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 .code 22 23FAT_DIRECTORY_ENTRY_SIZE EQU 020h 24FAT_DIRECTORY_ENTRY_SHIFT EQU 5 25BLOCK_SIZE EQU 0200h 26BLOCK_MASK EQU 01ffh 27BLOCK_SHIFT EQU 9 28 ; "EFILDR_____" 29LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL" 30LOADER_FILENAME_PART2 EQU 030325244h ; "DR20" 31LOADER_FILENAME_PART3 EQU 020202030h ; "0___" 32 33 org 0h 34Ia32Jump: 35 jmp BootSectorEntryPoint ; JMP inst - 3 bytes 36 nop 37 38OemId db "INTEL " ; OemId - 8 bytes 39; BPB data below will be fixed by tool 40SectorSize dw 0 ; Sector Size - 16 bits 41SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits 42ReservedSectors dw 0 ; Reserved Sectors - 16 bits 43NoFats db 0 ; Number of FATs - 8 bits 44RootEntries dw 0 ; Root Entries - 16 bits 45Sectors dw 0 ; Number of Sectors - 16 bits 46Media db 0 ; Media - 8 bits - ignored 47SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits 48SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored 49Heads dw 0 ; Heads - 16 bits - ignored 50HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored 51LargeSectors dd 0 ; Large Sectors - 32 bits 52 53;****************************************************************************** 54; 55;The structure for FAT32 starting at offset 36 of the boot sector. (At this point, 56;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.) 57; 58;****************************************************************************** 59 60SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes 61ExtFlags dw 0 ; Mirror Flag - 2 bytes 62FSVersion dw 0 ; File System Version - 2 bytes 63RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes 64FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes 65BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes 66Reserved db 12 dup(0) ; Reserved Field - 12 bytes 67PhysicalDrive db 0 ; Physical Drive Number - 1 byte 68Reserved1 db 0 ; Reserved Field - 1 byte 69Signature db 0 ; Extended Boot Signature - 1 byte 70VolId db " " ; Volume Serial Number - 4 bytes 71FatLabel db " " ; Volume Label - 11 bytes 72FileSystemType db "FAT32 " ; File System Type - 8 bytes 73 74BootSectorEntryPoint: 75 ASSUME ds:@code 76 ASSUME ss:@code 77 78; **************************************************************************** 79; Start Print 80; **************************************************************************** 81 mov si, offset StartString 82 call PrintString 83 84; **************************************************************************** 85; Print over 86; **************************************************************************** 87 88 mov ax,cs ; ax = 0 89 mov ss,ax ; ss = 0 90 add ax,1000h 91 mov ds,ax 92 93 mov sp,07c00h ; sp = 0x7c00 94 mov bp,sp ; bp = 0x7c00 95 96 mov ah,8 ; ah = 8 - Get Drive Parameters Function 97 mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL 98 int 13h ; Get Drive Parameters 99 xor ax,ax ; ax = 0 100 mov al,dh ; al = dh 101 inc al ; MaxHead = al + 1 102 push ax ; 0000:7bfe = MaxHead 103 mov al,cl ; al = cl 104 and al,03fh ; MaxSector = al & 0x3f 105 push ax ; 0000:7bfc = MaxSector 106 107 cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature 108 jne BadBootSector 109 mov cx,word ptr [bp+RootEntries] ; cx = RootEntries 110 shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes 111 mov bx,cx ; bx = size of the Root Directory in bytes 112 and bx,BLOCK_MASK ; See if it is an even number of sectors long 113 jne BadBootSector ; If is isn't, then the boot sector is bad. 114 mov bx,cx ; bx = size of the Root Directory in bytes 115 shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors 116 mov al,byte ptr [bp+NoFats] ; al = NoFats 117 xor ah,ah ; ah = 0 ==> ax = NoFats 118 mul word ptr [bp+SectorsPerFat32] ; ax = NoFats * SectorsPerFat 119 add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA 120 add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA 121 mov word ptr [bp],ax ; Save FirstClusterLBA for later use 122 123 mov ax,word ptr [bp+RootCluster] ; ax = StartCluster of Root Directory 124 sub ax,2 ; ax = StartCluster - 2 125 xor bh,bh 126 mov bl,byte ptr [bp+SectorsPerCluster]; bx = SectorsPerCluster 127 mul bx ; ax = (StartCluster - 2) * SectorsPerCluster 128 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster 129 push ds 130 pop es 131 xor di,di ; Store directory in es:di = 1000:0000 132 call ReadBlocks ; Read StartCluster of Root Directory 133 134 ; dx - variable storage (initial value is 0) 135 ; bx - loader (initial value is 0) 136 xor dx, dx 137 xor bx, bx 138 139FindEFILDR: 140 cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL" 141 jne FindVARSTORE 142 cmp dword ptr [di+4],LOADER_FILENAME_PART2 143 jne FindVARSTORE 144 cmp dword ptr [di+7],LOADER_FILENAME_PART3 145 jne FindVARSTORE 146 mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <---------------------------------- 147 test dx, dx 148 je FindNext ; Efivar.bin is not loaded 149 jmp FoundAll 150 151FindVARSTORE: 152 ; if the file is not loader file, see if it's "EFIVAR BIN" 153 cmp dword ptr [di], 056494645h ; Compare to "EFIV" 154 jne FindNext 155 cmp dword ptr [di+4], 020205241h ; Compare to "AR " 156 jne FindNext 157 cmp dword ptr [di+7], 04e494220h ; Compare to " BIN" 158 jne FindNext 159 mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <--------------------- 160 add dx, 26 161 test bx, bx 162 je FindNext ; Efildr is not loaded 163 jmp FoundAll 164 165FindNext: 166 ; go to next find 167 add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di 168 sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx 169 ; TODO: jump to FindVarStore if ... 170 jne FindEFILDR 171 jmp NotFoundAll 172 173FoundAll: 174FoundEFILDR: 175 mov cx,bx ; cx = Start Cluster for EFILDR <---------------------------------- 176 mov ax,cs ; Destination = 2000:0000 177 add ax,2000h 178 mov es,ax 179 xor di,di 180ReadFirstClusterOfEFILDR: 181 mov ax,cx ; ax = StartCluster 182 sub ax,2 ; ax = StartCluster - 2 183 xor bh,bh 184 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster 185 push dx 186 mul bx 187 pop dx ; ax = (StartCluster - 2) * SectorsPerCluster 188 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster 189 xor bh,bh 190 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster 191 push es 192 call ReadBlocks 193 pop ax 194JumpIntoFirstSectorOfEFILDR: 195 mov word ptr [bp+JumpSegment],ax 196JumpFarInstruction: 197 db 0eah 198JumpOffset: 199 dw 0000h 200JumpSegment: 201 dw 2000h 202 203 204PrintString: 205 mov ax,0b800h 206 mov es,ax 207 mov ax, 07c0h 208 mov ds, ax 209 mov cx, 6 210 mov di, 160 211 rep movsw 212 ret 213; **************************************************************************** 214; ReadBlocks - Reads a set of blocks from a block device 215; 216; AX = Start LBA 217; BX = Number of Blocks to Read 218; ES:DI = Buffer to store sectors read from disk 219; **************************************************************************** 220 221; cx = Blocks 222; bx = NumberOfBlocks 223; si = StartLBA 224 225ReadBlocks: 226 pusha 227 add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA 228 add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA 229 mov esi,eax ; esi = Start LBA 230 mov cx,bx ; cx = Number of blocks to read 231ReadCylinderLoop: 232 mov bp,07bfch ; bp = 0x7bfc 233 mov eax,esi ; eax = Start LBA 234 xor edx,edx ; edx = 0 235 movzx ebx,word ptr [bp] ; bx = MaxSector 236 div ebx ; ax = StartLBA / MaxSector 237 inc dx ; dx = (StartLBA % MaxSector) + 1 238 sub bx,dx ; bx = MaxSector - Sector 239 inc bx ; bx = MaxSector - Sector + 1 240 cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1) 241 jg LimitTransfer 242 mov bx,cx ; bx = Blocks 243LimitTransfer: 244 push cx 245 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector 246 xor dx,dx ; dx = 0 247 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder 248 ; dx = ax % (MaxHead + 1) = Head 249 250 push bx ; Save number of blocks to transfer 251 mov dh,dl ; dh = Head 252 mov bp,07c00h ; bp = 0x7c00 253 mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number 254 mov ch,al ; ch = Cylinder 255 mov al,bl ; al = Blocks 256 mov ah,2 ; ah = Function 2 257 mov bx,di ; es:bx = Buffer address 258 int 013h 259 jc DiskError 260 pop bx 261 pop cx 262 movzx ebx,bx 263 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks 264 sub cx,bx ; Blocks = Blocks - NumberOfBlocks 265 mov ax,es 266 shl bx,(BLOCK_SHIFT-4) 267 add ax,bx 268 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE 269 cmp cx,0 270 jne ReadCylinderLoop 271 popa 272 ret 273 274; **************************************************************************** 275; ERROR Condition: 276; **************************************************************************** 277NotFoundAll: 278 ; if we found EFILDR, continue 279 test bx,bx 280 jne FoundEFILDR 281BadBootSector: 282DiskError: 283 mov si, offset ErrorString 284 call PrintString 285Halt: 286 jmp Halt 287 288StartString: 289 db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch 290ErrorString: 291 db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch 292 293; **************************************************************************** 294; LBA Offset for BootSector, need patched by tool for HD boot. 295; **************************************************************************** 296 297 org 01fah 298LBAOffsetForBootSector: 299 dd 0h 300 301; **************************************************************************** 302; Sector Signature 303; **************************************************************************** 304 305 org 01feh 306SectorSignature: 307 dw 0aa55h ; Boot Sector Signature 308 309 end 310 311