2016-02-01 9 views
7

मेरे पास बूट करने के लिए एक कर्नेल है, मैं कमांड qemu-system-i386 -kernel kernel.bin का उपयोग कर रहा हूं। qemu-system-i386 -cdrom CD.iso के साथ बूट करने के लिए बूट करने योग्य डिस्क छवि बनाने का कोई तरीका है?मैं अपने कर्नेल के साथ बूट करने योग्य सीडी छवि कैसे बना सकता हूं?

कोड मैं इन आदेशों के साथ लिनक्स में संकलन कर रहा हूँ:

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

कोड: 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

चारों ओर देखो "** अल Torito **" मानक http: //wiki.osdev.org/El-Torito – rom1nux

+0

संभावित डुप्लिकेट [कस्टम बूटलोडर के साथ बूट करने योग्य आईएसओ छवि बनाना] (http://stackoverflow.com/questions/34268518/creating-a-bootable-iso-image-with- कस्टम बूटलोडर) –

उत्तर

3

सबसे पहले मैं आप कैसे बूटिंग प्रक्रिया वास्तव में काम करता है के मूल विचार दे। दरअसल जब आप कमांड qemu-system-i386 -kernel kernel.bin चलाते हैं तो क्यूमु आपके कर्नेल बाइनरी को 0x7c000 पर मेमोरी में लोड करता है जहां से आगे बढ़ना बूट हो जाता है। यदि आप आईएसओ से बूट करना चाहते हैं तो आपको BIOS को बताना होगा कि मेरे आईएसओ में बूट करने योग्य छवि (मार्क बूट फ्लैग) है, और इसे अपने कर्नेल को लॉड करने के लिए उचित निर्देश दें।

यह कैसे करें?
आपको एक बूटलोडर सेट करना होगा जिसे आपके BIOS द्वारा 0x7c000 पर लोड किया जा सकता है और बाद में यह आपकी कर्नेल छवि को स्मृति में लोड करेगा और कर्नेल एंट्री पॉइंट पर जायेगा।
तो, अपने आईएसओ सक्रिय (बूट ध्वज) को चिह्नित करें और बूट लोडर कोड जोड़ें।

मैं देख सकता हूँ आप पहले से ही सेटअप मल्टीबूट entrypoint कोड

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

आप यहाँ http://wiki.osdev.org/GRUB_2 से ग्रब बूट श्रृंखला स्थापित करने के बारे में और अधिक पढ़ सकते हैं तुम भी उपयोग कर सकते हैं 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% 
संबंधित मुद्दे

 संबंधित मुद्दे