1 #------------------------------------------------------------------------------
\r
3 #* Copyright 2006 - 2007, Intel Corporation
\r
4 #* All rights reserved. This program and the accompanying materials
\r
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
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
16 #------------------------------------------------------------------------------
\r
24 .equ FAT_DIRECTORY_ENTRY_SIZE, 0x0020
\r
25 .equ FAT_DIRECTORY_ENTRY_SHIFT, 5
\r
26 .equ BLOCK_SIZE, 0x0200
\r
27 .equ BLOCK_MASK, 0x01ff
\r
30 .equ LOADER_FILENAME_PART1, 0x4c494645 # "EFIL"
\r
31 .equ LOADER_FILENAME_PART2, 0x30325244 # "DR20"
\r
32 .equ LOADER_FILENAME_PART3, 0x20202030 # "0___"
\r
38 jmp BootSectorEntryPoint # JMP inst - 3 bytes
\r
41 OemId: .ascii "INTEL " # OemId - 8 bytes
\r
42 # BPB data below will be fixed by tool
\r
43 SectorSize: .word 0 # Sector Size - 16 bits
\r
44 SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits
\r
45 ReservedSectors: .word 0 # Reserved Sectors - 16 bits
\r
46 NoFats: .byte 0 # Number of FATs - 8 bits
\r
47 RootEntries: .word 0 # Root Entries - 16 bits
\r
48 Sectors: .word 0 # Number of Sectors - 16 bits
\r
49 Media: .byte 0 # Media - 8 bits - ignored
\r
50 SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits
\r
51 SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored
\r
52 Heads: .word 0 # Heads - 16 bits - ignored
\r
53 HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored
\r
54 LargeSectors: .long 0 # Large Sectors - 32 bits
\r
56 #******************************************************************************
\r
58 #The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
\r
59 #the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
\r
61 #******************************************************************************
\r
63 SectorsPerFat32: .long 0 # Sectors Per FAT for FAT32 - 4 bytes
\r
64 ExtFlags: .word 0 # Mirror Flag - 2 bytes
\r
65 FSVersion: .word 0 # File System Version - 2 bytes
\r
66 RootCluster: .long 0 # 1st Cluster Number of Root Dir - 4 bytes
\r
67 FSInfo: .word 0 # Sector Number of FSINFO - 2 bytes
\r
68 BkBootSector: .word 0 # Sector Number of Bk BootSector - 2 bytes
\r
69 Reserved: .fill 12, 1, 0 # Reserved Field - 12 bytes
\r
70 PhysicalDrive: .byte 0 # Physical Drive Number - 1 byte
\r
71 Reserved1: .byte 0 # Reserved Field - 1 byte
\r
72 Signature: .byte 0 # Extended Boot Signature - 1 byte
\r
73 VolId: .ascii " " # Volume Serial Number - 4 bytes
\r
74 FatLabel: .ascii " " # Volume Label - 11 bytes
\r
75 FileSystemType: .ascii "FAT32 " # File System Type - 8 bytes
\r
76 BootSectorEntryPoint:
\r
80 # ****************************************************************************
\r
82 # ****************************************************************************
\r
83 leaw %cs:StartString, %si
\r
86 # ****************************************************************************
\r
88 # ****************************************************************************
\r
90 movw %cs, %ax # ax = 0
\r
91 movw %ax, %ss # ss = 0
\r
95 movw $0x7c00, %sp # sp = 0x7c00
\r
96 movw %sp, %bp # bp = 0x7c00
\r
98 movb $8, %ah # ah = 8 - Get Drive Parameters Function
\r
99 movb %dl, PhysicalDrive(%bp) # BBS defines that BIOS would pass the booting driver number to the loader through DL
\r
100 int $0x13 # Get Drive Parameters
\r
101 xorw %ax, %ax # ax = 0
\r
102 movb %dh, %al # al = dh
\r
103 incb %al # MaxHead = al + 1
\r
104 pushw %ax # 0000:7bfe = MaxHead
\r
105 movb %cl, %al # al = cl
\r
106 andb $0x3f, %al # MaxSector = al & 0x3f
\r
107 pushw %ax # 0000:7bfc = MaxSector
\r
109 cmpw $0xaa55, SectorSignature(%bp) # Verify Boot Sector Signature
\r
111 movw RootEntries(%bp), %cx # cx = RootEntries
\r
112 shlw $FAT_DIRECTORY_ENTRY_SHIFT, %cx # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
\r
113 movw %cx, %bx # bx = size of the Root Directory in bytes
\r
114 andw $BLOCK_MASK, %bx # See if it is an even number of sectors long
\r
115 jne BadBootSector # If is isn't, then the boot sector is bad.
\r
116 movw %cx, %bx # bx = size of the Root Directory in bytes
\r
117 shrw $BLOCK_SHIFT, %bx # bx = size of Root Directory in sectors
\r
118 movb NoFats(%bp), %al # al = NoFats
\r
119 xorb %ah, %ah # ah = 0 ==> ax = NoFats
\r
120 mulw SectorsPerFat32(%bp) # ax = NoFats * SectorsPerFat
\r
121 addw ReservedSectors(%bp), %ax # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
\r
122 addw %bx, %ax # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA
\r
123 movw %ax, (%bp) # Save FirstClusterLBA for later use
\r
125 movw RootCluster(%bp), %ax # ax = StartCluster of Root Directory
\r
126 subw $2, %ax # ax = StartCluster - 2
\r
128 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
\r
129 mulw %bx # ax = (StartCluster - 2) * SectorsPerCluster
\r
130 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
\r
133 xorw %di, %di # Store directory in es:di = 1000:0000
\r
134 call ReadBlocks # Read StartCluster of Root Directory
\r
136 # dx - variable storage (initial value is 0)
\r
137 # bx - loader (initial value is 0)
\r
142 cmpl $LOADER_FILENAME_PART1, (%di)
\r
144 cmpl $LOADER_FILENAME_PART2, 4(%di)
\r
146 cmpl $LOADER_FILENAME_PART3, 7(%di)
\r
148 movw 26(%di), %bx # bx = Start Cluster for EFILDR <----------------------------------
\r
150 je FindNext # Efivar.bin is not loaded
\r
154 ## if the file is not loader file, see if it's "EFIVAR BIN"
\r
155 cmpl $0x56494645, (%di) # Compare to "EFIV"
\r
157 cmpl $0x20205241, 4(%di) # Compare to "AR "
\r
159 cmpl $0x4e494220, 7(%di) # Compare to " BIN"
\r
161 movw %di, %dx # dx = Offset of Start Cluster for Efivar.bin <---------------------
\r
164 je FindNext # Efildr is not loaded
\r
169 addw $FAT_DIRECTORY_ENTRY_SIZE, %di # Increment di
\r
170 subw $FAT_DIRECTORY_ENTRY_SIZE, %cx # Decrement cx
\r
171 # TODO: jump to FindVarStore if ...
\r
177 movw %bx, %cx # cx = Start Cluster for EFILDR <----------------------------------
\r
178 movw %cs, %ax # Destination = 2000:0000
\r
182 ReadFirstClusterOfEFILDR:
\r
183 movw %cx, %ax # ax = StartCluster
\r
184 subw $2, %ax # ax = StartCluster - 2
\r
186 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
\r
189 popw %dx # ax = (StartCluster - 2) * SectorsPerCluster
\r
190 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
\r
192 movb SectorsPerCluster(%bp), %bl # bx = Number of Sectors in a cluster
\r
196 JumpIntoFirstSectorOfEFILDR:
\r
197 movw %ax, JumpSegment(%bp)
\r
198 JumpFarInstruction:
\r
216 # ****************************************************************************
\r
217 # ReadBlocks - Reads a set of blocks from a block device
\r
220 # BX = Number of Blocks to Read
\r
221 # ES:DI = Buffer to store sectors read from disk
\r
222 # ****************************************************************************
\r
225 # bx = NumberOfBlocks
\r
230 addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
\r
231 addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
\r
232 movl %eax, %esi # esi = Start LBA
\r
233 movw %bx, %cx # cx = Number of blocks to read
\r
235 movw $0x7bfc, %bp # bp = 0x7bfc
\r
236 movl %esi, %eax # eax = Start LBA
\r
237 xorl %edx, %edx # edx = 0
\r
238 movzwl (%bp), %ebx # bx = MaxSector
\r
239 divl %ebx # ax = StartLBA / MaxSector
\r
240 incw %dx # dx = (StartLBA % MaxSector) + 1
\r
241 subw %dx, %bx # bx = MaxSector - Sector
\r
242 incw %bx # bx = MaxSector - Sector + 1
\r
243 cmpw %bx, %cx # Compare (Blocks) to (MaxSector - Sector + 1)
\r
245 movw %cx, %bx # bx = Blocks
\r
248 movb %dl, %cl # cl = (StartLBA % MaxSector) + 1 = Sector
\r
249 xorw %dx, %dx # dx = 0
\r
250 divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
\r
251 # dx = ax % (MaxHead + 1) = Head
\r
253 pushw %bx # Save number of blocks to transfer
\r
254 movb %dl, %dh # dh = Head
\r
255 movw $0x7c00, %bp # bp = 0x7c00
\r
256 movb PhysicalDrive(%bp), %dl # dl = Drive Number
\r
257 movb %al, %ch # ch = Cylinder
\r
258 movb %bl, %al # al = Blocks
\r
259 movb $2, %ah # ah = Function 2
\r
260 movw %di, %bx # es:bx = Buffer address
\r
266 addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks
\r
267 subw %bx, %cx # Blocks = Blocks - NumberOfBlocks
\r
269 shlw $(BLOCK_SHIFT-4), %bx
\r
271 movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
\r
273 jne ReadCylinderLoop
\r
277 # ****************************************************************************
\r
279 # ****************************************************************************
\r
281 ## if we found EFILDR, continue
\r
286 leaw %cs:ErrorString, %si
\r
292 .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c
\r
294 .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c
\r
296 # ****************************************************************************
\r
297 # LBA Offset for BootSector, need patched by tool for HD boot.
\r
298 # ****************************************************************************
\r
300 # .org 0x01fa # BUG_BUG
\r
301 LBAOffsetForBootSector:
\r
304 # ****************************************************************************
\r
306 # ****************************************************************************
\r
308 # .org 0x01fe # BUG_BUG
\r
310 .word 0xaa55 # Boot Sector Signature
\r