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 #------------------------------------------------------------------------------
23 .equ FAT_DIRECTORY_ENTRY_SIZE, 0x0020
24 .equ FAT_DIRECTORY_ENTRY_SHIFT, 5
25 .equ BLOCK_SIZE, 0x0200
26 .equ BLOCK_MASK, 0x01ff
29 .equ LOADER_FILENAME_PART1, 0x4c494645 # "EFIL"
30 .equ LOADER_FILENAME_PART2, 0x30325244 # "DR20"
31 .equ LOADER_FILENAME_PART3, 0x20202030 # "0___"
35 jmp BootSectorEntryPoint # JMP inst - 3 bytes
38 OemId: .ascii "INTEL " # OemId - 8 bytes
39 # BPB data below will be fixed by tool
40 SectorSize: .word 0 # Sector Size - 16 bits
41 SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits
42 ReservedSectors: .word 0 # Reserved Sectors - 16 bits
43 NoFats: .byte 0 # Number of FATs - 8 bits
44 RootEntries: .word 0 # Root Entries - 16 bits
45 Sectors: .word 0 # Number of Sectors - 16 bits
46 Media: .byte 0 # Media - 8 bits - ignored
47 SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits
48 SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored
49 Heads: .word 0 # Heads - 16 bits - ignored
50 HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored
51 LargeSectors: .long 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: .long 0 # Sectors Per FAT for FAT32 - 4 bytes
61 ExtFlags: .word 0 # Mirror Flag - 2 bytes
62 FSVersion: .word 0 # File System Version - 2 bytes
63 RootCluster: .long 0 # 1st Cluster Number of Root Dir - 4 bytes
64 FSInfo: .word 0 # Sector Number of FSINFO - 2 bytes
65 BkBootSector: .word 0 # Sector Number of Bk BootSector - 2 bytes
66 Reserved: .fill 12, 1, 0 # Reserved Field - 12 bytes
67 PhysicalDrive: .byte 0 # Physical Drive Number - 1 byte
68 Reserved1: .byte 0 # Reserved Field - 1 byte
69 Signature: .byte 0 # Extended Boot Signature - 1 byte
70 VolId: .ascii " " # Volume Serial Number - 4 bytes
71 FatLabel: .ascii " " # Volume Label - 11 bytes
72 FileSystemType: .ascii "FAT32 " # File System Type - 8 bytes
77 # ****************************************************************************
79 # ****************************************************************************
80 leaw %cs:StartString, %si
83 # ****************************************************************************
85 # ****************************************************************************
87 movw %cs, %ax # ax = 0
88 movw %ax, %ss # ss = 0
92 movw $0x7c00, %sp # sp = 0x7c00
93 movw %sp, %bp # bp = 0x7c00
95 movb $8, %ah # ah = 8 - Get Drive Parameters Function
96 movb %dl, PhysicalDrive(%bp) # BBS defines that BIOS would pass the booting driver number to the loader through DL
97 int $0x13 # Get Drive Parameters
98 xorw %ax, %ax # ax = 0
99 movb %dh, %al # al = dh
100 incb %al # MaxHead = al + 1
101 pushw %ax # 0000:7bfe = MaxHead
102 movb %cl, %al # al = cl
103 andb $0x3f, %al # MaxSector = al & 0x3f
104 pushw %ax # 0000:7bfc = MaxSector
106 cmpw $0xaa55, SectorSignature(%bp) # Verify Boot Sector Signature
108 movw RootEntries(%bp), %cx # cx = RootEntries
109 shlw $FAT_DIRECTORY_ENTRY_SHIFT, %cx # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
110 movw %cx, %bx # bx = size of the Root Directory in bytes
111 andw $BLOCK_MASK, %bx # See if it is an even number of sectors long
112 jne BadBootSector # If is isn't, then the boot sector is bad.
113 movw %cx, %bx # bx = size of the Root Directory in bytes
114 shrw $BLOCK_SHIFT, %bx # bx = size of Root Directory in sectors
115 movb NoFats(%bp), %al # al = NoFats
116 xorb %ah, %ah # ah = 0 ==> ax = NoFats
117 mulw SectorsPerFat32(%bp) # ax = NoFats * SectorsPerFat
118 addw ReservedSectors(%bp), %ax # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
119 addw %bx, %ax # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA
120 movw %ax, (%bp) # Save FirstClusterLBA for later use
122 movw RootCluster(%bp), %ax # ax = StartCluster of Root Directory
123 subw $2, %ax # ax = StartCluster - 2
125 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
126 mulw %bx # ax = (StartCluster - 2) * SectorsPerCluster
127 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
130 xorw %di, %di # Store directory in es:di = 1000:0000
131 call ReadBlocks # Read StartCluster of Root Directory
133 # dx - variable storage (initial value is 0)
134 # bx - loader (initial value is 0)
139 cmpl $LOADER_FILENAME_PART1, (%di)
141 cmpl $LOADER_FILENAME_PART2, 4(%di)
143 cmpl $LOADER_FILENAME_PART3, 7(%di)
145 movw 26(%di), %bx # bx = Start Cluster for EFILDR <----------------------------------
147 je FindNext # Efivar.bin is not loaded
151 # if the file is not loader file, see if it's "EFIVAR BIN"
152 cmpl $0x56494645, (%di) # Compare to "EFIV"
154 cmpl $0x20205241, 4(%di) # Compare to "AR "
156 cmpl $0x4e494220, 7(%di) # Compare to " BIN"
158 movw %di, %dx # dx = Offset of Start Cluster for Efivar.bin <---------------------
161 je FindNext # Efildr is not loaded
166 addw $FAT_DIRECTORY_ENTRY_SIZE, %di # Increment di
167 subw $FAT_DIRECTORY_ENTRY_SIZE, %cx # Decrement cx
168 # TODO: jump to FindVarStore if ...
174 movw %bx, %cx # cx = Start Cluster for EFILDR <----------------------------------
175 movw %cs, %ax # Destination = 2000:0000
179 ReadFirstClusterOfEFILDR:
180 movw %cx, %ax # ax = StartCluster
181 subw $2, %ax # ax = StartCluster - 2
183 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
186 popw %dx # ax = (StartCluster - 2) * SectorsPerCluster
187 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
189 movb SectorsPerCluster(%bp), %bl # bx = Number of Sectors in a cluster
193 JumpIntoFirstSectorOfEFILDR:
194 movw %ax, JumpSegment(%bp)
213 # ****************************************************************************
214 # ReadBlocks - Reads a set of blocks from a block device
217 # BX = Number of Blocks to Read
218 # ES:DI = Buffer to store sectors read from disk
219 # ****************************************************************************
222 # bx = NumberOfBlocks
227 addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
228 addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
229 movl %eax, %esi # esi = Start LBA
230 movw %bx, %cx # cx = Number of blocks to read
232 movw $0x7bfc, %bp # bp = 0x7bfc
233 movl %esi, %eax # eax = Start LBA
234 xorl %edx, %edx # edx = 0
235 movzwl (%bp), %ebx # bx = MaxSector
236 divl %ebx # ax = StartLBA / MaxSector
237 incw %dx # dx = (StartLBA % MaxSector) + 1
238 subw %dx, %bx # bx = MaxSector - Sector
239 incw %bx # bx = MaxSector - Sector + 1
240 cmpw %bx, %cx # Compare (Blocks) to (MaxSector - Sector + 1)
242 movw %cx, %bx # bx = Blocks
245 movb %dl, %cl # cl = (StartLBA % MaxSector) + 1 = Sector
246 xorw %dx, %dx # dx = 0
247 divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
248 # dx = ax % (MaxHead + 1) = Head
250 pushw %bx # Save number of blocks to transfer
251 movb %dl, %dh # dh = Head
252 movw $0x7c00, %bp # bp = 0x7c00
253 movb PhysicalDrive(%bp), %dl # dl = Drive Number
254 movb %al, %ch # ch = Cylinder
255 movb %bl, %al # al = Blocks
256 movb $2, %ah # ah = Function 2
257 movw %di, %bx # es:bx = Buffer address
263 addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks
264 subw %bx, %cx # Blocks = Blocks - NumberOfBlocks
266 shlw $(BLOCK_SHIFT-4), %bx
268 movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
274 # ****************************************************************************
276 # ****************************************************************************
278 # if we found EFILDR, continue
283 leaw %cs:ErrorString, %si
289 .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c
291 .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c
293 # ****************************************************************************
294 # LBA Offset for BootSector, need patched by tool for HD boot.
295 # ****************************************************************************
298 LBAOffsetForBootSector:
301 # ****************************************************************************
303 # ****************************************************************************
307 .word 0xaa55 # Boot Sector Signature