Decode a hard disk partitioned with the GPT scheme in the UEFI 2.0\r
specification.\r
\r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
+ Caution: This file requires additional review when modified.\r
+ This driver will have external input - disk partition.\r
+ This external input must be validated carefully to avoid security issue like\r
+ buffer overflow, integer overflow.\r
+\r
+ PartitionInstallGptChildHandles() routine will read disk partition content and\r
+ do basic validation before PartitionInstallChildHandle().\r
+\r
+ PartitionValidGptTable(), PartitionCheckGptEntry() routine will accept disk\r
+ partition content and validate the GPT table and GPT entry.\r
+\r
+Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.\r
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+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
#include "Partition.h"\r
\r
+/**\r
+ Install child handles if the Handle supports GPT partition structure.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ The GPT partition table header is external input, so this routine\r
+ will do basic validation for GPT partition table header before return.\r
\r
+ @param[in] BlockIo Parent BlockIo interface.\r
+ @param[in] DiskIo Disk Io protocol.\r
+ @param[in] Lba The starting Lba of the Partition Table\r
+ @param[out] PartHeader Stores the partition table that is read\r
+\r
+ @retval TRUE The partition table is valid\r
+ @retval FALSE The partition table is not valid\r
+\r
+**/\r
BOOLEAN\r
PartitionValidGptTable (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
OUT EFI_PARTITION_TABLE_HEADER *PartHeader\r
);\r
\r
+/**\r
+ Check if the CRC field in the Partition table header is valid\r
+ for Partition entry array.\r
+\r
+ @param[in] BlockIo Parent BlockIo interface\r
+ @param[in] DiskIo Disk Io Protocol.\r
+ @param[in] PartHeader Partition table header structure\r
+\r
+ @retval TRUE the CRC is valid\r
+ @retval FALSE the CRC is invalid\r
\r
+**/\r
BOOLEAN\r
PartitionCheckGptEntryArrayCRC (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
);\r
\r
\r
+/**\r
+ Restore Partition Table to its alternate place\r
+ (Primary -> Backup or Backup -> Primary).\r
+\r
+ @param[in] BlockIo Parent BlockIo interface.\r
+ @param[in] DiskIo Disk Io Protocol.\r
+ @param[in] PartHeader Partition table header structure.\r
+\r
+ @retval TRUE Restoring succeeds\r
+ @retval FALSE Restoring failed\r
+\r
+**/\r
BOOLEAN\r
PartitionRestoreGptTable (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
);\r
\r
\r
+/**\r
+ This routine will check GPT partition entry and return entry status.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ The GPT partition entry is external input, so this routine\r
+ will do basic validation for GPT partition entry and report status.\r
+\r
+ @param[in] PartHeader Partition table header structure\r
+ @param[in] PartEntry The partition entry array\r
+ @param[out] PEntryStatus the partition entry status array \r
+ recording the status of each partition\r
+\r
+**/\r
VOID\r
PartitionCheckGptEntry (\r
IN EFI_PARTITION_TABLE_HEADER *PartHeader,\r
);\r
\r
\r
+/**\r
+ Checks the CRC32 value in the table header.\r
+\r
+ @param MaxSize Max Size limit\r
+ @param Size The size of the table\r
+ @param Hdr Table to check\r
+\r
+ @return TRUE CRC Valid\r
+ @return FALSE CRC Invalid\r
+\r
+**/\r
BOOLEAN\r
PartitionCheckCrcAltSize (\r
IN UINTN MaxSize,\r
);\r
\r
\r
+/**\r
+ Checks the CRC32 value in the table header.\r
+\r
+ @param MaxSize Max Size limit\r
+ @param Hdr Table to check\r
+\r
+ @return TRUE CRC Valid\r
+ @return FALSE CRC Invalid\r
+\r
+**/\r
BOOLEAN\r
PartitionCheckCrc (\r
IN UINTN MaxSize,\r
);\r
\r
\r
+/**\r
+ Updates the CRC32 value in the table header.\r
+\r
+ @param Size The size of the table\r
+ @param Hdr Table to update\r
+\r
+**/\r
VOID\r
PartitionSetCrcAltSize (\r
IN UINTN Size,\r
);\r
\r
\r
+/**\r
+ Updates the CRC32 value in the table header.\r
+\r
+ @param Hdr Table to update\r
+\r
+**/\r
VOID\r
PartitionSetCrc (\r
IN OUT EFI_TABLE_HEADER *Hdr\r
/**\r
Install child handles if the Handle supports GPT partition structure.\r
\r
- @param[in] This - Calling context.\r
- @param[in] Handle - Parent Handle\r
- @param[in] DiskIo - Parent DiskIo interface\r
- @param[in] BlockIo - Parent BlockIo interface\r
- @param[in] DevicePath - Parent Device Path\r
+ Caution: This function may receive untrusted input.\r
+ The GPT partition table is external input, so this routine\r
+ will do basic validation for GPT partition table before install\r
+ child handle for each GPT partition.\r
+\r
+ @param[in] This Calling context.\r
+ @param[in] Handle Parent Handle.\r
+ @param[in] DiskIo Parent DiskIo interface.\r
+ @param[in] DiskIo2 Parent DiskIo2 interface.\r
+ @param[in] BlockIo Parent BlockIo interface.\r
+ @param[in] BlockIo2 Parent BlockIo2 interface.\r
+ @param[in] DevicePath Parent Device Path.\r
\r
- @retval EFI_SUCCESS Valid GPT disk\r
- @retval EFI_MEDIA_CHANGED Media changed Detected\r
- @retval other Not a valid GPT disk\r
+ @retval EFI_SUCCESS Valid GPT disk.\r
+ @retval EFI_MEDIA_CHANGED Media changed Detected.\r
+ @retval other Not a valid GPT disk.\r
\r
**/\r
EFI_STATUS\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE Handle,\r
IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,\r
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\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
+ 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 *Entry;\r
+ EFI_PARTITION_ENTRY_STATUS *PEntryStatus;\r
+ UINTN Index;\r
+ EFI_STATUS GptValidStatus;\r
+ HARDDRIVE_DEVICE_PATH HdDev;\r
+ UINT32 MediaId;\r
+ EFI_PARTITION_INFO_PROTOCOL PartitionInfo;\r
\r
ProtectiveMbr = NULL;\r
PrimaryHeader = NULL;\r
\r
BlockSize = BlockIo->Media->BlockSize;\r
LastBlock = BlockIo->Media->LastBlock;\r
+ MediaId = BlockIo->Media->MediaId;\r
\r
DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize));\r
- DEBUG ((EFI_D_INFO, " LastBlock : %x \n", LastBlock));\r
+ DEBUG ((EFI_D_INFO, " LastBlock : %lx \n", LastBlock));\r
\r
- GptValid = EFI_NOT_FOUND;\r
+ GptValidStatus = EFI_NOT_FOUND;\r
\r
//\r
// Allocate a buffer for the Protective MBR\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
+ Status = DiskIo->ReadDisk (\r
+ DiskIo,\r
+ MediaId,\r
+ 0,\r
+ BlockSize,\r
+ ProtectiveMbr\r
+ );\r
if (EFI_ERROR (Status)) {\r
- GptValid = Status;\r
+ GptValidStatus = Status;\r
goto Done;\r
}\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
+ for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {\r
+ if (ProtectiveMbr->Partition[Index].BootIndicator == 0x00 &&\r
+ ProtectiveMbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION &&\r
+ UNPACK_UINT32 (ProtectiveMbr->Partition[Index].StartingLBA) == 1\r
+ ) {\r
+ break;\r
+ }\r
+ }\r
+ if (Index == MAX_MBR_PARTITIONS) {\r
goto Done;\r
}\r
\r
}\r
\r
BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER));\r
-\r
if (BackupHeader == NULL) {\r
goto Done;\r
}\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
+ DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));\r
}\r
\r
if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {\r
//\r
// Read the EFI Partition Entries\r
//\r
- PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY));\r
+ PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);\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
+ DiskIo,\r
+ 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
+ GptValidStatus = Status;\r
+ DEBUG ((EFI_D_ERROR, " Partition Entry ReadDisk error\n"));\r
goto Done;\r
}\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
+ GptValidStatus = 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
+ Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index * PrimaryHeader->SizeOfPartitionEntry);\r
+ if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid) ||\r
PEntryStatus[Index].OutOfRange ||\r
- PEntryStatus[Index].Overlap\r
+ PEntryStatus[Index].Overlap ||\r
+ PEntryStatus[Index].OsSpecific\r
) {\r
//\r
- // Don't use null EFI Partition Entries or Invalid Partition Entries\r
+ // Don't use null EFI Partition Entries, Invalid Partition Entries or OS specific\r
+ // 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
+ 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
+ HdDev.PartitionNumber = (UINT32) Index + 1;\r
+ HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;\r
+ HdDev.SignatureType = SIGNATURE_TYPE_GUID;\r
+ HdDev.PartitionStart = Entry->StartingLBA;\r
+ HdDev.PartitionSize = Entry->EndingLBA - Entry->StartingLBA + 1;\r
+ CopyMem (HdDev.Signature, &Entry->UniquePartitionGUID, sizeof (EFI_GUID));\r
+\r
+ ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));\r
+ PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;\r
+ PartitionInfo.Type = PARTITION_TYPE_GPT;\r
+ if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)) {\r
+ PartitionInfo.System = 1;\r
+ }\r
+ CopyMem (&PartitionInfo.Info.Gpt, Entry, sizeof (EFI_PARTITION_ENTRY));\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
+ DEBUG ((EFI_D_INFO, " Index : %d\n", (UINT32) Index));\r
+ DEBUG ((EFI_D_INFO, " Start LBA : %lx\n", (UINT64) HdDev.PartitionStart));\r
+ DEBUG ((EFI_D_INFO, " End LBA : %lx\n", (UINT64) Entry->EndingLBA));\r
+ DEBUG ((EFI_D_INFO, " Partition size: %lx\n", (UINT64) HdDev.PartitionSize));\r
+ DEBUG ((EFI_D_INFO, " Start : %lx", MultU64x32 (Entry->StartingLBA, BlockSize)));\r
+ DEBUG ((EFI_D_INFO, " End : %lx\n", MultU64x32 (Entry->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
+ This,\r
+ Handle,\r
+ DiskIo,\r
+ DiskIo2,\r
+ BlockIo,\r
+ BlockIo2,\r
+ DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,\r
+ &PartitionInfo,\r
+ Entry->StartingLBA,\r
+ Entry->EndingLBA,\r
+ BlockSize,\r
+ &Entry->PartitionTypeGUID\r
+ );\r
}\r
\r
DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n"));\r
FreePool (PEntryStatus);\r
}\r
\r
- return GptValid;\r
+ return GptValidStatus;\r
}\r
\r
-\r
/**\r
- Install child handles if the Handle supports GPT partition structure.\r
+ This routine will read GPT partition table header and return it.\r
\r
- @param[in] BlockIo Parent BlockIo interface\r
+ Caution: This function may receive untrusted input.\r
+ The GPT partition table header is external input, so this routine\r
+ will do basic validation for GPT partition table header before return.\r
+\r
+ @param[in] BlockIo Parent BlockIo interface.\r
@param[in] DiskIo Disk Io protocol.\r
@param[in] Lba The starting Lba of the Partition Table\r
- @param[in] PartHeader Stores the partition table that is read\r
+ @param[out] PartHeader Stores the partition table that is read\r
\r
@retval TRUE The partition table is valid\r
@retval FALSE The partition table is not valid\r
EFI_STATUS Status;\r
UINT32 BlockSize;\r
EFI_PARTITION_TABLE_HEADER *PartHdr;\r
+ UINT32 MediaId;\r
\r
BlockSize = BlockIo->Media->BlockSize;\r
-\r
+ MediaId = BlockIo->Media->MediaId;\r
PartHdr = AllocateZeroPool (BlockSize);\r
\r
if (PartHdr == NULL) {\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
+ Status = DiskIo->ReadDisk (\r
+ DiskIo,\r
+ MediaId,\r
+ MultU64x32 (Lba, BlockSize),\r
+ BlockSize,\r
+ PartHdr\r
+ );\r
if (EFI_ERROR (Status)) {\r
FreePool (PartHdr);\r
return FALSE;\r
\r
if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||\r
!PartitionCheckCrc (BlockSize, &PartHdr->Header) ||\r
- PartHdr->MyLBA != Lba\r
+ PartHdr->MyLBA != Lba ||\r
+ (PartHdr->SizeOfPartitionEntry < sizeof (EFI_PARTITION_ENTRY))\r
) {\r
- DEBUG ((EFI_D_INFO, " !Valid efi partition table header\n"));\r
+ DEBUG ((EFI_D_INFO, "Invalid efi partition table header\n"));\r
+ FreePool (PartHdr);\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Ensure the NumberOfPartitionEntries * SizeOfPartitionEntry doesn't overflow.\r
+ //\r
+ if (PartHdr->NumberOfPartitionEntries > DivU64x32 (MAX_UINTN, PartHdr->SizeOfPartitionEntry)) {\r
FreePool (PartHdr);\r
return FALSE;\r
}\r
return TRUE;\r
}\r
\r
-\r
/**\r
Check if the CRC field in the Partition table header is valid\r
for Partition entry array.\r
\r
/**\r
Restore Partition Table to its alternate place\r
- (Primary -> Backup or Backup -> Primary)\r
+ (Primary -> Backup or Backup -> Primary).\r
\r
- @param[in] BlockIo Parent BlockIo interface\r
+ @param[in] BlockIo Parent BlockIo interface.\r
@param[in] DiskIo Disk Io Protocol.\r
- @param[in] PartHeader Partition table header structure\r
+ @param[in] PartHeader Partition table header structure.\r
\r
@retval TRUE Restoring succeeds\r
@retval FALSE Restoring failed\r
EFI_PARTITION_TABLE_HEADER *PartHdr;\r
EFI_LBA PEntryLBA;\r
UINT8 *Ptr;\r
+ UINT32 MediaId;\r
\r
PartHdr = NULL;\r
Ptr = NULL;\r
\r
BlockSize = BlockIo->Media->BlockSize;\r
+ MediaId = BlockIo->Media->MediaId;\r
\r
PartHdr = AllocateZeroPool (BlockSize);\r
\r
PartHdr->PartitionEntryLBA = PEntryLBA;\r
PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr);\r
\r
- Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, PartHdr->MyLBA, BlockSize, PartHdr);\r
+ Status = DiskIo->WriteDisk (\r
+ DiskIo,\r
+ MediaId,\r
+ MultU64x32 (PartHdr->MyLBA, (UINT32) BlockSize),\r
+ BlockSize,\r
+ PartHdr\r
+ );\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
+ DEBUG ((EFI_D_ERROR, " Allocate pool error\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
+ MediaId,\r
+ MultU64x32(PartHeader->PartitionEntryLBA, (UINT32) BlockSize),\r
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
Ptr\r
);\r
\r
Status = DiskIo->WriteDisk (\r
DiskIo,\r
- BlockIo->Media->MediaId,\r
- MultU64x32(PEntryLBA, BlockIo->Media->BlockSize),\r
+ MediaId,\r
+ MultU64x32(PEntryLBA, (UINT32) BlockSize),\r
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
Ptr\r
);\r
\r
Done:\r
FreePool (PartHdr);\r
- FreePool (Ptr);\r
+\r
+ if (Ptr != NULL) {\r
+ FreePool (Ptr);\r
+ }\r
\r
if (EFI_ERROR (Status)) {\r
return FALSE;\r
return TRUE;\r
}\r
\r
-\r
/**\r
- Restore Partition Table to its alternate place\r
- (Primary -> Backup or Backup -> Primary)\r
+ This routine will check GPT partition entry and return entry status.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ The GPT partition entry is external input, so this routine\r
+ will do basic validation for GPT partition entry and report status.\r
\r
@param[in] PartHeader Partition table header structure\r
@param[in] PartEntry The partition entry array\r
@param[out] PEntryStatus the partition entry status array \r
recording the status of each partition\r
+\r
**/\r
VOID\r
PartitionCheckGptEntry (\r
OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus\r
)\r
{\r
- EFI_LBA StartingLBA;\r
- EFI_LBA EndingLBA;\r
- UINTN Index1;\r
- UINTN Index2;\r
+ EFI_LBA StartingLBA;\r
+ EFI_LBA EndingLBA;\r
+ EFI_PARTITION_ENTRY *Entry;\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
+ Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index1 * PartHeader->SizeOfPartitionEntry);\r
+ if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
continue;\r
}\r
\r
- StartingLBA = PartEntry[Index1].StartingLBA;\r
- EndingLBA = PartEntry[Index1].EndingLBA;\r
+ StartingLBA = Entry->StartingLBA;\r
+ EndingLBA = Entry->EndingLBA;\r
if (StartingLBA > EndingLBA ||\r
StartingLBA < PartHeader->FirstUsableLBA ||\r
StartingLBA > PartHeader->LastUsableLBA ||\r
continue;\r
}\r
\r
- for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {\r
+ if ((Entry->Attributes & BIT1) != 0) {\r
+ //\r
+ // If Bit 1 is set, this indicate that this is an OS specific GUID partition. \r
+ //\r
+ PEntryStatus[Index1].OsSpecific = TRUE;\r
+ }\r
\r
- if (CompareGuid (&PartEntry[Index2].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
+ for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {\r
+ Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index2 * PartHeader->SizeOfPartitionEntry);\r
+ if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
continue;\r
}\r
\r
- if (PartEntry[Index2].EndingLBA >= StartingLBA && PartEntry[Index2].StartingLBA <= EndingLBA) {\r
+ if (Entry->EndingLBA >= StartingLBA && Entry->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
\r
/**\r
- Updates the CRC32 value in the table header\r
+ Updates the CRC32 value in the table header.\r
\r
- @param[in,out] Hdr Table to update\r
+ @param Hdr Table to update\r
\r
**/\r
VOID\r
\r
\r
/**\r
- Updates the CRC32 value in the table header\r
+ Updates the CRC32 value in the table header.\r
\r
- @param[in] Size The size of the table\r
- @param[in,out] Hdr Table to update\r
+ @param Size The size of the table\r
+ @param Hdr Table to update\r
\r
**/\r
VOID\r
IN UINTN Size,\r
IN OUT EFI_TABLE_HEADER *Hdr\r
)\r
-\r
{\r
UINT32 Crc;\r
\r
\r
\r
/**\r
- Checks the CRC32 value in the table header\r
+ Checks the CRC32 value in the table header.\r
\r
- @param[in] MaxSize Max Size limit\r
- @param[in,out] Hdr Table to check\r
+ @param MaxSize Max Size limit\r
+ @param Hdr Table to check\r
\r
- @return TRUE CRC Valid\r
- @return FALSE CRC Invalid\r
+ @return TRUE CRC Valid\r
+ @return FALSE CRC Invalid\r
\r
**/\r
BOOLEAN\r
\r
\r
/**\r
- Checks the CRC32 value in the table header\r
+ Checks the CRC32 value in the table header.\r
\r
- @param[in] MaxSize Max Size limit\r
- @param[in] Size The size of the table\r
- @param[in,out] Hdr Table to check\r
+ @param MaxSize Max Size limit\r
+ @param Size The size of the table\r
+ @param Hdr Table to check\r
\r
@return TRUE CRC Valid\r
@return FALSE CRC Invalid\r
return FALSE;\r
}\r
\r
- if (MaxSize && Size > MaxSize) {\r
+ if ((MaxSize != 0) && (Size > MaxSize)) {\r
DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n"));\r
return FALSE;\r
}\r