2016-02-01 7 views
7

Bir çekirdek var, önyükleme yapmak için qemu-system-i386 -kernel kernel.bin komutunu kullanıyorum. qemu-system-i386 -cdrom CD.iso ile önyükleme yapmak için önyüklenebilir disk görüntüsü oluşturmanın herhangi bir yolu var mı?Çekirdeğimle birlikte önyüklenebilir bir CD görüntüsü nasıl oluşturabilirim?

Ben bu komutları ile linux derleme am kod:

nasm -f elf32 kernel.asm -o kernelasm.o 
gcc -m32 -c kernel.c -o kernelc.o 
ld -m elf_i386 -T link.ld -o kernel.bin kernelasm.o kernelc.o 

ve daha sonra önyükleme qemu-system-i386 -kernel kernel.bin

KODU: kernel.asm:

[BITS 32] 
SECTION .text 
    align 4 
    dd 0x1BADB002 
    dd 0x00 
    dd - (0x1BADB002 + 0x00) 

global start 
global keyboard_handler 
global read_port 
global write_port 
global load_idt 

extern kmain 
extern keyboard_handler_main 

read_port: 
    mov edx, [esp + 4] 
    in al, dx 
    ret 

write_port: 
    mov edx, [esp + 4]  
    mov al, [esp + 4 + 4] 
    out dx, al 
    ret 

load_idt: 
    mov edx, [esp + 4] 
    lidt [edx] 
    sti 
    ret 

keyboard_handler:     
    call keyboard_handler_main 
    iretd 

start: 
    cli 
    mov esp, stack_space 
    call kmain 
    hlt 

section .bss 
resb 8192 
stack_space: 

kernel.c:

#include "keyboard_map.h" 

#define LINES 25 
#define COLUMNS_IN_LINE 80 
#define BYTES_FOR_EACH_ELEMENT 2 
#define SCREENSIZE BYTES_FOR_EACH_ELEMENT * COLUMNS_IN_LINE * LINES 

#define KEYBOARD_DATA_PORT 0x60 
#define KEYBOARD_STATUS_PORT 0x64 
#define IDT_SIZE 256 
#define INTERRUPT_GATE 0x8e 
#define KERNEL_CODE_SEGMENT_OFFSET 0x08 

#define ENTER_KEY_CODE 0x1C 

extern unsigned char keyboard_map[128]; 
extern void keyboard_handler(void); 
extern char read_port(unsigned short port); 
extern void write_port(unsigned short port, unsigned char data); 
extern void load_idt(unsigned long *idt_ptr); 

unsigned int current_loc = 0; 
char *vidptr = (char*)0xb8000; 

struct IDT_entry { 
    unsigned short int offset_lowerbits; 
    unsigned short int selector; 
    unsigned char zero; 
    unsigned char type_attr; 
    unsigned short int offset_higherbits; 
}; 

struct IDT_entry IDT[IDT_SIZE]; 


void idt_init(void) 
{ 
    unsigned long keyboard_address; 
    unsigned long idt_address; 
    unsigned long idt_ptr[2]; 

    keyboard_address = (unsigned long)keyboard_handler; 
    IDT[0x21].offset_lowerbits = keyboard_address & 0xffff; 
    IDT[0x21].selector = KERNEL_CODE_SEGMENT_OFFSET; 
    IDT[0x21].zero = 0; 
    IDT[0x21].type_attr = INTERRUPT_GATE; 
    IDT[0x21].offset_higherbits = (keyboard_address & 0xffff0000) >> 16; 

    write_port(0x20 , 0x11); 
    write_port(0xA0 , 0x11); 

    write_port(0x21 , 0x20); 
    write_port(0xA1 , 0x28); 

    write_port(0x21 , 0x00); 
    write_port(0xA1 , 0x00); 

    write_port(0x21 , 0x01); 
    write_port(0xA1 , 0x01); 

    write_port(0x21 , 0xff); 
    write_port(0xA1 , 0xff); 

    idt_address = (unsigned long)IDT ; 
    idt_ptr[0] = (sizeof (struct IDT_entry) * IDT_SIZE) + ((idt_address & 0xffff) << 16); 
    idt_ptr[1] = idt_address >> 16 ; 

    load_idt(idt_ptr); 
} 

void kb_init(void) 
{ 
    write_port(0x21 , 0xFD); 
} 

void kprint(const char *str) 
{ 
    unsigned int i = 0; 
    while (str[i] != '\0') { 
     vidptr[current_loc++] = str[i++]; 
     vidptr[current_loc++] = 0x07; 
    } 
} 

void kprint_newline(void) 
{ 
    unsigned int line_size = BYTES_FOR_EACH_ELEMENT * COLUMNS_IN_LINE; 
    current_loc = current_loc + (line_size - current_loc % (line_size)); 
} 

void clear_screen(void) 
{ 
    unsigned int i = 0; 
    while (i < SCREENSIZE) { 
     vidptr[i++] = ' '; 
     vidptr[i++] = 0x07; 
    } 
} 

void keyboard_handler_main(void) 
{ 
    unsigned char status; 
    char keycode; 

    write_port(0x20, 0x20); 

    status = read_port(KEYBOARD_STATUS_PORT); 
    if (status & 0x01) { 
     keycode = read_port(KEYBOARD_DATA_PORT); 
     if(keycode < 0) 
      return; 

     if(keycode == ENTER_KEY_CODE) { 
      kprint_newline(); 
      return; 
     } 

     vidptr[current_loc++] = keyboard_map[(unsigned char) keycode]; 
     vidptr[current_loc++] = 0x07; 
    } 
} 

void kmain(void) 
{ 
    const char *str = "my first kernel with keyboard support"; 
    clear_screen(); 
    kprint(str); 
    kprint_newline(); 
    kprint_newline(); 

    idt_init(); 
    kb_init(); 

    while(1); 
} 

keyboard_map.h:

unsigned char keyboard_map[128] = 
{ 
    0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */ 
    '9', '0', '-', '=', '\b', /* Backspace */ 
    '\t',   /* Tab */ 
    'q', 'w', 'e', 'r', /* 19 */ 
    't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */ 
    0,   /* 29 - Control */ 
    'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */ 
'\'', '`', 0,  /* Left shift */ 
'\\', 'z', 'x', 'c', 'v', 'b', 'n',   /* 49 */ 
    'm', ',', '.', '/', 0,    /* Right shift */ 
    '*', 
    0, /* Alt */ 
    ' ', /* Space bar */ 
    0, /* Caps lock */ 
    0, /* 59 - F1 key ... > */ 
    0, 0, 0, 0, 0, 0, 0, 0, 
    0, /* < ... F10 */ 
    0, /* 69 - Num lock*/ 
    0, /* Scroll Lock */ 
    0, /* Home key */ 
    0, /* Up Arrow */ 
    0, /* Page Up */ 
    '-', 
    0, /* Left Arrow */ 
    0, 
    0, /* Right Arrow */ 
    '+', 
    0, /* 79 - End key*/ 
    0, /* Down Arrow */ 
    0, /* Page Down */ 
    0, /* Insert Key */ 
    0, /* Delete Key */ 
    0, 0, 0, 
    0, /* F11 Key */ 
    0, /* F12 Key */ 
    0, /* All other keys are undefined */ 
}; 

link.ld:

OUTPUT_FORMAT(elf32-i386) 
ENTRY(start) 
SECTIONS 
{ 
    . = 0x100000; 
    .text : { *(.text) } 
    .data : { *(.data) } 
    .bss : { *(.bss) } 
} 
+4

https://www.gnu.org/software/grub/manual/html_node/Making-a-GRUB-bootable-CD_002dROM.html –

+0

Etrafına bak "** El -Torito **" standart http: //wiki.osdev.org/El-Torito – rom1nux

+0

[Özel önyükleyicili önyüklenebilir bir ISO görüntüsü oluşturma] 'nın olası kopyası (http://stackoverflow.com/questions/34268518/creating-a-bootable-iso-image-with- özel bootloader) –

cevap

3

Önce sana açılış sürecinin gerçekten nasıl çalıştığı temel fikir vermektedir. Aslında, qemu-system-i386 -kernel kernel.bin Qemu komutunu çalıştırdığınızda, önyüklemenin devam ettiği yerden çekirdek ikili dosyanızı 0x7c000 konumunda belleğe yükler. Eğer ISO'dan önyükleme yapmak istiyorsanız, BIOS'unuza, ISO'mda bir Önyüklenebilir görüntü (işaret önyükleme bayrağı) olduğunu ve çekirdeğinizi doldurmak için uygun yönergeler sağladığını söylemelisiniz.

Bu nasıl yapılır?
BIOS'unuz tarafından 0x7c000 ve daha sonra yüklenebilecek bir Önyükleyici ayarlamanız gerekir. Kernel Görüntü'nizi belleğe yükler ve çekirdek giriş noktasına atlar.
Yani, ISO etkinliğinizi (önyükleme bayrağı) işaretleyin ve önyükleyici kodunu ekleyin.

Ben zaten kurulum çoklu önyükleme girişnoktası kodu

align 4 
dd 0x1BADB002 
dd 0x00 
dd - (0x1BADB002 + 0x00) 

Burada http://wiki.osdev.org/GRUB_2 den grub çizme zincirini kurmayla ilgili daha fazla bilgi bulabilirsiniz da kullanabilirsiniz görebilmesi syslinux.cfg bootloaderhttp://www.syslinux.org/wiki/index.php?title=The_Syslinux_Project

syslinux Kopyalama isolinux.bin, syslinux.cfg ve mboot.c32, sizin çekirdek ikili görüntü. syslinux.cfg dosyasını yapılandırın ve aşağıdaki komutu yürütün.

mkisofs.exe -o %OUTPUT_DIR%\%BUILD_NAME%.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table %ISO_DIR% 
İlgili konular