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
This commit is contained in:
Brian Palmer 2002-02-26 00:26:35 +00:00
parent f83db8cc84
commit c66e8c39d3
15 changed files with 421 additions and 427 deletions

View file

@ -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:

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -23,104 +23,15 @@
#include <mm.h>
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;
}

View file

@ -0,0 +1,233 @@
/*
* 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 <disk.h>
#include <rtl.h>
#include <mm.h>
#include <debug.h>
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;
}

View file

@ -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 FS_FAT 1
#define FS_NTFS 2
#define FS_EXT2 3
#define FS_REISER 4
//
// 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 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

View file

@ -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

View file

@ -1,30 +0,0 @@
/*
* 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 <fs.h>
#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

View file

@ -19,7 +19,6 @@
#include <freeldr.h>
#include <fs.h>
#include "filesys.h"
#include "fat.h"
#include <disk.h>
#include <rtl.h>
@ -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;

View file

@ -254,4 +254,4 @@ BOOL MultiBootCloseModule(PVOID ModuleBase, DWORD dwModuleSize)
}
return(FALSE);
}
}

View file

@ -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