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___"
37 jmp BootSectorEntryPoint # JMP inst - 3 bytes
40 OemId: .ascii "INTEL " # OemId - 8 bytes
41 # BPB data below will be fixed by tool
42 SectorSize: .word 0 # Sector Size - 16 bits
43 SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits
44 ReservedSectors: .word 0 # Reserved Sectors - 16 bits
45 NoFats: .byte 0 # Number of FATs - 8 bits
46 RootEntries: .word 0 # Root Entries - 16 bits
47 Sectors: .word 0 # Number of Sectors - 16 bits
48 Media: .byte 0 # Media - 8 bits - ignored
49 SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits
50 SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored
51 Heads: .word 0 # Heads - 16 bits - ignored
52 HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored
53 LargeSectors: .long 0 # Large Sectors - 32 bits
55 #******************************************************************************
57 #The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
58 #the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
60 #******************************************************************************
62 SectorsPerFat32: .long 0 # Sectors Per FAT for FAT32 - 4 bytes
63 ExtFlags: .word 0 # Mirror Flag - 2 bytes
64 FSVersion: .word 0 # File System Version - 2 bytes
65 RootCluster: .long 0 # 1st Cluster Number of Root Dir - 4 bytes
66 FSInfo: .word 0 # Sector Number of FSINFO - 2 bytes
67 BkBootSector: .word 0 # Sector Number of Bk BootSector - 2 bytes
68 Reserved: .fill 12, 1, 0 # Reserved Field - 12 bytes
69 PhysicalDrive: .byte 0 # Physical Drive Number - 1 byte
70 Reserved1: .byte 0 # Reserved Field - 1 byte
71 Signature: .byte 0 # Extended Boot Signature - 1 byte
72 VolId: .ascii " " # Volume Serial Number - 4 bytes
73 FatLabel: .ascii " " # Volume Label - 11 bytes
74 FileSystemType: .ascii "FAT32 " # File System Type - 8 bytes
79 # ****************************************************************************
81 # ****************************************************************************
82 movw $StartString, %si
85 # ****************************************************************************
87 # ****************************************************************************
89 movw %cs, %ax # ax = 0
90 movw %ax, %ss # ss = 0
94 movw $0x7c00, %sp # sp = 0x7c00
95 movw %sp, %bp # bp = 0x7c00
97 movb $8, %ah # ah = 8 - Get Drive Parameters Function
98 movb %dl, PhysicalDrive(%bp) # BBS defines that BIOS would pass the booting driver number to the loader through DL
99 int $0x13 # Get Drive Parameters
100 xorw %ax, %ax # ax = 0
101 movb %dh, %al # al = dh
102 incb %al # MaxHead = al + 1
103 pushw %ax # 0000:7bfe = MaxHead
104 movb %cl, %al # al = cl
105 andb $0x3f, %al # MaxSector = al & 0x3f
106 pushw %ax # 0000:7bfc = MaxSector
108 cmpw $0xaa55, SectorSignature(%bp) # Verify Boot Sector Signature
110 movw RootEntries(%bp), %cx # cx = RootEntries
111 shlw $FAT_DIRECTORY_ENTRY_SHIFT, %cx # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
112 movw %cx, %bx # bx = size of the Root Directory in bytes
113 andw $BLOCK_MASK, %bx # See if it is an even number of sectors long
114 jne BadBootSector # If is isn't, then the boot sector is bad.
115 movw %cx, %bx # bx = size of the Root Directory in bytes
116 shrw $BLOCK_SHIFT, %bx # bx = size of Root Directory in sectors
117 movb NoFats(%bp), %al # al = NoFats
118 xorb %ah, %ah # ah = 0 ==> ax = NoFats
119 mulw SectorsPerFat32(%bp) # ax = NoFats * SectorsPerFat
120 addw ReservedSectors(%bp), %ax # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
121 addw %bx, %ax # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA
122 movw %ax, (%bp) # Save FirstClusterLBA for later use
124 movw RootCluster(%bp), %ax # ax = StartCluster of Root Directory
125 subw $2, %ax # ax = StartCluster - 2
127 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
128 mulw %bx # ax = (StartCluster - 2) * SectorsPerCluster
129 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
132 xorw %di, %di # Store directory in es:di = 1000:0000
133 call ReadBlocks # Read StartCluster of Root Directory
135 # dx - variable storage (initial value is 0)
136 # bx - loader (initial value is 0)
141 cmpl $LOADER_FILENAME_PART1, (%di)
143 cmpl $LOADER_FILENAME_PART2, 4(%di)
145 cmpl $LOADER_FILENAME_PART3, 7(%di)
147 movw 26(%di), %bx # bx = Start Cluster for EFILDR <----------------------------------
149 je FindNext # Efivar.bin is not loaded
153 ## if the file is not loader file, see if it's "EFIVAR BIN"
154 cmpl $0x56494645, (%di) # Compare to "EFIV"
156 cmpl $0x20205241, 4(%di) # Compare to "AR "
158 cmpl $0x4e494220, 7(%di) # Compare to " BIN"
160 movw %di, %dx # dx = Offset of Start Cluster for Efivar.bin <---------------------
163 je FindNext # Efildr is not loaded
168 addw $FAT_DIRECTORY_ENTRY_SIZE, %di # Increment di
169 subw $FAT_DIRECTORY_ENTRY_SIZE, %cx # Decrement cx
170 # TODO: jump to FindVarStore if ...
176 movw %bx, %cx # cx = Start Cluster for EFILDR <----------------------------------
177 movw %cs, %ax # Destination = 2000:0000
181 ReadFirstClusterOfEFILDR:
182 movw %cx, %ax # ax = StartCluster
183 subw $2, %ax # ax = StartCluster - 2
185 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
188 popw %dx # ax = (StartCluster - 2) * SectorsPerCluster
189 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
191 movb SectorsPerCluster(%bp), %bl # bx = Number of Sectors in a cluster
195 JumpIntoFirstSectorOfEFILDR:
196 movw %ax, JumpSegment(%bp)
215 # ****************************************************************************
216 # ReadBlocks - Reads a set of blocks from a block device
219 # BX = Number of Blocks to Read
220 # ES:DI = Buffer to store sectors read from disk
221 # ****************************************************************************
224 # bx = NumberOfBlocks
229 addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
230 addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
231 movl %eax, %esi # esi = Start LBA
232 movw %bx, %cx # cx = Number of blocks to read
234 movw $0x7bfc, %bp # bp = 0x7bfc
235 movl %esi, %eax # eax = Start LBA
236 xorl %edx, %edx # edx = 0
237 movzwl (%bp), %ebx # bx = MaxSector
238 divl %ebx # ax = StartLBA / MaxSector
239 incw %dx # dx = (StartLBA % MaxSector) + 1
240 subw %dx, %bx # bx = MaxSector - Sector
241 incw %bx # bx = MaxSector - Sector + 1
242 cmpw %bx, %cx # Compare (Blocks) to (MaxSector - Sector + 1)
244 movw %cx, %bx # bx = Blocks
247 movb %dl, %cl # cl = (StartLBA % MaxSector) + 1 = Sector
248 xorw %dx, %dx # dx = 0
249 divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
250 # dx = ax % (MaxHead + 1) = Head
252 pushw %bx # Save number of blocks to transfer
253 movb %dl, %dh # dh = Head
254 movw $0x7c00, %bp # bp = 0x7c00
255 movb PhysicalDrive(%bp), %dl # dl = Drive Number
256 movb %al, %ch # ch = Cylinder
257 movb %bl, %al # al = Blocks
258 movb $2, %ah # ah = Function 2
259 movw %di, %bx # es:bx = Buffer address
265 addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks
266 subw %bx, %cx # Blocks = Blocks - NumberOfBlocks
268 shlw $(BLOCK_SHIFT-4), %bx
270 movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
276 # ****************************************************************************
278 # ****************************************************************************
280 ## if we found EFILDR, continue
285 movw $ErrorString, %si
291 .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c
293 .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c
295 # ****************************************************************************
296 # LBA Offset for BootSector, need patched by tool for HD boot.
297 # ****************************************************************************
300 LBAOffsetForBootSector:
303 # ****************************************************************************
305 # ****************************************************************************
309 .word 0xaa55 # Boot Sector Signature