]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/BootSector/bootsect.asm
Update the copyright notice format
[mirror_edk2.git] / DuetPkg / BootSector / bootsect.asm
CommitLineData
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
36FAT_DIRECTORY_ENTRY_SIZE EQU 020h\r
37FAT_DIRECTORY_ENTRY_SHIFT EQU 5\r
38BLOCK_SIZE EQU 0200h\r
39BLOCK_MASK EQU 01ffh\r
40BLOCK_SHIFT EQU 9\r
41 ; "EFILDR_____"\r
42LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"\r
43LOADER_FILENAME_PART2 EQU 020205244h ; "DR__"\r
44LOADER_FILENAME_PART3 EQU 020202020h ; "____"\r
45\r
46 org 0h\r
47Ia32Jump:\r
48 jmp BootSectorEntryPoint ; JMP inst - 3 bytes\r
49 nop\r
50\r
51OemId db "INTEL " ; OemId - 8 bytes\r
52; BPB data below will be fixed by tool\r
53SectorSize dw 0 ; Sector Size - 16 bits\r
54SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits\r
55ReservedSectors dw 0 ; Reserved Sectors - 16 bits\r
56NoFats db 0 ; Number of FATs - 8 bits\r
57RootEntries dw 0 ; Root Entries - 16 bits\r
58Sectors dw 0 ; Number of Sectors - 16 bits\r
59Media db 0 ; Media - 8 bits - ignored\r
60SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits\r
61SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored\r
62Heads dw 0 ; Heads - 16 bits - ignored\r
63HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored\r
64LargeSectors dd 0 ; Large Sectors - 32 bits \r
65PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored\r
66CurrentHead db 0 ; Current Head - 8 bits\r
67Signature db 0 ; Signature - 8 bits - ignored\r
68Id db " " ; Id - 4 bytes\r
69FatLabel db " " ; Label - 11 bytes\r
70SystemId db "FAT12 " ; SystemId - 8 bytes\r
71\r
72BootSectorEntryPoint:\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
130FindEFILDR:\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
142FindVARSTORE:\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
156FindNext:\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
164FoundAll:\r
4d382070 165FoundEFILDR: ; 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
171ReadFirstClusterOfEFILDR:\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
185JumpIntoFirstSectorOfEFILDR:\r
4d382070 186 mov word ptr [bp+JumpSegment],ax ; 0x7d26\r
187JumpFarInstruction: ; 0x7d2a\r
c69dd9df 188 db 0eah\r
189JumpOffset:\r
190 dw 0000h\r
191JumpSegment:\r
192 dw 2000h\r
193\r
194\r
195PrintString:\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
216ReadBlocks:\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
222ReadCylinderLoop:\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
234LimitTransfer:\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 268NotFoundAll: ; 0x7da6\r
c69dd9df 269 ; if we found EFILDR, continue\r
270 test bx,bx\r
271 jne FoundEFILDR\r
272BadBootSector:\r
273DiskError:\r
274 lea si, cs:[ErrorString]\r
275 call PrintString\r
276Halt:\r
277 jmp Halt\r
278\r
279StartString:\r
280 db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch\r
281ErrorString:\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
289LBAOffsetForBootSector:\r
290 dd 0h\r
291\r
292; ****************************************************************************\r
293; Sector Signature\r
294; ****************************************************************************\r
295\r
296 org 01feh\r
297SectorSignature:\r
298 dw 0aa55h ; Boot Sector Signature\r
299\r
300 end \r
301 \r