3 * Copyright (C) 1998-2002 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.
31 /////////////////////////////////////////////////////////////////////////////////////////////
33 /////////////////////////////////////////////////////////////////////////////////////////////
35 ULONG FileSystemType
= 0; // Type of filesystem on boot device, set by OpenDiskDrive()
37 /////////////////////////////////////////////////////////////////////////////////////////////
39 /////////////////////////////////////////////////////////////////////////////////////////////
41 VOID
FileSystemError(PUCHAR ErrorString
)
43 DbgPrint((DPRINT_FILESYSTEM
, "%s\n", ErrorString
));
47 MessageBox(ErrorString
);
51 printf("%s", ErrorString
);
52 printf("\nPress any key\n");
59 * BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber);
61 * This function is called to open a disk drive for file access.
62 * It must be called before any of the file functions will work.
63 * It takes two parameters:
65 * Drive: The BIOS drive number of the disk to open
66 * Partition: This is zero for floppy drives.
67 * If the disk is a hard disk then this specifies
68 * The partition number to open (1 - 4)
69 * If it is zero then it opens the active (bootable) partition
72 BOOL
OpenDiskDrive(ULONG DriveNumber
, ULONG PartitionNumber
)
74 MASTER_BOOT_RECORD DriveMasterBootRecord
;
75 PARTITION_TABLE_ENTRY PartitionTableEntry
;
77 DbgPrint((DPRINT_FILESYSTEM
, "OpenDiskDrive() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber
, PartitionNumber
));
79 // Check and see if it is a floppy drive
80 // If so then just assume FAT12 file system type
81 if (FsInternalIsDiskPartitioned(DriveNumber
) == FALSE
)
83 DbgPrint((DPRINT_FILESYSTEM
, "Drive is a floppy diskette drive. Assuming FAT12 file system.\n"));
85 FileSystemType
= FS_FAT
;
86 return FatOpenVolume(DriveNumber
, 0);
90 // Read master boot record
92 if (!BiosInt13Read(DriveNumber
, 0, 0, 1, 1, &DriveMasterBootRecord
))
94 FileSystemError("Disk read error.");
101 DbgPrint((DPRINT_FILESYSTEM
, "Drive is a hard disk, dumping partition table:\n"));
102 DbgPrint((DPRINT_FILESYSTEM
, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD
)));
104 for (BootPartition
=0; BootPartition
<4; BootPartition
++)
106 DbgPrint((DPRINT_FILESYSTEM
, "-------------------------------------------\n"));
107 DbgPrint((DPRINT_FILESYSTEM
, "Partition %d\n", (BootPartition
+ 1)));
108 DbgPrint((DPRINT_FILESYSTEM
, "BootIndicator: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].BootIndicator
));
109 DbgPrint((DPRINT_FILESYSTEM
, "StartHead: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].StartHead
));
110 DbgPrint((DPRINT_FILESYSTEM
, "StartSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].StartSector
));
111 DbgPrint((DPRINT_FILESYSTEM
, "StartCylinder: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].StartCylinder
));
112 DbgPrint((DPRINT_FILESYSTEM
, "SystemIndicator: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].SystemIndicator
));
113 DbgPrint((DPRINT_FILESYSTEM
, "EndHead: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].EndHead
));
114 DbgPrint((DPRINT_FILESYSTEM
, "EndSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].EndSector
));
115 DbgPrint((DPRINT_FILESYSTEM
, "EndCylinder: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].EndCylinder
));
116 DbgPrint((DPRINT_FILESYSTEM
, "SectorCountBeforePartition: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].SectorCountBeforePartition
));
117 DbgPrint((DPRINT_FILESYSTEM
, "PartitionSectorCount: 0x%x\n", DriveMasterBootRecord
.PartitionTable
[BootPartition
].PartitionSectorCount
));
120 #endif // defined DEBUG
123 // Check the partition table magic value
124 if (DriveMasterBootRecord
.MasterBootRecordMagic
!= 0xaa55)
126 FileSystemError("Invalid partition table magic (0xaa55)");
130 // Get the requested partition entry
131 if (PartitionNumber
== 0)
133 // Partition requested was zero which means the boot partition
134 if (FsInternalGetActivePartitionEntry(DriveNumber
, &PartitionTableEntry
) == FALSE
)
141 // Get requested partition
142 if (FsInternalGetPartitionEntry(DriveNumber
, PartitionNumber
, &PartitionTableEntry
) == FALSE
)
148 // Check for valid partition
149 if (PartitionTableEntry
.SystemIndicator
== PARTITION_ENTRY_UNUSED
)
151 FileSystemError("Invalid partition.");
155 switch (PartitionTableEntry
.SystemIndicator
)
157 case PARTITION_FAT_12
:
158 case PARTITION_FAT_16
:
160 case PARTITION_XINT13
:
161 case PARTITION_FAT32
:
162 case PARTITION_FAT32_XINT13
:
163 FileSystemType
= FS_FAT
;
164 return FatOpenVolume(DriveNumber
, PartitionTableEntry
.SectorCountBeforePartition
);
167 FileSystemError("Unsupported file system.");
174 BOOL
FsInternalIsDiskPartitioned(ULONG DriveNumber
)
176 // Hard disks use drive numbers >= 0x80
177 // So if the drive number indicates a hard disk
179 if (DriveNumber
>= 0x80)
184 // Drive is a floppy diskette so return FALSE
188 BOOL
FsInternalGetActivePartitionEntry(ULONG DriveNumber
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
190 ULONG BootablePartitionCount
= 0;
191 MASTER_BOOT_RECORD MasterBootRecord
;
193 // Read master boot record
194 if (!BiosInt13Read(DriveNumber
, 0, 0, 1, 1, &MasterBootRecord
))
196 FileSystemError("Disk read error.");
200 // Count the bootable partitions
201 if (MasterBootRecord
.PartitionTable
[0].BootIndicator
== 0x80)
203 BootablePartitionCount
++;
206 if (MasterBootRecord
.PartitionTable
[1].BootIndicator
== 0x80)
208 BootablePartitionCount
++;
211 if (MasterBootRecord
.PartitionTable
[2].BootIndicator
== 0x80)
213 BootablePartitionCount
++;
216 if (MasterBootRecord
.PartitionTable
[3].BootIndicator
== 0x80)
218 BootablePartitionCount
++;
222 // Make sure there was only one bootable partition
223 if (BootablePartitionCount
!= 1)
225 FileSystemError("Too many bootable partitions or none found.");
229 // Copy the partition table entry
230 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
.PartitionTable
[BootPartition
], sizeof(PARTITION_TABLE_ENTRY
));
235 BOOL
FsInternalGetPartitionEntry(ULONG DriveNumber
, ULONG PartitionNumber
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
237 MASTER_BOOT_RECORD MasterBootRecord
;
239 // Read master boot record
240 if (!BiosInt13Read(DriveNumber
, 0, 0, 1, 1, &MasterBootRecord
))
242 FileSystemError("Disk read error.");
246 // PartitionNumber is one-based and we need it zero-based
249 // Copy the partition table entry
250 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
.PartitionTable
[PartitionNumber
], sizeof(PARTITION_TABLE_ENTRY
));
255 PFILE
OpenFile(PUCHAR FileName
)
257 PFILE FileHandle
= NULL
;
260 // Print status message
262 DbgPrint((DPRINT_FILESYSTEM
, "Opening file '%s'...\n", FileName
));
265 // Check file system type and pass off to appropriate handler
267 if (FileSystemType
== FS_FAT
)
269 FileHandle
= FatOpenFile(FileName
);
273 FileSystemError("Error: Unknown filesystem.");
278 // Check return value
280 if (FileHandle
!= NULL
)
282 DbgPrint((DPRINT_FILESYSTEM
, "OpenFile() succeeded. FileHandle: 0x%x\n", FileHandle
));
286 DbgPrint((DPRINT_FILESYSTEM
, "OpenFile() failed.\n"));
288 #endif // defined DEBUG
293 VOID
CloseFile(PFILE FileHandle
)
299 * returns number of bytes read or EOF
301 BOOL
ReadFile(PFILE FileHandle
, ULONG BytesToRead
, PULONG BytesRead
, PVOID Buffer
)
304 // Set the number of bytes read equal to zero
306 if (BytesRead
!=NULL
)
311 switch (FileSystemType
)
315 return FatReadFile(FileHandle
, BytesToRead
, BytesRead
, Buffer
);
319 FileSystemError("Unknown file system.");
326 ULONG
GetFileSize(PFILE FileHandle
)
328 switch (FileSystemType
)
332 return FatGetFileSize(FileHandle
);
335 FileSystemError("Unknown file system.");
342 VOID
SetFilePointer(PFILE FileHandle
, ULONG NewFilePointer
)
344 switch (FileSystemType
)
348 FatSetFilePointer(FileHandle
, NewFilePointer
);
352 FileSystemError("Unknown file system.");
357 ULONG
GetFilePointer(PFILE FileHandle
)
359 switch (FileSystemType
)
363 return FatGetFilePointer(FileHandle
);
367 FileSystemError("Unknown file system.");
374 BOOL
IsEndOfFile(PFILE FileHandle
)
376 if (GetFilePointer(FileHandle
) >= GetFileSize(FileHandle
))