mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[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
This commit is contained in:
parent
8831328081
commit
06b77b8572
9 changed files with 184 additions and 72 deletions
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -1422,8 +1422,6 @@ PcMachInit(const char *CmdLine)
|
|||
MachVtbl.InitializeBootDevices = PcInitializeBootDevices;
|
||||
MachVtbl.HwDetect = PcHwDetect;
|
||||
MachVtbl.HwIdle = PcHwIdle;
|
||||
|
||||
// DiskGetPartitionEntry = DiskGetMbrPartitionEntry; // Default
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
|
@ -231,8 +231,6 @@ XboxMachInit(const char *CmdLine)
|
|||
MachVtbl.HwDetect = XboxHwDetect;
|
||||
MachVtbl.HwIdle = XboxHwIdle;
|
||||
|
||||
DiskGetPartitionEntry = XboxDiskGetPartitionEntry;
|
||||
|
||||
/* Set LEDs to orange after init */
|
||||
XboxSetLED("oooo");
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue