1 #------------------------------------------------------------------------------ 2 #* 3 #* Copyright (c) 2006 - 2012, 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 8 #* 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. 11 #* 12 #* bs32.asm 13 #* 14 #* Abstract: 15 #* 16 #------------------------------------------------------------------------------ 17 18 #.MODEL small 19 .stack: 20 .486p: 21 .code16 22 23 .equ FAT_DIRECTORY_ENTRY_SIZE, 0x0020 24 .equ FAT_DIRECTORY_ENTRY_SHIFT, 5 25 .equ BLOCK_SIZE, 0x0200 26 .equ BLOCK_MASK, 0x01ff 27 .equ BLOCK_SHIFT, 9 28 # "EFILDR_____" 29 .equ LOADER_FILENAME_PART1, 0x4c494645 # "EFIL" 30 .equ LOADER_FILENAME_PART2, 0x30325244 # "DR20" 31 .equ LOADER_FILENAME_PART3, 0x20202030 # "0___" 32 33 .org 0x0 34 .global _start 35 _start: 36 Ia32Jump: 37 jmp BootSectorEntryPoint # JMP inst - 3 bytes 38 nop 39 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 55 #****************************************************************************** 56 # 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.) 59 # 60 #****************************************************************************** 61 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 75 BootSectorEntryPoint: 76 #ASSUME ds:@code 77 #ASSUME ss:@code 78 79 # **************************************************************************** 80 # Start Print 81 # **************************************************************************** 82 movw $StartString, %si 83 call PrintString 84 85 # **************************************************************************** 86 # Print over 87 # **************************************************************************** 88 89 movw %cs, %ax # ax = 0 90 movw %ax, %ss # ss = 0 91 addw $0x1000, %ax 92 movw %ax, %ds 93 94 movw $0x7c00, %sp # sp = 0x7c00 95 movw %sp, %bp # bp = 0x7c00 96 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 107 108 cmpw $0xaa55, SectorSignature(%bp) # Verify Boot Sector Signature 109 jne BadBootSector 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 123 124 movw RootCluster(%bp), %ax # ax = StartCluster of Root Directory 125 subw $2, %ax # ax = StartCluster - 2 126 xorb %bh, %bh 127 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster 128 mulw %bx # ax = (StartCluster - 2) * SectorsPerCluster 129 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster 130 pushw %ds 131 popw %es 132 xorw %di, %di # Store directory in es:di = 1000:0000 133 call ReadBlocks # Read StartCluster of Root Directory 134 135 # dx - variable storage (initial value is 0) 136 # bx - loader (initial value is 0) 137 xorw %dx, %dx 138 xorw %bx, %bx 139 140 FindEFILDR: 141 cmpl $LOADER_FILENAME_PART1, (%di) 142 jne FindVARSTORE 143 cmpl $LOADER_FILENAME_PART2, 4(%di) 144 jne FindVARSTORE 145 cmpl $LOADER_FILENAME_PART3, 7(%di) 146 jne FindVARSTORE 147 movw 26(%di), %bx # bx = Start Cluster for EFILDR <---------------------------------- 148 testw %dx, %dx 149 je FindNext # Efivar.bin is not loaded 150 jmp FoundAll 151 152 FindVARSTORE: 153 ## if the file is not loader file, see if it's "EFIVAR BIN" 154 cmpl $0x56494645, (%di) # Compare to "EFIV" 155 jne FindNext 156 cmpl $0x20205241, 4(%di) # Compare to "AR " 157 jne FindNext 158 cmpl $0x4e494220, 7(%di) # Compare to " BIN" 159 jne FindNext 160 movw %di, %dx # dx = Offset of Start Cluster for Efivar.bin <--------------------- 161 addw $26, %dx 162 testw %bx, %bx 163 je FindNext # Efildr is not loaded 164 jmp FoundAll 165 166 FindNext: 167 # go to next find 168 addw $FAT_DIRECTORY_ENTRY_SIZE, %di # Increment di 169 subw $FAT_DIRECTORY_ENTRY_SIZE, %cx # Decrement cx 170 # TODO: jump to FindVarStore if ... 171 jne FindEFILDR 172 jmp NotFoundAll 173 174 FoundAll: 175 FoundEFILDR: 176 movw %bx, %cx # cx = Start Cluster for EFILDR <---------------------------------- 177 movw %cs, %ax # Destination = 2000:0000 178 addw $0x2000, %ax 179 movw %ax, %es 180 xorw %di, %di 181 ReadFirstClusterOfEFILDR: 182 movw %cx, %ax # ax = StartCluster 183 subw $2, %ax # ax = StartCluster - 2 184 xorb %bh, %bh 185 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster 186 pushw %dx 187 mulw %bx 188 popw %dx # ax = (StartCluster - 2) * SectorsPerCluster 189 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster 190 xorb %bh, %bh 191 movb SectorsPerCluster(%bp), %bl # bx = Number of Sectors in a cluster 192 pushw %es 193 call ReadBlocks 194 popw %ax 195 JumpIntoFirstSectorOfEFILDR: 196 movw %ax, JumpSegment(%bp) 197 JumpFarInstruction: 198 .byte 0xea 199 JumpOffset: 200 .word 0x000 201 JumpSegment: 202 .word 0x2000 203 204 205 PrintString: 206 movw $0xb800, %ax 207 movw %ax, %es 208 movw $0x7c0, %ax 209 movw %ax, %ds 210 movw $6, %cx 211 movw $160, %di 212 rep 213 movsw 214 ret 215 # **************************************************************************** 216 # ReadBlocks - Reads a set of blocks from a block device 217 # 218 # AX = Start LBA 219 # BX = Number of Blocks to Read 220 # ES:DI = Buffer to store sectors read from disk 221 # **************************************************************************** 222 223 # cx = Blocks 224 # bx = NumberOfBlocks 225 # si = StartLBA 226 227 ReadBlocks: 228 pusha 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 233 ReadCylinderLoop: 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) 243 jg LimitTransfer 244 movw %cx, %bx # bx = Blocks 245 LimitTransfer: 246 pushw %cx 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 251 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 260 int $0x13 261 jc DiskError 262 popw %bx 263 popw %cx 264 movzwl %bx, %ebx 265 addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks 266 subw %bx, %cx # Blocks = Blocks - NumberOfBlocks 267 movw %es, %ax 268 shlw $(BLOCK_SHIFT-4), %bx 269 addw %bx, %ax 270 movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE 271 cmpw $0, %cx 272 jne ReadCylinderLoop 273 popa 274 ret 275 276 # **************************************************************************** 277 # ERROR Condition: 278 # **************************************************************************** 279 NotFoundAll: 280 ## if we found EFILDR, continue 281 testw %bx, %bx 282 jne FoundEFILDR 283 BadBootSector: 284 DiskError: 285 movw $ErrorString, %si 286 call PrintString 287 Halt: 288 jmp Halt 289 290 StartString: 291 .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c 292 ErrorString: 293 .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c 294 295 # **************************************************************************** 296 # LBA Offset for BootSector, need patched by tool for HD boot. 297 # **************************************************************************** 298 299 .org 0x01fa 300 LBAOffsetForBootSector: 301 .long 0x0 302 303 # **************************************************************************** 304 # Sector Signature 305 # **************************************************************************** 306 307 .org 0x01fe 308 SectorSignature: 309 .word 0xaa55 # Boot Sector Signature 310 311 312 313