fdcc0f28b6057b8432d2be1cab2f1fe2c9f9d393
[reactos.git] / freeldr / freeldr / fs / fs.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
4 *
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.
9 *
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.
14 *
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.
18 */
19
20 #include <freeldr.h>
21 #include <fs.h>
22 #include "fat.h"
23 #include <disk.h>
24 #include <rtl.h>
25 #include <ui.h>
26 #include <asmcode.h>
27 #include <debug.h>
28
29
30 /////////////////////////////////////////////////////////////////////////////////////////////
31 // DATA
32 /////////////////////////////////////////////////////////////////////////////////////////////
33
34 GEOMETRY DriveGeometry;
35 ULONG VolumeHiddenSectors;
36 ULONG CurrentlyOpenDriveNumber;
37 ULONG FileSystemType = 0; // Type of filesystem on boot device, set by OpenDiskDrive()
38
39 /////////////////////////////////////////////////////////////////////////////////////////////
40 // FUNCTIONS
41 /////////////////////////////////////////////////////////////////////////////////////////////
42
43 VOID FileSystemError(PUCHAR ErrorString)
44 {
45 DbgPrint((DPRINT_FILESYSTEM, "%s\n", ErrorString));
46
47 if (UserInterfaceUp)
48 {
49 MessageBox(ErrorString);
50 }
51 else
52 {
53 printf("%s", ErrorString);
54 printf("\nPress any key\n");
55 getch();
56 }
57 }
58
59 /*
60 *
61 * BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber);
62 *
63 * This function is called to open a disk drive for file access.
64 * It must be called before any of the file functions will work.
65 * It takes two parameters:
66 *
67 * Drive: The BIOS drive number of the disk to open
68 * Partition: This is zero for floppy drives.
69 * If the disk is a hard disk then this specifies
70 * The partition number to open (1 - 4)
71 * If it is zero then it opens the active (bootable) partition
72 *
73 */
74 BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber)
75 {
76 ULONG BootablePartitionCount = 0;
77 ULONG BootPartition = 0;
78 ULONG PartitionStartHead;
79 ULONG PartitionStartSector;
80 ULONG PartitionStartCylinder;
81 MASTER_BOOT_RECORD DriveMasterBootRecord;
82
83 DbgPrint((DPRINT_FILESYSTEM, "OpenDiskDrive() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber));
84
85 CurrentlyOpenDriveNumber = DriveNumber;
86
87 //
88 // Check and see if it is a floppy drive
89 // If so then just assume FAT12 file system type
90 //
91 if (DriveNumber < 0x80)
92 {
93 DbgPrint((DPRINT_FILESYSTEM, "Drive is a floppy diskette drive. Assuming FAT12 file system.\n"));
94
95 FileSystemType = FS_FAT;
96 return FatOpenVolume(DriveNumber, 0, 0, 1, FAT12);
97 }
98
99 //
100 // Read master boot record
101 //
102 if (!BiosInt13Read(DriveNumber, 0, 0, 1, 1, &DriveMasterBootRecord))
103 {
104 FileSystemError("Disk read error.");
105 return FALSE;
106 }
107
108
109 #ifdef DEBUG
110
111 DbgPrint((DPRINT_FILESYSTEM, "Drive is a hard disk, dumping partition table:\n"));
112 DbgPrint((DPRINT_FILESYSTEM, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD)));
113
114 for (BootPartition=0; BootPartition<4; BootPartition++)
115 {
116 DbgPrint((DPRINT_FILESYSTEM, "-------------------------------------------\n"));
117 DbgPrint((DPRINT_FILESYSTEM, "Partition %d\n", (BootPartition + 1)));
118 DbgPrint((DPRINT_FILESYSTEM, "BootIndicator: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].BootIndicator));
119 DbgPrint((DPRINT_FILESYSTEM, "StartHead: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartHead));
120 DbgPrint((DPRINT_FILESYSTEM, "StartSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartSector));
121 DbgPrint((DPRINT_FILESYSTEM, "StartCylinder: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartCylinder));
122 DbgPrint((DPRINT_FILESYSTEM, "SystemIndicator: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].SystemIndicator));
123 DbgPrint((DPRINT_FILESYSTEM, "EndHead: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndHead));
124 DbgPrint((DPRINT_FILESYSTEM, "EndSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndSector));
125 DbgPrint((DPRINT_FILESYSTEM, "EndCylinder: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndCylinder));
126 DbgPrint((DPRINT_FILESYSTEM, "SectorCountBeforePartition: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].SectorCountBeforePartition));
127 DbgPrint((DPRINT_FILESYSTEM, "PartitionSectorCount: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].PartitionSectorCount));
128 }
129
130 #endif // defined DEBUG
131
132
133 //
134 // Check the partition table magic value
135 //
136 if (DriveMasterBootRecord.MasterBootRecordMagic != 0xaa55)
137 {
138 FileSystemError("Invalid partition table magic (0xaa55)");
139 return FALSE;
140 }
141
142 if (PartitionNumber == 0)
143 {
144 //
145 // Count the bootable partitions
146 //
147 if (DriveMasterBootRecord.PartitionTable[0].BootIndicator == 0x80)
148 {
149 BootablePartitionCount++;
150 BootPartition = 1;
151 }
152 if (DriveMasterBootRecord.PartitionTable[1].BootIndicator == 0x80)
153 {
154 BootablePartitionCount++;
155 BootPartition = 2;
156 }
157 if (DriveMasterBootRecord.PartitionTable[2].BootIndicator == 0x80)
158 {
159 BootablePartitionCount++;
160 BootPartition = 3;
161 }
162 if (DriveMasterBootRecord.PartitionTable[3].BootIndicator == 0x80)
163 {
164 BootablePartitionCount++;
165 BootPartition = 4;
166 }
167
168 //
169 // Make sure there was only one bootable partition
170 //
171 if (BootablePartitionCount != 1)
172 {
173 FileSystemError("Too many bootable partitions or none found.");
174 return FALSE;
175 }
176 else
177 {
178 //
179 // We found the boot partition, so set the partition number
180 //
181 PartitionNumber = BootPartition;
182 }
183 }
184
185 //
186 // Right now the partition number is one-based
187 // and we need zero based
188 //
189 PartitionNumber--;
190
191 //
192 // Check for valid partition
193 //
194 if (DriveMasterBootRecord.PartitionTable[PartitionNumber].SystemIndicator == PARTITION_ENTRY_UNUSED)
195 {
196 FileSystemError("Invalid partition.");
197 return FALSE;
198 }
199
200 PartitionStartHead = DriveMasterBootRecord.PartitionTable[PartitionNumber].StartHead;
201 PartitionStartSector = DriveMasterBootRecord.PartitionTable[PartitionNumber].StartSector & 0x3F;
202 PartitionStartCylinder = MAKE_CYLINDER(
203 DriveMasterBootRecord.PartitionTable[PartitionNumber].StartCylinder,
204 DriveMasterBootRecord.PartitionTable[PartitionNumber].StartSector);
205
206 DbgPrint((DPRINT_FILESYSTEM, "PartitionStartHead: %d\n", PartitionStartHead));
207 DbgPrint((DPRINT_FILESYSTEM, "PartitionStartSector: %d\n", PartitionStartSector));
208 DbgPrint((DPRINT_FILESYSTEM, "PartitionStartCylinder: %d\n", PartitionStartCylinder));
209 DbgPrint((DPRINT_FILESYSTEM, "PartitionNumber: %d\n", PartitionNumber));
210
211 switch (DriveMasterBootRecord.PartitionTable[PartitionNumber].SystemIndicator)
212 {
213 case PARTITION_FAT_12:
214 FileSystemType = FS_FAT;
215 return FatOpenVolume(DriveNumber, PartitionStartHead, PartitionStartCylinder, PartitionStartSector, FAT12);
216 case PARTITION_FAT_16:
217 case PARTITION_HUGE:
218 case PARTITION_XINT13:
219 FileSystemType = FS_FAT;
220 return FatOpenVolume(DriveNumber, PartitionStartHead, PartitionStartCylinder, PartitionStartSector, FAT16);
221 case PARTITION_FAT32:
222 case PARTITION_FAT32_XINT13:
223 FileSystemType = FS_FAT;
224 return FatOpenVolume(DriveNumber, PartitionStartHead, PartitionStartCylinder, PartitionStartSector, FAT32);
225 default:
226 FileSystemType = 0;
227 FileSystemError("Unsupported file system.");
228 return FALSE;
229 }
230
231 return TRUE;
232 }
233
234 PFILE OpenFile(PUCHAR FileName)
235 {
236 PFILE FileHandle = NULL;
237
238 //
239 // Print status message
240 //
241 DbgPrint((DPRINT_FILESYSTEM, "Opening file '%s'...\n", FileName));
242
243 //
244 // Check file system type and pass off to appropriate handler
245 //
246 if (FileSystemType == FS_FAT)
247 {
248 FileHandle = FatOpenFile(FileName);
249 }
250 else
251 {
252 FileSystemError("Error: Unknown filesystem.");
253 }
254
255 #ifdef DEBUG
256 //
257 // Check return value
258 //
259 if (FileHandle != NULL)
260 {
261 DbgPrint((DPRINT_FILESYSTEM, "OpenFile() succeeded. FileHandle: 0x%x\n", FileHandle));
262 }
263 else
264 {
265 DbgPrint((DPRINT_FILESYSTEM, "OpenFile() failed.\n"));
266 }
267 #endif // defined DEBUG
268
269 return FileHandle;
270 }
271
272 VOID CloseFile(PFILE FileHandle)
273 {
274 }
275
276 /*
277 * ReadFile()
278 * returns number of bytes read or EOF
279 */
280 BOOL ReadFile(PFILE FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer)
281 {
282 //
283 // Set the number of bytes read equal to zero
284 //
285 if (BytesRead !=NULL)
286 {
287 *BytesRead = 0;
288 }
289
290 switch (FileSystemType)
291 {
292 case FS_FAT:
293
294 return FatReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
295
296 default:
297
298 FileSystemError("Unknown file system.");
299 return FALSE;
300 }
301
302 return FALSE;
303 }
304
305 ULONG GetFileSize(PFILE FileHandle)
306 {
307 switch (FileSystemType)
308 {
309 case FS_FAT:
310
311 return FatGetFileSize(FileHandle);
312
313 default:
314 FileSystemError("Unknown file system.");
315 break;
316 }
317
318 return 0;
319 }
320
321 VOID SetFilePointer(PFILE FileHandle, ULONG NewFilePointer)
322 {
323 switch (FileSystemType)
324 {
325 case FS_FAT:
326
327 FatSetFilePointer(FileHandle, NewFilePointer);
328 break;
329
330 default:
331 FileSystemError("Unknown file system.");
332 break;
333 }
334 }
335
336 ULONG GetFilePointer(PFILE FileHandle)
337 {
338 switch (FileSystemType)
339 {
340 case FS_FAT:
341
342 return FatGetFilePointer(FileHandle);
343 break;
344
345 default:
346 FileSystemError("Unknown file system.");
347 break;
348 }
349
350 return 0;
351 }
352
353 BOOL IsEndOfFile(PFILE FileHandle)
354 {
355 if (GetFilePointer(FileHandle) >= GetFileSize(FileHandle))
356 {
357 return TRUE;
358 }
359 else
360 {
361 return FALSE;
362 }
363 }