mirror of
https://github.com/reactos/reactos.git
synced 2024-06-28 08:51:29 +00:00
![Hermès Bélusca-Maïto](/assets/img/avatar_default.png)
- Add optional arguments BootDrive and BootPartition to ChainLoadBiosBootSectorCode() so as not to modify explicitly the FrldrBootDrive and FrldrBootPartition variables, that should remain purely internal. - Implement ChainLoadBiosBootSectorCode() for x64. - Get rid of the machine-specific DiskGetBootPath(), and instead do its job only once in the machine-specific InitializeBootDevices() (or in MachInit() for PPC). Cache the result of this operation into the globally-accessible FrldrBootPath buffer. This avoids the unneeded calls to (Mach)DiskGetBootPath() we used to do before. Also remove the separate distinction between the PC and XBOX versions of this functionality. - Move the PC-specific DiskIsDriveRemovable() and DiskGetBootPath() as well as the disk-IO-error functionality, back into the corresponding PC-arch files. - Simplify IniFileInitialize(), getting rid of IniOpenIniFile().
590 lines
19 KiB
C
590 lines
19 KiB
C
/*
|
|
* FreeLoader
|
|
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifndef _M_ARM
|
|
#include <freeldr.h>
|
|
|
|
#include <debug.h>
|
|
DBG_DEFAULT_CHANNEL(DISK);
|
|
|
|
#define MaxDriveNumber 0xFF
|
|
static 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: */
|
|
};
|
|
|
|
static BOOLEAN
|
|
DiskReadBootRecord(
|
|
IN UCHAR DriveNumber,
|
|
IN ULONGLONG LogicalSectorNumber,
|
|
OUT PMASTER_BOOT_RECORD BootRecord)
|
|
{
|
|
ULONG Index;
|
|
|
|
/* Read master boot record */
|
|
if (!MachDiskReadLogicalSectors(DriveNumber, LogicalSectorNumber, 1, DiskReadBuffer))
|
|
{
|
|
return FALSE;
|
|
}
|
|
RtlCopyMemory(BootRecord, DiskReadBuffer, sizeof(MASTER_BOOT_RECORD));
|
|
|
|
TRACE("Dumping partition table for drive 0x%x:\n", DriveNumber);
|
|
TRACE("Boot record logical start sector = %d\n", LogicalSectorNumber);
|
|
TRACE("sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD));
|
|
|
|
for (Index = 0; Index < 4; Index++)
|
|
{
|
|
TRACE("-------------------------------------------\n");
|
|
TRACE("Partition %d\n", (Index + 1));
|
|
TRACE("BootIndicator: 0x%x\n", BootRecord->PartitionTable[Index].BootIndicator);
|
|
TRACE("StartHead: 0x%x\n", BootRecord->PartitionTable[Index].StartHead);
|
|
TRACE("StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].StartSector);
|
|
TRACE("StartCylinder: 0x%x\n", BootRecord->PartitionTable[Index].StartCylinder);
|
|
TRACE("SystemIndicator: 0x%x\n", BootRecord->PartitionTable[Index].SystemIndicator);
|
|
TRACE("EndHead: 0x%x\n", BootRecord->PartitionTable[Index].EndHead);
|
|
TRACE("EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].EndSector);
|
|
TRACE("EndCylinder: 0x%x\n", BootRecord->PartitionTable[Index].EndCylinder);
|
|
TRACE("SectorCountBeforePartition: 0x%x\n", BootRecord->PartitionTable[Index].SectorCountBeforePartition);
|
|
TRACE("PartitionSectorCount: 0x%x\n", BootRecord->PartitionTable[Index].PartitionSectorCount);
|
|
}
|
|
|
|
/* Check the partition table magic value */
|
|
return (BootRecord->MasterBootRecordMagic == 0xaa55);
|
|
}
|
|
|
|
static BOOLEAN
|
|
DiskGetFirstPartitionEntry(
|
|
IN PMASTER_BOOT_RECORD MasterBootRecord,
|
|
OUT PPARTITION_TABLE_ENTRY PartitionTableEntry)
|
|
{
|
|
ULONG Index;
|
|
|
|
for (Index = 0; Index < 4; Index++)
|
|
{
|
|
/* Check the system indicator. If it's not an extended or unused partition then we're done. */
|
|
if ((MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_ENTRY_UNUSED) &&
|
|
(MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_EXTENDED) &&
|
|
(MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_XINT13_EXTENDED))
|
|
{
|
|
RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY));
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOLEAN
|
|
DiskGetFirstExtendedPartitionEntry(
|
|
IN PMASTER_BOOT_RECORD MasterBootRecord,
|
|
OUT PPARTITION_TABLE_ENTRY PartitionTableEntry)
|
|
{
|
|
ULONG Index;
|
|
|
|
for (Index = 0; Index < 4; Index++)
|
|
{
|
|
/* Check the system indicator. If it an extended partition then we're done. */
|
|
if ((MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_EXTENDED) ||
|
|
(MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_XINT13_EXTENDED))
|
|
{
|
|
RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY));
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOLEAN
|
|
DiskGetActivePartitionEntry(
|
|
IN UCHAR DriveNumber,
|
|
OUT PPARTITION_TABLE_ENTRY PartitionTableEntry,
|
|
OUT PULONG ActivePartition)
|
|
{
|
|
ULONG BootablePartitionCount = 0;
|
|
ULONG CurrentPartitionNumber;
|
|
ULONG Index;
|
|
MASTER_BOOT_RECORD MasterBootRecord;
|
|
PPARTITION_TABLE_ENTRY ThisPartitionTableEntry;
|
|
|
|
*ActivePartition = 0;
|
|
|
|
/* Read master boot record */
|
|
if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
CurrentPartitionNumber = 0;
|
|
for (Index = 0; Index < 4; Index++)
|
|
{
|
|
ThisPartitionTableEntry = &MasterBootRecord.PartitionTable[Index];
|
|
|
|
if (ThisPartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED &&
|
|
ThisPartitionTableEntry->SystemIndicator != PARTITION_EXTENDED &&
|
|
ThisPartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED)
|
|
{
|
|
CurrentPartitionNumber++;
|
|
|
|
/* Test if this is the bootable partition */
|
|
if (ThisPartitionTableEntry->BootIndicator == 0x80)
|
|
{
|
|
BootablePartitionCount++;
|
|
*ActivePartition = CurrentPartitionNumber;
|
|
|
|
/* Copy the partition table entry */
|
|
RtlCopyMemory(PartitionTableEntry,
|
|
ThisPartitionTableEntry,
|
|
sizeof(PARTITION_TABLE_ENTRY));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Make sure there was only one bootable partition */
|
|
if (BootablePartitionCount == 0)
|
|
{
|
|
ERR("No bootable (active) partitions found.\n");
|
|
return FALSE;
|
|
}
|
|
else if (BootablePartitionCount != 1)
|
|
{
|
|
ERR("Too many bootable (active) partitions found.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOLEAN
|
|
DiskGetMbrPartitionEntry(
|
|
IN UCHAR DriveNumber,
|
|
IN ULONG PartitionNumber,
|
|
OUT PPARTITION_TABLE_ENTRY PartitionTableEntry)
|
|
{
|
|
MASTER_BOOT_RECORD MasterBootRecord;
|
|
PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry;
|
|
ULONG ExtendedPartitionNumber;
|
|
ULONG ExtendedPartitionOffset;
|
|
ULONG Index;
|
|
ULONG CurrentPartitionNumber;
|
|
PPARTITION_TABLE_ENTRY ThisPartitionTableEntry;
|
|
|
|
/* Read master boot record */
|
|
if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
CurrentPartitionNumber = 0;
|
|
for (Index = 0; Index < 4; Index++)
|
|
{
|
|
ThisPartitionTableEntry = &MasterBootRecord.PartitionTable[Index];
|
|
|
|
if (ThisPartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED &&
|
|
ThisPartitionTableEntry->SystemIndicator != PARTITION_EXTENDED &&
|
|
ThisPartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED)
|
|
{
|
|
CurrentPartitionNumber++;
|
|
}
|
|
|
|
if (PartitionNumber == CurrentPartitionNumber)
|
|
{
|
|
RtlCopyMemory(PartitionTableEntry, ThisPartitionTableEntry, sizeof(PARTITION_TABLE_ENTRY));
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* They want an extended partition entry so we will need
|
|
* to loop through all the extended partitions on the disk
|
|
* and return the one they want.
|
|
*/
|
|
ExtendedPartitionNumber = PartitionNumber - CurrentPartitionNumber - 1;
|
|
|
|
/*
|
|
* Set the initial relative starting sector to 0.
|
|
* This is because extended partition starting
|
|
* sectors a numbered relative to their parent.
|
|
*/
|
|
ExtendedPartitionOffset = 0;
|
|
|
|
for (Index = 0; Index <= ExtendedPartitionNumber; Index++)
|
|
{
|
|
/* Get the extended partition table entry */
|
|
if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord, &ExtendedPartitionTableEntry))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Adjust the relative starting sector of the partition */
|
|
ExtendedPartitionTableEntry.SectorCountBeforePartition += ExtendedPartitionOffset;
|
|
if (ExtendedPartitionOffset == 0)
|
|
{
|
|
/* Set the start of the parrent extended partition */
|
|
ExtendedPartitionOffset = ExtendedPartitionTableEntry.SectorCountBeforePartition;
|
|
}
|
|
/* Read the partition boot record */
|
|
if (!DiskReadBootRecord(DriveNumber, ExtendedPartitionTableEntry.SectorCountBeforePartition, &MasterBootRecord))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Get the first real partition table entry */
|
|
if (!DiskGetFirstPartitionEntry(&MasterBootRecord, PartitionTableEntry))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Now correct the start sector of the partition */
|
|
PartitionTableEntry->SectorCountBeforePartition += ExtendedPartitionTableEntry.SectorCountBeforePartition;
|
|
}
|
|
|
|
/*
|
|
* When we get here we should have the correct entry already
|
|
* stored in PartitionTableEntry, so just return TRUE.
|
|
*/
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOLEAN
|
|
DiskGetBrfrPartitionEntry(
|
|
IN UCHAR DriveNumber,
|
|
IN ULONG PartitionNumber,
|
|
OUT 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(
|
|
IN 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(
|
|
IN UCHAR DriveNumber,
|
|
OUT PPARTITION_TABLE_ENTRY PartitionTableEntry,
|
|
OUT PULONG 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(
|
|
IN UCHAR DriveNumber,
|
|
IN ULONG PartitionNumber,
|
|
OUT 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
|
|
IopReadBootRecord(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONGLONG LogicalSectorNumber,
|
|
IN ULONG SectorSize,
|
|
OUT PMASTER_BOOT_RECORD BootRecord)
|
|
{
|
|
ULONG_PTR FileId = (ULONG_PTR)DeviceObject;
|
|
LARGE_INTEGER Position;
|
|
ULONG BytesRead;
|
|
ARC_STATUS Status;
|
|
|
|
Position.QuadPart = LogicalSectorNumber * SectorSize;
|
|
Status = ArcSeek(FileId, &Position, SeekAbsolute);
|
|
if (Status != ESUCCESS)
|
|
return STATUS_IO_DEVICE_ERROR;
|
|
|
|
Status = ArcRead(FileId, BootRecord, SectorSize, &BytesRead);
|
|
if (Status != ESUCCESS || BytesRead != SectorSize)
|
|
return STATUS_IO_DEVICE_ERROR;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
IopCopyPartitionRecord(
|
|
IN BOOLEAN ReturnRecognizedPartitions,
|
|
IN ULONG SectorSize,
|
|
IN PPARTITION_TABLE_ENTRY PartitionTableEntry,
|
|
OUT PARTITION_INFORMATION *PartitionEntry)
|
|
{
|
|
BOOLEAN IsRecognized;
|
|
|
|
IsRecognized = TRUE; /* FIXME */
|
|
if (!IsRecognized && ReturnRecognizedPartitions)
|
|
return FALSE;
|
|
|
|
PartitionEntry->StartingOffset.QuadPart = (ULONGLONG)PartitionTableEntry->SectorCountBeforePartition * SectorSize;
|
|
PartitionEntry->PartitionLength.QuadPart = (ULONGLONG)PartitionTableEntry->PartitionSectorCount * SectorSize;
|
|
PartitionEntry->HiddenSectors = 0;
|
|
PartitionEntry->PartitionNumber = 0; /* Will be filled later */
|
|
PartitionEntry->PartitionType = PartitionTableEntry->SystemIndicator;
|
|
PartitionEntry->BootIndicator = (PartitionTableEntry->BootIndicator & 0x80) ? TRUE : FALSE;
|
|
PartitionEntry->RecognizedPartition = IsRecognized;
|
|
PartitionEntry->RewritePartition = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
NTSTATUS
|
|
FASTCALL
|
|
IoReadPartitionTable(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONG SectorSize,
|
|
IN BOOLEAN ReturnRecognizedPartitions,
|
|
OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
|
|
{
|
|
NTSTATUS Status;
|
|
PMASTER_BOOT_RECORD MasterBootRecord;
|
|
PDRIVE_LAYOUT_INFORMATION Partitions;
|
|
ULONG NbPartitions, i, Size;
|
|
|
|
*PartitionBuffer = NULL;
|
|
|
|
if (SectorSize < sizeof(MASTER_BOOT_RECORD))
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
MasterBootRecord = ExAllocatePool(NonPagedPool, SectorSize);
|
|
if (!MasterBootRecord)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
/* Read disk MBR */
|
|
Status = IopReadBootRecord(DeviceObject, 0, SectorSize, MasterBootRecord);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ExFreePool(MasterBootRecord);
|
|
return Status;
|
|
}
|
|
|
|
/* Check validity of boot record */
|
|
if (MasterBootRecord->MasterBootRecordMagic != 0xaa55)
|
|
{
|
|
ExFreePool(MasterBootRecord);
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
/* Count number of partitions */
|
|
NbPartitions = 0;
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
NbPartitions++;
|
|
|
|
if (MasterBootRecord->PartitionTable[i].SystemIndicator == PARTITION_EXTENDED ||
|
|
MasterBootRecord->PartitionTable[i].SystemIndicator == PARTITION_XINT13_EXTENDED)
|
|
{
|
|
/* FIXME: unhandled case; count number of partitions */
|
|
UNIMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
if (NbPartitions == 0)
|
|
{
|
|
ExFreePool(MasterBootRecord);
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
/* Allocation space to store partitions */
|
|
Size = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry) +
|
|
NbPartitions * sizeof(PARTITION_INFORMATION);
|
|
Partitions = ExAllocatePool(NonPagedPool, Size);
|
|
if (!Partitions)
|
|
{
|
|
ExFreePool(MasterBootRecord);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
/* Count number of partitions */
|
|
NbPartitions = 0;
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
if (IopCopyPartitionRecord(ReturnRecognizedPartitions,
|
|
SectorSize,
|
|
&MasterBootRecord->PartitionTable[i],
|
|
&Partitions->PartitionEntry[NbPartitions]))
|
|
{
|
|
Partitions->PartitionEntry[NbPartitions].PartitionNumber = NbPartitions + 1;
|
|
NbPartitions++;
|
|
}
|
|
|
|
if (MasterBootRecord->PartitionTable[i].SystemIndicator == PARTITION_EXTENDED ||
|
|
MasterBootRecord->PartitionTable[i].SystemIndicator == PARTITION_XINT13_EXTENDED)
|
|
{
|
|
/* FIXME: unhandled case; copy partitions */
|
|
UNIMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
Partitions->PartitionCount = NbPartitions;
|
|
Partitions->Signature = MasterBootRecord->Signature;
|
|
ExFreePool(MasterBootRecord);
|
|
|
|
*PartitionBuffer = Partitions;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
#endif // _M_AMD64
|
|
#endif
|