views:

277

answers:

3

I am writing a boot loader, and I've got most of the details down, but I am not sure why some boot loaders relocate themselves in memory before they begin the bulk of their execution.

Can anyone explain this?

An example of this behavior is the original v0.01 Linux kernel bootloader which has the following comment in it:

boot.s is loaded at 0x7c00 by the bios-startup routines, and moves itself out of the way to address 0x90000, and jumps there.

+3  A: 

From the linked article:

In practice, the MBR usually contains a boot loader whose purpose is to load another boot loader - to be found at the start of one of the partitions. This is often a very simple program which finds the first partition marked Active, loads its first sector into RAM, and commences its execution. Since by convention the new boot loader is also loaded to adress 7C00h, the old loader may need to relocate all or part of itself to a different location before doing this. Also, ES:SI is expected to contain the address in RAM of the partition table, and DL the boot drive number. Breaking such conventions may render a bootloader incompatible with other bootloaders.

CookieOfFortune
But he's specifically asking about the Linux v0.01 boot loader at the bottom of that page, which does __not__ appear to be a 2 stage loader. It seems to load the kernel straight to 0x10000, as the comment at the top states.
IRBMe
Thanks, perfect answer! I had gathered that the apps were chained together but it had not occurred to me that all the others would also be loaded at the same address.I had noticed the DL register being used to identify the drive number but again I could not find any explicit documentation about this.I don't suppose there is a standard BIOS reference manual document floating around the interwebs is there? I used to have a book containing the interrupt tables, but its at least 20 years old and probably very out of date (and lost).
icStatic
Here's a list of BIOS interrupts: http://en.wikipedia.org/wiki/BIOS_interrupt_call. These are obviously only available until your OS sets up the Interrupt Table.
Falaina
+6  A: 

CookieOfFortune is essentially correct (Because he wanted to move something into the place where the initial bootloader was), but it wasn't for a second bootloader, but rather the kernel itself.

From his comments:

It then loads the system at 0x10000, using BIOS interrupts. Thereafter it disables all interrupts, moves the system down to 0x0000, changes to protected mode, and calls the start of system. System then must RE-initialize the protected mode in it's own tables, and enable interrupts as needed.

He wants the kernel to be located at 0x0000...0xKERNEL_SIZE-1, however the initial bootloader is currently at 0x7C00, so if the kernel was over ~32 KB it would overwrite the bootloader as it was moving it. The fact that the kernel is located at 0x0000 also explains this comment:

"NOTE! currently system is at most 8*65536 bytes long."

If it was any longer than 512 KB starting at 0 it would run the risk of hitting the reserved area of the x86 address space.

I believe this code section contains the actual jump into the kernel

mov ax,#0x0001 | protected mode (PE) bit
lmsw ax  | This is it!
jmpi 0,8  | jmp offset 0 of segment 8 (cs)
Falaina
A: 

Sometimes the bootloader is in ROM, and needs to be copied to RAM at some point.

Paul Nathan
The bootloader most certainly is not in ROM. The BIOS may be, though...
bdonlan
I've used a bootloader that started out in ROM. Sorry. =)
Paul Nathan
Okay, well, usually it's not :)
bdonlan