mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
MdeModulePkg/GptLib: Extract shareable GPT parser into a library
As reported in CVE-2024-13745 via oss-sec, DxeTpm2MeasureBootLib can measure a partition table that differs from the one parsed by the PartitionDxe driver. To address this, the more complete GPT parsing logic from PartitionDxe is extracted into a standalone GptLib library so it can be shared between PartitionDxe and DxeTpm2MeasureBootLib. This ensures that the exact same partition table measured into PCR[5] is the one parsed and used by the system. PartitionDxe behavior is unchanged. Ref: https://seclists.org/oss-sec/2026/q2/727 Signed-off-by: Richard Lyu <richard.lyu@suse.com>
This commit is contained in:
parent
2938b830f6
commit
00a865d595
8 changed files with 707 additions and 590 deletions
97
MdeModulePkg/Include/Library/GptLib.h
Normal file
97
MdeModulePkg/Include/Library/GptLib.h
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/** @file
|
||||
Shared GUID Partition Table (GPT) parsing and validation routines.
|
||||
|
||||
These routines decode and validate a disk partitioned with the GPT scheme
|
||||
as described in the UEFI specification. They are shared between the
|
||||
Partition driver (which installs child handles) and other consumers that
|
||||
need to parse the same on-disk GPT layout.
|
||||
|
||||
Caution: These routines may receive untrusted input. The GPT partition
|
||||
table is external input and must be validated carefully to avoid security
|
||||
issues like buffer overflow and integer overflow.
|
||||
|
||||
Copyright (c) 2026, SUSE LLC. All rights reserved.<BR>
|
||||
Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.
|
||||
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Guid/Gpt.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/DiskIo.h>
|
||||
|
||||
//
|
||||
// GPT Partition Entry Status
|
||||
//
|
||||
typedef struct {
|
||||
BOOLEAN OutOfRange;
|
||||
BOOLEAN Overlap;
|
||||
BOOLEAN OsSpecific;
|
||||
} EFI_PARTITION_ENTRY_STATUS;
|
||||
|
||||
/**
|
||||
Read GPT partition table header from the given LBA and validate it.
|
||||
|
||||
Caution: This function may receive untrusted input.
|
||||
The GPT partition table header is external input, so this routine
|
||||
will do basic validation for GPT partition table header before return.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io protocol.
|
||||
@param[in] Lba The starting Lba of the Partition Table.
|
||||
@param[out] PartHeader Stores the partition table that is read.
|
||||
|
||||
@retval TRUE The partition table is valid.
|
||||
@retval FALSE The partition table is not valid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionValidGptTable (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_LBA Lba,
|
||||
OUT EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Restore Partition Table to its alternate place
|
||||
(Primary -> Backup or Backup -> Primary).
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure.
|
||||
|
||||
@retval TRUE Restoring succeeds.
|
||||
@retval FALSE Restoring failed.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionRestoreGptTable (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Check GPT partition entries and report the status of each entry.
|
||||
|
||||
Caution: This function may receive untrusted input.
|
||||
The GPT partition entry is external input, so this routine
|
||||
will do basic validation for GPT partition entry and report status.
|
||||
|
||||
@param[in] PartHeader Partition table header structure.
|
||||
@param[in] PartEntry The partition entry array.
|
||||
@param[out] PEntryStatus The partition entry status array
|
||||
recording the status of each partition.
|
||||
|
||||
**/
|
||||
VOID
|
||||
PartitionCheckGptEntry (
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader,
|
||||
IN EFI_PARTITION_ENTRY *PartEntry,
|
||||
OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
|
||||
);
|
||||
548
MdeModulePkg/Library/GptLib/Gpt.c
Normal file
548
MdeModulePkg/Library/GptLib/Gpt.c
Normal file
|
|
@ -0,0 +1,548 @@
|
|||
/** @file
|
||||
Decode a hard disk partitioned with the GPT scheme in the UEFI 2.0
|
||||
specification.
|
||||
|
||||
Caution: This file requires additional review when modified.
|
||||
This driver will have external input - disk partition.
|
||||
This external input must be validated carefully to avoid security issue like
|
||||
buffer overflow, integer overflow.
|
||||
|
||||
PartitionValidGptTable(), PartitionCheckGptEntry() routine will accept disk
|
||||
partition content and validate the GPT table and GPT entry.
|
||||
|
||||
Copyright (c) 2026, SUSE LLC. All rights reserved.<BR>
|
||||
Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.
|
||||
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/GptLib.h>
|
||||
|
||||
/**
|
||||
Check if the CRC field in the Partition table header is valid
|
||||
for Partition entry array.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure
|
||||
|
||||
@retval TRUE the CRC is valid
|
||||
@retval FALSE the CRC is invalid
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
PartitionCheckGptEntryArrayCRC (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Checks the CRC32 value in the table header.
|
||||
|
||||
@param MaxSize Max Size limit
|
||||
@param Size The size of the table
|
||||
@param Hdr Table to check
|
||||
|
||||
@return TRUE CRC Valid
|
||||
@return FALSE CRC Invalid
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
PartitionCheckCrcAltSize (
|
||||
IN UINTN MaxSize,
|
||||
IN UINTN Size,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
);
|
||||
|
||||
/**
|
||||
Checks the CRC32 value in the table header.
|
||||
|
||||
@param MaxSize Max Size limit
|
||||
@param Hdr Table to check
|
||||
|
||||
@return TRUE CRC Valid
|
||||
@return FALSE CRC Invalid
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
PartitionCheckCrc (
|
||||
IN UINTN MaxSize,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
);
|
||||
|
||||
/**
|
||||
Updates the CRC32 value in the table header.
|
||||
|
||||
@param Size The size of the table
|
||||
@param Hdr Table to update
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
PartitionSetCrcAltSize (
|
||||
IN UINTN Size,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
);
|
||||
|
||||
/**
|
||||
Updates the CRC32 value in the table header.
|
||||
|
||||
@param Hdr Table to update
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
PartitionSetCrc (
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
);
|
||||
|
||||
/**
|
||||
This routine will read GPT partition table header and return it.
|
||||
|
||||
Caution: This function may receive untrusted input.
|
||||
The GPT partition table header is external input, so this routine
|
||||
will do basic validation for GPT partition table header before return.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io protocol.
|
||||
@param[in] Lba The starting Lba of the Partition Table
|
||||
@param[out] PartHeader Stores the partition table that is read
|
||||
|
||||
@retval TRUE The partition table is valid
|
||||
@retval FALSE The partition table is not valid
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionValidGptTable (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_LBA Lba,
|
||||
OUT EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 BlockSize;
|
||||
EFI_PARTITION_TABLE_HEADER *PartHdr;
|
||||
UINT32 MediaId;
|
||||
|
||||
BlockSize = BlockIo->Media->BlockSize;
|
||||
MediaId = BlockIo->Media->MediaId;
|
||||
PartHdr = AllocateZeroPool (BlockSize);
|
||||
|
||||
if (PartHdr == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "Allocate pool error\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Read the EFI Partition Table Header
|
||||
//
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
MediaId,
|
||||
MultU64x32 (Lba, BlockSize),
|
||||
BlockSize,
|
||||
PartHdr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (PartHdr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||
|
||||
!PartitionCheckCrc (BlockSize, &PartHdr->Header) ||
|
||||
(PartHdr->MyLBA != Lba) ||
|
||||
(PartHdr->SizeOfPartitionEntry < sizeof (EFI_PARTITION_ENTRY))
|
||||
)
|
||||
{
|
||||
DEBUG ((DEBUG_INFO, "Invalid efi partition table header\n"));
|
||||
FreePool (PartHdr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Ensure the NumberOfPartitionEntries * SizeOfPartitionEntry doesn't overflow.
|
||||
//
|
||||
if (PartHdr->NumberOfPartitionEntries > DivU64x32 (MAX_UINTN, PartHdr->SizeOfPartitionEntry)) {
|
||||
FreePool (PartHdr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER));
|
||||
if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) {
|
||||
FreePool (PartHdr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, " Valid efi partition table header\n"));
|
||||
FreePool (PartHdr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the CRC field in the Partition table header is valid
|
||||
for Partition entry array.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure
|
||||
|
||||
@retval TRUE the CRC is valid
|
||||
@retval FALSE the CRC is invalid
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
PartitionCheckGptEntryArrayCRC (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 *Ptr;
|
||||
UINT32 Crc;
|
||||
UINTN Size;
|
||||
|
||||
//
|
||||
// Read the EFI Partition Entries
|
||||
//
|
||||
Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
|
||||
if (Ptr == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, " Allocate pool error\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MultU64x32 (PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
|
||||
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Ptr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry;
|
||||
|
||||
Status = gBS->CalculateCrc32 (Ptr, Size, &Crc);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n"));
|
||||
FreePool (Ptr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FreePool (Ptr);
|
||||
|
||||
return (BOOLEAN)(PartHeader->PartitionEntryArrayCRC32 == Crc);
|
||||
}
|
||||
|
||||
/**
|
||||
Restore Partition Table to its alternate place
|
||||
(Primary -> Backup or Backup -> Primary).
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure.
|
||||
|
||||
@retval TRUE Restoring succeeds
|
||||
@retval FALSE Restoring failed
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionRestoreGptTable (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN BlockSize;
|
||||
EFI_PARTITION_TABLE_HEADER *PartHdr;
|
||||
EFI_LBA PEntryLBA;
|
||||
UINT8 *Ptr;
|
||||
UINT32 MediaId;
|
||||
|
||||
PartHdr = NULL;
|
||||
Ptr = NULL;
|
||||
|
||||
BlockSize = BlockIo->Media->BlockSize;
|
||||
MediaId = BlockIo->Media->MediaId;
|
||||
|
||||
PartHdr = AllocateZeroPool (BlockSize);
|
||||
|
||||
if (PartHdr == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "Allocate pool error\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \
|
||||
(PartHeader->LastUsableLBA + 1) : \
|
||||
(PRIMARY_PART_HEADER_LBA + 1);
|
||||
|
||||
CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
|
||||
|
||||
PartHdr->MyLBA = PartHeader->AlternateLBA;
|
||||
PartHdr->AlternateLBA = PartHeader->MyLBA;
|
||||
PartHdr->PartitionEntryLBA = PEntryLBA;
|
||||
PartitionSetCrc ((EFI_TABLE_HEADER *)PartHdr);
|
||||
|
||||
Status = DiskIo->WriteDisk (
|
||||
DiskIo,
|
||||
MediaId,
|
||||
MultU64x32 (PartHdr->MyLBA, (UINT32)BlockSize),
|
||||
BlockSize,
|
||||
PartHdr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
|
||||
if (Ptr == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, " Allocate pool error\n"));
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
MediaId,
|
||||
MultU64x32 (PartHeader->PartitionEntryLBA, (UINT32)BlockSize),
|
||||
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Status = DiskIo->WriteDisk (
|
||||
DiskIo,
|
||||
MediaId,
|
||||
MultU64x32 (PEntryLBA, (UINT32)BlockSize),
|
||||
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
||||
Ptr
|
||||
);
|
||||
|
||||
Done:
|
||||
FreePool (PartHdr);
|
||||
|
||||
if (Ptr != NULL) {
|
||||
FreePool (Ptr);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
This routine will check GPT partition entry and return entry status.
|
||||
|
||||
Caution: This function may receive untrusted input.
|
||||
The GPT partition entry is external input, so this routine
|
||||
will do basic validation for GPT partition entry and report status.
|
||||
|
||||
@param[in] PartHeader Partition table header structure
|
||||
@param[in] PartEntry The partition entry array
|
||||
@param[out] PEntryStatus the partition entry status array
|
||||
recording the status of each partition
|
||||
|
||||
**/
|
||||
VOID
|
||||
PartitionCheckGptEntry (
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader,
|
||||
IN EFI_PARTITION_ENTRY *PartEntry,
|
||||
OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
|
||||
)
|
||||
{
|
||||
EFI_LBA StartingLBA;
|
||||
EFI_LBA EndingLBA;
|
||||
EFI_PARTITION_ENTRY *Entry;
|
||||
UINTN Index1;
|
||||
UINTN Index2;
|
||||
|
||||
DEBUG ((DEBUG_INFO, " start check partition entries\n"));
|
||||
for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) {
|
||||
Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + Index1 * PartHeader->SizeOfPartitionEntry);
|
||||
if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StartingLBA = Entry->StartingLBA;
|
||||
EndingLBA = Entry->EndingLBA;
|
||||
if ((StartingLBA > EndingLBA) ||
|
||||
(StartingLBA < PartHeader->FirstUsableLBA) ||
|
||||
(StartingLBA > PartHeader->LastUsableLBA) ||
|
||||
(EndingLBA < PartHeader->FirstUsableLBA) ||
|
||||
(EndingLBA > PartHeader->LastUsableLBA)
|
||||
)
|
||||
{
|
||||
PEntryStatus[Index1].OutOfRange = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Entry->Attributes & BIT1) != 0) {
|
||||
//
|
||||
// If Bit 1 is set, this indicate that this is an OS specific GUID partition.
|
||||
//
|
||||
PEntryStatus[Index1].OsSpecific = TRUE;
|
||||
}
|
||||
|
||||
for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {
|
||||
Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + Index2 * PartHeader->SizeOfPartitionEntry);
|
||||
if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Entry->EndingLBA >= StartingLBA) && (Entry->StartingLBA <= EndingLBA)) {
|
||||
//
|
||||
// This region overlaps with the Index1'th region
|
||||
//
|
||||
PEntryStatus[Index1].Overlap = TRUE;
|
||||
PEntryStatus[Index2].Overlap = TRUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, " End check partition entries\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the CRC32 value in the table header.
|
||||
|
||||
@param Hdr Table to update
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
PartitionSetCrc (
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
)
|
||||
{
|
||||
PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the CRC32 value in the table header.
|
||||
|
||||
@param Size The size of the table
|
||||
@param Hdr Table to update
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
PartitionSetCrcAltSize (
|
||||
IN UINTN Size,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
)
|
||||
{
|
||||
UINT32 Crc;
|
||||
|
||||
Hdr->CRC32 = 0;
|
||||
gBS->CalculateCrc32 ((UINT8 *)Hdr, Size, &Crc);
|
||||
Hdr->CRC32 = Crc;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks the CRC32 value in the table header.
|
||||
|
||||
@param MaxSize Max Size limit
|
||||
@param Hdr Table to check
|
||||
|
||||
@return TRUE CRC Valid
|
||||
@return FALSE CRC Invalid
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
PartitionCheckCrc (
|
||||
IN UINTN MaxSize,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
)
|
||||
{
|
||||
return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
Checks the CRC32 value in the table header.
|
||||
|
||||
@param MaxSize Max Size limit
|
||||
@param Size The size of the table
|
||||
@param Hdr Table to check
|
||||
|
||||
@return TRUE CRC Valid
|
||||
@return FALSE CRC Invalid
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
PartitionCheckCrcAltSize (
|
||||
IN UINTN MaxSize,
|
||||
IN UINTN Size,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
)
|
||||
{
|
||||
UINT32 Crc;
|
||||
UINT32 OrgCrc;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Crc = 0;
|
||||
|
||||
if (Size == 0) {
|
||||
//
|
||||
// If header size is 0 CRC will pass so return FALSE here
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((MaxSize != 0) && (Size > MaxSize)) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckCrc32: Size > MaxSize\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// clear old crc from header
|
||||
//
|
||||
OrgCrc = Hdr->CRC32;
|
||||
Hdr->CRC32 = 0;
|
||||
|
||||
Status = gBS->CalculateCrc32 ((UINT8 *)Hdr, Size, &Crc);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckCrc32: Crc calculation failed\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// set results
|
||||
//
|
||||
Hdr->CRC32 = Crc;
|
||||
|
||||
//
|
||||
// return status
|
||||
//
|
||||
DEBUG_CODE_BEGIN ();
|
||||
if (OrgCrc != Crc) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckCrc32: Crc check failed\n"));
|
||||
}
|
||||
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
return (BOOLEAN)(OrgCrc == Crc);
|
||||
}
|
||||
49
MdeModulePkg/Library/GptLib/GptLib.inf
Normal file
49
MdeModulePkg/Library/GptLib/GptLib.inf
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
## @file
|
||||
# Shared GUID Partition Table (GPT) parsing and validation library.
|
||||
#
|
||||
# Provides the GPT table parsing, validation and restore routines that are
|
||||
# shared between the Partition driver and other consumers that must parse the
|
||||
# same on-disk GPT layout.
|
||||
#
|
||||
# Caution: This library requires additional review when modified.
|
||||
# This library will have external input - disk partition.
|
||||
# This external input must be validated carefully to avoid security issue like
|
||||
# buffer overflow, integer overflow.
|
||||
#
|
||||
# Copyright (c) 2026, SUSE LLC. All rights reserved.<BR>
|
||||
# Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.
|
||||
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = GptLib
|
||||
FILE_GUID = E228F30C-C7D5-4A93-BBA7-B4E22327E289
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = GptLib
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 EBC AARCH64 RISCV64 LOONGARCH64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
Gpt.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
MemoryAllocationLib
|
||||
UefiBootServicesTableLib
|
||||
|
||||
[Guids]
|
||||
gEfiPartTypeUnusedGuid ## SOMETIMES_CONSUMES ## GUID
|
||||
|
|
@ -32,6 +32,9 @@
|
|||
Core/PrivateInclude
|
||||
|
||||
[LibraryClasses]
|
||||
## @libraryclass Provides GPT partition table parsing and validation routines.
|
||||
GptLib|Include/Library/GptLib.h
|
||||
|
||||
## @libraryclass Defines a set of methods to reset whole system.
|
||||
ResetSystemLib|Include/Library/ResetSystemLib.h
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
|
||||
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
|
||||
SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
|
||||
GptLib|MdeModulePkg/Library/GptLib/GptLib.inf
|
||||
#
|
||||
# UEFI & PI
|
||||
#
|
||||
|
|
@ -215,6 +216,7 @@
|
|||
MdeModulePkg/Logo/Logo.inf
|
||||
MdeModulePkg/Logo/LogoDxe.inf
|
||||
MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
|
||||
MdeModulePkg/Library/GptLib/GptLib.inf
|
||||
MdeModulePkg/Library/BootDiscoveryPolicyUiLib/BootDiscoveryPolicyUiLib.inf
|
||||
MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
|
||||
MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/** @file
|
||||
Decode a hard disk partitioned with the GPT scheme in the UEFI 2.0
|
||||
specification.
|
||||
Install GPT partition child handles for the Partition driver.
|
||||
|
||||
Caution: This file requires additional review when modified.
|
||||
This driver will have external input - disk partition.
|
||||
|
|
@ -8,10 +7,9 @@
|
|||
buffer overflow, integer overflow.
|
||||
|
||||
PartitionInstallGptChildHandles() routine will read disk partition content and
|
||||
do basic validation before PartitionInstallChildHandle().
|
||||
|
||||
PartitionValidGptTable(), PartitionCheckGptEntry() routine will accept disk
|
||||
partition content and validate the GPT table and GPT entry.
|
||||
do basic validation before PartitionInstallChildHandle(). The GPT table
|
||||
parsing and validation helpers it relies on live in the shared GPT parser
|
||||
(GptLib/Gpt.c).
|
||||
|
||||
Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.
|
||||
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
|
|
@ -21,146 +19,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|||
|
||||
#include "Partition.h"
|
||||
|
||||
/**
|
||||
Install child handles if the Handle supports GPT partition structure.
|
||||
|
||||
Caution: This function may receive untrusted input.
|
||||
The GPT partition table header is external input, so this routine
|
||||
will do basic validation for GPT partition table header before return.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io protocol.
|
||||
@param[in] Lba The starting Lba of the Partition Table
|
||||
@param[out] PartHeader Stores the partition table that is read
|
||||
|
||||
@retval TRUE The partition table is valid
|
||||
@retval FALSE The partition table is not valid
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionValidGptTable (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_LBA Lba,
|
||||
OUT EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Check if the CRC field in the Partition table header is valid
|
||||
for Partition entry array.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure
|
||||
|
||||
@retval TRUE the CRC is valid
|
||||
@retval FALSE the CRC is invalid
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionCheckGptEntryArrayCRC (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Restore Partition Table to its alternate place
|
||||
(Primary -> Backup or Backup -> Primary).
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure.
|
||||
|
||||
@retval TRUE Restoring succeeds
|
||||
@retval FALSE Restoring failed
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionRestoreGptTable (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
);
|
||||
|
||||
/**
|
||||
This routine will check GPT partition entry and return entry status.
|
||||
|
||||
Caution: This function may receive untrusted input.
|
||||
The GPT partition entry is external input, so this routine
|
||||
will do basic validation for GPT partition entry and report status.
|
||||
|
||||
@param[in] PartHeader Partition table header structure
|
||||
@param[in] PartEntry The partition entry array
|
||||
@param[out] PEntryStatus the partition entry status array
|
||||
recording the status of each partition
|
||||
|
||||
**/
|
||||
VOID
|
||||
PartitionCheckGptEntry (
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader,
|
||||
IN EFI_PARTITION_ENTRY *PartEntry,
|
||||
OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
|
||||
);
|
||||
|
||||
/**
|
||||
Checks the CRC32 value in the table header.
|
||||
|
||||
@param MaxSize Max Size limit
|
||||
@param Size The size of the table
|
||||
@param Hdr Table to check
|
||||
|
||||
@return TRUE CRC Valid
|
||||
@return FALSE CRC Invalid
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionCheckCrcAltSize (
|
||||
IN UINTN MaxSize,
|
||||
IN UINTN Size,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
);
|
||||
|
||||
/**
|
||||
Checks the CRC32 value in the table header.
|
||||
|
||||
@param MaxSize Max Size limit
|
||||
@param Hdr Table to check
|
||||
|
||||
@return TRUE CRC Valid
|
||||
@return FALSE CRC Invalid
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionCheckCrc (
|
||||
IN UINTN MaxSize,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
);
|
||||
|
||||
/**
|
||||
Updates the CRC32 value in the table header.
|
||||
|
||||
@param Size The size of the table
|
||||
@param Hdr Table to update
|
||||
|
||||
**/
|
||||
VOID
|
||||
PartitionSetCrcAltSize (
|
||||
IN UINTN Size,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
);
|
||||
|
||||
/**
|
||||
Updates the CRC32 value in the table header.
|
||||
|
||||
@param Hdr Table to update
|
||||
|
||||
**/
|
||||
VOID
|
||||
PartitionSetCrc (
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
);
|
||||
|
||||
/**
|
||||
Install child handles if the Handle supports GPT partition structure.
|
||||
|
||||
|
|
@ -446,438 +304,3 @@ Done:
|
|||
|
||||
return GptValidStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
This routine will read GPT partition table header and return it.
|
||||
|
||||
Caution: This function may receive untrusted input.
|
||||
The GPT partition table header is external input, so this routine
|
||||
will do basic validation for GPT partition table header before return.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io protocol.
|
||||
@param[in] Lba The starting Lba of the Partition Table
|
||||
@param[out] PartHeader Stores the partition table that is read
|
||||
|
||||
@retval TRUE The partition table is valid
|
||||
@retval FALSE The partition table is not valid
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionValidGptTable (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_LBA Lba,
|
||||
OUT EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 BlockSize;
|
||||
EFI_PARTITION_TABLE_HEADER *PartHdr;
|
||||
UINT32 MediaId;
|
||||
|
||||
BlockSize = BlockIo->Media->BlockSize;
|
||||
MediaId = BlockIo->Media->MediaId;
|
||||
PartHdr = AllocateZeroPool (BlockSize);
|
||||
|
||||
if (PartHdr == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "Allocate pool error\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Read the EFI Partition Table Header
|
||||
//
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
MediaId,
|
||||
MultU64x32 (Lba, BlockSize),
|
||||
BlockSize,
|
||||
PartHdr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (PartHdr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||
|
||||
!PartitionCheckCrc (BlockSize, &PartHdr->Header) ||
|
||||
(PartHdr->MyLBA != Lba) ||
|
||||
(PartHdr->SizeOfPartitionEntry < sizeof (EFI_PARTITION_ENTRY))
|
||||
)
|
||||
{
|
||||
DEBUG ((DEBUG_INFO, "Invalid efi partition table header\n"));
|
||||
FreePool (PartHdr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Ensure the NumberOfPartitionEntries * SizeOfPartitionEntry doesn't overflow.
|
||||
//
|
||||
if (PartHdr->NumberOfPartitionEntries > DivU64x32 (MAX_UINTN, PartHdr->SizeOfPartitionEntry)) {
|
||||
FreePool (PartHdr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER));
|
||||
if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) {
|
||||
FreePool (PartHdr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, " Valid efi partition table header\n"));
|
||||
FreePool (PartHdr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the CRC field in the Partition table header is valid
|
||||
for Partition entry array.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure
|
||||
|
||||
@retval TRUE the CRC is valid
|
||||
@retval FALSE the CRC is invalid
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionCheckGptEntryArrayCRC (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 *Ptr;
|
||||
UINT32 Crc;
|
||||
UINTN Size;
|
||||
|
||||
//
|
||||
// Read the EFI Partition Entries
|
||||
//
|
||||
Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
|
||||
if (Ptr == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, " Allocate pool error\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MultU64x32 (PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
|
||||
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Ptr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry;
|
||||
|
||||
Status = gBS->CalculateCrc32 (Ptr, Size, &Crc);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n"));
|
||||
FreePool (Ptr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FreePool (Ptr);
|
||||
|
||||
return (BOOLEAN)(PartHeader->PartitionEntryArrayCRC32 == Crc);
|
||||
}
|
||||
|
||||
/**
|
||||
Restore Partition Table to its alternate place
|
||||
(Primary -> Backup or Backup -> Primary).
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure.
|
||||
|
||||
@retval TRUE Restoring succeeds
|
||||
@retval FALSE Restoring failed
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionRestoreGptTable (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN BlockSize;
|
||||
EFI_PARTITION_TABLE_HEADER *PartHdr;
|
||||
EFI_LBA PEntryLBA;
|
||||
UINT8 *Ptr;
|
||||
UINT32 MediaId;
|
||||
|
||||
PartHdr = NULL;
|
||||
Ptr = NULL;
|
||||
|
||||
BlockSize = BlockIo->Media->BlockSize;
|
||||
MediaId = BlockIo->Media->MediaId;
|
||||
|
||||
PartHdr = AllocateZeroPool (BlockSize);
|
||||
|
||||
if (PartHdr == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "Allocate pool error\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \
|
||||
(PartHeader->LastUsableLBA + 1) : \
|
||||
(PRIMARY_PART_HEADER_LBA + 1);
|
||||
|
||||
CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
|
||||
|
||||
PartHdr->MyLBA = PartHeader->AlternateLBA;
|
||||
PartHdr->AlternateLBA = PartHeader->MyLBA;
|
||||
PartHdr->PartitionEntryLBA = PEntryLBA;
|
||||
PartitionSetCrc ((EFI_TABLE_HEADER *)PartHdr);
|
||||
|
||||
Status = DiskIo->WriteDisk (
|
||||
DiskIo,
|
||||
MediaId,
|
||||
MultU64x32 (PartHdr->MyLBA, (UINT32)BlockSize),
|
||||
BlockSize,
|
||||
PartHdr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
|
||||
if (Ptr == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, " Allocate pool error\n"));
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
MediaId,
|
||||
MultU64x32 (PartHeader->PartitionEntryLBA, (UINT32)BlockSize),
|
||||
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Status = DiskIo->WriteDisk (
|
||||
DiskIo,
|
||||
MediaId,
|
||||
MultU64x32 (PEntryLBA, (UINT32)BlockSize),
|
||||
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
||||
Ptr
|
||||
);
|
||||
|
||||
Done:
|
||||
FreePool (PartHdr);
|
||||
|
||||
if (Ptr != NULL) {
|
||||
FreePool (Ptr);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
This routine will check GPT partition entry and return entry status.
|
||||
|
||||
Caution: This function may receive untrusted input.
|
||||
The GPT partition entry is external input, so this routine
|
||||
will do basic validation for GPT partition entry and report status.
|
||||
|
||||
@param[in] PartHeader Partition table header structure
|
||||
@param[in] PartEntry The partition entry array
|
||||
@param[out] PEntryStatus the partition entry status array
|
||||
recording the status of each partition
|
||||
|
||||
**/
|
||||
VOID
|
||||
PartitionCheckGptEntry (
|
||||
IN EFI_PARTITION_TABLE_HEADER *PartHeader,
|
||||
IN EFI_PARTITION_ENTRY *PartEntry,
|
||||
OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
|
||||
)
|
||||
{
|
||||
EFI_LBA StartingLBA;
|
||||
EFI_LBA EndingLBA;
|
||||
EFI_PARTITION_ENTRY *Entry;
|
||||
UINTN Index1;
|
||||
UINTN Index2;
|
||||
|
||||
DEBUG ((DEBUG_INFO, " start check partition entries\n"));
|
||||
for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) {
|
||||
Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + Index1 * PartHeader->SizeOfPartitionEntry);
|
||||
if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StartingLBA = Entry->StartingLBA;
|
||||
EndingLBA = Entry->EndingLBA;
|
||||
if ((StartingLBA > EndingLBA) ||
|
||||
(StartingLBA < PartHeader->FirstUsableLBA) ||
|
||||
(StartingLBA > PartHeader->LastUsableLBA) ||
|
||||
(EndingLBA < PartHeader->FirstUsableLBA) ||
|
||||
(EndingLBA > PartHeader->LastUsableLBA)
|
||||
)
|
||||
{
|
||||
PEntryStatus[Index1].OutOfRange = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Entry->Attributes & BIT1) != 0) {
|
||||
//
|
||||
// If Bit 1 is set, this indicate that this is an OS specific GUID partition.
|
||||
//
|
||||
PEntryStatus[Index1].OsSpecific = TRUE;
|
||||
}
|
||||
|
||||
for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {
|
||||
Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + Index2 * PartHeader->SizeOfPartitionEntry);
|
||||
if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Entry->EndingLBA >= StartingLBA) && (Entry->StartingLBA <= EndingLBA)) {
|
||||
//
|
||||
// This region overlaps with the Index1'th region
|
||||
//
|
||||
PEntryStatus[Index1].Overlap = TRUE;
|
||||
PEntryStatus[Index2].Overlap = TRUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, " End check partition entries\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the CRC32 value in the table header.
|
||||
|
||||
@param Hdr Table to update
|
||||
|
||||
**/
|
||||
VOID
|
||||
PartitionSetCrc (
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
)
|
||||
{
|
||||
PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the CRC32 value in the table header.
|
||||
|
||||
@param Size The size of the table
|
||||
@param Hdr Table to update
|
||||
|
||||
**/
|
||||
VOID
|
||||
PartitionSetCrcAltSize (
|
||||
IN UINTN Size,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
)
|
||||
{
|
||||
UINT32 Crc;
|
||||
|
||||
Hdr->CRC32 = 0;
|
||||
gBS->CalculateCrc32 ((UINT8 *)Hdr, Size, &Crc);
|
||||
Hdr->CRC32 = Crc;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks the CRC32 value in the table header.
|
||||
|
||||
@param MaxSize Max Size limit
|
||||
@param Hdr Table to check
|
||||
|
||||
@return TRUE CRC Valid
|
||||
@return FALSE CRC Invalid
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionCheckCrc (
|
||||
IN UINTN MaxSize,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
)
|
||||
{
|
||||
return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
Checks the CRC32 value in the table header.
|
||||
|
||||
@param MaxSize Max Size limit
|
||||
@param Size The size of the table
|
||||
@param Hdr Table to check
|
||||
|
||||
@return TRUE CRC Valid
|
||||
@return FALSE CRC Invalid
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PartitionCheckCrcAltSize (
|
||||
IN UINTN MaxSize,
|
||||
IN UINTN Size,
|
||||
IN OUT EFI_TABLE_HEADER *Hdr
|
||||
)
|
||||
{
|
||||
UINT32 Crc;
|
||||
UINT32 OrgCrc;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Crc = 0;
|
||||
|
||||
if (Size == 0) {
|
||||
//
|
||||
// If header size is 0 CRC will pass so return FALSE here
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((MaxSize != 0) && (Size > MaxSize)) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckCrc32: Size > MaxSize\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// clear old crc from header
|
||||
//
|
||||
OrgCrc = Hdr->CRC32;
|
||||
Hdr->CRC32 = 0;
|
||||
|
||||
Status = gBS->CalculateCrc32 ((UINT8 *)Hdr, Size, &Crc);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckCrc32: Crc calculation failed\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// set results
|
||||
//
|
||||
Hdr->CRC32 = Crc;
|
||||
|
||||
//
|
||||
// return status
|
||||
//
|
||||
DEBUG_CODE_BEGIN ();
|
||||
if (OrgCrc != Crc) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckCrc32: Crc check failed\n"));
|
||||
}
|
||||
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
return (BOOLEAN)(OrgCrc == Crc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
|
||||
#include <Library/GptLib.h>
|
||||
|
||||
#include <IndustryStandard/Mbr.h>
|
||||
#include <IndustryStandard/ElTorito.h>
|
||||
#include <IndustryStandard/Udf.h>
|
||||
|
|
@ -93,15 +95,6 @@ extern EFI_COMPONENT_NAME2_PROTOCOL gPartitionComponentName2;
|
|||
(((UINT8 *) a)[2] << 16) | \
|
||||
(((UINT8 *) a)[3] << 24) )
|
||||
|
||||
//
|
||||
// GPT Partition Entry Status
|
||||
//
|
||||
typedef struct {
|
||||
BOOLEAN OutOfRange;
|
||||
BOOLEAN Overlap;
|
||||
BOOLEAN OsSpecific;
|
||||
} EFI_PARTITION_ENTRY_STATUS;
|
||||
|
||||
//
|
||||
// Function Prototypes
|
||||
//
|
||||
|
|
|
|||
|
|
@ -47,10 +47,12 @@
|
|||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
DevicePathLib
|
||||
GptLib
|
||||
UefiBootServicesTableLib
|
||||
MemoryAllocationLib
|
||||
BaseMemoryLib
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue