{
NTSTATUSStatus;
PUCHAR Sector = NULL;
ULONGLONG StartingSector;
PEFI_PARTITION_HEADER EFIHeader;
ULONG i, HeaderCRC32, PreviousCRC32, SectoredPartitionEntriesSize, LonelyPartitions;
PAGED_CODE();
ASSERT(Disk);
ASSERT(IS_VALID_DISK_INFO(Disk));
ASSERT(HeaderBuffer);
/* In case we want to read backup table, we read last disk sector */if (ReadBackupTable)
{
StartingSector = Disk->SectorCount - 1ULL;
}
else
{
/* Otherwise we start at first sector (as sector 0 is the MBR) */
StartingSector = 1ULL;
}
Status = FstubReadSector(Disk->DeviceObject,
Disk->SectorSize,
StartingSector,
Disk->Buffer);
if (!NT_SUCCESS(Status))
{
DPRINT("EFI::Failed reading header!\n");
returnStatus;
}
/* Let's use read buffer as EFI_PARTITION_HEADER */
EFIHeader = (PEFI_PARTITION_HEADER)Disk->Buffer;
/* First check signature * Then, check version (we only support v1) * Finally check header size */if (EFIHeader->Signature != EFI_HEADER_SIGNATURE ||
EFIHeader->Revision != EFI_HEADER_REVISION_1 ||
EFIHeader->HeaderSize != sizeof(EFI_PARTITION_HEADER))
{
DPRINT("EFI::Wrong signature/version/header size!\n");
DPRINT("%I64x (expected: %I64x)\n", EFIHeader->Signature, EFI_HEADER_SIGNATURE);
DPRINT("%03x (expected: %03x)\n", EFIHeader->Revision, EFI_HEADER_REVISION_1);
DPRINT("%02x (expected: %02x)\n", EFIHeader->HeaderSize, sizeof(EFI_PARTITION_HEADER));
returnSTATUS_DISK_CORRUPT_ERROR;
}
/* Save current checksum */
HeaderCRC32 = EFIHeader->HeaderCRC32;
/* Then zero the one in EFI header. This is needed to compute header checksum */
EFIHeader->HeaderCRC32 = 0;
/* Compute header checksum and compare with the one present in partition table */if (RtlComputeCrc32(0, (PUCHAR)Disk->Buffer, sizeof(EFI_PARTITION_HEADER)) != HeaderCRC32)
{
DPRINT("EFI::Not matching header checksum!\n");
returnSTATUS_DISK_CORRUPT_ERROR;
}
/* Put back removed checksum in header */
EFIHeader->HeaderCRC32 = HeaderCRC32;
/* Check if current LBA is matching with ours */if (EFIHeader->MyLBA != StartingSector)
{
DPRINT("EFI::Not matching starting sector!\n");
returnSTATUS_DISK_CORRUPT_ERROR;
}
/* Allocate a buffer to read a sector on the disk */
Sector = ExAllocatePoolWithTag(NonPagedPool,
Disk->SectorSize,
TAG_FSTUB);
if (!Sector)
{
DPRINT("EFI::Lacking resources!\n");
returnSTATUS_INSUFFICIENT_RESOURCES;
}
/* Count how much sectors we'll have to read to read the whole partition table */
SectoredPartitionEntriesSize = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
/* Compute partition table checksum */for (i = 0, PreviousCRC32 = 0; i < SectoredPartitionEntriesSize; i++)
{
Status = FstubReadSector(Disk->DeviceObject,
Disk->SectorSize,
EFIHeader->PartitionEntryLBA + i,
(PUSHORT)Sector);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Sector, TAG_FSTUB);
DPRINT("EFI::Failed reading sector for partition entry!\n");
returnStatus;
}
PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector, Disk->SectorSize);
}
/* Check whether we have a last sector not full of partitions */
LonelyPartitions = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) % Disk->SectorSize;
/* In such case, we have to complete checksum computation */if (LonelyPartitions != 0)
{
/* Read the sector that contains those partitions */
Status = FstubReadSector(Disk->DeviceObject,
Disk->SectorSize,
EFIHeader->PartitionEntryLBA + i,
(PUSHORT)Sector);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Sector, TAG_FSTUB);
DPRINT("EFI::Failed reading sector for partition entry!\n");
returnStatus;
}
/* Then complete checksum by computing on each partition */for (i = 0; i < LonelyPartitions; i++)
{
PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector + i * PARTITION_ENTRY_SIZE, PARTITION_ENTRY_SIZE);
}
}
/* Finally, release memory */ExFreePoolWithTag(Sector, TAG_FSTUB);
/* Compare checksums */if (PreviousCRC32 == EFIHeader->PartitionEntryCRC32)
{
/* In case of a success, return read header */
*HeaderBuffer = *EFIHeader;
returnSTATUS_SUCCESS;
}
else
{
DPRINT("EFI::Not matching partition table checksum!\n");
DPRINT("EFI::Expected: %x, received: %x\n", EFIHeader->PartitionEntryCRC32, PreviousCRC32);
returnSTATUS_DISK_CORRUPT_ERROR;
}
}
Generated on Mon May 28 2012 06:07:14 for ReactOS by
1.7.6.1
ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.