From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.151; helo=mga17.intel.com; envelope-from=chao.b.zhang@intel.com; receiver=edk2-devel@lists.01.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id DAF5B211B6C1A for ; Tue, 22 Jan 2019 22:21:43 -0800 (PST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Jan 2019 22:21:42 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,510,1539673200"; d="scan'208";a="312636039" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by fmsmga006.fm.intel.com with ESMTP; 22 Jan 2019 22:21:42 -0800 Received: from fmsmsx111.amr.corp.intel.com (10.18.116.5) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.408.0; Tue, 22 Jan 2019 22:21:42 -0800 Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by fmsmsx111.amr.corp.intel.com (10.18.116.5) with Microsoft SMTP Server (TLS) id 14.3.408.0; Tue, 22 Jan 2019 22:21:42 -0800 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.63]) by SHSMSX104.ccr.corp.intel.com ([169.254.5.159]) with mapi id 14.03.0415.000; Wed, 23 Jan 2019 14:21:40 +0800 From: "Zhang, Chao B" To: "Chen, Chen A" , "edk2-devel@lists.01.org" Thread-Topic: [PATCH 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature. Thread-Index: AQHUrgjLGr8ppGvJVEqNoeR2lyZNFaW8a2wA Date: Wed, 23 Jan 2019 06:21:39 +0000 Message-ID: References: <20190117020303.10244-1-chen.a.chen@intel.com> In-Reply-To: <20190117020303.10244-1-chen.a.chen@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ctpclassification: CTP_NT x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiZmViNzRiMGYtMDY3Yy00Njc4LTg3MmYtOWRmMjY2MWU3MDE2IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiQW1VN21FRG5KVWhjR25TSHRIYkJCRWFwRnh6bmtUWXc1U2I5NjBIZFwvUXdrd081Y1VoTGpWNWJJYjlyUXNCVHMifQ== dlp-product: dlpe-windows dlp-version: 11.0.400.15 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Jan 2019 06:21:44 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by : Chao Zhang -----Original Message----- From: Chen, Chen A=20 Sent: Thursday, January 17, 2019 10:03 AM To: edk2-devel@lists.01.org Cc: Chen, Chen A ; Ni, Ray ; Zhang= , Chao B 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=3D1470 This feature is used for finding GPT partition, follow the following step t= o check. 1) Check Protective MBR. 2) Check GPT primary/backup header. 3) Check GPT primary/backup entry array. Cc: Ruiyu Ni Cc: Zhang Chao B Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Chen A Chen --- 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 inde= x 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 #include #include +#include #include #include #include diff --git a/FatPkg/FatPei/FatPei.inf b/FatPkg/FatPei/FatPei.inf index 829e= 87fe92..dd0869f7cd 100644 --- a/FatPkg/FatPei/FatPei.inf +++ b/FatPkg/FatPei/FatPei.inf @@ -31,6 +31,7 @@ =20 [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 ## U= NDEFINED gRecoveryOnFatFloppyDiskGuid ## SOMETIMES_CONSUMES ## U= NDEFINED gRecoveryOnFatNvmeDiskGuid ## SOMETIMES_CONSUMES ## U= NDEFINED + gEfiPartTypeUnusedGuid ## SOMETIMES_CONSUMES ## U= NDEFINED =20 =20 [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.
+ +This program and the accompanying materials are licensed and made=20 +available under the terms and conditions of the BSD License which=20 +accompanies this distribution. The full text of the license may be=20 +found at http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=20 +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include +#include +#include +#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)=20 +% (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 =3D PartHeader->Header.CRC32; + + // + // Set CRC field to zero when doing calcuation // + PartHeader->Header.CRC32 =3D 0; + + Crc =3D CalculateCrc32 (PartHeader, PartHeader->Header.HeaderSize); + + // + // Restore Header CRC + // + PartHeader->Header.CRC32 =3D GptHdrCrc; + + return (GptHdrCrc =3D=3D 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 =3D (UINTN)MultU64x32(PartHeader->NumberOfPartitionEntries,=20 + PartHeader->SizeOfPartitionEntry); + Crc =3D CalculateCrc32 (PartEntry, Size); + + return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 =3D=3D Crc); } + +/** + The function is used for valid GPT table. Both for Primary and Backup GP= T header. + + @param[in] PrivateData The global memory map=20 + @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 ( =20 + 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 =3D &(PrivateData->BlockDevice[ParentBlockDevNo]); + + if (IsPrimaryHeader) { + Lba =3D PRIMARY_PART_HEADER_LBA; + AlternateLba =3D ParentBlockDev->LastBlock; } else { + Lba =3D ParentBlockDev->LastBlock; + AlternateLba =3D PRIMARY_PART_HEADER_LBA; } + + if ( (PartHdr->Header.Signature !=3D EFI_PTAB_HEADER_ID) || + (PartHdr->Header.Revision !=3D 0x00010000) || + (PartHdr->Header.HeaderSize < 92) || + (PartHdr->Header.HeaderSize > ParentBlockDev->BlockSize) || + (!PartitionCheckGptHeaderCRC (PartHdr)) || + (PartHdr->Header.Reserved !=3D 0) + ) { + DEBUG ((DEBUG_ERROR, "Invalid efi partition table header\n")); + return FALSE; + } + + // + // | Block0 | Block1 |Block2 ~ FirstUsableLBA - 1|FirstUsabl= eLBA, ... ,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 !=3D Lba) || + (PartHdr->AlternateLBA !=3D AlternateLba) || + (PartHdr->FirstUsableLBA < 2 + EFI_SIZE_TO_BLOCKS (GPT_PART_ENTRY_M= IN_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 >=3D PartHdr->FirstUsableLBA && PartHdr= ->PartitionEntryLBA <=3D PartHdr->LastUsableLBA) || + (PartHdr->SizeOfPartitionEntry%128 !=3D 0) || + (PartHdr->SizeOfPartitionEntry !=3D sizeof (EFI_PARTITION_ENTRY)) + ) { + DEBUG ((DEBUG_ERROR, "Invalid efi partition table header\n")); + return FALSE; + } + + PartitionEntryArraySize =3D MultU64x32=20 + (PartHdr->NumberOfPartitionEntries, PartHdr->SizeOfPartitionEntry); =20 + EntryArraySizeRemainder =3D 0; PartitionEntryBlockNumb =3D=20 + DivU64x32Remainder (PartitionEntryArraySize, ParentBlockDev->BlockSize, &= EntryArraySizeRemainder); if (EntryArraySizeRemainder !=3D 0) { + PartitionEntryBlockNumb++; + } + + if (IsPrimaryHeader) { + EntryArrayLastLba =3D PartHdr->FirstUsableLBA; } else { + EntryArrayLastLba =3D ParentBlockDev->LastBlock; } + + // + // Make sure partition entry array not overlaps with partition area or t= he LastBlock. + // + if (PartHdr->PartitionEntryLBA + PartitionEntryBlockNumb > EntryArrayLas= tLba) { + DEBUG ((DEBUG_ERROR, "GPT Partition Entry Array Error!\n")); + DEBUG ((DEBUG_ERROR, "PartitionEntryArraySize =3D %lu.\n", PartitionEn= tryArraySize)); + DEBUG ((DEBUG_ERROR, "PartitionEntryLBA =3D %lu.\n", PartHdr->Partitio= nEntryLBA)); + DEBUG ((DEBUG_ERROR, "PartitionEntryBlockNumb =3D %lu.\n", PartitionEn= tryBlockNumb)); + DEBUG ((DEBUG_ERROR, "EntryArrayLastLba =3D %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=20 + @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 =3D &(PrivateData->BlockDevice[ParentBlockDevNo]); + Found =3D FALSE; + + PartitionEntryArraySize =3D MultU64x32=20 + (PartHdr->NumberOfPartitionEntries, PartHdr->SizeOfPartitionEntry); =20 + EntryArraySizeRemainder =3D 0; PartitionEntryBlockNumb =3D=20 + DivU64x32Remainder (PartitionEntryArraySize, ParentBlockDev->BlockSize, &= EntryArraySizeRemainder); if (EntryArraySizeRemainder !=3D 0) { + PartitionEntryBlockNumb++; + } + PartitionEntryArraySize =3D MultU64x32 (PartitionEntryBlockNumb,=20 + ParentBlockDev->BlockSize); + + PartitionEntryBuffer =3D (EFI_PARTITION_ENTRY *) AllocatePages=20 + (EFI_SIZE_TO_PAGES ((UINTN)PartitionEntryArraySize)); + if (PartitionEntryBuffer =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Allocate memory error!\n")); + goto EXIT; + } + + PartitionEntryStatus =3D (EFI_PARTITION_ENTRY_STATUS *) AllocatePages=20 + (EFI_SIZE_TO_PAGES (PartHdr->NumberOfPartitionEntries * sizeof (EFI_PARTI= TION_ENTRY_STATUS))); if (PartitionEntryStatus =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Allocate memory error!\n")); + goto EXIT; + } + ZeroMem (PartitionEntryStatus, PartHdr->NumberOfPartitionEntries *=20 + sizeof (EFI_PARTITION_ENTRY_STATUS)); + =20 + Status =3D 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 =3D 0; Index1 < PartHdr->NumberOfPartitionEntries; Index1++)= { + Entry =3D (EFI_PARTITION_ENTRY *) ((UINT8 *) PartitionEntryBuffer + In= dex1 * PartHdr->SizeOfPartitionEntry); + if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) = { + continue; + } + + StartingLBA =3D Entry->StartingLBA; + EndingLBA =3D Entry->EndingLBA; + if (StartingLBA > EndingLBA || + StartingLBA < PartHdr->FirstUsableLBA || + StartingLBA > PartHdr->LastUsableLBA || + EndingLBA < PartHdr->FirstUsableLBA || + EndingLBA > PartHdr->LastUsableLBA + ) { + PartitionEntryStatus[Index1].OutOfRange =3D TRUE; + continue; + } + + if ((Entry->Attributes & BIT1) !=3D 0) { + // + // If Bit 1 is set, this indicate that this is an OS specific GUID p= artition. + // + PartitionEntryStatus[Index1].OsSpecific =3D TRUE; + } + + for (Index2 =3D Index1 + 1; Index2 < PartHdr->NumberOfPartitionEntries= ; Index2++) { + Entry =3D (EFI_PARTITION_ENTRY *) ((UINT8 *) PartitionEntryBuffer + = Index2 * PartHdr->SizeOfPartitionEntry); + if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)= ) { + continue; + } + + if (Entry->EndingLBA >=3D StartingLBA && Entry->StartingLBA <=3D End= ingLBA) { + // + // This region overlaps with the Index1'th region + // + PartitionEntryStatus[Index1].Overlap =3D TRUE; + PartitionEntryStatus[Index2].Overlap =3D TRUE; + continue; + } + } + } + + for (Index =3D 0; Index < PartHdr->NumberOfPartitionEntries; Index++) { + if (CompareGuid (&PartitionEntryBuffer[Index].PartitionTypeGUID, &gEfi= PartTypeUnusedGuid)|| + PartitionEntryStatus[Index].OutOfRange || + PartitionEntryStatus[Index].Overlap || + PartitionEntryStatus[Index].OsSpecific) { + // + // Don't use null EFI Partition Entries, Invalid Partition Entries o= r OS specific + // partition Entries + // + continue; + } + + if (PrivateData->BlockDeviceCount >=3D PEI_FAT_MAX_BLOCK_DEVICE) { + break; + } + + Found =3D TRUE; + BlockDevPtr =3D &(PrivateData->BlockDevice[PrivateDa= ta->BlockDeviceCount]); + + BlockDevPtr->BlockSize =3D ParentBlockDev->BlockSize; + BlockDevPtr->LastBlock =3D PartitionEntryBuffer[Index].EndingLB= A; + BlockDevPtr->IoAlign =3D ParentBlockDev->IoAlign; + BlockDevPtr->Logical =3D TRUE; + BlockDevPtr->PartitionChecked =3D FALSE; + BlockDevPtr->StartingPos =3D MultU64x32 ( + PartitionEntryBuffer[Index].Starting= LBA, + ParentBlockDev->BlockSize + ); + BlockDevPtr->ParentDevNo =3D 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= )); + } + =20 +EXIT: + if (PartitionEntryBuffer !=3D NULL) { + FreePages (PartitionEntryBuffer, EFI_SIZE_TO_PAGES=20 +((UINTN)PartitionEntryArraySize)); + } + + if (PartitionEntryStatus !=3D NULL) { + FreePages (PartitionEntryStatus, EFI_SIZE_TO_PAGES=20 + (PartHdr->NumberOfPartitionEntries * sizeof=20 + (EFI_PARTITION_ENTRY_STATUS))); } + =20 + 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. + =20 + @param PrivateData The global memory map=20 + @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 =3D &(PrivateData->BlockDevice[ParentBlockDevNo]); + PartHdr =3D (EFI_PARTITION_TABLE_HEADER *) PrivateData->BlockDat= a; + + if (IsPrimary) { + GptHeaderLBA =3D PRIMARY_PART_HEADER_LBA; } else { + GptHeaderLBA =3D ParentBlockDev->LastBlock; } + + Status =3D 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 =3D (MASTER_BOOT_RECORD *) PrivateData->BlockData; + ParentBlockDev =3D &(PrivateData->BlockDevice[ParentBlockDevNo]); + + // + // Read Protective MBR + // + Status =3D FatReadBlock ( + PrivateData, + ParentBlockDevNo, + 0, + ParentBlockDev->BlockSize, + ProtectiveMbr + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GPT Error When Read Protective Mbr From Partitio= n!\n")); + return FALSE; + } + + if (ProtectiveMbr->Signature !=3D 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.=20 + // These parst will not used by UEFI, so we skip to check them. + // + for (Index =3D 0; Index < MAX_MBR_PARTITIONS; Index++) { + MbrPartition =3D (MBR_PARTITION_ENTRY *)&ProtectiveMbr->Partition[Inde= x]; + if (MbrPartition->BootIndicator =3D=3D 0x00 && + MbrPartition->StartingCHS[0] =3D=3D 0x00 && + MbrPartition->StartingCHS[1] =3D=3D 0x02 && + MbrPartition->StartingCHS[2] =3D=3D 0x00 && + MbrPartition->OSType =3D=3D PMBR_GPT_PARTITION && + MbrPartition->StartingLBA =3D=3D 0x1 + ) { + return TRUE; + } + } + + DEBUG ((DEBUG_ERROR, "Protective Mbr, All Partition Entry Are=20 +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=20 + @param ParentBlockDevNo The parent block device + + @retval TRUE New partitions are detected and logical block = devices=20 + are added to block device array=20 + @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 =3D &(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 =3D PartitionCheckGptStructure (PrivateData, ParentBlockDevNo,=20 + TRUE); if (!Found) { + DEBUG ((DEBUG_ERROR, "Primary GPT Header Error, Try to Check Backup GP= T Header!\n")); + Found =3D PartitionCheckGptStructure (PrivateData, ParentBlockDevNo,=20 + FALSE); } + + if (Found) { + ParentBlockDev->PartitionChecked =3D TRUE; } + + return Found; +} -- 2.16.2.windows.1