From c66e8c39d37fcfae17f32c4c82901b4ef4e1f3ed Mon Sep 17 00:00:00 2001 From: Brian Palmer Date: Tue, 26 Feb 2002 00:26:35 +0000 Subject: [PATCH] Added full disk partition management functions Extended partitions are supported (untested) If you call OpenDrive() with Partition == 0 you get the active (or bootable) partition Partitions 1 - 4 are the primary partitions Partitions 5 - n are the extended partitions Also added disk parameter detection code (always assumes 512 byte sector size, I don't like that but I don't see any other way) svn path=/trunk/; revision=2651 --- freeldr/freeldr/arch/Makefile | 4 +- freeldr/freeldr/arch/i386/disk.S | 92 +++++++++++- freeldr/freeldr/cache/blocklist.c | 2 +- freeldr/freeldr/debug.c | 7 +- freeldr/freeldr/disk.h | 66 ++++++++- freeldr/freeldr/disk/Makefile | 5 +- freeldr/freeldr/disk/disk.c | 75 +--------- freeldr/freeldr/disk/geometry.c | 97 +------------ freeldr/freeldr/disk/partition.c | 233 ++++++++++++++++++++++++++++++ freeldr/freeldr/fs.h | 68 +-------- freeldr/freeldr/fs/fat.c | 32 +--- freeldr/freeldr/fs/filesys.h | 30 ---- freeldr/freeldr/fs/fs.c | 131 +---------------- freeldr/freeldr/multiboot.c | 2 +- freeldr/freeldr/rules.mk | 4 +- 15 files changed, 421 insertions(+), 427 deletions(-) create mode 100644 freeldr/freeldr/disk/partition.c delete mode 100644 freeldr/freeldr/fs/filesys.h diff --git a/freeldr/freeldr/arch/Makefile b/freeldr/freeldr/arch/Makefile index 5c4685edb65..5baf058a7c8 100644 --- a/freeldr/freeldr/arch/Makefile +++ b/freeldr/freeldr/arch/Makefile @@ -21,11 +21,13 @@ include ../rules.mk TARGET = i386 +OBJS = $(TARGET)/arch.S $(TARGET)/boot.S $(TARGET)/mb.S $(TARGET)/mem.S $(TARGET)/disk.S + .PHONY : clean all: arch.a -arch.a: +arch.a: $(OBJS) $(MAKE) -C $(TARGET) clean: diff --git a/freeldr/freeldr/arch/i386/disk.S b/freeldr/freeldr/arch/i386/disk.S index 0e8cdc55945..8b3c1979350 100644 --- a/freeldr/freeldr/arch/i386/disk.S +++ b/freeldr/freeldr/arch/i386/disk.S @@ -385,8 +385,8 @@ EXTERN(_get_heads) int $0x13 jc _get_heads_error - incb %dh movzbl %dh,%edx + incl %edx movl %edx,_biosdisk_retval jmp _get_heads_done @@ -512,4 +512,94 @@ _get_sectors_done: ret +/* + * BOOL BiosInt13GetDriveParameters(ULONG Drive, PGEOMETRY Geometry); + */ +_bios_int13_cylinders: + .long 0 +_bios_int13_heads: + .long 0 +_bios_int13_sectors: + .long 0 +_bios_int13_bytes_per_sector: + .long 0 +_bios_int13_drive_parameters_struct_address: + .long 0 +EXTERN(_BiosInt13GetDriveParameters) + .code32 + + push %ebx + push %ecx + push %edx + push %edi + push %esi + push %es + + /* Get drive */ + movl 0x1c(%esp),%eax + movl %eax,_biosdisk_drive + movl 0x20(%esp),%eax + movl %eax,_bios_int13_drive_parameters_struct_address + + call switch_to_real + + .code16 + + movb $0x08,%ah + movb _biosdisk_drive,%dl + int $0x13 + jc _BiosInt13GetDriveParameters_Error + + // Get the heads + movzbl %dh,%eax + incl %eax + movl %eax,_bios_int13_heads + + // Get the sectors + movw %cx,%dx + andb $0x3f,%dl + movzbl %dl,%edx + movl %edx,_bios_int13_sectors + + // Get the cylinders + xorl %edx,%edx + andb $0xc0,%cl + shrb $0x06,%cl + movb %cl,%dh + movb %ch,%dl + incl %edx + movl %edx,_bios_int13_cylinders + + // Get the bytes per sector + movl $512,_bios_int13_bytes_per_sector // Just assume 512 bytes per sector + movl $0x01,_biosdisk_retval + jmp _BiosInt13GetDriveParameters_Done + +_BiosInt13GetDriveParameters_Error: + movl $0x00,_biosdisk_retval + +_BiosInt13GetDriveParameters_Done: + + call switch_to_prot + + .code32 + + // Copy drive parameters to structure + movl $_bios_int13_cylinders,%esi + movl _bios_int13_drive_parameters_struct_address,%edi + movl $0x04,%ecx + cld + rep movsl + + movl _biosdisk_retval,%eax // Get return value + + pop %es + pop %esi + pop %edi + pop %edx + pop %ecx + pop %ebx + + ret + diff --git a/freeldr/freeldr/cache/blocklist.c b/freeldr/freeldr/cache/blocklist.c index 3b899b66d36..18028841483 100644 --- a/freeldr/freeldr/cache/blocklist.c +++ b/freeldr/freeldr/cache/blocklist.c @@ -122,7 +122,7 @@ PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNu } // Now try to read in the block - if (!DiskReadMultipleLogicalSectors(CacheDrive->DriveNumber, (BlockNumber * CacheDrive->BlockSize), CacheDrive->BlockSize, (PVOID)DISKREADBUFFER)) + if (!DiskReadLogicalSectors(CacheDrive->DriveNumber, (BlockNumber * CacheDrive->BlockSize), CacheDrive->BlockSize, (PVOID)DISKREADBUFFER)) { FreeMemory(CacheBlock->BlockData); FreeMemory(CacheBlock); diff --git a/freeldr/freeldr/debug.c b/freeldr/freeldr/debug.c index dfdafbf8975..9f93e05caf8 100644 --- a/freeldr/freeldr/debug.c +++ b/freeldr/freeldr/debug.c @@ -39,11 +39,12 @@ ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | #define BOCHS_OUTPUT_PORT 0xe9 -//ULONG DebugPort = RS232; +ULONG DebugPort = RS232; //ULONG DebugPort = SCREEN; -ULONG DebugPort = BOCHS; +//ULONG DebugPort = BOCHS; ULONG ComPort = COM1; -ULONG BaudRate = 19200; +//ULONG BaudRate = 19200; +ULONG BaudRate = 115200; BOOL DebugStartOfLine = TRUE; diff --git a/freeldr/freeldr/disk.h b/freeldr/freeldr/disk.h index f00a6228399..d9232e84b3c 100644 --- a/freeldr/freeldr/disk.h +++ b/freeldr/freeldr/disk.h @@ -30,6 +30,55 @@ typedef struct _GEOMETRY } GEOMETRY, *PGEOMETRY; +// +// Define the structure of a partition table entry +// +typedef struct _PARTITION_TABLE_ENTRY +{ + BYTE BootIndicator; // 0x00 - non-bootable partition, 0x80 - bootable partition (one partition only) + BYTE StartHead; // Beginning head number + BYTE StartSector; // Beginning sector (2 high bits of cylinder #) + BYTE StartCylinder; // Beginning cylinder# (low order bits of cylinder #) + BYTE SystemIndicator; // System indicator + BYTE EndHead; // Ending head number + BYTE EndSector; // Ending sector (2 high bits of cylinder #) + BYTE EndCylinder; // Ending cylinder# (low order bits of cylinder #) + DWORD SectorCountBeforePartition; // Number of sectors preceding the partition + DWORD PartitionSectorCount; // Number of sectors in the partition + +} PACKED PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY; + +// +// Define the structure of the master boot record +// +typedef struct _MASTER_BOOT_RECORD +{ + BYTE MasterBootRecordCodeAndData[0x1be]; + PARTITION_TABLE_ENTRY PartitionTable[4]; + WORD MasterBootRecordMagic; + +} PACKED MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD; + +// +// Partition type defines +// +#define PARTITION_ENTRY_UNUSED 0x00 // Entry unused +#define PARTITION_FAT_12 0x01 // 12-bit FAT entries +#define PARTITION_XENIX_1 0x02 // Xenix +#define PARTITION_XENIX_2 0x03 // Xenix +#define PARTITION_FAT_16 0x04 // 16-bit FAT entries +#define PARTITION_EXTENDED 0x05 // Extended partition entry +#define PARTITION_HUGE 0x06 // Huge partition MS-DOS V4 +#define PARTITION_IFS 0x07 // IFS Partition +#define PARTITION_OS2BOOTMGR 0x0A // OS/2 Boot Manager/OPUS/Coherent swap +#define PARTITION_FAT32 0x0B // FAT32 +#define PARTITION_FAT32_XINT13 0x0C // FAT32 using extended int13 services +#define PARTITION_XINT13 0x0E // Win95 partition using extended int13 services +#define PARTITION_XINT13_EXTENDED 0x0F // Same as type 5 but uses extended int13 services +#define PARTITION_PREP 0x41 // PowerPC Reference Platform (PReP) Boot Partition +#define PARTITION_LDM 0x42 // Logical Disk Manager partition +#define PARTITION_UNIX 0x63 // Unix + /////////////////////////////////////////////////////////////////////////////////////// // // BIOS Disk Functions @@ -46,6 +95,7 @@ void stop_floppy(void); // Implemented in asmcode.S int get_heads(int drive); // Implemented in asmcode.S int get_cylinders(int drive); // Implemented in asmcode.S int get_sectors(int drive); // Implemented in asmcode.S +BOOL BiosInt13GetDriveParameters(ULONG Drive, PGEOMETRY Geometry); // Implemented in disk.S /////////////////////////////////////////////////////////////////////////////////////// // @@ -54,8 +104,18 @@ int get_sectors(int drive); // Implemented in asmcode.S /////////////////////////////////////////////////////////////////////////////////////// VOID DiskError(PUCHAR ErrorString); BOOL DiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY DriveGeometry); -BOOL DiskSetDriveGeometry(ULONG DriveNumber, ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector); -BOOL DiskReadMultipleLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer); -BOOL DiskReadLogicalSector(ULONG DriveNumber, ULONG SectorNumber, PVOID Buffer); +BOOL DiskReadLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer); + +/////////////////////////////////////////////////////////////////////////////////////// +// +// Fixed Disk Partition Management Functions +// +/////////////////////////////////////////////////////////////////////////////////////// +BOOL DiskIsDriveRemovable(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 DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry); +BOOL DiskReadBootRecord(ULONG DriveNumber, ULONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord); #endif // defined __DISK_H diff --git a/freeldr/freeldr/disk/Makefile b/freeldr/freeldr/disk/Makefile index 9f95c12cad9..2d918bb489c 100644 --- a/freeldr/freeldr/disk/Makefile +++ b/freeldr/freeldr/disk/Makefile @@ -19,7 +19,7 @@ include ../rules.mk -OBJS = disk.o geometry.o +OBJS = disk.o geometry.o partition.o .PHONY : clean @@ -34,6 +34,9 @@ disk.o: disk.c ../disk.h geometry.o: geometry.c ../disk.h $(CC) $(FLAGS) -o geometry.o -c geometry.c +partition.o: partition.c ../disk.h + $(CC) $(FLAGS) -o partition.o -c partition.c + clean: - $(RM) *.o - $(RM) *.a diff --git a/freeldr/freeldr/disk/disk.c b/freeldr/freeldr/disk/disk.c index 9abe85108b7..eafe8787266 100644 --- a/freeldr/freeldr/disk/disk.c +++ b/freeldr/freeldr/disk/disk.c @@ -50,7 +50,7 @@ VOID DiskError(PUCHAR ErrorString) } } -BOOL DiskReadMultipleLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer) +BOOL DiskReadLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer) { ULONG PhysicalSector; ULONG PhysicalHead; @@ -151,76 +151,3 @@ BOOL DiskReadMultipleLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG return TRUE; } - -BOOL DiskReadLogicalSector(ULONG DriveNumber, ULONG SectorNumber, PVOID Buffer) -{ - ULONG PhysicalSector; - ULONG PhysicalHead; - ULONG PhysicalTrack; - GEOMETRY DriveGeometry; - - DbgPrint((DPRINT_DISK, "ReadLogicalSector() DriveNumber: 0x%x SectorNumber: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, Buffer)); - - // - // Check to see if it is a fixed disk drive - // If so then check to see if Int13 extensions work - // If they do then use them, otherwise default back to BIOS calls - // - if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber))) - { - DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE")); - - // - // LBA is easy, nothing to calculate - // Just do the read - // - if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer)) - { - DiskError("Disk read error."); - return FALSE; - } - } - else - { - // - // Get the drive geometry - // - if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry)) - { - return FALSE; - } - - // - // Calculate the physical disk offsets - // - PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors); - PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads; - PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads; - - DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead)); - DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack)); - DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector)); - - // - // Make sure the read is within the geometry boundaries - // - if ((PhysicalHead >= DriveGeometry.Heads) || - (PhysicalTrack >= DriveGeometry.Cylinders) || - (PhysicalSector > DriveGeometry.Sectors)) - { - DiskError("Disk read exceeds drive geometry limits."); - return FALSE; - } - - // - // Perform the read - // - if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, 1, Buffer)) - { - DiskError("Disk read error."); - return FALSE; - } - } - - return TRUE; -} diff --git a/freeldr/freeldr/disk/geometry.c b/freeldr/freeldr/disk/geometry.c index e28313f71e7..61f25616f69 100644 --- a/freeldr/freeldr/disk/geometry.c +++ b/freeldr/freeldr/disk/geometry.c @@ -23,104 +23,15 @@ #include -typedef struct -{ - LIST_ITEM ListEntry; - - ULONG DriveNumber; - GEOMETRY DriveGeometry; - -} DRIVE_GEOMETRY, *PDRIVE_GEOMETRY; - - -PDRIVE_GEOMETRY DriveGeometryListHead = NULL; - - BOOL DiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY DriveGeometry) { - PDRIVE_GEOMETRY DriveGeometryListEntry; - - // - // Search the drive geometry list for the requested drive - // - DriveGeometryListEntry = DriveGeometryListHead; - while (DriveGeometryListEntry != NULL) - { - // - // Check to see if this is the drive we want - // - if (DriveGeometryListEntry->DriveNumber == DriveNumber) - { - // - // Yep - return the information - // - RtlCopyMemory(DriveGeometry, &DriveGeometryListEntry->DriveGeometry, sizeof(GEOMETRY)); - return TRUE; - } - - // - // Nope, get next item - // - DriveGeometryListEntry = (PDRIVE_GEOMETRY)RtlListGetNext((PLIST_ITEM)DriveGeometryListEntry); - } - - DiskError("Drive geometry unknown."); - return FALSE; -} - -BOOL DiskSetDriveGeometry(ULONG DriveNumber, ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector) -{ - PDRIVE_GEOMETRY DriveGeometryListEntry; - - // - // Search the drive geometry list for the requested drive - // - DriveGeometryListEntry = DriveGeometryListHead; - while (DriveGeometryListEntry != NULL) - { - // - // Check to see if this is the drive - // - if (DriveGeometryListEntry->DriveNumber == DriveNumber) - { - // - // Yes, we already have this drive's geometry information - // so just return - // - return TRUE; - } - - // - // Nope, get next item - // - DriveGeometryListEntry = (PDRIVE_GEOMETRY)RtlListGetNext((PLIST_ITEM)DriveGeometryListEntry); - } - - // - // If we get here then this is a new drive and we have - // to add it's information to our list - // - DriveGeometryListEntry = (PDRIVE_GEOMETRY)AllocateMemory(sizeof(DRIVE_GEOMETRY)); - if (DriveGeometryListEntry == NULL) + // For now just return the geometry as the BIOS reports it + // BytesPerSector is always set to 512 by BiosInt13GetDriveParameters() + if (!BiosInt13GetDriveParameters(DriveNumber, DriveGeometry)) { + DiskError("Drive geometry unknown."); return FALSE; } - RtlZeroMemory(DriveGeometryListEntry, sizeof(DRIVE_GEOMETRY)); - DriveGeometryListEntry->DriveNumber = DriveNumber; - DriveGeometryListEntry->DriveGeometry.Cylinders = Cylinders; - DriveGeometryListEntry->DriveGeometry.Heads = Heads; - DriveGeometryListEntry->DriveGeometry.Sectors = Sectors; - DriveGeometryListEntry->DriveGeometry.BytesPerSector = BytesPerSector; - - if (DriveGeometryListHead == NULL) - { - DriveGeometryListHead = DriveGeometryListEntry; - } - else - { - RtlListInsertTail((PLIST_ITEM)DriveGeometryListHead, (PLIST_ITEM)DriveGeometryListEntry); - } - return TRUE; } diff --git a/freeldr/freeldr/disk/partition.c b/freeldr/freeldr/disk/partition.c new file mode 100644 index 00000000000..89cf40a626d --- /dev/null +++ b/freeldr/freeldr/disk/partition.c @@ -0,0 +1,233 @@ +/* + * FreeLoader + * Copyright (C) 1998-2002 Brian Palmer + * + * 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 +#include +#include +#include +#include + + + +BOOL DiskIsDriveRemovable(ULONG DriveNumber) +{ + // Hard disks use drive numbers >= 0x80 + // So if the drive number indicates a hard disk + // then return FALSE + if (DriveNumber >= 0x80) + { + return FALSE; + } + + // Drive is a floppy diskette so return TRUE + return TRUE; +} + +BOOL DiskGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) +{ + ULONG BootablePartitionCount = 0; + MASTER_BOOT_RECORD MasterBootRecord; + + // Read master boot record + if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord)) + { + return FALSE; + } + + // Count the bootable partitions + if (MasterBootRecord.PartitionTable[0].BootIndicator == 0x80) + { + BootablePartitionCount++; + BootPartition = 0; + } + if (MasterBootRecord.PartitionTable[1].BootIndicator == 0x80) + { + BootablePartitionCount++; + BootPartition = 1; + } + if (MasterBootRecord.PartitionTable[2].BootIndicator == 0x80) + { + BootablePartitionCount++; + BootPartition = 2; + } + if (MasterBootRecord.PartitionTable[3].BootIndicator == 0x80) + { + BootablePartitionCount++; + BootPartition = 3; + } + + // Make sure there was only one bootable partition + if (BootablePartitionCount != 1) + { + DiskError("Too many bootable partitions or none found."); + return FALSE; + } + + // Copy the partition table entry + RtlCopyMemory(PartitionTableEntry, &MasterBootRecord.PartitionTable[BootPartition], sizeof(PARTITION_TABLE_ENTRY)); + + return TRUE; +} + +BOOL DiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) +{ + MASTER_BOOT_RECORD MasterBootRecord; + PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry; + ULONG ExtendedPartitionNumber; + ULONG Index; + + // Read master boot record + if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord)) + { + return FALSE; + } + + // If they are asking for a primary + // partition then things are easy + if (PartitionNumber < 5) + { + // PartitionNumber is one-based and we need it zero-based + PartitionNumber--; + + // Copy the partition table entry + RtlCopyMemory(PartitionTableEntry, &MasterBootRecord.PartitionTable[PartitionNumber], sizeof(PARTITION_TABLE_ENTRY)); + + return TRUE; + } + else + { + // They want an extended partition entry so we will need + // to loop through all the extended partitions on the disk + // and return the one they want. + + ExtendedPartitionNumber = PartitionNumber - 5; + + for (Index=0; Index<=ExtendedPartitionNumber; Index++) + { + // Get the extended partition table entry + if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord, &ExtendedPartitionTableEntry)) + { + return FALSE; + } + + // Read the partition boot record + if (!DiskReadBootRecord(DriveNumber, ExtendedPartitionTableEntry.SectorCountBeforePartition, &MasterBootRecord)) + { + return FALSE; + } + + // Get the first real partition table entry + if (!DiskGetFirstPartitionEntry(&MasterBootRecord, PartitionTableEntry)) + { + return FALSE; + } + } + + // When we get here we should have the correct entry + // already stored in PartitionTableEntry + // so just return TRUE + return TRUE; + } + +} + +BOOL DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry) +{ + ULONG Index; + + for (Index=0; Index<4; Index++) + { + // Check the system indicator + // If it's not an extended or unused partition + // then we're done + if ((MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_ENTRY_UNUSED) && + (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_EXTENDED) && + (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_XINT13_EXTENDED)) + { + RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY)); + return TRUE; + } + } + + return FALSE; +} + +BOOL DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry) +{ + ULONG Index; + + for (Index=0; Index<4; Index++) + { + // Check the system indicator + // If it an extended partition then we're done + if ((MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_EXTENDED) || + (MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_XINT13_EXTENDED)) + { + RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY)); + return TRUE; + } + } + + return FALSE; +} + +BOOL DiskReadBootRecord(ULONG DriveNumber, ULONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord) +{ + ULONG Index; + + // Read master boot record + if (!DiskReadLogicalSectors(DriveNumber, LogicalSectorNumber, 1, BootRecord)) + { + return FALSE; + } + + +#ifdef DEBUG + + DbgPrint((DPRINT_DISK, "Dumping partition table for drive 0x%x:\n", DriveNumber)); + DbgPrint((DPRINT_DISK, "Boot record logical start sector = %d\n", LogicalSectorNumber)); + DbgPrint((DPRINT_DISK, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD))); + + for (Index=0; Index<4; Index++) + { + DbgPrint((DPRINT_DISK, "-------------------------------------------\n")); + DbgPrint((DPRINT_DISK, "Partition %d\n", (Index + 1))); + DbgPrint((DPRINT_DISK, "BootIndicator: 0x%x\n", BootRecord->PartitionTable[Index].BootIndicator)); + DbgPrint((DPRINT_DISK, "StartHead: 0x%x\n", BootRecord->PartitionTable[Index].StartHead)); + DbgPrint((DPRINT_DISK, "StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].StartSector)); + DbgPrint((DPRINT_DISK, "StartCylinder: 0x%x\n", BootRecord->PartitionTable[Index].StartCylinder)); + DbgPrint((DPRINT_DISK, "SystemIndicator: 0x%x\n", BootRecord->PartitionTable[Index].SystemIndicator)); + DbgPrint((DPRINT_DISK, "EndHead: 0x%x\n", BootRecord->PartitionTable[Index].EndHead)); + DbgPrint((DPRINT_DISK, "EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].EndSector)); + DbgPrint((DPRINT_DISK, "EndCylinder: 0x%x\n", BootRecord->PartitionTable[Index].EndCylinder)); + DbgPrint((DPRINT_DISK, "SectorCountBeforePartition: 0x%x\n", BootRecord->PartitionTable[Index].SectorCountBeforePartition)); + DbgPrint((DPRINT_DISK, "PartitionSectorCount: 0x%x\n", BootRecord->PartitionTable[Index].PartitionSectorCount)); + } + +#endif // defined DEBUG + + // Check the partition table magic value + if (BootRecord->MasterBootRecordMagic != 0xaa55) + { + DiskError("Invalid partition table magic (0xaa55)"); + return FALSE; + } + + return TRUE; +} diff --git a/freeldr/freeldr/fs.h b/freeldr/freeldr/fs.h index 26aec03dbfa..3da03153e44 100644 --- a/freeldr/freeldr/fs.h +++ b/freeldr/freeldr/fs.h @@ -20,63 +20,16 @@ #ifndef __FS_H #define __FS_H -// -// Define the structure of a partition table entry -// -typedef struct _PARTITION_TABLE_ENTRY -{ - BYTE BootIndicator; // 0x00 - non-bootable partition, 0x80 - bootable partition (one partition only) - BYTE StartHead; // Beginning head number - BYTE StartSector; // Beginning sector (2 high bits of cylinder #) - BYTE StartCylinder; // Beginning cylinder# (low order bits of cylinder #) - BYTE SystemIndicator; // System indicator - BYTE EndHead; // Ending head number - BYTE EndSector; // Ending sector (2 high bits of cylinder #) - BYTE EndCylinder; // Ending cylinder# (low order bits of cylinder #) - DWORD SectorCountBeforePartition; // Number of sectors preceding the partition - DWORD PartitionSectorCount; // Number of sectors in the partition -} PACKED PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY; +#define EOF -1 -// -// This macro will return the cylinder when you pass it a cylinder/sector -// pair where the high 2 bits of the cylinder are stored in the sector byte -// -#define MAKE_CYLINDER(cylinder, sector) ( cylinder + ((((WORD)sector) & 0xC0) << 2) ) - -// -// Define the structure of the master boot record -// -typedef struct _MASTER_BOOT_RECORD -{ - BYTE MasterBootRecordCodeAndData[0x1be]; - PARTITION_TABLE_ENTRY PartitionTable[4]; - WORD MasterBootRecordMagic; - -} PACKED MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD; - -// -// Partition type defines -// -#define PARTITION_ENTRY_UNUSED 0x00 // Entry unused -#define PARTITION_FAT_12 0x01 // 12-bit FAT entries -#define PARTITION_XENIX_1 0x02 // Xenix -#define PARTITION_XENIX_2 0x03 // Xenix -#define PARTITION_FAT_16 0x04 // 16-bit FAT entries -#define PARTITION_EXTENDED 0x05 // Extended partition entry -#define PARTITION_HUGE 0x06 // Huge partition MS-DOS V4 -#define PARTITION_IFS 0x07 // IFS Partition -#define PARTITION_OS2BOOTMGR 0x0A // OS/2 Boot Manager/OPUS/Coherent swap -#define PARTITION_FAT32 0x0B // FAT32 -#define PARTITION_FAT32_XINT13 0x0C // FAT32 using extended int13 services -#define PARTITION_XINT13 0x0E // Win95 partition using extended int13 services -#define PARTITION_XINT13_EXTENDED 0x0F // Same as type 5 but uses extended int13 services -#define PARTITION_PREP 0x41 // PowerPC Reference Platform (PReP) Boot Partition -#define PARTITION_LDM 0x42 // Logical Disk Manager partition -#define PARTITION_UNIX 0x63 // Unix +#define FS_FAT 1 +#define FS_NTFS 2 +#define FS_EXT2 3 +#define FS_REISER 4 -#define FILE VOID -#define PFILE FILE * +#define FILE VOID +#define PFILE FILE * VOID FileSystemError(PUCHAR ErrorString); BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber); @@ -88,11 +41,4 @@ VOID SetFilePointer(PFILE FileHandle, ULONG NewFilePointer); ULONG GetFilePointer(PFILE FileHandle); BOOL IsEndOfFile(PFILE FileHandle); - -#define EOF -1 - -#define FS_FAT 1 -#define FS_NTFS 2 -#define FS_EXT2 3 - #endif // #defined __FS_H diff --git a/freeldr/freeldr/fs/fat.c b/freeldr/freeldr/fs/fat.c index ca09a7e5350..b9bdecc84bc 100644 --- a/freeldr/freeldr/fs/fat.c +++ b/freeldr/freeldr/fs/fat.c @@ -43,9 +43,6 @@ ULONG FatDriveNumber = 0; BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector) { - ULONG PhysicalTrack; - ULONG PhysicalHead; - ULONG PhysicalSector; DbgPrint((DPRINT_FILESYSTEM, "FatOpenVolume() DriveNumber = 0x%x VolumeStartSector = %d\n", DriveNumber, VolumeStartSector)); @@ -80,26 +77,9 @@ BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector) // Now try to read the boot sector // If this fails then abort - if (BiosInt13ExtensionsSupported(DriveNumber)) + if (!DiskReadLogicalSectors(DriveNumber, VolumeStartSector, 1, FatVolumeBootSector)) { - if (!BiosInt13ReadExtended(DriveNumber, VolumeStartSector, 1, FatVolumeBootSector)) - { - FileSystemError("Disk read error."); - return FALSE; - } - } - else - { - // Calculate the physical disk offsets - PhysicalSector = 1 + (VolumeStartSector % get_sectors(DriveNumber)); - PhysicalHead = (VolumeStartSector / get_sectors(DriveNumber)) % get_heads(DriveNumber); - PhysicalTrack = (VolumeStartSector / get_sectors(DriveNumber)) / get_heads(DriveNumber); - - if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, 1, FatVolumeBootSector)) - { - FileSystemError("Disk read error."); - return FALSE; - } + return FALSE; } // Get the FAT type @@ -180,14 +160,6 @@ BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector) return FALSE; } - // - // Set the drive geometry - // - if (!DiskSetDriveGeometry(DriveNumber, get_cylinders(DriveNumber), get_heads(DriveNumber), get_sectors(DriveNumber), FatVolumeBootSector->BytesPerSector)) - { - return FALSE; - } - // // Check the FAT cluster size // We do not support clusters bigger than 64k diff --git a/freeldr/freeldr/fs/filesys.h b/freeldr/freeldr/fs/filesys.h deleted file mode 100644 index 5184c8a4766..00000000000 --- a/freeldr/freeldr/fs/filesys.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * FreeLoader - * Copyright (C) 1998-2002 Brian Palmer - * - * 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 - -#ifndef __FILESYS_H -#define __FILESYS_H - -BOOL FsInternalIsDiskPartitioned(ULONG DriveNumber); // Returns TRUE if the disk contains partitions, FALSE if floppy disk -BOOL FsInternalGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); // Returns the active partition table entry -BOOL FsInternalGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); // Returns the active partition table entry -ULONG FsInternalGetPartitionCount(ULONG DriveNumber); // Returns the number of partitions on the disk - -#endif // #defined __FILESYS_H diff --git a/freeldr/freeldr/fs/fs.c b/freeldr/freeldr/fs/fs.c index 331cfb88351..eebf2ac78a5 100644 --- a/freeldr/freeldr/fs/fs.c +++ b/freeldr/freeldr/fs/fs.c @@ -19,7 +19,6 @@ #include #include -#include "filesys.h" #include "fat.h" #include #include @@ -71,14 +70,13 @@ VOID FileSystemError(PUCHAR ErrorString) */ BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber) { - MASTER_BOOT_RECORD DriveMasterBootRecord; PARTITION_TABLE_ENTRY PartitionTableEntry; DbgPrint((DPRINT_FILESYSTEM, "OpenDiskDrive() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber)); // Check and see if it is a floppy drive // If so then just assume FAT12 file system type - if (FsInternalIsDiskPartitioned(DriveNumber) == FALSE) + if (DiskIsDriveRemovable(DriveNumber)) { DbgPrint((DPRINT_FILESYSTEM, "Drive is a floppy diskette drive. Assuming FAT12 file system.\n")); @@ -86,52 +84,14 @@ BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber) return FatOpenVolume(DriveNumber, 0); } - // - // Read master boot record - // - if (!BiosInt13Read(DriveNumber, 0, 0, 1, 1, &DriveMasterBootRecord)) - { - FileSystemError("Disk read error."); - return FALSE; - } - - -#ifdef DEBUG - - DbgPrint((DPRINT_FILESYSTEM, "Drive is a hard disk, dumping partition table:\n")); - DbgPrint((DPRINT_FILESYSTEM, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD))); - - for (BootPartition=0; BootPartition<4; BootPartition++) - { - DbgPrint((DPRINT_FILESYSTEM, "-------------------------------------------\n")); - DbgPrint((DPRINT_FILESYSTEM, "Partition %d\n", (BootPartition + 1))); - DbgPrint((DPRINT_FILESYSTEM, "BootIndicator: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].BootIndicator)); - DbgPrint((DPRINT_FILESYSTEM, "StartHead: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartHead)); - DbgPrint((DPRINT_FILESYSTEM, "StartSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartSector)); - DbgPrint((DPRINT_FILESYSTEM, "StartCylinder: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartCylinder)); - DbgPrint((DPRINT_FILESYSTEM, "SystemIndicator: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].SystemIndicator)); - DbgPrint((DPRINT_FILESYSTEM, "EndHead: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndHead)); - DbgPrint((DPRINT_FILESYSTEM, "EndSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndSector)); - DbgPrint((DPRINT_FILESYSTEM, "EndCylinder: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndCylinder)); - DbgPrint((DPRINT_FILESYSTEM, "SectorCountBeforePartition: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].SectorCountBeforePartition)); - DbgPrint((DPRINT_FILESYSTEM, "PartitionSectorCount: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].PartitionSectorCount)); - } - -#endif // defined DEBUG - - - // Check the partition table magic value - if (DriveMasterBootRecord.MasterBootRecordMagic != 0xaa55) - { - FileSystemError("Invalid partition table magic (0xaa55)"); - return FALSE; - } + // Set the boot partition + BootPartition = PartitionNumber; // Get the requested partition entry if (PartitionNumber == 0) { // Partition requested was zero which means the boot partition - if (FsInternalGetActivePartitionEntry(DriveNumber, &PartitionTableEntry) == FALSE) + if (DiskGetActivePartitionEntry(DriveNumber, &PartitionTableEntry) == FALSE) { return FALSE; } @@ -139,7 +99,7 @@ BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber) else { // Get requested partition - if (FsInternalGetPartitionEntry(DriveNumber, PartitionNumber, &PartitionTableEntry) == FALSE) + if (DiskGetPartitionEntry(DriveNumber, PartitionNumber, &PartitionTableEntry) == FALSE) { return FALSE; } @@ -171,87 +131,6 @@ BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber) return TRUE; } -BOOL FsInternalIsDiskPartitioned(ULONG DriveNumber) -{ - // Hard disks use drive numbers >= 0x80 - // So if the drive number indicates a hard disk - // then return TRUE - if (DriveNumber >= 0x80) - { - return TRUE; - } - - // Drive is a floppy diskette so return FALSE - return FALSE; -} - -BOOL FsInternalGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) -{ - ULONG BootablePartitionCount = 0; - MASTER_BOOT_RECORD MasterBootRecord; - - // Read master boot record - if (!BiosInt13Read(DriveNumber, 0, 0, 1, 1, &MasterBootRecord)) - { - FileSystemError("Disk read error."); - return FALSE; - } - - // Count the bootable partitions - if (MasterBootRecord.PartitionTable[0].BootIndicator == 0x80) - { - BootablePartitionCount++; - BootPartition = 0; - } - if (MasterBootRecord.PartitionTable[1].BootIndicator == 0x80) - { - BootablePartitionCount++; - BootPartition = 1; - } - if (MasterBootRecord.PartitionTable[2].BootIndicator == 0x80) - { - BootablePartitionCount++; - BootPartition = 2; - } - if (MasterBootRecord.PartitionTable[3].BootIndicator == 0x80) - { - BootablePartitionCount++; - BootPartition = 3; - } - - // Make sure there was only one bootable partition - if (BootablePartitionCount != 1) - { - FileSystemError("Too many bootable partitions or none found."); - return FALSE; - } - - // Copy the partition table entry - RtlCopyMemory(PartitionTableEntry, &MasterBootRecord.PartitionTable[BootPartition], sizeof(PARTITION_TABLE_ENTRY)); - - return TRUE; -} - -BOOL FsInternalGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) -{ - MASTER_BOOT_RECORD MasterBootRecord; - - // Read master boot record - if (!BiosInt13Read(DriveNumber, 0, 0, 1, 1, &MasterBootRecord)) - { - FileSystemError("Disk read error."); - return FALSE; - } - - // PartitionNumber is one-based and we need it zero-based - PartitionNumber--; - - // Copy the partition table entry - RtlCopyMemory(PartitionTableEntry, &MasterBootRecord.PartitionTable[PartitionNumber], sizeof(PARTITION_TABLE_ENTRY)); - - return TRUE; -} - PFILE OpenFile(PUCHAR FileName) { PFILE FileHandle = NULL; diff --git a/freeldr/freeldr/multiboot.c b/freeldr/freeldr/multiboot.c index dd54d152174..123e5630273 100644 --- a/freeldr/freeldr/multiboot.c +++ b/freeldr/freeldr/multiboot.c @@ -254,4 +254,4 @@ BOOL MultiBootCloseModule(PVOID ModuleBase, DWORD dwModuleSize) } return(FALSE); -} \ No newline at end of file +} diff --git a/freeldr/freeldr/rules.mk b/freeldr/freeldr/rules.mk index 904b9c83abe..521c9a40a31 100644 --- a/freeldr/freeldr/rules.mk +++ b/freeldr/freeldr/rules.mk @@ -26,7 +26,7 @@ CP = cmd /C copy MAKE = make # For a release build uncomment this line -FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -I../ -I../../ -O3 +#FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -I../ -I../../ -O3 # For a debug build uncomment this line -#FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -I../ -I../../ -DDEBUG -O3 +FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -I../ -I../../ -DDEBUG -O3 -- 2.17.1