Creating a Bootable Iso Image with Custom Bootloader

Creating a bootable ISO image with custom bootloader

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

How to make an bootable iso(not cd or flash drive) for testing your own boot loader?

a very simple script will do this in linux as below :-

rm -f disk_images/myos.iso
mkisofs -quiet -V 'MYOS' -input-charset iso8859-1 -o disk_images/myos.iso -b myos.flp disk_images/ || exit

The floppy drive is made as below :-

nasm -f bin -o boot.bin boot.asm
dd if=boot.bin of=floppy.img count=1 bs=512 //for the bootloader

and

dd if=boot.bin of=floppy.img skip seek=1 count=1339 //assuming a 1.44Mb floppy

and then you have the file system

mkdosfs (or whatever system you want ) -C floppy.img 1440

If you ned help for windows , let me know :)

make bootloader and kernel into iso?

I recommend you to use a standard bootloader if you are going to write an OS and use an emulator instead of real machine any way (not because you bootloader could break computer - it probably couldn't, but because it is a simpler way to start up with and debug. You will almost certainly get bored of burning a CD each update.

Also, note that ISO uses a more complicated boot protocol than floppy/harddisks does. The best approach is to use GRUB or ISOLINUX if you wish to use CD and use a floppy image (which can be attached to CD by emulation latter) if you wish to have you very own bootloader.

How can I create a bootable CD image with my kernel?

First I give you basic idea of how booting process really works. Actually when you run command qemu-system-i386 -kernel kernel.bin Qemu loads up your kernel binary into memory at location 0x7c000 from where booting further proceed.
If you want to boot from ISO then you have to tell the BIOS that there is a Bootable image (mark boot flag) in my iso, and give it proper instructions to laod up your kernel.

How to do that?

You have to setup a Bootloader that can be loaded by your BIOS at 0x7c000 and later It would load your Kernel Image into memory and jump to kernel entry point.
So, mark your ISO active (boot flag) and add boot loader code.

I can see you already have setup multiboot entrypoint code

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

You can read more about setting up grub boot chain from here http://wiki.osdev.org/GRUB_2
You can also use syslinux bootloader http://www.syslinux.org/wiki/index.php?title=The_Syslinux_Project

syslinux
Copy isolinux.bin, syslinux.cfg and mboot.c32 to your build path of your kernel binary image.
configure syslinux.cfg and execute the following command.

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%

How to create a bootable disk

are you trying to create bootable win7/8 installer?
If yes, get UltraISO and then openup your ISO with that program, then goto bootable->Write disk image, after that you will be able to bootup your flashdrive

How to make a bootable disc (.iso) that loads a kernel (.elf)

There is a lot more to it that just converting your kernel file to binary and placing it on an ISO disc (image).

You need to have a boot loader of some kind. If you boot as a legacy BIOS machine, you will need a boot loader that understands the ISO file system, finding, then reading the kernel file into memory. There are a few already made, Grub comes to mind.

Since you want to create your own (and I commend you on that), you will need to read up on how the ISO file system is stored on the disc, how the BIOS will load one or more sectors for you, etc.

For example, the BIOS will load one or more sectors from the disc using different methods. One would be floppy emulation, another could be hard drive emulation, while another could be direct ISO disc sector reads.

I would suggest that you don't start with ISO. Start with a floppy image or even better, a hard drive image. Then all you have to do is write a boot sector and loader that uses the BIOS read disk services. This is much easier.

However, don't get me wrong, there is still a lot of work to do this.

If you wish to skip all of that, you can write your kernel as a (Win) PE file and use the newer firmware (UEFI) to load it for you. EFI will use a GPT formatted drive with one or more FAT volumes and will find and load your PE formatted executable for you.

However, and some may disagree, but since you are doing this project as a learning experience, I suggest you take the Legacy BIOS route. This will let you learn a lot more about how a computer boots up, loads the first instructions, etc.

For the Legacy BIOS floppy or hard drive route, do a search for boot sectors and either floppy or hard drive. This will show you how some have accomplished the task. This boot sector usually loads another file which is the OS loader. This loader is then used to load the kernel and (possibly) other files, setting up the necessary items before jumping to the kernel.

If you wish, I have written a few books on this subject, showing how to write boot sectors for floppies, hard drives, as well as ISO disc images. I also have included example source code from an earlier version.

Booting from iso image why memory address of bootloader is not 0x7c00

It's caused because of a common misinterpretation of the El Torito CD-ROM boot specification which says that emulated bootsectors should be loaded at the "traditional segment of 7C0" by default. It doesn't say that a non-traditional starting address of 07C0:0000 should be used instead of the traditional 0000:7C00, but BIOS writers have interpreted this as a requirement nonetheless.

While you can assume that your bootsector is loaded at a linear address of 00007C00 and that the BIOS starts execution of your code at the first byte of the bootsector, you can't assume any particular value of CS:IP. While most bootsectors can be written not to depend on the segment value loaded into CS, as near JMP and CALL instructions are relative, if yours does then you'll need to put a far JMP instruction your code to ensure CS is loaded with the expected segment value:

  jmp $0x07c0,$start
start:

Note that the choice of segment (0x07c0) in the example above is based on the fact that your bootsector has an "org" of 0, so that the offset of the first byte of bootsector is assumed to be 0 rather than 0x7c00. This means with the above code added to the start of your bootsector, it would consistently print 0000.



Related Topics



Leave a reply



Submit