1 #------------------------------------------------------------------------------
3 #* Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>
4 #* 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, 0x020
24 .equ FAT_DIRECTORY_ENTRY_SHIFT, 5
25 .equ BLOCK_SIZE, 0x0200
26 .equ BLOCK_MASK, 0x01ff
29 .equ LOADER_FILENAME_PART1, 0x04c494645 # "EFIL"
30 .equ LOADER_FILENAME_PART2, 0x036315244 # "DR16"
31 .equ LOADER_FILENAME_PART3, 0x020202036 # "6___"
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
54 PhysicalDrive: .byte 0 # PhysicalDriveNumber - 8 bits - ignored
55 CurrentHead: .byte 0 # Current Head - 8 bits
56 Signature: .byte 0 # Signature - 8 bits - ignored
57 VolId: .ascii " " # Volume Serial Number- 4 bytes
58 FatLabel: .ascii " " # Label - 11 bytes
59 SystemId: .ascii "FAT12 " # SystemId - 8 bytes
65 # ****************************************************************************
67 # ****************************************************************************
68 movw $StartString, %si
71 # ****************************************************************************
73 # ****************************************************************************
75 movw %cs, %ax # ax = 0
76 movw %ax, %ss # ss = 0
80 movw $0x7c00, %sp # sp = 0x7c00
81 movw %sp, %bp # bp = 0x7c00
83 movb $8, %ah # ah = 8 - Get Drive Parameters Function
84 movb %dl, PhysicalDrive(%bp) # BBS defines that BIOS would pass the booting driver number to the loader through DL
85 int $0x13 # Get Drive Parameters
86 xorw %ax, %ax # ax = 0
87 movb %dh, %al # al = dh
88 incb %al # MaxHead = al + 1
89 pushw %ax # 0000:7bfe = MaxHead
90 movb %cl, %al # al = cl
91 andb $0x3f, %al # MaxSector = al & 0x3f
92 pushw %ax # 0000:7bfc = MaxSector
94 cmpw $0xaa55, SectorSignature(%bp) # Verify Boot Sector Signature
96 movw RootEntries(%bp), %cx # cx = RootEntries
97 shlw $FAT_DIRECTORY_ENTRY_SHIFT, %cx # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
98 movw %cx, %bx # bx = size of the Root Directory in bytes
99 andw $BLOCK_MASK, %bx # See if it is an even number of sectors long
100 jne BadBootSector # If is isn't, then the boot sector is bad.
101 movw %cx, %bx # bx = size of the Root Directory in bytes
102 shrw $BLOCK_SHIFT, %bx # bx = size of Root Directory in sectors
103 movb NoFats(%bp), %al # al = NoFats
104 xorb %ah, %ah # ah = 0 ==> ax = NoFats
105 mulw SectorsPerFat(%bp) # ax = NoFats * SectorsPerFat
106 addw ReservedSectors(%bp), %ax # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
109 xorw %di, %di # Store directory in es:di = 1000:0000
110 call ReadBlocks # Read entire Root Directory
111 addw %bx, %ax # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
112 movw %ax, (%bp) # Save FirstClusterLBA (FirstDataSector) for later use
114 # dx - variable storage (initial value is 0)
115 # bx - loader (initial value is 0)
120 cmpl $LOADER_FILENAME_PART1, (%di) # Compare to "EFIL"
122 cmpl $LOADER_FILENAME_PART2, 4(%di)
124 cmpl $LOADER_FILENAME_PART3, 7(%di)
126 movw 26(%di), %bx # bx = Start Cluster for EFILDR <----------------------------------
128 je FindNext # Efivar.bin is not loaded
132 ##if the file is not loader file, see if it's "EFIVAR BIN"
133 cmpl $0x56494645, (%di) # Compare to "EFIV"
135 cmpl $0x20205241, 4(%di) # Compare to "AR "
137 cmpl $0x4e494220, 7(%di) # Compare to " BIN"
139 movw %di, %dx # dx = Offset of Start Cluster for Efivar.bin <---------------------
142 je FindNext # Efildr is not loaded
147 addw $FAT_DIRECTORY_ENTRY_SIZE, %di # Increment di
148 subw $FAT_DIRECTORY_ENTRY_SIZE, %cx # Decrement cx
149 # TODO: jump to FindVarStore if ...
155 movw %bx, %cx # cx = Start Cluster for EFILDR <----------------------------------
156 movw %cs, %ax # Destination = 2000:0000
160 ReadFirstClusterOfEFILDR:
161 movw %cx, %ax # ax = StartCluster
162 subw $2, %ax # ax = StartCluster - 2
164 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
167 popw %dx # ax = (StartCluster - 2) * SectorsPerCluster
168 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
170 movb SectorsPerCluster(%bp), %bl # bx = Number of Sectors in a cluster
174 JumpIntoFirstSectorOfEFILDR:
175 movw %ax, JumpSegment(%bp)
194 # ****************************************************************************
195 # ReadBlocks - Reads a set of blocks from a block device
198 # BX = Number of Blocks to Read
199 # ES:DI = Buffer to store sectors read from disk
200 # ****************************************************************************
203 # bx = NumberOfBlocks
208 addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
209 addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
210 movl %eax, %esi # esi = Start LBA
211 movw %bx, %cx # cx = Number of blocks to read
213 movw $0x7bfc, %bp # bp = 0x7bfc
214 movl %esi, %eax # eax = Start LBA
215 xorl %edx, %edx # edx = 0
216 movzwl (%bp), %ebx # bx = MaxSector
217 divl %ebx # ax = StartLBA / MaxSector
218 incw %dx # dx = (StartLBA % MaxSector) + 1
219 subw %dx, %bx # bx = MaxSector - Sector
220 incw %bx # bx = MaxSector - Sector + 1
221 cmpw %bx, %cx # Compare (Blocks) to (MaxSector - Sector + 1)
223 movw %cx, %bx # bx = Blocks
226 movb %dl, %cl # cl = (StartLBA % MaxSector) + 1 = Sector
227 xorw %dx, %dx # dx = 0
228 divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
229 # dx = ax % (MaxHead + 1) = Head
231 pushw %bx # Save number of blocks to transfer
232 movb %dl, %dh # dh = Head
233 movw $0x7c00, %bp # bp = 0x7c00
234 movb PhysicalDrive(%bp), %dl # dl = Drive Number
235 movb %al, %ch # ch = Cylinder
236 movb %bl, %al # al = Blocks
237 movb $2, %ah # ah = Function 2
238 movw %di, %bx # es:bx = Buffer address
244 addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks
245 subw %bx, %cx # Blocks = Blocks - NumberOfBlocks
247 shlw $(BLOCK_SHIFT-4),%bx
249 movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
255 # ****************************************************************************
257 # ****************************************************************************
259 ## if we found EFILDR, continue
264 movw $ErrorString, %si
270 .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c
272 .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c
274 # ****************************************************************************
275 # LBA Offset for BootSector, need patched by tool for HD boot.
276 # ****************************************************************************
279 LBAOffsetForBootSector:
282 # ****************************************************************************
284 # ****************************************************************************
288 .word 0xaa55 # Boot Sector Signature