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