https://git.reactos.org/?p=reactos.git;a=commitdiff;h=06b77b857250ee22e8ec5250d5ffdc3d486726a6

commit 06b77b857250ee22e8ec5250d5ffdc3d486726a6
Author:     Stanislav Motylkov <[email protected]>
AuthorDate: Mon Jul 29 15:25:54 2019 +0300
Commit:     Hermès BÉLUSCA - MAÏTO <[email protected]>
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 {

Reply via email to