From e2c92c0ffb799c16002629274eeccf06d4860c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 12 Apr 2026 22:28:17 +0200 Subject: [PATCH] [FREELDR] Switch partition interface to using the more generic PARTITION_INFORMATION instead of the MBR-specific PARTITION_TABLE_ENTRY structure. Simplify also some aspects of the code: - for MBR code, avoid copying around partition entries, but use pointers instead; - more generally, use the actual disk sector size instead of guessing, and pass it to the partition interface routines. --- boot/freeldr/freeldr/arch/i386/hwdisk.c | 59 ++++----- boot/freeldr/freeldr/arch/i386/ntoskrnl.c | 4 +- boot/freeldr/freeldr/arch/uefi/uefidisk.c | 150 ++++++++++++---------- boot/freeldr/freeldr/disk/disk.c | 21 +-- boot/freeldr/freeldr/disk/part_brfr.c | 62 +++++---- boot/freeldr/freeldr/disk/part_gpt.c | 39 +++--- boot/freeldr/freeldr/disk/part_mbr.c | 121 ++++++++++------- boot/freeldr/freeldr/disk/partition.c | 83 ++++++++---- boot/freeldr/freeldr/include/disk.h | 18 ++- 9 files changed, 318 insertions(+), 239 deletions(-) diff --git a/boot/freeldr/freeldr/arch/i386/hwdisk.c b/boot/freeldr/freeldr/arch/i386/hwdisk.c index e6dd2100ae1..316cca5bddf 100644 --- a/boot/freeldr/freeldr/arch/i386/hwdisk.c +++ b/boot/freeldr/freeldr/arch/i386/hwdisk.c @@ -87,9 +87,9 @@ DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId) CONFIGURATION_TYPE DriveType; UCHAR DriveNumber; ULONG DrivePartition, SectorSize; - ULONGLONG SectorOffset = 0; - ULONGLONG SectorCount = 0; - PARTITION_TABLE_ENTRY PartitionTableEntry; + GEOMETRY Geometry; + ULONGLONG SectorOffset; + ULONGLONG SectorCount; if (DiskReadBufferSize == 0) { @@ -102,38 +102,37 @@ DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId) return EINVAL; DriveType = DiskGetConfigType(DriveNumber); - if (DriveType == CdromController) + + if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry)) + return EIO; + if (Geometry.BytesPerSector == 0) { - /* This is a CD-ROM device */ - SectorSize = 2048; - } - else - { - /* This is either a floppy disk or a hard disk device, but it doesn't - * matter which one because they both have 512 bytes per sector */ - SectorSize = 512; + WARN("MachDiskGetDriveGeometry(0x%x) failed, fall back to hardcoded values\n", DriveNumber); + if (DriveType == CdromController) + { + /* This is a CD-ROM device */ + Geometry.BytesPerSector = 2048; + } + else + { + /* This is either a floppy disk or a hard disk device, but it doesn't + * matter which one because they both have 512 bytes per sector */ + Geometry.BytesPerSector = 512; + } } + SectorSize = Geometry.BytesPerSector; if (DrivePartition != 0xff && DrivePartition != 0) { - if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry)) - return EINVAL; + PARTITION_INFORMATION PartitionEntry; + if (!DiskGetPartitionEntry(DriveNumber, SectorSize, DrivePartition, &PartitionEntry)) + return EIO; - SectorOffset = PartitionTableEntry.SectorCountBeforePartition; - SectorCount = PartitionTableEntry.PartitionSectorCount; + SectorOffset = PartitionEntry.StartingOffset.QuadPart / SectorSize; + SectorCount = PartitionEntry.PartitionLength.QuadPart / SectorSize; } else { - GEOMETRY Geometry; - if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry)) - return EINVAL; - - if (SectorSize != Geometry.BytesPerSector) - { - ERR("SectorSize (%lu) != Geometry.BytesPerSector (%lu), expect problems!\n", - SectorSize, Geometry.BytesPerSector); - } - SectorOffset = 0; SectorCount = Geometry.Sectors; } @@ -202,7 +201,7 @@ DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count) *Count = (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)Buffer); Context->SectorNumber = SectorOffset - Context->SectorOffset; - return (!ret) ? EIO : ESUCCESS; + return (ret ? ESUCCESS : EIO); } static ARC_STATUS @@ -406,11 +405,9 @@ DiskGetBootPath( } else { - ULONG BootPartition; - PARTITION_TABLE_ENTRY PartitionEntry; - /* This is a hard disk, find the boot partition */ - if (!DiskGetBootPartitionEntry(FrldrBootDrive, &PartitionEntry, &BootPartition)) + ULONG BootPartition; + if (!DiskGetBootPartitionEntry(FrldrBootDrive, NULL, &BootPartition)) { ERR("Failed to get boot partition entry\n"); return FALSE; diff --git a/boot/freeldr/freeldr/arch/i386/ntoskrnl.c b/boot/freeldr/freeldr/arch/i386/ntoskrnl.c index 7695daee3b4..10a6835068b 100644 --- a/boot/freeldr/freeldr/arch/i386/ntoskrnl.c +++ b/boot/freeldr/freeldr/arch/i386/ntoskrnl.c @@ -57,6 +57,8 @@ IoSetPartitionInformation( } #ifndef _M_AMD64 +#include "disk/part_mbr.h" // For PARTITION_TABLE_ENTRY and MASTER_BOOT_RECORD + NTSTATUS NTAPI IopReadBootRecord( @@ -203,7 +205,7 @@ IoReadPartitionTable( *PartitionBuffer = Partitions; return STATUS_SUCCESS; } -#endif // _M_AMD64 +#endif // !_M_AMD64 NTSTATUS FASTCALL diff --git a/boot/freeldr/freeldr/arch/uefi/uefidisk.c b/boot/freeldr/freeldr/arch/uefi/uefidisk.c index 4854c8f7e9d..caf5df095d4 100644 --- a/boot/freeldr/freeldr/arch/uefi/uefidisk.c +++ b/boot/freeldr/freeldr/arch/uefi/uefidisk.c @@ -2,7 +2,7 @@ * PROJECT: FreeLoader UEFI Support * LICENSE: MIT (https://spdx.org/licenses/MIT) * PURPOSE: Disk Access Functions - * COPYRIGHT: Copyright 2022 Justin Miller + * COPYRIGHT: Copyright 2022-2026 Justin Miller */ /* INCLUDES ******************************************************************/ @@ -169,16 +169,17 @@ DiskReadGptHeader( static BOOLEAN UefiGetBootPartitionEntry( - IN UCHAR DriveNumber, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry, - OUT PULONG BootPartition) + _In_ UCHAR DriveNumber, + _Out_opt_ PPARTITION_INFORMATION PartitionEntry, + _Out_ PULONG BootPartition) { ULONG PartitionNum; ULONG ArcDriveIndex; EFI_BLOCK_IO* BootBlockIo; EFI_STATUS Status; + ULONG BlockSize; ULONGLONG BootPartitionSize; - PARTITION_TABLE_ENTRY TempPartitionEntry; + PARTITION_INFORMATION TempPartitionEntry; TRACE("UefiGetBootPartitionEntry: DriveNumber: %d\n", DriveNumber - FIRST_BIOS_DISK); @@ -206,16 +207,25 @@ UefiGetBootPartitionEntry( BootPartitionSize = BootBlockIo->Media->LastBlock + 1; TRACE("Boot partition: Size=%llu blocks, BlockSize=%lu\n", - BootPartitionSize, BootBlockIo->Media->BlockSize); + BootPartitionSize, BootBlockIo->Media->BlockSize); /* If boot handle is the root device itself (not a logical partition) */ if (!BootBlockIo->Media->LogicalPartition) { TRACE("Boot handle is root device, using partition 0\n"); *BootPartition = 0; - if (PartitionTableEntry != NULL) + if (PartitionEntry) { - RtlZeroMemory(PartitionTableEntry, sizeof(*PartitionTableEntry)); + // RtlZeroMemory(PartitionEntry, sizeof(*PartitionEntry)); + /* Represent the whole disk */ + PartitionEntry->StartingOffset.QuadPart = 0ULL; + PartitionEntry->PartitionLength.QuadPart = (BootPartitionSize * BootBlockIo->Media->BlockSize); + PartitionEntry->HiddenSectors = 0; + PartitionEntry->PartitionNumber = *BootPartition; + PartitionEntry->PartitionType = PARTITION_GPT; /* Mark as GPT partition */ + PartitionEntry->BootIndicator = TRUE; + PartitionEntry->RecognizedPartition = TRUE; + PartitionEntry->RewritePartition = FALSE; } return TRUE; } @@ -228,14 +238,11 @@ UefiGetBootPartitionEntry( { /* For GPT, iterate through GPT partition entries */ GPT_PARTITION_ENTRY GptEntry; - ULONG ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK; EFI_BLOCK_IO* RootBlockIo; - ULONG BlockSize; - ULONGLONG EntryLba; - ULONG EntryOffset; ULONG EntriesPerBlock; EFI_STATUS Status; EFI_GUID UnusedGuid = EFI_PART_TYPE_UNUSED_GUID; + EFI_GUID SystemGuid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID; Status = GlobalSystemTable->BootServices->HandleProtocol( InternalUefiDisk[ArcDriveIndex].Handle, @@ -251,8 +258,8 @@ UefiGetBootPartitionEntry( /* Iterate through GPT partition entries */ for (ULONG i = 0; i < GptHeader.NumberOfPartitionEntries; i++) { - EntryLba = GptHeader.PartitionEntryLba + (i / EntriesPerBlock); - EntryOffset = (i % EntriesPerBlock) * GptHeader.SizeOfPartitionEntry; + ULONGLONG EntryLba = GptHeader.PartitionEntryLba + (i / EntriesPerBlock); + ULONG EntryOffset = (i % EntriesPerBlock) * GptHeader.SizeOfPartitionEntry; /* Read the block containing the partition entry */ Status = RootBlockIo->ReadBlocks( @@ -276,28 +283,30 @@ UefiGetBootPartitionEntry( ULONGLONG PartitionSizeBlocks = GptEntry.EndingLba - GptEntry.StartingLba + 1; TRACE("GPT Partition %lu: StartLba=%llu, EndLba=%llu, SizeBlocks=%llu\n", - i + 1, GptEntry.StartingLba, GptEntry.EndingLba, PartitionSizeBlocks); + i + 1, GptEntry.StartingLba, GptEntry.EndingLba, PartitionSizeBlocks); /* Match partition by size (within 1 block tolerance for rounding) */ if (PartitionSizeBlocks == BootPartitionSize || - (PartitionSizeBlocks > 0 && + (PartitionSizeBlocks > 0 && (PartitionSizeBlocks - 1 <= BootPartitionSize && BootPartitionSize <= PartitionSizeBlocks + 1))) { TRACE("Found matching GPT partition %lu: Size matches (%llu blocks)\n", - i + 1, BootPartitionSize); + i + 1, BootPartitionSize); *BootPartition = i + 1; /* GPT partitions are 1-indexed */ - /* Convert GPT entry to MBR-style entry for compatibility */ - if (PartitionTableEntry != NULL) + /* Convert GPT entry to standard-style entry */ + if (PartitionEntry) { - RtlZeroMemory(PartitionTableEntry, sizeof(*PartitionTableEntry)); - ULONGLONG StartSector = (GptEntry.StartingLba * BlockSize) / 512; - ULONGLONG SectorCount = (PartitionSizeBlocks * BlockSize) / 512; - PartitionTableEntry->SectorCountBeforePartition = (ULONG)StartSector; - PartitionTableEntry->PartitionSectorCount = (ULONG)SectorCount; - PartitionTableEntry->SystemIndicator = PARTITION_GPT; + PartitionEntry->StartingOffset.QuadPart = (GptEntry.StartingLba * BlockSize); + PartitionEntry->PartitionLength.QuadPart = ((ULONGLONG)PartitionSizeBlocks * BlockSize); + PartitionEntry->HiddenSectors = 0; + PartitionEntry->PartitionNumber = *BootPartition; + PartitionEntry->PartitionType = PARTITION_GPT; /* Mark as GPT partition */ + PartitionEntry->BootIndicator = RtlEqualMemory(&GptEntry.PartitionTypeGuid, &SystemGuid, sizeof(SystemGuid)); + PartitionEntry->RecognizedPartition = TRUE; + PartitionEntry->RewritePartition = FALSE; } return TRUE; } @@ -306,36 +315,32 @@ UefiGetBootPartitionEntry( else { /* MBR partition matching */ + + BlockSize = BootBlockIo->Media->BlockSize; + PartitionNum = FIRST_PARTITION; - while (DiskGetPartitionEntry(DriveNumber, PartitionNum, &TempPartitionEntry)) + while (DiskGetPartitionEntry(DriveNumber, BlockSize, PartitionNum, &TempPartitionEntry)) { - ULONGLONG PartitionSizeSectors = TempPartitionEntry.PartitionSectorCount; - ULONGLONG PartitionSizeBlocks; + /* Convert partition size to UEFI blocks */ + ULONGLONG PartitionSizeBlocks = TempPartitionEntry.PartitionLength.QuadPart / BlockSize; + ULONGLONG StartingLba = TempPartitionEntry.StartingOffset.QuadPart / BlockSize; + ULONGLONG EndingLba = StartingLba + PartitionSizeBlocks - 1; - /* Convert partition size from MBR sectors (always 512 bytes) to UEFI blocks. - * MBR partition table always uses 512-byte sectors per specification. - * UEFI Block I/O protocol reports sizes in device's BlockSize bytes. */ - /* Compare in bytes to avoid rounding issues, then convert to boot partition's block size */ - ULONGLONG PartitionSizeBytes = PartitionSizeSectors * 512ULL; - PartitionSizeBlocks = PartitionSizeBytes / BootBlockIo->Media->BlockSize; - - TRACE("Partition %lu: SizeSectors=%llu, SizeBlocks=%llu\n", - PartitionNum, PartitionSizeSectors, PartitionSizeBlocks); + TRACE("Partition %lu: StartLba=%llu, EndLba=%llu, SizeBlocks=%llu\n", + PartitionNum, StartingLba, EndingLba, PartitionSizeBlocks); /* Match partition by size (within 1 block tolerance for rounding) */ if (PartitionSizeBlocks == BootPartitionSize || - (PartitionSizeBlocks > 0 && + (PartitionSizeBlocks > 0 && (PartitionSizeBlocks - 1 <= BootPartitionSize && BootPartitionSize <= PartitionSizeBlocks + 1))) { TRACE("Found matching partition %lu: Size matches (%llu blocks)\n", - PartitionNum, BootPartitionSize); + PartitionNum, BootPartitionSize); *BootPartition = PartitionNum; - if (PartitionTableEntry != NULL) - { - RtlCopyMemory(PartitionTableEntry, &TempPartitionEntry, sizeof(*PartitionTableEntry)); - } + if (PartitionEntry) + RtlCopyMemory(PartitionEntry, &TempPartitionEntry, sizeof(*PartitionEntry)); return TRUE; } @@ -348,9 +353,18 @@ UefiGetBootPartitionEntry( { TRACE("Boot device is CD-ROM, using partition 0xFF\n"); *BootPartition = 0xFF; - if (PartitionTableEntry != NULL) + if (PartitionEntry) { - RtlZeroMemory(PartitionTableEntry, sizeof(*PartitionTableEntry)); + // RtlZeroMemory(PartitionEntry, sizeof(*PartitionEntry)); + /* Represent the whole disk */ + PartitionEntry->StartingOffset.QuadPart = 0ULL; + PartitionEntry->PartitionLength.QuadPart = (BootPartitionSize * BootBlockIo->Media->BlockSize); + PartitionEntry->HiddenSectors = 0; + PartitionEntry->PartitionNumber = *BootPartition; + PartitionEntry->PartitionType = PARTITION_GPT; /* Mark as GPT partition */ + PartitionEntry->BootIndicator = TRUE; + PartitionEntry->RecognizedPartition = TRUE; + PartitionEntry->RewritePartition = FALSE; } return TRUE; } @@ -358,13 +372,12 @@ UefiGetBootPartitionEntry( /* Fallback: if we can't determine, use partition 1 */ ERR("Could not determine boot partition, using partition 1 as fallback\n"); PartitionNum = FIRST_PARTITION; - if (DiskGetPartitionEntry(DriveNumber, PartitionNum, &TempPartitionEntry)) + if (DiskGetPartitionEntry(DriveNumber, BootBlockIo->Media->BlockSize, + PartitionNum, &TempPartitionEntry)) { *BootPartition = PartitionNum; - if (PartitionTableEntry != NULL) - { - RtlCopyMemory(PartitionTableEntry, &TempPartitionEntry, sizeof(*PartitionTableEntry)); - } + if (PartitionEntry) + RtlCopyMemory(PartitionEntry, &TempPartitionEntry, sizeof(*PartitionEntry)); return TRUE; } @@ -409,10 +422,9 @@ UefiDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId) DISKCONTEXT* Context; UCHAR DriveNumber; ULONG DrivePartition, SectorSize; - ULONGLONG SectorOffset = 0; - ULONGLONG SectorCount = 0; + ULONGLONG SectorOffset; + ULONGLONG SectorCount; ULONG ArcDriveIndex; - PARTITION_TABLE_ENTRY PartitionTableEntry; EFI_BLOCK_IO* BlockIo; EFI_STATUS Status; @@ -453,33 +465,29 @@ UefiDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId) if (!BlockIo->Media->MediaPresent) { ERR("Media not present for drive %d\n", DriveNumber); - return EINVAL; + return ENXIO; } +#if 0 + GEOMETRY Geometry; + if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry)) + return EIO; +#endif SectorSize = BlockIo->Media->BlockSize; if (DrivePartition != 0xff && DrivePartition != 0) { - if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry)) - return EINVAL; + PARTITION_INFORMATION PartitionEntry; + if (!DiskGetPartitionEntry(DriveNumber, SectorSize, DrivePartition, &PartitionEntry)) + return EIO; - SectorOffset = PartitionTableEntry.SectorCountBeforePartition; - SectorCount = PartitionTableEntry.PartitionSectorCount; + SectorOffset = PartitionEntry.StartingOffset.QuadPart / SectorSize; + SectorCount = PartitionEntry.PartitionLength.QuadPart / SectorSize; } else { - GEOMETRY Geometry; - if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry)) - return EINVAL; - - if (SectorSize != Geometry.BytesPerSector) - { - ERR("SectorSize (%lu) != Geometry.BytesPerSector (%lu), expect problems!\n", - SectorSize, Geometry.BytesPerSector); - } - SectorOffset = 0; - SectorCount = Geometry.Sectors; + SectorCount = BlockIo->Media->LastBlock + 1; // Geometry.Sectors; } Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT); @@ -492,6 +500,7 @@ UefiDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId) Context->SectorCount = SectorCount; Context->SectorNumber = 0; FsSetDeviceSpecific(*FileId, Context); + return ESUCCESS; } @@ -998,7 +1007,6 @@ UefiSetBootpath(VOID) else { ULONG BootPartition; - PARTITION_TABLE_ENTRY PartitionEntry; /* This is a hard disk */ /* If boot handle is a logical partition, we need to determine which partition number */ @@ -1013,7 +1021,7 @@ UefiSetBootpath(VOID) else { /* Boot handle is the root device itself */ - if (!UefiGetBootPartitionEntry(FrldrBootDrive, &PartitionEntry, &BootPartition)) + if (!UefiGetBootPartitionEntry(FrldrBootDrive, NULL, &BootPartition)) { ERR("Failed to get boot partition entry\n"); return FALSE; diff --git a/boot/freeldr/freeldr/disk/disk.c b/boot/freeldr/freeldr/disk/disk.c index 98e30bcbff3..a7159d9adc3 100644 --- a/boot/freeldr/freeldr/disk/disk.c +++ b/boot/freeldr/freeldr/disk/disk.c @@ -13,7 +13,8 @@ #include DBG_DEFAULT_CHANNEL(DISK); -#include "disk/part_gpt.h" +#include "part_mbr.h" // FIXME: For MASTER_BOOT_RECORD +#include "part_gpt.h" // Defined in part_gpt.c extern BOOLEAN @@ -85,30 +86,34 @@ DiskInitialize( { PMASTER_BOOT_RECORD Mbr; PULONG Buffer; + GEOMETRY Geometry; ULONGLONG SectorStart; - ULONG SectorSize; + ULONG MbrSectorSize; ULONG i; ULONG Checksum, Signature; BOOLEAN ValidPartitionTable; BOOLEAN IsCdRom; PGUID GptDiskGuid = NULL; GPT_TABLE_HEADER GptHeader; - PARTITION_TABLE_ENTRY PartitionTableEntry; + PARTITION_INFORMATION PartitionEntry; CHAR ArcName[MAX_PATH]; NTSTATUS NtStatus; TRACE("DiskInitialize(0x%02X, '%s', Type: %lu)\n", DriveNumber, DeviceName, DeviceType); + if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry)) + return FALSE; + IsCdRom = (DeviceType == CdromController); if (IsCdRom) { SectorStart = 16ULL; - SectorSize = 2048; + MbrSectorSize = 2048; } else // (DeviceType == FloppyDiskPeripheral || DiskPeripheral) { SectorStart = 0ULL; - SectorSize = 512; + MbrSectorSize = 512; } /* Read the MBR */ @@ -126,7 +131,7 @@ DiskInitialize( /* Calculate the MBR checksum */ Checksum = 0; - for (i = 0; i < SectorSize / sizeof(ULONG); i++) + for (i = 0; i < MbrSectorSize / sizeof(ULONG); i++) { Checksum += Buffer[i]; } @@ -185,9 +190,9 @@ DiskInitialize( /* Add partitions */ i = FIRST_PARTITION; - while (DiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry)) + while (DiskGetPartitionEntry(DriveNumber, Geometry.BytesPerSector, i, &PartitionEntry)) { - if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED) + if (PartitionEntry.PartitionType != PARTITION_ENTRY_UNUSED) { NtStatus = RtlStringCbPrintfA(ArcName, sizeof(ArcName), "%spartition(%lu)", DeviceName, i); diff --git a/boot/freeldr/freeldr/disk/part_brfr.c b/boot/freeldr/freeldr/disk/part_brfr.c index 2f30c518908..2d07c79b3cf 100644 --- a/boot/freeldr/freeldr/disk/part_brfr.c +++ b/boot/freeldr/freeldr/disk/part_brfr.c @@ -18,9 +18,9 @@ static struct { - ULONG SectorCountBeforePartition; - ULONG PartitionSectorCount; - UCHAR SystemIndicator; + ULONG SectorStart; + ULONG SectorCount; + UCHAR PartitionType; } XboxPartitions[] = { /* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */ @@ -31,33 +31,45 @@ static struct { 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */ }; +static BOOLEAN +DiskIsBrfr( + _In_ UCHAR DriveNumber) +{ + /* Read the Xbox-specific sector */ + if (!MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, DiskReadBuffer)) + return FALSE; /* Partition does not exist */ + + /* Verify the magic Xbox signature */ + return (*((PULONG)DiskReadBuffer) == XBOX_SIGNATURE); +} + BOOLEAN DiskGetBrfrPartitionEntry( - IN UCHAR DriveNumber, - IN ULONG PartitionNumber, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry) + _In_ UCHAR DriveNumber, + _In_ ULONG SectorSize, + _In_ ULONG PartitionNumber, + _Out_ PPARTITION_INFORMATION PartitionEntry) { - /* - * Get partition entry of an Xbox-standard BRFR partitioned disk. - */ - if (PartitionNumber >= 1 && PartitionNumber <= RTL_NUMBER_OF(XboxPartitions) && - MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, DiskReadBuffer)) - { - if (*((PULONG)DiskReadBuffer) != XBOX_SIGNATURE) - { - /* No magic Xbox partitions */ - return FALSE; - } + ASSERT(SectorSize >= 512); - RtlZeroMemory(PartitionTableEntry, sizeof(PARTITION_TABLE_ENTRY)); - PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator; - PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition; - PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount; - return TRUE; - } + if (!DiskIsBrfr(DriveNumber)) + return FALSE; /* No magic Xbox partitions */ - /* Partition does not exist */ - return FALSE; + /* Get partition entry of an Xbox-standard BRFR partitioned disk */ + if (!(1 <= PartitionNumber && PartitionNumber <= RTL_NUMBER_OF(XboxPartitions))) + return FALSE; /* Partition does not exist */ + + /* Convert to standard-style entry */ + PartitionEntry->StartingOffset.QuadPart = (ULONGLONG)XboxPartitions[PartitionNumber - 1].SectorStart * SectorSize; + PartitionEntry->PartitionLength.QuadPart = (ULONGLONG)XboxPartitions[PartitionNumber - 1].SectorCount * SectorSize; + PartitionEntry->HiddenSectors = 0; + PartitionEntry->PartitionNumber = PartitionNumber; + PartitionEntry->PartitionType = XboxPartitions[PartitionNumber - 1].PartitionType; + PartitionEntry->BootIndicator = (PartitionNumber == FATX_DATA_PARTITION); + PartitionEntry->RecognizedPartition = TRUE; + PartitionEntry->RewritePartition = FALSE; + + return TRUE; } #endif diff --git a/boot/freeldr/freeldr/disk/part_gpt.c b/boot/freeldr/freeldr/disk/part_gpt.c index 6467866a9d1..4b40eb79d4c 100644 --- a/boot/freeldr/freeldr/disk/part_gpt.c +++ b/boot/freeldr/freeldr/disk/part_gpt.c @@ -45,34 +45,33 @@ DiskReadGptHeader( BOOLEAN DiskGetGptPartitionEntry( _In_ UCHAR DriveNumber, + _In_ ULONG SectorSize, // BlockSize _In_ ULONG PartitionNumber, - _Out_ PPARTITION_TABLE_ENTRY PartitionTableEntry) + _Out_ PPARTITION_INFORMATION PartitionEntry) { GPT_TABLE_HEADER GptHeader; GPT_PARTITION_ENTRY GptEntry; - GEOMETRY Geometry; - ULONG BlockSize; ULONGLONG EntryLba; ULONG EntryOffset; ULONG EntriesPerBlock; GUID UnusedGuid = EFI_PART_TYPE_UNUSED_GUID; + GUID SystemGuid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID; - if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry)) - return FALSE; - BlockSize = Geometry.BytesPerSector; + ASSERT(SectorSize >= 512); /* Read GPT header */ if (!DiskReadGptHeader(DriveNumber, &GptHeader)) return FALSE; /* Validate partition number */ - if (PartitionNumber == 0 || PartitionNumber > GptHeader.NumberOfPartitionEntries) + //if (PartitionNumber == 0 || PartitionNumber > GptHeader.NumberOfPartitionEntries) + if (!(1 <= PartitionNumber && PartitionNumber <= GptHeader.NumberOfPartitionEntries)) return FALSE; /* Convert to 0-based index */ ULONG EntryIndex = PartitionNumber - 1; - EntriesPerBlock = BlockSize / GptHeader.SizeOfPartitionEntry; + EntriesPerBlock = SectorSize / GptHeader.SizeOfPartitionEntry; EntryLba = GptHeader.PartitionEntryLba + (EntryIndex / EntriesPerBlock); EntryOffset = (EntryIndex % EntriesPerBlock) * GptHeader.SizeOfPartitionEntry; @@ -87,20 +86,18 @@ DiskGetGptPartitionEntry( if (RtlEqualMemory(&GptEntry.PartitionTypeGuid, &UnusedGuid, sizeof(UnusedGuid))) return FALSE; - /* Convert GPT entry to MBR-style PARTITION_TABLE_ENTRY */ - RtlZeroMemory(PartitionTableEntry, sizeof(*PartitionTableEntry)); + /* Calculate partition size in blocks */ + ULONGLONG PartitionSizeBlocks = GptEntry.EndingLba - GptEntry.StartingLba + 1; - /* Calculate sector offset and count. - * GPT uses LBA, convert to 512-byte sectors. */ - ULONGLONG SectorCount = (GptEntry.EndingLba - GptEntry.StartingLba + 1); - - /* For GPT, we need to convert from device block size to 512-byte sectors */ - ULONGLONG StartSector = (GptEntry.StartingLba * BlockSize) / 512; - ULONGLONG SectorCount512 = (SectorCount * BlockSize) / 512; - - PartitionTableEntry->SectorCountBeforePartition = (ULONG)StartSector; - PartitionTableEntry->PartitionSectorCount = (ULONG)SectorCount512; - PartitionTableEntry->SystemIndicator = PARTITION_GPT; /* Mark as GPT partition */ + /* Convert GPT entry to standard-style entry */ + PartitionEntry->StartingOffset.QuadPart = (GptEntry.StartingLba * SectorSize); + PartitionEntry->PartitionLength.QuadPart = (PartitionSizeBlocks * SectorSize); + PartitionEntry->HiddenSectors = 0; + PartitionEntry->PartitionNumber = PartitionNumber; + PartitionEntry->PartitionType = PARTITION_GPT; /* Mark as GPT partition */ + PartitionEntry->BootIndicator = RtlEqualMemory(&GptEntry.PartitionTypeGuid, &SystemGuid, sizeof(SystemGuid)); + PartitionEntry->RecognizedPartition = TRUE; + PartitionEntry->RewritePartition = FALSE; return TRUE; } diff --git a/boot/freeldr/freeldr/disk/part_mbr.c b/boot/freeldr/freeldr/disk/part_mbr.c index 533b05b3dbf..7211020598d 100644 --- a/boot/freeldr/freeldr/disk/part_mbr.c +++ b/boot/freeldr/freeldr/disk/part_mbr.c @@ -15,8 +15,8 @@ static BOOLEAN DiskGetFirstPartitionEntry( - IN PMASTER_BOOT_RECORD MasterBootRecord, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry) + _In_ PMASTER_BOOT_RECORD MasterBootRecord, + _Out_ PPARTITION_TABLE_ENTRY* pPartitionTableEntry) { ULONG Index; @@ -27,7 +27,7 @@ DiskGetFirstPartitionEntry( (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_EXTENDED) && (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_XINT13_EXTENDED)) { - RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY)); + *pPartitionTableEntry = &MasterBootRecord->PartitionTable[Index]; return TRUE; } } @@ -37,8 +37,8 @@ DiskGetFirstPartitionEntry( static BOOLEAN DiskGetFirstExtendedPartitionEntry( - IN PMASTER_BOOT_RECORD MasterBootRecord, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry) + _In_ PMASTER_BOOT_RECORD MasterBootRecord, + _Out_ PPARTITION_TABLE_ENTRY* pPartitionTableEntry) { ULONG Index; @@ -48,7 +48,7 @@ DiskGetFirstExtendedPartitionEntry( if ((MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_EXTENDED) || (MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_XINT13_EXTENDED)) { - RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY)); + *pPartitionTableEntry = &MasterBootRecord->PartitionTable[Index]; return TRUE; } } @@ -56,47 +56,66 @@ DiskGetFirstExtendedPartitionEntry( return FALSE; } +static VOID +DiskMbrPartitionTableEntryToInformation( + _Out_ PPARTITION_INFORMATION PartitionEntry, + _In_ PPARTITION_TABLE_ENTRY PartitionTableEntry, + _In_ ULONG PartitionNumber, + _In_ ULONG SectorSize) +{ + PartitionEntry->StartingOffset.QuadPart = (ULONGLONG)PartitionTableEntry->SectorCountBeforePartition * SectorSize; + PartitionEntry->PartitionLength.QuadPart = (ULONGLONG)PartitionTableEntry->PartitionSectorCount * SectorSize; + PartitionEntry->HiddenSectors = 0; + PartitionEntry->PartitionNumber = PartitionNumber; + PartitionEntry->PartitionType = PartitionTableEntry->SystemIndicator; + PartitionEntry->BootIndicator = (PartitionTableEntry->BootIndicator == 0x80); // or "& 0x80" + PartitionEntry->RecognizedPartition = TRUE; + PartitionEntry->RewritePartition = FALSE; +} + BOOLEAN DiskGetActivePartitionEntry( - IN UCHAR DriveNumber, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry, - OUT PULONG ActivePartition) + _In_ UCHAR DriveNumber, + _In_ ULONG SectorSize, + _Out_opt_ PPARTITION_INFORMATION PartitionEntry, + _Out_ PULONG ActivePartition) { + MASTER_BOOT_RECORD MasterBootRecord; ULONG BootablePartitionCount = 0; ULONG CurrentPartitionNumber; ULONG Index; - MASTER_BOOT_RECORD MasterBootRecord; - PPARTITION_TABLE_ENTRY ThisPartitionTableEntry; + + ASSERT(SectorSize >= 512); *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]; + PPARTITION_TABLE_ENTRY PartitionTableEntry = &MasterBootRecord.PartitionTable[Index]; - if (ThisPartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED && - ThisPartitionTableEntry->SystemIndicator != PARTITION_EXTENDED && - ThisPartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED) + if (PartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED && + PartitionTableEntry->SystemIndicator != PARTITION_EXTENDED && + PartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED) { CurrentPartitionNumber++; /* Test if this is the bootable partition */ - if (ThisPartitionTableEntry->BootIndicator == 0x80) + if (PartitionTableEntry->BootIndicator == 0x80) { BootablePartitionCount++; *ActivePartition = CurrentPartitionNumber; /* Copy the partition table entry */ - RtlCopyMemory(PartitionTableEntry, - ThisPartitionTableEntry, - sizeof(PARTITION_TABLE_ENTRY)); + if (PartitionEntry) + { + DiskMbrPartitionTableEntryToInformation(PartitionEntry, PartitionTableEntry, + *ActivePartition, SectorSize); + } } } } @@ -118,39 +137,44 @@ DiskGetActivePartitionEntry( BOOLEAN DiskGetMbrPartitionEntry( - IN UCHAR DriveNumber, - IN ULONG PartitionNumber, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry) + _In_ UCHAR DriveNumber, + _In_ ULONG SectorSize, + _In_ ULONG PartitionNumber, + _Out_ PPARTITION_INFORMATION PartitionEntry) { MASTER_BOOT_RECORD MasterBootRecord; - PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry; + PPARTITION_TABLE_ENTRY PartitionTableEntry; ULONG ExtendedPartitionNumber; ULONG ExtendedPartitionOffset; ULONG Index; ULONG CurrentPartitionNumber; - PPARTITION_TABLE_ENTRY ThisPartitionTableEntry; + + ASSERT(SectorSize >= 512); + + /* Validate partition number */ + if (PartitionNumber < 1) //if (PartitionNumber == 0) + return FALSE; /* Read master boot record */ if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord)) - { return FALSE; - } CurrentPartitionNumber = 0; for (Index = 0; Index < 4; Index++) { - ThisPartitionTableEntry = &MasterBootRecord.PartitionTable[Index]; + PartitionTableEntry = &MasterBootRecord.PartitionTable[Index]; - if (ThisPartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED && - ThisPartitionTableEntry->SystemIndicator != PARTITION_EXTENDED && - ThisPartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED) + if (PartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED && + PartitionTableEntry->SystemIndicator != PARTITION_EXTENDED && + PartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED) { CurrentPartitionNumber++; } if (PartitionNumber == CurrentPartitionNumber) { - RtlCopyMemory(PartitionTableEntry, ThisPartitionTableEntry, sizeof(PARTITION_TABLE_ENTRY)); + DiskMbrPartitionTableEntryToInformation(PartitionEntry, PartitionTableEntry, + PartitionNumber, SectorSize); return TRUE; } } @@ -171,39 +195,38 @@ DiskGetMbrPartitionEntry( for (Index = 0; Index <= ExtendedPartitionNumber; Index++) { + PPARTITION_TABLE_ENTRY ExtendedPartitionTableEntry; + ULONG SectorCountBeforePartition; + /* Get the extended partition table entry */ if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord, &ExtendedPartitionTableEntry)) - { return FALSE; - } /* Adjust the relative starting sector of the partition */ - ExtendedPartitionTableEntry.SectorCountBeforePartition += ExtendedPartitionOffset; + ExtendedPartitionTableEntry->SectorCountBeforePartition += ExtendedPartitionOffset; if (ExtendedPartitionOffset == 0) { - /* Set the start of the parrent extended partition */ - ExtendedPartitionOffset = ExtendedPartitionTableEntry.SectorCountBeforePartition; + /* Set the start of the parent extended partition */ + ExtendedPartitionOffset = ExtendedPartitionTableEntry->SectorCountBeforePartition; } + SectorCountBeforePartition = ExtendedPartitionTableEntry->SectorCountBeforePartition; + /* Read the partition boot record */ - if (!DiskReadBootRecord(DriveNumber, ExtendedPartitionTableEntry.SectorCountBeforePartition, &MasterBootRecord)) - { + if (!DiskReadBootRecord(DriveNumber, SectorCountBeforePartition, &MasterBootRecord)) return FALSE; - } /* Get the first real partition table entry */ - if (!DiskGetFirstPartitionEntry(&MasterBootRecord, PartitionTableEntry)) - { + if (!DiskGetFirstPartitionEntry(&MasterBootRecord, &PartitionTableEntry)) return FALSE; - } /* Now correct the start sector of the partition */ - PartitionTableEntry->SectorCountBeforePartition += ExtendedPartitionTableEntry.SectorCountBeforePartition; + PartitionTableEntry->SectorCountBeforePartition += SectorCountBeforePartition; } - /* - * When we get here we should have the correct entry already - * stored in PartitionTableEntry, so just return TRUE. - */ + /* When we get here we should have the correct entry already + * stored in PartitionTableEntry, so just return TRUE. */ + DiskMbrPartitionTableEntryToInformation(PartitionEntry, PartitionTableEntry, + PartitionNumber, SectorSize); return TRUE; } diff --git a/boot/freeldr/freeldr/disk/partition.c b/boot/freeldr/freeldr/disk/partition.c index e9eb41a0ce9..cfe67f116d4 100644 --- a/boot/freeldr/freeldr/disk/partition.c +++ b/boot/freeldr/freeldr/disk/partition.c @@ -5,6 +5,7 @@ * PURPOSE: Block Device partition management * COPYRIGHT: Copyright 2002-2003 Brian Palmer * Copyright 2019 Stanislav Motylkov + * Copyright 2025-2026 Hermès Bélusca-Maïto */ #ifndef _M_ARM @@ -16,6 +17,8 @@ DBG_DEFAULT_CHANNEL(DISK); #define MaxDriveNumber 0xFF static PARTITION_STYLE DiskPartitionType[MaxDriveNumber + 1]; +#include "part_mbr.h" // FIXME: For MASTER_BOOT_RECORD + BOOLEAN DiskReadBootRecord( IN UCHAR DriveNumber, @@ -56,15 +59,14 @@ DiskReadBootRecord( } #include "part_mbr.c" -#include "part_brfr.c" #include "part_gpt.c" +#include "part_brfr.c" VOID DiskDetectPartitionType( - IN UCHAR DriveNumber) + _In_ UCHAR DriveNumber) { MASTER_BOOT_RECORD MasterBootRecord; - PARTITION_TABLE_ENTRY PartitionTableEntry; /* Probe for Master Boot Record */ if (DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord)) @@ -82,17 +84,13 @@ DiskDetectPartitionType( /* Check for GUID Partition Table */ for (Index = 0; Index < 4; Index++) { - PPARTITION_TABLE_ENTRY ThisPartitionTableEntry; - ThisPartitionTableEntry = &MasterBootRecord.PartitionTable[Index]; + PPARTITION_TABLE_ENTRY PartitionTableEntry = &MasterBootRecord.PartitionTable[Index]; - if (ThisPartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED) + if (PartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED) { PartitionCount++; - - if (Index == 0 && ThisPartitionTableEntry->SystemIndicator == PARTITION_GPT) - { + if (Index == 0 && PartitionTableEntry->SystemIndicator == PARTITION_GPT) GPTProtect = TRUE; - } } } @@ -108,14 +106,14 @@ DiskDetectPartitionType( } /* Probe for Xbox-BRFR partitioning */ - if (DiskGetBrfrPartitionEntry(DriveNumber, FATX_DATA_PARTITION, &PartitionTableEntry)) + if (DiskIsBrfr(DriveNumber)) { DiskPartitionType[DriveNumber] = PARTITION_STYLE_BRFR; TRACE("Drive 0x%X partition type Xbox-BRFR\n", DriveNumber); return; } - /* Failed to detect partitions, assume partitionless disk */ + /* Failed to detect partitions, assume non-partitioned disk */ DiskPartitionType[DriveNumber] = PARTITION_STYLE_RAW; TRACE("Drive 0x%X partition type unknown\n", DriveNumber); } @@ -123,15 +121,24 @@ DiskDetectPartitionType( // FIXME: This function is specific to BIOS-based PC platform. BOOLEAN DiskGetBootPartitionEntry( - IN UCHAR DriveNumber, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry, - OUT PULONG BootPartition) + _In_ UCHAR DriveNumber, + _Out_opt_ PPARTITION_INFORMATION PartitionEntry, + _Out_ PULONG BootPartition) { +#if 0 + GEOMETRY Geometry; + if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry)) + return FALSE; +#endif + switch (DiskPartitionType[DriveNumber]) { case PARTITION_STYLE_MBR: { - return DiskGetActivePartitionEntry(DriveNumber, PartitionTableEntry, BootPartition); + return DiskGetActivePartitionEntry(DriveNumber, + /* MBR partition table always uses 512-byte sectors per specification */ + 512, // Geometry.BytesPerSector + PartitionEntry, BootPartition); } case PARTITION_STYLE_GPT: { @@ -145,7 +152,13 @@ DiskGetBootPartitionEntry( } case PARTITION_STYLE_BRFR: { - if (DiskGetBrfrPartitionEntry(DriveNumber, FATX_DATA_PARTITION, PartitionTableEntry)) + PARTITION_INFORMATION TempPartitionEntry; + if (!PartitionEntry) + PartitionEntry = &TempPartitionEntry; + if (DiskGetBrfrPartitionEntry(DriveNumber, + 512, // Geometry.BytesPerSector + FATX_DATA_PARTITION, + PartitionEntry)) { *BootPartition = FATX_DATA_PARTITION; return TRUE; @@ -163,19 +176,40 @@ DiskGetBootPartitionEntry( BOOLEAN DiskGetPartitionEntry( - IN UCHAR DriveNumber, - IN ULONG PartitionNumber, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry) + _In_ UCHAR DriveNumber, + _In_opt_ ULONG SectorSize, + _In_ ULONG PartitionNumber, + _Out_ PPARTITION_INFORMATION PartitionEntry) { + if (SectorSize == 0) + { + GEOMETRY Geometry; + if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry)) + return FALSE; + SectorSize = Geometry.BytesPerSector; + } + if (SectorSize < 512) + { + ERR("Drive 0x%X: Invalid sector size %lu\n", DriveNumber, SectorSize); + return FALSE; + } + switch (DiskPartitionType[DriveNumber]) { case PARTITION_STYLE_MBR: { - return DiskGetMbrPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry); + return DiskGetMbrPartitionEntry(DriveNumber, + /* MBR partition table always uses 512-byte sectors per specification */ + 512, // SectorSize + PartitionNumber, + PartitionEntry); } case PARTITION_STYLE_GPT: { - return DiskGetGptPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry); + return DiskGetGptPartitionEntry(DriveNumber, + SectorSize, + PartitionNumber, + PartitionEntry); } case PARTITION_STYLE_RAW: { @@ -184,7 +218,10 @@ DiskGetPartitionEntry( } case PARTITION_STYLE_BRFR: { - return DiskGetBrfrPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry); + return DiskGetBrfrPartitionEntry(DriveNumber, + 512, // SectorSize + PartitionNumber, + PartitionEntry); } default: { diff --git a/boot/freeldr/freeldr/include/disk.h b/boot/freeldr/freeldr/include/disk.h index 2858b6aa73b..053c4ec2186 100644 --- a/boot/freeldr/freeldr/include/disk.h +++ b/boot/freeldr/freeldr/include/disk.h @@ -29,9 +29,6 @@ typedef struct _GEOMETRY ULONGLONG Sectors; ///< Total number of disk sectors/LBA blocks } GEOMETRY, *PGEOMETRY; -// Some modules use the explicit MBR structures. TODO: Deprecate -#include "disk/part_mbr.h" - /* * Partition type defines (of PSDK) */ @@ -111,19 +108,20 @@ DiskInitialize( VOID DiskDetectPartitionType( - IN UCHAR DriveNumber); + _In_ UCHAR DriveNumber); BOOLEAN DiskGetBootPartitionEntry( - IN UCHAR DriveNumber, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry, - OUT PULONG BootPartition); + _In_ UCHAR DriveNumber, + _Out_opt_ PPARTITION_INFORMATION PartitionEntry, + _Out_ PULONG BootPartition); BOOLEAN DiskGetPartitionEntry( - IN UCHAR DriveNumber, - IN ULONG PartitionNumber, - OUT PPARTITION_TABLE_ENTRY PartitionTableEntry); + _In_ UCHAR DriveNumber, + _In_opt_ ULONG SectorSize, + _In_ ULONG PartitionNumber, + _Out_ PPARTITION_INFORMATION PartitionEntry); /*