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