* [PATCH v2 1/3] FatPkg: Break down Part.c file.
2019-01-28 5:55 [PATCH v2 0/3] FatPkg/GPT: Introduce GPT patch v2 Chen A Chen
@ 2019-01-28 5:55 ` Chen A Chen
2019-01-28 5:56 ` [PATCH v2 2/3] MdePkg/UefiGpt.h: Add new definition for enable GPT support Chen A Chen
2019-01-28 5:56 ` [PATCH v2 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature Chen A Chen
2 siblings, 0 replies; 5+ messages in thread
From: Chen A Chen @ 2019-01-28 5:55 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
Break down partition parsing logic to 2 parts, Eltorito and MBR.
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/Eltorito.c | 239 +++++++++++++++++++++++++++++
FatPkg/FatPei/FatPei.inf | 4 +-
FatPkg/FatPei/Mbr.c | 182 ++++++++++++++++++++++
FatPkg/FatPei/Part.c | 385 +----------------------------------------------
4 files changed, 425 insertions(+), 385 deletions(-)
create mode 100644 FatPkg/FatPei/Eltorito.c
create mode 100644 FatPkg/FatPei/Mbr.c
diff --git a/FatPkg/FatPei/Eltorito.c b/FatPkg/FatPei/Eltorito.c
new file mode 100644
index 0000000000..ffaef51860
--- /dev/null
+++ b/FatPkg/FatPei/Eltorito.c
@@ -0,0 +1,239 @@
+/** @file
+ Routines supporting partition discovery and
+ logical device reading
+
+Copyright (c) 2006 - 2019, 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/ElTorito.h>
+#include "FatLitePeim.h"
+
+/**
+ This function finds Eltorito partitions. Main algorithm
+ is ported from DXE partition driver.
+
+ @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
+FatFindEltoritoPartitions (
+ IN PEI_FAT_PRIVATE_DATA *PrivateData,
+ IN UINTN ParentBlockDevNo
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Found;
+ PEI_FAT_BLOCK_DEVICE *BlockDev;
+ PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
+ UINT32 VolDescriptorLba;
+ UINT32 Lba;
+ CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
+ ELTORITO_CATALOG *Catalog;
+ UINTN Check;
+ UINTN Index;
+ UINTN MaxIndex;
+ UINT16 *CheckBuffer;
+ UINT32 SubBlockSize;
+ UINT32 SectorCount;
+ UINT32 VolSpaceSize;
+
+ if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
+ return FALSE;
+ }
+
+ Found = FALSE;
+ ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
+ VolSpaceSize = 0;
+
+ //
+ // CD_ROM has the fixed block size as 2048 bytes
+ //
+ if (ParentBlockDev->BlockSize != 2048) {
+ return FALSE;
+ }
+
+ VolDescriptor = (CDROM_VOLUME_DESCRIPTOR *) PrivateData->BlockData;
+ Catalog = (ELTORITO_CATALOG *) VolDescriptor;
+
+ //
+ // the ISO-9660 volume descriptor starts at 32k on the media
+ // and CD_ROM has the fixed block size as 2048 bytes, so...
+ //
+ VolDescriptorLba = 15;
+ //
+ // ((16*2048) / Media->BlockSize) - 1;
+ //
+ // Loop: handle one volume descriptor per time
+ //
+ while (TRUE) {
+
+ VolDescriptorLba += 1;
+ if (VolDescriptorLba > ParentBlockDev->LastBlock) {
+ //
+ // We are pointing past the end of the device so exit
+ //
+ break;
+ }
+
+ Status = FatReadBlock (
+ PrivateData,
+ ParentBlockDevNo,
+ VolDescriptorLba,
+ ParentBlockDev->BlockSize,
+ VolDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Check for valid volume descriptor signature
+ //
+ if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||
+ CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0
+ ) {
+ //
+ // end of Volume descriptor list
+ //
+ break;
+ }
+ //
+ // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte
+ //
+ if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) {
+ VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1];
+ }
+ //
+ // Is it an El Torito volume descriptor?
+ //
+ if (CompareMem (
+ VolDescriptor->BootRecordVolume.SystemId,
+ CDVOL_ELTORITO_ID,
+ sizeof (CDVOL_ELTORITO_ID) - 1
+ ) != 0) {
+ continue;
+ }
+ //
+ // Read in the boot El Torito boot catalog
+ //
+ Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
+ if (Lba > ParentBlockDev->LastBlock) {
+ continue;
+ }
+
+ Status = FatReadBlock (
+ PrivateData,
+ ParentBlockDevNo,
+ Lba,
+ ParentBlockDev->BlockSize,
+ Catalog
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ //
+ // We don't care too much about the Catalog header's contents, but we do want
+ // to make sure it looks like a Catalog header
+ //
+ if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
+ continue;
+ }
+
+ Check = 0;
+ CheckBuffer = (UINT16 *) Catalog;
+ for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
+ Check += CheckBuffer[Index];
+ }
+
+ if ((Check & 0xFFFF) != 0) {
+ continue;
+ }
+
+ MaxIndex = ParentBlockDev->BlockSize / sizeof (ELTORITO_CATALOG);
+ for (Index = 1; Index < MaxIndex; Index += 1) {
+ //
+ // Next entry
+ //
+ Catalog += 1;
+
+ //
+ // Check this entry
+ //
+ if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
+ continue;
+ }
+
+ SubBlockSize = 512;
+ SectorCount = Catalog->Boot.SectorCount;
+
+ switch (Catalog->Boot.MediaType) {
+
+ case ELTORITO_NO_EMULATION:
+ SubBlockSize = ParentBlockDev->BlockSize;
+ SectorCount = Catalog->Boot.SectorCount;
+ break;
+
+ case ELTORITO_HARD_DISK:
+ break;
+
+ case ELTORITO_12_DISKETTE:
+ SectorCount = 0x50 * 0x02 * 0x0F;
+ break;
+
+ case ELTORITO_14_DISKETTE:
+ SectorCount = 0x50 * 0x02 * 0x12;
+ break;
+
+ case ELTORITO_28_DISKETTE:
+ SectorCount = 0x50 * 0x02 * 0x24;
+ break;
+
+ default:
+ SectorCount = 0;
+ SubBlockSize = ParentBlockDev->BlockSize;
+ break;
+ }
+
+ if (SectorCount < 2) {
+ SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32) (ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32) (VolSpaceSize - Catalog->Boot.Lba);
+ }
+ //
+ // Register this partition
+ //
+ if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
+
+ Found = TRUE;
+
+ BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
+
+ BlockDev->BlockSize = SubBlockSize;
+ BlockDev->LastBlock = SectorCount - 1;
+ BlockDev->IoAlign = ParentBlockDev->IoAlign;
+ BlockDev->Logical = TRUE;
+ BlockDev->PartitionChecked = FALSE;
+ BlockDev->StartingPos = MultU64x32 (Catalog->Boot.Lba, ParentBlockDev->BlockSize);
+ BlockDev->ParentDevNo = ParentBlockDevNo;
+
+ PrivateData->BlockDeviceCount++;
+ }
+ }
+ }
+
+ ParentBlockDev->PartitionChecked = TRUE;
+
+ return Found;
+
+}
\ No newline at end of file
diff --git a/FatPkg/FatPei/FatPei.inf b/FatPkg/FatPei/FatPei.inf
index fc8d612283..5401f9a10b 100644
--- a/FatPkg/FatPei/FatPei.inf
+++ b/FatPkg/FatPei/FatPei.inf
@@ -1,7 +1,7 @@
## @file
# Lite Fat driver only used in Pei Phase.
#
-# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2019, 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
@@ -30,6 +30,8 @@
#
[Sources]
+ Mbr.c
+ Eltorito.c
Part.c
FatLiteApi.c
FatLiteLib.c
diff --git a/FatPkg/FatPei/Mbr.c b/FatPkg/FatPei/Mbr.c
new file mode 100644
index 0000000000..c0a147e10c
--- /dev/null
+++ b/FatPkg/FatPei/Mbr.c
@@ -0,0 +1,182 @@
+/** @file
+ Routines supporting partition discovery and
+ logical device reading
+
+Copyright (c) 2006 - 2019, 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 "FatLitePeim.h"
+
+/**
+ Test to see if the Mbr buffer is a valid MBR
+
+ @param Mbr Parent Handle
+ @param LastLba Last Lba address on the device.
+
+ @retval TRUE Mbr is a Valid MBR
+ @retval FALSE Mbr is not a Valid MBR
+
+**/
+BOOLEAN
+PartitionValidMbr (
+ IN MASTER_BOOT_RECORD *Mbr,
+ IN EFI_PEI_LBA LastLba
+ )
+{
+ UINT32 StartingLBA;
+ UINT32 EndingLBA;
+ UINT32 NewEndingLBA;
+ INTN Index1;
+ INTN Index2;
+ BOOLEAN MbrValid;
+
+ if (Mbr->Signature != MBR_SIGNATURE) {
+ return FALSE;
+ }
+ //
+ // The BPB also has this signature, so it can not be used alone.
+ //
+ MbrValid = FALSE;
+ for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {
+ if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) {
+ continue;
+ }
+
+ MbrValid = TRUE;
+ StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);
+ EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;
+ if (EndingLBA > LastLba) {
+ //
+ // Compatability Errata:
+ // Some systems try to hide drive space with thier INT 13h driver
+ // This does not hide space from the OS driver. This means the MBR
+ // that gets created from DOS is smaller than the MBR created from
+ // a real OS (NT & Win98). This leads to BlockIo->LastBlock being
+ // wrong on some systems FDISKed by the OS.
+ //
+ // return FALSE Because no block devices on a system are implemented
+ // with INT 13h
+ //
+ return FALSE;
+ }
+
+ for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {
+ if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index2].SizeInLBA) == 0) {
+ continue;
+ }
+
+ NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;
+ if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) {
+ //
+ // This region overlaps with the Index1'th region
+ //
+ return FALSE;
+ }
+ }
+ }
+ //
+ // Non of the regions overlapped so MBR is O.K.
+ //
+ return MbrValid;
+}
+
+
+/**
+ This function finds Mbr partitions. Main algorithm
+ is ported from DXE partition driver.
+
+ @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
+FatFindMbrPartitions (
+ IN PEI_FAT_PRIVATE_DATA *PrivateData,
+ IN UINTN ParentBlockDevNo
+ )
+{
+ EFI_STATUS Status;
+ MASTER_BOOT_RECORD *Mbr;
+ UINTN Index;
+ BOOLEAN Found;
+ PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
+ PEI_FAT_BLOCK_DEVICE *BlockDev;
+
+ 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 exceeds FAT_MAX_BLOCK_SIZE\n", ParentBlockDev->BlockSize));
+ return FALSE;
+ }
+
+ Found = FALSE;
+ Mbr = (MASTER_BOOT_RECORD *) PrivateData->BlockData;
+
+ Status = FatReadBlock (
+ PrivateData,
+ ParentBlockDevNo,
+ 0,
+ ParentBlockDev->BlockSize,
+ Mbr
+ );
+
+ if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) {
+ goto Done;
+ }
+ //
+ // We have a valid mbr - add each partition
+ //
+ for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
+ if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0) {
+ //
+ // Don't use null MBR entries
+ //
+ continue;
+ }
+ //
+ // Register this partition
+ //
+ if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
+
+ Found = TRUE;
+
+ BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
+
+ BlockDev->BlockSize = MBR_SIZE;
+ BlockDev->LastBlock = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1;
+ BlockDev->IoAlign = ParentBlockDev->IoAlign;
+ BlockDev->Logical = TRUE;
+ BlockDev->PartitionChecked = FALSE;
+ BlockDev->StartingPos = MultU64x32 (
+ UNPACK_INT32 (Mbr->Partition[Index].StartingLBA),
+ ParentBlockDev->BlockSize
+ );
+ BlockDev->ParentDevNo = ParentBlockDevNo;
+
+ PrivateData->BlockDeviceCount++;
+ }
+ }
+
+Done:
+
+ ParentBlockDev->PartitionChecked = TRUE;
+ return Found;
+}
diff --git a/FatPkg/FatPei/Part.c b/FatPkg/FatPei/Part.c
index be185460f3..1cf5f11b27 100644
--- a/FatPkg/FatPei/Part.c
+++ b/FatPkg/FatPei/Part.c
@@ -2,7 +2,7 @@
Routines supporting partition discovery and
logical device reading
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2019, 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
@@ -14,8 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
-#include <IndustryStandard/Mbr.h>
-#include <IndustryStandard/ElTorito.h>
#include "FatLitePeim.h"
/**
@@ -83,384 +81,3 @@ FatFindPartitions (
} while (Found && PrivateData->BlockDeviceCount <= PEI_FAT_MAX_BLOCK_DEVICE);
}
-
-/**
- This function finds Eltorito partitions. Main algorithm
- is ported from DXE partition driver.
-
- @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
-FatFindEltoritoPartitions (
- IN PEI_FAT_PRIVATE_DATA *PrivateData,
- IN UINTN ParentBlockDevNo
- )
-{
- EFI_STATUS Status;
- BOOLEAN Found;
- PEI_FAT_BLOCK_DEVICE *BlockDev;
- PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
- UINT32 VolDescriptorLba;
- UINT32 Lba;
- CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
- ELTORITO_CATALOG *Catalog;
- UINTN Check;
- UINTN Index;
- UINTN MaxIndex;
- UINT16 *CheckBuffer;
- UINT32 SubBlockSize;
- UINT32 SectorCount;
- UINT32 VolSpaceSize;
-
- if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
- return FALSE;
- }
-
- Found = FALSE;
- ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
- VolSpaceSize = 0;
-
- //
- // CD_ROM has the fixed block size as 2048 bytes
- //
- if (ParentBlockDev->BlockSize != 2048) {
- return FALSE;
- }
-
- VolDescriptor = (CDROM_VOLUME_DESCRIPTOR *) PrivateData->BlockData;
- Catalog = (ELTORITO_CATALOG *) VolDescriptor;
-
- //
- // the ISO-9660 volume descriptor starts at 32k on the media
- // and CD_ROM has the fixed block size as 2048 bytes, so...
- //
- VolDescriptorLba = 15;
- //
- // ((16*2048) / Media->BlockSize) - 1;
- //
- // Loop: handle one volume descriptor per time
- //
- while (TRUE) {
-
- VolDescriptorLba += 1;
- if (VolDescriptorLba > ParentBlockDev->LastBlock) {
- //
- // We are pointing past the end of the device so exit
- //
- break;
- }
-
- Status = FatReadBlock (
- PrivateData,
- ParentBlockDevNo,
- VolDescriptorLba,
- ParentBlockDev->BlockSize,
- VolDescriptor
- );
- if (EFI_ERROR (Status)) {
- break;
- }
- //
- // Check for valid volume descriptor signature
- //
- if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||
- CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0
- ) {
- //
- // end of Volume descriptor list
- //
- break;
- }
- //
- // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte
- //
- if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) {
- VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1];
- }
- //
- // Is it an El Torito volume descriptor?
- //
- if (CompareMem (
- VolDescriptor->BootRecordVolume.SystemId,
- CDVOL_ELTORITO_ID,
- sizeof (CDVOL_ELTORITO_ID) - 1
- ) != 0) {
- continue;
- }
- //
- // Read in the boot El Torito boot catalog
- //
- Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
- if (Lba > ParentBlockDev->LastBlock) {
- continue;
- }
-
- Status = FatReadBlock (
- PrivateData,
- ParentBlockDevNo,
- Lba,
- ParentBlockDev->BlockSize,
- Catalog
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
- //
- // We don't care too much about the Catalog header's contents, but we do want
- // to make sure it looks like a Catalog header
- //
- if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
- continue;
- }
-
- Check = 0;
- CheckBuffer = (UINT16 *) Catalog;
- for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
- Check += CheckBuffer[Index];
- }
-
- if ((Check & 0xFFFF) != 0) {
- continue;
- }
-
- MaxIndex = ParentBlockDev->BlockSize / sizeof (ELTORITO_CATALOG);
- for (Index = 1; Index < MaxIndex; Index += 1) {
- //
- // Next entry
- //
- Catalog += 1;
-
- //
- // Check this entry
- //
- if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
- continue;
- }
-
- SubBlockSize = 512;
- SectorCount = Catalog->Boot.SectorCount;
-
- switch (Catalog->Boot.MediaType) {
-
- case ELTORITO_NO_EMULATION:
- SubBlockSize = ParentBlockDev->BlockSize;
- SectorCount = Catalog->Boot.SectorCount;
- break;
-
- case ELTORITO_HARD_DISK:
- break;
-
- case ELTORITO_12_DISKETTE:
- SectorCount = 0x50 * 0x02 * 0x0F;
- break;
-
- case ELTORITO_14_DISKETTE:
- SectorCount = 0x50 * 0x02 * 0x12;
- break;
-
- case ELTORITO_28_DISKETTE:
- SectorCount = 0x50 * 0x02 * 0x24;
- break;
-
- default:
- SectorCount = 0;
- SubBlockSize = ParentBlockDev->BlockSize;
- break;
- }
-
- if (SectorCount < 2) {
- SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32) (ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32) (VolSpaceSize - Catalog->Boot.Lba);
- }
- //
- // Register this partition
- //
- if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
-
- Found = TRUE;
-
- BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
-
- BlockDev->BlockSize = SubBlockSize;
- BlockDev->LastBlock = SectorCount - 1;
- BlockDev->IoAlign = ParentBlockDev->IoAlign;
- BlockDev->Logical = TRUE;
- BlockDev->PartitionChecked = FALSE;
- BlockDev->StartingPos = MultU64x32 (Catalog->Boot.Lba, ParentBlockDev->BlockSize);
- BlockDev->ParentDevNo = ParentBlockDevNo;
-
- PrivateData->BlockDeviceCount++;
- }
- }
- }
-
- ParentBlockDev->PartitionChecked = TRUE;
-
- return Found;
-
-}
-
-
-/**
- Test to see if the Mbr buffer is a valid MBR
-
- @param Mbr Parent Handle
- @param LastLba Last Lba address on the device.
-
- @retval TRUE Mbr is a Valid MBR
- @retval FALSE Mbr is not a Valid MBR
-
-**/
-BOOLEAN
-PartitionValidMbr (
- IN MASTER_BOOT_RECORD *Mbr,
- IN EFI_PEI_LBA LastLba
- )
-{
- UINT32 StartingLBA;
- UINT32 EndingLBA;
- UINT32 NewEndingLBA;
- INTN Index1;
- INTN Index2;
- BOOLEAN MbrValid;
-
- if (Mbr->Signature != MBR_SIGNATURE) {
- return FALSE;
- }
- //
- // The BPB also has this signature, so it can not be used alone.
- //
- MbrValid = FALSE;
- for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {
- if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) {
- continue;
- }
-
- MbrValid = TRUE;
- StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);
- EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;
- if (EndingLBA > LastLba) {
- //
- // Compatability Errata:
- // Some systems try to hide drive space with thier INT 13h driver
- // This does not hide space from the OS driver. This means the MBR
- // that gets created from DOS is smaller than the MBR created from
- // a real OS (NT & Win98). This leads to BlockIo->LastBlock being
- // wrong on some systems FDISKed by the OS.
- //
- // return FALSE Because no block devices on a system are implemented
- // with INT 13h
- //
- return FALSE;
- }
-
- for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {
- if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index2].SizeInLBA) == 0) {
- continue;
- }
-
- NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;
- if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) {
- //
- // This region overlaps with the Index1'th region
- //
- return FALSE;
- }
- }
- }
- //
- // Non of the regions overlapped so MBR is O.K.
- //
- return MbrValid;
-}
-
-
-/**
- This function finds Mbr partitions. Main algorithm
- is ported from DXE partition driver.
-
- @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
-FatFindMbrPartitions (
- IN PEI_FAT_PRIVATE_DATA *PrivateData,
- IN UINTN ParentBlockDevNo
- )
-{
- EFI_STATUS Status;
- MASTER_BOOT_RECORD *Mbr;
- UINTN Index;
- BOOLEAN Found;
- PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
- PEI_FAT_BLOCK_DEVICE *BlockDev;
-
- if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
- return FALSE;
- }
-
- ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
-
- Found = FALSE;
- Mbr = (MASTER_BOOT_RECORD *) PrivateData->BlockData;
-
- Status = FatReadBlock (
- PrivateData,
- ParentBlockDevNo,
- 0,
- ParentBlockDev->BlockSize,
- Mbr
- );
-
- if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) {
- goto Done;
- }
- //
- // We have a valid mbr - add each partition
- //
- for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
- if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0) {
- //
- // Don't use null MBR entries
- //
- continue;
- }
- //
- // Register this partition
- //
- if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
-
- Found = TRUE;
-
- BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
-
- BlockDev->BlockSize = MBR_SIZE;
- BlockDev->LastBlock = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1;
- BlockDev->IoAlign = ParentBlockDev->IoAlign;
- BlockDev->Logical = TRUE;
- BlockDev->PartitionChecked = FALSE;
- BlockDev->StartingPos = MultU64x32 (
- UNPACK_INT32 (Mbr->Partition[Index].StartingLBA),
- ParentBlockDev->BlockSize
- );
- BlockDev->ParentDevNo = ParentBlockDevNo;
-
- PrivateData->BlockDeviceCount++;
- }
- }
-
-Done:
-
- ParentBlockDev->PartitionChecked = TRUE;
- return Found;
-}
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] FatPkg: Add GPT check in FatPei to support Capsule-on-Disk feature.
2019-01-28 5:55 [PATCH v2 0/3] FatPkg/GPT: Introduce GPT patch v2 Chen A Chen
2019-01-28 5:55 ` [PATCH v2 1/3] FatPkg: Break down Part.c file Chen A Chen
2019-01-28 5:56 ` [PATCH v2 2/3] MdePkg/UefiGpt.h: Add new definition for enable GPT support Chen A Chen
@ 2019-01-28 5:56 ` Chen A Chen
2 siblings, 0 replies; 5+ messages in thread
From: Chen A Chen @ 2019-01-28 5:56 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 | 3 +-
FatPkg/FatPei/FatPei.inf | 3 +
FatPkg/FatPei/Gpt.c | 552 ++++++++++++++++++++++++++++++++++++++++++++
FatPkg/FatPei/Part.c | 16 +-
4 files changed, 570 insertions(+), 4 deletions(-)
create mode 100644 FatPkg/FatPei/Gpt.c
diff --git a/FatPkg/FatPei/FatLitePeim.h b/FatPkg/FatPei/FatLitePeim.h
index fbf887da5f..3a0d8ae123 100644
--- a/FatPkg/FatPei/FatLitePeim.h
+++ b/FatPkg/FatPei/FatLitePeim.h
@@ -1,7 +1,7 @@
/** @file
Data structures for FAT recovery PEIM
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2019, 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
@@ -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 5401f9a10b..2ed11ba0a6 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..0cb640bd6f
--- /dev/null
+++ b/FatPkg/FatPei/Gpt.c
@@ -0,0 +1,552 @@
+/** @file
+ Routines supporting partition discovery and
+ logical device reading
+
+Copyright (c) 2019 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 (EFI_GPT_PART_ENTRY_MIN_SIZE, ParentBlockDev->BlockSize)) ||
+ (PartHdr->LastUsableLBA > ParentBlockDev->LastBlock - 1 - EFI_SIZE_TO_BLOCKS (EFI_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;
+ }
+
+ //
+ // Ensure the NumberOfPartitionEntries * SizeOfPartitionEntry doesn't overflow.
+ //
+ if (PartHdr->NumberOfPartitionEntries > DivU64x32 (MAX_UINTN, PartHdr->SizeOfPartitionEntry)) {
+ DEBUG ((DEBUG_ERROR, "Memory overflow in GPT Entry Array\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_RECORD *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 parts will not be used by UEFI, so we skip to check them.
+ //
+ for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
+ MbrPartition = (MBR_PARTITION_RECORD *)&ProtectiveMbr->Partition[Index];
+ if (MbrPartition->BootIndicator == 0x00 &&
+ MbrPartition->StartSector == 0x02 &&
+ MbrPartition->OSIndicator == PMBR_GPT_PARTITION &&
+ UNPACK_UINT32 (MbrPartition->StartingLBA) == 1
+ ) {
+ return TRUE;
+ }
+ }
+
+ DEBUG ((DEBUG_ERROR, "Protective Mbr, All Partition Entry Are Empty!\n"));
+ return FALSE;
+}
+
+/**
+ This function is used for finding GPT partition on block device.
+ As follow UEFI spec we should check protective 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;
+}
diff --git a/FatPkg/FatPei/Part.c b/FatPkg/FatPei/Part.c
index 1cf5f11b27..a0e9fec882 100644
--- a/FatPkg/FatPei/Part.c
+++ b/FatPkg/FatPei/Part.c
@@ -72,9 +72,19 @@ FatFindPartitions (
for (Index = 0; Index < PrivateData->BlockDeviceCount; Index++) {
if (!PrivateData->BlockDevice[Index].PartitionChecked) {
- Found = FatFindMbrPartitions (PrivateData, Index);
- if (!Found) {
- Found = FatFindEltoritoPartitions (PrivateData, Index);
+ if (FatFindGptPartitions (PrivateData, Index)) {
+ Found = TRUE;
+ continue;
+ }
+
+ if (FatFindMbrPartitions (PrivateData, Index)) {
+ Found = TRUE;
+ continue;
+ }
+
+ if (FatFindEltoritoPartitions (PrivateData, Index)) {
+ Found = TRUE;
+ continue;
}
}
}
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 5+ messages in thread