2019-02-26 21:43:13 8 Comments
I am working on writing my own operating system. So far, my code exceeds 512 bytes, which is too large to fit in a simple boot sector.
I understand that I now have to write a bootloader that reads arbitrary code that may or may not be greater than a single 512-byte sector.
The bootloader would need to:
- Function as a boot record with disk signature 0xaa55.
- Read a second stage (the test code) start from LBA 1 (LBA 0 is boot sector) of arbitrary length starting at memory address 0x7E00.
- Transfer control to it using a FAR JMP to 0x0000:0x7E00.
- Be usable as a 1.44 MiB floppy disk image for use in emulators like QEMU, BOCHS, VirtualBox etc.
- Can be transferred and used on a USB stick to test on real hardware with the BIOS set to boot USB using Floppy Disk Drive (FDD) emulation. Note: Some bootloaders do not work well when placed on USB drives.
- Pass the boot drive to the second stage in DL.
- Zero out all the segment registers and set SS:SP to 0x0000:0x7C00 (grows down from just under the bootloader).
This would also serve as a good starting point for asking questions on Stack Overflow that involve OS development. Programmers often struggle to create a Minimal, Complete, and Verifiable Example. A common boilerplate/template would allow other Stack Overflow users wishing to help to test the code with a limited amount of fuss.
How would I go about building such a reusable bootloader?
Related Questions
Sponsored Content
1 Answered Questions
1 Answered Questions
[SOLVED] Bootloader works in emulators but not on real hardware
- 2017-01-28 15:39:57
- user2725580
- 459 View
- 2 Score
- 1 Answer
- Tags: assembly x86 x86-16 bootloader gas
2 Answered Questions
[SOLVED] Problems loading second stage of a bootloader and/or transferring control to it
- 2017-01-22 20:32:07
- paradox
- 290 View
- 2 Score
- 2 Answer
- Tags: linux assembly x86-16 bootloader bios
3 Answered Questions
[SOLVED] How do I write a bin file (512 bytes) to the first sector (sector 0) of a floppy disk?
- 2015-10-01 17:40:19
- Star OS
- 6038 View
- 8 Score
- 3 Answer
- Tags: assembly bootloader bios osdev floppy
1 Answered Questions
[SOLVED] FAT32 Finding Stage 2 Bootloader
- 2016-10-23 15:56:32
- ArdaGuler
- 175 View
- 0 Score
- 1 Answer
- Tags: assembly kernel bootloader
2 comments
@Michael Petch 2019-02-26 21:43:13
I have written such code as part of other answers but never had an opportunity to present a simple test harness that could be referenced from other Stackoverflow questions. What you are asking for is rather trivial. One can do this by writing a bootloader in NASM that includes a binary image of the assembled code you wish to test. This image would be read from disk starting at LBA 1 (first sector after the bootloader) using BIOS function Int 13/ah=2. Control would then be transferred to it via a FAR JMP to 0x0000:0x7e00.
The bootloader code would look like this:
bpb.inc:
boot.asm:
To use this you would first generate a binary file called
stage2.bin
. Afterstage2.bin
has been built you can build a 1.44MiB disk image without a BIOS Parameter Block (BPB) with this command:To build a 1.44MiB disk image with a BPB you can build it with this command:
The code in
stage2.bin
would have to be generated with the assumption that the ORG (origin point) is 0x07e00 in memory.Sample Usage/Example
An example of code generated to a file called
stage2.bin
that can be loaded with this test harness:testcode.asm:
Note: there is an
ORG 0x7e00
at the top. This is important. To assemble this file intostage2.bin
use:Then create the 1.44MiB disk image with:
The result should be a disk image exactly 1.44MiB in size, contains a copy of
stage2.bin
and has our test harness boot sector.The file
stage2.bin
can be anything that has binary code written to be loaded and started at 0x0000:0x7e00. The language (C, assembly etc) used to create the code instage2.bin
doesn't matter. I use NASM for this example. When this test code is executed in QEMU usingqemu-system-i386 -fda disk.img
it would look similar to this:Special Note: : Using
-DWITH_BPB
to enable a BPB is useful if you are booting from USB using FDD emulation. Some BIOSes that boot USB as a floppy will assume a BPB is is present and overwrite the area with drive geometry before transferring control to it at physical address 0x07c00.@ecm 2019-07-26 16:50:06
I modified my own boot sector loader to add a new protocol. It makes it set es = ds = ss = 0 and load the whole load file to address 07E00h, jumping to that at 0000h:7E00h. However, sp is left pointing somewhat below 7C00h.
And there's the big difference to the requirements in the question: This loader uses the (FAT12 or FAT16) filesystem to load the next stage. It loads from a file named KERNEL7E.BIN if found. The file name, like the entire load protocol, can be adjusted by editing the source file or passing defines on the NASM command line.
A limitation due to the code size is that only single-character error messages are output when an error occurs: R means disk Read error, M means the file to be loaded is too large (out of Memory). Another limitation is that the RPL (Remote Program Loader) protocol isn't used as it needs some more bytes.
To lessen the space pressure, the loader can be built with
-D_CHS=0 -D_QUERY_GEOMETRY=0
(if to load via ROM-BIOS's LBA interface) or-D_LBA=0
(if to load via CHS interface).To build the loader, clone the lmacros and ldosboot repositories, and put them next to each other. The loader is to be built from the ldosboot directory with NASM this way for FAT12:
Or this way for FAT16:
Here's how to install the loader into an existing already-formatted FAT12 or FAT16 file system image:
Instead of using an existing image, an entire image can be created by NASM. I wrote such a program at https://bitbucket.org/ecm/bootimg/src/default/ It builds like this:
nasm -I ../lmacros/ -D_BOOTFILE="'../ldosboot/boot12.bin'" -D_MULTIPAYLOADFILE="'../ldebug/bin/ldebug.com','../ldebug/bin/lddebug.com'" bootimg.asm -o bootimg.img
Note how the long def has double quotes around single-quoted list entries. Each list entry is stripped to the basename (after the last slash or backslash), has its content added to the data area, and has a directory entry added to the root directory. Filenames are ASCII and in allcaps.
The ldosboot repo contains a two-sector FAT32 loader too, but I didn't modify it to support this protocol yet. With relocation, the FAT buffer should be at the top of memory already. That means the file can be loaded to 07E00h. However, ss will be at a high segment instead of zero. Other than that difference, the protocol can be specified with switches. The command to build this is
nasm -I ../lmacros/ boot32.asm -l boot7e32.lst -D_MAP=boot7e32.map -o boot7e32.bin -D_RELOCATE -D_MEMORY_CONTINUE=0 -D_ZERO_DS -D_ZERO_ES -D_SET_BL_UNIT=0 -D_SET_DL_UNIT=1 -D_LOAD_ADR=07E00h -D_EXEC_SEG_ADJ=-7E0h -D_EXEC_OFS=7E00h -D_OEM_NAME="'KERNEL7E'" -D_LOAD_NAME="'KERNEL7E'" -D_LOAD_EXT="'BIN'"
There's also the instsect program (in its own repo) for DOS, which is built with loader images and installs them to a DOS drive.
@Michael Petch 2019-07-26 17:04:33
I only briefly summed it up as common boilerplate/template would allow other Stack Overflow users wishing to help to test the code with a limited amount of fuss. at the bottom of my question. The target wasn't really for OS design but a method to help people potentially create better minimal reproducible example when presenting their code on this site as many people doing OSDev neglect to show us their bootloaders.
@Michael Petch 2019-07-26 17:11:13
I'm the upvote. I probably should add to my question the reasons why I had a specification that didn't involve using a file system. On Stackoverflow we get questions that span OSes (especially Windows and Linux). The spec was designed in such a way that simply having NASM could produce a floppy image that was usable without requiring more tools (to mount and unmount images - much more involved on Windows). Much easier in userspace on Linux with
mtools
. I'm actually partial to directing people to Alexey Frunze's (another SO user) BOOTPROG as well: github.com/alexfru/BootProg@ecm 2019-07-26 17:32:47
@Michael Petch: I did actually work with alexfru's loader implementation too when I started developing the ldosboot collection. However, I eventually decided to use Chris Giese's. As for your requirements, I understand that the formatting and accessing of an image isn't always easy. Still I want to advertise my loader as an alternative. Thanks for the upvote!
@Michael Petch 2019-07-26 17:34:06
Understood, there was nothing wrong with your answer which was why I was more than happy to upvote. I too have bootloaders that will read Fat12 etc. My first bootloader was in the late 1980s (I was doing work with Wendin DOS) and back then besides asking for help on places like Compuserv there wasn't a plethora of example bootloaders to draw inspiration from except to disassemble DOS ones.
@ecm 2019-07-26 22:16:07
@Michael Petch: I added a program (script ish) that uses NASM to build a file system image. I added the description to my answer. It lacks sophistication, but is certainly a sufficient alternative to your solution for anyone wanting to use only NASM.