c91813f95d6be4d1d9c7441261ef0ef3c14b6996
[reactos.git] / reactos / boot / freeldr / freeldr / fs / fs.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 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 "iso.h"
24 #include "ext2.h"
25 #include "ntfs.h"
26 #include "fsrec.h"
27 #include <disk.h>
28 #include <rtl.h>
29 #include <ui.h>
30 #include <arch.h>
31 #include <debug.h>
32 #include <machine.h>
33
34
35 /////////////////////////////////////////////////////////////////////////////////////////////
36 // DATA
37 /////////////////////////////////////////////////////////////////////////////////////////////
38
39 ULONG FsType = 0; // Type of filesystem on boot device, set by FsOpenVolume()
40
41 /////////////////////////////////////////////////////////////////////////////////////////////
42 // FUNCTIONS
43 /////////////////////////////////////////////////////////////////////////////////////////////
44
45 VOID FileSystemError(PUCHAR ErrorString)
46 {
47 DbgPrint((DPRINT_FILESYSTEM, "%s\n", ErrorString));
48
49 UiMessageBox(ErrorString);
50 }
51
52 /*
53 *
54 * BOOL FsOpenVolume(ULONG DriveNumber, ULONG PartitionNumber);
55 *
56 * This function is called to open a disk volume for file access.
57 * It must be called before any of the file functions will work.
58 * It takes two parameters:
59 *
60 * Drive: The BIOS drive number of the disk to open
61 * Partition: This is zero for floppy drives.
62 * If the disk is a hard disk then this specifies
63 * The partition number to open (1 - 4)
64 * If it is zero then it opens the active (bootable) partition
65 *
66 */
67 BOOL FsOpenVolume(ULONG DriveNumber, ULONG PartitionNumber)
68 {
69 PARTITION_TABLE_ENTRY PartitionTableEntry;
70 UCHAR ErrorText[80];
71 UCHAR VolumeType;
72
73 DbgPrint((DPRINT_FILESYSTEM, "FsOpenVolume() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber));
74
75 // Check and see if it is a floppy drive
76 // If so then just assume FAT12 file system type
77 if (DiskIsDriveRemovable(DriveNumber))
78 {
79 DbgPrint((DPRINT_FILESYSTEM, "Drive is a floppy diskette drive. Assuming FAT12 file system.\n"));
80
81 FsType = FS_FAT;
82 return FatOpenVolume(DriveNumber, 0, 0);
83 }
84
85 // Check for ISO9660 file system type
86 if (DriveNumber >= 0x80 && FsRecIsIso9660(DriveNumber))
87 {
88 DbgPrint((DPRINT_FILESYSTEM, "Drive is a cdrom drive. Assuming ISO-9660 file system.\n"));
89
90 FsType = FS_ISO9660;
91 return IsoOpenVolume(DriveNumber);
92 }
93
94 // Set the boot partition
95 BootPartition = PartitionNumber;
96
97 // Get the requested partition entry
98 if (PartitionNumber == 0)
99 {
100 // Partition requested was zero which means the boot partition
101 if (DiskGetActivePartitionEntry(DriveNumber, &PartitionTableEntry) == FALSE)
102 {
103 FileSystemError("No active partition.");
104 return FALSE;
105 }
106 }
107 else
108 {
109 // Get requested partition
110 if (MachDiskGetPartitionEntry(DriveNumber, PartitionNumber, &PartitionTableEntry) == FALSE)
111 {
112 FileSystemError("Partition not found.");
113 return FALSE;
114 }
115 }
116
117 // Check for valid partition
118 if (PartitionTableEntry.SystemIndicator == PARTITION_ENTRY_UNUSED)
119 {
120 FileSystemError("Invalid partition.");
121 return FALSE;
122 }
123
124 // Try to recognize the file system
125 if (!FsRecognizeVolume(DriveNumber, PartitionTableEntry.SectorCountBeforePartition, &VolumeType))
126 {
127 FileSystemError("Unrecognized file system.");
128 return FALSE;
129 }
130
131 //switch (PartitionTableEntry.SystemIndicator)
132 switch (VolumeType)
133 {
134 case PARTITION_FAT_12:
135 case PARTITION_FAT_16:
136 case PARTITION_HUGE:
137 case PARTITION_XINT13:
138 case PARTITION_FAT32:
139 case PARTITION_FAT32_XINT13:
140 FsType = FS_FAT;
141 return FatOpenVolume(DriveNumber, PartitionTableEntry.SectorCountBeforePartition, PartitionTableEntry.PartitionSectorCount);
142 case PARTITION_EXT2:
143 FsType = FS_EXT2;
144 return Ext2OpenVolume(DriveNumber, PartitionTableEntry.SectorCountBeforePartition);
145 case PARTITION_NTFS:
146 FsType = FS_NTFS;
147 return NtfsOpenVolume(DriveNumber, PartitionTableEntry.SectorCountBeforePartition);
148 default:
149 FsType = 0;
150 sprintf(ErrorText, "Unsupported file system. Type: 0x%x", VolumeType);
151 FileSystemError(ErrorText);
152 return FALSE;
153 }
154
155 return TRUE;
156 }
157
158 PFILE FsOpenFile(PUCHAR FileName)
159 {
160 PFILE FileHandle = NULL;
161
162 //
163 // Print status message
164 //
165 DbgPrint((DPRINT_FILESYSTEM, "Opening file '%s'...\n", FileName));
166
167 //
168 // Check and see if the first character is '\' or '/' and remove it if so
169 //
170 while ((*FileName == '\\') || (*FileName == '/'))
171 {
172 FileName++;
173 }
174
175 //
176 // Check file system type and pass off to appropriate handler
177 //
178 switch (FsType)
179 {
180 case FS_FAT:
181 FileHandle = FatOpenFile(FileName);
182 break;
183 case FS_ISO9660:
184 FileHandle = IsoOpenFile(FileName);
185 break;
186 case FS_EXT2:
187 FileHandle = Ext2OpenFile(FileName);
188 break;
189 case FS_NTFS:
190 FileHandle = NtfsOpenFile(FileName);
191 break;
192 default:
193 FileSystemError("Error: Unknown filesystem.");
194 break;
195 }
196
197 #ifdef DEBUG
198 //
199 // Check return value
200 //
201 if (FileHandle != NULL)
202 {
203 DbgPrint((DPRINT_FILESYSTEM, "FsOpenFile() succeeded. FileHandle: 0x%x\n", FileHandle));
204 }
205 else
206 {
207 DbgPrint((DPRINT_FILESYSTEM, "FsOpenFile() failed.\n"));
208 }
209 #endif // defined DEBUG
210
211 return FileHandle;
212 }
213
214 VOID FsCloseFile(PFILE FileHandle)
215 {
216 }
217
218 /*
219 * ReadFile()
220 * returns number of bytes read or EOF
221 */
222 BOOL FsReadFile(PFILE FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer)
223 {
224 ULONGLONG BytesReadBig;
225 BOOL Success;
226
227 //
228 // Set the number of bytes read equal to zero
229 //
230 if (BytesRead != NULL)
231 {
232 *BytesRead = 0;
233 }
234
235 switch (FsType)
236 {
237 case FS_FAT:
238
239 return FatReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
240
241 case FS_ISO9660:
242
243 return IsoReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
244
245 case FS_EXT2:
246
247 //return Ext2ReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
248 Success = Ext2ReadFile(FileHandle, BytesToRead, &BytesReadBig, Buffer);
249 *BytesRead = (ULONG)BytesReadBig;
250 return Success;
251
252 case FS_NTFS:
253
254 return NtfsReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
255
256 default:
257
258 FileSystemError("Unknown file system.");
259 return FALSE;
260 }
261
262 return FALSE;
263 }
264
265 ULONG FsGetFileSize(PFILE FileHandle)
266 {
267 switch (FsType)
268 {
269 case FS_FAT:
270
271 return FatGetFileSize(FileHandle);
272
273 case FS_ISO9660:
274
275 return IsoGetFileSize(FileHandle);
276
277 case FS_EXT2:
278
279 return Ext2GetFileSize(FileHandle);
280
281 case FS_NTFS:
282
283 return NtfsGetFileSize(FileHandle);
284
285 default:
286 FileSystemError("Unknown file system.");
287 break;
288 }
289
290 return 0;
291 }
292
293 VOID FsSetFilePointer(PFILE FileHandle, ULONG NewFilePointer)
294 {
295 switch (FsType)
296 {
297 case FS_FAT:
298
299 FatSetFilePointer(FileHandle, NewFilePointer);
300 break;
301
302 case FS_ISO9660:
303
304 IsoSetFilePointer(FileHandle, NewFilePointer);
305 break;
306
307 case FS_EXT2:
308
309 Ext2SetFilePointer(FileHandle, NewFilePointer);
310 break;
311
312 case FS_NTFS:
313
314 NtfsSetFilePointer(FileHandle, NewFilePointer);
315 break;
316
317 default:
318 FileSystemError("Unknown file system.");
319 break;
320 }
321 }
322
323 ULONG FsGetFilePointer(PFILE FileHandle)
324 {
325 switch (FsType)
326 {
327 case FS_FAT:
328
329 return FatGetFilePointer(FileHandle);
330 break;
331
332 case FS_ISO9660:
333
334 return IsoGetFilePointer(FileHandle);
335 break;
336
337 case FS_EXT2:
338
339 return Ext2GetFilePointer(FileHandle);
340 break;
341
342 case FS_NTFS:
343
344 return NtfsGetFilePointer(FileHandle);
345 break;
346
347 default:
348 FileSystemError("Unknown file system.");
349 break;
350 }
351
352 return 0;
353 }
354
355 BOOL FsIsEndOfFile(PFILE FileHandle)
356 {
357 if (FsGetFilePointer(FileHandle) >= FsGetFileSize(FileHandle))
358 {
359 return TRUE;
360 }
361 else
362 {
363 return FALSE;
364 }
365 }
366
367 /*
368 * FsGetNumPathParts()
369 * This function parses a path in the form of dir1\dir2\file1.ext
370 * and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext)
371 */
372 ULONG FsGetNumPathParts(PUCHAR Path)
373 {
374 ULONG i;
375 ULONG num;
376
377 for (i=0,num=0; i<(int)strlen(Path); i++)
378 {
379 if ((Path[i] == '\\') || (Path[i] == '/'))
380 {
381 num++;
382 }
383 }
384 num++;
385
386 DbgPrint((DPRINT_FILESYSTEM, "FatGetNumPathParts() Path = %s NumPathParts = %d\n", Path, num));
387
388 return num;
389 }
390
391 /*
392 * FsGetFirstNameFromPath()
393 * This function parses a path in the form of dir1\dir2\file1.ext
394 * and puts the first name of the path (e.g. "dir1") in buffer
395 * compatible with the MSDOS directory structure
396 */
397 VOID FsGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path)
398 {
399 ULONG i;
400
401 // Copy all the characters up to the end of the
402 // string or until we hit a '\' character
403 // and put them in Buffer
404 for (i=0; i<(int)strlen(Path); i++)
405 {
406 if ((Path[i] == '\\') || (Path[i] == '/'))
407 {
408 break;
409 }
410 else
411 {
412 Buffer[i] = Path[i];
413 }
414 }
415
416 Buffer[i] = 0;
417
418 DbgPrint((DPRINT_FILESYSTEM, "FatGetFirstNameFromPath() Path = %s FirstName = %s\n", Path, Buffer));
419 }