diff --git a/boot/freeldr/freeldr/arch/i386/hwdisk.c b/boot/freeldr/freeldr/arch/i386/hwdisk.c index 826780a07fb..50bb00e8406 100644 --- a/boot/freeldr/freeldr/arch/i386/hwdisk.c +++ b/boot/freeldr/freeldr/arch/i386/hwdisk.c @@ -231,6 +231,9 @@ GetHarddiskInformation(UCHAR DriveNumber) PARTITION_TABLE_ENTRY PartitionTableEntry; PCHAR Identifier = PcDiskIdentifier[DriveNumber - 0x80]; + /* Detect disk partition type */ + DiskDetectPartitionType(DriveNumber); + /* Read the MBR */ if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer)) { diff --git a/boot/freeldr/freeldr/arch/i386/machpc.c b/boot/freeldr/freeldr/arch/i386/machpc.c index 497f89b5483..5ec2195638a 100644 --- a/boot/freeldr/freeldr/arch/i386/machpc.c +++ b/boot/freeldr/freeldr/arch/i386/machpc.c @@ -1422,8 +1422,6 @@ PcMachInit(const char *CmdLine) MachVtbl.InitializeBootDevices = PcInitializeBootDevices; MachVtbl.HwDetect = PcHwDetect; MachVtbl.HwIdle = PcHwIdle; - - // DiskGetPartitionEntry = DiskGetMbrPartitionEntry; // Default } VOID diff --git a/boot/freeldr/freeldr/arch/i386/machxbox.c b/boot/freeldr/freeldr/arch/i386/machxbox.c index 350a0c3e1e7..139f5719251 100644 --- a/boot/freeldr/freeldr/arch/i386/machxbox.c +++ b/boot/freeldr/freeldr/arch/i386/machxbox.c @@ -231,8 +231,6 @@ XboxMachInit(const char *CmdLine) MachVtbl.HwDetect = XboxHwDetect; MachVtbl.HwIdle = XboxHwIdle; - DiskGetPartitionEntry = XboxDiskGetPartitionEntry; - /* Set LEDs to orange after init */ XboxSetLED("oooo"); } diff --git a/boot/freeldr/freeldr/arch/i386/xboxdisk.c b/boot/freeldr/freeldr/arch/i386/xboxdisk.c index 9e31ce9937d..e1e4d3559e7 100644 --- a/boot/freeldr/freeldr/arch/i386/xboxdisk.c +++ b/boot/freeldr/freeldr/arch/i386/xboxdisk.c @@ -30,25 +30,6 @@ DBG_DEFAULT_CHANNEL(DISK); #define XBOX_IDE_COMMAND_PORT 0x1f0 #define XBOX_IDE_CONTROL_PORT 0x170 -/* BRFR signature at disk offset 0x600 */ -#define XBOX_SIGNATURE_SECTOR 3 -#define XBOX_SIGNATURE ('B' | ('R' << 8) | ('F' << 16) | ('R' << 24)) - -static struct -{ - ULONG SectorCountBeforePartition; - ULONG PartitionSectorCount; - UCHAR SystemIndicator; -} XboxPartitions[] = -{ - /* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */ - { 0x0055F400, 0x0098f800, PARTITION_FAT32 }, /* Store , E: */ - { 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */ - { 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */ - { 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */ - { 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */ -}; - #define IDE_SECTOR_BUF_SZ 512 #define IDE_MAX_POLL_RETRIES 100000 #define IDE_MAX_BUSY_RETRIES 50000 @@ -471,32 +452,6 @@ XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG Sect return TRUE; } -BOOLEAN -XboxDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) -{ - UCHAR SectorData[IDE_SECTOR_BUF_SZ]; - - /* - * This is the Xbox, chances are that there is a Xbox-standard - * partitionless disk in it so let's check that first. - */ - if (PartitionNumber >= 1 && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) && - MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, SectorData)) - { - if (*((PULONG) SectorData) == XBOX_SIGNATURE) - { - memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY)); - PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator; - PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition; - PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount; - return TRUE; - } - } - - /* No magic Xbox partitions, maybe there's a MBR */ - return DiskGetMbrPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry); -} - BOOLEAN XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry) { diff --git a/boot/freeldr/freeldr/disk/disk.c b/boot/freeldr/freeldr/disk/disk.c index 55701205248..11cc0a7a63d 100644 --- a/boot/freeldr/freeldr/disk/disk.c +++ b/boot/freeldr/freeldr/disk/disk.c @@ -130,9 +130,9 @@ BOOLEAN DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size) PARTITION_TABLE_ENTRY PartitionEntry; /* This is a hard disk */ - if (!DiskGetActivePartitionEntry(FrldrBootDrive, &PartitionEntry, &BootPartition)) + if (!DiskGetBootPartitionEntry(FrldrBootDrive, &PartitionEntry, &BootPartition)) { - ERR("Invalid active partition information\n"); + ERR("Failed to get boot partition entry\n"); return FALSE; } diff --git a/boot/freeldr/freeldr/disk/partition.c b/boot/freeldr/freeldr/disk/partition.c index 1feaf5105c7..3aa69d9b589 100644 --- a/boot/freeldr/freeldr/disk/partition.c +++ b/boot/freeldr/freeldr/disk/partition.c @@ -17,11 +17,6 @@ * 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 @@ -29,8 +24,30 @@ DBG_DEFAULT_CHANNEL(DISK); -/* This function serves to retrieve a partition entry for devices that handle partitions differently */ -DISK_GET_PARTITION_ENTRY DiskGetPartitionEntry = DiskGetMbrPartitionEntry; +#define MaxDriveNumber 0xFF +PARTITION_STYLE DiskPartitionType[MaxDriveNumber + 1]; + +/* BRFR signature at disk offset 0x600 */ +#define XBOX_SIGNATURE_SECTOR 3 +#define XBOX_SIGNATURE ('B' | ('R' << 8) | ('F' << 16) | ('R' << 24)) + +/* Default hardcoded partition number to boot from Xbox disk */ +#define FATX_DATA_PARTITION 1 + +static struct +{ + ULONG SectorCountBeforePartition; + ULONG PartitionSectorCount; + UCHAR SystemIndicator; +} XboxPartitions[] = +{ + /* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */ + { 0x0055F400, 0x0098F800, PARTITION_FAT32 }, /* Store , E: */ + { 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */ + { 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */ + { 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */ + { 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */ +}; BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry, @@ -253,6 +270,152 @@ BOOLEAN DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMA return TRUE; } +BOOLEAN +DiskGetBrfrPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) +{ + /* + * Get partition entry of an Xbox-standard BRFR partitioned disk. + */ + if (PartitionNumber >= 1 && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) && + MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, DiskReadBuffer)) + { + if (*((PULONG)DiskReadBuffer) != XBOX_SIGNATURE) + { + /* No magic Xbox partitions */ + return FALSE; + } + + memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY)); + PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator; + PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition; + PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount; + return TRUE; + } + + /* Partition does not exist */ + return FALSE; +} + +VOID DiskDetectPartitionType(UCHAR DriveNumber) +{ + MASTER_BOOT_RECORD MasterBootRecord; + ULONG Index; + ULONG PartitionCount = 0; + PPARTITION_TABLE_ENTRY ThisPartitionTableEntry; + BOOLEAN GPTProtect = FALSE; + PARTITION_TABLE_ENTRY PartitionTableEntry; + + /* Probe for Master Boot Record */ + if (DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord)) + { + DiskPartitionType[DriveNumber] = PARTITION_STYLE_MBR; + + /* Check for GUID Partition Table */ + for (Index = 0; Index < 4; Index++) + { + ThisPartitionTableEntry = &MasterBootRecord.PartitionTable[Index]; + + if (ThisPartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED) + { + PartitionCount++; + + if (Index == 0 && ThisPartitionTableEntry->SystemIndicator == PARTITION_GPT) + { + GPTProtect = TRUE; + } + } + } + + if (PartitionCount == 1 && GPTProtect) + { + DiskPartitionType[DriveNumber] = PARTITION_STYLE_GPT; + } + TRACE("Drive 0x%X partition type %s\n", DriveNumber, DiskPartitionType[DriveNumber] == PARTITION_STYLE_MBR ? "MBR" : "GPT"); + return; + } + + /* Probe for Xbox-BRFR partitioning */ + if (DiskGetBrfrPartitionEntry(DriveNumber, FATX_DATA_PARTITION, &PartitionTableEntry)) + { + DiskPartitionType[DriveNumber] = PARTITION_STYLE_BRFR; + TRACE("Drive 0x%X partition type Xbox-BRFR\n", DriveNumber); + return; + } + + /* Failed to detect partitions, assume partitionless disk */ + DiskPartitionType[DriveNumber] = PARTITION_STYLE_RAW; + TRACE("Drive 0x%X partition type unknown\n", DriveNumber); +} + +BOOLEAN DiskGetBootPartitionEntry(UCHAR DriveNumber, + PPARTITION_TABLE_ENTRY PartitionTableEntry, + ULONG *BootPartition) +{ + switch (DiskPartitionType[DriveNumber]) + { + case PARTITION_STYLE_MBR: + { + return DiskGetActivePartitionEntry(DriveNumber, PartitionTableEntry, BootPartition); + } + case PARTITION_STYLE_GPT: + { + FIXME("DiskGetBootPartitionEntry() unimplemented for GPT\n"); + return FALSE; + } + case PARTITION_STYLE_RAW: + { + FIXME("DiskGetBootPartitionEntry() unimplemented for RAW\n"); + return FALSE; + } + case PARTITION_STYLE_BRFR: + { + if (DiskGetBrfrPartitionEntry(DriveNumber, FATX_DATA_PARTITION, PartitionTableEntry)) + { + *BootPartition = FATX_DATA_PARTITION; + return TRUE; + } + return FALSE; + } + default: + { + ERR("Drive 0x%X partition type = %d, should not happen!\n", DriveNumber, DiskPartitionType[DriveNumber]); + ASSERT(FALSE); + } + } + return FALSE; +} + +BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) +{ + switch (DiskPartitionType[DriveNumber]) + { + case PARTITION_STYLE_MBR: + { + return DiskGetMbrPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry); + } + case PARTITION_STYLE_GPT: + { + FIXME("DiskGetPartitionEntry() unimplemented for GPT\n"); + return FALSE; + } + case PARTITION_STYLE_RAW: + { + FIXME("DiskGetPartitionEntry() unimplemented for RAW\n"); + return FALSE; + } + case PARTITION_STYLE_BRFR: + { + return DiskGetBrfrPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry); + } + default: + { + ERR("Drive 0x%X partition type = %d, should not happen!\n", DriveNumber, DiskPartitionType[DriveNumber]); + ASSERT(FALSE); + } + } + return FALSE; +} + #ifndef _M_AMD64 NTSTATUS NTAPI diff --git a/boot/freeldr/freeldr/include/arch/i386/machxbox.h b/boot/freeldr/freeldr/include/arch/i386/machxbox.h index 3a394c35703..d1c42a40bae 100644 --- a/boot/freeldr/freeldr/include/arch/i386/machxbox.h +++ b/boot/freeldr/freeldr/include/arch/i386/machxbox.h @@ -52,7 +52,6 @@ PVOID XboxMemReserveMemory(ULONG MbToReserve); PFREELDR_MEMORY_DESCRIPTOR XboxMemGetMemoryMap(ULONG *MemoryMapSize); BOOLEAN XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); -BOOLEAN XboxDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOLEAN XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY DriveGeometry); ULONG XboxDiskGetCacheableBlockCount(UCHAR DriveNumber); diff --git a/boot/freeldr/freeldr/include/disk.h b/boot/freeldr/freeldr/include/disk.h index a701ad26c15..6629c768dcf 100644 --- a/boot/freeldr/freeldr/include/disk.h +++ b/boot/freeldr/freeldr/include/disk.h @@ -102,6 +102,7 @@ typedef struct _MASTER_BOOT_RECORD #define PARTITION_UNIX 0x63 // Unix #define VALID_NTFT 0xC0 // NTFT uses high order bits #define PARTITION_NTFT 0x80 // NTFT partition +#define PARTITION_GPT 0xEE // GPT protective partition #ifdef __REACTOS__ #define PARTITION_OLD_LINUX 0x43 #define PARTITION_LINUX 0x83 @@ -144,18 +145,9 @@ extern SIZE_T DiskReadBufferSize; // /////////////////////////////////////////////////////////////////////////////////////// -/* Signature of DiskGetPartitionEntry(...) */ -typedef -BOOLEAN -(*DISK_GET_PARTITION_ENTRY)(UCHAR DriveNumber, - ULONG PartitionNumber, - PPARTITION_TABLE_ENTRY PartitionTableEntry); - -/* This function serves to retrieve a partition entry for devices that handle partitions differently */ -extern DISK_GET_PARTITION_ENTRY DiskGetPartitionEntry; - -BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry, ULONG *ActivePartition); -BOOLEAN DiskGetMbrPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); +VOID DiskDetectPartitionType(UCHAR DriveNumber); +BOOLEAN DiskGetBootPartitionEntry(UCHAR DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry, ULONG *BootPartition); +BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOLEAN DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOLEAN DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOLEAN DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord); diff --git a/sdk/include/psdk/ntdddisk.h b/sdk/include/psdk/ntdddisk.h index 24387a02d54..13b8e0e9995 100644 --- a/sdk/include/psdk/ntdddisk.h +++ b/sdk/include/psdk/ntdddisk.h @@ -410,7 +410,11 @@ typedef struct _PARTITION_INFORMATION_GPT { typedef enum _PARTITION_STYLE { PARTITION_STYLE_MBR, PARTITION_STYLE_GPT, - PARTITION_STYLE_RAW + PARTITION_STYLE_RAW, +#ifdef __REACTOS__ + /* ReactOS custom partition handlers */ + PARTITION_STYLE_BRFR = 128 /* Xbox-BRFR partitioning scheme */ +#endif } PARTITION_STYLE; typedef struct _DISK_PARTITION_INFO {