1 ;------------------------------------------------------------------------------
3 ;* Copyright 2006 - 2007, Intel Corporation
4 ;* All rights reserved. This program and the accompanying materials
5 ;* are licensed and made available under the terms and conditions of the BSD License
6 ;* which accompanies this distribution. The full text of the license may be found at
7 ;* http://opensource.org/licenses/bsd-license.php
9 ;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 ;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 ;* bootsect.asm is built as 16-bit binary file in 512 bytes and patched to disk/partition's
15 ;* first section - boot sector.
17 ;* The startup sequence for DUET disk boot sector is:
19 ;* 1, LegacyBios check 0xAA55 signature at boot sectore offset 0x1FE to judget
20 ;* whether disk/partition is bootable.
21 ;* 2, LegacyBios will load boot sector to 0x7c00 in real mode, pass BPB data and
22 ;* hand off control to 0x7c00 code.
23 ;* 3, boot sector code simply parse FAT format in boot disk and find EfiLdr binary file
24 ;* and EfiVar.bin if exists. For first boot, EfiVar.bin does not exist.
25 ;* 4, boot sector load the first sector of EfiLdr binary which is start.com to
26 ;* 0x2000:0x0000 address.
27 ;* 5, boot sector handoff control to 0x2000:0x0000 for start.com binary.
29 ;------------------------------------------------------------------------------
36 FAT_DIRECTORY_ENTRY_SIZE EQU 020h
37 FAT_DIRECTORY_ENTRY_SHIFT EQU 5
42 LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
43 LOADER_FILENAME_PART2 EQU 020205244h ; "DR__"
44 LOADER_FILENAME_PART3 EQU 020202020h ; "____"
48 jmp BootSectorEntryPoint ; JMP inst - 3 bytes
51 OemId db "INTEL " ; OemId - 8 bytes
52 ; BPB data below will be fixed by tool
53 SectorSize dw 0 ; Sector Size - 16 bits
54 SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
55 ReservedSectors dw 0 ; Reserved Sectors - 16 bits
56 NoFats db 0 ; Number of FATs - 8 bits
57 RootEntries dw 0 ; Root Entries - 16 bits
58 Sectors dw 0 ; Number of Sectors - 16 bits
59 Media db 0 ; Media - 8 bits - ignored
60 SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
61 SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
62 Heads dw 0 ; Heads - 16 bits - ignored
63 HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
64 LargeSectors dd 0 ; Large Sectors - 32 bits
65 PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
66 CurrentHead db 0 ; Current Head - 8 bits
67 Signature db 0 ; Signature - 8 bits - ignored
68 Id db " " ; Id - 4 bytes
69 FatLabel db " " ; Label - 11 bytes
70 SystemId db "FAT12 " ; SystemId - 8 bytes
76 ; ****************************************************************************
78 ; ****************************************************************************
79 lea si, cs:[StartString]
82 ; ****************************************************************************
84 ; ****************************************************************************
91 mov sp,07c00h ; sp = 0x7c00
92 mov bp,sp ; bp = 0x7c00
94 mov ah,8 ; ah = 8 - Get Drive Parameters Function
95 mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
96 int 13h ; Get Drive Parameters
98 mov al,dh ; al = dh (number of sides (0 based))
99 inc al ; MaxHead = al + 1
100 push ax ; 0000:7bfe = MaxHead
101 mov al,cl ; al = cl (CL = sectors per track)
102 and al,03fh ; MaxSector = al & 0x3f
103 push ax ; 0000:7bfc = MaxSector
105 cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
107 mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
108 shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
109 mov bx,cx ; bx = size of the Root Directory in bytes
110 and bx,BLOCK_MASK ; See if it is an even number of sectors long
111 jne BadBootSector ; If is isn't, then the boot sector is bad.
112 mov bx,cx ; bx = size of the Root Directory in bytes
113 shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
114 mov al,byte ptr [bp+NoFats] ; al = NoFats
115 xor ah,ah ; ah = 0 ==> ax = NoFats
116 mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat
117 add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
120 xor di,di ; Store directory in es:di = 1000:0000
121 call ReadBlocks ; Read entire Root Directory
122 add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
123 mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use
125 ; dx - variable storage (initial value is 0)
126 ; bx - loader (initial value is 0)
131 cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
133 cmp dword ptr [di+4],LOADER_FILENAME_PART2
135 cmp dword ptr [di+7],LOADER_FILENAME_PART3
137 mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
139 je FindNext ; Efivar.bin is not loaded
143 ; if the file is not loader file, see if it's "EFIVAR BIN"
144 cmp dword ptr [di], 056494645h ; Compare to "EFIV"
146 cmp dword ptr [di+4], 020205241h ; Compare to "AR "
148 cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
150 mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
153 je FindNext ; Efildr is not loaded
158 add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
159 sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
160 ; TODO: jump to FindVarStore if ...
165 FoundEFILDR: ; 0x7cfe
166 mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
167 mov ax,cs ; Destination = 2000:0000
171 ReadFirstClusterOfEFILDR:
172 mov ax,cx ; ax = StartCluster
173 sub ax,2 ; ax = StartCluster - 2
175 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
178 pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
179 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
181 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
185 JumpIntoFirstSectorOfEFILDR:
186 mov word ptr [bp+JumpSegment],ax ; 0x7d26
187 JumpFarInstruction: ; 0x7d2a
204 ; ****************************************************************************
205 ; ReadBlocks - Reads a set of blocks from a block device
208 ; BX = Number of Blocks to Read
209 ; ES:DI = Buffer to store sectors read from disk
210 ; ****************************************************************************
213 ; bx = NumberOfBlocks
218 add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
219 add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
220 mov esi,eax ; esi = Start LBA
221 mov cx,bx ; cx = Number of blocks to read
223 mov bp,07bfch ; bp = 0x7bfc
224 mov eax,esi ; eax = Start LBA
225 xor edx,edx ; edx = 0
226 movzx ebx,word ptr [bp] ; bx = MaxSector
227 div ebx ; ax = StartLBA / MaxSector
228 inc dx ; dx = (StartLBA % MaxSector) + 1
229 sub bx,dx ; bx = MaxSector - Sector
230 inc bx ; bx = MaxSector - Sector + 1
231 cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
233 mov bx,cx ; bx = Blocks
236 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
238 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
239 ; dx = ax % (MaxHead + 1) = Head
241 push bx ; Save number of blocks to transfer
242 mov dh,dl ; dh = Head
243 mov bp,07c00h ; bp = 0x7c00
244 mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
245 mov ch,al ; ch = Cylinder
246 mov al,bl ; al = Blocks
247 mov ah,2 ; ah = Function 2
248 mov bx,di ; es:bx = Buffer address
254 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
255 sub cx,bx ; Blocks = Blocks - NumberOfBlocks
257 shl bx,(BLOCK_SHIFT-4)
259 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
265 ; ****************************************************************************
267 ; ****************************************************************************
268 NotFoundAll: ; 0x7da6
269 ; if we found EFILDR, continue
274 lea si, cs:[ErrorString]
280 db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
282 db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
284 ; ****************************************************************************
285 ; LBA Offset for BootSector, need patched by tool for HD boot.
286 ; ****************************************************************************
289 LBAOffsetForBootSector:
292 ; ****************************************************************************
294 ; ****************************************************************************
298 dw 0aa55h ; Boot Sector Signature