public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature.
@ 2019-01-17  2:03 Chen A Chen
       [not found] ` <734D49CCEBEEF84792F5B80ED585239D5BFC0EC2@SHSMSX103.ccr.corp.intel.com>
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Chen A Chen @ 2019-01-17  2:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Chen A Chen, Ruiyu Ni, Zhang Chao B

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



^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-01-28  5:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2019-01-28  5:10 ` Wu, Hao A

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox