]>
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 | |
c0e741ef | 12 | ;* bootsect.asm\r |
13 | ;* \r | |
14 | ;* bootsect.asm is built as 16-bit binary file in 512 bytes and patched to disk/partition's \r | |
15 | ;* first section - boot sector. \r | |
16 | ;*\r | |
17 | ;* The startup sequence for DUET disk boot sector is:\r | |
18 | ;*\r | |
19 | ;* 1, LegacyBios check 0xAA55 signature at boot sectore offset 0x1FE to judget \r | |
20 | ;* whether disk/partition is bootable.\r | |
21 | ;* 2, LegacyBios will load boot sector to 0x7c00 in real mode, pass BPB data and\r | |
22 | ;* hand off control to 0x7c00 code.\r | |
23 | ;* 3, boot sector code simply parse FAT format in boot disk and find EfiLdr binary file \r | |
24 | ;* and EfiVar.bin if exists. For first boot, EfiVar.bin does not exist.\r | |
25 | ;* 4, boot sector load the first sector of EfiLdr binary which is start.com to\r | |
26 | ;* 0x2000:0x0000 address.\r | |
27 | ;* 5, boot sector handoff control to 0x2000:0x0000 for start.com binary.\r | |
c69dd9df | 28 | ;*\r |
29 | ;------------------------------------------------------------------------------\r | |
30 | \r | |
31 | .model small\r | |
32 | .stack\r | |
33 | .486p\r | |
34 | .code\r | |
35 | \r | |
36 | FAT_DIRECTORY_ENTRY_SIZE EQU 020h\r | |
37 | FAT_DIRECTORY_ENTRY_SHIFT EQU 5\r | |
38 | BLOCK_SIZE EQU 0200h\r | |
39 | BLOCK_MASK EQU 01ffh\r | |
40 | BLOCK_SHIFT EQU 9\r | |
41 | ; "EFILDR_____"\r | |
42 | LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"\r | |
43 | LOADER_FILENAME_PART2 EQU 020205244h ; "DR__"\r | |
44 | LOADER_FILENAME_PART3 EQU 020202020h ; "____"\r | |
45 | \r | |
46 | org 0h\r | |
47 | Ia32Jump:\r | |
48 | jmp BootSectorEntryPoint ; JMP inst - 3 bytes\r | |
49 | nop\r | |
50 | \r | |
51 | OemId db "INTEL " ; OemId - 8 bytes\r | |
52 | ; BPB data below will be fixed by tool\r | |
53 | SectorSize dw 0 ; Sector Size - 16 bits\r | |
54 | SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits\r | |
55 | ReservedSectors dw 0 ; Reserved Sectors - 16 bits\r | |
56 | NoFats db 0 ; Number of FATs - 8 bits\r | |
57 | RootEntries dw 0 ; Root Entries - 16 bits\r | |
58 | Sectors dw 0 ; Number of Sectors - 16 bits\r | |
59 | Media db 0 ; Media - 8 bits - ignored\r | |
60 | SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits\r | |
61 | SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored\r | |
62 | Heads dw 0 ; Heads - 16 bits - ignored\r | |
63 | HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored\r | |
64 | LargeSectors dd 0 ; Large Sectors - 32 bits \r | |
65 | PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored\r | |
66 | CurrentHead db 0 ; Current Head - 8 bits\r | |
67 | Signature db 0 ; Signature - 8 bits - ignored\r | |
68 | Id db " " ; Id - 4 bytes\r | |
69 | FatLabel db " " ; Label - 11 bytes\r | |
70 | SystemId db "FAT12 " ; SystemId - 8 bytes\r | |
71 | \r | |
72 | BootSectorEntryPoint:\r | |
73 | ASSUME ds:@code\r | |
74 | ASSUME ss:@code\r | |
75 | \r | |
76 | ; ****************************************************************************\r | |
77 | ; Start Print\r | |
78 | ; ****************************************************************************\r | |
79 | lea si, cs:[StartString]\r | |
80 | call PrintString\r | |
81 | \r | |
82 | ; ****************************************************************************\r | |
83 | ; Print over\r | |
84 | ; ****************************************************************************\r | |
85 | \r | |
86 | mov ax,cs ; ax = 0\r | |
87 | mov ss,ax ; ss = 0\r | |
88 | add ax,1000h\r | |
89 | mov ds,ax\r | |
90 | \r | |
91 | mov sp,07c00h ; sp = 0x7c00\r | |
92 | mov bp,sp ; bp = 0x7c00\r | |
93 | \r | |
94 | mov ah,8 ; ah = 8 - Get Drive Parameters Function\r | |
95 | mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL\r | |
96 | int 13h ; Get Drive Parameters\r | |
4d382070 | 97 | xor ax,ax ; ax = 0\r |
98 | mov al,dh ; al = dh (number of sides (0 based))\r | |
99 | inc al ; MaxHead = al + 1\r | |
100 | push ax ; 0000:7bfe = MaxHead\r | |
101 | mov al,cl ; al = cl (CL = sectors per track)\r | |
102 | and al,03fh ; MaxSector = al & 0x3f\r | |
103 | push ax ; 0000:7bfc = MaxSector\r | |
c69dd9df | 104 | \r |
105 | cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature\r | |
106 | jne BadBootSector\r | |
107 | mov cx,word ptr [bp+RootEntries] ; cx = RootEntries\r | |
108 | shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes\r | |
109 | mov bx,cx ; bx = size of the Root Directory in bytes\r | |
110 | and bx,BLOCK_MASK ; See if it is an even number of sectors long\r | |
111 | jne BadBootSector ; If is isn't, then the boot sector is bad.\r | |
112 | mov bx,cx ; bx = size of the Root Directory in bytes\r | |
113 | shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors\r | |
114 | mov al,byte ptr [bp+NoFats] ; al = NoFats\r | |
115 | xor ah,ah ; ah = 0 ==> ax = NoFats\r | |
116 | mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat\r | |
117 | add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA\r | |
118 | push ds\r | |
119 | pop es\r | |
120 | xor di,di ; Store directory in es:di = 1000:0000\r | |
121 | call ReadBlocks ; Read entire Root Directory\r | |
122 | add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)\r | |
123 | mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use\r | |
124 | \r | |
125 | ; dx - variable storage (initial value is 0)\r | |
126 | ; bx - loader (initial value is 0)\r | |
127 | xor dx, dx\r | |
128 | xor bx, bx\r | |
129 | \r | |
130 | FindEFILDR:\r | |
131 | cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"\r | |
132 | jne FindVARSTORE\r | |
133 | cmp dword ptr [di+4],LOADER_FILENAME_PART2\r | |
134 | jne FindVARSTORE\r | |
135 | cmp dword ptr [di+7],LOADER_FILENAME_PART3\r | |
136 | jne FindVARSTORE\r | |
137 | mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------\r | |
138 | test dx, dx\r | |
139 | je FindNext ; Efivar.bin is not loaded\r | |
140 | jmp FoundAll\r | |
141 | \r | |
142 | FindVARSTORE:\r | |
143 | ; if the file is not loader file, see if it's "EFIVAR BIN"\r | |
144 | cmp dword ptr [di], 056494645h ; Compare to "EFIV"\r | |
145 | jne FindNext\r | |
146 | cmp dword ptr [di+4], 020205241h ; Compare to "AR "\r | |
147 | jne FindNext\r | |
148 | cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"\r | |
149 | jne FindNext\r | |
150 | mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------\r | |
151 | add dx, 26\r | |
152 | test bx, bx\r | |
153 | je FindNext ; Efildr is not loaded\r | |
154 | jmp FoundAll\r | |
155 | \r | |
156 | FindNext:\r | |
157 | ; go to next find\r | |
158 | add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di\r | |
159 | sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx\r | |
160 | ; TODO: jump to FindVarStore if ...\r | |
161 | jne FindEFILDR\r | |
162 | jmp NotFoundAll\r | |
163 | \r | |
164 | FoundAll:\r | |
4d382070 | 165 | FoundEFILDR: ; 0x7cfe\r |
c69dd9df | 166 | mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------\r |
167 | mov ax,cs ; Destination = 2000:0000\r | |
168 | add ax,2000h\r | |
169 | mov es,ax\r | |
170 | xor di,di\r | |
171 | ReadFirstClusterOfEFILDR:\r | |
172 | mov ax,cx ; ax = StartCluster\r | |
173 | sub ax,2 ; ax = StartCluster - 2\r | |
174 | xor bh,bh \r | |
175 | mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster\r | |
176 | push dx\r | |
177 | mul bx\r | |
178 | pop dx ; ax = (StartCluster - 2) * SectorsPerCluster\r | |
179 | add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster\r | |
180 | xor bh,bh\r | |
181 | mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster\r | |
182 | push es\r | |
183 | call ReadBlocks\r | |
184 | pop ax\r | |
185 | JumpIntoFirstSectorOfEFILDR:\r | |
4d382070 | 186 | mov word ptr [bp+JumpSegment],ax ; 0x7d26\r |
187 | JumpFarInstruction: ; 0x7d2a\r | |
c69dd9df | 188 | db 0eah\r |
189 | JumpOffset:\r | |
190 | dw 0000h\r | |
191 | JumpSegment:\r | |
192 | dw 2000h\r | |
193 | \r | |
194 | \r | |
195 | PrintString:\r | |
196 | mov ax,0b800h\r | |
197 | mov es,ax\r | |
198 | mov ax, 07c0h\r | |
199 | mov ds, ax\r | |
200 | mov cx, 7\r | |
201 | mov di, 160\r | |
202 | rep movsw\r | |
203 | ret\r | |
204 | ; ****************************************************************************\r | |
205 | ; ReadBlocks - Reads a set of blocks from a block device\r | |
206 | ;\r | |
207 | ; AX = Start LBA\r | |
208 | ; BX = Number of Blocks to Read\r | |
209 | ; ES:DI = Buffer to store sectors read from disk\r | |
210 | ; ****************************************************************************\r | |
211 | \r | |
212 | ; cx = Blocks\r | |
213 | ; bx = NumberOfBlocks\r | |
214 | ; si = StartLBA\r | |
215 | \r | |
216 | ReadBlocks:\r | |
217 | pusha\r | |
218 | add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA\r | |
219 | add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA\r | |
220 | mov esi,eax ; esi = Start LBA\r | |
221 | mov cx,bx ; cx = Number of blocks to read\r | |
222 | ReadCylinderLoop:\r | |
223 | mov bp,07bfch ; bp = 0x7bfc\r | |
224 | mov eax,esi ; eax = Start LBA\r | |
225 | xor edx,edx ; edx = 0\r | |
226 | movzx ebx,word ptr [bp] ; bx = MaxSector\r | |
227 | div ebx ; ax = StartLBA / MaxSector\r | |
228 | inc dx ; dx = (StartLBA % MaxSector) + 1\r | |
229 | sub bx,dx ; bx = MaxSector - Sector\r | |
230 | inc bx ; bx = MaxSector - Sector + 1\r | |
231 | cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)\r | |
232 | jg LimitTransfer\r | |
233 | mov bx,cx ; bx = Blocks\r | |
234 | LimitTransfer:\r | |
235 | push cx\r | |
236 | mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector\r | |
237 | xor dx,dx ; dx = 0\r | |
238 | div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder \r | |
239 | ; dx = ax % (MaxHead + 1) = Head\r | |
240 | \r | |
241 | push bx ; Save number of blocks to transfer\r | |
242 | mov dh,dl ; dh = Head\r | |
243 | mov bp,07c00h ; bp = 0x7c00\r | |
244 | mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number\r | |
245 | mov ch,al ; ch = Cylinder\r | |
246 | mov al,bl ; al = Blocks\r | |
247 | mov ah,2 ; ah = Function 2\r | |
248 | mov bx,di ; es:bx = Buffer address\r | |
249 | int 013h\r | |
250 | jc DiskError\r | |
251 | pop bx\r | |
252 | pop cx\r | |
253 | movzx ebx,bx\r | |
254 | add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks\r | |
255 | sub cx,bx ; Blocks = Blocks - NumberOfBlocks\r | |
256 | mov ax,es\r | |
257 | shl bx,(BLOCK_SHIFT-4)\r | |
258 | add ax,bx\r | |
259 | mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE\r | |
260 | cmp cx,0\r | |
261 | jne ReadCylinderLoop\r | |
262 | popa\r | |
263 | ret\r | |
264 | \r | |
265 | ; ****************************************************************************\r | |
266 | ; ERROR Condition:\r | |
267 | ; ****************************************************************************\r | |
4d382070 | 268 | NotFoundAll: ; 0x7da6\r |
c69dd9df | 269 | ; if we found EFILDR, continue\r |
270 | test bx,bx\r | |
271 | jne FoundEFILDR\r | |
272 | BadBootSector:\r | |
273 | DiskError:\r | |
274 | lea si, cs:[ErrorString]\r | |
275 | call PrintString\r | |
276 | Halt:\r | |
277 | jmp Halt\r | |
278 | \r | |
279 | StartString:\r | |
280 | db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch\r | |
281 | ErrorString:\r | |
282 | db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch\r | |
283 | \r | |
284 | ; ****************************************************************************\r | |
285 | ; LBA Offset for BootSector, need patched by tool for HD boot.\r | |
286 | ; ****************************************************************************\r | |
287 | \r | |
288 | org 01fah\r | |
289 | LBAOffsetForBootSector:\r | |
290 | dd 0h\r | |
291 | \r | |
292 | ; ****************************************************************************\r | |
293 | ; Sector Signature\r | |
294 | ; ****************************************************************************\r | |
295 | \r | |
296 | org 01feh\r | |
297 | SectorSignature:\r | |
298 | dw 0aa55h ; Boot Sector Signature\r | |
299 | \r | |
300 | end \r | |
301 | \r |