Added ISO-9660 support.
authorEric Kohl <eric.kohl@reactos.org>
Tue, 23 Apr 2002 09:08:59 +0000 (09:08 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Tue, 23 Apr 2002 09:08:59 +0000 (09:08 +0000)
svn path=/trunk/; revision=2865

freeldr/freeldr/disk.h
freeldr/freeldr/disk/partition.c
freeldr/freeldr/fs.h
freeldr/freeldr/fs/Makefile
freeldr/freeldr/fs/fs.c
freeldr/freeldr/fs/iso.c [new file with mode: 0644]
freeldr/freeldr/fs/iso.h [new file with mode: 0644]

index d9232e8..9255bc6 100644 (file)
@@ -112,6 +112,7 @@ BOOL        DiskReadLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorC
 //
 ///////////////////////////////////////////////////////////////////////////////////////
 BOOL   DiskIsDriveRemovable(ULONG DriveNumber);
 //
 ///////////////////////////////////////////////////////////////////////////////////////
 BOOL   DiskIsDriveRemovable(ULONG DriveNumber);
+BOOL   DiskIsDriveCdRom(ULONG DriveNumber);
 BOOL   DiskGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
 BOOL   DiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
 BOOL   DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
 BOOL   DiskGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
 BOOL   DiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
 BOOL   DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
index ad9aa2d..3df892a 100644 (file)
@@ -40,6 +40,43 @@ BOOL DiskIsDriveRemovable(ULONG DriveNumber)
        return TRUE;
 }
 
        return TRUE;
 }
 
+
+BOOL DiskIsDriveCdRom(ULONG DriveNumber)
+{
+       PUCHAR Sector;
+       BOOL Result;
+
+       // Hard disks use drive numbers >= 0x80
+       // So if the drive number indicates a hard disk
+       // then return FALSE
+       if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
+       {
+               Sector = AllocateMemory(2048);
+
+               if (!BiosInt13ReadExtended(DriveNumber, 16, 1, Sector))
+               {
+                       DiskError("Disk read error.");
+                       FreeMemory(Sector);
+                       return FALSE;
+               }
+
+               Result = (Sector[0] == 1 &&
+                         Sector[1] == 'C' &&
+                         Sector[2] == 'D' &&
+                         Sector[3] == '0' &&
+                         Sector[4] == '0' &&
+                         Sector[5] == '1');
+
+               FreeMemory(Sector);
+
+               return Result;
+       }
+
+       // Drive is not CdRom so return FALSE
+       return FALSE;
+}
+
+
 BOOL DiskGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
 {
        ULONG                           BootablePartitionCount = 0;
 BOOL DiskGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
 {
        ULONG                           BootablePartitionCount = 0;
index 3da0315..4aa9b27 100644 (file)
@@ -27,6 +27,7 @@
 #define        FS_NTFS                 2
 #define        FS_EXT2                 3
 #define FS_REISER              4
 #define        FS_NTFS                 2
 #define        FS_EXT2                 3
 #define FS_REISER              4
+#define FS_ISO9660             5
 
 #define FILE                   VOID
 #define PFILE                  FILE *
 
 #define FILE                   VOID
 #define PFILE                  FILE *
index 15bdaec..3524026 100644 (file)
@@ -19,7 +19,7 @@
        
 include ../rules.mk
 
        
 include ../rules.mk
 
-OBJS = fs.o fat.o
+OBJS = fs.o fat.o iso.o
 
 .PHONY : clean
 
 
 .PHONY : clean
 
@@ -34,6 +34,9 @@ fs.o: fs.c fat.h ../fs.h
 fat.o: fat.c fat.h ../fs.h
        $(CC) $(FLAGS) -o fat.o -c fat.c
 
 fat.o: fat.c fat.h ../fs.h
        $(CC) $(FLAGS) -o fat.o -c fat.c
 
+iso.o: iso.c iso.h ../fs.h
+       $(CC) $(FLAGS) -o iso.o -c iso.c
+
 clean:
        - $(RM) *.o
        - $(RM) *.a
 clean:
        - $(RM) *.o
        - $(RM) *.a
index eebf2ac..80d9522 100644 (file)
@@ -20,6 +20,7 @@
 #include <freeldr.h>
 #include <fs.h>
 #include "fat.h"
 #include <freeldr.h>
 #include <fs.h>
 #include "fat.h"
+#include "iso.h"
 #include <disk.h>
 #include <rtl.h>
 #include <ui.h>
 #include <disk.h>
 #include <rtl.h>
 #include <ui.h>
@@ -84,6 +85,16 @@ BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber)
                return FatOpenVolume(DriveNumber, 0);
        }
 
                return FatOpenVolume(DriveNumber, 0);
        }
 
+       // Check and see if it is a cdrom drive
+       // If so then just assume ISO9660 file system type
+       if (DiskIsDriveCdRom(DriveNumber))
+       {
+               DbgPrint((DPRINT_FILESYSTEM, "Drive is a cdrom drive. Assuming ISO-9660 file system.\n"));
+
+               FileSystemType = FS_ISO9660;
+               return IsoOpenVolume(DriveNumber);
+       }
+
        // Set the boot partition
        BootPartition = PartitionNumber;
 
        // Set the boot partition
        BootPartition = PartitionNumber;
 
@@ -93,6 +104,7 @@ BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber)
                // Partition requested was zero which means the boot partition
                if (DiskGetActivePartitionEntry(DriveNumber, &PartitionTableEntry) == FALSE)
                {
                // Partition requested was zero which means the boot partition
                if (DiskGetActivePartitionEntry(DriveNumber, &PartitionTableEntry) == FALSE)
                {
+                       FileSystemError("No active partition.");
                        return FALSE;
                }
        }
                        return FALSE;
                }
        }
@@ -101,6 +113,7 @@ BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber)
                // Get requested partition
                if (DiskGetPartitionEntry(DriveNumber, PartitionNumber, &PartitionTableEntry) == FALSE)
                {
                // Get requested partition
                if (DiskGetPartitionEntry(DriveNumber, PartitionNumber, &PartitionTableEntry) == FALSE)
                {
+                       FileSystemError("Partition not found.");
                        return FALSE;
                }
        }
                        return FALSE;
                }
        }
@@ -147,6 +160,10 @@ PFILE OpenFile(PUCHAR FileName)
        {
                FileHandle = FatOpenFile(FileName);
        }
        {
                FileHandle = FatOpenFile(FileName);
        }
+       else if (FileSystemType == FS_ISO9660)
+       {
+               FileHandle = IsoOpenFile(FileName);
+       }
        else
        {
                FileSystemError("Error: Unknown filesystem.");
        else
        {
                FileSystemError("Error: Unknown filesystem.");
@@ -193,6 +210,10 @@ BOOL ReadFile(PFILE FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffe
 
                return FatReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
 
 
                return FatReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
 
+       case FS_ISO9660:
+
+               return IsoReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
+
        default:
 
                FileSystemError("Unknown file system.");
        default:
 
                FileSystemError("Unknown file system.");
@@ -210,6 +231,10 @@ ULONG GetFileSize(PFILE FileHandle)
 
                return FatGetFileSize(FileHandle);
 
 
                return FatGetFileSize(FileHandle);
 
+       case FS_ISO9660:
+
+               return IsoGetFileSize(FileHandle);
+
        default:
                FileSystemError("Unknown file system.");
                break;
        default:
                FileSystemError("Unknown file system.");
                break;
@@ -227,6 +252,11 @@ VOID SetFilePointer(PFILE FileHandle, ULONG NewFilePointer)
                FatSetFilePointer(FileHandle, NewFilePointer);
                break;
 
                FatSetFilePointer(FileHandle, NewFilePointer);
                break;
 
+       case FS_ISO9660:
+
+               IsoSetFilePointer(FileHandle, NewFilePointer);
+               break;
+
        default:
                FileSystemError("Unknown file system.");
                break;
        default:
                FileSystemError("Unknown file system.");
                break;
@@ -242,6 +272,11 @@ ULONG GetFilePointer(PFILE FileHandle)
                return FatGetFilePointer(FileHandle);
                break;
 
                return FatGetFilePointer(FileHandle);
                break;
 
+       case FS_ISO9660:
+
+               return IsoGetFilePointer(FileHandle);
+               break;
+
        default:
                FileSystemError("Unknown file system.");
                break;
        default:
                FileSystemError("Unknown file system.");
                break;
diff --git a/freeldr/freeldr/fs/iso.c b/freeldr/freeldr/fs/iso.c
new file mode 100644 (file)
index 0000000..2fdfef1
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ *  FreeLoader
+ *  Copyright (C) 1998-2002  Brian Palmer  <brianp@sginet.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <freeldr.h>
+#include <fs.h>
+#include "iso.h"
+#include <disk.h>
+#include <rtl.h>
+#include <ui.h>
+#include <arch.h>
+#include <mm.h>
+#include <debug.h>
+#include <cache.h>
+
+
+#define SECTORSIZE 2048
+
+static ULONG   IsoRootSector;          // Starting sector of the root directory
+static ULONG   IsoRootLength;          // Length of the root directory
+
+ULONG          IsoDriveNumber = 0;
+
+
+BOOL IsoOpenVolume(ULONG DriveNumber)
+{
+       PPVD Pvd;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoOpenVolume() DriveNumber = 0x%x VolumeStartSector = 16\n", DriveNumber));
+       printf("IsoOpenVolume() DriveNumber = 0x%x\n", DriveNumber);
+
+       // Store the drive number
+       IsoDriveNumber = DriveNumber;
+
+       IsoRootSector = 0;
+       IsoRootLength = 0;
+
+       Pvd = AllocateMemory(SECTORSIZE);
+
+       if (!BiosInt13ReadExtended(DriveNumber, 16, 1, Pvd))
+       {
+               FileSystemError("Failed to read the PVD.");
+               FreeMemory(Pvd);
+               return FALSE;
+       }
+
+       IsoRootSector = Pvd->RootDirRecord.ExtentLocationL;
+       IsoRootLength = Pvd->RootDirRecord.DataLengthL;
+
+       FreeMemory(Pvd);
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoRootSector = %u  IsoRootLegth = %u\n", IsoRootSector, IsoRootLength));
+       printf("IsoRootSector = %u  IsoRootLegth = %u\n", IsoRootSector, IsoRootLength);
+
+       return TRUE;
+}
+
+
+static BOOL IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer, UINT32 DirectoryLength, PUCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer)
+{
+       PDIR_RECORD     Record;
+       ULONG           Offset;
+       ULONG i;
+       UCHAR Name[32];
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectoryLength = %d FileName = %s\n", DirectoryBuffer, DirectoryLength, FileName));
+       printf("IsoSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectoryLength = %d FileName = %s\n", DirectoryBuffer, DirectoryLength, FileName);
+
+       memset(Name, 0, 32 * sizeof(UCHAR));
+
+       Offset = 0;
+       Record = (PDIR_RECORD)DirectoryBuffer;
+       while (TRUE)
+       {
+               Offset = Offset + Record->RecordLength;
+               Record = (PDIR_RECORD)(DirectoryBuffer + Offset);
+
+               if (Record->RecordLength == 0)
+               {
+                       Offset = ROUND_UP(Offset, SECTORSIZE);
+                       Record = (PDIR_RECORD)(DirectoryBuffer + Offset);
+               }
+
+               if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
+               {
+//                     DbgPrint((DPRINT_FILESYSTEM, "Name '.'\n"));
+                       printf("Name '.'\n");
+               }
+               else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
+               {
+//                     DbgPrint((DPRINT_FILESYSTEM, "Name '..'\n"));
+                       printf("Name '..'\n");
+               }
+               else
+               {
+                       for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
+                               Name[i] = Record->FileId[i];
+                       Name[i] = 0;
+//                     DbgPrint((DPRINT_FILESYSTEM, "Name '%s'\n", Name));
+                       printf("Name '%s'\n", Name);
+
+                       if (strlen(FileName) == strlen(Name) && stricmp(FileName, Name) == 0)
+                       {
+                               IsoFileInfoPointer->FileStart = Record->ExtentLocationL;
+                               IsoFileInfoPointer->FileSize = Record->DataLengthL;
+                               IsoFileInfoPointer->FilePointer = 0;
+                               IsoFileInfoPointer->Directory = (Record->FileFlags & 0x02)?TRUE:FALSE;
+
+                               return TRUE;
+                       }
+
+               }
+
+               if (Offset >= DirectoryLength)
+                       return FALSE;
+
+               memset(Name, 0, 32 * sizeof(UCHAR));
+       }
+
+       return FALSE;
+}
+
+
+
+static PVOID IsoBufferDirectory(UINT32 DirectoryStartSector, UINT32 DirectoryLength)
+{
+       PVOID   DirectoryBuffer;
+       UINT32  SectorCount;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoBufferDirectory() DirectoryStartSector = %d DirectoryLength = %d\n", DirectoryStartSector, DirectoryLength));
+       printf("IsoBufferDirectory() DirectoryStartSector = %d DirectoryLength = %d\n", DirectoryStartSector, DirectoryLength);
+
+       //
+       // Attempt to allocate memory for directory buffer
+       //
+//     DbgPrint((DPRINT_FILESYSTEM, "Trying to allocate (DirectoryLength) %d bytes.\n", DirectoryLength));
+       printf("Trying to allocate (DirectoryLength) %d bytes.\n", DirectoryLength);
+       DirectoryBuffer = AllocateMemory(DirectoryLength);
+
+       if (DirectoryBuffer == NULL)
+       {
+               return NULL;
+       }
+
+       SectorCount = ROUND_UP(DirectoryLength, SECTORSIZE) / SECTORSIZE;
+//     DbgPrint((DPRINT_FILESYSTEM, "Trying to read (DirectoryCount) %d sectors.\n", SectorCount));
+       printf("Trying to read (DirectoryCount) %d sectors.\n", SectorCount);
+
+       //
+       // Now read directory contents into DirectoryBuffer
+       //
+       if (!BiosInt13ReadExtended(IsoDriveNumber, DirectoryStartSector, SectorCount, DirectoryBuffer))
+       {
+               FreeMemory(DirectoryBuffer);
+               return NULL;
+       }
+
+       return DirectoryBuffer;
+}
+
+
+/*
+ * IsoGetNumPathParts()
+ * This function parses a path in the form of dir1\dir2\file1.ext
+ * and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext)
+ */
+static ULONG IsoGetNumPathParts(PUCHAR Path)
+{
+       ULONG   i;
+       ULONG   num;
+
+       for (i=0,num=0; i<(int)strlen(Path); i++)
+       {
+               if (Path[i] == '\\')
+               {
+                       num++;
+               }
+       }
+       num++;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoGetNumPathParts() Path = %s NumPathParts = %d\n", Path, num));
+       printf("IsoGetNumPathParts() Path = %s NumPathParts = %d\n", Path, num);
+
+       return num;
+}
+
+
+/*
+ * IsoGetFirstNameFromPath()
+ * This function parses a path in the form of dir1\dir2\file1.ext
+ * and puts the first name of the path (e.g. "dir1") in buffer
+ * compatible with the MSDOS directory structure
+ */
+static VOID IsoGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path)
+{
+       ULONG   i;
+
+       // Copy all the characters up to the end of the
+       // string or until we hit a '\' character
+       // and put them in Buffer
+       for (i=0; i<(int)strlen(Path); i++)
+       {
+               if (Path[i] == '\\')
+               {
+                       break;
+               }
+               else
+               {
+                       Buffer[i] = Path[i];
+               }
+       }
+
+       Buffer[i] = 0;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoGetFirstNameFromPath() Path = %s FirstName = %s\n", Path, Buffer));
+       printf("IsoGetFirstNameFromPath() Path = %s FirstName = %s\n", Path, Buffer);
+}
+
+
+/*
+ * IsoLookupFile()
+ * This function searches the file system for the
+ * specified filename and fills in an ISO_FILE_INFO structure
+ * with info describing the file, etc. returns true
+ * if the file exists or false otherwise
+ */
+static BOOL IsoLookupFile(PUCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer)
+{
+       int             i;
+       ULONG           NumberOfPathParts;
+       UCHAR           PathPart[261];
+       PVOID           DirectoryBuffer;
+       UINT32          DirectorySector;
+       UINT32          DirectoryLength;
+       ISO_FILE_INFO   IsoFileInfo;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoLookupFile() FileName = %s\n", FileName));
+       printf("IsoLookupFile() FileName = %s\n", FileName);
+
+       memset(IsoFileInfoPointer, 0, sizeof(ISO_FILE_INFO));
+
+       //
+       // Check and see if the first character is '\' and remove it if so
+       //
+       while (*FileName == '\\')
+       {
+               FileName++;
+       }
+
+       //
+       // Figure out how many sub-directories we are nested in
+       //
+       NumberOfPathParts = IsoGetNumPathParts(FileName);
+
+       DirectorySector = IsoRootSector;
+       DirectoryLength = IsoRootLength;
+
+       //
+       // Loop once for each part
+       //
+       for (i=0; i<NumberOfPathParts; i++)
+       {
+               //
+               // Get first path part
+               //
+               IsoGetFirstNameFromPath(PathPart, FileName);
+
+               //
+               // Advance to the next part of the path
+               //
+               for (; (*FileName != '\\') && (*FileName != '\0'); FileName++)
+               {
+               }
+               FileName++;
+
+               //
+               // Buffer the directory contents
+               //
+               DirectoryBuffer = IsoBufferDirectory(DirectorySector, DirectoryLength);
+               if (DirectoryBuffer == NULL)
+               {
+                       return FALSE;
+               }
+
+               //
+               // Search for file name in directory
+               //
+               if (!IsoSearchDirectoryBufferForFile(DirectoryBuffer, DirectoryLength, PathPart, &IsoFileInfo))
+               {
+                       FreeMemory(DirectoryBuffer);
+                       return FALSE;
+               }
+
+               FreeMemory(DirectoryBuffer);
+
+               //
+               // If we have another sub-directory to go then
+               // grab the start sector and file size
+               //
+               if ((i+1) < NumberOfPathParts)
+               {
+                       DirectorySector = IsoFileInfo.FileStart;
+                       DirectoryLength = IsoFileInfo.FileSize;
+               }
+
+       }
+
+       memcpy(IsoFileInfoPointer, &IsoFileInfo, sizeof(ISO_FILE_INFO));
+
+       return TRUE;
+}
+
+
+/*
+ * IsoOpenFile()
+ * Tries to open the file 'name' and returns true or false
+ * for success and failure respectively
+ */
+FILE* IsoOpenFile(PUCHAR FileName)
+{
+       ISO_FILE_INFO           TempFileInfo;
+       PISO_FILE_INFO          FileHandle;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoOpenFile() FileName = %s\n", FileName));
+       printf("IsoOpenFile() FileName = %s\n", FileName);
+
+       if (!IsoLookupFile(FileName, &TempFileInfo))
+       {
+               return NULL;
+       }
+
+       FileHandle = AllocateMemory(sizeof(ISO_FILE_INFO));
+
+       if (FileHandle == NULL)
+       {
+               return NULL;
+       }
+
+       memcpy(FileHandle, &TempFileInfo, sizeof(ISO_FILE_INFO));
+
+       return (FILE*)FileHandle;
+}
+
+
+/*
+ * IsoReadPartialSector()
+ * Reads part of a cluster into memory
+ */
+static BOOL IsoReadPartialSector(ULONG SectorNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
+{
+       PUCHAR  SectorBuffer;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoReadPartialSector() SectorNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", SectorNumber, StartingOffset, Length, Buffer));
+       printf("IsoReadPartialSector() SectorNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", SectorNumber, StartingOffset, Length, Buffer);
+
+       SectorBuffer = AllocateMemory(SECTORSIZE);
+       if (SectorBuffer == NULL)
+       {
+               return FALSE;
+       }
+
+       if (!BiosInt13ReadExtended(IsoDriveNumber, SectorNumber, 1, SectorBuffer))
+       {
+               FreeMemory(SectorBuffer);
+               return FALSE;
+       }
+
+       memcpy(Buffer, ((PVOID)SectorBuffer + StartingOffset), Length);
+
+       FreeMemory(SectorBuffer);
+
+       return TRUE;
+}
+
+
+/*
+ * IsoReadFile()
+ * Reads BytesToRead from open file and
+ * returns the number of bytes read in BytesRead
+ */
+BOOL IsoReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer)
+{
+       PISO_FILE_INFO  IsoFileInfo = (PISO_FILE_INFO)FileHandle;
+       UINT32          SectorNumber;
+       UINT32          OffsetInSector;
+       UINT32          LengthInSector;
+       UINT32          NumberOfSectors;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer));
+       printf("IsoReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer);
+
+       if (BytesRead != NULL)
+       {
+               *BytesRead = 0;
+       }
+
+       //
+       // If they are trying to read past the
+       // end of the file then return success
+       // with BytesRead == 0
+       //
+       if (IsoFileInfo->FilePointer >= IsoFileInfo->FileSize)
+       {
+               return TRUE;
+       }
+
+       //
+       // If they are trying to read more than there is to read
+       // then adjust the amount to read
+       //
+       if ((IsoFileInfo->FilePointer + BytesToRead) > IsoFileInfo->FileSize)
+       {
+               BytesToRead = (IsoFileInfo->FileSize - IsoFileInfo->FilePointer);
+       }
+
+       //
+       // Ok, now we have to perform at most 3 calculations
+       // I'll draw you a picture (using nifty ASCII art):
+       //
+       // CurrentFilePointer -+
+       //                     |
+       //    +----------------+
+       //    |
+       // +-----------+-----------+-----------+-----------+
+       // | Sector  1 | Sector  2 | Sector  3 | Sector  4 |
+       // +-----------+-----------+-----------+-----------+
+       //    |                                    |
+       //    +---------------+--------------------+
+       //                    |
+       // BytesToRead -------+
+       //
+       // 1 - The first calculation (and read) will align
+       //     the file pointer with the next sector
+       //     boundary (if we are supposed to read that much)
+       // 2 - The next calculation (and read) will read
+       //     in all the full sectors that the requested
+       //     amount of data would cover (in this case
+       //     sectors 2 & 3).
+       // 3 - The last calculation (and read) would read
+       //     in the remainder of the data requested out of
+       //     the last sector.
+       //
+
+
+       //
+       // Only do the first read if we
+       // aren't aligned on a cluster boundary
+       //
+       if (IsoFileInfo->FilePointer % SECTORSIZE)
+       {
+               //
+               // Do the math for our first read
+               //
+               SectorNumber = IsoFileInfo->FileStart + (IsoFileInfo->FilePointer / SECTORSIZE);
+               OffsetInSector = IsoFileInfo->FilePointer % SECTORSIZE;
+               LengthInSector = (BytesToRead > (SECTORSIZE - OffsetInSector)) ? (SECTORSIZE - OffsetInSector) : BytesToRead;
+
+               //
+               // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
+               //
+               if (!IsoReadPartialSector(SectorNumber, OffsetInSector, LengthInSector, Buffer))
+               {
+                       return FALSE;
+               }
+               if (BytesRead != NULL)
+               {
+                       *BytesRead += LengthInSector;
+               }
+               BytesToRead -= LengthInSector;
+               IsoFileInfo->FilePointer += LengthInSector;
+               Buffer += LengthInSector;
+       }
+
+       //
+       // Do the math for our second read (if any data left)
+       //
+       if (BytesToRead > 0)
+       {
+               //
+               // Determine how many full clusters we need to read
+               //
+               NumberOfSectors = (BytesToRead / SECTORSIZE);
+
+               if (NumberOfSectors > 0)
+               {
+                       SectorNumber = IsoFileInfo->FileStart + (IsoFileInfo->FilePointer / SECTORSIZE);
+
+                       //
+                       // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
+                       //
+                       if (!BiosInt13ReadExtended(IsoDriveNumber, SectorNumber, NumberOfSectors, Buffer))
+                       {
+                               return FALSE;
+                       }
+                       if (BytesRead != NULL)
+                       {
+                               *BytesRead += (NumberOfSectors * SECTORSIZE);
+                       }
+                       BytesToRead -= (NumberOfSectors * SECTORSIZE);
+                       IsoFileInfo->FilePointer += (NumberOfSectors * SECTORSIZE);
+                       Buffer += (NumberOfSectors * SECTORSIZE);
+               }
+       }
+
+       //
+       // Do the math for our third read (if any data left)
+       //
+       if (BytesToRead > 0)
+       {
+               SectorNumber = IsoFileInfo->FileStart + (IsoFileInfo->FilePointer / SECTORSIZE);
+
+               //
+               // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
+               //
+               if (!IsoReadPartialSector(SectorNumber, 0, BytesToRead, Buffer))
+               {
+                       return FALSE;
+               }
+               if (BytesRead != NULL)
+               {
+                       *BytesRead += BytesToRead;
+               }
+               BytesToRead -= BytesToRead;
+               IsoFileInfo->FilePointer += BytesToRead;
+               Buffer += BytesToRead;
+       }
+
+       printf("IsoReadFile() done\n");
+
+       return TRUE;
+}
+
+
+ULONG IsoGetFileSize(FILE *FileHandle)
+{
+       PISO_FILE_INFO  IsoFileHandle = (PISO_FILE_INFO)FileHandle;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoGetFileSize() FileSize = %d\n", IsoFileHandle->FileSize));
+       printf("IsoGetFileSize() FileSize = %d\n", IsoFileHandle->FileSize);
+
+       return IsoFileHandle->FileSize;
+}
+
+VOID IsoSetFilePointer(FILE *FileHandle, ULONG NewFilePointer)
+{
+       PISO_FILE_INFO  IsoFileHandle = (PISO_FILE_INFO)FileHandle;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoSetFilePointer() NewFilePointer = %d\n", NewFilePointer));
+       printf("IsoSetFilePointer() NewFilePointer = %d\n", NewFilePointer);
+
+       IsoFileHandle->FilePointer = NewFilePointer;
+}
+
+ULONG IsoGetFilePointer(FILE *FileHandle)
+{
+       PISO_FILE_INFO  IsoFileHandle = (PISO_FILE_INFO)FileHandle;
+
+//     DbgPrint((DPRINT_FILESYSTEM, "IsoGetFilePointer() FilePointer = %d\n", IsoFileHandle->FilePointer));
+       printf("IsoGetFilePointer() FilePointer = %d\n", IsoFileHandle->FilePointer);
+
+       return IsoFileHandle->FilePointer;
+}
diff --git a/freeldr/freeldr/fs/iso.h b/freeldr/freeldr/fs/iso.h
new file mode 100644 (file)
index 0000000..287c378
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ *  FreeLoader
+ *  Copyright (C) 1998-2002  Brian Palmer  <brianp@sginet.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ISO_H
+#define __ISO_H
+
+
+struct _DIR_RECORD
+{
+  UCHAR  RecordLength;                 // 1
+  UCHAR  ExtAttrRecordLength;          // 2
+  ULONG  ExtentLocationL;              // 3-6
+  ULONG  ExtentLocationM;              // 7-10
+  ULONG  DataLengthL;                  // 11-14
+  ULONG  DataLengthM;                  // 15-18
+  UCHAR  Year;                         // 19
+  UCHAR  Month;                                // 20
+  UCHAR  Day;                          // 21
+  UCHAR  Hour;                         // 22
+  UCHAR  Minute;                       // 23
+  UCHAR  Second;                       // 24
+  UCHAR  TimeZone;                     // 25
+  UCHAR  FileFlags;                    // 26
+  UCHAR  FileUnitSize;                 // 27
+  UCHAR  InterleaveGapSize;            // 28
+  ULONG  VolumeSequenceNumber;         // 29-32
+  UCHAR  FileIdLength;                 // 33
+  UCHAR  FileId[1];                    // 34
+} __attribute__((packed));
+
+typedef struct _DIR_RECORD DIR_RECORD, *PDIR_RECORD;
+
+
+
+
+/* Volume Descriptor header*/
+struct _VD_HEADER
+{
+  UCHAR  VdType;                       // 1
+  UCHAR  StandardId[5];                        // 2-6
+  UCHAR  VdVersion;                    // 7
+} __attribute__((packed));
+
+typedef struct _VD_HEADER VD_HEADER, *PVD_HEADER;
+
+
+
+/* Primary Volume Descriptor */
+struct _PVD
+{
+  UCHAR  VdType;                       // 1
+  UCHAR  StandardId[5];                        // 2-6
+  UCHAR  VdVersion;                    // 7
+  UCHAR  unused0;                      // 8
+  UCHAR  SystemId[32];                 // 9-40
+  UCHAR  VolumeId[32];                 // 41-72
+  UCHAR  unused1[8];                   // 73-80
+  ULONG  VolumeSpaceSizeL;             // 81-84
+  ULONG  VolumeSpaceSizeM;             // 85-88
+  UCHAR  unused2[32];                  // 89-120
+  ULONG  VolumeSetSize;                        // 121-124
+  ULONG  VolumeSequenceNumber;         // 125-128
+  ULONG  LogicalBlockSize;             // 129-132
+  ULONG  PathTableSizeL;               // 133-136
+  ULONG  PathTableSizeM;               // 137-140
+  ULONG  LPathTablePos;                        // 141-144
+  ULONG  LOptPathTablePos;             // 145-148
+  ULONG  MPathTablePos;                        // 149-152
+  ULONG  MOptPathTablePos;             // 153-156
+  DIR_RECORD RootDirRecord;            // 157-190
+  UCHAR  VolumeSetIdentifier[128];     // 191-318
+  UCHAR  PublisherIdentifier[128];     // 319-446
+
+  /* more data ... */
+
+} __attribute__((packed));
+
+typedef struct _PVD PVD, *PPVD;
+
+
+
+typedef struct
+{
+       ULONG   FileStart;              // File start sector
+       ULONG   FileSize;               // File size
+       ULONG   FilePointer;            // File pointer
+       BOOL    Directory;
+       ULONG   DriveNumber;
+} ISO_FILE_INFO, * PISO_FILE_INFO;
+
+
+BOOL   IsoOpenVolume(ULONG DriveNumber);
+FILE*  IsoOpenFile(PUCHAR FileName);
+BOOL   IsoReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer);
+ULONG  IsoGetFileSize(FILE *FileHandle);
+VOID   IsoSetFilePointer(FILE *FileHandle, ULONG NewFilePointer);
+ULONG  IsoGetFilePointer(FILE *FileHandle);
+
+#endif // #defined __FAT_H