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.
14 #* bootsect.S is built as 16-bit binary file in 512 bytes and patched to disk/partition's
15 #* first section - boot sector.
17 #* The startup sequence for DUET disk boot sector is:
19 #* 1, LegacyBios check 0xAA55 signature at boot sectore offset 0x1FE to judget
20 #* whether disk/partition is bootable.
21 #* 2, LegacyBios will load boot sector to 0x7c00 in real mode, pass BPB data and
22 #* hand off control to 0x7c00 code.
23 #* 3, boot sector code simply parse FAT format in boot disk and find EfiLdr binary file
24 #* and EfiVar.bin if exists. For first boot, EfiVar.bin does not exist.
25 #* 4, boot sector load the first sector of EfiLdr binary which is start.com to
26 #* 0x2000:0x0000 address.
27 #* 5, boot sector handoff control to 0x2000:0x0000 for start.com binary.
29 #------------------------------------------------------------------------------
35 .equ FAT_DIRECTORY_ENTRY_SIZE, 0x020
36 .equ FAT_DIRECTORY_ENTRY_SHIFT, 5
37 .equ BLOCK_SIZE, 0x0200
38 .equ BLOCK_MASK, 0x01ff
41 .equ LOADER_FILENAME_PART1, 0x04c494645 # "EFIL"
42 .equ LOADER_FILENAME_PART2, 0x020205244 # "DR__"
43 .equ LOADER_FILENAME_PART3, 0x020202020 # "____"
49 jmp BootSectorEntryPoint # JMP inst - 3 bytes
52 OemId: .ascii "INTEL " # OemId - 8 bytes
53 # BPB data below will be fixed by tool
54 SectorSize: .word 0 # Sector Size - 16 bits
55 SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits
56 ReservedSectors: .word 0 # Reserved Sectors - 16 bits
57 NoFats: .byte 0 # Number of FATs - 8 bits
58 RootEntries: .word 0 # Root Entries - 16 bits
59 Sectors: .word 0 # Number of Sectors - 16 bits
60 Media: .byte 0 # Media - 8 bits - ignored
61 SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits
62 SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored
63 Heads: .word 0 # Heads - 16 bits - ignored
64 HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored
65 LargeSectors: .long 0 # Large Sectors - 32 bits
66 PhysicalDrive: .byte 0 # PhysicalDriveNumber - 8 bits - ignored
67 CurrentHead: .byte 0 # Current Head - 8 bits
68 Signature: .byte 0 # Signature - 8 bits - ignored
69 VolId: .ascii " " # Volume Serial Number- 4 bytes
70 FatLabel: .ascii " " # Label - 11 bytes
71 SystemId: .ascii "FAT12 " # SystemId - 8 bytes
77 # ****************************************************************************
79 # ****************************************************************************
80 movw $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 SectorsPerFat(%bp) # ax = NoFats * SectorsPerFat
118 addw ReservedSectors(%bp), %ax # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
121 xorw %di, %di # Store directory in es:di = 1000:0000
122 call ReadBlocks # Read entire Root Directory
123 addw %bx, %ax # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
124 movw %ax, (%bp) # Save FirstClusterLBA (FirstDataSector) for later use
126 # dx - variable storage (initial value is 0)
127 # bx - loader (initial value is 0)
132 cmpl $LOADER_FILENAME_PART1, (%di) # Compare to "EFIL"
134 cmpl $LOADER_FILENAME_PART2, 4(%di)
136 cmpl $LOADER_FILENAME_PART3, 7(%di)
138 movw 26(%di), %bx # bx = Start Cluster for EFILDR <----------------------------------
140 je FindNext # Efivar.bin is not loaded
144 ## if the file is not loader file, see if it's "EFIVAR BIN"
145 cmpl $0x56494645, (%di) # Compare to "EFIV"
147 cmpl $0x20205241, 4(%di) # Compare to "AR "
149 cmpl $0x4e494220, 7(%di) # Compare to " BIN"
151 movw %di, %dx # dx = Offset of Start Cluster for Efivar.bin <---------------------
154 je FindNext # Efildr is not loaded
159 addw $FAT_DIRECTORY_ENTRY_SIZE, %di # Increment di
160 subw $FAT_DIRECTORY_ENTRY_SIZE, %cx # Decrement cx
161 # TODO: jump to FindVarStore if ...
167 movw %bx, %cx # cx = Start Cluster for EFILDR <----------------------------------
168 movw %cs, %ax # Destination = 2000:0000
172 ReadFirstClusterOfEFILDR:
173 movw %cx, %ax # ax = StartCluster
174 subw $2, %ax # ax = StartCluster - 2
176 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
179 popw %dx # ax = (StartCluster - 2) * SectorsPerCluster
180 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
182 movb SectorsPerCluster(%bp), %bl # bx = Number of Sectors in a cluster
186 JumpIntoFirstSectorOfEFILDR:
187 movw %ax, JumpSegment(%bp)
206 # ****************************************************************************
207 # ReadBlocks - Reads a set of blocks from a block device
210 # BX = Number of Blocks to Read
211 # ES:DI = Buffer to store sectors read from disk
212 # ****************************************************************************
215 # bx = NumberOfBlocks
220 addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
221 addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
222 movl %eax, %esi # esi = Start LBA
223 movw %bx, %cx # cx = Number of blocks to read
225 movw $0x7bfc, %bp # bp = 0x7bfc
226 movl %esi, %eax # eax = Start LBA
227 xorl %edx, %edx # edx = 0
228 movzwl (%bp), %ebx # bx = MaxSector
229 divl %ebx # ax = StartLBA / MaxSector
230 incw %dx # dx = (StartLBA % MaxSector) + 1
231 subw %dx, %bx # bx = MaxSector - Sector
232 incw %bx # bx = MaxSector - Sector + 1
233 cmpw %bx, %cx # Compare (Blocks) to (MaxSector - Sector + 1)
235 movw %cx, %bx # bx = Blocks
238 movb %dl, %cl # cl = (StartLBA % MaxSector) + 1 = Sector
239 xorw %dx, %dx # dx = 0
240 divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
241 # dx = ax % (MaxHead + 1) = Head
243 pushw %bx # Save number of blocks to transfer
244 movb %dl, %dh # dh = Head
245 movw $0x7c00, %bp # bp = 0x7c00
246 movb PhysicalDrive(%bp), %dl # dl = Drive Number
247 movb %al, %ch # ch = Cylinder
248 movb %bl, %al # al = Blocks
249 movb $2, %ah # ah = Function 2
250 movw %di, %bx # es:bx = Buffer address
256 addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks
257 subw %bx, %cx # Blocks = Blocks - NumberOfBlocks
259 shlw $(BLOCK_SHIFT-4), %bx
261 movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
267 # ****************************************************************************
269 # ****************************************************************************
271 ## if we found EFILDR, continue
276 movw $ErrorString, %si
282 .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c
284 .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c
286 # ****************************************************************************
287 # LBA Offset for BootSector, need patched by tool for HD boot.
288 # ****************************************************************************
290 .org 0x01fa # Comment it for pass build. Should optimise code size.
291 LBAOffsetForBootSector:
294 # ****************************************************************************
296 # ****************************************************************************
298 .org 0x01fe # Comment it for pass build.
300 .word 0xaa55 # Boot Sector Signature