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