Home | History | Annotate | Download | only in BootSector
      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 
     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     030325244h   ; "DR20"
     31 LOADER_FILENAME_PART3     EQU     020202030h   ; "0___"
     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 
     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 
     60 SectorsPerFat32   dd  0             ; Sectors Per FAT for FAT32       - 4 bytes
     61 ExtFlags          dw  0             ; Mirror Flag                     - 2 bytes
     62 FSVersion         dw  0             ; File System Version             - 2 bytes
     63 RootCluster       dd  0             ; 1st Cluster Number of Root Dir  - 4 bytes
     64 FSInfo            dw  0             ; Sector Number of FSINFO         - 2 bytes
     65 BkBootSector      dw  0             ; Sector Number of Bk BootSector  - 2 bytes
     66 Reserved          db  12 dup(0)     ; Reserved Field                  - 12 bytes
     67 PhysicalDrive     db  0             ; Physical Drive Number           - 1 byte
     68 Reserved1         db  0             ; Reserved Field                  - 1 byte
     69 Signature         db  0             ; Extended Boot Signature         - 1 byte
     70 VolId             db  "    "        ; Volume Serial Number            - 4 bytes
     71 FatLabel          db  "           " ; Volume Label                    - 11 bytes
     72 FileSystemType    db  "FAT32   "    ; File System Type                - 8 bytes
     73 
     74 BootSectorEntryPoint:
     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 
    139 FindEFILDR:
    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 
    151 FindVARSTORE:
    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   
    165 FindNext:
    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 
    173 FoundAll:
    174 FoundEFILDR:
    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
    180 ReadFirstClusterOfEFILDR:
    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
    194 JumpIntoFirstSectorOfEFILDR:
    195   mov     word ptr [bp+JumpSegment],ax
    196 JumpFarInstruction:
    197   db      0eah
    198 JumpOffset:
    199   dw      0000h
    200 JumpSegment:
    201   dw      2000h
    202 
    203 
    204 PrintString:
    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 
    225 ReadBlocks:
    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
    231 ReadCylinderLoop:
    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
    243 LimitTransfer:
    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 ; ****************************************************************************
    277 NotFoundAll:
    278   ; if we found EFILDR, continue
    279   test bx,bx
    280   jne  FoundEFILDR
    281 BadBootSector:
    282 DiskError:
    283   mov  si, offset ErrorString
    284   call PrintString
    285 Halt:
    286   jmp   Halt
    287 
    288 StartString:
    289   db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch
    290 ErrorString:
    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
    298 LBAOffsetForBootSector:
    299   dd        0h
    300 
    301 ; ****************************************************************************
    302 ; Sector Signature
    303 ; ****************************************************************************
    304 
    305   org 01feh
    306 SectorSignature:
    307   dw        0aa55h      ; Boot Sector Signature
    308 
    309   end 
    310   
    311