reactos/hal/halx86/xbox/part_xbox.c
Stanislav Motylkov af7ec17ce1 [HALXBOX] Don't use Xbox partitions if MBR signature found (#2253)
* [HALXBOX] Formatting only.

* [HALXBOX] Don't use Xbox partitions if MBR signature found.

- Fixes BSOD 0x7B when booting from a HDD that have both MBR and BRFR signatures.
- It happens when you format Xbox (BRFR) disk as MBR.
  After that "BRFR" signature is still located at sector 3.
- Also fix pre-existing leaks.

CORE-16216 CORE-16329
2020-01-18 18:41:32 +01:00

344 lines
11 KiB
C

/*
* PROJECT: Xbox HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Xbox specific handling of partition tables
* COPYRIGHT: Copyright 2004 Ge van Geldorp (gvg@reactos.com)
* Copyright 2020 Stanislav Motylkov (x86corez@gmail.com)
*/
/* INCLUDES *****************************************************************/
#include "halxbox.h"
#include <internal/tag.h>
#define NDEBUG
#include <debug.h>
#define XBOX_SIGNATURE_SECTOR 3
#define XBOX_SIGNATURE ('B' | ('R' << 8) | ('F' << 16) | ('R' << 24))
#define PARTITION_SIGNATURE 0xaa55
/* VARIABLES ***************************************************************/
static pHalExamineMBR NtoskrnlExamineMBR;
static pHalIoReadPartitionTable NtoskrnlIoReadPartitionTable;
static pHalIoSetPartitionInformation NtoskrnlIoSetPartitionInformation;
static pHalIoWritePartitionTable NtoskrnlIoWritePartitionTable;
static struct
{
ULONG SectorStart;
ULONG SectorCount;
CHAR PartitionType;
} 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 XBOX_PARTITION_COUNT (sizeof(XboxPartitions) / sizeof(XboxPartitions[0]))
/* FUNCTIONS ***************************************************************/
static NTSTATUS
HalpXboxReadSector(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
IN PLARGE_INTEGER SectorOffset,
OUT PVOID Sector)
{
IO_STATUS_BLOCK StatusBlock;
KEVENT Event;
PIRP Irp;
NTSTATUS Status;
DPRINT("HalpXboxReadSector(%p %lu 0x%08x%08x %p)\n",
DeviceObject, SectorSize, SectorOffset->u.HighPart, SectorOffset->u.LowPart, Sector);
ASSERT(DeviceObject);
ASSERT(Sector);
KeInitializeEvent(&Event,
NotificationEvent,
FALSE);
/* Read the sector */
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
DeviceObject,
Sector,
SectorSize,
SectorOffset,
&Event,
&StatusBlock);
if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
Status = IoCallDriver(DeviceObject,
Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = StatusBlock.Status;
}
if (!NT_SUCCESS(Status))
{
DPRINT("Reading sector failed (Status 0x%08lx)\n", Status);
return Status;
}
return Status;
}
static NTSTATUS FASTCALL
HalpXboxDeviceHasXboxPartitioning(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
OUT BOOLEAN *HasXboxPartitioning)
{
PVOID SectorData;
LARGE_INTEGER Offset;
NTSTATUS Status;
BOOLEAN HasMBRPartitioning;
DPRINT("HalpXboxDeviceHasXboxPartitioning(%p %lu %p)\n",
DeviceObject,
SectorSize,
HasXboxPartitioning);
SectorData = ExAllocatePoolWithTag(PagedPool, SectorSize, TAG_HAL_XBOX);
if (!SectorData)
{
return STATUS_NO_MEMORY;
}
Offset.QuadPart = 0;
Status = HalpXboxReadSector(DeviceObject, SectorSize, &Offset, SectorData);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
HasMBRPartitioning = (*((USHORT *)SectorData + (SectorSize / sizeof(USHORT)) - 1) == PARTITION_SIGNATURE);
if (HasMBRPartitioning)
{
*HasXboxPartitioning = FALSE;
goto Cleanup;
}
Offset.QuadPart = XBOX_SIGNATURE_SECTOR * SectorSize;
Status = HalpXboxReadSector(DeviceObject, SectorSize, &Offset, SectorData);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
DPRINT("Signature 0x%02x 0x%02x 0x%02x 0x%02x\n",
*((UCHAR *) SectorData), *((UCHAR *) SectorData + 1), *((UCHAR *) SectorData + 2), *((UCHAR *) SectorData + 3));
*HasXboxPartitioning = (XBOX_SIGNATURE == *((ULONG *) SectorData));
Cleanup:
ExFreePoolWithTag(SectorData, TAG_HAL_XBOX);
if (NT_SUCCESS(Status))
{
DPRINT("%s partitioning found\n", *HasXboxPartitioning ? "Xbox" : "MBR");
}
return Status;
}
static VOID FASTCALL
HalpXboxExamineMBR(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
IN ULONG MBRTypeIdentifier,
OUT PVOID *Buffer)
{
BOOLEAN HasXboxPartitioning;
NTSTATUS Status;
DPRINT("HalpXboxExamineMBR(%p %lu %lx %p)\n",
DeviceObject,
SectorSize,
MBRTypeIdentifier,
Buffer);
*Buffer = NULL;
Status = HalpXboxDeviceHasXboxPartitioning(DeviceObject, SectorSize, &HasXboxPartitioning);
if (!NT_SUCCESS(Status))
{
return;
}
if (!HasXboxPartitioning)
{
DPRINT("Delegating to standard MBR code\n");
NtoskrnlExamineMBR(DeviceObject, SectorSize, MBRTypeIdentifier, Buffer);
return;
}
/* Buffer already set to NULL */
return;
}
static NTSTATUS FASTCALL
HalpXboxIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
IN BOOLEAN ReturnRecognizedPartitions,
OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
{
BOOLEAN HasXboxPartitioning;
NTSTATUS Status;
ULONG Part;
PPARTITION_INFORMATION PartInfo;
DPRINT("HalpXboxIoReadPartitionTable(%p %lu %x %p)\n",
DeviceObject,
SectorSize,
ReturnRecognizedPartitions,
PartitionBuffer);
Status = HalpXboxDeviceHasXboxPartitioning(DeviceObject, SectorSize, &HasXboxPartitioning);
if (!NT_SUCCESS(Status))
{
return Status;
}
if (!HasXboxPartitioning)
{
DPRINT("Delegating to standard MBR code\n");
return NtoskrnlIoReadPartitionTable(DeviceObject, SectorSize,
ReturnRecognizedPartitions, PartitionBuffer);
}
*PartitionBuffer = (PDRIVE_LAYOUT_INFORMATION)ExAllocatePoolWithTag(
PagedPool,
sizeof(DRIVE_LAYOUT_INFORMATION) +
XBOX_PARTITION_COUNT * sizeof(PARTITION_INFORMATION),
TAG_FILE_SYSTEM);
if (*PartitionBuffer == NULL)
{
return STATUS_NO_MEMORY;
}
(*PartitionBuffer)->PartitionCount = XBOX_PARTITION_COUNT;
(*PartitionBuffer)->Signature = PARTITION_SIGNATURE;
for (Part = 0; Part < XBOX_PARTITION_COUNT; Part++)
{
PartInfo = (*PartitionBuffer)->PartitionEntry + Part;
PartInfo->StartingOffset.QuadPart = (ULONGLONG) XboxPartitions[Part].SectorStart *
(ULONGLONG) SectorSize;
PartInfo->PartitionLength.QuadPart = (ULONGLONG) XboxPartitions[Part].SectorCount *
(ULONGLONG) SectorSize;
PartInfo->HiddenSectors = 0;
PartInfo->PartitionNumber = Part + 1;
PartInfo->PartitionType = XboxPartitions[Part].PartitionType;
PartInfo->BootIndicator = FALSE;
PartInfo->RecognizedPartition = TRUE;
PartInfo->RewritePartition = FALSE;
DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x rec: %d\n",
Part,
PartInfo->PartitionNumber,
PartInfo->BootIndicator,
PartInfo->PartitionType,
PartInfo->StartingOffset.QuadPart,
PartInfo->PartitionLength.QuadPart,
PartInfo->RecognizedPartition);
}
return STATUS_SUCCESS;
}
static NTSTATUS FASTCALL
HalpXboxIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
IN ULONG PartitionNumber,
IN ULONG PartitionType)
{
BOOLEAN HasXboxPartitioning;
NTSTATUS Status;
DPRINT("HalpXboxIoSetPartitionInformation(%p %lu %lu %lu)\n",
DeviceObject,
SectorSize,
PartitionNumber,
PartitionType);
Status = HalpXboxDeviceHasXboxPartitioning(DeviceObject, SectorSize, &HasXboxPartitioning);
if (!NT_SUCCESS(Status))
{
return Status;
}
if (!HasXboxPartitioning)
{
DPRINT("Delegating to standard MBR code\n");
return NtoskrnlIoSetPartitionInformation(DeviceObject, SectorSize,
PartitionNumber, PartitionType);
}
/* Can't change the partitioning */
DPRINT1("Xbox partitions are fixed, can't change them\n");
return STATUS_ACCESS_DENIED;
}
static NTSTATUS FASTCALL
HalpXboxIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
IN ULONG SectorsPerTrack,
IN ULONG NumberOfHeads,
IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
{
BOOLEAN HasXboxPartitioning;
NTSTATUS Status;
DPRINT("HalpXboxIoWritePartitionTable(%p %lu %lu %lu %p)\n",
DeviceObject,
SectorSize,
SectorsPerTrack,
NumberOfHeads,
PartitionBuffer);
Status = HalpXboxDeviceHasXboxPartitioning(DeviceObject, SectorSize, &HasXboxPartitioning);
if (!NT_SUCCESS(Status))
{
return Status;
}
if (!HasXboxPartitioning)
{
DPRINT("Delegating to standard MBR code\n");
return NtoskrnlIoWritePartitionTable(DeviceObject, SectorSize,
SectorsPerTrack, NumberOfHeads,
PartitionBuffer);
}
/* Can't change the partitioning */
DPRINT1("Xbox partitions are fixed, can't change them\n");
return STATUS_ACCESS_DENIED;
}
#define HalExamineMBR HALDISPATCH->HalExamineMBR
#define HalIoReadPartitionTable HALDISPATCH->HalIoReadPartitionTable
#define HalIoSetPartitionInformation HALDISPATCH->HalIoSetPartitionInformation
#define HalIoWritePartitionTable HALDISPATCH->HalIoWritePartitionTable
void
HalpXboxInitPartIo(void)
{
NtoskrnlExamineMBR = HalExamineMBR;
HalExamineMBR = HalpXboxExamineMBR;
NtoskrnlIoReadPartitionTable = HalIoReadPartitionTable;
HalIoReadPartitionTable = HalpXboxIoReadPartitionTable;
NtoskrnlIoSetPartitionInformation = HalIoSetPartitionInformation;
HalIoSetPartitionInformation = HalpXboxIoSetPartitionInformation;
NtoskrnlIoWritePartitionTable = HalIoWritePartitionTable;
HalIoWritePartitionTable = HalpXboxIoWritePartitionTable;
}
/* EOF */