3 * Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define FS_DO_ERROR(s) \
28 if (UserInterfaceUp) \
33 printf("\nPress any key\n"); \
39 int nSectorBuffered
= -1; // Tells us which sector was read into SectorBuffer[]
41 BYTE SectorBuffer
[512]; // 512 byte buffer space for read operations, ReadOneSector reads to here
43 int FSType
= NULL
; // Type of filesystem on boot device, set by OpenDiskDrive()
45 char *pFileSysData
= (char *)(FILESYSADDR
); // Load address for filesystem data
46 char *pFat32FATCacheIndex
= (char *)(FILESYSADDR
); // Load address for filesystem data
48 BOOL
OpenDiskDrive(int nDrive
, int nPartition
)
50 int num_bootable_partitions
= 0;
51 int boot_partition
= 0;
52 int partition_type
= 0;
53 int head
, sector
, cylinder
;
56 // Check and see if it is a floppy drive
60 if (!biosdisk(_DISK_READ
, nDrive
, 0, 0, 1, 1, SectorBuffer
))
62 FS_DO_ERROR("Disk Read Error");
67 if (*((WORD
*)(SectorBuffer
+ 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA))
69 FS_DO_ERROR("Invalid boot sector magic (0xaa55)");
75 // Read master boot record
76 if (!biosdisk(_DISK_READ
, nDrive
, 0, 0, 1, 1, SectorBuffer
))
78 FS_DO_ERROR("Disk Read Error");
83 if (*((WORD
*)(SectorBuffer
+ 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA))
85 FS_DO_ERROR("Invalid partition table magic (0xaa55)");
91 // Check for bootable partitions
92 if (SectorBuffer
[0x1BE] == 0x80)
93 num_bootable_partitions
++;
94 if (SectorBuffer
[0x1CE] == 0x80)
96 num_bootable_partitions
++;
99 if (SectorBuffer
[0x1DE] == 0x80)
101 num_bootable_partitions
++;
104 if (SectorBuffer
[0x1EE] == 0x80)
106 num_bootable_partitions
++;
110 // Make sure there was only one bootable partition
111 if (num_bootable_partitions
> 1)
113 FS_DO_ERROR("Too many boot partitions");
117 offset
= 0x1BE + (boot_partition
* 0x10);
120 offset
= 0x1BE + ((nPartition
-1) * 0x10);
122 partition_type
= SectorBuffer
[offset
+ 4];
124 // Check for valid partition
125 if (partition_type
== 0)
127 FS_DO_ERROR("Invalid boot partition");
131 head
= SectorBuffer
[offset
+ 1];
132 sector
= (SectorBuffer
[offset
+ 2] & 0x3F);
133 cylinder
= SectorBuffer
[offset
+ 3];
134 if (SectorBuffer
[offset
+ 2] & 0x80)
136 if (SectorBuffer
[offset
+ 2] & 0x40)
139 // Read partition boot sector
140 if (!biosdisk(_DISK_READ
, nDrive
, head
, cylinder
, sector
, 1, SectorBuffer
))
142 FS_DO_ERROR("Disk Read Error");
146 // Check for validity
147 if (*((WORD
*)(SectorBuffer
+ 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA))
149 FS_DO_ERROR("Invalid boot sector magic (0xaa55)");
157 nSectorsPerCluster
= 0;
158 nReservedSectors
= 0;
162 nSectorsPerFAT16
= 0;
163 nSectorsPerTrack
= 0;
168 nSectorsPerFAT32
= 0;
170 nFileSystemVersion
= 0;
171 nRootDirStartCluster
= 0;
173 nRootDirSectorStart
= 0;
174 nDataSectorStart
= 0;
178 nNumberOfClusters
= 0;
181 memcpy(&nBytesPerSector
, SectorBuffer
+ BPB_BYTESPERSECTOR
, 2);
182 memcpy(&nSectorsPerCluster
, SectorBuffer
+ BPB_SECTORSPERCLUSTER
, 1);
183 memcpy(&nReservedSectors
, SectorBuffer
+ BPB_RESERVEDSECTORS
, 2);
184 memcpy(&nNumberOfFATs
, SectorBuffer
+ BPB_NUMBEROFFATS
, 1);
185 memcpy(&nRootDirEntries
, SectorBuffer
+ BPB_ROOTDIRENTRIES
, 2);
186 memcpy(&nTotalSectors16
, SectorBuffer
+ BPB_TOTALSECTORS16
, 2);
187 memcpy(&nSectorsPerFAT16
, SectorBuffer
+ BPB_SECTORSPERFAT16
, 2);
188 memcpy(&nSectorsPerTrack
, SectorBuffer
+ BPB_SECTORSPERTRACK
, 2);
189 memcpy(&nNumberOfHeads
, SectorBuffer
+ BPB_NUMBEROFHEADS
, 2);
190 memcpy(&nHiddenSectors
, SectorBuffer
+ BPB_HIDDENSECTORS
, 4);
191 memcpy(&nTotalSectors32
, SectorBuffer
+ BPB_TOTALSECTORS32
, 4);
193 memcpy(&nSectorsPerFAT32
, SectorBuffer
+ BPB_SECTORSPERFAT32
, 4);
194 memcpy(&nExtendedFlags
, SectorBuffer
+ BPB_EXTENDEDFLAGS32
, 2);
195 memcpy(&nFileSystemVersion
, SectorBuffer
+ BPB_FILESYSTEMVERSION32
, 2);
196 memcpy(&nRootDirStartCluster
, SectorBuffer
+ BPB_ROOTDIRSTARTCLUSTER32
, 4);
199 if (nTotalSectors16
!= 0)
200 nTotalSectors
= nTotalSectors16
;
202 nTotalSectors
= nTotalSectors32
;
204 if (nSectorsPerFAT16
!= 0)
205 nSectorsPerFAT
= nSectorsPerFAT16
;
207 nSectorsPerFAT
= nSectorsPerFAT32
;
209 nRootDirSectorStart
= (nNumberOfFATs
* nSectorsPerFAT
) + nReservedSectors
;
210 nRootDirSectors
= ((nRootDirEntries
* 32) + (nBytesPerSector
- 1)) / nBytesPerSector
;
211 nDataSectorStart
= nReservedSectors
+ (nNumberOfFATs
* nSectorsPerFAT
) + nRootDirSectors
;
212 nNumberOfClusters
= (nTotalSectors
- nDataSectorStart
) / nSectorsPerCluster
;
214 // Determine FAT type
215 if (nNumberOfClusters
< 4085)
217 /* Volume is FAT12 */
220 else if (nNumberOfClusters
< 65525)
222 /* Volume is FAT16 */
227 /* Volume is FAT32 */
231 // we only work with version 0
232 if (*((WORD
*)(SectorBuffer
+ BPB_FILESYSTEMVERSION32
)) != 0)
234 FS_DO_ERROR("Error: FreeLoader is too old to work with this FAT32 filesystem.\nPlease update FreeLoader.");
241 // Buffer the FAT table if it is small enough
242 if ((FSType
== FS_FAT
) && (nFATType
== FAT12
))
244 if (!ReadMultipleSectors(nReservedSectors
, nSectorsPerFAT
, pFileSysData
))
247 else if ((FSType
== FS_FAT
) && (nFATType
== FAT16
))
249 if (!ReadMultipleSectors(nReservedSectors
, nSectorsPerFAT
, pFileSysData
))
252 else if ((FSType
== FS_FAT
) && (nFATType
== FAT32
))
254 // The FAT table is too big to be buffered so
255 // we will initialize our cache and cache it
257 for (offset
=0; offset
<256; offset
++)
258 ((int*)pFat32FATCacheIndex
)[offset
] = -1;
264 BOOL
ReadMultipleSectors(int nSect
, int nNumberOfSectors
, void *pBuffer
)
272 nSect
+= nHiddenSectors
;
274 while (nNumberOfSectors
)
276 PhysicalSector
= 1 + (nSect
% nSectorsPerTrack
);
277 PhysicalHead
= (nSect
/ nSectorsPerTrack
) % nNumberOfHeads
;
278 PhysicalTrack
= nSect
/ (nSectorsPerTrack
* nNumberOfHeads
);
280 if (PhysicalSector
> 1)
282 if (nNumberOfSectors
>= (nSectorsPerTrack
- (PhysicalSector
- 1)))
283 nNum
= (nSectorsPerTrack
- (PhysicalSector
- 1));
285 nNum
= nNumberOfSectors
;
289 if (nNumberOfSectors
>= nSectorsPerTrack
)
290 nNum
= nSectorsPerTrack
;
292 nNum
= nNumberOfSectors
;
295 bRetVal
= biosdisk(_DISK_READ
, BootDrive
, PhysicalHead
, PhysicalTrack
, PhysicalSector
, nNum
, pBuffer
);
299 FS_DO_ERROR("Disk Error");
303 pBuffer
+= (nNum
* 512);
304 nNumberOfSectors
-= nNum
;
311 BOOL
ReadOneSector(int nSect
)
318 nSectorBuffered
= nSect
;
320 nSect
+= nHiddenSectors
;
321 PhysicalSector
= 1 + (nSect
% nSectorsPerTrack
);
322 PhysicalHead
= (nSect
/ nSectorsPerTrack
) % nNumberOfHeads
;
323 PhysicalTrack
= nSect
/ (nSectorsPerTrack
* nNumberOfHeads
);
326 bRetVal
= biosdisk(_DISK_READ
, BootDrive
, PhysicalHead
, PhysicalTrack
, PhysicalSector
, 1, SectorBuffer
);
330 FS_DO_ERROR("Disk Error");
337 BOOL
OpenFile(char *filename
, FILE *pFile
)
342 if(!FATOpenFile(filename
, &(pFile
->fat
)))
344 pFile
->filesize
= pFile
->fat
.dwSize
;
347 FS_DO_ERROR("Error: Unknown filesystem.");
357 * returns number of bytes read or EOF
359 int ReadFile(FILE *pFile
, int count
, void *buffer
)
364 return FATRead(&(pFile
->fat
), count
, buffer
);
366 FS_DO_ERROR("Error: Unknown filesystem.");
373 DWORD
GetFileSize(FILE *pFile
)
375 return pFile
->filesize
;
378 DWORD
Rewind(FILE *pFile
)
383 pFile
->fat
.dwCurrentCluster
= pFile
->fat
.dwStartCluster
;
384 pFile
->fat
.dwCurrentReadOffset
= 0;
387 FS_DO_ERROR("Error: Unknown filesystem.");
391 return pFile
->filesize
;
394 int feof(FILE *pFile
)
399 if (pFile
->fat
.dwCurrentReadOffset
>= pFile
->fat
.dwSize
)
405 FS_DO_ERROR("Error: Unknown filesystem.");
413 int fseek(FILE *pFile
, DWORD offset
)
418 return FATfseek(&(pFile
->fat
), offset
);
421 FS_DO_ERROR("Error: Unknown filesystem.");