ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

NTSTATUS NTAPI FstubReadHeaderEFI ( IN PDISK_INFORMATION  Disk,
IN BOOLEAN  ReadBackupTable,
PEFI_PARTITION_HEADER  HeaderBuffer 
)

Definition at line 798 of file fstubex.c.

Referenced by FstubReadPartitionTableEFI(), FstubVerifyPartitionTableEFI(), and IoWritePartitionTableEx().

{
    NTSTATUS Status;
    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");
        return Status;
    }
    /* 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));
        return STATUS_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");
        return STATUS_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");
        return STATUS_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");
        return STATUS_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");
            return Status;
        }

        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");
            return Status;
        }

        /* 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;
        return STATUS_SUCCESS;
    }
    else
    {
        DPRINT("EFI::Not matching partition table checksum!\n");
        DPRINT("EFI::Expected: %x, received: %x\n", EFIHeader->PartitionEntryCRC32, PreviousCRC32);
        return STATUS_DISK_CORRUPT_ERROR;
    }
}

Generated on Mon May 28 2012 06:07:14 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.