* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+/*
+ * TODO: This is here where we should add support for GPT partitions
+ * as well as partitionless disks!
+ */
+
#ifndef _M_ARM
#include <freeldr.h>
+
#include <debug.h>
DBG_DEFAULT_CHANNEL(DISK);
+/* This function serves to retrieve a partition entry for devices that handle partitions differently */
+DISK_GET_PARTITION_ENTRY DiskGetPartitionEntry = DiskGetMbrPartitionEntry;
+
BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber,
- PPARTITION_TABLE_ENTRY PartitionTableEntry,
- ULONG *ActivePartition)
+ PPARTITION_TABLE_ENTRY PartitionTableEntry,
+ ULONG *ActivePartition)
{
- ULONG BootablePartitionCount = 0;
- MASTER_BOOT_RECORD MasterBootRecord;
-
- *ActivePartition = 0;
- // Read master boot record
- if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord))
- {
- return FALSE;
- }
-
- // Count the bootable partitions
- if (MasterBootRecord.PartitionTable[0].BootIndicator == 0x80)
- {
- BootablePartitionCount++;
- *ActivePartition = 1;
- }
- if (MasterBootRecord.PartitionTable[1].BootIndicator == 0x80)
- {
- BootablePartitionCount++;
- *ActivePartition = 2;
- }
- if (MasterBootRecord.PartitionTable[2].BootIndicator == 0x80)
- {
- BootablePartitionCount++;
- *ActivePartition = 3;
- }
- if (MasterBootRecord.PartitionTable[3].BootIndicator == 0x80)
- {
- BootablePartitionCount++;
- *ActivePartition = 4;
- }
-
- // Make sure there was only one bootable partition
- if (BootablePartitionCount == 0)
- {
- ERR("No bootable (active) partitions found.\n");
- return FALSE;
- }
- else if (BootablePartitionCount != 1)
- {
- ERR("Too many bootable (active) partitions found.\n");
- return FALSE;
- }
-
- // Copy the partition table entry
- RtlCopyMemory(PartitionTableEntry,
- &MasterBootRecord.PartitionTable[*ActivePartition - 1],
- sizeof(PARTITION_TABLE_ENTRY));
-
- return TRUE;
+ ULONG BootablePartitionCount = 0;
+ ULONG CurrentPartitionNumber;
+ ULONG Index;
+ MASTER_BOOT_RECORD MasterBootRecord;
+ PPARTITION_TABLE_ENTRY ThisPartitionTableEntry;
+
+ *ActivePartition = 0;
+
+ // Read master boot record
+ if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord))
+ {
+ return FALSE;
+ }
+
+ CurrentPartitionNumber = 0;
+ for (Index=0; Index<4; Index++)
+ {
+ ThisPartitionTableEntry = &MasterBootRecord.PartitionTable[Index];
+
+ if (ThisPartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED &&
+ ThisPartitionTableEntry->SystemIndicator != PARTITION_EXTENDED &&
+ ThisPartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED)
+ {
+ CurrentPartitionNumber++;
+
+ // Test if this is the bootable partition
+ if (ThisPartitionTableEntry->BootIndicator == 0x80)
+ {
+ BootablePartitionCount++;
+ *ActivePartition = CurrentPartitionNumber;
+
+ // Copy the partition table entry
+ RtlCopyMemory(PartitionTableEntry,
+ ThisPartitionTableEntry,
+ sizeof(PARTITION_TABLE_ENTRY));
+ }
+ }
+ }
+
+ // Make sure there was only one bootable partition
+ if (BootablePartitionCount == 0)
+ {
+ ERR("No bootable (active) partitions found.\n");
+ return FALSE;
+ }
+ else if (BootablePartitionCount != 1)
+ {
+ ERR("Too many bootable (active) partitions found.\n");
+ return FALSE;
+ }
+
+ return TRUE;
}
-BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
+BOOLEAN DiskGetMbrPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
{
- MASTER_BOOT_RECORD MasterBootRecord;
- PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry;
- ULONG ExtendedPartitionNumber;
- ULONG ExtendedPartitionOffset;
- 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;
-
- // Set the initial relative starting sector to 0
- // This is because extended partition starting
- // sectors a numbered relative to their parent
- ExtendedPartitionOffset = 0;
-
- for (Index=0; Index<=ExtendedPartitionNumber; Index++)
- {
- // Get the extended partition table entry
- if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord, &ExtendedPartitionTableEntry))
- {
- return FALSE;
- }
-
- // Adjust the relative starting sector of the partition
- ExtendedPartitionTableEntry.SectorCountBeforePartition += ExtendedPartitionOffset;
- if (ExtendedPartitionOffset == 0)
- {
- // Set the start of the parrent extended partition
- ExtendedPartitionOffset = ExtendedPartitionTableEntry.SectorCountBeforePartition;
- }
- // 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;
- }
-
- // Now correct the start sector of the partition
- PartitionTableEntry->SectorCountBeforePartition += ExtendedPartitionTableEntry.SectorCountBeforePartition;
- }
-
- // When we get here we should have the correct entry
- // already stored in PartitionTableEntry
- // so just return TRUE
- return TRUE;
- }
+ MASTER_BOOT_RECORD MasterBootRecord;
+ PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry;
+ ULONG ExtendedPartitionNumber;
+ ULONG ExtendedPartitionOffset;
+ ULONG Index;
+ ULONG CurrentPartitionNumber;
+ PPARTITION_TABLE_ENTRY ThisPartitionTableEntry;
+
+ // Read master boot record
+ if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord))
+ {
+ return FALSE;
+ }
+
+ CurrentPartitionNumber = 0;
+ for (Index=0; Index<4; Index++)
+ {
+ ThisPartitionTableEntry = &MasterBootRecord.PartitionTable[Index];
+
+ if (ThisPartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED &&
+ ThisPartitionTableEntry->SystemIndicator != PARTITION_EXTENDED &&
+ ThisPartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED)
+ {
+ CurrentPartitionNumber++;
+ }
+
+ if (PartitionNumber == CurrentPartitionNumber)
+ {
+ RtlCopyMemory(PartitionTableEntry, ThisPartitionTableEntry, sizeof(PARTITION_TABLE_ENTRY));
+ return TRUE;
+ }
+ }
+
+ // 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 - CurrentPartitionNumber - 1;
+
+ // Set the initial relative starting sector to 0
+ // This is because extended partition starting
+ // sectors a numbered relative to their parent
+ ExtendedPartitionOffset = 0;
+
+ for (Index=0; Index<=ExtendedPartitionNumber; Index++)
+ {
+ // Get the extended partition table entry
+ if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord, &ExtendedPartitionTableEntry))
+ {
+ return FALSE;
+ }
+
+ // Adjust the relative starting sector of the partition
+ ExtendedPartitionTableEntry.SectorCountBeforePartition += ExtendedPartitionOffset;
+ if (ExtendedPartitionOffset == 0)
+ {
+ // Set the start of the parrent extended partition
+ ExtendedPartitionOffset = ExtendedPartitionTableEntry.SectorCountBeforePartition;
+ }
+ // 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;
+ }
+ // Now correct the start sector of the partition
+ PartitionTableEntry->SectorCountBeforePartition += ExtendedPartitionTableEntry.SectorCountBeforePartition;
+ }
+
+ // When we get here we should have the correct entry
+ // already stored in PartitionTableEntry
+ // so just return TRUE
+ return TRUE;
}
BOOLEAN 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;
+ 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;
}
BOOLEAN 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;
+ 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;
}
BOOLEAN DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord)
{
- ULONG Index;
-
- // Read master boot record
- if (!MachDiskReadLogicalSectors(DriveNumber, LogicalSectorNumber, 1, (PVOID)DISKREADBUFFER))
- {
- return FALSE;
- }
- RtlCopyMemory(BootRecord, (PVOID)DISKREADBUFFER, sizeof(MASTER_BOOT_RECORD));
-
-
- TRACE("Dumping partition table for drive 0x%x:\n", DriveNumber);
- TRACE("Boot record logical start sector = %d\n", LogicalSectorNumber);
- TRACE("sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD));
-
- for (Index=0; Index<4; Index++)
- {
- TRACE("-------------------------------------------\n");
- TRACE("Partition %d\n", (Index + 1));
- TRACE("BootIndicator: 0x%x\n", BootRecord->PartitionTable[Index].BootIndicator);
- TRACE("StartHead: 0x%x\n", BootRecord->PartitionTable[Index].StartHead);
- TRACE("StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].StartSector);
- TRACE("StartCylinder: 0x%x\n", BootRecord->PartitionTable[Index].StartCylinder);
- TRACE("SystemIndicator: 0x%x\n", BootRecord->PartitionTable[Index].SystemIndicator);
- TRACE("EndHead: 0x%x\n", BootRecord->PartitionTable[Index].EndHead);
- TRACE("EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].EndSector);
- TRACE("EndCylinder: 0x%x\n", BootRecord->PartitionTable[Index].EndCylinder);
- TRACE("SectorCountBeforePartition: 0x%x\n", BootRecord->PartitionTable[Index].SectorCountBeforePartition);
- TRACE("PartitionSectorCount: 0x%x\n", BootRecord->PartitionTable[Index].PartitionSectorCount);
- }
-
- // Check the partition table magic value
- if (BootRecord->MasterBootRecordMagic != 0xaa55)
- {
- return FALSE;
- }
-
- return TRUE;
+ ULONG Index;
+
+ // Read master boot record
+ if (!MachDiskReadLogicalSectors(DriveNumber, LogicalSectorNumber, 1, DiskReadBuffer))
+ {
+ return FALSE;
+ }
+ RtlCopyMemory(BootRecord, DiskReadBuffer, sizeof(MASTER_BOOT_RECORD));
+
+ TRACE("Dumping partition table for drive 0x%x:\n", DriveNumber);
+ TRACE("Boot record logical start sector = %d\n", LogicalSectorNumber);
+ TRACE("sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD));
+
+ for (Index=0; Index<4; Index++)
+ {
+ TRACE("-------------------------------------------\n");
+ TRACE("Partition %d\n", (Index + 1));
+ TRACE("BootIndicator: 0x%x\n", BootRecord->PartitionTable[Index].BootIndicator);
+ TRACE("StartHead: 0x%x\n", BootRecord->PartitionTable[Index].StartHead);
+ TRACE("StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].StartSector);
+ TRACE("StartCylinder: 0x%x\n", BootRecord->PartitionTable[Index].StartCylinder);
+ TRACE("SystemIndicator: 0x%x\n", BootRecord->PartitionTable[Index].SystemIndicator);
+ TRACE("EndHead: 0x%x\n", BootRecord->PartitionTable[Index].EndHead);
+ TRACE("EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].EndSector);
+ TRACE("EndCylinder: 0x%x\n", BootRecord->PartitionTable[Index].EndCylinder);
+ TRACE("SectorCountBeforePartition: 0x%x\n", BootRecord->PartitionTable[Index].SectorCountBeforePartition);
+ TRACE("PartitionSectorCount: 0x%x\n", BootRecord->PartitionTable[Index].PartitionSectorCount);
+ }
+
+ // Check the partition table magic value
+ if (BootRecord->MasterBootRecordMagic != 0xaa55)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
}
+#ifndef _M_AMD64
NTSTATUS
NTAPI
IopReadBootRecord(
IN ULONG SectorSize,
OUT PMASTER_BOOT_RECORD BootRecord)
{
- ULONG FileId = (ULONG)DeviceObject;
+ ULONG_PTR FileId = (ULONG_PTR)DeviceObject;
LARGE_INTEGER Position;
ULONG BytesRead;
- ULONG Status;
+ ARC_STATUS Status;
Position.QuadPart = LogicalSectorNumber * SectorSize;
Status = ArcSeek(FileId, &Position, SeekAbsolute);
*PartitionBuffer = Partitions;
return STATUS_SUCCESS;
}
-
+#endif // _M_AMD64
#endif