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