All UEFI applications in the MdeModukePkg should be placed in MdeModulePkg/Application
[edk2.git] / DuetPkg / BootSector / bs32.asm
blobbc84f83732bbb2d4e5815a8a6288440387fb26f2
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 ;* bs32.asm
13 ;*
14 ;* Abstract:
16 ;------------------------------------------------------------------------------
18 .model small
19 .stack
20 .486p
21 .code
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 030325244h ; "DR20"
31 LOADER_FILENAME_PART3 EQU 020202030h ; "0___"
33 org 0h
34 Ia32Jump:
35 jmp BootSectorEntryPoint ; JMP inst - 3 bytes
36 nop
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
53 ;******************************************************************************
55 ;The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
56 ;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
58 ;******************************************************************************
60 SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes
61 ExtFlags dw 0 ; Mirror Flag - 2 bytes
62 FSVersion dw 0 ; File System Version - 2 bytes
63 RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes
64 FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes
65 BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes
66 Reserved db 12 dup(0) ; Reserved Field - 12 bytes
67 PhysicalDrive db 0 ; Physical Drive Number - 1 byte
68 Reserved1 db 0 ; Reserved Field - 1 byte
69 Signature db 0 ; Extended Boot Signature - 1 byte
70 VolId db " " ; Volume Serial Number - 4 bytes
71 FatLabel db " " ; Volume Label - 11 bytes
72 FileSystemType db "FAT32 " ; File System Type - 8 bytes
74 BootSectorEntryPoint:
75 ASSUME ds:@code
76 ASSUME ss:@code
78 ; ****************************************************************************
79 ; Start Print
80 ; ****************************************************************************
81 lea si, cs:[StartString]
82 call PrintString
84 ; ****************************************************************************
85 ; Print over
86 ; ****************************************************************************
88 mov ax,cs ; ax = 0
89 mov ss,ax ; ss = 0
90 add ax,1000h
91 mov ds,ax
93 mov sp,07c00h ; sp = 0x7c00
94 mov bp,sp ; bp = 0x7c00
96 mov ah,8 ; ah = 8 - Get Drive Parameters Function
97 mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
98 int 13h ; Get Drive Parameters
99 xor ax,ax ; ax = 0
100 mov al,dh ; al = dh
101 inc al ; MaxHead = al + 1
102 push ax ; 0000:7bfe = MaxHead
103 mov al,cl ; al = cl
104 and al,03fh ; MaxSector = al & 0x3f
105 push ax ; 0000:7bfc = MaxSector
107 cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
108 jne BadBootSector
109 mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
110 shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
111 mov bx,cx ; bx = size of the Root Directory in bytes
112 and bx,BLOCK_MASK ; See if it is an even number of sectors long
113 jne BadBootSector ; If is isn't, then the boot sector is bad.
114 mov bx,cx ; bx = size of the Root Directory in bytes
115 shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
116 mov al,byte ptr [bp+NoFats] ; al = NoFats
117 xor ah,ah ; ah = 0 ==> ax = NoFats
118 mul word ptr [bp+SectorsPerFat32] ; ax = NoFats * SectorsPerFat
119 add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
120 add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA
121 mov word ptr [bp],ax ; Save FirstClusterLBA for later use
123 mov ax,word ptr [bp+RootCluster] ; ax = StartCluster of Root Directory
124 sub ax,2 ; ax = StartCluster - 2
125 xor bh,bh
126 mov bl,byte ptr [bp+SectorsPerCluster]; bx = SectorsPerCluster
127 mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
128 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
129 push ds
130 pop es
131 xor di,di ; Store directory in es:di = 1000:0000
132 call ReadBlocks ; Read StartCluster of Root Directory
134 ; dx - variable storage (initial value is 0)
135 ; bx - loader (initial value is 0)
136 xor dx, dx
137 xor bx, bx
139 FindEFILDR:
140 cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
141 jne FindVARSTORE
142 cmp dword ptr [di+4],LOADER_FILENAME_PART2
143 jne FindVARSTORE
144 cmp dword ptr [di+7],LOADER_FILENAME_PART3
145 jne FindVARSTORE
146 mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
147 test dx, dx
148 je FindNext ; Efivar.bin is not loaded
149 jmp FoundAll
151 FindVARSTORE:
152 ; if the file is not loader file, see if it's "EFIVAR BIN"
153 cmp dword ptr [di], 056494645h ; Compare to "EFIV"
154 jne FindNext
155 cmp dword ptr [di+4], 020205241h ; Compare to "AR "
156 jne FindNext
157 cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
158 jne FindNext
159 mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
160 add dx, 26
161 test bx, bx
162 je FindNext ; Efildr is not loaded
163 jmp FoundAll
165 FindNext:
166 ; go to next find
167 add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
168 sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
169 ; TODO: jump to FindVarStore if ...
170 jne FindEFILDR
171 jmp NotFoundAll
173 FoundAll:
174 FoundEFILDR:
175 mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
176 mov ax,cs ; Destination = 2000:0000
177 add ax,2000h
178 mov es,ax
179 xor di,di
180 ReadFirstClusterOfEFILDR:
181 mov ax,cx ; ax = StartCluster
182 sub ax,2 ; ax = StartCluster - 2
183 xor bh,bh
184 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
185 push dx
186 mul bx
187 pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
188 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
189 xor bh,bh
190 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
191 push es
192 call ReadBlocks
193 pop ax
194 JumpIntoFirstSectorOfEFILDR:
195 mov word ptr [bp+JumpSegment],ax
196 JumpFarInstruction:
197 db 0eah
198 JumpOffset:
199 dw 0000h
200 JumpSegment:
201 dw 2000h
204 PrintString:
205 mov ax,0b800h
206 mov es,ax
207 mov ax, 07c0h
208 mov ds, ax
209 mov cx, 7
210 mov di, 160
211 rep movsw
213 ; ****************************************************************************
214 ; ReadBlocks - Reads a set of blocks from a block device
216 ; AX = Start LBA
217 ; BX = Number of Blocks to Read
218 ; ES:DI = Buffer to store sectors read from disk
219 ; ****************************************************************************
221 ; cx = Blocks
222 ; bx = NumberOfBlocks
223 ; si = StartLBA
225 ReadBlocks:
226 pusha
227 add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
228 add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
229 mov esi,eax ; esi = Start LBA
230 mov cx,bx ; cx = Number of blocks to read
231 ReadCylinderLoop:
232 mov bp,07bfch ; bp = 0x7bfc
233 mov eax,esi ; eax = Start LBA
234 xor edx,edx ; edx = 0
235 movzx ebx,word ptr [bp] ; bx = MaxSector
236 div ebx ; ax = StartLBA / MaxSector
237 inc dx ; dx = (StartLBA % MaxSector) + 1
238 sub bx,dx ; bx = MaxSector - Sector
239 inc bx ; bx = MaxSector - Sector + 1
240 cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
241 jg LimitTransfer
242 mov bx,cx ; bx = Blocks
243 LimitTransfer:
244 push cx
245 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
246 xor dx,dx ; dx = 0
247 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
248 ; dx = ax % (MaxHead + 1) = Head
250 push bx ; Save number of blocks to transfer
251 mov dh,dl ; dh = Head
252 mov bp,07c00h ; bp = 0x7c00
253 mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
254 mov ch,al ; ch = Cylinder
255 mov al,bl ; al = Blocks
256 mov ah,2 ; ah = Function 2
257 mov bx,di ; es:bx = Buffer address
258 int 013h
259 jc DiskError
260 pop bx
261 pop cx
262 movzx ebx,bx
263 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
264 sub cx,bx ; Blocks = Blocks - NumberOfBlocks
265 mov ax,es
266 shl bx,(BLOCK_SHIFT-4)
267 add ax,bx
268 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
269 cmp cx,0
270 jne ReadCylinderLoop
271 popa
274 ; ****************************************************************************
275 ; ERROR Condition:
276 ; ****************************************************************************
277 NotFoundAll:
278 ; if we found EFILDR, continue
279 test bx,bx
280 jne FoundEFILDR
281 BadBootSector:
282 DiskError:
283 lea si, cs:[ErrorString]
284 call PrintString
285 Halt:
286 jmp Halt
288 StartString:
289 db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
290 ErrorString:
291 db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
293 ; ****************************************************************************
294 ; LBA Offset for BootSector, need patched by tool for HD boot.
295 ; ****************************************************************************
297 org 01fah
298 LBAOffsetForBootSector:
299 dd 0h
301 ; ****************************************************************************
302 ; Sector Signature
303 ; ****************************************************************************
305 org 01feh
306 SectorSignature:
307 dw 0aa55h ; Boot Sector Signature
309 end