source: trunk/BOOTCODE/SPECIAL/FAT16.ASM@ 39

Last change on this file since 39 was 38, checked in by Ben Rietbroek, 12 years ago

Converting to JWasm -- phase #1 (not working) [2012-02-15]

WARNING!!

All commits upto and including the commit of [2012-05-13] contain
a severe bug!! Building from these sources and then disabling
the 'force LBA' feature while also using the drive-letter feature or
editing the label can DESTROY THE MBR on ALL ATTACHED DISKS!!
DO NOT DISABLE 'FORCE LBA USAGE' WHEN BUILT FROM THE THESE COMMITS!!

Problems

o WLink generates an oversized image
o Only Tasm with TLink works correctly

File size: 12.3 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 ModuleNames
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 DriveIO_DAP_Absolute, edx ; Read in Boot-Record of partition
45 mov DriveIO_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 DriveIO_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 DriveIO_DAP_Transfer, eax ; Transfer to that segment
82 mov eax, FAT16_AbsRootBegin
83 mov DriveIO_DAP_Absolute, eax ; Read in Root-Entries...
84 mov ax, FAT16_NumOfRootEntries
85 shr ax, 4 ; NumOfRootEntries/16
86 mov DriveIO_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 di
106 mov cx, 11
107 repe cmpsb ; Compare total 11-bytes
108 pop di si
109 je FAT16SE_EntryFound
110 add di, 32 ; Skip 1 FAT16-Entry now :)
111 dec bx
112 jnz FAT16SE_SearchLoop
113 FAT16SE_NoEntries:
114 ret
115
116 FAT16SE_EntryFound:
117 mov dx, wptr es:[di+26] ; Starting Cluster of Entry
118 ret
119FAT16_SearchEntry EndP
120
121; Reads a Cluster and gets Next-Cluster as well...
122; In: DX - Cluster-Number to load, DAP_Transfer-Offset filled out
123; ES - Segment, where to read Cluster to
124; DI - Offset, where to read Cluster to
125; Out: DX - Cluster that follows this one, [ES:DI] filled out
126; DI - Offset, adjusted
127; Destroyed: None
128FAT16_ReadCluster Proc Near Uses eax bx
129 push dx
130 ; First read Cluster into buffer...
131 mov ax, es
132 shl eax, 16
133 mov ax, di
134 mov DriveIO_DAP_Transfer, eax ; Read to 9000:DI
135 mov ax, dx
136 sub ax, 2 ; Everything starts at Cluster 2
137 ;movzx bx, FAT16_SecsPerCluster
138 mov bl,FAT16_SecsPerCluster
139 mov bh,0
140
141 mul bx
142 shl edx, 16
143 mov dx, ax ; EDX - Relative to Cluster-Start
144 add edx, FAT16_AbsClusterBegin ; EDX - Absolute Sector Count
145 mov DriveIO_DAP_Absolute, edx
146 mov DriveIO_DAP_NumBlocks, bx ; Get a whole cluster
147 call FAT16_LoadSectors ; DONE.
148 pop dx
149 ; Update DI to next position...
150 mov al, FAT16_SecsPerCluster
151 shl ax, 9
152 add di, ax
153 ; Finally, look for next Cluster following to this one...
154 ;movzx bx, dl
155 mov bl,dl
156 mov bh,0
157
158 shl bx, 1 ; BX - Offset within FAT-Table
159 shr dx, 8 ; DX - FAT-Sector
160 cmp dl, FAT16_FATCacheSector
161 je FAT16RC_GotFATsectorAlready
162 ; Load FAT-Sector, because the required one is not in Cache
163 mov FAT16_FATCacheSector, dl
164 mov ax, cs
165 shl eax, 16
166 mov ax, offset FAT16_FATCache
167 mov DriveIO_DAP_Transfer, eax ; Transfer to FAT-Cache Area
168 movzx edx, dx
169 mov eax, FAT16_AbsFATBegin
170 add eax, edx
171 mov DriveIO_DAP_Absolute, eax ; Read in Boot-Record of partition
172 mov DriveIO_DAP_NumBlocks, 1 ; 1 Sector to load
173 call FAT16_LoadSectors ; DONE.
174 FAT16RC_GotFATsectorAlready:
175 mov dx, wptr cs:[FAT16_FATCache+bx] ; Get Next-Cluster Pointer
176 ret
177FAT16_ReadCluster EndP
178
179; Preserves all registers, help routine for LoadKernel
180; supports more than 1 sector read (unlike MBR_IO_LoadSector)
181FAT16_LoadSectors Proc Near Uses eax dx ds si
182 push cs
183 pop ds
184 mov si, offset DriveIO_DAP
185 mov dl, ds:[FAT16_Drive]
186 mov ah, 42h ; Extended Read
187 int 13h
188 jnc FAT16LS_Success
189 call MBR_LoadError
190
191 FAT16LS_Success:
192 movzx eax, wptr ds:[DriveIO_DAP_NumBlocks]
193 add dptr ds:[DriveIO_DAP_Absolute+0], eax ; Adjust Absolute Offset
194 ret
195FAT16_LoadSectors EndP
196
197; Will Pre-Process Directory loaded to 9000:0, remove directory and VFAT
198; entries for display purpose in window
199; In: DI - Ending-Offset of Directory
200; ES == CS
201; Out: None
202; Destroyed: None
203FAT16_ProcessKrnlDirectory Proc Near Uses ds si es di
204 mov dx, di ; DX - Ending-Offset of Directory
205 mov ax, 9000h
206 mov ds, ax ; DS == 9000h
207 xor si, si ; SI - Current Pos in Directory
208 mov di, offset LINUX_KernelEntries ; DI - Array of Kernel-Entries
209 mov cs:[LINUX_KernelNo], 0
210 FAT16PPD_DirectoryLoop:
211 mov al, ds:[si] ; +0 -> First char of Basename
212 or al, al
213 jz FAT16PPD_IgnoreEntry ; == 0, empty
214 cmp al, 0E5h
215 je FAT16PPD_IgnoreEntry ; == E5, deleted
216 mov al, ds:[si+11] ; +11 -> Flags of Entry
217 cmp al, 0Fh ; 0F as flags -> VFAT Entry
218 je FAT16PPD_IgnoreEntry
219 test al, 18h ; Bit 4 -> Directory
220 jnz FAT16PPD_IgnoreEntry ; Bit 3 -> Volume
221
222 ; Set Size-Entry in KernelSizeTable
223 push ds si di
224 mov bx, ds:[si+30]
225 mov ax, ds:[si+28] ; BX:AX - Size of file in Bytes
226
227 mov dx, bx
228 and dx, 511 ; My crazy way of dividing a 32-bit
229 shr ax, 9 ; value through 512 using 16-bit
230 shr bx, 9 ; instructions... :)
231 shl dx, 7 ; (dont ever ever use a DIV)
232 or ax, dx ; BX:AX - Size of file in 512-blocks
233
234 push cs
235 pop ds ; DS==CS for GetSizeElementPtr
236 push ax
237 mov ax, di
238 call PART_GetSizeElementPointer ; SI - Pointer to Size Element
239 pop ax
240 mov di, si
241 call PART_FillOutSizeElement ; BX:AX -> ES:DI (Size Element)
242 pop di si ds
243
244 ; Copy entry and make append extension to basename
245 ; "TEST TMP" -> "TESTTMP "
246 mov bx, 7
247 FAT16PPD_GetLenOfBasename:
248 cmp bptr ds:[si+bx], ' '
249 jne FAT16PPD_EndOfBasename
250 dec bx
251 jnz FAT16PPD_GetLenOfBasename
252 FAT16PPD_EndOfBasename:
253 mov ah, bl
254 inc ah ; AH - Count of Basename Chars (max 8)
255 mov bx, 10
256 FAT16PPD_GetLenOfExtension:
257 cmp bptr ds:[si+bx], ' '
258 jne FAT16PPD_EndOfExtension
259 dec bl
260 cmp bl, 7
261 ja FAT16PPD_GetLenOfExtension
262 FAT16PPD_EndOfExtension:
263 sub bl, 7 ; BL - Count of Extension Chars (max 3)
264 ; Now we will copy&fill out 11 characters (Basename&Extension)
265 push dx
266 push ax
267 xor eax, eax
268 stosd ; +0 [DWORD] Empty Serial
269 pop ax
270 mov dx, si
271 ;movzx cx, ah
272 mov cl,ah
273 mov ch,0
274
275 rep movsb
276 mov si, dx ; Restore SI
277 add si, 8
278 or bl, bl
279 jz FAT16PPD_NoExtensionCopy
280 mov cl, bl
281 rep movsb
282 FAT16PPD_NoExtensionCopy:
283 add ah, bl ; AH - Total Bytes of BaseName
284 mov cl, 11
285 mov al, ' '
286 sub cl, ah
287 jz FAT16PPD_NoFillUpName
288 rep stosb ; +4 [STR*11] Label
289 FAT16PPD_NoFillUpName:
290 mov si, dx ; Restore SI
291
292 mov al, FAT16_Drive
293 mov ah, 0FDh
294 stosw ; +15 [BYTE/BYTE] Drive, SystemID
295 xor ax, ax
296 stosb ; +17 [BYTE] Flags
297 stosw ; +18 [WORD] CRC
298 mov ax, wptr ds:[si+26] ; Starting Cluster of File
299 stosw
300 xor ax, ax
301 stosb ; +20 [BYTE/BYTE/BYTE] Location Begin
302 stosw
303 stosb ; +23 [BYTE/BYTE/BYTE] Location Part
304 mov cx, 4
305 rep stosw ; +26 [DWORD/DWORD] Abs Locations
306 pop dx
307 inc cs:[LINUX_KernelNo]
308 FAT16PPD_IgnoreEntry:
309 add si, 32
310 cmp si, dx ; We are at Ending-Offset ?
311 jb FAT16PPD_DirectoryLoop
312 ; Done, now we got a maximum of 20 kernels in LINUX_KernelEntries-Array.
313 ret
314FAT16_ProcessKrnlDirectory EndP
Note: See TracBrowser for help on using the repository browser.