| 1 | ; AiR-BOOT (c) Copyright 1998-2008 M. Kiewitz | 
|---|
| 2 | ; | 
|---|
| 3 | ; This file is part of AiR-BOOT | 
|---|
| 4 | ; | 
|---|
| 5 | ; AiR-BOOT is free software: you can redistribute it and/or modify it under | 
|---|
| 6 | ;  the terms of the GNU General Public License as published by the Free | 
|---|
| 7 | ;  Software Foundation, either version 3 of the License, or (at your option) | 
|---|
| 8 | ;  any later version. | 
|---|
| 9 | ; | 
|---|
| 10 | ; AiR-BOOT is distributed in the hope that it will be useful, but WITHOUT ANY | 
|---|
| 11 | ;  WARRANTY: without even the implied warranty of MERCHANTABILITY or FITNESS | 
|---|
| 12 | ;  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 
|---|
| 13 | ;  details. | 
|---|
| 14 | ; | 
|---|
| 15 | ; You should have received a copy of the GNU General Public License along with | 
|---|
| 16 | ;  AiR-BOOT. If not, see <http://www.gnu.org/licenses/>. | 
|---|
| 17 | ; | 
|---|
| 18 | ;--------------------------------------------------------------------------- | 
|---|
| 19 | ;                                                 AiR-BOOT / FAT-16 SUPPORT | 
|---|
| 20 | ;--------------------------------------------------------------------------- | 
|---|
| 21 |  | 
|---|
| 22 | IFDEF   MODULE_NAMES | 
|---|
| 23 | DB 'FAT16',0 | 
|---|
| 24 | ENDIF | 
|---|
| 25 |  | 
|---|
| 26 | ; Here is access code for accessing FAT-16 partitions. It's not a complete | 
|---|
| 27 | ;  File-API and only for simple readonly-access. | 
|---|
| 28 | ; It's currently only used by SPECIAL\LINUX.ASM for Linux Kernel Loading. | 
|---|
| 29 | ; | 
|---|
| 30 | ; Note: This code will ONLY WORK on computers with INT 13h Extension. | 
|---|
| 31 | ;        I did not want to code silly cylinder stuff here. I have also used | 
|---|
| 32 | ;        i386 code in here, because Linux requires so as well. Please note that | 
|---|
| 33 | ;        I don't use i386 code anywhere (!) else in AiR-BOOT.                    ; Rousseau: yes you did, movezx is 386-only :-) | 
|---|
| 34 | ;                                                                                ; Replaced by 286 instructions. | 
|---|
| 35 | ; Initialize FAT-16 access on specified partition (required for following xs) | 
|---|
| 36 | ;        In: DS:SI - IPT-Entry that contains a FAT-16 partition | 
|---|
| 37 | ;       Out: None | 
|---|
| 38 | ; Destroyed: None | 
|---|
| 39 | FAT16_InitAccess                Proc Near  Uses eax bx edx | 
|---|
| 40 | mov    al, bptr ds:[si+LocIPT_Drive] | 
|---|
| 41 | mov    FAT16_Drive, al | 
|---|
| 42 | mov    edx, dptr ds:[si+LocIPT_AbsoluteBegin] | 
|---|
| 43 | mov    FAT16_AbsPartitionBegin, edx | 
|---|
| 44 | mov    INT13X_DAP_Absolute, edx       ; Read in Boot-Record of partition | 
|---|
| 45 | mov    INT13X_DAP_NumBlocks, 1        ; 1 Sector to load | 
|---|
| 46 | mov    FAT16_FATCacheSector, 255      ; Sector 255 - So nothing cached | 
|---|
| 47 | mov    ax, ds | 
|---|
| 48 | shl    eax, 16 | 
|---|
| 49 | mov    ax, offset FAT16_FATCache | 
|---|
| 50 | mov    INT13X_DAP_Transfer, eax       ; Transfer to FAT-Cache Area | 
|---|
| 51 | call   FAT16_LoadSectors | 
|---|
| 52 | mov    al, bptr [FAT16_FATCache+13] | 
|---|
| 53 | mov    FAT16_SecsPerCluster, al | 
|---|
| 54 | movzx  eax, wptr [FAT16_FATCache+14]  ; +14 -> ReservedSectors | 
|---|
| 55 | add    edx, eax                       ; EDX = AbsPartitionPos+ReservedSectors | 
|---|
| 56 | mov    FAT16_AbsFATBegin, edx         ; Is Absolute-FAT-Begin | 
|---|
| 57 | movzx  ax, bptr [FAT16_FATCache+16]   ; +16 -> FAT-Copies Count | 
|---|
| 58 | mov    bx, wptr [FAT16_FATCache+22]   ; +22 -> Sectors Per FAT | 
|---|
| 59 | mov    FAT16_SecsPerFAT, bx | 
|---|
| 60 | push   dx | 
|---|
| 61 | mul    bx | 
|---|
| 62 | pop    dx | 
|---|
| 63 | movzx  eax, ax | 
|---|
| 64 | add    edx, eax | 
|---|
| 65 | mov    FAT16_AbsRootBegin, edx        ; Is Absolute-Root-Begin | 
|---|
| 66 | movzx  eax, wptr [FAT16_FATCache+17]  ; +17 -> Number of Root Entries | 
|---|
| 67 | mov    FAT16_NumOfRootEntries, ax | 
|---|
| 68 | shr    eax, 4                         ; NumOfRootEntries/16 | 
|---|
| 69 | add    edx, eax | 
|---|
| 70 | mov    FAT16_AbsClusterBegin, edx     ; Is Absolute-Cluster-Begin | 
|---|
| 71 | ret | 
|---|
| 72 | FAT16_InitAccess                EndP | 
|---|
| 73 |  | 
|---|
| 74 | ; Reads Root-Entries to 9000:0 for further processing... | 
|---|
| 75 | ;        In: None | 
|---|
| 76 | ;       Out: None | 
|---|
| 77 | ; Destroyed: None | 
|---|
| 78 | FAT16_ReadRoot                  Proc Near  Uses eax | 
|---|
| 79 | mov    ax, 9000h | 
|---|
| 80 | shl    eax, 16                        ; 9000:0 -> Space for Root | 
|---|
| 81 | mov    INT13X_DAP_Transfer, eax       ; Transfer to that segment | 
|---|
| 82 | mov    eax, FAT16_AbsRootBegin | 
|---|
| 83 | mov    INT13X_DAP_Absolute, eax       ; Read in Root-Entries... | 
|---|
| 84 | mov    ax, FAT16_NumOfRootEntries | 
|---|
| 85 | shr    ax, 4                          ; NumOfRootEntries/16 | 
|---|
| 86 | mov    INT13X_DAP_NumBlocks, ax       ;  -> Sectors of Root-Entries | 
|---|
| 87 | call   FAT16_LoadSectors              ; DONE. | 
|---|
| 88 | ret | 
|---|
| 89 | FAT16_ReadRoot                  EndP | 
|---|
| 90 |  | 
|---|
| 91 | ; Searches a FAT16-File-Entry in specified memory block | 
|---|
| 92 | ;        In: CX - Total Count of File-Entries to search | 
|---|
| 93 | ;            SI - Offset, what to search for Segment CS (11-Byte block) | 
|---|
| 94 | ;       Out: DX - Cluster, where the data starts... | 
|---|
| 95 | ; Destroyed: None | 
|---|
| 96 | FAT16_SearchEntry               Proc Near  Uses ax bx es di | 
|---|
| 97 | xor    dx, dx                         ; No Result as default | 
|---|
| 98 | or     cx, cx | 
|---|
| 99 | jz     FAT16SE_NoEntries | 
|---|
| 100 | mov    bx, cx | 
|---|
| 101 | mov    ax, 9000h | 
|---|
| 102 | mov    es, ax | 
|---|
| 103 | xor    di, di | 
|---|
| 104 | FAT16SE_SearchLoop: | 
|---|
| 105 | push   si | 
|---|
| 106 | push   di | 
|---|
| 107 | mov    cx, 11 | 
|---|
| 108 | repe   cmpsb                    ; Compare total 11-bytes | 
|---|
| 109 | pop    di | 
|---|
| 110 | pop    si | 
|---|
| 111 | je     FAT16SE_EntryFound | 
|---|
| 112 | add    di, 32                      ; Skip 1 FAT16-Entry now :) | 
|---|
| 113 | dec    bx | 
|---|
| 114 | jnz    FAT16SE_SearchLoop | 
|---|
| 115 | FAT16SE_NoEntries: | 
|---|
| 116 | ret | 
|---|
| 117 |  | 
|---|
| 118 | FAT16SE_EntryFound: | 
|---|
| 119 | mov    dx, wptr es:[di+26]            ; Starting Cluster of Entry | 
|---|
| 120 | ret | 
|---|
| 121 | FAT16_SearchEntry               EndP | 
|---|
| 122 |  | 
|---|
| 123 | ; Reads a Cluster and gets Next-Cluster as well... | 
|---|
| 124 | ;        In: DX - Cluster-Number to load, DAP_Transfer-Offset filled out | 
|---|
| 125 | ;            ES - Segment, where to read Cluster to | 
|---|
| 126 | ;            DI - Offset, where to read Cluster to | 
|---|
| 127 | ;       Out: DX - Cluster that follows this one, es:[DI] filled out | 
|---|
| 128 | ;            DI - Offset, adjusted | 
|---|
| 129 | ; Destroyed: None | 
|---|
| 130 | FAT16_ReadCluster               Proc Near  Uses eax bx | 
|---|
| 131 | push   dx | 
|---|
| 132 | ; First read Cluster into buffer... | 
|---|
| 133 | mov    ax, es | 
|---|
| 134 | shl    eax, 16 | 
|---|
| 135 | mov    ax, di | 
|---|
| 136 | mov    INT13X_DAP_Transfer, eax    ; Read to 9000:DI | 
|---|
| 137 | mov    ax, dx | 
|---|
| 138 | sub    ax, 2                       ; Everything starts at Cluster 2 | 
|---|
| 139 | ;movzx  bx, FAT16_SecsPerCluster | 
|---|
| 140 | mov   bl,FAT16_SecsPerCluster | 
|---|
| 141 | mov   bh,0 | 
|---|
| 142 |  | 
|---|
| 143 | mul    bx | 
|---|
| 144 | shl    edx, 16 | 
|---|
| 145 | mov    dx, ax                      ; EDX - Relative to Cluster-Start | 
|---|
| 146 | add    edx, FAT16_AbsClusterBegin  ; EDX - Absolute Sector Count | 
|---|
| 147 | mov    INT13X_DAP_Absolute, edx | 
|---|
| 148 | mov    INT13X_DAP_NumBlocks, bx    ; Get a whole cluster | 
|---|
| 149 | call   FAT16_LoadSectors           ; DONE. | 
|---|
| 150 | pop    dx | 
|---|
| 151 | ; Update DI to next position... | 
|---|
| 152 | mov    al, FAT16_SecsPerCluster | 
|---|
| 153 | shl    ax, 9 | 
|---|
| 154 | add    di, ax | 
|---|
| 155 | ; Finally, look for next Cluster following to this one... | 
|---|
| 156 | ;movzx  bx, dl | 
|---|
| 157 | mov   bl,dl | 
|---|
| 158 | mov   bh,0 | 
|---|
| 159 |  | 
|---|
| 160 | shl    bx, 1                          ; BX - Offset within FAT-Table | 
|---|
| 161 | shr    dx, 8                          ; DX - FAT-Sector | 
|---|
| 162 | cmp    dl, FAT16_FATCacheSector | 
|---|
| 163 | je     FAT16RC_GotFATsectorAlready | 
|---|
| 164 | ; Load FAT-Sector, because the required one is not in Cache | 
|---|
| 165 | mov    FAT16_FATCacheSector, dl | 
|---|
| 166 | mov    ax, cs | 
|---|
| 167 | shl    eax, 16 | 
|---|
| 168 | mov    ax, offset FAT16_FATCache | 
|---|
| 169 | mov    INT13X_DAP_Transfer, eax       ; Transfer to FAT-Cache Area | 
|---|
| 170 | movzx  edx, dx | 
|---|
| 171 | mov    eax, FAT16_AbsFATBegin | 
|---|
| 172 | add    eax, edx | 
|---|
| 173 | mov    INT13X_DAP_Absolute, eax       ; Read in Boot-Record of partition | 
|---|
| 174 | mov    INT13X_DAP_NumBlocks, 1        ; 1 Sector to load | 
|---|
| 175 | call   FAT16_LoadSectors              ; DONE. | 
|---|
| 176 | FAT16RC_GotFATsectorAlready: | 
|---|
| 177 | mov    dx, wptr cs:[FAT16_FATCache+bx] ; Get Next-Cluster Pointer | 
|---|
| 178 | ret | 
|---|
| 179 | FAT16_ReadCluster               EndP | 
|---|
| 180 |  | 
|---|
| 181 | ; Preserves all registers, help routine for LoadKernel | 
|---|
| 182 | ; supports more than 1 sector read (unlike MBR_IO_LoadSector) | 
|---|
| 183 | FAT16_LoadSectors               Proc Near  Uses eax dx ds si | 
|---|
| 184 | push   cs | 
|---|
| 185 | pop    ds | 
|---|
| 186 | mov    si, offset INT13X_DAP | 
|---|
| 187 | mov    dl, ds:[FAT16_Drive] | 
|---|
| 188 | mov    ah, 42h                        ; Extended Read | 
|---|
| 189 | int    13h | 
|---|
| 190 | jnc    FAT16LS_Success | 
|---|
| 191 | call   MBR_LoadError | 
|---|
| 192 |  | 
|---|
| 193 | FAT16LS_Success: | 
|---|
| 194 | movzx  eax, wptr ds:[INT13X_DAP_NumBlocks] | 
|---|
| 195 | add    dptr ds:[INT13X_DAP_Absolute+0], eax  ; Adjust Absolute Offset | 
|---|
| 196 | ret | 
|---|
| 197 | FAT16_LoadSectors               EndP | 
|---|
| 198 |  | 
|---|
| 199 | ; Will Pre-Process Directory loaded to 9000:0, remove directory and VFAT | 
|---|
| 200 | ;  entries for display purpose in window | 
|---|
| 201 | ;        In: DI - Ending-Offset of Directory | 
|---|
| 202 | ;            ES == CS | 
|---|
| 203 | ;       Out: None | 
|---|
| 204 | ; Destroyed: None | 
|---|
| 205 | FAT16_ProcessKrnlDirectory      Proc Near  Uses ds si es di | 
|---|
| 206 | mov    dx, di                         ; DX - Ending-Offset of Directory | 
|---|
| 207 | mov    ax, 9000h | 
|---|
| 208 | mov    ds, ax                         ; DS == 9000h | 
|---|
| 209 | xor    si, si                         ; SI - Current Pos in Directory | 
|---|
| 210 | mov    di, offset LINUX_KernelEntries ; DI - Array of Kernel-Entries | 
|---|
| 211 | mov    cs:[LINUX_KernelNo], 0 | 
|---|
| 212 | FAT16PPD_DirectoryLoop: | 
|---|
| 213 | mov    al, ds:[si]                 ; +0  -> First char of Basename | 
|---|
| 214 | or     al, al | 
|---|
| 215 | jz     FAT16PPD_IgnoreEntry        ; == 0, empty | 
|---|
| 216 | cmp    al, 0E5h | 
|---|
| 217 | je     FAT16PPD_IgnoreEntry        ; == E5, deleted | 
|---|
| 218 | mov    al, ds:[si+11]              ; +11 -> Flags of Entry | 
|---|
| 219 | cmp    al, 0Fh                     ; 0F as flags -> VFAT Entry | 
|---|
| 220 | je     FAT16PPD_IgnoreEntry | 
|---|
| 221 | test   al, 18h                     ; Bit 4 -> Directory | 
|---|
| 222 | jnz    FAT16PPD_IgnoreEntry        ; Bit 3 -> Volume | 
|---|
| 223 |  | 
|---|
| 224 | ; Set Size-Entry in KernelSizeTable | 
|---|
| 225 | push   ds | 
|---|
| 226 | push   si | 
|---|
| 227 | push   di | 
|---|
| 228 | mov    bx, ds:[si+30] | 
|---|
| 229 | mov    ax, ds:[si+28]           ; BX:AX - Size of file in Bytes | 
|---|
| 230 |  | 
|---|
| 231 | mov    dx, bx | 
|---|
| 232 | and    dx, 511                  ; My crazy way of dividing a 32-bit | 
|---|
| 233 | shr    ax, 9                    ; value through 512 using 16-bit | 
|---|
| 234 | shr    bx, 9                    ; instructions... :) | 
|---|
| 235 | shl    dx, 7                    ; (dont ever ever use a DIV) | 
|---|
| 236 | or     ax, dx                   ; BX:AX - Size of file in 512-blocks | 
|---|
| 237 |  | 
|---|
| 238 | push   cs | 
|---|
| 239 | pop    ds                       ; DS==CS for GetSizeElementPtr | 
|---|
| 240 | push   ax | 
|---|
| 241 | mov    ax, di | 
|---|
| 242 | call   PART_GetSizeElementPointer ; SI - Pointer to Size Element | 
|---|
| 243 | pop    ax | 
|---|
| 244 | mov    di, si | 
|---|
| 245 | call   PART_FillOutSizeElement  ; BX:AX -> ES:DI (Size Element) | 
|---|
| 246 | pop    di | 
|---|
| 247 | pop    si | 
|---|
| 248 | pop    ds | 
|---|
| 249 |  | 
|---|
| 250 | ; Copy entry and make append extension to basename | 
|---|
| 251 | ; "TEST    TMP" -> "TESTTMP    " | 
|---|
| 252 | mov    bx, 7 | 
|---|
| 253 | FAT16PPD_GetLenOfBasename: | 
|---|
| 254 | cmp    bptr ds:[si+bx], ' ' | 
|---|
| 255 | jne    FAT16PPD_EndOfBasename | 
|---|
| 256 | dec    bx | 
|---|
| 257 | jnz    FAT16PPD_GetLenOfBasename | 
|---|
| 258 | FAT16PPD_EndOfBasename: | 
|---|
| 259 | mov    ah, bl | 
|---|
| 260 | inc    ah                          ; AH - Count of Basename Chars (max 8) | 
|---|
| 261 | mov    bx, 10 | 
|---|
| 262 | FAT16PPD_GetLenOfExtension: | 
|---|
| 263 | cmp    bptr ds:[si+bx], ' ' | 
|---|
| 264 | jne    FAT16PPD_EndOfExtension | 
|---|
| 265 | dec    bl | 
|---|
| 266 | cmp    bl, 7 | 
|---|
| 267 | ja     FAT16PPD_GetLenOfExtension | 
|---|
| 268 | FAT16PPD_EndOfExtension: | 
|---|
| 269 | sub    bl, 7                       ; BL - Count of Extension Chars (max 3) | 
|---|
| 270 | ; Now we will copy&fill out 11 characters (Basename&Extension) | 
|---|
| 271 | push   dx | 
|---|
| 272 | push      ax | 
|---|
| 273 | xor    eax, eax | 
|---|
| 274 | stosd                        ; +0 [DWORD] Empty Serial | 
|---|
| 275 | pop       ax | 
|---|
| 276 | mov    dx, si | 
|---|
| 277 | ;movzx  cx, ah | 
|---|
| 278 | mov   cl,ah | 
|---|
| 279 | mov   ch,0 | 
|---|
| 280 |  | 
|---|
| 281 | rep    movsb | 
|---|
| 282 | mov    si, dx                   ; Restore SI | 
|---|
| 283 | add    si, 8 | 
|---|
| 284 | or     bl, bl | 
|---|
| 285 | jz     FAT16PPD_NoExtensionCopy | 
|---|
| 286 | mov    cl, bl | 
|---|
| 287 | rep    movsb | 
|---|
| 288 | FAT16PPD_NoExtensionCopy: | 
|---|
| 289 | add    ah, bl                   ; AH - Total Bytes of BaseName | 
|---|
| 290 | mov    cl, 11 | 
|---|
| 291 | mov    al, ' ' | 
|---|
| 292 | sub    cl, ah | 
|---|
| 293 | jz     FAT16PPD_NoFillUpName | 
|---|
| 294 | rep    stosb                    ; +4 [STR*11] Label | 
|---|
| 295 | FAT16PPD_NoFillUpName: | 
|---|
| 296 | mov    si, dx                   ; Restore SI | 
|---|
| 297 |  | 
|---|
| 298 | mov    al, FAT16_Drive | 
|---|
| 299 | mov    ah, 0FDh | 
|---|
| 300 | stosw                           ; +15 [BYTE/BYTE] Drive, SystemID | 
|---|
| 301 | xor    ax, ax | 
|---|
| 302 | stosb                           ; +17 [BYTE] Flags | 
|---|
| 303 | stosw                           ; +18 [WORD] CRC | 
|---|
| 304 | mov    ax, wptr ds:[si+26]      ; Starting Cluster of File | 
|---|
| 305 | stosw | 
|---|
| 306 | xor    ax, ax | 
|---|
| 307 | stosb                           ; +20 [BYTE/BYTE/BYTE] Location Begin | 
|---|
| 308 | stosw | 
|---|
| 309 | stosb                           ; +23 [BYTE/BYTE/BYTE] Location Part | 
|---|
| 310 | mov    cx, 4 | 
|---|
| 311 | rep    stosw                    ; +26 [DWORD/DWORD] Abs Locations | 
|---|
| 312 | pop    dx | 
|---|
| 313 | inc    cs:[LINUX_KernelNo] | 
|---|
| 314 | FAT16PPD_IgnoreEntry: | 
|---|
| 315 | add    si, 32 | 
|---|
| 316 | cmp    si, dx                         ; We are at Ending-Offset ? | 
|---|
| 317 | jb     FAT16PPD_DirectoryLoop | 
|---|
| 318 | ; Done, now we got a maximum of 20 kernels in LINUX_KernelEntries-Array. | 
|---|
| 319 | ret | 
|---|
| 320 | FAT16_ProcessKrnlDirectory      EndP | 
|---|