title: How can I create a bootable CD image with my kernel?
body: <p>I have a kernel, to boot I am using command <code>qemu-system-i386 -kernel kernel.bin</code>. Is any way to create bootable disk image to boot with <code>qemu-system-i386 -cdrom CD.iso</code>?</p>
  
  <p>The code I am compiling in linux with these commands:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>and then booting with <code>qemu-system-i386 -kernel kernel.bin</code></p>
  
  <p>CODE:
  kernel.asm:</p>
  
  <pre><code>[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:
  </code></pre>
  
  <p>kernel.c:</p>
  
  <pre><code>#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 &amp; 0xffff;
      IDT[0x21].selector = KERNEL_CODE_SEGMENT_OFFSET;
      IDT[0x21].zero = 0;
      IDT[0x21].type_attr = INTERRUPT_GATE;
      IDT[0x21].offset_higherbits = (keyboard_address &amp; 0xffff0000) &gt;&gt; 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 &amp; 0xffff) &lt;&lt; 16);
      idt_ptr[1] = idt_address &gt;&gt; 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 &lt; 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 &amp; 0x01) {
          keycode = read_port(KEYBOARD_DATA_PORT);
          if(keycode &lt; 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);
  }
  </code></pre>
  
  <p>keyboard_map.h:</p>
  
  <pre><code>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 ... &gt; */
      0,   0,   0,   0,   0,   0,   0,   0,
      0,  /* &lt; ... 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 */
  };
  </code></pre>
  
  <p>link.ld:</p>
  
  <pre><code>OUTPUT_FORMAT(elf32-i386)
  ENTRY(start)
  SECTIONS
   {
     . = 0x100000;
     .text : { *(.text) }
     .data : { *(.data) }
     .bss  : { *(.bss)  }
   }
  </code></pre>