https://git.reactos.org/?p=reactos.git;a=commitdiff;h=06b77b857250ee22e8ec5…
commit 06b77b857250ee22e8ec5250d5ffdc3d486726a6
Author: Stanislav Motylkov <x86corez(a)gmail.com>
AuthorDate: Mon Jul 29 15:25:54 2019 +0300
Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)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 {