]>
Commit | Line | Data |
---|---|---|
c69dd9df | 1 | ;------------------------------------------------------------------------------\r |
2 | ;*\r | |
e7c4ef5e | 3 | ;* Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r |
b1f700a8 | 4 | ;* This program and the accompanying materials \r |
c69dd9df | 5 | ;* are licensed and made available under the terms and conditions of the BSD License \r |
6 | ;* which accompanies this distribution. The full text of the license may be found at \r | |
7 | ;* http://opensource.org/licenses/bsd-license.php \r | |
8 | ;* \r | |
9 | ;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r | |
10 | ;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r | |
11 | ;* \r | |
12 | ;* bs32.asm\r | |
13 | ;* \r | |
14 | ;* Abstract:\r | |
15 | ;*\r | |
16 | ;------------------------------------------------------------------------------\r | |
17 | \r | |
18 | .model small\r | |
19 | .stack\r | |
20 | .486p\r | |
21 | .code\r | |
22 | \r | |
23 | FAT_DIRECTORY_ENTRY_SIZE EQU 020h\r | |
24 | FAT_DIRECTORY_ENTRY_SHIFT EQU 5\r | |
25 | BLOCK_SIZE EQU 0200h\r | |
26 | BLOCK_MASK EQU 01ffh\r | |
27 | BLOCK_SHIFT EQU 9\r | |
28 | ; "EFILDR_____"\r | |
29 | LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"\r | |
30 | LOADER_FILENAME_PART2 EQU 030325244h ; "DR20"\r | |
31 | LOADER_FILENAME_PART3 EQU 020202030h ; "0___"\r | |
32 | \r | |
33 | org 0h\r | |
34 | Ia32Jump:\r | |
35 | jmp BootSectorEntryPoint ; JMP inst - 3 bytes\r | |
36 | nop\r | |
37 | \r | |
38 | OemId db "INTEL " ; OemId - 8 bytes\r | |
39 | ; BPB data below will be fixed by tool\r\r | |
40 | SectorSize dw 0 ; Sector Size - 16 bits\r | |
41 | SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits\r | |
42 | ReservedSectors dw 0 ; Reserved Sectors - 16 bits\r | |
43 | NoFats db 0 ; Number of FATs - 8 bits\r | |
44 | RootEntries dw 0 ; Root Entries - 16 bits\r | |
45 | Sectors dw 0 ; Number of Sectors - 16 bits\r | |
46 | Media db 0 ; Media - 8 bits - ignored\r | |
47 | SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits\r | |
48 | SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored\r | |
49 | Heads dw 0 ; Heads - 16 bits - ignored\r | |
50 | HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored\r | |
51 | LargeSectors dd 0 ; Large Sectors - 32 bits \r | |
52 | \r | |
53 | ;******************************************************************************\r | |
54 | ;\r | |
55 | ;The structure for FAT32 starting at offset 36 of the boot sector. (At this point, \r | |
56 | ;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)\r | |
57 | ;\r | |
58 | ;******************************************************************************\r | |
59 | \r | |
60 | SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes\r | |
61 | ExtFlags dw 0 ; Mirror Flag - 2 bytes\r | |
62 | FSVersion dw 0 ; File System Version - 2 bytes\r | |
63 | RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes\r | |
64 | FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes\r | |
65 | BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes\r | |
66 | Reserved db 12 dup(0) ; Reserved Field - 12 bytes\r | |
67 | PhysicalDrive db 0 ; Physical Drive Number - 1 byte\r | |
68 | Reserved1 db 0 ; Reserved Field - 1 byte\r | |
69 | Signature db 0 ; Extended Boot Signature - 1 byte\r | |
70 | VolId db " " ; Volume Serial Number - 4 bytes\r | |
71 | FatLabel db " " ; Volume Label - 11 bytes\r | |
72 | FileSystemType db "FAT32 " ; File System Type - 8 bytes\r | |
73 | \r | |
74 | BootSectorEntryPoint:\r | |
75 | ASSUME ds:@code\r | |
76 | ASSUME ss:@code\r | |
77 | \r | |
78 | ; ****************************************************************************\r | |
79 | ; Start Print\r | |
80 | ; ****************************************************************************\r | |
e7c4ef5e | 81 | mov si, offset StartString\r |
c69dd9df | 82 | call PrintString\r |
83 | \r | |
84 | ; ****************************************************************************\r | |
85 | ; Print over\r | |
86 | ; ****************************************************************************\r | |
87 | \r | |
88 | mov ax,cs ; ax = 0\r | |
89 | mov ss,ax ; ss = 0\r | |
90 | add ax,1000h\r | |
91 | mov ds,ax\r | |
92 | \r | |
93 | mov sp,07c00h ; sp = 0x7c00\r | |
94 | mov bp,sp ; bp = 0x7c00\r | |
95 | \r | |
96 | mov ah,8 ; ah = 8 - Get Drive Parameters Function\r | |
97 | mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL\r | |
98 | int 13h ; Get Drive Parameters\r | |
99 | xor ax,ax ; ax = 0\r | |
100 | mov al,dh ; al = dh\r | |
101 | inc al ; MaxHead = al + 1\r | |
102 | push ax ; 0000:7bfe = MaxHead\r | |
103 | mov al,cl ; al = cl\r | |
104 | and al,03fh ; MaxSector = al & 0x3f\r | |
105 | push ax ; 0000:7bfc = MaxSector\r | |
106 | \r | |
107 | cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature\r | |
108 | jne BadBootSector\r | |
109 | mov cx,word ptr [bp+RootEntries] ; cx = RootEntries\r | |
110 | shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes\r | |
111 | mov bx,cx ; bx = size of the Root Directory in bytes\r | |
112 | and bx,BLOCK_MASK ; See if it is an even number of sectors long\r | |
113 | jne BadBootSector ; If is isn't, then the boot sector is bad.\r | |
114 | mov bx,cx ; bx = size of the Root Directory in bytes\r | |
115 | shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors\r | |
116 | mov al,byte ptr [bp+NoFats] ; al = NoFats\r | |
117 | xor ah,ah ; ah = 0 ==> ax = NoFats\r | |
118 | mul word ptr [bp+SectorsPerFat32] ; ax = NoFats * SectorsPerFat\r | |
119 | add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA\r | |
120 | add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA\r | |
121 | mov word ptr [bp],ax ; Save FirstClusterLBA for later use\r | |
122 | \r | |
123 | mov ax,word ptr [bp+RootCluster] ; ax = StartCluster of Root Directory\r | |
124 | sub ax,2 ; ax = StartCluster - 2\r | |
125 | xor bh,bh \r | |
126 | mov bl,byte ptr [bp+SectorsPerCluster]; bx = SectorsPerCluster\r | |
127 | mul bx ; ax = (StartCluster - 2) * SectorsPerCluster\r | |
128 | add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster\r | |
129 | push ds\r | |
130 | pop es\r | |
131 | xor di,di ; Store directory in es:di = 1000:0000\r | |
132 | call ReadBlocks ; Read StartCluster of Root Directory\r | |
133 | \r | |
134 | ; dx - variable storage (initial value is 0)\r | |
135 | ; bx - loader (initial value is 0)\r | |
136 | xor dx, dx\r | |
137 | xor bx, bx\r | |
138 | \r | |
139 | FindEFILDR:\r | |
140 | cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"\r | |
141 | jne FindVARSTORE\r | |
142 | cmp dword ptr [di+4],LOADER_FILENAME_PART2\r | |
143 | jne FindVARSTORE\r | |
144 | cmp dword ptr [di+7],LOADER_FILENAME_PART3\r | |
145 | jne FindVARSTORE\r | |
146 | mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------\r | |
147 | test dx, dx\r | |
148 | je FindNext ; Efivar.bin is not loaded\r | |
149 | jmp FoundAll\r | |
150 | \r | |
151 | FindVARSTORE:\r | |
152 | ; if the file is not loader file, see if it's "EFIVAR BIN"\r | |
153 | cmp dword ptr [di], 056494645h ; Compare to "EFIV"\r | |
154 | jne FindNext\r | |
155 | cmp dword ptr [di+4], 020205241h ; Compare to "AR "\r | |
156 | jne FindNext\r | |
157 | cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"\r | |
158 | jne FindNext\r | |
159 | mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------\r | |
160 | add dx, 26\r | |
161 | test bx, bx\r | |
162 | je FindNext ; Efildr is not loaded\r | |
163 | jmp FoundAll\r | |
164 | \r | |
165 | FindNext:\r | |
166 | ; go to next find\r | |
167 | add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di\r | |
168 | sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx\r | |
169 | ; TODO: jump to FindVarStore if ...\r | |
170 | jne FindEFILDR\r | |
171 | jmp NotFoundAll\r | |
172 | \r | |
173 | FoundAll:\r | |
174 | FoundEFILDR:\r | |
175 | mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------\r | |
176 | mov ax,cs ; Destination = 2000:0000\r | |
177 | add ax,2000h\r | |
178 | mov es,ax\r | |
179 | xor di,di\r | |
180 | ReadFirstClusterOfEFILDR:\r | |
181 | mov ax,cx ; ax = StartCluster\r | |
182 | sub ax,2 ; ax = StartCluster - 2\r | |
183 | xor bh,bh \r | |
184 | mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster\r | |
185 | push dx\r | |
186 | mul bx\r | |
187 | pop dx ; ax = (StartCluster - 2) * SectorsPerCluster\r | |
188 | add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster\r | |
189 | xor bh,bh\r | |
190 | mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster\r | |
191 | push es\r | |
192 | call ReadBlocks\r | |
193 | pop ax\r | |
194 | JumpIntoFirstSectorOfEFILDR:\r | |
195 | mov word ptr [bp+JumpSegment],ax\r | |
196 | JumpFarInstruction:\r | |
197 | db 0eah\r | |
198 | JumpOffset:\r | |
199 | dw 0000h\r | |
200 | JumpSegment:\r | |
201 | dw 2000h\r | |
202 | \r | |
203 | \r | |
204 | PrintString:\r | |
205 | mov ax,0b800h\r | |
206 | mov es,ax\r | |
207 | mov ax, 07c0h\r | |
208 | mov ds, ax\r | |
e7c4ef5e | 209 | mov cx, 6\r |
c69dd9df | 210 | mov di, 160\r |
211 | rep movsw\r | |
212 | ret\r | |
213 | ; ****************************************************************************\r | |
214 | ; ReadBlocks - Reads a set of blocks from a block device\r | |
215 | ;\r | |
216 | ; AX = Start LBA\r | |
217 | ; BX = Number of Blocks to Read\r | |
218 | ; ES:DI = Buffer to store sectors read from disk\r | |
219 | ; ****************************************************************************\r | |
220 | \r | |
221 | ; cx = Blocks\r | |
222 | ; bx = NumberOfBlocks\r | |
223 | ; si = StartLBA\r | |
224 | \r | |
225 | ReadBlocks:\r | |
226 | pusha\r | |
227 | add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA\r | |
228 | add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA\r | |
229 | mov esi,eax ; esi = Start LBA\r | |
230 | mov cx,bx ; cx = Number of blocks to read\r | |
231 | ReadCylinderLoop:\r | |
232 | mov bp,07bfch ; bp = 0x7bfc\r | |
233 | mov eax,esi ; eax = Start LBA\r | |
234 | xor edx,edx ; edx = 0\r | |
235 | movzx ebx,word ptr [bp] ; bx = MaxSector\r | |
236 | div ebx ; ax = StartLBA / MaxSector\r | |
237 | inc dx ; dx = (StartLBA % MaxSector) + 1\r | |
238 | sub bx,dx ; bx = MaxSector - Sector\r | |
239 | inc bx ; bx = MaxSector - Sector + 1\r | |
240 | cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)\r | |
241 | jg LimitTransfer\r | |
242 | mov bx,cx ; bx = Blocks\r | |
243 | LimitTransfer:\r | |
244 | push cx\r | |
245 | mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector\r | |
246 | xor dx,dx ; dx = 0\r | |
247 | div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder \r | |
248 | ; dx = ax % (MaxHead + 1) = Head\r | |
249 | \r | |
250 | push bx ; Save number of blocks to transfer\r | |
251 | mov dh,dl ; dh = Head\r | |
252 | mov bp,07c00h ; bp = 0x7c00\r | |
253 | mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number\r | |
254 | mov ch,al ; ch = Cylinder\r | |
255 | mov al,bl ; al = Blocks\r | |
256 | mov ah,2 ; ah = Function 2\r | |
257 | mov bx,di ; es:bx = Buffer address\r | |
258 | int 013h\r | |
259 | jc DiskError\r | |
260 | pop bx\r | |
261 | pop cx\r | |
262 | movzx ebx,bx\r | |
263 | add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks\r | |
264 | sub cx,bx ; Blocks = Blocks - NumberOfBlocks\r | |
265 | mov ax,es\r | |
266 | shl bx,(BLOCK_SHIFT-4)\r | |
267 | add ax,bx\r | |
268 | mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE\r | |
269 | cmp cx,0\r | |
270 | jne ReadCylinderLoop\r | |
271 | popa\r | |
272 | ret\r | |
273 | \r | |
274 | ; ****************************************************************************\r | |
275 | ; ERROR Condition:\r | |
276 | ; ****************************************************************************\r | |
277 | NotFoundAll:\r | |
278 | ; if we found EFILDR, continue\r | |
279 | test bx,bx\r | |
280 | jne FoundEFILDR\r | |
281 | BadBootSector:\r | |
282 | DiskError:\r | |
e7c4ef5e | 283 | mov si, offset ErrorString\r |
c69dd9df | 284 | call PrintString\r |
285 | Halt:\r | |
286 | jmp Halt\r | |
287 | \r | |
288 | StartString:\r | |
e7c4ef5e | 289 | db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch\r |
c69dd9df | 290 | ErrorString:\r |
e7c4ef5e | 291 | db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch\r |
c69dd9df | 292 | \r |
293 | ; ****************************************************************************\r | |
294 | ; LBA Offset for BootSector, need patched by tool for HD boot.\r | |
295 | ; ****************************************************************************\r | |
296 | \r | |
297 | org 01fah\r | |
298 | LBAOffsetForBootSector:\r | |
299 | dd 0h\r | |
300 | \r | |
301 | ; ****************************************************************************\r | |
302 | ; Sector Signature\r | |
303 | ; ****************************************************************************\r | |
304 | \r | |
305 | org 01feh\r | |
306 | SectorSignature:\r | |
307 | dw 0aa55h ; Boot Sector Signature\r | |
308 | \r | |
309 | end \r | |
310 | \r |