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