]>
Commit | Line | Data |
---|---|---|
c69dd9df | 1 | ;------------------------------------------------------------------------------\r |
2 | ;*\r | |
b1f700a8 HT |
3 | ;* Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>\r |
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 | ;* bs16.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 036315244h ; "DR16"\r | |
31 | LOADER_FILENAME_PART3 EQU 020202036h ; "6___"\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 | |
c27b9ffe | 39 | ; BPB data below will be fixed by tool\r |
c69dd9df | 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 | PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored\r | |
53 | CurrentHead db 0 ; Current Head - 8 bits\r | |
54 | Signature db 0 ; Signature - 8 bits - ignored\r | |
55 | Id db " " ; Id - 4 bytes\r | |
56 | FatLabel db " " ; Label - 11 bytes\r | |
57 | SystemId db "FAT16 " ; SystemId - 8 bytes\r | |
58 | \r | |
59 | BootSectorEntryPoint:\r | |
60 | ASSUME ds:@code\r | |
61 | ASSUME ss:@code\r | |
62 | \r | |
63 | ; ****************************************************************************\r | |
64 | ; Start Print\r | |
65 | ; ****************************************************************************\r | |
66 | lea si, cs:[StartString]\r | |
67 | call PrintString\r | |
68 | \r | |
69 | ; ****************************************************************************\r | |
70 | ; Print over\r | |
71 | ; ****************************************************************************\r | |
72 | \r | |
73 | mov ax,cs ; ax = 0\r | |
74 | mov ss,ax ; ss = 0\r | |
75 | add ax,1000h\r | |
76 | mov ds,ax\r | |
77 | \r | |
78 | mov sp,07c00h ; sp = 0x7c00\r | |
79 | mov bp,sp ; bp = 0x7c00\r | |
80 | \r | |
81 | mov ah,8 ; ah = 8 - Get Drive Parameters Function\r | |
82 | mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL\r | |
83 | int 13h ; Get Drive Parameters\r | |
84 | xor ax,ax ; ax = 0\r | |
85 | mov al,dh ; al = dh\r | |
86 | inc al ; MaxHead = al + 1\r | |
87 | push ax ; 0000:7bfe = MaxHead\r | |
88 | mov al,cl ; al = cl\r | |
89 | and al,03fh ; MaxSector = al & 0x3f\r | |
90 | push ax ; 0000:7bfc = MaxSector\r | |
91 | \r | |
92 | cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature\r | |
93 | jne BadBootSector\r | |
94 | mov cx,word ptr [bp+RootEntries] ; cx = RootEntries\r | |
95 | shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes\r | |
96 | mov bx,cx ; bx = size of the Root Directory in bytes\r | |
97 | and bx,BLOCK_MASK ; See if it is an even number of sectors long\r | |
98 | jne BadBootSector ; If is isn't, then the boot sector is bad.\r | |
99 | mov bx,cx ; bx = size of the Root Directory in bytes\r | |
100 | shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors\r | |
101 | mov al,byte ptr [bp+NoFats] ; al = NoFats\r | |
102 | xor ah,ah ; ah = 0 ==> ax = NoFats\r | |
103 | mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat\r | |
104 | add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA\r | |
105 | push ds\r | |
106 | pop es\r | |
107 | xor di,di ; Store directory in es:di = 1000:0000\r | |
108 | call ReadBlocks ; Read entire Root Directory\r | |
109 | add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)\r | |
110 | mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use\r | |
111 | \r | |
112 | ; dx - variable storage (initial value is 0)\r | |
113 | ; bx - loader (initial value is 0)\r | |
114 | xor dx, dx\r | |
115 | xor bx, bx\r | |
116 | \r | |
117 | FindEFILDR:\r | |
118 | cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"\r | |
119 | jne FindVARSTORE\r | |
120 | cmp dword ptr [di+4],LOADER_FILENAME_PART2\r | |
121 | jne FindVARSTORE\r | |
122 | cmp dword ptr [di+7],LOADER_FILENAME_PART3\r | |
123 | jne FindVARSTORE\r | |
124 | mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------\r | |
125 | test dx, dx\r | |
126 | je FindNext ; Efivar.bin is not loaded\r | |
127 | jmp FoundAll\r | |
128 | \r | |
129 | FindVARSTORE:\r | |
130 | ; if the file is not loader file, see if it's "EFIVAR BIN"\r | |
131 | cmp dword ptr [di], 056494645h ; Compare to "EFIV"\r | |
132 | jne FindNext\r | |
133 | cmp dword ptr [di+4], 020205241h ; Compare to "AR "\r | |
134 | jne FindNext\r | |
135 | cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"\r | |
136 | jne FindNext\r | |
137 | mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------\r | |
138 | add dx, 26\r | |
139 | test bx, bx\r | |
140 | je FindNext ; Efildr is not loaded\r | |
141 | jmp FoundAll\r | |
142 | \r | |
143 | FindNext:\r | |
144 | ; go to next find\r | |
145 | add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di\r | |
146 | sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx\r | |
147 | ; TODO: jump to FindVarStore if ...\r | |
148 | jne FindEFILDR\r | |
149 | jmp NotFoundAll\r | |
150 | \r | |
151 | FoundAll:\r | |
152 | FoundEFILDR:\r | |
153 | mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------\r | |
154 | mov ax,cs ; Destination = 2000:0000\r | |
155 | add ax,2000h\r | |
156 | mov es,ax\r | |
157 | xor di,di\r | |
158 | ReadFirstClusterOfEFILDR:\r | |
159 | mov ax,cx ; ax = StartCluster\r | |
160 | sub ax,2 ; ax = StartCluster - 2\r | |
161 | xor bh,bh \r | |
162 | mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster\r | |
163 | push dx\r | |
164 | mul bx\r | |
165 | pop dx ; ax = (StartCluster - 2) * SectorsPerCluster\r | |
166 | add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster\r | |
167 | xor bh,bh\r | |
168 | mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster\r | |
169 | push es\r | |
170 | call ReadBlocks\r | |
171 | pop ax\r | |
172 | JumpIntoFirstSectorOfEFILDR:\r | |
173 | mov word ptr [bp+JumpSegment],ax\r | |
174 | JumpFarInstruction:\r | |
175 | db 0eah\r | |
176 | JumpOffset:\r | |
177 | dw 0000h\r | |
178 | JumpSegment:\r | |
179 | dw 2000h\r | |
180 | \r | |
181 | \r | |
182 | PrintString:\r | |
183 | mov ax,0b800h\r | |
184 | mov es,ax\r | |
185 | mov ax, 07c0h\r | |
186 | mov ds, ax\r | |
187 | mov cx, 7\r | |
188 | mov di, 160\r | |
189 | rep movsw\r | |
190 | ret\r | |
191 | ; ****************************************************************************\r | |
192 | ; ReadBlocks - Reads a set of blocks from a block device\r | |
193 | ;\r | |
194 | ; AX = Start LBA\r | |
195 | ; BX = Number of Blocks to Read\r | |
196 | ; ES:DI = Buffer to store sectors read from disk\r | |
197 | ; ****************************************************************************\r | |
198 | \r | |
199 | ; cx = Blocks\r | |
200 | ; bx = NumberOfBlocks\r | |
201 | ; si = StartLBA\r | |
202 | \r | |
203 | ReadBlocks:\r | |
204 | pusha\r | |
205 | add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA\r | |
206 | add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA\r | |
207 | mov esi,eax ; esi = Start LBA\r | |
208 | mov cx,bx ; cx = Number of blocks to read\r | |
209 | ReadCylinderLoop:\r | |
210 | mov bp,07bfch ; bp = 0x7bfc\r | |
211 | mov eax,esi ; eax = Start LBA\r | |
212 | xor edx,edx ; edx = 0\r | |
213 | movzx ebx,word ptr [bp] ; bx = MaxSector\r | |
214 | div ebx ; ax = StartLBA / MaxSector\r | |
215 | inc dx ; dx = (StartLBA % MaxSector) + 1\r | |
216 | sub bx,dx ; bx = MaxSector - Sector\r | |
217 | inc bx ; bx = MaxSector - Sector + 1\r | |
218 | cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)\r | |
219 | jg LimitTransfer\r | |
220 | mov bx,cx ; bx = Blocks\r | |
221 | LimitTransfer:\r | |
222 | push cx\r | |
223 | mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector\r | |
224 | xor dx,dx ; dx = 0\r | |
225 | div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder \r | |
226 | ; dx = ax % (MaxHead + 1) = Head\r | |
227 | \r | |
228 | push bx ; Save number of blocks to transfer\r | |
229 | mov dh,dl ; dh = Head\r | |
230 | mov bp,07c00h ; bp = 0x7c00\r | |
231 | mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number\r | |
232 | mov ch,al ; ch = Cylinder\r | |
233 | mov al,bl ; al = Blocks\r | |
234 | mov ah,2 ; ah = Function 2\r | |
235 | mov bx,di ; es:bx = Buffer address\r | |
236 | int 013h\r | |
237 | jc DiskError\r | |
238 | pop bx\r | |
239 | pop cx\r | |
240 | movzx ebx,bx\r | |
241 | add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks\r | |
242 | sub cx,bx ; Blocks = Blocks - NumberOfBlocks\r | |
243 | mov ax,es\r | |
244 | shl bx,(BLOCK_SHIFT-4)\r | |
245 | add ax,bx\r | |
246 | mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE\r | |
247 | cmp cx,0\r | |
248 | jne ReadCylinderLoop\r | |
249 | popa\r | |
250 | ret\r | |
251 | \r | |
252 | ; ****************************************************************************\r | |
253 | ; ERROR Condition:\r | |
254 | ; ****************************************************************************\r | |
255 | NotFoundAll:\r | |
256 | ; if we found EFILDR, continue\r | |
257 | test bx,bx\r | |
258 | jne FoundEFILDR\r | |
259 | BadBootSector:\r | |
260 | DiskError:\r | |
261 | lea si, cs:[ErrorString]\r | |
262 | call PrintString\r | |
263 | Halt:\r | |
264 | jmp Halt\r | |
265 | \r | |
266 | StartString:\r | |
267 | db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch\r | |
268 | ErrorString:\r | |
269 | db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch\r | |
270 | \r | |
271 | ; ****************************************************************************\r | |
272 | ; LBA Offset for BootSector, need patched by tool for HD boot.\r | |
273 | ; ****************************************************************************\r | |
274 | \r | |
275 | org 01fah\r | |
276 | LBAOffsetForBootSector:\r | |
277 | dd 0h\r | |
278 | \r | |
279 | ; ****************************************************************************\r | |
280 | ; Sector Signature\r | |
281 | ; ****************************************************************************\r | |
282 | \r | |
283 | org 01feh\r | |
284 | SectorSignature:\r | |
285 | dw 0aa55h ; Boot Sector Signature\r | |
286 | \r | |
287 | end \r | |
288 | \r |