3 * Copyright (C) 1999, 2000, 2001 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.
29 /////////////////////////////////////////////////////////////////////////////////////////////
31 /////////////////////////////////////////////////////////////////////////////////////////////
33 GEOMETRY DriveGeometry
;
34 ULONG VolumeHiddenSectors
;
35 ULONG CurrentlyOpenDriveNumber
;
36 ULONG FileSystemType
= 0; // Type of filesystem on boot device, set by OpenDiskDrive()
38 /////////////////////////////////////////////////////////////////////////////////////////////
40 /////////////////////////////////////////////////////////////////////////////////////////////
42 VOID
FileSystemError(PUCHAR ErrorString
)
44 DbgPrint((DPRINT_FILESYSTEM
, "%s\n", ErrorString
));
48 MessageBox(ErrorString
);
52 printf("%s", ErrorString
);
53 printf("\nPress any key\n");
60 * BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber);
62 * This function is called to open a disk drive for file access.
63 * It must be called before any of the file functions will work.
64 * It takes two parameters:
66 * Drive: The BIOS drive number of the disk to open
67 * Partition: This is zero for floppy drives.
68 * If the disk is a hard disk then this specifies
69 * The partition number to open (1 - 4)
70 * If it is zero then it opens the active (bootable) partition
73 BOOL
OpenDiskDrive(ULONG DriveNumber
, ULONG PartitionNumber
)
75 ULONG BootablePartitionCount
= 0;
76 ULONG BootPartition
= 0;
77 ULONG PartitionStartHead
;
78 ULONG PartitionStartSector
;
79 ULONG PartitionStartCylinder
;
80 MASTER_BOOT_RECORD DriveMasterBootRecord
;
82 DbgPrint((DPRINT_FILESYSTEM
, "OpenDiskDrive() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber
, PartitionNumber
));
84 CurrentlyOpenDriveNumber
= DriveNumber
;
87 // Check and see if it is a floppy drive
88 // If so then just assume FAT12 file system type
90 if (DriveNumber
< 0x80)
92 DbgPrint((DPRINT_FILESYSTEM
, "Drive is a floppy diskette drive. Assuming FAT12 file system.\n"));
94 FileSystemType
= FS_FAT
;
95 return FatOpenVolume(DriveNumber
, 0, 0, 1, FAT12
);
99 // Read master boot record
101 if (!BiosInt13Read(DriveNumber
, 0, 0, 1, 1, &DriveMasterBootRecord
))
103 FileSystemError("Disk read error.");
110 DbgPrint((DPRINT_FILESYSTEM
, "Drive is a hard disk, dumping partition table:\n"));
111 DbgPrint((DPRINT_FILESYSTEM
, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD
)));
113 for (BootPartition
=0; BootPartition
<4; BootPartition
++)
115 DbgPrint((DPRINT_FILESYSTEM
, "-------------------------------------------\n"));
116 DbgPrint((DPRINT_FILESYSTEM
, "Partition %d\n", (BootPartition
+ 1)));
117 DbgPrint((DPRINT_FILESYSTEM
, "BootIndicator: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].BootIndicator
));
118 DbgPrint((DPRINT_FILESYSTEM
, "StartHead: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].StartHead
));
119 DbgPrint((DPRINT_FILESYSTEM
, "StartSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].StartSector
));
120 DbgPrint((DPRINT_FILESYSTEM
, "StartCylinder: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].StartCylinder
));
121 DbgPrint((DPRINT_FILESYSTEM
, "SystemIndicator: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].SystemIndicator
));
122 DbgPrint((DPRINT_FILESYSTEM
, "EndHead: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].EndHead
));
123 DbgPrint((DPRINT_FILESYSTEM
, "EndSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].EndSector
));
124 DbgPrint((DPRINT_FILESYSTEM
, "EndCylinder: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].EndCylinder
));
125 DbgPrint((DPRINT_FILESYSTEM
, "SectorCountBeforePartition: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].SectorCountBeforePartition
));
126 DbgPrint((DPRINT_FILESYSTEM
, "PartitionSectorCount: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].PartitionSectorCount
));
129 #endif // defined DEBUG
133 // Check the partition table magic value
135 if (DriveMasterBootRecord
.MasterBootRecordMagic
!= 0xaa55)
137 FileSystemError("Invalid partition table magic (0xaa55)");
141 if (PartitionNumber
== 0)
144 // Count the bootable partitions
146 if (DriveMasterBootRecord
.PartitionTable
[0].BootIndicator
== 0x80)
148 BootablePartitionCount
++;
151 if (DriveMasterBootRecord
.PartitionTable
[1].BootIndicator
== 0x80)
153 BootablePartitionCount
++;
156 if (DriveMasterBootRecord
.PartitionTable
[2].BootIndicator
== 0x80)
158 BootablePartitionCount
++;
161 if (DriveMasterBootRecord
.PartitionTable
[3].BootIndicator
== 0x80)
163 BootablePartitionCount
++;
168 // Make sure there was only one bootable partition
170 if (BootablePartitionCount
!= 1)
172 FileSystemError("Too many bootable partitions or none found.");
178 // We found the boot partition, so set the partition number
180 PartitionNumber
= BootPartition
;
185 // Right now the partition number is one-based
186 // and we need zero based
191 // Check for valid partition
193 if (DriveMasterBootRecord
.PartitionTable
[PartitionNumber
].SystemIndicator
== PARTITION_ENTRY_UNUSED
)
195 FileSystemError("Invalid partition.");
199 PartitionStartHead
= DriveMasterBootRecord
.PartitionTable
[PartitionNumber
].StartHead
;
200 PartitionStartSector
= DriveMasterBootRecord
.PartitionTable
[PartitionNumber
].StartSector
& 0x3F;
201 PartitionStartCylinder
= MAKE_CYLINDER(
202 DriveMasterBootRecord
.PartitionTable
[PartitionNumber
].StartCylinder
,
203 DriveMasterBootRecord
.PartitionTable
[PartitionNumber
].StartSector
);
205 DbgPrint((DPRINT_FILESYSTEM
, "PartitionStartHead: %d\n", PartitionStartHead
));
206 DbgPrint((DPRINT_FILESYSTEM
, "PartitionStartSector: %d\n", PartitionStartSector
));
207 DbgPrint((DPRINT_FILESYSTEM
, "PartitionStartCylinder: %d\n", PartitionStartCylinder
));
208 DbgPrint((DPRINT_FILESYSTEM
, "PartitionNumber: %d\n", PartitionNumber
));
210 switch (DriveMasterBootRecord
.PartitionTable
[PartitionNumber
].SystemIndicator
)
212 case PARTITION_FAT_12
:
213 FileSystemType
= FS_FAT
;
214 return FatOpenVolume(DriveNumber
, PartitionStartHead
, PartitionStartCylinder
, PartitionStartSector
, FAT12
);
215 case PARTITION_FAT_16
:
217 case PARTITION_XINT13
:
218 FileSystemType
= FS_FAT
;
219 return FatOpenVolume(DriveNumber
, PartitionStartHead
, PartitionStartCylinder
, PartitionStartSector
, FAT16
);
220 case PARTITION_FAT32
:
221 case PARTITION_FAT32_XINT13
:
222 FileSystemType
= FS_FAT
;
223 return FatOpenVolume(DriveNumber
, PartitionStartHead
, PartitionStartCylinder
, PartitionStartSector
, FAT32
);
226 FileSystemError("Unsupported file system.");
233 VOID
SetDriveGeometry(ULONG Cylinders
, ULONG Heads
, ULONG Sectors
, ULONG BytesPerSector
)
235 DriveGeometry
.Cylinders
= Cylinders
;
236 DriveGeometry
.Heads
= Heads
;
237 DriveGeometry
.Sectors
= Sectors
;
238 DriveGeometry
.BytesPerSector
= BytesPerSector
;
240 DbgPrint((DPRINT_FILESYSTEM
, "DriveGeometry.Cylinders: %d\n", DriveGeometry
.Cylinders
));
241 DbgPrint((DPRINT_FILESYSTEM
, "DriveGeometry.Heads: %d\n", DriveGeometry
.Heads
));
242 DbgPrint((DPRINT_FILESYSTEM
, "DriveGeometry.Sectors: %d\n", DriveGeometry
.Sectors
));
243 DbgPrint((DPRINT_FILESYSTEM
, "DriveGeometry.BytesPerSector: %d\n", DriveGeometry
.BytesPerSector
));
246 VOID
SetVolumeProperties(ULONG HiddenSectors
)
248 VolumeHiddenSectors
= HiddenSectors
;
251 BOOL
ReadMultipleLogicalSectors(ULONG SectorNumber
, ULONG SectorCount
, PVOID Buffer
)
259 nSect += nHiddenSectors;
261 while (nNumberOfSectors)
263 PhysicalSector = 1 + (nSect % nSectorsPerTrack);
264 PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads;
265 PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads);
267 if (PhysicalSector > 1)
269 if (nNumberOfSectors >= (nSectorsPerTrack - (PhysicalSector - 1)))
270 nNum = (nSectorsPerTrack - (PhysicalSector - 1));
272 nNum = nNumberOfSectors;
276 if (nNumberOfSectors >= nSectorsPerTrack)
277 nNum = nSectorsPerTrack;
279 nNum = nNumberOfSectors;
282 bRetVal = biosdisk(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
286 FS_DO_ERROR("Disk Error");
290 pBuffer += (nNum * 512);
291 nNumberOfSectors -= nNum;
296 PVOID RealBuffer
= Buffer
;
298 for (CurrentSector
=SectorNumber
; CurrentSector
<(SectorNumber
+ SectorCount
); CurrentSector
++)
300 if (!ReadLogicalSector(CurrentSector
, RealBuffer
) )
305 RealBuffer
+= DriveGeometry
.BytesPerSector
;
311 BOOL
ReadLogicalSector(ULONG SectorNumber
, PVOID Buffer
)
313 ULONG PhysicalSector
;
317 DbgPrint((DPRINT_FILESYSTEM
, "ReadLogicalSector() SectorNumber: %d Buffer: 0x%x\n", SectorNumber
, Buffer
));
319 SectorNumber
+= VolumeHiddenSectors
;
320 PhysicalSector
= 1 + (SectorNumber
% DriveGeometry
.Sectors
);
321 PhysicalHead
= (SectorNumber
/ DriveGeometry
.Sectors
) % DriveGeometry
.Heads
;
322 PhysicalTrack
= (SectorNumber
/ DriveGeometry
.Sectors
) / DriveGeometry
.Heads
;
324 //DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
325 //DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
326 //DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
327 if (PhysicalHead
>= DriveGeometry
.Heads
)
329 BugCheck((DPRINT_FILESYSTEM
, "PhysicalHead >= DriveGeometry.Heads\nPhysicalHead = %d\nDriveGeometry.Heads = %d\n", PhysicalHead
, DriveGeometry
.Heads
));
331 if (PhysicalTrack
>= DriveGeometry
.Cylinders
)
333 BugCheck((DPRINT_FILESYSTEM
, "PhysicalTrack >= DriveGeometry.Cylinders\nPhysicalTrack = %d\nDriveGeometry.Cylinders = %d\n", PhysicalTrack
, DriveGeometry
.Cylinders
));
335 if (PhysicalSector
> DriveGeometry
.Sectors
)
337 BugCheck((DPRINT_FILESYSTEM
, "PhysicalSector > DriveGeometry.Sectors\nPhysicalSector = %d\nDriveGeometry.Sectors = %d\n", PhysicalSector
, DriveGeometry
.Sectors
));
340 if ((CurrentlyOpenDriveNumber
>= 0x80) &&
341 (BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber
)) &&
342 (SectorNumber
> (DriveGeometry
.Cylinders
* DriveGeometry
.Heads
* DriveGeometry
.Sectors
)))
344 DbgPrint((DPRINT_FILESYSTEM
, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", CurrentlyOpenDriveNumber
, BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber
) ? "TRUE" : "FALSE"));
345 if ( !BiosInt13ReadExtended(CurrentlyOpenDriveNumber
, SectorNumber
, 1, Buffer
) )
347 FileSystemError("Disk read error.");
353 if ( !BiosInt13Read(CurrentlyOpenDriveNumber
, PhysicalHead
, PhysicalTrack
, PhysicalSector
, 1, Buffer
) )
355 FileSystemError("Disk read error.");
363 PFILE
OpenFile(PUCHAR FileName
)
365 PFILE FileHandle
= NULL
;
368 // Print status message
370 DbgPrint((DPRINT_FILESYSTEM
, "Opening file '%s'...\n", FileName
));
373 // Check file system type and pass off to appropriate handler
375 if (FileSystemType
== FS_FAT
)
377 FileHandle
= FatOpenFile(FileName
);
381 FileSystemError("Error: Unknown filesystem.");
386 // Check return value
388 if (FileHandle
!= NULL
)
390 DbgPrint((DPRINT_FILESYSTEM
, "OpenFile() succeeded. FileHandle: 0x%x\n", FileHandle
));
394 DbgPrint((DPRINT_FILESYSTEM
, "OpenFile() failed.\n"));
396 #endif // defined DEBUG
401 VOID
CloseFile(PFILE FileHandle
)
407 * returns number of bytes read or EOF
409 BOOL
ReadFile(PFILE FileHandle
, ULONG BytesToRead
, PULONG BytesRead
, PVOID Buffer
)
412 // Set the number of bytes read equal to zero
414 if (BytesRead
!=NULL
)
419 switch (FileSystemType
)
423 return FatReadFile(FileHandle
, BytesToRead
, BytesRead
, Buffer
);
427 FileSystemError("Unknown file system.");
434 ULONG
GetFileSize(PFILE FileHandle
)
436 switch (FileSystemType
)
440 return FatGetFileSize(FileHandle
);
443 FileSystemError("Unknown file system.");
450 VOID
SetFilePointer(PFILE FileHandle
, ULONG NewFilePointer
)
452 switch (FileSystemType
)
456 FatSetFilePointer(FileHandle
, NewFilePointer
);
460 FileSystemError("Unknown file system.");
465 ULONG
GetFilePointer(PFILE FileHandle
)
467 switch (FileSystemType
)
471 return FatGetFilePointer(FileHandle
);
475 FileSystemError("Unknown file system.");
482 BOOL
IsEndOfFile(PFILE FileHandle
)
484 if (GetFilePointer(FileHandle
) >= GetFileSize(FileHandle
))