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.
16 ;------------------------------------------------------------------------------
23 FAT_DIRECTORY_ENTRY_SIZE EQU 020h
24 FAT_DIRECTORY_ENTRY_SHIFT EQU 5
29 LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
30 LOADER_FILENAME_PART2 EQU 036315244h ; "DR16"
31 LOADER_FILENAME_PART3 EQU 020202036h ; "6___"
35 jmp BootSectorEntryPoint ; JMP inst - 3 bytes
38 OemId db "INTEL " ; OemId - 8 bytes
39 ; BPB data below will be fixed by tool
40 SectorSize dw 0 ; Sector Size - 16 bits
41 SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
42 ReservedSectors dw 0 ; Reserved Sectors - 16 bits
43 NoFats db 0 ; Number of FATs - 8 bits
44 RootEntries dw 0 ; Root Entries - 16 bits
45 Sectors dw 0 ; Number of Sectors - 16 bits
46 Media db 0 ; Media - 8 bits - ignored
47 SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
48 SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
49 Heads dw 0 ; Heads - 16 bits - ignored
50 HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
51 LargeSectors dd 0 ; Large Sectors - 32 bits
52 PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
53 CurrentHead db 0 ; Current Head - 8 bits
54 Signature db 0 ; Signature - 8 bits - ignored
55 Id db " " ; Id - 4 bytes
56 FatLabel db " " ; Label - 11 bytes
57 SystemId db "FAT16 " ; SystemId - 8 bytes
63 ; ****************************************************************************
65 ; ****************************************************************************
66 lea si, cs:[StartString]
69 ; ****************************************************************************
71 ; ****************************************************************************
78 mov sp,07c00h ; sp = 0x7c00
79 mov bp,sp ; bp = 0x7c00
81 mov ah,8 ; ah = 8 - Get Drive Parameters Function
82 mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
83 int 13h ; Get Drive Parameters
86 inc al ; MaxHead = al + 1
87 push ax ; 0000:7bfe = MaxHead
89 and al,03fh ; MaxSector = al & 0x3f
90 push ax ; 0000:7bfc = MaxSector
92 cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
94 mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
95 shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
96 mov bx,cx ; bx = size of the Root Directory in bytes
97 and bx,BLOCK_MASK ; See if it is an even number of sectors long
98 jne BadBootSector ; If is isn't, then the boot sector is bad.
99 mov bx,cx ; bx = size of the Root Directory in bytes
100 shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
101 mov al,byte ptr [bp+NoFats] ; al = NoFats
102 xor ah,ah ; ah = 0 ==> ax = NoFats
103 mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat
104 add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
107 xor di,di ; Store directory in es:di = 1000:0000
108 call ReadBlocks ; Read entire Root Directory
109 add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
110 mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use
112 ; dx - variable storage (initial value is 0)
113 ; bx - loader (initial value is 0)
118 cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
120 cmp dword ptr [di+4],LOADER_FILENAME_PART2
122 cmp dword ptr [di+7],LOADER_FILENAME_PART3
124 mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
126 je FindNext ; Efivar.bin is not loaded
130 ; if the file is not loader file, see if it's "EFIVAR BIN"
131 cmp dword ptr [di], 056494645h ; Compare to "EFIV"
133 cmp dword ptr [di+4], 020205241h ; Compare to "AR "
135 cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
137 mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
140 je FindNext ; Efildr is not loaded
145 add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
146 sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
147 ; TODO: jump to FindVarStore if ...
153 mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
154 mov ax,cs ; Destination = 2000:0000
158 ReadFirstClusterOfEFILDR:
159 mov ax,cx ; ax = StartCluster
160 sub ax,2 ; ax = StartCluster - 2
162 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
165 pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
166 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
168 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
172 JumpIntoFirstSectorOfEFILDR:
173 mov word ptr [bp+JumpSegment],ax
191 ; ****************************************************************************
192 ; ReadBlocks - Reads a set of blocks from a block device
195 ; BX = Number of Blocks to Read
196 ; ES:DI = Buffer to store sectors read from disk
197 ; ****************************************************************************
200 ; bx = NumberOfBlocks
205 add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
206 add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
207 mov esi,eax ; esi = Start LBA
208 mov cx,bx ; cx = Number of blocks to read
210 mov bp,07bfch ; bp = 0x7bfc
211 mov eax,esi ; eax = Start LBA
212 xor edx,edx ; edx = 0
213 movzx ebx,word ptr [bp] ; bx = MaxSector
214 div ebx ; ax = StartLBA / MaxSector
215 inc dx ; dx = (StartLBA % MaxSector) + 1
216 sub bx,dx ; bx = MaxSector - Sector
217 inc bx ; bx = MaxSector - Sector + 1
218 cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
220 mov bx,cx ; bx = Blocks
223 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
225 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
226 ; dx = ax % (MaxHead + 1) = Head
228 push bx ; Save number of blocks to transfer
229 mov dh,dl ; dh = Head
230 mov bp,07c00h ; bp = 0x7c00
231 mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
232 mov ch,al ; ch = Cylinder
233 mov al,bl ; al = Blocks
234 mov ah,2 ; ah = Function 2
235 mov bx,di ; es:bx = Buffer address
241 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
242 sub cx,bx ; Blocks = Blocks - NumberOfBlocks
244 shl bx,(BLOCK_SHIFT-4)
246 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
252 ; ****************************************************************************
254 ; ****************************************************************************
256 ; if we found EFILDR, continue
261 lea si, cs:[ErrorString]
267 db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
269 db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
271 ; ****************************************************************************
272 ; LBA Offset for BootSector, need patched by tool for HD boot.
273 ; ****************************************************************************
276 LBAOffsetForBootSector:
279 ; ****************************************************************************
281 ; ****************************************************************************
285 dw 0aa55h ; Boot Sector Signature