+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Gpt.c\r
+\r
+Abstract:\r
+\r
+ Decode a hard disk partitioned with the GPT scheme in the EFI 1.0\r
+ specification.\r
+\r
+--*/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "Partition.h"\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionValidGptTable (\r
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ IN EFI_LBA Lba,\r
+ OUT EFI_PARTITION_TABLE_HEADER *PartHeader\r
+ );\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionCheckGptEntryArrayCRC (\r
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader\r
+ );\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionRestoreGptTable (\r
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader\r
+ );\r
+\r
+STATIC\r
+VOID\r
+PartitionCheckGptEntry (\r
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader,\r
+ IN EFI_PARTITION_ENTRY *PartEntry,\r
+ OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus\r
+ );\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionCheckCrcAltSize (\r
+ IN UINTN MaxSize,\r
+ IN UINTN Size,\r
+ IN OUT EFI_TABLE_HEADER *Hdr\r
+ );\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionCheckCrc (\r
+ IN UINTN MaxSize,\r
+ IN OUT EFI_TABLE_HEADER *Hdr\r
+ );\r
+\r
+STATIC\r
+VOID\r
+PartitionSetCrcAltSize (\r
+ IN UINTN Size,\r
+ IN OUT EFI_TABLE_HEADER *Hdr\r
+ );\r
+\r
+STATIC\r
+VOID\r
+PartitionSetCrc (\r
+ IN OUT EFI_TABLE_HEADER *Hdr\r
+ );\r
+\r
+EFI_STATUS\r
+PartitionInstallGptChildHandles (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Install child handles if the Handle supports GPT partition structure.\r
+\r
+Arguments:\r
+ This - Calling context.\r
+ Handle - Parent Handle\r
+ DiskIo - Parent DiskIo interface\r
+ BlockIo - Parent BlockIo interface\r
+ DevicePath - Parent Device Path\r
+\r
+Returns:\r
+ EFI_SUCCESS - Valid GPT disk\r
+ EFI_MEDIA_CHANGED - Media changed Detected\r
+ !EFI_SUCCESS - Not a valid GPT disk\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 BlockSize;\r
+ EFI_LBA LastBlock;\r
+ MASTER_BOOT_RECORD *ProtectiveMbr;\r
+ EFI_PARTITION_TABLE_HEADER *PrimaryHeader;\r
+ EFI_PARTITION_TABLE_HEADER *BackupHeader;\r
+ EFI_PARTITION_ENTRY *PartEntry;\r
+ EFI_PARTITION_ENTRY_STATUS *PEntryStatus;\r
+ UINTN Index;\r
+ EFI_STATUS GptValid;\r
+ HARDDRIVE_DEVICE_PATH HdDev;\r
+\r
+ ProtectiveMbr = NULL;\r
+ PrimaryHeader = NULL;\r
+ BackupHeader = NULL;\r
+ PartEntry = NULL;\r
+ PEntryStatus = NULL;\r
+\r
+ BlockSize = BlockIo->Media->BlockSize;\r
+ LastBlock = BlockIo->Media->LastBlock;\r
+\r
+ DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize));\r
+ DEBUG ((EFI_D_INFO, " LastBlock : %x \n", LastBlock));\r
+\r
+ GptValid = EFI_NOT_FOUND;\r
+\r
+ //\r
+ // Allocate a buffer for the Protective MBR\r
+ //\r
+ ProtectiveMbr = AllocatePool (BlockSize);\r
+ if (ProtectiveMbr == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Read the Protective MBR from LBA #0\r
+ //\r
+ Status = BlockIo->ReadBlocks (\r
+ BlockIo,\r
+ BlockIo->Media->MediaId,\r
+ 0,\r
+ BlockIo->Media->BlockSize,\r
+ ProtectiveMbr\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ GptValid = Status;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Verify that the Protective MBR is valid\r
+ //\r
+ if (ProtectiveMbr->Partition[0].BootIndicator != 0x00 ||\r
+ ProtectiveMbr->Partition[0].OSIndicator != PMBR_GPT_PARTITION ||\r
+ UNPACK_UINT32 (ProtectiveMbr->Partition[0].StartingLBA) != 1\r
+ ) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Allocate the GPT structures\r
+ //\r
+ PrimaryHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER));\r
+ if (PrimaryHeader == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER));\r
+\r
+ if (BackupHeader == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check primary and backup partition tables\r
+ //\r
+ if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) {\r
+ DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n"));\r
+\r
+ if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) {\r
+ DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n"));\r
+ goto Done;\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, " Valid backup partition table\n"));\r
+ DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n"));\r
+ if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) {\r
+ DEBUG ((EFI_D_INFO, " Restore primary partition table error\n"));\r
+ }\r
+\r
+ if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) {\r
+ DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));\r
+ }\r
+ }\r
+ } else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {\r
+ DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n"));\r
+ DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n"));\r
+ if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) {\r
+ DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));\r
+ }\r
+\r
+ if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {\r
+ DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));\r
+ }\r
+\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n"));\r
+\r
+ //\r
+ // Read the EFI Partition Entries\r
+ //\r
+ PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY));\r
+ if (PartEntry == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));\r
+ goto Done;\r
+ }\r
+\r
+ Status = DiskIo->ReadDisk (\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize),\r
+ PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry),\r
+ PartEntry\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ GptValid = Status;\r
+ DEBUG ((EFI_D_INFO, " Partition Entry ReadBlocks error\n"));\r
+ goto Done;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, " Partition entries read block success\n"));\r
+\r
+ DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries));\r
+\r
+ PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS));\r
+ if (PEntryStatus == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check the integrity of partition entries\r
+ //\r
+ PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus);\r
+\r
+ //\r
+ // If we got this far the GPT layout of the disk is valid and we should return true\r
+ //\r
+ GptValid = EFI_SUCCESS;\r
+\r
+ //\r
+ // Create child device handles\r
+ //\r
+ for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
+ if (CompareGuid (&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeUnusedGuid) ||\r
+ PEntryStatus[Index].OutOfRange ||\r
+ PEntryStatus[Index].Overlap\r
+ ) {\r
+ //\r
+ // Don't use null EFI Partition Entries or Invalid Partition Entries\r
+ //\r
+ continue;\r
+ }\r
+\r
+ ZeroMem (&HdDev, sizeof (HdDev));\r
+ HdDev.Header.Type = MEDIA_DEVICE_PATH;\r
+ HdDev.Header.SubType = MEDIA_HARDDRIVE_DP;\r
+ SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));\r
+\r
+ HdDev.PartitionNumber = (UINT32) Index + 1;\r
+ HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;\r
+ HdDev.SignatureType = SIGNATURE_TYPE_GUID;\r
+ HdDev.PartitionStart = PartEntry[Index].StartingLBA;\r
+ HdDev.PartitionSize = PartEntry[Index].EndingLBA - PartEntry[Index].StartingLBA + 1;\r
+ CopyMem (HdDev.Signature, &PartEntry[Index].UniquePartitionGUID, sizeof (EFI_GUID));\r
+\r
+ DEBUG ((EFI_D_INFO, " Index : %d\n", Index));\r
+ DEBUG ((EFI_D_INFO, " Start LBA : %x\n", HdDev.PartitionStart));\r
+ DEBUG ((EFI_D_INFO, " End LBA : %x\n", PartEntry[Index].EndingLBA));\r
+ DEBUG ((EFI_D_INFO, " Partition size: %x\n", HdDev.PartitionSize));\r
+ DEBUG ((EFI_D_INFO, " Start : %x", MultU64x32 (PartEntry[Index].StartingLBA, BlockSize)));\r
+ DEBUG ((EFI_D_INFO, " End : %x\n", MultU64x32 (PartEntry[Index].EndingLBA, BlockSize)));\r
+\r
+ Status = PartitionInstallChildHandle (\r
+ This,\r
+ Handle,\r
+ DiskIo,\r
+ BlockIo,\r
+ DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,\r
+ PartEntry[Index].StartingLBA,\r
+ PartEntry[Index].EndingLBA,\r
+ BlockSize,\r
+ CompareGuid(&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)\r
+ );\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n"));\r
+\r
+Done:\r
+ if (ProtectiveMbr != NULL) {\r
+ FreePool (ProtectiveMbr);\r
+ }\r
+ if (PrimaryHeader != NULL) {\r
+ FreePool (PrimaryHeader);\r
+ }\r
+ if (BackupHeader != NULL) {\r
+ FreePool (BackupHeader);\r
+ }\r
+ if (PartEntry != NULL) {\r
+ FreePool (PartEntry);\r
+ }\r
+ if (PEntryStatus != NULL) {\r
+ FreePool (PEntryStatus);\r
+ }\r
+\r
+ return GptValid;\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionValidGptTable (\r
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ IN EFI_LBA Lba,\r
+ OUT EFI_PARTITION_TABLE_HEADER *PartHeader\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Check if the GPT partition table is valid\r
+\r
+Arguments:\r
+ BlockIo - Parent BlockIo interface\r
+ DiskIo - Disk Io protocol.\r
+ Lba - The starting Lba of the Partition Table\r
+ PartHeader - Stores the partition table that is read\r
+\r
+Returns:\r
+ TRUE - The partition table is valid\r
+ FALSE - The partition table is not valid\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 BlockSize;\r
+ EFI_PARTITION_TABLE_HEADER *PartHdr;\r
+\r
+ BlockSize = BlockIo->Media->BlockSize;\r
+\r
+ PartHdr = AllocateZeroPool (BlockSize);\r
+\r
+ if (PartHdr == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));\r
+ return FALSE;\r
+ }\r
+ //\r
+ // Read the EFI Partition Table Header\r
+ //\r
+ Status = BlockIo->ReadBlocks (\r
+ BlockIo,\r
+ BlockIo->Media->MediaId,\r
+ Lba,\r
+ BlockSize,\r
+ PartHdr\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (PartHdr);\r
+ return FALSE;\r
+ }\r
+\r
+ if ((PartHdr->Header.Signature == EFI_PTAB_HEADER_ID) ||\r
+ !PartitionCheckCrc (BlockSize, &PartHdr->Header) ||\r
+ PartHdr->MyLBA != Lba\r
+ ) {\r
+ DEBUG ((EFI_D_INFO, " !Valid efi partition table header\n"));\r
+ FreePool (PartHdr);\r
+ return FALSE;\r
+ }\r
+\r
+ CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER));\r
+ if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) {\r
+ FreePool (PartHdr);\r
+ return FALSE;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, " Valid efi partition table header\n"));\r
+ FreePool (PartHdr);\r
+ return TRUE;\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionCheckGptEntryArrayCRC (\r
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Check if the CRC field in the Partition table header is valid\r
+ for Partition entry array\r
+\r
+Arguments:\r
+\r
+ BlockIo - parent BlockIo interface\r
+ DiskIo - Disk Io Protocol.\r
+ PartHeader - Partition table header structure\r
+\r
+Returns:\r
+\r
+ TRUE - the CRC is valid\r
+ FALSE - the CRC is invalid\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *Ptr;\r
+ UINT32 Crc;\r
+ UINTN Size;\r
+\r
+ //\r
+ // Read the EFI Partition Entries\r
+ //\r
+ Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);\r
+ if (Ptr == NULL) {\r
+ DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ Status = DiskIo->ReadDisk (\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
+ PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
+ Ptr\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Ptr);\r
+ return FALSE;\r
+ }\r
+\r
+ Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry;\r
+\r
+ Status = gBS->CalculateCrc32 (Ptr, Size, &Crc);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n"));\r
+ FreePool (Ptr);\r
+ return FALSE;\r
+ }\r
+\r
+ FreePool (Ptr);\r
+\r
+ return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 == Crc);\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionRestoreGptTable (\r
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Restore Partition Table to its alternate place\r
+ (Primary -> Backup or Backup -> Primary)\r
+\r
+Arguments:\r
+\r
+ BlockIo - parent BlockIo interface\r
+ DiskIo - Disk Io Protocol.\r
+ PartHeader - the source Partition table header structure\r
+\r
+Returns:\r
+\r
+ TRUE - Restoring succeeds\r
+ FALSE - Restoring failed\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BlockSize;\r
+ EFI_PARTITION_TABLE_HEADER *PartHdr;\r
+ EFI_LBA PEntryLBA;\r
+ UINT8 *Ptr;\r
+\r
+ PartHdr = NULL;\r
+ Ptr = NULL;\r
+\r
+ BlockSize = BlockIo->Media->BlockSize;\r
+\r
+ PartHdr = AllocateZeroPool (BlockSize);\r
+\r
+ if (PartHdr == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \\r
+ (PartHeader->LastUsableLBA + 1) : \\r
+ (PRIMARY_PART_HEADER_LBA + 1);\r
+\r
+ CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER));\r
+\r
+ PartHdr->MyLBA = PartHeader->AlternateLBA;\r
+ PartHdr->AlternateLBA = PartHeader->MyLBA;\r
+ PartHdr->PartitionEntryLBA = PEntryLBA;\r
+ PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr);\r
+\r
+ Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, PartHdr->MyLBA, BlockSize, PartHdr);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);\r
+ if (Ptr == NULL) {\r
+ DEBUG ((EFI_D_ERROR, " Allocate pool effor\n"));\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ Status = DiskIo->ReadDisk (\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
+ PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
+ Ptr\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = DiskIo->WriteDisk (\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32(PEntryLBA, BlockIo->Media->BlockSize),\r
+ PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
+ Ptr\r
+ );\r
+\r
+Done:\r
+ FreePool (PartHdr);\r
+ FreePool (Ptr);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+STATIC\r
+VOID\r
+PartitionCheckGptEntry (\r
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader,\r
+ IN EFI_PARTITION_ENTRY *PartEntry,\r
+ OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Check each partition entry for its range\r
+\r
+Arguments:\r
+\r
+ PartHeader - the partition table header\r
+ PartEntry - the partition entry array\r
+ PEntryStatus - the partition entry status array recording the status of\r
+ each partition\r
+\r
+Returns:\r
+ VOID\r
+\r
+--*/\r
+{\r
+ EFI_LBA StartingLBA;\r
+ EFI_LBA EndingLBA;\r
+ UINTN Index1;\r
+ UINTN Index2;\r
+\r
+ DEBUG ((EFI_D_INFO, " start check partition entries\n"));\r
+ for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) {\r
+ if (CompareGuid (&PartEntry[Index1].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
+ continue;\r
+ }\r
+\r
+ StartingLBA = PartEntry[Index1].StartingLBA;\r
+ EndingLBA = PartEntry[Index1].EndingLBA;\r
+ if (StartingLBA > EndingLBA ||\r
+ StartingLBA < PartHeader->FirstUsableLBA ||\r
+ StartingLBA > PartHeader->LastUsableLBA ||\r
+ EndingLBA < PartHeader->FirstUsableLBA ||\r
+ EndingLBA > PartHeader->LastUsableLBA\r
+ ) {\r
+ PEntryStatus[Index1].OutOfRange = TRUE;\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {\r
+\r
+ if (CompareGuid (&PartEntry[Index2].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
+ continue;\r
+ }\r
+\r
+ if (PartEntry[Index2].EndingLBA >= StartingLBA && PartEntry[Index2].StartingLBA <= EndingLBA) {\r
+ //\r
+ // This region overlaps with the Index1'th region\r
+ //\r
+ PEntryStatus[Index1].Overlap = TRUE;\r
+ PEntryStatus[Index2].Overlap = TRUE;\r
+ continue;\r
+\r
+ }\r
+ }\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, " End check partition entries\n"));\r
+}\r
+\r
+STATIC\r
+VOID\r
+PartitionSetCrc (\r
+ IN OUT EFI_TABLE_HEADER *Hdr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Updates the CRC32 value in the table header\r
+\r
+Arguments:\r
+\r
+ Hdr - The table to update\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);\r
+}\r
+\r
+STATIC\r
+VOID\r
+PartitionSetCrcAltSize (\r
+ IN UINTN Size,\r
+ IN OUT EFI_TABLE_HEADER *Hdr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Updates the CRC32 value in the table header\r
+\r
+Arguments:\r
+\r
+ Size - The size of the table\r
+ Hdr - The table to update\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ UINT32 Crc;\r
+\r
+ Hdr->CRC32 = 0;\r
+ gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);\r
+ Hdr->CRC32 = Crc;\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionCheckCrc (\r
+ IN UINTN MaxSize,\r
+ IN OUT EFI_TABLE_HEADER *Hdr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Checks the CRC32 value in the table header\r
+\r
+Arguments:\r
+\r
+ MaxSize - Max Size limit\r
+ Hdr - The table to check\r
+\r
+Returns:\r
+\r
+ TRUE if the CRC is OK in the table\r
+\r
+--*/\r
+{\r
+ return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+PartitionCheckCrcAltSize (\r
+ IN UINTN MaxSize,\r
+ IN UINTN Size,\r
+ IN OUT EFI_TABLE_HEADER *Hdr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Checks the CRC32 value in the table header\r
+\r
+Arguments:\r
+\r
+ MaxSize - Max Size Limit\r
+ Size - The size of the table\r
+ Hdr - The table to check\r
+\r
+Returns:\r
+\r
+ TRUE if the CRC is OK in the table\r
+\r
+--*/\r
+{\r
+ UINT32 Crc;\r
+ UINT32 OrgCrc;\r
+ EFI_STATUS Status;\r
+\r
+ Crc = 0;\r
+\r
+ if (Size == 0) {\r
+ //\r
+ // If header size is 0 CRC will pass so return FALSE here\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ if (MaxSize && Size > MaxSize) {\r
+ DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n"));\r
+ return FALSE;\r
+ }\r
+ //\r
+ // clear old crc from header\r
+ //\r
+ OrgCrc = Hdr->CRC32;\r
+ Hdr->CRC32 = 0;\r
+\r
+ Status = gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n"));\r
+ return FALSE;\r
+ }\r
+ //\r
+ // set results\r
+ //\r
+ Hdr->CRC32 = Crc;\r
+\r
+ //\r
+ // return status\r
+ //\r
+ DEBUG_CODE_BEGIN ();\r
+ if (OrgCrc != Crc) {\r
+ DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n"));\r
+ }\r
+ DEBUG_CODE_END ();\r
+\r
+ return (BOOLEAN) (OrgCrc == Crc);\r
+}\r