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