https://git.reactos.org/?p=reactos.git;a=commitdiff;h=06b77b857250ee22e8ec52...
commit 06b77b857250ee22e8ec5250d5ffdc3d486726a6 Author: Stanislav Motylkov x86corez@gmail.com AuthorDate: Mon Jul 29 15:25:54 2019 +0300 Commit: Hermès BÉLUSCA - MAÏTO hermes.belusca-maito@reactos.org CommitDate: Mon Jul 29 14:25:54 2019 +0200
[FREELDR] Implement proper partition type detection and handling (#1762)
- This allows to detect and dynamically handle different partitioning schemes. - Implemented detection of MBR, GPT, Xbox-BRFR, and partitionless disks. - Currently only MBR and Xbox-BRFR partitions are handled and tested.
CORE-9841 CORE-15768 CORE-16216 CORE-16248 --- boot/freeldr/freeldr/arch/i386/hwdisk.c | 3 + boot/freeldr/freeldr/arch/i386/machpc.c | 2 - boot/freeldr/freeldr/arch/i386/machxbox.c | 2 - boot/freeldr/freeldr/arch/i386/xboxdisk.c | 45 ------ boot/freeldr/freeldr/disk/disk.c | 4 +- boot/freeldr/freeldr/disk/partition.c | 177 +++++++++++++++++++++- boot/freeldr/freeldr/include/arch/i386/machxbox.h | 1 - boot/freeldr/freeldr/include/disk.h | 16 +- sdk/include/psdk/ntdddisk.h | 6 +- 9 files changed, 184 insertions(+), 72 deletions(-)
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 <freeldr.h>
@@ -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 {