Creating a bootable ISO image with custom bootloader
Asked Answered
S

2

12

I am trying to convert a bootloader I wrote in Assembly Language to an ISO image file. The following is the code from MikeOS bootloader. Here is my bootloader code:

   BITS 16
start:
    mov ax, 07C0h     ; Set up 4K stack space after this bootloader
    add ax, 288       ; (4096 + 512) / 16 bytes per paragraph
    mov ss, ax
    mov sp, 4096

    mov ax, 07C0h     ; Set data segment to where we're loaded
    mov ds, ax

    mov si, text_string   ; Put string position into SI
    call print_string ; Call our string-printing routine

    jmp $         ; Jump here - infinite loop!
    text_string db 'This is my cool new OS!', 0

    print_string:         ; Routine: output string in SI to screen
    mov ah, 0Eh       ; int 10h 'print char' function

.repeat:
    lodsb         ; Get character from string
    cmp al, 0
    je .done      ; If char is zero, end of string
    int 10h           ; Otherwise, print it
    jmp .repeat
.done:
    ret

    times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
    dw 0xAA55     ; The standard PC boot signature

I typed the following command:

nasm -f bin -o boot.bin boot.asm 

This command works fine and it gives a .bin output. Next I typed the following command:

dd if=boot.bin of=floppy.img count=1 bs=512 

This also worked fine and gave me the .img output file. When I type this command:

dd if=boot.bin of=floppy.img skip seek=1 count=1339

I get the following error: dd: unrecognized operand ‘skip’. I read in the DD documentation that the skip attribute must have a number assigned to it. Any ideas what number should I type with skip attribute (Ex. skip=1).

Next I type the following command:

mkdosfs -C floppy.img 1440 

I get the following error: mkdosfs: unable to create floppy.img. How do I fix the problems I am encountering? Is there another easier way I could convert my bootloader .bin file to an ISO image?

Smasher answered 14/12, 2015 at 13:41 Comment(0)
R
35

It appears you found your example for creating a bootable ISO image from this StackOverflow Answer. Unfortunately you picked an accepted answer that is incorrect in many ways. Pretend you never saw that answer.

On most Linux distros either a program called genisoimage or mkisofs exists. These days they are actually the same program. Whichever you have can be substituted in the examples below. My examples will assume the ISO creation utility is called genisoimage.


In your question you have some bootloader code in a file called boot.asm. You correctly assemble this to a boot sector binary image with:

nasm -f bin -o boot.bin boot.asm

This creates boot.bin which is your boot sector. The next step is to create a floppy disk image and place boot.bin in the first sector. You can do that with this:

dd if=/dev/zero of=floppy.img bs=1024 count=1440
dd if=boot.bin of=floppy.img seek=0 count=1 conv=notrunc

The first command simply makes a zero filled disk image equal to the size of a 1.44MB floppy (1024*1440 bytes). The second command places boot.bin into the first sector of floppy.img without truncating the rest of the file. seek=0 says seek to first sector (512 bytes is default size of a block for DD). count=1 specifies we only want to copy 1 sector (512 bytes) from boot.bin. conv=notrunc says that after writing to the output file, that the remaining disk image is to remain intact (not truncated).


After building a disk image as shown above, you can create an ISO image with these commands:

mkdir iso
cp floppy.img iso/
genisoimage -quiet -V 'MYOS' -input-charset iso8859-1 -o myos.iso -b floppy.img \
    -hide floppy.img iso/

The commands above first create a sub-directory called iso that will contain the files to be placed onto the final CD-ROM image. The second command doesn't do anything more than copy our floppy.img into iso directory because we need that for booting. The third command does the heavy lifting and builds the ISO image.

  • -V 'MYOS' sets the volume label (It can be whatever you want)
  • -input-charset iso8859-1 sets the character set being used. Don't change it
  • -o myos.iso says the ISO image will be output to the file myos.iso
  • -b floppy.img says that our ISO will be bootable and the boot image being used is the file floppy.img
  • -hide floppy.img isn't needed but it hides the boot image from the final ISO's directory listing. If you were to mount this ISO and do an ls on it to list the files, floppy.img wouldn't appear.
  • iso/ on the end of the command is the directory that will be used to build the ISO image from. It needs to at least contain our bootable floppy image, but you can place any other files you wish into the iso/ directory.

The ISO image myos.iso that is generated can be booted. An example of using QEMU to launch such an image:

qemu-system-i386 -cdrom ./myos.iso
Rubbish answered 14/12, 2015 at 19:27 Comment(0)
S
9

For CD; there's a specification ("El Torito") that describes how bootable CDs work; where the first 16 (2048-byte) sectors are unused, there's a "boot catalogue" that the firmware uses to decide which boot loader it should use (so you can have a single CD that boots very different systems - e.g. PC BIOS, UEFI, PowerPC, etc), then the boot loaders themselves.

For "PC BIOS" alone, there's 3 possibilities:

  • emulate a floppy disk (using a "floppy disk image" stored on CD)
  • emulate a hard disk (using a "hard disk image" stored on CD)
  • no emulation

The first 2 options are mostly for compatibly purposes only (crusty old OSs that don't support booting from CDs, like MS-DOS); and have performance implications (e.g. to emulate loading one 512-byte virtual sector, the firmware has to load a real 2048-byte sector and throw away the excess 1536 bytes). Any OS designed/written in the last 15+ years should be using "no emulation".

For "no emulation":

  • The firmware loads your entire boot loader (which can be up to about 512 KiB) and not just one sector
  • Sectors on CDs are 2048 bytes (and not 512 bytes); and should be loaded via. "int 0x13 extensions" (and not the old/limited "CHS disk functions" that you'd use for floppy)
  • There is no need for a BIOS Parameter Block (which should be considered mandatory for floppy disks)
  • There is no need for a partition table (which should be considered mandatory for hard disks, including GPT)
  • You'll probably want to support ISO9660 as the file system (to find the kernel and/or other files that the boot loader needs to load) and not FAT.

Also note that (in general) for "PC BIOS" you're probably going to want 5 different boot loaders (one for floppy, one for "MBR partitioned" hard disk, one for "GPT partitioned" hard disk, one for CD, and one for network boot). These cases are all different enough (and the "one 512-byte initial sector only" limitation for 3 of these cases is restrictive enough) to make the "all devices supported by one boot loader" idea a disaster.

To actually generate the ISO; you can use an existing tool (e.g. mkisofs), or you can write your own tool (ISO9660 and "El Torito" are both relatively easy to understand, and writing your own tool to generate an ISO can be done in less than 2 days, which is like a drop in the ocean for OS development projects).

Schoenfelder answered 14/12, 2015 at 21:41 Comment(1)
I am one of your upvoters. Your question technically doesn't answer the specific question of how to do it, it does contain useful information for ISO images in general.Rubbish

© 2022 - 2024 — McMap. All rights reserved.