From: "Chen, Chen A" <chen.a.chen@intel.com>
To: "Zhang, Chao B" <chao.b.zhang@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Ni, Ray" <ray.ni@intel.com>, "Wu, Hao A" <hao.a.wu@intel.com>
Subject: Re: [PATCH 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature.
Date: Wed, 23 Jan 2019 08:40:31 +0000 [thread overview]
Message-ID: <8CCE94730AD68946B3D28B43192D9D2D06E5C183@shsmsx102.ccr.corp.intel.com> (raw)
In-Reply-To: <FF72C7E4248F3C4E9BDF19D4918E90F24DE54376@shsmsx102.ccr.corp.intel.com>
Hi Ray and Hao
Do you have any comments for this patch?
-----Original Message-----
From: Zhang, Chao B
Sent: Wednesday, January 23, 2019 2:22 PM
To: Chen, Chen A <chen.a.chen@intel.com>; edk2-devel@lists.01.org
Cc: Ni, Ray <ray.ni@intel.com>
Subject: RE: [PATCH 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature.
Reviewed-by : Chao Zhang <chao.b.zhang@intel.com>
-----Original Message-----
From: Chen, Chen A
Sent: Thursday, January 17, 2019 10:03 AM
To: edk2-devel@lists.01.org
Cc: Chen, Chen A <chen.a.chen@intel.com>; Ni, Ray <ray.ni@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: [PATCH 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature.
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1470
This feature is used for finding GPT partition, follow the following step to check.
1) Check Protective MBR.
2) Check GPT primary/backup header.
3) Check GPT primary/backup entry array.
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Zhang Chao B <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Chen A Chen <chen.a.chen@intel.com>
---
FatPkg/FatPei/FatLitePeim.h | 1 +
FatPkg/FatPei/FatPei.inf | 3 +
FatPkg/FatPei/Gpt.c | 546 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 550 insertions(+)
create mode 100644 FatPkg/FatPei/Gpt.c
diff --git a/FatPkg/FatPei/FatLitePeim.h b/FatPkg/FatPei/FatLitePeim.h index fbf887da5f..afb429c56e 100644
--- a/FatPkg/FatPei/FatLitePeim.h
+++ b/FatPkg/FatPei/FatLitePeim.h
@@ -27,6 +27,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/BaseLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/PeiServicesTablePointerLib.h>
#include <Library/PeiServicesLib.h>
diff --git a/FatPkg/FatPei/FatPei.inf b/FatPkg/FatPei/FatPei.inf index 829e87fe92..dd0869f7cd 100644
--- a/FatPkg/FatPei/FatPei.inf
+++ b/FatPkg/FatPei/FatPei.inf
@@ -31,6 +31,7 @@
[Sources]
Mbr.c
+ Gpt.c
Eltorito.c
Part.c
FatLiteApi.c
@@ -49,6 +50,7 @@
[LibraryClasses]
PcdLib
BaseMemoryLib
+ MemoryAllocationLib
PeimEntryPoint
BaseLib
DebugLib
@@ -61,6 +63,7 @@
gRecoveryOnFatIdeDiskGuid ## SOMETIMES_CONSUMES ## UNDEFINED
gRecoveryOnFatFloppyDiskGuid ## SOMETIMES_CONSUMES ## UNDEFINED
gRecoveryOnFatNvmeDiskGuid ## SOMETIMES_CONSUMES ## UNDEFINED
+ gEfiPartTypeUnusedGuid ## SOMETIMES_CONSUMES ## UNDEFINED
[Ppis]
diff --git a/FatPkg/FatPei/Gpt.c b/FatPkg/FatPei/Gpt.c new file mode 100644 index 0000000000..d1f4c1c8b5
--- /dev/null
+++ b/FatPkg/FatPei/Gpt.c
@@ -0,0 +1,546 @@
+/** @file
+ Routines supporting partition discovery and
+ logical device reading
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials are licensed and made
+available under the terms and conditions of the BSD License which
+accompanies this distribution. The full text of the license may be
+found at http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <IndustryStandard/Mbr.h>
+#include <Uefi/UefiGpt.h>
+#include <Library/BaseLib.h>
+#include "FatLitePeim.h"
+
+//
+// Assumption: 'a' and 'blocksize' are all UINT32 or UINT64.
+// If 'a' and 'blocksize' are not the same type, should use DivU64xU32 to calculate.
+//
+#define EFI_SIZE_TO_BLOCKS(a, blocksize) (((a) / (blocksize)) + (((a)
+% (blocksize)) ? 1 : 0))
+
+//
+// GPT Partition Entry Status
+//
+typedef struct {
+ BOOLEAN OutOfRange;
+ BOOLEAN Overlap;
+ BOOLEAN OsSpecific;
+} EFI_PARTITION_ENTRY_STATUS;
+
+/**
+ Check if the CRC field in the Partition table header is valid
+
+ @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
+PartitionCheckGptHeaderCRC (
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader
+ )
+{
+ UINT32 GptHdrCrc;
+ UINT32 Crc;
+
+ GptHdrCrc = PartHeader->Header.CRC32;
+
+ //
+ // Set CRC field to zero when doing calcuation //
+ PartHeader->Header.CRC32 = 0;
+
+ Crc = CalculateCrc32 (PartHeader, PartHeader->Header.HeaderSize);
+
+ //
+ // Restore Header CRC
+ //
+ PartHeader->Header.CRC32 = GptHdrCrc;
+
+ return (GptHdrCrc == Crc);
+}
+
+
+/**
+ 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_PARTITION_TABLE_HEADER *PartHeader,
+ IN EFI_PARTITION_ENTRY *PartEntry
+ )
+{
+ UINT32 Crc;
+ UINTN Size;
+
+ Size = (UINTN)MultU64x32(PartHeader->NumberOfPartitionEntries,
+ PartHeader->SizeOfPartitionEntry);
+ Crc = CalculateCrc32 (PartEntry, Size);
+
+ return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 == Crc); }
+
+/**
+ The function is used for valid GPT table. Both for Primary and Backup GPT header.
+
+ @param[in] PrivateData The global memory map
+ @param[in] ParentBlockDevNo The parent block device
+ @param[in] IsPrimaryHeader Indicate to which header will be checked.
+ @param[in] PartHdr Stores the partition table that is read
+
+ @retval TRUE The partition table is valid
+ @retval FALSE The partition table is not valid
+
+**/
+BOOLEAN
+PartitionCheckGptHeader (
+ IN PEI_FAT_PRIVATE_DATA *PrivateData,
+ IN UINTN ParentBlockDevNo,
+ IN BOOLEAN IsPrimaryHeader,
+ IN EFI_PARTITION_TABLE_HEADER *PartHdr
+ )
+{
+ PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
+ EFI_PEI_LBA Lba;
+ EFI_PEI_LBA AlternateLba;
+ EFI_PEI_LBA EntryArrayLastLba;
+
+ UINT64 PartitionEntryArraySize;
+ UINT64 PartitionEntryBlockNumb;
+ UINT32 EntryArraySizeRemainder;
+
+ ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
+
+ if (IsPrimaryHeader) {
+ Lba = PRIMARY_PART_HEADER_LBA;
+ AlternateLba = ParentBlockDev->LastBlock; } else {
+ Lba = ParentBlockDev->LastBlock;
+ AlternateLba = PRIMARY_PART_HEADER_LBA; }
+
+ if ( (PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||
+ (PartHdr->Header.Revision != 0x00010000) ||
+ (PartHdr->Header.HeaderSize < 92) ||
+ (PartHdr->Header.HeaderSize > ParentBlockDev->BlockSize) ||
+ (!PartitionCheckGptHeaderCRC (PartHdr)) ||
+ (PartHdr->Header.Reserved != 0)
+ ) {
+ DEBUG ((DEBUG_ERROR, "Invalid efi partition table header\n"));
+ return FALSE;
+ }
+
+ //
+ // | Block0 | Block1 |Block2 ~ FirstUsableLBA - 1|FirstUsableLBA, ... ,LastUsableLBA|LastUsableLBA+1 ~ LastBlock-1| LastBlock |
+ // |Protective MBR|Primary Header|Entry Array(At Least 16384)| Partition | Entry Array(At Least 16384) |BackUp Header|
+ //
+ // 1. Protective MBR is fixed at Block 0.
+ // 2. Primary Header is fixed at Block 1.
+ // 3. Backup Header is fixed at LastBlock.
+ // 4. Must be remain 128*128 bytes for primary entry array.
+ // 5. Must be remain 128*128 bytes for backup entry array.
+ // 6. SizeOfPartitionEntry must be equals to 128 * 2^n.
+ //
+ if ( (PartHdr->MyLBA != Lba) ||
+ (PartHdr->AlternateLBA != AlternateLba) ||
+ (PartHdr->FirstUsableLBA < 2 + EFI_SIZE_TO_BLOCKS (GPT_PART_ENTRY_MIN_SIZE, ParentBlockDev->BlockSize)) ||
+ (PartHdr->LastUsableLBA > ParentBlockDev->LastBlock - 1 - EFI_SIZE_TO_BLOCKS (GPT_PART_ENTRY_MIN_SIZE, ParentBlockDev->BlockSize)) ||
+ (PartHdr->FirstUsableLBA > PartHdr->LastUsableLBA) ||
+ (PartHdr->PartitionEntryLBA < 2) ||
+ (PartHdr->PartitionEntryLBA > ParentBlockDev->LastBlock - 1) ||
+ (PartHdr->PartitionEntryLBA >= PartHdr->FirstUsableLBA && PartHdr->PartitionEntryLBA <= PartHdr->LastUsableLBA) ||
+ (PartHdr->SizeOfPartitionEntry%128 != 0) ||
+ (PartHdr->SizeOfPartitionEntry != sizeof (EFI_PARTITION_ENTRY))
+ ) {
+ DEBUG ((DEBUG_ERROR, "Invalid efi partition table header\n"));
+ return FALSE;
+ }
+
+ PartitionEntryArraySize = MultU64x32
+ (PartHdr->NumberOfPartitionEntries, PartHdr->SizeOfPartitionEntry);
+ EntryArraySizeRemainder = 0; PartitionEntryBlockNumb =
+ DivU64x32Remainder (PartitionEntryArraySize, ParentBlockDev->BlockSize, &EntryArraySizeRemainder); if (EntryArraySizeRemainder != 0) {
+ PartitionEntryBlockNumb++;
+ }
+
+ if (IsPrimaryHeader) {
+ EntryArrayLastLba = PartHdr->FirstUsableLBA; } else {
+ EntryArrayLastLba = ParentBlockDev->LastBlock; }
+
+ //
+ // Make sure partition entry array not overlaps with partition area or the LastBlock.
+ //
+ if (PartHdr->PartitionEntryLBA + PartitionEntryBlockNumb > EntryArrayLastLba) {
+ DEBUG ((DEBUG_ERROR, "GPT Partition Entry Array Error!\n"));
+ DEBUG ((DEBUG_ERROR, "PartitionEntryArraySize = %lu.\n", PartitionEntryArraySize));
+ DEBUG ((DEBUG_ERROR, "PartitionEntryLBA = %lu.\n", PartHdr->PartitionEntryLBA));
+ DEBUG ((DEBUG_ERROR, "PartitionEntryBlockNumb = %lu.\n", PartitionEntryBlockNumb));
+ DEBUG ((DEBUG_ERROR, "EntryArrayLastLba = %lu.\n", EntryArrayLastLba));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This function is used to verify each partition in block device.
+
+ @param[in] PrivateData The global memory map
+ @param[in] ParentBlockDevNo The parent block device
+ @param[in] PartHdr Stores the partition table that is read
+
+ @retval TRUE The partition is valid
+ @retval FALSE The partition is not valid
+
+**/
+
+BOOLEAN
+PartitionCheckGptEntryArray (
+ IN PEI_FAT_PRIVATE_DATA *PrivateData,
+ IN UINTN ParentBlockDevNo,
+ IN EFI_PARTITION_TABLE_HEADER *PartHdr
+ )
+{
+ EFI_STATUS Status;
+ PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
+ PEI_FAT_BLOCK_DEVICE *BlockDevPtr;
+
+ UINT64 PartitionEntryArraySize;
+ UINT64 PartitionEntryBlockNumb;
+ UINT32 EntryArraySizeRemainder;
+
+ EFI_PARTITION_ENTRY *PartitionEntryBuffer;
+ EFI_PARTITION_ENTRY_STATUS *PartitionEntryStatus;
+
+ BOOLEAN Found;
+ EFI_LBA StartingLBA;
+ EFI_LBA EndingLBA;
+ UINTN Index;
+ UINTN Index1;
+ UINTN Index2;
+ EFI_PARTITION_ENTRY *Entry;
+
+ ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
+ Found = FALSE;
+
+ PartitionEntryArraySize = MultU64x32
+ (PartHdr->NumberOfPartitionEntries, PartHdr->SizeOfPartitionEntry);
+ EntryArraySizeRemainder = 0; PartitionEntryBlockNumb =
+ DivU64x32Remainder (PartitionEntryArraySize, ParentBlockDev->BlockSize, &EntryArraySizeRemainder); if (EntryArraySizeRemainder != 0) {
+ PartitionEntryBlockNumb++;
+ }
+ PartitionEntryArraySize = MultU64x32 (PartitionEntryBlockNumb,
+ ParentBlockDev->BlockSize);
+
+ PartitionEntryBuffer = (EFI_PARTITION_ENTRY *) AllocatePages
+ (EFI_SIZE_TO_PAGES ((UINTN)PartitionEntryArraySize));
+ if (PartitionEntryBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "Allocate memory error!\n"));
+ goto EXIT;
+ }
+
+ PartitionEntryStatus = (EFI_PARTITION_ENTRY_STATUS *) AllocatePages
+ (EFI_SIZE_TO_PAGES (PartHdr->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS))); if (PartitionEntryStatus == NULL) {
+ DEBUG ((DEBUG_ERROR, "Allocate memory error!\n"));
+ goto EXIT;
+ }
+ ZeroMem (PartitionEntryStatus, PartHdr->NumberOfPartitionEntries *
+ sizeof (EFI_PARTITION_ENTRY_STATUS));
+
+ Status = FatReadBlock (
+ PrivateData,
+ ParentBlockDevNo,
+ PartHdr->PartitionEntryLBA,
+ (UINTN)PartitionEntryArraySize,
+ PartitionEntryBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Read partition entry array error!\n"));
+ goto EXIT;
+ }
+
+ if (!PartitionCheckGptEntryArrayCRC (PartHdr, PartitionEntryBuffer)) {
+ DEBUG ((EFI_D_ERROR, "Partition entries CRC check fail\n"));
+ goto EXIT;
+ }
+
+ for (Index1 = 0; Index1 < PartHdr->NumberOfPartitionEntries; Index1++) {
+ Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartitionEntryBuffer + Index1 * PartHdr->SizeOfPartitionEntry);
+ if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
+ continue;
+ }
+
+ StartingLBA = Entry->StartingLBA;
+ EndingLBA = Entry->EndingLBA;
+ if (StartingLBA > EndingLBA ||
+ StartingLBA < PartHdr->FirstUsableLBA ||
+ StartingLBA > PartHdr->LastUsableLBA ||
+ EndingLBA < PartHdr->FirstUsableLBA ||
+ EndingLBA > PartHdr->LastUsableLBA
+ ) {
+ PartitionEntryStatus[Index1].OutOfRange = TRUE;
+ continue;
+ }
+
+ if ((Entry->Attributes & BIT1) != 0) {
+ //
+ // If Bit 1 is set, this indicate that this is an OS specific GUID partition.
+ //
+ PartitionEntryStatus[Index1].OsSpecific = TRUE;
+ }
+
+ for (Index2 = Index1 + 1; Index2 < PartHdr->NumberOfPartitionEntries; Index2++) {
+ Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartitionEntryBuffer + Index2 * PartHdr->SizeOfPartitionEntry);
+ if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
+ continue;
+ }
+
+ if (Entry->EndingLBA >= StartingLBA && Entry->StartingLBA <= EndingLBA) {
+ //
+ // This region overlaps with the Index1'th region
+ //
+ PartitionEntryStatus[Index1].Overlap = TRUE;
+ PartitionEntryStatus[Index2].Overlap = TRUE;
+ continue;
+ }
+ }
+ }
+
+ for (Index = 0; Index < PartHdr->NumberOfPartitionEntries; Index++) {
+ if (CompareGuid (&PartitionEntryBuffer[Index].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)||
+ PartitionEntryStatus[Index].OutOfRange ||
+ PartitionEntryStatus[Index].Overlap ||
+ PartitionEntryStatus[Index].OsSpecific) {
+ //
+ // Don't use null EFI Partition Entries, Invalid Partition Entries or OS specific
+ // partition Entries
+ //
+ continue;
+ }
+
+ if (PrivateData->BlockDeviceCount >= PEI_FAT_MAX_BLOCK_DEVICE) {
+ break;
+ }
+
+ Found = TRUE;
+ BlockDevPtr = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
+
+ BlockDevPtr->BlockSize = ParentBlockDev->BlockSize;
+ BlockDevPtr->LastBlock = PartitionEntryBuffer[Index].EndingLBA;
+ BlockDevPtr->IoAlign = ParentBlockDev->IoAlign;
+ BlockDevPtr->Logical = TRUE;
+ BlockDevPtr->PartitionChecked = FALSE;
+ BlockDevPtr->StartingPos = MultU64x32 (
+ PartitionEntryBuffer[Index].StartingLBA,
+ ParentBlockDev->BlockSize
+ );
+ BlockDevPtr->ParentDevNo = ParentBlockDevNo;
+
+ PrivateData->BlockDeviceCount++;
+
+ DEBUG ((DEBUG_INFO, "Find GPT Partition [0x%lx", PartitionEntryBuffer[Index].StartingLBA, BlockDevPtr->LastBlock));
+ DEBUG ((DEBUG_INFO, ", 0x%lx]\n", BlockDevPtr->LastBlock));
+ DEBUG ((DEBUG_INFO, " BlockSize %x\n", BlockDevPtr->BlockSize));
+ }
+
+EXIT:
+ if (PartitionEntryBuffer != NULL) {
+ FreePages (PartitionEntryBuffer, EFI_SIZE_TO_PAGES
+((UINTN)PartitionEntryArraySize));
+ }
+
+ if (PartitionEntryStatus != NULL) {
+ FreePages (PartitionEntryStatus, EFI_SIZE_TO_PAGES
+ (PartHdr->NumberOfPartitionEntries * sizeof
+ (EFI_PARTITION_ENTRY_STATUS))); }
+
+ return Found;
+}
+
+/**
+ The function is used to check GPT structure, include GPT header and GPT entry array.
+
+ 1. Check GPT header.
+ 2. Check partition entry array.
+ 3. Check each partitions.
+
+ @param PrivateData The global memory map
+ @param ParentBlockDevNo The parent block device
+ @param IsPrimary Indicate primary or backup to be check
+
+ @retval TRUE Primary or backup GPT structure is valid.
+ @retval FALSE Both primary and backup are invalid.
+
+**/
+BOOLEAN
+PartitionCheckGptStructure (
+ IN PEI_FAT_PRIVATE_DATA *PrivateData,
+ IN UINTN ParentBlockDevNo,
+ IN BOOLEAN IsPrimary
+ )
+{
+ EFI_STATUS Status;
+ PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
+ EFI_PARTITION_TABLE_HEADER *PartHdr;
+ EFI_PEI_LBA GptHeaderLBA;
+
+ ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
+ PartHdr = (EFI_PARTITION_TABLE_HEADER *) PrivateData->BlockData;
+
+ if (IsPrimary) {
+ GptHeaderLBA = PRIMARY_PART_HEADER_LBA; } else {
+ GptHeaderLBA = ParentBlockDev->LastBlock; }
+
+ Status = FatReadBlock (
+ PrivateData,
+ ParentBlockDevNo,
+ GptHeaderLBA,
+ ParentBlockDev->BlockSize,
+ PartHdr
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ if (!PartitionCheckGptHeader (PrivateData, ParentBlockDevNo, IsPrimary, PartHdr)) {
+ return FALSE;
+ }
+
+ if (!PartitionCheckGptEntryArray (PrivateData, ParentBlockDevNo, PartHdr)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This function is used to check protective MBR structure before checking GPT.
+
+ @param PrivateData The global memory map
+ @param ParentBlockDevNo The parent block device
+
+ @retval TRUE Valid protective MBR
+ @retval FALSE Invalid MBR
+**/
+BOOLEAN
+PartitionCheckProtectiveMbr (
+ IN PEI_FAT_PRIVATE_DATA *PrivateData,
+ IN UINTN ParentBlockDevNo
+ )
+{
+ EFI_STATUS Status;
+ MASTER_BOOT_RECORD *ProtectiveMbr;
+ MBR_PARTITION_ENTRY *MbrPartition;
+ PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
+ UINTN Index;
+
+ ProtectiveMbr = (MASTER_BOOT_RECORD *) PrivateData->BlockData;
+ ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
+
+ //
+ // Read Protective MBR
+ //
+ Status = FatReadBlock (
+ PrivateData,
+ ParentBlockDevNo,
+ 0,
+ ParentBlockDev->BlockSize,
+ ProtectiveMbr
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "GPT Error When Read Protective Mbr From Partition!\n"));
+ return FALSE;
+ }
+
+ if (ProtectiveMbr->Signature != MBR_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "Protective Mbr Signature is invalid!\n"));
+ return FALSE;
+ }
+
+ //
+ // The partition define in UEFI Spec Table 17.
+ // Boot Code, Unique MBR Disk Signature, Unknown.
+ // These parst will not used by UEFI, so we skip to check them.
+ //
+ for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
+ MbrPartition = (MBR_PARTITION_ENTRY *)&ProtectiveMbr->Partition[Index];
+ if (MbrPartition->BootIndicator == 0x00 &&
+ MbrPartition->StartingCHS[0] == 0x00 &&
+ MbrPartition->StartingCHS[1] == 0x02 &&
+ MbrPartition->StartingCHS[2] == 0x00 &&
+ MbrPartition->OSType == PMBR_GPT_PARTITION &&
+ MbrPartition->StartingLBA == 0x1
+ ) {
+ return TRUE;
+ }
+ }
+
+ DEBUG ((DEBUG_ERROR, "Protective Mbr, All Partition Entry Are
+Empty!\n"));
+ return FALSE;
+}
+
+/**
+ This function is used for findg GPT partition on block device.
+ As follow UEFI spec We should check protecive MBR first and then
+ try to check both primary/backup GPT structures.
+
+ @param PrivateData The global memory map
+ @param ParentBlockDevNo The parent block device
+
+ @retval TRUE New partitions are detected and logical block devices
+ are added to block device array
+ @retval FALSE No New partitions are added;
+
+**/
+BOOLEAN
+FatFindGptPartitions (
+ IN PEI_FAT_PRIVATE_DATA *PrivateData,
+ IN UINTN ParentBlockDevNo
+ )
+{
+ BOOLEAN Found;
+ PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
+
+ if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
+ return FALSE;
+ }
+
+ ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
+ if (ParentBlockDev->BlockSize > PEI_FAT_MAX_BLOCK_SIZE) {
+ DEBUG ((DEBUG_ERROR, "Device BlockSize %x exceed FAT_MAX_BLOCK_SIZE\n", ParentBlockDev->BlockSize));
+ return FALSE;
+ }
+
+ if (!PartitionCheckProtectiveMbr (PrivateData, ParentBlockDevNo)) {
+ return FALSE;
+ }
+
+ Found = PartitionCheckGptStructure (PrivateData, ParentBlockDevNo,
+ TRUE); if (!Found) {
+ DEBUG ((DEBUG_ERROR, "Primary GPT Header Error, Try to Check Backup GPT Header!\n"));
+ Found = PartitionCheckGptStructure (PrivateData, ParentBlockDevNo,
+ FALSE); }
+
+ if (Found) {
+ ParentBlockDev->PartitionChecked = TRUE; }
+
+ return Found;
+}
--
2.16.2.windows.1
next prev parent reply other threads:[~2019-01-23 8:40 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-17 2:03 [PATCH 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature Chen A Chen
[not found] ` <734D49CCEBEEF84792F5B80ED585239D5BFC0EC2@SHSMSX103.ccr.corp.intel.com>
2019-01-23 1:25 ` Wu, Hao A
2019-01-23 1:27 ` Wu, Hao A
2019-01-23 6:21 ` Zhang, Chao B
2019-01-23 8:40 ` Chen, Chen A [this message]
2019-01-28 5:10 ` Wu, Hao A
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8CCE94730AD68946B3D28B43192D9D2D06E5C183@shsmsx102.ccr.corp.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox