From: "Wu, Hao A" <hao.a.wu@intel.com>
To: "Ni, Ray" <ray.ni@intel.com>,
"Chen, Chen A" <chen.a.chen@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Zhang, Chao B" <chao.b.zhang@intel.com>
Subject: Re: [PATCH 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature.
Date: Wed, 23 Jan 2019 01:27:23 +0000 [thread overview]
Message-ID: <B80AF82E9BFB8E4FBD8C89DA810C6A093C880503@SHSMSX101.ccr.corp.intel.com> (raw)
In-Reply-To: <B80AF82E9BFB8E4FBD8C89DA810C6A093C8804EE@SHSMSX101.ccr.corp.intel.com>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Wu, Hao A
> Sent: Wednesday, January 23, 2019 9:25 AM
> To: Ni, Ray; Chen, Chen A; edk2-devel@lists.01.org
> Cc: Zhang, Chao B
> Subject: Re: [edk2] [PATCH 3/3] FatPkg: Add GPT check in FatPei to support
> Capsule-on-Disk feature.
>
> > -----Original Message-----
> > From: Ni, Ray
> > Sent: Thursday, January 17, 2019 11:50 AM
> > To: Chen, Chen A; edk2-devel@lists.01.org; Wu, Hao A
> > Cc: Zhang, Chao B
> > Subject: RE: [PATCH 3/3] FatPkg: Add GPT check in FatPei to support
> Capsule-
> > on-Disk feature.
> >
> > Adding Wu Hao in the reviewer list.
>
> Sorry for the delayed response.
> I will try my best to give my comments as soon as possible.
>
> Please help to ping if there is reply within the next two weeks.
Correction:
Please help to ping if there is no reply within the next two weeks.
>
> Best Regards,
> Hao Wu
>
> >
> > > -----Original Message-----
> > > From: Chen, Chen A <chen.a.chen@intel.com>
> > > 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
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
next prev parent reply other threads:[~2019-01-23 1:27 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 [this message]
2019-01-23 6:21 ` Zhang, Chao B
2019-01-23 8:40 ` Chen, Chen A
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=B80AF82E9BFB8E4FBD8C89DA810C6A093C880503@SHSMSX101.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