source: trunk/bootcode/special/fat16.asm@ 201

Last change on this file since 201 was 106, checked in by Ben Rietbroek, 8 years ago

This file updated for consistency - not part of AirBoot [v1.1.1-testing]

CAUTION:
This is a testbuild !
AirBoot uses the BIOS to access disks and a small coding error can trash
partition tables or other vital disk structures. You are advised to make
backups of TRACK0 and EBRs before using this testbuild. More info at:
https://rousseaux.github.io/netlabs.air-boot/pdf/AirBoot-v1.1.0-manual.pdf

File size: 12.4 KB
Line 
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
22IFDEF MODULE_NAMES
23DB 'FAT16',0
24ENDIF
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
39FAT16_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
72FAT16_InitAccess EndP
73
74; Reads Root-Entries to 9000:0 for further processing...
75; In: None
76; Out: None
77; Destroyed: None
78FAT16_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
89FAT16_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
96FAT16_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
121FAT16_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
130FAT16_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
179FAT16_ReadCluster EndP
180
181; Preserves all registers, help routine for LoadKernel
182; supports more than 1 sector read (unlike MBR_IO_LoadSector)
183FAT16_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
197FAT16_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
205FAT16_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
320FAT16_ProcessKrnlDirectory EndP
Note: See TracBrowser for help on using the repository browser.