Thursday, August 02, 2012

Launch Boot loader from MBR

In previous posts I went into the process of building a Boot loader in assembler on the MBR (Master Boot Record).

If you open a binary editor to inspect the contents of the Boot loader created in the previous post you will realize that the assembled code occupies around 203 bytes.

Due to the distribution of the MBR, there are around 440 bytes available for the code. So this simple code used to print basic drive information takes around 50% of the total available.

In modern OS (ie Linux) the MBR is used to launch the Boot loader (Linux) from a specific location in the Disk (where there should be more than enough space). Linux, in particular, uses the MBR to launch it's Boot loader (GRUB)

The following code will launch our boot loader from the MBR. First, our launcher must load the Bootloader from the media (aka Disk Drive) to a specific location in memory. Then we call a "jmp" to transfer the flow of execution to the loaded application.

  1. BITS 16                 ;Tell compiler that this is 16 Bit code
  2. org 07C00h              ;Tell compiler code will be loaded in this memory section
  3. mov si, txtStr
  4. call printTxt
  5. call crlf
  6. mov si, txtStr2
  7. call printTxt
  8. call crlf
  9. mov ah, 02h
  10. mov al, 1               ; Sectors to Read
  11. mov cl, 2               ; Sector to Start Reading [5..0]
  12. mov ch, 0               ; Cylinder [15..6]
  13. mov dh, 0               ; Head Number
  14. mov dl, 80h             ; Drive Number Hard Drive 1
  15. mov bx,0x07E0   ;Where to load Bootloader 0x70E0:00
  16. mov es,bx
  17. mov bx,0x00
  18. int 13h         ;Int 13 is all functions for disks
  19. mov si, txtLaunch
  20. call printTxt
  21. call crlf
  22. jmp 0x07E0:0x00         ;Run Bootloader.
  23.                                                 ; PhysicalAddress = Segment * 16 + Offset
  24. JMP $
  25. %include "utils.asm"
  26. ;AppData
  27. txtStr db "Hello Again..", 0
  28. txtStr2 db "Loading Kernel", 0
  29. txtLaunch db "Launching Kernel", 0
  30. times 510-($-$$) db 0   ;Fill the rest of the Loader with "0"
  31. dw 0AA55h               ;Bootloader Signature

Loading from Disk is achieved in lines 11-22. Please read INT 13H documentation to get more details about the "02h" service. In the code above I will read 1 sector from the (virtual) Hard Drive starting from sector #2 cx[5..0], Cylinder 0 cx[15..6], Head #0. It's important to know what this location means in the logical space on Disk; refer to CHS to LBA mapping. Logical space in this code point to the Sector #1 (It's the second sector, having MBR as the first one).

Bootloader will be stored in memory in the location 0x07E0:0x00 just after the location of the MBR. This area of memory is around 480 KB of available space (See Memory Map).

After it has been loaded in the memory, the code will jump to that location in memory and continue executing (line 28).

The following code is an example of our Boot loader. It simply prints "Bootloader Running" if everything is working correctly. There's not much to say other than the data registry (ds) must be reset, otherwise data will point to wrong locations in memory.

  1. BITS 16         ;Tell compiler that this is 16 Bit code
  2. push cs         ;Reset ds
  3. pop ds
  4. mov si, txtStr
  5. call printTxt
  6. call crlf
  7. JMP $
  8. %include "utils.asm"
  9. ;AppData
  10. txtStr db "Bootloader Running!", 0

There's no special magic during the assembly step. Files are compiled as in previous posts.

Only one question is left to answer. Where is our Boot loader stored? The answer lies in the line 13 on the first piece of code. Binary file must be stored in Sector 1 of the hard drive. The following instruction will do the job for us:

       dd if=test.bin bs=512 of=/dev/sdb seek=1

As usual (It will be usual in the following posts) there are a lot of steps to be done. You can complete them as exercise.

  • Take proper actions on the result of INT 13h. What if it returns an error?
  • How would you load a bigger Boot loader?
  • How would you implement "utils.asm"?