2016-02-01 23 views
7

私はブートするカーネルを持っています。私はコマンドqemu-system-i386 -kernel kernel.binを使っています。 qemu-system-i386 -cdrom CD.isoで起動するブート可能なディスクイメージを作成する方法はありますか?カーネルでブート可能なCDイメージを作成するにはどうしたらいいですか?

私はこれらのコマンドでLinux上でコンパイルしていますコード:

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 

し、その後で起動qemu-system-i386 -kernel kernel.bin

CODE: 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

周りを見て、 "**エルトリート**" 標準のhttp: //wiki.osdev.org/El-Torito – rom1nux

+0

[カスタムブートローダで起動可能なISOイメージを作成する]の可能な複製(http://stackoverflow.com/questions/34268518/creating-a-bootable-iso-image-with-カスタムブートローダ) –

答えて

3

まず、私はあなたのブートプロセスが実際にどのように動作するかの基本的なアイデアを与えます。実際にコマンドqemu-system-i386 -kernel kernel.binを実行すると、Qemuはブートをさらに進める場所0x7c000のメモリにカーネルバイナリをロードします。 ISOからブートしたい場合は、isoにブート可能なイメージ(ブート・フラグをマークする)があることをBIOSに通知し、カーネルを完成させるための適切な指示を与える必要があります。

どうすればよいですか?
BIOSで0x7c000以降でロードできるブートローダをセットアップする必要があります。カーネルイメージをメモリにロードしてカーネルのエントリポイントにジャンプします。
ISOのアクティブ(ブートフラグ)をマークし、ブートローダコードを追加してください。

私はあなたがすでにセットアップマルチブートエントリポイントコード

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

あなたがここhttp://wiki.osdev.org/GRUB_2 からGRUBブートチェーンの設定の詳細を読むことができます。また、使用することができますを持って見ることができますのsyslinuxブートローダhttp://www.syslinux.org/wiki/index.php?title=The_Syslinux_Project

syslinux isolinux.bin、syslinux.cfg、およびmboot.c32を自分のビルドパスにコピーします。カーネルバイナリイメージ。 syslinux.cfgを設定し、次のコマンドを実行します。

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% 
関連する問題