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