Bootstrap Loader

Home OS Home

                    The computer's BIOS attempt to boot the operating system from either floppy disk or the hard disk. When it boots from a floppy disk, it reads the content of the first sector of the floppy disk to memory at 0000:7C00 (segment:offset). If it is from a hard drive, it loads the Master Boot Sector to determine the active partition and then loads the boot code into the same address from the first sector of the partition. For easy of documentation, I will only discuss the Floppy Disk booting system. After loading your code there, BIOS does a far jump to 0000:7C00H. Some crappy BIOS does a far jump to 7C00:0000. This isn't a big concern because all that changes is your CS and IP which we do not need to concern about in our bootstrap loader.

                    In a floppy disk, one sector is a 512 byte continuous data storage location. That means, our boot code cannot be more than 512 bytes long. If you are a beginner, you might think that it is too small for any program. That is where the trick comes in. As it's name tells us, bootstrap loader does only only thing, it boot our computer, nothing else! Then it is our 'kernel' that does the super job. Our bootstrap loader reads out kernel from the floppy and put it in a specific location and then we jump from our 'bootstrap' to the 'kernel'. To make our life easier, we will use MS-DOS FAT12 file system when copying our files to floppy. Now there is one big problem. The first sector (logic sector 0) in an FAT12 file system is a reserved sector. When you format a floppy disk, MS-DOS places some data in that sector. If you change that data, the floppy will not read in DOS. So how will we put our boot code in the first sector without changing the values that are already in the sector? More that that we cannot just cut and paste our code into the floppy, because MS-DOS doesn't write anything in the first sector, not even the first file you write.

448 Bytes
2 Bytes
62 Bytes
                    The way we solve is by examining the first sector of a floppy with the help of 'debug' program. It will take us hours to do that. Instead you can just look it in the internet or believe what I say and it should work with out any problem. The first sector of a bootable floppy disk is divided into three parts. If you look in some books or other resources, you will see that they call the first 62 bytes as boot sector, the next 448 bytes as boot code and the last 2 bytes as signature. If you are new to this boot system, this will confuse you. At first I said that the BIOS loads my boot sector(512 bytes) to memory and now I say that my boot sector is only 62 bytes. This is just a nasty convention used in many places. From here on, I will call the first 62 bytes as boot structure. As you might have already figured out, MS-DOS only checks to see if the data in the boot structure is correct. So as long as we keep that data unchanged, we could put any code in the 448 bytes. So the 512 bytes of the first sector should look like the table below.

 

Boot Code

 

Boot Structure

Signature

 

 

 

 

 

 

                    Now, like I said earlier, there are two ways to know what is in Boot Structure. The hardest way is to debug the first sector. The easiest way is to look below. The boot structure contains the following information in the following order. Remember, the values should be exact and must be in order.

 

Variable Name

Size of Variable

Value

Short Jump Instruction 3 Bytes A jump to a label
OEM Name 8 Bytes Any value
Bytes Per Sector 2 Bytes 0x0200
Sectors Per Cluster 1 Byte 0x01
Reserved Sectors 2 Bytes 0x0001
# of FAT(s) 1 Byte 0x02
# of Root Directory Entries 2 Bytes 0x00E0
# of Sectors 2 Bytes 0x0B40
Media Byte 1 Byte 0xF0
Sectors Per FAT 2 Bytes 0x0009
Sectors Per Track 2 Bytes 0x0012
# of Heads 2 Bytes 0x02
# of Hidden Sectors 4 Bytes 0x00000000
Huge Sectors 4 Bytes 0x00000000
Drive Number 1 Byte 0x00
Flags 1 Byte 0x00
Boot Signature 1 Byte 0x29
Volume ID 4 Bytes Any value
Volume Label 11 Bytes Any value
File System 8 Bytes FAT12

 

                    I am not going to discuss what each means. Because that would take us into file-systems. Although the FAT12 file-system is a simple one, you can find better sources on internet about file systems. You don't need to know about FAT12 because you could read data through BIOS via sector, cylinder, track and head number. If you are good in assembly, you should be able to figure that out easily by looking in BIOS interrupts. Now, the last 2 bytes of the 512 bytes is called Signature and that should be set to 0xAA55. Now you have 448 bytes to code your boot loader. The only thing you should be doing in loader is read the 'kernel' off the floppy disk into a memory location. And then, jump there. Wow! so easy. For clarity, I will provide a small example. You should be able modify it with some additional code and should be running your boot code with no problem.

[Note: This is for NASM]

[ORG 0x0000]
[BITS 16]
jmp START                                                        ; jump instruction

        OEM_ID                               db     "My    OS"
        BytesPerSector                  dw     0x0200
        SectorsPerCluster             db     0x01
        ReservedSectors              dw     0x0001
        TotalFATs                          db     0x02
        MaxRootEntries                 dw     0x00E0
        TotalSectorsSmall             dw     0x0B40
        MediaDescriptor               db     0xF0
        SectorsPerFAT                 dw     0x0009
        SectorsPerTrack               dw     0x0012
        NumHeads                        dw     0x0002
        HiddenSectors                 dd     0x00000000
        TotalSectorsLarge          dd     0x00000000
        DriveNumber                   db     0x00
        Flags                                db     0x00
        Signature                        db     0x29
        VolumeID                        dd     0xFFFFFFFF
        VolumeLabel                  db     "SIVA BOOT"
        SystemID                         db     "FAT12 "

START:
                cli
                mov ax, 0x07C0
                mov ds, ax
                mov es, ax
                mov fs, ax
                mov gs, ax

                mov ax, 0x0400                    ; create stack [change if necessary]
                mov ss, ax
                mov sp, 0xFFFF
                sti

                mov si, msgLoading            ; Print out the message
                call PrintMsg

;////// TO DO ///// [You should write your kernel loading code here]

 

; .................................................

 

;/////// Loading Code Ends here

PrintMesg:
                lodsb                                   ; load next character [ES:SI]
                or al, al                                ; If 00H, then exit
                jz .Print2
                mov ah, 0x0E
                mov bh, 0x00
                mov bl, 0x07
                int 0x10                               ; BIOS interrupt
                jmp PrintMesg                      ; Continue to next character
        .Print2:
                ret

;/////// Data Section //////

msgLoading        db        "Please Wait..... Loading Kernel.......", 00H

times 510-($-$$) DB 0                      ; This make sure that your code is 512 bytes long
dw 0xAA55                                         ; The boot signature

;/////////////////// Boot Code Ends ///////////////////////

 

                    There will be one thing that looks the same in everybody's OS, the Boot Code. It is becoming a long lasting tradition to load kernel from the boot code. The only difference is from there. You should finish the code there and should have the code running before going further. See you in next topic.

 

OS Into Home System Theory Choosing Platform Bootstrap INIT or KERNEL