You are on page 1of 12

Olux Organization

Introduction to Bootloader

Introduction to Bootloader
Merck Hung merckhung@gmail.com, 洪豪謙

Agenda
1. 簡單的 Bootloader 範例
2. 關於 FAT BPB Structure
3. 關於 MBR Signature
4. 開發工具
5. 組合語言
6. Partition Table
7. INT 16h 取得 Keyboard Input
8. VGA RAM 於螢幕列印字串
9. 跳轉 C 語言
10. 實際測試 Bootloader 開機
Olux Organization
Introduction to Bootloader

1. 簡單的 Bootloader 範例
以下是一簡單的 Bootloader 範例, 一開始部分是傳統 FAT12 的 Structure.
以現在的機器來說, 這部分不要也可以開機, 但如果有的話相容性較佳.

但如果是以 FAT16, FAT32 為檔案系統之作業系統, 則這部分務必要填寫正確數值,


否則作業系統本身可能無法讀取硬碟資料.
Olux Organization
Introduction to Bootloader

2. 關於 FAT BPB Structure


Name Offset Size Description
(byte) (bytes)
BS_jmpBoot 0 3 Jump instruction to boot code. This field has two allowed forms:
jmpBoot[0] = 0xEB, jmpBoot[1] = 0x??, jmpBoot[2] = 0x90
and

jmpBoot[0] = 0xE9, jmpBoot[1] = 0x??, jmpBoot[2] = 0x??

0x?? indicates that any 8-bit value is allowed in that byte. What this forms is a three-byte Intel
x86 unconditional branch (jump) instruction that jumps to the start of the operating system
bootstrap code. This code typically occupies the rest of sector 0 of the volume following the

BPB and possibly other sectors. Either of these forms is acceptable. JmpBoot[0] = 0xEB is the
more frequently used format.
BS_OEMName 3 8 “MSWIN4.1” There are many misconceptions about this field. It is only a name string.
Microsoft operating systems don’t pay any attention to this field. Some FAT drivers do. This is
the reason that the indicated string, “MSWIN4.1”, is the recommended setting, because it is the
setting least likely to cause compatibility problems. If you want to put something else in here,
that is your option, but the result may be that some FAT drivers might not recognize the volume.
Typically this is some indication of what system formatted the volume.
BPB_BytsPerSec 11 2 Count of bytes per sector. This value may take on only the following values: 512, 1024, 2048 or
4096. If maximum compatibility with old implementations is desired, only the value 512 should
be used. There is a lot of FAT code in the world that is basically “hard wired” to 512 bytes per
sector and doesn’t bother to check this field to make sure it is 512. Microsoft operating systems
will properly support 1024, 2048, and 4096.

Note: Do not misinterpret these statements about maximum compatibility. If the media being
recorded has a physical sector size N, you must use N and this must still be less than or equal to

4096. Maximum compatibility is achieved by only using media with specific sector sizes.
BPB_SecPerClus 13 1 Number of sectors per allocation unit. This value must be a power of 2 that is greater than 0.
The legal values are 1, 2, 4, 8, 16, 32, 64, and 128. Note however, that a value should never be
used that results in a “bytes per cluster” value (BPB_BytsPerSec * BPB_SecPerClus) greater
than 32K (32 * 1024). There is a misconception that values greater than this are OK. Values that
cause a cluster size greater than 32K bytes do not work properly; do not try to define one. Some
versions of some systems allow 64K bytes per cluster value. Many application setup programs
will not work correctly on such a FAT volume.
BPB_RsvdSecCn 14 2 Number of reserved sectors in the Reserved region of the volume starting at the first sector of
t the volume. This field must not be 0. For FAT12 and FAT16 volumes, this value should never
be anything other than 1. For FAT32 volumes, this value is typically 32. There is a lot of FAT
code in the world “hard wired” to 1 reserved sector for FAT12 and FAT16 volumes and that
doesn’t bother to check this field to make sure it is 1. Microsoft operating systems will properly
support any non-zero value in this field.
Olux Organization
Introduction to Bootloader

BPB_NumFATs 16 1 The count of FAT data structures on the volume. This field should always contain the value 2
for any FAT volume of any type. Although any value greater than or equal to 1 is perfectly
valid, many software programs and a few operating systems’ FAT file system drivers may not
function properly if the value is something other than 2. All Microsoft file system drivers will
support a value other than 2, but it is still highly recommended that no value other than 2 be
used in this field.

The reason the standard value for this field is 2 is to provide redundancy for the FAT data
structure so that if a sector goes bad in one of the FATs, that data is not lost because it is
duplicated in the other FAT. On non-disk-based media, such as FLASH memory cards, where
such redundancy is a useless feature, a value of 1 may be used to save the space that a second

copy of the FAT uses, but some FAT file system drivers might not recognize such a volume
properly.
BPB_RootEntCnt 17 2 For FAT12 and FAT16 volumes, this field contains the count of 32-byte directory entries in the
root directory. For FAT32 volumes, this field must be set to 0. For FAT12 and FAT16 volumes,
this value should always specify a count that when multiplied by 32 results in an even multiple
of BPB_BytsPerSec. For maximum compatibility, FAT16 volumes should use the value 512.
BPB_TotSec16 19 2 This field is the old 16-bit total count of sectors on the volume. This count includes the count of
all sectors in all four regions of the volume. This field can be 0; if it is 0, then BPB_TotSec32
must be non-zero. For FAT32 volumes, this field must be 0. For FAT12 and FAT16 volumes,
this field contains the sector count, and BPB_TotSec32 is 0 if the total sector count “fits” (is
less than 0x10000).
BPB_Media 21 1 0xF8 is the standard value for “fixed” (non-removable) media. For removable media, 0xF0 is
frequently used. The legal values for this field are 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD,
0xFE, and 0xFF. The only other important point is that whatever value is put in here must also
be put in the low byte of the FAT[0] entry. This dates back to the old MS-DOS 1.x media
determination noted earlier and is no longer usually used for anything.
BPB_FATSz16 22 2 This field is the FAT12/FAT16 16-bit count of sectors occupied by ONE FAT. On FAT32
volumes this field must be 0, and BPB_FATSz32 contains the FAT size count.
BPB_SecPerTrk 24 2 Sectors per track for interrupt 0x13. This field is only relevant for media that have a geometry
(volume is broken down into tracks by multiple heads and cylinders) and are visible on interrupt
0x13. This field contains the “sectors per track” geometry value.
BPB_NumHeads 26 2 Number of heads for interrupt 0x13. This field is relevant as discussed earlier for
BPB_SecPerTrk. This field contains the one based “count of heads”. For example, on a 1.44
MB 3.5-inch floppy drive this value is 2.
BPB_HiddSec 28 4 Count of hidden sectors preceding the partition that contains this FAT volume. This field is
generally only relevant for media visible on interrupt 0x13. This field should always be zero on
media that are not partitioned. Exactly what value is appropriate is operating system specific.
BPB_TotSec32 32 4 This field is the new 32-bit total count of sectors on the volume. This count includes the count
of all sectors in all four regions of the volume. This field can be 0; if it is 0, then BPB_TotSec16
must be non-zero. For FAT32 volumes, this field must be non-zero. For FAT12/FAT16 volumes,
this field contains the sector count if BPB_TotSec16 is 0 (count is greater than or equal to
0x10000).
Olux Organization
Introduction to Bootloader

3. 關於 MBR Signature
BIOS會要求 MBR 內的 Bootloader, 在 512 bytes 的邊界上, 務必要有 0xAA55 的 MBR Signature.
如無則 BIOS 會認為此顆硬碟無法開機.

在組合語言中, 我們利用 DUP Pseudo Macro 來填滿 0, 讓 0xAA55 正好對齊 512 bytes 邊界.
Olux Organization
Introduction to Bootloader

4. 開發工具
在組合語言的開發中, 我們將會使用 MASM 6.11 來組譯我們的 Bootloader.
而 C語言方面, 則使用 “Digital Mars C/C++ Compilers” 來做.

先將主要用於開機的 sldr.asm (MBR區段) 及 cstart.c (C 程式區段) 各自編譯為 object file 後,


最後再將所有 object file link 為 DOS EXE程式.

但因為編譯出來為 DOS 可執行程式, 故我們需要再利用 EXE2ROM 工具來轉換 EXE


到可用於開機的 Binary 檔.

EXE 與 BIN 檔之差異為, EXE 內程式之 Address 會在 DOS 載入該程式時填寫,


會隨著每次載入而有不同之值.

而 BIN 檔內之 Address 是已經填寫固定之值, 並以 0x7C00 為起始點.

ASSEMBLER = ml.exe
CC = sc.exe
EXE2ROM = utils\exe2rom.exe
ASSEMBLE_FLAGS = /Fm /Fl /c
CC_FLAGS = -c -ms
OBJS =

all: sldr

sldr:
$(ASSEMBLER) $(ASSEMBLE_FLAGS) $@.asm
$(CC) -ms -c cstart.c
$(CC) -ms sldr.obj cstart.obj
$(EXE2ROM) -s0x7c00 SLDR.EXE sldr.bin

clean:
rm -rf *.img *.bin *.EXE *.exe *.map *.obj *.lst *.MAP *.STS *.CV4 DELETED
Olux Organization
Introduction to Bootloader

5. 組合語言
SubRoutine 的要素
scnClrScr PROC NEAR PUBLIC

push ds
push ax
push bx
push cx

; Point to VGA Text mode buffer


push VIDEORAM
pop ds

mov ax, COL_WB


xor bx, bx
mov cx, (COLUMN * LINE * 2)

ClrScr:

; Clear Screen
mov ds:[bx], ax
add bx, 2
sub cx, 2
jnz ClrScr

pop cx
pop bx
pop ax
pop ds

ret

scnClrScr ENDP

Flow Control
liChkSnapshotRequest PROC NEAR PUBLIC

push es
push di
push ax

; Get Control Data


mov ax, RELOCATE_SEG
mov es, ax
mov di, CTL_OFFSET

; Check Flag
cmp es:[di].liCtlInfo.SnapshotRequest, 0
je notSet

; Set, Switch to User 2


mov es:[di].liCtlInfo.CurrentUser, 2
call liSaveControlData
stc
jmp Exit

notSet:
Olux Organization
Introduction to Bootloader

6. Partition Table
基本上 MBR 有 512 bytes 可供使用, 但其中需扣除 Partition Table 的大小才是真正 MBR
Bootloader 可用的空間.

其中 Partition #1 從 0x1BE 開始, 每 16 bytes 都是一個 Primary Partition 的 Information, 總共有 4


個 Primary Partitions.

這範圍 Bootloader 不能有任何 Code, 因為 fdisk 將會寫入這個部分, 否則 bootloader


將會有被破壞之虞.

Field Sample
Byte Offset Meaning
Length Value
Boot Indicator. Indicates whether the partition is the system
partition. Legal values are:
00 BYTE 0x80
00 = Do not use for booting.
80 = System partition.
01 BYTE 0x01 Starting Head.
Starting Sector. Only bits 0-5 are used. Bits 6-7 are the upper two
02 6 bits 0x01
bits for the Starting Cylinder field.
Starting Cylinder. This field contains the lower 8 bits of the cylinder
03 10 bits 0x00 value. Starting cylinder is thus a 10-bit number, with a maximum
value of 1023.
System ID. This byte defines the volume type. In Windows NT, it
04 BYTE 0x06 also indicates that a partition is part of a volume that requires the
use of the HKEY_LOCAL_MACHINE\SYSTEM\DISK Registry subkey.
05 BYTE 0x0F Ending Head.
Ending Sector. Only bits 0-5 are used. Bits 6-7 are the upper two
06 6 bits 0x3F
bits for the Ending Cylinder field.
Ending Cylinder. This field contains the lower 8 bits of the cylinder
07 10 bits 0x196 value. Ending cylinder is thus a 10-bit number, with a maximum
value of 1023.
3F 00 00
08 DWORD Relative Sector.
00
51 42 06
12 DWORD Total Sectors.
00
Olux Organization
Introduction to Bootloader

取得 Keyboard Input
7. INT 16h取得

;##############################################################################
; wait_input -- Call BIOS service to get keyboard input
;
; Input :
; None
;
; Output:
; AH = Scan code
; AL = ASCII code
;
; Modified:
; None
;
wait_input MACRO

xor ax, ax
int 16h

ENDM

Keyboard Codes (in hex)


Key Scan Code ASCII Shift Ctrl Alt Num Caps Shift Caps Shift Num
Esc 01 1B 1B 1B - 1B 1B 1B 1B
1! 02 31 21 7800 31 31 31 31
2@ 03 32 40 0300 7900 32 32 32 32
3# 04 33 23 - 7A00 33 33 33 33
4$ 05 34 24 - 7B00 34 34 34 34
5% 06 35 25 - 7C00 35 35 35 35
6^ 07 36 5E 1E 7D00 36 36 36 36
7& 08 37 26 - 7E00 37 37 37 37
8* 09 38 2A - 7F00 38 38 38 38
9( 0A 39 28 - 8000 39 39 39 39
0) 0B 30 29 - 8100 30 30 30 30
-_ 0C 2D 5F 1F 8200 2D 2D 5F 5F
=+ 0D 3D 2B - 8300 3D 3D 2B 2B
Bksp 0E 08 08 7F - 08 08 08 08
Tab 0F 09 0F00 - 09 09 0F00 0F00
Q 10 71 51 11 1000 71 51 71 51
W 11 77 57 17 1100 77 57 77 57
E 12 65 45 05 1200 65 45 65 45
R 13 72 52 12 1300 72 52 72 52
T 14 74 54 14 1400 74 54 74 54
Y 15 79 59 19 1500 79 59 79 59
U 16 75 55 15 1600 75 55 75 55
I 17 69 49 09 1700 69 49 69 49
O 18 6F 4F 0F 1800 6F 4F 6F 4F
P 19 70 50 10 1900 70 50 70 50
[{ 1A 5B 7B 1B - 5B 5B 7B 7B
]} 1B 5D 7D 1D - 5D 5D 7D 7D
enter 1C 0D 0D 0A - 0D 0D 0A 0A
ctrl 1D - - - - - - - -
A 1E 61 41 01 1E00 61 41 61 41
S 1F 73 53 13 1F00 73 53 73 53
Olux Organization
Introduction to Bootloader

Keyboard Codes (in hex)


Key Scan Code ASCII Shift Ctrl Alt Num Caps Shift Caps Shift Num
D 20 64 44 04 2000 64 44 64 44
F 21 66 46 06 2100 66 46 66 46
G 22 67 47 07 2200 67 47 67 47
H 23 68 48 08 2300 68 48 68 48
J 24 6A 4A 0A 2400 6A 4A 6A 4A
K 25 6B 4B 0B 2500 6B 4B 6B 4B
L 26 6C 4C 0C 2600 6C 4C 6C 4C
;: 27 3B 3A - - 3B 3B 3A 3A
'" 28 27 22 - - 27 27 22 22
`~ 29 60 7E - - 60 60 7E 7E
Lshift 2A - - - - - - - -
\| 2B 5C 7C 1C - 5C 5C 7C 7C
Z 2C 7A 5A 1A 2C00 7A 5A 7A 5A
X 2D 78 58 18 2D00 78 58 78 58
C 2E 63 43 03 2E00 63 43 63 43
V 2F 76 56 16 2F00 76 56 76 56
B 30 62 42 02 3000 62 42 62 42
N 31 6E 4E 0E 3100 6E 4E 6E 4E
M 32 6D 4D 0D 3200 6D 4D 6D 4D
,< 33 2C 3C - - 2C 2C 3C 3C
.> 34 2E 3E - - 2E 2E 3E 3E
/? 35 2F 3F - - 2F 2F 3F 3F
Rshift 36 - - - - - - - -
* PrtSc 37 2A INT 5 10 - 2A 2A INT 5 INT 5
alt 38 - - - - - - - -
space 39 20 20 20 - 20 20 20 20
caps 3A - - - - - - - -
F1 3B 3B00 5400 5E00 6800 3B00 3B00 5400 5400
F2 3C 3C00 5500 5F00 6900 3C00 3C00 5500 5500
F3 3D 3D00 5600 6000 6A00 3D00 3D00 5600 5600
F4 3E 3E00 5700 6100 6B00 3E00 3E00 5700 5700
F5 3F 3F00 5800 6200 6C00 3F00 3F00 5800 5800
F6 40 4000 5900 6300 6D00 4000 4000 5900 5900
F7 41 4100 5A00 6400 6E00 4100 4100 5A00 5A00
F8 42 4200 5B00 6500 6F00 4200 4200 5B00 5B00
F9 43 4300 5C00 6600 7000 4300 4300 5C00 5C00
F10 44 4400 5D00 6700 7100 4400 4400 5D00 5D00
num 45 - - - - - - - -
scrl 46 - - - - - - - -
home 47 4700 37 7700 - 37 4700 37 4700
up 48 4800 38 - - 38 4800 38 4800
pgup 49 4900 39 8400 - 39 4900 39 4900
- (kpd) 4A 2D 2D - - 2D 2D 2D 2D
left 4B 4B00 34 7300 - 34 4B00 34 4B00
center 4C 4C00 35 - - 35 4C00 35 4C00
right 4D 4D00 36 7400 - 36 4D00 36 4D00
+ (kpd) 4E 2B 2B - - 2B 2B 2B 2B
end 4F 4F00 31 7500 - 31 4F00 31 4F00
down 50 5000 32 - - 32 5000 32 5000
pgdn 51 5100 33 7600 - 33 5100 33 5100
ins 52 5200 30 - - 30 5200 30 5200
del 53 5300 2E - - 2E 5300 2E 5300
Olux Organization
Introduction to Bootloader

8. VGA RAM 於螢幕列印字串


記憶體 0xB8000 的位址, 是 PC VGA RAM 的起始位置.
偶數 Offset 為 ASCII Code, 及其相對於螢幕上之顯示位置.
奇數 Offset 為 Attribute Code, 用以控制相對螢幕位置上之, 背景與前景字串顏色.

Foreground Text Background


0x00 - Black 0x00 - Black
0x01 - Blue 0x10 - Blue
0x02 - Green 0x20 - Green
0x03 - Cyan 0x30 - Cyan
0x04 - Red 0x40 - Red
0x05 - Magenta 0x50 - Magenta
0x06 - Brown 0x60 - Brown
0x07 - Light Gray 0x70 - Light Gray
0x08 - Drak Gray 0x80 - Blinking Black
0x09 - Light Blue 0x90 - Blinking Blue
0x0A - Light Green 0xA0 - Blinking Green
0x0B - Light Cyan 0xB0 - Blinking Cyan
0x0C - Light Red 0xC0 - Blinking Red
0x0D - Light Magenta 0xD0 - Blinking Magenta
0x0E - Yellow 0xE0 - Blinking Brown
0x0F - White 0xF0 - Blinking Light Gray
Olux Organization
Introduction to Bootloader

9. 跳轉 C 語言

C 語言DOS程式之 Code 區段命名通常為 _TEXT, 進入點為 _main.


故我們在組合語言區段內, 宣告一 _TEXT Code Segment, 並 extern _main 進來.

而後於組合語言 _TEXT16 開機的過程中, 做長跳躍至 _TEXT 內的 _main 函式, 也就是 C


語言的進入點, 來完成跳轉 C 語言.

jmp _main
jmp $

STACK_BASE DB 478 DUP( 0 )


DW 0AA55h

MAIN endp

;###############################################################################
; Data area
;

_TEXT16 ENDS

_TEXT SEGMENT PARA USE16 'CODE'

EXTERN _main:FAR
_TEXT ENDS

You might also like