Home | History | Annotate | Download | only in BootSector
      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