From: "Ni, Ruiyu" <ruiyu.ni@intel.com>
To: Tim Lewis <tim.lewis@insyde.com>,
Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>,
"Carsey, Jaben" <jaben.carsey@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Subject: Re: [PATCH] GPT Shell Application/Library
Date: Tue, 18 Oct 2016 01:55:26 +0000 [thread overview]
Message-ID: <734D49CCEBEEF84792F5B80ED585239D58E36F85@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <7236196A5DF6C040855A6D96F556A53F3F80DD@msmail.insydesw.com.tw>
Or we could have a common wrapper module, that links to different library to provide different <command>.efi.
This will require the name of the wrapper module is customizable. Haven't tried on that, seems doable.
Thanks/Ray
> -----Original Message-----
> From: Tim Lewis [mailto:tim.lewis@insyde.com]
> Sent: Tuesday, October 18, 2016 9:48 AM
> To: Ni, Ruiyu <ruiyu.ni@intel.com>; Vladimir Olovyannikov
> <vladimir.olovyannikov@broadcom.com>; Carsey, Jaben
> <jaben.carsey@intel.com>; edk2-devel@lists.01.org
> Subject: RE: [PATCH] GPT Shell Application/Library
>
> We would prefer that this tool be external. Tim
>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ni,
> Ruiyu
> Sent: Monday, October 17, 2016 6:46 PM
> To: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>; Carsey,
> Jaben <jaben.carsey@intel.com>; edk2-devel@lists.01.org
> Subject: Re: [edk2] [PATCH] GPT Shell Application/Library
>
> Jaben,
> Do you think that providing a standalone gpt.efi is better? So that Shell.efi
> only provides the internal commands listed in Shell spec.
>
> Thanks/Ray
>
> > -----Original Message-----
> > From: Vladimir Olovyannikov
> [mailto:vladimir.olovyannikov@broadcom.com]
> > Sent: Sunday, October 16, 2016 1:24 PM
> > To: Carsey, Jaben <jaben.carsey@intel.com>; edk2-devel@lists.01.org; Ni,
> > Ruiyu <ruiyu.ni@intel.com>
> > Cc: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> > Subject: [PATCH] GPT Shell Application/Library
> >
> > This allows managing (create, delete, modify, fat format) of GPT
> > partitions from within UEFI Shell.
> > Syntax:
> > gpt <command> [device_mapped_name] [parameters...]
> > See usage examples in the .uni file
> > ---
> > .../Library/UefiShellGptCommandLib/FatFormat.c | 611 +++++++
> > .../Library/UefiShellGptCommandLib/FatFormat.h | 111 ++
> > .../Library/UefiShellGptCommandLib/GptWorker.c | 1902
> > ++++++++++++++++++++
> > .../Library/UefiShellGptCommandLib/GptWorker.h | 186 ++
> > .../UefiShellGptCommandLib.c | 1135 ++++++++++++
> > .../UefiShellGptCommandLib.inf | 79 +
> > .../UefiShellGptCommandLib.uni | 117 ++
> > ShellPkg/ShellPkg.dec | 1 +
> > ShellPkg/ShellPkg.dsc | 4 +
> > 9 files changed, 4146 insertions(+)
> > create mode 100644
> ShellPkg/Library/UefiShellGptCommandLib/FatFormat.c
> > create mode 100644
> > ShellPkg/Library/UefiShellGptCommandLib/FatFormat.h
> > create mode 100644
> > ShellPkg/Library/UefiShellGptCommandLib/GptWorker.c
> > create mode 100644
> > ShellPkg/Library/UefiShellGptCommandLib/GptWorker.h
> > create mode 100644
> > ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.c
> > create mode 100644
> > ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.inf
> > create mode 100644
> > ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.uni
> >
> > diff --git a/ShellPkg/Library/UefiShellGptCommandLib/FatFormat.c
> > b/ShellPkg/Library/UefiShellGptCommandLib/FatFormat.c
> > new file mode 100644
> > index 000000000000..ba7904e6be28
> > --- /dev/null
> > +++ b/ShellPkg/Library/UefiShellGptCommandLib/FatFormat.c
> > @@ -0,0 +1,611 @@
> > +/** @file
> > +
> > + Copyright (c) 2003 - 2012, Rob Riglar, Ultra-Embedded.com. 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.
> > +
> > +**/
> > +
> > +/* Portions Copyright (c) 2016, Broadcom. All rights reserved */
> > +
> > +#include "FatFormat.h"
> > +
> > +//-----------------------------------------------------------------------------
> > +// Tables
> > +//-----------------------------------------------------------------------------
> > +typedef struct
> > +{
> > + UINT64 Sectors;
> > + UINT8 SectorsPerCluster;
> > +} SectorsPerClusterTable;
> > +
> > +STATIC SectorsPerClusterTable ClusterSizeTable16[] =
> > +{
> > + { 32680, 2 }, // 16MB - 1K
> > + { 262144, 4 }, // 128MB - 2K
> > + { 524288, 8 }, // 256MB - 4K
> > + { 1048576, 16 }, // 512MB - 8K
> > + { 2097152, 32 }, // 1GB - 16K
> > + { 4194304, 64 }, // 2GB - 32K
> > + { 8388608, 128 }, // 2GB - 64K [Warning only supported by Windows XP
> > onwards]
> > + { 0, 0 } // Invalid
> > +};
> > +
> > +STATIC SectorsPerClusterTable ClusterSizeTable32[] =
> > +{
> > + { 532480, 1 }, // 260MB - 512b
> > + { 16777216, 8 }, // 8GB - 4K
> > + { 33554432, 16 }, // 16GB - 8K
> > + { 67108864, 32 }, // 32GB - 16K
> > + { 0xFFFFFFFF, 64 }, // >32GB - 32K
> > + { 0, 0 } // Invalid
> > +};
> > +
> > +STATIC
> > +EFI_LBA LbaOfCluster (
> > + IN FATFS *Fs,
> > + IN UINT64 ClusterNumber
> > + )
> > +{
> > + if (Fs->FatType == FAT_TYPE_16)
> > + return (Fs->ClusterBeginLba +
> > + (Fs->RootEntryCount * 32 / FAT_SECTOR_SIZE) +
> > + ((ClusterNumber - 2) * Fs->SectorsPerCluster));
> > + else
> > + return ((Fs->ClusterBeginLba +
> > + ((ClusterNumber - 2) * Fs->SectorsPerCluster)));
> > +}
> > +
> > +//-----------------------------------------------------------------------------
> > +// fatfs_calc_cluster_size: Calculate what cluster size should be used
> > +//-----------------------------------------------------------------------------
> > +STATIC
> > +UINT8 CalcClusterSize (
> > + IN UINTN Sectors,
> > + IN BOOLEAN IsFat32)
> > +{
> > + UINTN Index;
> > +
> > + if (!IsFat32) {
> > + for (Index = 0; ClusterSizeTable16[Index].SectorsPerCluster != 0;
> Index++)
> > + if (Sectors <= ClusterSizeTable16[Index].Sectors)
> > + return ClusterSizeTable16[Index].SectorsPerCluster;
> > + } else {
> > + for (Index = 0; ClusterSizeTable32[Index].SectorsPerCluster != 0;
> Index++)
> > + if (Sectors <= ClusterSizeTable32[Index].Sectors)
> > + return ClusterSizeTable32[Index].SectorsPerCluster;
> > + }
> > +
> > + return 0;
> > +}
> > +//-----------------------------------------------------------------------------
> > +// fatfs_erase_sectors: Erase a number of sectors
> > +//-----------------------------------------------------------------------------
> > +STATIC
> > +EFI_STATUS
> > +EraseSectors (
> > + IN FATFS *Fs,
> > + IN EFI_LBA Lba,
> > + IN UINTN Count
> > + )
> > +{
> > + UINTN Index;
> > + EFI_STATUS Status;
> > +
> > + // Zero Sector first
> > + ZeroMem (Fs->CurrentSector.Sector, FAT_SECTOR_SIZE);
> > +
> > + for (Index = 0; Index < Count; Index++)
> > + Status = Fs->DiskIo->WriteDisk (
> > + Fs->DiskIo, Fs->BlockIo->Media->MediaId,
> > + MultU64x32 (Fs->StartingLBA, Fs->BlockIo->Media->BlockSize) +
> > + MultU64x32 ((Lba + Index), FAT_SECTOR_SIZE),
> > + FAT_SECTOR_SIZE, Fs->CurrentSector.Sector);
> > +
> > + return Status;
> > +}
> > +//-----------------------------------------------------------------------------
> > +// fatfs_create_boot_sector: Create the boot Sector
> > +//-----------------------------------------------------------------------------
> > +STATIC
> > +EFI_STATUS
> > +CreateBootSector (
> > + IN FATFS *Fs,
> > + IN EFI_LBA BootSectorLba,
> > + IN UINT64 VolSectors,
> > + IN CONST CHAR8 *Name,
> > + IN BOOLEAN IsFat32
> > + )
> > +{
> > + UINTN TotalClusters;
> > + UINTN Index;
> > + EFI_STATUS Status;
> > +
> > + // Zero Sector initially
> > + ZeroMem (Fs->CurrentSector.Sector, FAT_SECTOR_SIZE);
> > +
> > + // OEM Name & Jump Code
> > + Fs->CurrentSector.Sector[0] = 0xEB;
> > + Fs->CurrentSector.Sector[1] = 0x3C;
> > + Fs->CurrentSector.Sector[2] = 0x90;
> > + Fs->CurrentSector.Sector[3] = 0x4D;
> > + Fs->CurrentSector.Sector[4] = 0x53;
> > + Fs->CurrentSector.Sector[5] = 0x44;
> > + Fs->CurrentSector.Sector[6] = 0x4F;
> > + Fs->CurrentSector.Sector[7] = 0x53;
> > + Fs->CurrentSector.Sector[8] = 0x35;
> > + Fs->CurrentSector.Sector[9] = 0x2E;
> > + Fs->CurrentSector.Sector[10] = 0x30;
> > +
> > + // Bytes per Sector
> > + Fs->CurrentSector.Sector[11] = (FAT_SECTOR_SIZE >> 0) & 0xFF;
> > + Fs->CurrentSector.Sector[12] = (FAT_SECTOR_SIZE >> 8) & 0xFF;
> > +
> > + // Get sectors per cluster size for the disk
> > + Fs->SectorsPerCluster = CalcClusterSize (VolSectors, IsFat32);
> > + if (!Fs->SectorsPerCluster)
> > + return 0; // Invalid disk size
> > +
> > + // Sectors per cluster
> > + Fs->CurrentSector.Sector[13] = Fs->SectorsPerCluster;
> > +
> > + // Reserved Sectors
> > + if (!IsFat32)
> > + Fs->ReservedSectors = 8;
> > + else
> > + Fs->ReservedSectors = 32;
> > + Fs->CurrentSector.Sector[14] = (Fs->ReservedSectors >> 0) & 0xFF;
> > + Fs->CurrentSector.Sector[15] = (Fs->ReservedSectors >> 8) & 0xFF;
> > +
> > + // Number of FATS
> > + Fs->NumOfFats = 2;
> > + Fs->CurrentSector.Sector[16] = Fs->NumOfFats;
> > +
> > + // Max entries in root dir (FAT16 only)
> > + if (!IsFat32) {
> > + Fs->RootEntryCount = 512;
> > + Fs->CurrentSector.Sector[17] = (Fs->RootEntryCount >> 0) & 0xFF;
> > + Fs->CurrentSector.Sector[18] = (Fs->RootEntryCount >> 8) & 0xFF;
> > + } else {
> > + Fs->RootEntryCount = 0;
> > + Fs->CurrentSector.Sector[17] = 0;
> > + Fs->CurrentSector.Sector[18] = 0;
> > + }
> > +
> > + // [FAT16] Total sectors (use FAT32 count instead)
> > + Fs->CurrentSector.Sector[19] = 0x00;
> > + Fs->CurrentSector.Sector[20] = 0x00;
> > +
> > + // Media type
> > + Fs->CurrentSector.Sector[21] = 0xF8;
> > +
> > +
> > + // FAT16 BS Details
> > + if (!IsFat32) {
> > + // Count of sectors used by the FAT table (FAT16 only)
> > + TotalClusters = (VolSectors / Fs->SectorsPerCluster) + 1;
> > + Fs->FatSectors = (TotalClusters / (FAT_SECTOR_SIZE / 2)) + 1;
> > + Fs->CurrentSector.Sector[22] = (UINT8)((Fs->FatSectors >> 0) & 0xFF);
> > + Fs->CurrentSector.Sector[23] = (UINT8)((Fs->FatSectors >> 8) & 0xFF);
> > +
> > + // Sectors per track
> > + Fs->CurrentSector.Sector[24] = 0x00;
> > + Fs->CurrentSector.Sector[25] = 0x00;
> > +
> > + // Heads
> > + Fs->CurrentSector.Sector[26] = 0x00;
> > + Fs->CurrentSector.Sector[27] = 0x00;
> > +
> > + // Hidden sectors
> > + Fs->CurrentSector.Sector[28] = 0x20;
> > + Fs->CurrentSector.Sector[29] = 0x00;
> > + Fs->CurrentSector.Sector[30] = 0x00;
> > + Fs->CurrentSector.Sector[31] = 0x00;
> > +
> > + // Total sectors for this volume
> > + Fs->CurrentSector.Sector[32] = (UINT8)((VolSectors >> 0) & 0xFF);
> > + Fs->CurrentSector.Sector[33] = (UINT8)((VolSectors >> 8) & 0xFF);
> > + Fs->CurrentSector.Sector[34] = (UINT8)((VolSectors >> 16) & 0xFF);
> > + Fs->CurrentSector.Sector[35] = (UINT8)((VolSectors >> 24) & 0xFF);
> > +
> > + // Drive number
> > + Fs->CurrentSector.Sector[36] = 0x00;
> > +
> > + // Reserved
> > + Fs->CurrentSector.Sector[37] = 0x00;
> > +
> > + // Boot signature
> > + Fs->CurrentSector.Sector[38] = 0x29;
> > +
> > + // Volume ID
> > + Fs->CurrentSector.Sector[39] = 0x12;
> > + Fs->CurrentSector.Sector[40] = 0x34;
> > + Fs->CurrentSector.Sector[41] = 0x56;
> > + Fs->CurrentSector.Sector[42] = 0x78;
> > +
> > + // Volume name
> > + for (Index = 0; Index < 11; Index++) {
> > + if (Index < AsciiStrLen (Name))
> > + Fs->CurrentSector.Sector[Index + 43] = Name[Index];
> > + else
> > + Fs->CurrentSector.Sector[Index + 43] = ' ';
> > + }
> > +
> > + // File sys type
> > + Fs->CurrentSector.Sector[54] = 'F';
> > + Fs->CurrentSector.Sector[55] = 'A';
> > + Fs->CurrentSector.Sector[56] = 'T';
> > + Fs->CurrentSector.Sector[57] = '1';
> > + Fs->CurrentSector.Sector[58] = '6';
> > + Fs->CurrentSector.Sector[59] = ' ';
> > + Fs->CurrentSector.Sector[60] = ' ';
> > + Fs->CurrentSector.Sector[61] = ' ';
> > +
> > + // Signature
> > + Fs->CurrentSector.Sector[510] = 0x55;
> > + Fs->CurrentSector.Sector[511] = 0xAA;
> > + }
> > + // FAT32 BS Details
> > + else {
> > + // Count of sectors used by the FAT table (FAT16 only)
> > + Fs->CurrentSector.Sector[22] = 0;
> > + Fs->CurrentSector.Sector[23] = 0;
> > +
> > + // Sectors per track (default)
> > + Fs->CurrentSector.Sector[24] = 0x3F;
> > + Fs->CurrentSector.Sector[25] = 0x00;
> > +
> > + // Heads (default)
> > + Fs->CurrentSector.Sector[26] = 0xFF;
> > + Fs->CurrentSector.Sector[27] = 0x00;
> > +
> > + // Hidden sectors
> > + Fs->CurrentSector.Sector[28] = 0x00;
> > + Fs->CurrentSector.Sector[29] = 0x00;
> > + Fs->CurrentSector.Sector[30] = 0x00;
> > + Fs->CurrentSector.Sector[31] = 0x00;
> > +
> > + // Total sectors for this volume
> > + Fs->CurrentSector.Sector[32] = (UINT8)((VolSectors >> 0) & 0xFF);
> > + Fs->CurrentSector.Sector[33] = (UINT8)((VolSectors >> 8) & 0xFF);
> > + Fs->CurrentSector.Sector[34] = (UINT8)((VolSectors >> 16) & 0xFF);
> > + Fs->CurrentSector.Sector[35] = (UINT8)((VolSectors >> 24) & 0xFF);
> > +
> > + TotalClusters = (VolSectors / Fs->SectorsPerCluster) + 1;
> > + Fs->FatSectors = (TotalClusters / (FAT_SECTOR_SIZE / 4)) + 1;
> > +
> > + // BPB_FATSz32
> > + Fs->CurrentSector.Sector[36] = (UINT8)((Fs->FatSectors >> 0) & 0xFF);
> > + Fs->CurrentSector.Sector[37] = (UINT8)((Fs->FatSectors >> 8) & 0xFF);
> > + Fs->CurrentSector.Sector[38] = (UINT8)((Fs->FatSectors >> 16) & 0xFF);
> > + Fs->CurrentSector.Sector[39] = (UINT8)((Fs->FatSectors >> 24) & 0xFF);
> > +
> > + // BPB_ExtFlags
> > + Fs->CurrentSector.Sector[40] = 0;
> > + Fs->CurrentSector.Sector[41] = 0;
> > +
> > + // BPB_FSVer
> > + Fs->CurrentSector.Sector[42] = 0;
> > + Fs->CurrentSector.Sector[43] = 0;
> > +
> > + // BPB_RootClus
> > + Fs->CurrentSector.Sector[44] = (UINT8)((Fs->RootdirFirstCluster >> 0) &
> > 0xFF);
> > + Fs->CurrentSector.Sector[45] = (UINT8)((Fs->RootdirFirstCluster >> 8) &
> > 0xFF);
> > + Fs->CurrentSector.Sector[46] = (UINT8)((Fs->RootdirFirstCluster >> 16)
> &
> > 0xFF);
> > + Fs->CurrentSector.Sector[47] = (UINT8)((Fs->RootdirFirstCluster >> 24)
> &
> > 0xFF);
> > +
> > + // BPB_FSInfo
> > + Fs->CurrentSector.Sector[48] = (UINT8)((Fs->FsInfoSector >> 0) & 0xFF);
> > + Fs->CurrentSector.Sector[49] = (UINT8)((Fs->FsInfoSector >> 8) & 0xFF);
> > +
> > + // BPB_BkBootSec
> > + Fs->CurrentSector.Sector[50] = 6;
> > + Fs->CurrentSector.Sector[51] = 0;
> > +
> > + // Drive number
> > + Fs->CurrentSector.Sector[64] = 0x00;
> > +
> > + // Boot signature
> > + Fs->CurrentSector.Sector[66] = 0x29;
> > +
> > + // Volume ID
> > + Fs->CurrentSector.Sector[67] = 0x12;
> > + Fs->CurrentSector.Sector[68] = 0x34;
> > + Fs->CurrentSector.Sector[69] = 0x56;
> > + Fs->CurrentSector.Sector[70] = 0x78;
> > +
> > + // Volume name
> > + for (Index = 0; Index < 11; Index++) {
> > + if (Index < (int)AsciiStrLen (Name))
> > + Fs->CurrentSector.Sector[Index + 71] = Name[Index];
> > + else
> > + Fs->CurrentSector.Sector[Index + 71] = ' ';
> > + }
> > +
> > + // File sys type
> > + Fs->CurrentSector.Sector[82] = 'F';
> > + Fs->CurrentSector.Sector[83] = 'A';
> > + Fs->CurrentSector.Sector[84] = 'T';
> > + Fs->CurrentSector.Sector[85] = '3';
> > + Fs->CurrentSector.Sector[86] = '2';
> > + Fs->CurrentSector.Sector[87] = ' ';
> > + Fs->CurrentSector.Sector[88] = ' ';
> > + Fs->CurrentSector.Sector[89] = ' ';
> > +
> > + // Signature
> > + Fs->CurrentSector.Sector[510] = 0x55;
> > + Fs->CurrentSector.Sector[511] = 0xAA;
> > + }
> > +
> > + Status = Fs->DiskIo->WriteDisk (
> > + Fs->DiskIo, Fs->BlockIo->Media->MediaId,
> > + MultU64x32 (Fs->StartingLBA, Fs->BlockIo->Media->BlockSize) +
> > + MultU64x32 (Fs->FatBeginLba, FAT_SECTOR_SIZE),
> > + FAT_SECTOR_SIZE,
> > + Fs->CurrentSector.Sector);
> > +
> > + return Status;
> > +}
> > +//-----------------------------------------------------------------------------
> > +// fatfs_create_fsinfo_sector: Create the FSInfo Sector (FAT32)
> > +//-----------------------------------------------------------------------------
> > +STATIC
> > +EFI_STATUS
> > +CreateFsinfoSector (
> > + IN FATFS *Fs,
> > + IN EFI_LBA SectorLba
> > + )
> > +{
> > + EFI_STATUS Status;
> > +
> > + // Zero Sector initially
> > + ZeroMem (Fs->CurrentSector.Sector, FAT_SECTOR_SIZE);
> > +
> > + // FSI_LeadSig
> > + Fs->CurrentSector.Sector[0] = 0x52;
> > + Fs->CurrentSector.Sector[1] = 0x52;
> > + Fs->CurrentSector.Sector[2] = 0x61;
> > + Fs->CurrentSector.Sector[3] = 0x41;
> > +
> > + // FSI_StrucSig
> > + Fs->CurrentSector.Sector[484] = 0x72;
> > + Fs->CurrentSector.Sector[485] = 0x72;
> > + Fs->CurrentSector.Sector[486] = 0x41;
> > + Fs->CurrentSector.Sector[487] = 0x61;
> > +
> > + // FSI_Free_Count
> > + Fs->CurrentSector.Sector[488] = 0xFF;
> > + Fs->CurrentSector.Sector[489] = 0xFF;
> > + Fs->CurrentSector.Sector[490] = 0xFF;
> > + Fs->CurrentSector.Sector[491] = 0xFF;
> > +
> > + // FSI_Nxt_Free
> > + Fs->CurrentSector.Sector[492] = 0xFF;
> > + Fs->CurrentSector.Sector[493] = 0xFF;
> > + Fs->CurrentSector.Sector[494] = 0xFF;
> > + Fs->CurrentSector.Sector[495] = 0xFF;
> > +
> > + // Signature
> > + Fs->CurrentSector.Sector[510] = 0x55;
> > + Fs->CurrentSector.Sector[511] = 0xAA;
> > +
> > + Status = Fs->DiskIo->WriteDisk (
> > + Fs->DiskIo, Fs->BlockIo->Media->MediaId,
> > + MultU64x32 (Fs->StartingLBA, Fs->BlockIo->Media->BlockSize) +
> > + MultU64x32 (SectorLba, FAT_SECTOR_SIZE),
> > + FAT_SECTOR_SIZE,
> > + Fs->CurrentSector.Sector);
> > +
> > + return Status;
> > +}
> > +//-----------------------------------------------------------------------------
> > +// fatfs_erase_fat: Erase FAT table using fs details in fs struct
> > +//-----------------------------------------------------------------------------
> > +STATIC
> > +EFI_STATUS
> > +EraseFat (
> > + IN FATFS *Fs,
> > + IN BOOLEAN IsFat32)
> > +{
> > + UINTN Index;
> > + EFI_STATUS Status;
> > +
> > + // Zero Sector initially
> > + ZeroMem (Fs->CurrentSector.Sector, FAT_SECTOR_SIZE);
> > +
> > + // Initialise default allocate / reserved clusters
> > + if (!IsFat32) {
> > + SET_16BIT_WORD (Fs->CurrentSector.Sector, 0, 0xFFF8);
> > + SET_16BIT_WORD (Fs->CurrentSector.Sector, 2, 0xFFFF);
> > + } else {
> > + SET_32BIT_WORD (Fs->CurrentSector.Sector, 0, 0x0FFFFFF8);
> > + SET_32BIT_WORD (Fs->CurrentSector.Sector, 4, 0xFFFFFFFF);
> > + SET_32BIT_WORD (Fs->CurrentSector.Sector, 8, 0x0FFFFFFF);
> > + }
> > +
> > + Status = Fs->DiskIo->WriteDisk (
> > + Fs->DiskIo, Fs->BlockIo->Media->MediaId,
> > + MultU64x32 (Fs->StartingLBA, Fs->BlockIo->Media->BlockSize) +
> > + MultU64x32 (Fs->FatBeginLba, FAT_SECTOR_SIZE),
> > + FAT_SECTOR_SIZE,
> > + Fs->CurrentSector.Sector);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + // Zero remaining FAT sectors
> > + ZeroMem (Fs->CurrentSector.Sector, FAT_SECTOR_SIZE);
> > + for (Index = 1; Index < Fs->FatSectors * Fs->NumOfFats; Index++) {
> > + Status = Fs->DiskIo->WriteDisk (
> > + Fs->DiskIo,
> > + Fs->BlockIo->Media->MediaId,
> > + MultU64x32 (Fs->StartingLBA, Fs->BlockIo->Media->BlockSize) +
> > + MultU64x32 ((Fs->FatBeginLba + Index), FAT_SECTOR_SIZE),
> > + FAT_SECTOR_SIZE,
> > + Fs->CurrentSector.Sector);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > + }
> > + return Status;
> > +}
> > +//-----------------------------------------------------------------------------
> > +// fatfs_format_fat16: Format a FAT16 partition
> > +//-----------------------------------------------------------------------------
> > +STATIC
> > +EFI_STATUS
> > +FormatFat16 (
> > + IN FATFS *Fs,
> > + IN UINT64 VolumeSectors,
> > + IN CONST CHAR8 *Name
> > + )
> > +{
> > + EFI_STATUS Status;
> > +
> > + Fs->CurrentSector.Address = FAT32_INVALID_CLUSTER;
> > + Fs->CurrentSector.Dirty = 0;
> > +
> > + Fs->NextFreeCluster = 0; // Invalid
> > +
> > + // Volume is FAT16
> > + Fs->FatType = FAT_TYPE_16;
> > +
> > + // Not valid for FAT16
> > + Fs->FsInfoSector = 0;
> > + Fs->RootdirFirstCluster = 0;
> > +
> > + Fs->LbaBegin = 0;
> > + Status = CreateBootSector (Fs, Fs->LbaBegin, VolumeSectors, Name, 0);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + // For FAT16 (which this may be), RootdirFirstCluster is actuall
> > RootdirFirstSector
> > + Fs->RootdirFirstSector = Fs->ReservedSectors + (Fs->NumOfFats * Fs-
> > >FatSectors);
> > + Fs->RootdirSectors = ((Fs->RootEntryCount * 32) +
> > + (FAT_SECTOR_SIZE - 1)) / FAT_SECTOR_SIZE;
> > +
> > + // First FAT LBA Address
> > + Fs->FatBeginLba = Fs->LbaBegin + Fs->ReservedSectors;
> > +
> > + // The Address of the first data cluster on this volume
> > + Fs->ClusterBeginLba = Fs->FatBeginLba +
> > + (Fs->NumOfFats * Fs->FatSectors);
> > +
> > + // Initialise FAT sectors
> > + Status = EraseFat (Fs, 0);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + // Erase Root directory
> > + Status = EraseSectors (
> > + Fs,
> > + Fs->LbaBegin + Fs->RootdirFirstSector,
> > + Fs->RootdirSectors);
> > +
> > + return Status;
> > +}
> > +//-----------------------------------------------------------------------------
> > +// fatfs_format_fat32: Format a FAT32 partition
> > +//-----------------------------------------------------------------------------
> > +STATIC
> > +EFI_STATUS
> > +FormatFat32 (
> > + IN FATFS *Fs,
> > + IN UINTN VolumeSectors,
> > + IN CONST CHAR8 *Name
> > + )
> > +{
> > + EFI_STATUS Status;
> > +
> > + Fs->CurrentSector.Address = FAT32_INVALID_CLUSTER;
> > + Fs->CurrentSector.Dirty = 0;
> > +
> > + Fs->NextFreeCluster = 0; // Invalid
> > +
> > + // Volume is FAT32
> > + Fs->FatType = FAT_TYPE_32;
> > +
> > + // Basic defaults for normal FAT32 partitions
> > + Fs->FsInfoSector = 1;
> > + Fs->RootdirFirstCluster = 2;
> > +
> > + // Sector 0: Boot Sector
> > + // NOTE: We don't need an MBR, it is a waste of a good Sector!
> > + Fs->LbaBegin = 0;
> > + Status = CreateBootSector (Fs, Fs->LbaBegin, VolumeSectors, Name, 1);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + // First FAT LBA address
> > + Fs->FatBeginLba = Fs->LbaBegin + Fs->ReservedSectors;
> > +
> > + // The address of the first data cluster on this volume
> > + Fs->ClusterBeginLba = Fs->FatBeginLba + (Fs->NumOfFats * Fs-
> > >FatSectors);
> > +
> > + // Initialise FSInfo sector
> > + Status = CreateFsinfoSector (Fs, Fs->FsInfoSector);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + // Initialise FAT sectors
> > + Status = EraseFat (Fs, 1);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + // Erase Root directory
> > + Status = EraseSectors (
> > + Fs,
> > + LbaOfCluster (Fs, Fs->RootdirFirstCluster),
> > + Fs->SectorsPerCluster);
> > +
> > + return Status;
> > +}
> > +//-----------------------------------------------------------------------------
> > +// fatfs_format: Format a partition with either FAT16 or FAT32 based on
> size
> > +//-----------------------------------------------------------------------------
> > +EFI_STATUS
> > +FatFormat (
> > + IN EFI_LBA StartingLBA,
> > + IN EFI_LBA EndingLBA,
> > + IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
> > + IN EFI_DISK_IO_PROTOCOL *DiskIo,
> > + IN CHAR8 *VolumeName,
> > + IN BOOLEAN ForceFat32
> > + )
> > +{
> > + FATFS Fs;
> > + UINT64 VolumeSectors;
> > +
> > + VolumeSectors = DivU64x32 (
> > + MultU64x32 (
> > + EndingLBA - StartingLBA + 1, BlockIo->Media->BlockSize),
> > + FAT_SECTOR_SIZE);
> > +
> > + if (VolumeName == NULL) {
> > + VolumeName = DEFAULT_FAT_LABEL_NAME;
> > + }
> > +
> > + ZeroMem (&Fs, sizeof(Fs));
> > +
> > + Fs.StartingLBA = StartingLBA;
> > + Fs.EndingLBA = EndingLBA;
> > + Fs.BlockIo = BlockIo;
> > + Fs.DiskIo = DiskIo;
> > + // 2GB - 32K limit for safe behaviour for FAT16
> > + if ((VolumeSectors <= 4194304) && (!ForceFat32)) {
> > + return FormatFat16 (&Fs, VolumeSectors, VolumeName);
> > + } else {
> > + return FormatFat32 (&Fs, VolumeSectors, VolumeName);
> > + }
> > +}
> > diff --git a/ShellPkg/Library/UefiShellGptCommandLib/FatFormat.h
> > b/ShellPkg/Library/UefiShellGptCommandLib/FatFormat.h
> > new file mode 100644
> > index 000000000000..d1a325a57abe
> > --- /dev/null
> > +++ b/ShellPkg/Library/UefiShellGptCommandLib/FatFormat.h
> > @@ -0,0 +1,111 @@
> > +/** @file
> > +
> > + Copyright (c) 2003 - 2012, Ultra-Embedded.com. 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.
> > +
> > +**/
> > +
> > +/* Portions Copyright (c) 2016, Broadcom. All rights reserved */
> > +
> > +#ifndef __FAT_FORMAT_H__
> > +#define __FAT_FORMAT_H__
> > +
> > +#include "GptWorker.h"
> > +
> > +#define FAT_SECTOR_SIZE 512
> > +#define FAT_BUFFER_SECTORS 1
> > +#define FAT32_LAST_CLUSTER 0xFFFFFFFF
> > +#define FAT32_INVALID_CLUSTER 0xFFFFFFFF
> > +#define FAT_DIR_ENTRY_SIZE 32
> > +#define FAT_BUFFERS 1
> > +#define DEFAULT_FAT_LABEL_NAME "EFIVOL"
> > +
> > +#define GET_32BIT_WORD(Buffer, Location)
> > ( ((UINT32)Buffer[Location + 3] << 24) + \
> > + ((UINT32)Buffer[Location + 2] <<16 ) + \
> > + ((UINT32)Buffer[Location + 1] << 8) + \
> > + (UINT32)Buffer[Location+0] )
> > +
> > +#define GET_16BIT_WORD(Buffer, Location)
> > ( ((UINT16)Buffer[Location + 1] << 8) + \
> > + (UINT16)Buffer[Location+0])
> > +
> > +#define SET_32BIT_WORD(Buffer, Location, Value) { Buffer[Location + 0]
> =
> > (UINT8)((Value) & 0xFF); \
> > + Buffer[Location + 1] = (UINT8)((Value >> 8) &
> 0xFF);
> > \
> > + Buffer[Location + 2] = (UINT8)((Value >> 16) &
> > 0xFF); \
> > + Buffer[Location + 3] = (UINT8)((Value >> 24) &
> > 0xFF); }
> > +
> > +#define SET_16BIT_WORD(Buffer, Location, Value) { Buffer[Location + 0]
> =
> > (UINT8)((Value) & 0xFF); \
> > + Buffer[Location + 1] = (UINT8)((Value >> 8) &
> > 0xFF); }
> > +
> > +typedef enum eFatType
> > +{
> > + FAT_TYPE_16,
> > + FAT_TYPE_32
> > +} FAT_FS_TYPE;
> > +
> > +
> > +// Forward declaration
> > +typedef struct _FAT_BUFFER FAT_BUFFER;
> > +
> > +struct _FAT_BUFFER {
> > + UINT8 Sector[FAT_SECTOR_SIZE * FAT_BUFFER_SECTORS];
> > + UINTN Address;
> > + BOOLEAN Dirty;
> > + UINT8 *Ptr;
> > +
> > + // Next in chain of sector buffers
> > + struct FAT_BUFFER *NextBuf;
> > +};
> > +
> > +typedef struct
> > +{
> > + // Filesystem globals
> > + UINT8 SectorsPerCluster;
> > + EFI_LBA ClusterBeginLba;
> > + UINTN RootdirFirstCluster;
> > + UINTN RootdirFirstSector;
> > + UINTN RootdirSectors;
> > + EFI_LBA FatBeginLba;
> > + UINT16 FsInfoSector;
> > + EFI_LBA LbaBegin;
> > + UINTN FatSectors;
> > + UINTN NextFreeCluster;
> > + UINT16 RootEntryCount;
> > + UINT16 ReservedSectors;
> > + UINT8 NumOfFats;
> > + FAT_FS_TYPE FatType;
> > +
> > + // Working buffer
> > + FAT_BUFFER CurrentSector;
> > + // FAT Buffer
> > + FAT_BUFFER *FatBufferHead;
> > + FAT_BUFFER FatBuffers[FAT_BUFFERS];
> > + EFI_LBA StartingLBA;
> > + EFI_LBA EndingLBA;
> > + EFI_BLOCK_IO_PROTOCOL *BlockIo;
> > + EFI_DISK_IO_PROTOCOL *DiskIo;
> > +
> > +} FATFS;
> > +
> > +
> > +
> > +//-----------------------------------------------------------------------------
> > +// Prototypes
> > +//-----------------------------------------------------------------------------
> > +EFI_STATUS
> > +FatFormat (
> > + IN EFI_LBA StartingLBA,
> > + IN EFI_LBA EndingLBA,
> > + IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
> > + IN EFI_DISK_IO_PROTOCOL *DiskIo,
> > + IN CHAR8 *VolumeName,
> > + IN BOOLEAN ForceFat32
> > + );
> > +
> > +#endif
> > diff --git a/ShellPkg/Library/UefiShellGptCommandLib/GptWorker.c
> > b/ShellPkg/Library/UefiShellGptCommandLib/GptWorker.c
> > new file mode 100644
> > index 000000000000..0546c94488b0
> > --- /dev/null
> > +++ b/ShellPkg/Library/UefiShellGptCommandLib/GptWorker.c
> > @@ -0,0 +1,1902 @@
> > +/** @file
> > +Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2016, Broadcom. 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 "GptWorker.h"
> > +
> > +#define GPT_DEBUG_LEVEL 0
> > +
> > +STATIC EFI_PARTITION_TABLE_HEADER *PrimaryHeader = NULL;
> > +STATIC EFI_PARTITION_TABLE_HEADER *BackupHeader = NULL;
> > +STATIC EFI_PARTITION_ENTRY *PartEntry = NULL;
> > +STATIC EFI_PARTITION_ENTRY_STATUS *PEntryStatus = NULL;
> > +
> > +STATIC EFI_BLOCK_IO_PROTOCOL *BlockIo;
> > +STATIC EFI_DISK_IO_PROTOCOL *DiskIo;
> > +
> > +STATIC BOOLEAN MbrValid;
> > +STATIC BOOLEAN GptValid;
> > +
> > +STATIC EFI_KNOWN_PARTITION_TYPE PartitionTypes[] =
> > +{
> > + // Known Partition type GUIDs
> > + // Expand this table as needed.
> > + // Starting with EFI System partition
> > + { { 0xC12A7328L, 0xF81F, 0x11D2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E,
> 0xC9,
> > 0x3B } }, L"EFI System" },
> > + // Known Windows partition types
> > + { { 0xE3C9E316L, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02,
> 0x15,
> > 0xAE } }, L"MS Windows Reserved (MSR)" },
> > + { { 0xEBD0A0A2L, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26,
> 0x99,
> > 0xC7 } }, L"MS Windows Basic Data" },
> > + { { 0x5808C8AAL, 0x7E8F, 0x42E0, { 0x85, 0xD2, 0xE1, 0xE9, 0x04, 0x34,
> 0xCF,
> > 0xB3 } }, L"MS Windows LDM Metadata" },
> > + { { 0xAF9B60A0L, 0x1431, 0x4F62, { 0xBC, 0x68, 0x33, 0x11, 0x71, 0x4A,
> 0x69,
> > 0xAD } }, L"MS Windows LDM Data" },
> > + { { 0xDE94BBA4L, 0x06D1, 0x4D40, { 0xA1, 0x6A, 0xBF, 0xD5, 0x01, 0x79,
> > 0xD6, 0xAC } }, L"MS Windows Recovery Environment" },
> > + { { 0xE75CAF8FL, 0xF680, 0x4CEE, { 0xAF, 0xA3, 0xB0, 0x01, 0xE5, 0x6E,
> 0xFC,
> > 0x2D } }, L"MS Windows Storage Spaces" },
> > + // Known Linux partition types
> > + { { 0x0FC63DAFL, 0x8483, 0x4772, { 0x8E, 0x79, 0x3D, 0x69, 0xD8, 0x47,
> 0x7D,
> > 0xE4 } }, L"Linux Filesystem Data" },
> > + { { 0xA19D880FL, 0x05FC, 0x4D3B, { 0xA0, 0x06, 0x74, 0x3F, 0x0F, 0x84,
> 0x91,
> > 0x1E } }, L"Linux RAID" },
> > + { { 0x44479540L, 0xF297, 0x41B2, { 0x9A, 0xF7, 0xD1, 0x31, 0xD5, 0xF0,
> 0x45,
> > 0x8A } }, L"Linux Root (x86)" },
> > + { { 0x4F68BCE3L, 0xE8CD, 0x4DB1, { 0x96, 0xE7, 0xFB, 0xCA, 0xF9, 0x84,
> 0xB7,
> > 0x09 } }, L"Linux Root (x86-64)" },
> > + { { 0x69DAD710L, 0x2CE4, 0x4E3C, { 0xB1, 0x6C, 0x21, 0xA1, 0xD4, 0x9A,
> > 0xBe, 0xD3 } }, L"Linux Root (ARM 32-bit)" },
> > + { { 0xB921B045L, 0x1DF0, 0x41C3, { 0xAF, 0x44, 0x4C, 0x6F, 0x28, 0x0D,
> 0x3F,
> > 0xAE } }, L"Linux Root (ARM 64-bit/AARCH64)" },
> > + { { 0x0657FD6DL, 0xA4AB, 0x43C4, { 0x84, 0xE5, 0x09, 0x33, 0xC8, 0x4B,
> 0x4F,
> > 0x4F } }, L"Linux Swap" },
> > + { { 0xE6D6D379L, 0xF507, 0x44C2, { 0xA2, 0x3C, 0x23, 0x8F, 0x2A, 0x3D,
> 0xF9,
> > 0x28 } }, L"Linux Logical Volume Manager (LVM)" },
> > + { { 0x933AC7E1L, 0x2EB4, 0x4F13, { 0xB8, 0x44, 0x0E, 0x14, 0xE2, 0xAE,
> 0xF9,
> > 0x15 } }, L"Linux /home" },
> > + { { 0x3B8F8425L, 0x20E0, 0x4F3B, { 0x90, 0x7F, 0x1A, 0x25, 0xA7, 0x6F,
> 0x98,
> > 0xE8 } }, L"Linux /srv (server data)" },
> > + { { 0x7FFEC5C9L, 0x2D00, 0x49B7, { 0x89, 0x41, 0x3E, 0xA1, 0x0A, 0x55,
> 0x86,
> > 0xB7 } }, L"Linux Plain dm-crypt" },
> > + { { 0xCA7D7CCBL, 0x63ED, 0x4C53, { 0x86, 0x1C, 0x17, 0x42, 0x53, 0x60,
> 0x59,
> > 0xCC } }, L"Linux LUKS" },
> > + { { 0x8DA63339L, 0x0007, 0x60C0, { 0xC4, 0x36, 0x08, 0x3A, 0xC8, 0x23,
> 0x09,
> > 0x08 } }, L"Linux Reserved" },
> > +};
> > +
> > +MASTER_BOOT_RECORD ProtectiveMbrTemplate = {
> > + { 0 }, // BoostStrapCode [440]
> > + { 0 }, // UniqueMbrSignature[4] (unused)
> > + { 0 }, // Unknown[2]
> > +
> > + // PARTITIONS
> > + {
> > + // MBR_PARTITION_RECORD
> > + {
> > + 0, // BootIndicator
> > + 0, // StartHead
> > + 0x1, // StartSector
> > + 0x1, // StartTrack
> > + PMBR_GPT_PARTITION, // OSIndicator
> > + 0xff, // EndHead
> > + 0xff, // EndSector
> > + 0xff, // EndTrack
> > + { 0x1, 0x0, 0x0, 0x0 }, // StartingLba[4]
> > + { 0xff, 0xff, 0xff, 0xff }, // SizeInLba[4]
> > + },
> > + { 0 }, { 0 }, { 0 }, // Unused partitions
> > + },
> > +
> > + MBR_SIGNATURE // Signature
> > +};
> > +
> > +STATIC UINT32 CurRand = 1;
> > +
> > +/**
> > + Get random seed based on the RTC
> > +
> > +**/
> > +
> > +STATIC
> > +VOID
> > +Srand (VOID)
> > +{
> > + EFI_TIME Time;
> > + UINT32 Seed;
> > + UINT64 MonotonicCount;
> > +
> > + gRT->GetTime (&Time, NULL);
> > + Seed = (~Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 |
> > Time.Second);
> > + Seed ^= Time.Nanosecond;
> > + Seed ^= Time.Year << 7;
> > +
> > + gBS->GetNextMonotonicCount (&MonotonicCount);
> > + Seed += (UINT32)MonotonicCount;
> > +
> > + /* Store this seed */
> > + CurRand = (UINT32)Seed;
> > +}
> > +
> > +/**
> > + Get a pseudo-random number
> > +
> > + @retval A pseudo-random number in the range 0 - 0x7fff
> > +**/
> > +
> > +STATIC UINTN Rand (VOID)
> > +{
> > + /* return a pseudo-random in range 0 - 0x7fff */
> > + return ((CurRand = CurRand * 214013L + 2531011L) >> 16) & 0x7fff;
> > +}
> > +
> > +/**
> > + Generate a GUID
> > +
> > + @param[in] Guid A pointer to a GUID receiving a generated value
> > +**/
> > +
> > +STATIC VOID
> > +GenerateGuid (OUT GUID *Guid)
> > +{
> > + UINTN Index;
> > + UINT16 Buffer[sizeof(GUID)];
> > +
> > + /* Generates 128 random bits for new UUID */
> > + for (Index = 0; Index < sizeof(GUID); Index++) {
> > + UINTN V;
> > +
> > + V = Rand () >> 7;
> > + Buffer[Index] = (UINT16)V;
> > + }
> > + /* set variant 10x and version 4 as required by RFC 4122 */
> > + Buffer[8] = 0x80 | (Buffer[8] & 0x3f);
> > + Buffer[6] = 0x40 | (Buffer[6] & 0xf);
> > + CopyGuid (Guid, (CONST GUID *)Buffer);
> > +}
> > +
> > +/**
> > + Clean up globals
> > +**/
> > +VOID
> > +GptCleanupGlobals (VOID)
> > +{
> > + SHELL_FREE_NON_NULL (PrimaryHeader);
> > + SHELL_FREE_NON_NULL (BackupHeader);
> > + SHELL_FREE_NON_NULL (PartEntry);
> > + SHELL_FREE_NON_NULL (PEntryStatus);
> > + GptValid = FALSE;
> > + MbrValid = FALSE;
> > +}
> > +
> > +/**
> > + Caution: This function may receive untrusted input.
> > + The GPT partition table header is external input, so this routine
> > + will do basic validation for GPT partition table header before return.
> > +
> > + @param[in] Lba The starting Lba of the Partition Table
> > + @param[out] PartHeader Stores the partition table that is read
> > +
> > + @retval EFI_SUCCESS The partition table is valid
> > + @retval ERROR The partition table is not valid
> > +
> > +**/
> > +STATIC
> > +EFI_STATUS
> > +PartitionValidGptTable (
> > + IN EFI_LBA Lba,
> > + OUT EFI_PARTITION_TABLE_HEADER *PartHeader
> > + );
> > +
> > +/**
> > + Check if the CRC field in the Partition table header is valid
> > + for Partition entry array.
> > +
> > + @param[in] PartHeader Partition table header structure
> > +
> > + @retval TRUE the CRC is valid
> > + @retval FALSE the CRC is invalid
> > +
> > +**/
> > +STATIC
> > +BOOLEAN
> > +PartitionCheckGptEntryArrayCRC (
> > + IN EFI_PARTITION_TABLE_HEADER *PartHeader
> > + );
> > +
> > +
> > +/**
> > + Restore Partition Table to its alternate place
> > + (Primary -> Backup or Backup -> Primary).
> > +
> > + @param[in] PartHeader Partition table header structure.
> > +
> > + @retval TRUE Restoring succeeds
> > + @retval FALSE Restoring failed
> > +
> > +**/
> > +STATIC
> > +BOOLEAN
> > +PartitionRestoreGptTable (
> > + IN EFI_PARTITION_TABLE_HEADER *PartHeader
> > + );
> > +
> > +
> > +/**
> > + This routine will check GPT partition entry and return entry status.
> > +
> > + Caution: This function may receive untrusted input.
> > + The GPT partition entry is external input, so this routine
> > + will do basic validation for GPT partition entry and report status.
> > +
> > + @param[in] PartHeader Partition table header structure
> > + @param[in] PartEntry The partition entry array
> > + @param[out] PEntryStatus the partition entry status array
> > + recording the status of each partition
> > +
> > +**/
> > +STATIC
> > +VOID
> > +PartitionCheckGptEntry (
> > + IN EFI_PARTITION_TABLE_HEADER *PartHeader,
> > + IN EFI_PARTITION_ENTRY *PartEntry,
> > + OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
> > + );
> > +
> > +
> > +/**
> > + Checks the CRC32 value in the table header.
> > +
> > + @param MaxSize Max Size limit
> > + @param Size The size of the table
> > + @param Hdr Table to check
> > +
> > + @return TRUE CRC Valid
> > + @return FALSE CRC Invalid
> > +
> > +**/
> > +STATIC
> > +BOOLEAN
> > +PartitionCheckCrcAltSize (
> > + IN UINTN MaxSize,
> > + IN UINTN Size,
> > + IN OUT EFI_TABLE_HEADER *Hdr
> > + );
> > +
> > +
> > +/**
> > + Checks the CRC32 value in the table header.
> > +
> > + @param MaxSize Max Size limit
> > + @param Hdr Table to check
> > +
> > + @return TRUE CRC Valid
> > + @return FALSE CRC Invalid
> > +
> > +**/
> > +STATIC
> > +BOOLEAN
> > +PartitionCheckCrc (
> > + IN UINTN MaxSize,
> > + IN OUT EFI_TABLE_HEADER *Hdr
> > + );
> > +
> > +
> > +/**
> > + Updates the CRC32 value in the table header.
> > +
> > + @param Size The size of the table
> > + @param Hdr Table to update
> > +
> > +**/
> > +STATIC
> > +VOID
> > +PartitionSetCrcAltSize (
> > + IN UINTN Size,
> > + IN OUT EFI_TABLE_HEADER *Hdr
> > + );
> > +
> > +
> > +/**
> > + Updates the CRC32 value in the table header.
> > +
> > + @param Hdr Table to update
> > +
> > +**/
> > +STATIC
> > +VOID
> > +PartitionSetCrc (
> > + IN OUT EFI_TABLE_HEADER *Hdr
> > + );
> > +
> > +
> > +/**
> > + Get GPT tables.
> > +
> > + Caution: This function may receive untrusted input.
> > + The GPT partition table is external input, so this routine
> > + will do basic validation for GPT partition table before install
> > + child handle for each GPT partition.
> > +
> > + @param[in] DiskIoProt DiskIo interface.
> > + @param[in] BlockIoProt BlockIo interface.
> > +
> > + @retval EFI_SUCCESS Valid GPT disk.
> > + @retval EFI_MEDIA_CHANGED Media changed Detected.
> > + @retval other Not a valid GPT disk.
> > +
> > +**/
> > +EFI_STATUS
> > +PartitionGetGptTables (
> > + IN EFI_DISK_IO_PROTOCOL *DiskIoProt,
> > + IN EFI_BLOCK_IO_PROTOCOL *BlockIoProt
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT32 BlockSize;
> > + EFI_LBA LastBlock;
> > + UINTN Index;
> > + EFI_STATUS GptValidStatus;
> > + UINT32 MediaId;
> > + MASTER_BOOT_RECORD *ProtectiveMbr;
> > +
> > + // Clear leftovers
> > + GptCleanupGlobals ();
> > +
> > + MbrValid = FALSE;
> > + GptValid = FALSE;
> > +
> > + ProtectiveMbr = NULL;
> > +
> > + BlockIo = BlockIoProt;
> > + DiskIo = DiskIoProt;
> > +
> > + if (CurRand == 1) {
> > + Srand ();
> > + }
> > +
> > + BlockSize = BlockIo->Media->BlockSize;
> > + LastBlock = BlockIo->Media->LastBlock;
> > + MediaId = BlockIo->Media->MediaId;
> > +
> > + DEBUG ((EFI_D_VERBOSE, " BlockSize : %d \n", BlockSize));
> > + DEBUG ((EFI_D_VERBOSE, " LastBlock : %lx \n", LastBlock));
> > +
> > + GptValidStatus = EFI_NOT_FOUND;
> > + GptValid = FALSE;
> > + MbrValid = FALSE;
> > +
> > + //
> > + // Allocate a buffer for the Protective MBR
> > + //
> > + ProtectiveMbr = AllocatePool (BlockSize);
> > + if (ProtectiveMbr == NULL) {
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > +
> > + //
> > + // Read the Protective MBR from LBA #0
> > + //
> > + Status = DiskIo->ReadDisk (
> > + DiskIo,
> > + MediaId,
> > + 0,
> > + BlockSize,
> > + ProtectiveMbr
> > + );
> > + if (EFI_ERROR (Status)) {
> > + GptValidStatus = Status;
> > + goto Done;
> > + }
> > +
> > + //
> > + // Verify that the Protective MBR is valid
> > + //
> > + for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
> > + if (ProtectiveMbr->Partition[Index].BootIndicator == 0x00 &&
> > + ProtectiveMbr->Partition[Index].OSIndicator ==
> > PMBR_GPT_PARTITION &&
> > + UNPACK_UINT32 (ProtectiveMbr->Partition[Index].StartingLBA) == 1
> > + ) {
> > + break;
> > + }
> > + }
> > + if (Index == MAX_MBR_PARTITIONS) {
> > + goto Done;
> > + }
> > +
> > + MbrValid = TRUE;
> > +
> > + //
> > + // Allocate the GPT structures
> > + //
> > + PrimaryHeader = AllocateZeroPool
> > (sizeof(EFI_PARTITION_TABLE_HEADER));
> > + if (PrimaryHeader == NULL) {
> > + goto Done;
> > + }
> > +
> > + BackupHeader = AllocateZeroPool
> > (sizeof(EFI_PARTITION_TABLE_HEADER));
> > + if (BackupHeader == NULL) {
> > + goto Done;
> > + }
> > +
> > + //
> > + // Check primary and backup partition tables
> > + //
> > + Status = PartitionValidGptTable (PRIMARY_PART_HEADER_LBA,
> > PrimaryHeader);
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n"));
> > +
> > + Status = PartitionValidGptTable (LastBlock, BackupHeader);
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n"));
> > + goto Done;
> > + } else {
> > + DEBUG ((EFI_D_INFO, " Valid backup partition table\n"));
> > + DEBUG ((EFI_D_INFO, " Restore primary partition table by the
> > backup\n"));
> > + if (!PartitionRestoreGptTable (BackupHeader)) {
> > + DEBUG ((EFI_D_INFO, " Restore primary partition table error\n"));
> > + }
> > +
> > + Status = PartitionValidGptTable (BackupHeader->AlternateLBA,
> > PrimaryHeader);
> > + if (!EFI_ERROR (Status)) {
> > + DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));
> > + }
> > + }
> > + } else if (EFI_ERROR (PartitionValidGptTable (PrimaryHeader-
> > >AlternateLBA, BackupHeader))) {
> > + DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition
> > table\n"));
> > + DEBUG ((EFI_D_INFO, " Restore backup partition table by the
> > primary\n"));
> > + if (!PartitionRestoreGptTable (PrimaryHeader)) {
> > + DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));
> > + }
> > +
> > + Status = PartitionValidGptTable (PrimaryHeader->AlternateLBA,
> > BackupHeader);
> > + if (!EFI_ERROR (Status)) {
> > + DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));
> > + }
> > + }
> > +
> > + DEBUG ((EFI_D_VERBOSE, " Valid primary and Valid backup partition
> > table\n"));
> > +
> > + //
> > + // Read the EFI Partition Entries
> > + //
> > + PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries *
> > PrimaryHeader->SizeOfPartitionEntry);
> > + if (PartEntry == NULL) {
> > + DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
> > + goto Done;
> > + }
> > +
> > + Status = DiskIo->ReadDisk (
> > + DiskIo,
> > + MediaId,
> > + MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockSize),
> > + PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader-
> > >SizeOfPartitionEntry),
> > + PartEntry
> > + );
> > + if (EFI_ERROR (Status)) {
> > + GptValidStatus = Status;
> > + DEBUG ((EFI_D_ERROR, " Partition Entry ReadDisk error\n"));
> > + goto Done;
> > + }
> > +
> > + DEBUG ((EFI_D_VERBOSE, " Partition entries read block success\n"));
> > +
> > + DEBUG ((EFI_D_VERBOSE, " Number of partition entries: %d\n",
> > PrimaryHeader->NumberOfPartitionEntries));
> > +
> > + PEntryStatus = AllocateZeroPool (PrimaryHeader-
> > >NumberOfPartitionEntries * sizeof(EFI_PARTITION_ENTRY_STATUS));
> > + if (PEntryStatus == NULL) {
> > + DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
> > + goto Done;
> > + }
> > +
> > + //
> > + // Check the integrity of partition entries
> > + //
> > + PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus);
> > +
> > + //
> > + // If we got this far the GPT layout of the disk is valid and we should
> return
> > true
> > + //
> > + GptValidStatus = EFI_SUCCESS;
> > +
> > + Done:
> > + SHELL_FREE_NON_NULL (ProtectiveMbr);
> > + if (EFI_ERROR (GptValidStatus)) {
> > + SHELL_FREE_NON_NULL (PrimaryHeader);
> > + SHELL_FREE_NON_NULL (BackupHeader);
> > + SHELL_FREE_NON_NULL (PartEntry);
> > + SHELL_FREE_NON_NULL (PEntryStatus);
> > + } else {
> > + GptValid = TRUE;
> > + }
> > +
> > + return GptValidStatus;
> > +}
> > +
> > +/**
> > + This routine will read GPT partition table header and return it.
> > +
> > + Caution: This function may receive untrusted input.
> > + The GPT partition table header is external input, so this routine
> > + will do basic validation for GPT partition table header before return.
> > +
> > + @param[in] Lba The starting Lba of the Partition Table
> > + @param[out] PartHeader Stores the partition table that is read
> > +
> > + @retval TRUE The partition table is valid
> > + @retval FALSE The partition table is not valid
> > +
> > +**/
> > +STATIC
> > +EFI_STATUS
> > +PartitionValidGptTable (
> > + IN EFI_LBA Lba,
> > + OUT EFI_PARTITION_TABLE_HEADER *PartHeader
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT32 BlockSize;
> > + EFI_PARTITION_TABLE_HEADER *PartHdr;
> > + UINT32 MediaId;
> > +
> > + BlockSize = BlockIo->Media->BlockSize;
> > + MediaId = BlockIo->Media->MediaId;
> > + PartHdr = AllocateZeroPool (BlockSize);
> > +
> > + if (PartHdr == NULL) {
> > + DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > + //
> > + // Read the EFI Partition Table Header
> > + //
> > + Status = DiskIo->ReadDisk (
> > + DiskIo,
> > + MediaId,
> > + MultU64x32 (Lba, BlockSize),
> > + BlockSize,
> > + PartHdr
> > + );
> > + if (EFI_ERROR (Status)) {
> > + FreePool (PartHdr);
> > + return Status;
> > + }
> > +
> > + if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||
> > + !PartitionCheckCrc (BlockSize, &PartHdr->Header) ||
> > + PartHdr->MyLBA != Lba ||
> > + (PartHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY))
> > + ) {
> > + DEBUG ((EFI_D_ERROR, "Invalid efi partition table header\n"));
> > + FreePool (PartHdr);
> > + return EFI_VOLUME_CORRUPTED;
> > + }
> > +
> > + //
> > + // Ensure the NumberOfPartitionEntries * SizeOfPartitionEntry doesn't
> > overflow.
> > + //
> > + if (PartHdr->NumberOfPartitionEntries > DivU64x32 (MAX_UINTN,
> > PartHdr->SizeOfPartitionEntry)) {
> > + FreePool (PartHdr);
> > + return EFI_VOLUME_CORRUPTED;
> > + }
> > +
> > + CopyMem (PartHeader, PartHdr,
> sizeof(EFI_PARTITION_TABLE_HEADER));
> > + if (!PartitionCheckGptEntryArrayCRC (PartHeader)) {
> > + FreePool (PartHdr);
> > + return EFI_VOLUME_CORRUPTED;
> > + }
> > +
> > + DEBUG ((EFI_D_VERBOSE, " Valid efi partition table header\n"));
> > + FreePool (PartHdr);
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + Check if the CRC field in the Partition table header is valid
> > + for Partition entry array.
> > +
> > + @param[in] PartHeader Partition table header structure
> > +
> > + @retval TRUE the CRC is valid
> > + @retval FALSE the CRC is invalid
> > +
> > +**/
> > +STATIC
> > +BOOLEAN
> > +PartitionCheckGptEntryArrayCRC (
> > + IN EFI_PARTITION_TABLE_HEADER *PartHeader
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT8 *Ptr;
> > + UINT32 Crc;
> > + UINTN Size;
> > +
> > + //
> > + // Read the EFI Partition Entries
> > + //
> > + Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries *
> PartHeader-
> > >SizeOfPartitionEntry);
> > + if (Ptr == NULL) {
> > + DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));
> > + return FALSE;
> > + }
> > +
> > + Status = DiskIo->ReadDisk (
> > + DiskIo,
> > + BlockIo->Media->MediaId,
> > + MultU64x32 (PartHeader->PartitionEntryLBA, BlockIo->Media-
> >BlockSize),
> > + PartHeader->NumberOfPartitionEntries * PartHeader-
> > >SizeOfPartitionEntry,
> > + Ptr
> > + );
> > + if (EFI_ERROR (Status)) {
> > + FreePool (Ptr);
> > + return FALSE;
> > + }
> > +
> > + Size = PartHeader->NumberOfPartitionEntries * PartHeader-
> > >SizeOfPartitionEntry;
> > +
> > + Status = gBS->CalculateCrc32 (Ptr, Size, &Crc);
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((EFI_D_ERROR, "CheckPEntryArrayCRC: Crc calculation
> failed\n"));
> > + FreePool (Ptr);
> > + return FALSE;
> > + }
> > +
> > + FreePool (Ptr);
> > +
> > + return (BOOLEAN)(PartHeader->PartitionEntryArrayCRC32 == Crc);
> > +}
> > +
> > +
> > +/**
> > + Restore Partition Table to its alternate place
> > + (Primary -> Backup or Backup -> Primary).
> > +
> > + @param[in] PartHeader Partition table header structure.
> > +
> > + @retval TRUE Restoring succeeds
> > + @retval FALSE Restoring failed
> > +
> > +**/
> > +STATIC
> > +BOOLEAN
> > +PartitionRestoreGptTable (
> > + IN EFI_PARTITION_TABLE_HEADER *PartHeader
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINTN BlockSize;
> > + EFI_PARTITION_TABLE_HEADER *PartHdr;
> > + EFI_LBA PEntryLBA;
> > + UINT8 *Ptr;
> > + UINT32 MediaId;
> > +
> > + PartHdr = NULL;
> > + Ptr = NULL;
> > +
> > + BlockSize = BlockIo->Media->BlockSize;
> > + MediaId = BlockIo->Media->MediaId;
> > +
> > + PartHdr = AllocateZeroPool (BlockSize);
> > +
> > + if (PartHdr == NULL) {
> > + DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
> > + return FALSE;
> > + }
> > +
> > + PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ?\
> > + (PartHeader->LastUsableLBA + 1) :\
> > + (PRIMARY_PART_HEADER_LBA + 1);
> > +
> > + CopyMem (PartHdr, PartHeader,
> sizeof(EFI_PARTITION_TABLE_HEADER));
> > +
> > + PartHdr->MyLBA = PartHeader->AlternateLBA;
> > + PartHdr->AlternateLBA = PartHeader->MyLBA;
> > + PartHdr->PartitionEntryLBA = PEntryLBA;
> > + PartitionSetCrc ((EFI_TABLE_HEADER *)PartHdr);
> > +
> > + Status = DiskIo->WriteDisk (
> > + DiskIo,
> > + MediaId,
> > + MultU64x32 (PartHdr->MyLBA, (UINT32)BlockSize),
> > + BlockSize,
> > + PartHdr
> > + );
> > + if (EFI_ERROR (Status)) {
> > + goto Done;
> > + }
> > +
> > + Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries *
> PartHeader-
> > >SizeOfPartitionEntry);
> > + if (Ptr == NULL) {
> > + DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));
> > + Status = EFI_OUT_OF_RESOURCES;
> > + goto Done;
> > + }
> > +
> > + Status = DiskIo->ReadDisk (
> > + DiskIo,
> > + MediaId,
> > + MultU64x32 (PartHeader->PartitionEntryLBA, (UINT32)BlockSize),
> > + PartHeader->NumberOfPartitionEntries * PartHeader-
> > >SizeOfPartitionEntry,
> > + Ptr
> > + );
> > + if (EFI_ERROR (Status)) {
> > + goto Done;
> > + }
> > +
> > + Status = DiskIo->WriteDisk (
> > + DiskIo,
> > + MediaId,
> > + MultU64x32 (PEntryLBA, (UINT32)BlockSize),
> > + PartHeader->NumberOfPartitionEntries * PartHeader-
> > >SizeOfPartitionEntry,
> > + Ptr
> > + );
> > +
> > + Done:
> > + FreePool (PartHdr);
> > +
> > + if (Ptr != NULL) {
> > + FreePool (Ptr);
> > + }
> > +
> > + if (EFI_ERROR (Status)) {
> > + return FALSE;
> > + }
> > +
> > + return TRUE;
> > +}
> > +
> > +/**
> > + This routine will check GPT partition entry and return entry status.
> > +
> > + Caution: This function may receive untrusted input.
> > + The GPT partition entry is external input, so this routine
> > + will do basic validation for GPT partition entry and report status.
> > +
> > + @param[in] PartHeader Partition table header structure
> > + @param[in] PartEntry The partition entry array
> > + @param[out] PEntryStatus the partition entry status array
> > + recording the status of each partition
> > +
> > +**/
> > +STATIC
> > +VOID
> > +PartitionCheckGptEntry (
> > + IN EFI_PARTITION_TABLE_HEADER *PartHeader,
> > + IN EFI_PARTITION_ENTRY *PartEntry,
> > + OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
> > + )
> > +{
> > + EFI_LBA StartingLBA;
> > + EFI_LBA EndingLBA;
> > + EFI_PARTITION_ENTRY *Entry;
> > + UINTN Index1;
> > + UINTN Index2;
> > +
> > + DEBUG ((EFI_D_VERBOSE, " start check partition entries\n"));
> > + for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries;
> > Index1++) {
> > + Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + Index1 *
> > PartHeader->SizeOfPartitionEntry);
> > + if (CompareGuid (&Entry->PartitionTypeGUID,
> > &gEfiPartTypeUnusedGuid)) {
> > + continue;
> > + }
> > +
> > + StartingLBA = Entry->StartingLBA;
> > + EndingLBA = Entry->EndingLBA;
> > + if (StartingLBA > EndingLBA ||
> > + StartingLBA < PartHeader->FirstUsableLBA ||
> > + StartingLBA > PartHeader->LastUsableLBA ||
> > + EndingLBA < PartHeader->FirstUsableLBA ||
> > + EndingLBA > PartHeader->LastUsableLBA
> > + ) {
> > + PEntryStatus[Index1].OutOfRange = TRUE;
> > + continue;
> > + }
> > +
> > + if ((Entry->Attributes & BIT1) != 0) {
> > + //
> > + // If Bit 1 is set, this indicate that this is an OS specific GUID partition.
> > + //
> > + PEntryStatus[Index1].OsSpecific = TRUE;
> > + }
> > +
> > + for (Index2 = Index1 + 1; Index2 < PartHeader-
> > >NumberOfPartitionEntries; Index2++) {
> > + Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + Index2 *
> > PartHeader->SizeOfPartitionEntry);
> > + if (CompareGuid (&Entry->PartitionTypeGUID,
> > &gEfiPartTypeUnusedGuid)) {
> > + continue;
> > + }
> > +
> > + if (Entry->EndingLBA >= StartingLBA && Entry->StartingLBA <=
> EndingLBA)
> > {
> > + //
> > + // This region overlaps with the Index1'th region
> > + //
> > + PEntryStatus[Index1].Overlap = TRUE;
> > + PEntryStatus[Index2].Overlap = TRUE;
> > + continue;
> > + }
> > + }
> > + }
> > +
> > + DEBUG ((EFI_D_VERBOSE, " End check partition entries\n"));
> > +}
> > +
> > +
> > +/**
> > + Updates the CRC32 value in the table header.
> > +
> > + @param Hdr Table to update
> > +
> > +**/
> > +STATIC
> > +VOID
> > +PartitionSetCrc (
> > + IN OUT EFI_TABLE_HEADER *Hdr
> > + )
> > +{
> > + PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);
> > +}
> > +
> > +
> > +/**
> > + Updates the CRC32 value in the table header.
> > +
> > + @param Size The size of the table
> > + @param Hdr Table to update
> > +
> > +**/
> > +STATIC
> > +VOID
> > +PartitionSetCrcAltSize (
> > + IN UINTN Size,
> > + IN OUT EFI_TABLE_HEADER *Hdr
> > + )
> > +{
> > + UINT32 Crc;
> > +
> > + Hdr->CRC32 = 0;
> > + gBS->CalculateCrc32 ((UINT8 *)Hdr, Size, &Crc);
> > + Hdr->CRC32 = Crc;
> > +}
> > +
> > +
> > +/**
> > + Checks the CRC32 value in the table header.
> > +
> > + @param MaxSize Max Size limit
> > + @param Hdr Table to check
> > +
> > + @return TRUE CRC Valid
> > + @return FALSE CRC Invalid
> > +
> > +**/
> > +STATIC
> > +BOOLEAN
> > +PartitionCheckCrc (
> > + IN UINTN MaxSize,
> > + IN OUT EFI_TABLE_HEADER *Hdr
> > + )
> > +{
> > + return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);
> > +}
> > +
> > +
> > +/**
> > + Checks the CRC32 value in the table header.
> > +
> > + @param MaxSize Max Size limit
> > + @param Size The size of the table
> > + @param Hdr Table to check
> > +
> > + @return TRUE CRC Valid
> > + @return FALSE CRC Invalid
> > +
> > +**/
> > +STATIC
> > +BOOLEAN
> > +PartitionCheckCrcAltSize (
> > + IN UINTN MaxSize,
> > + IN UINTN Size,
> > + IN OUT EFI_TABLE_HEADER *Hdr
> > + )
> > +{
> > + UINT32 Crc;
> > + UINT32 OrgCrc;
> > + EFI_STATUS Status;
> > +
> > + Crc = 0;
> > +
> > + if (Size == 0) {
> > + //
> > + // If header size is 0 CRC will pass so return FALSE here
> > + //
> > + return FALSE;
> > + }
> > +
> > + if ((MaxSize != 0) && (Size > MaxSize)) {
> > + DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n"));
> > + return FALSE;
> > + }
> > + //
> > + // clear old crc from header
> > + //
> > + OrgCrc = Hdr->CRC32;
> > + Hdr->CRC32 = 0;
> > +
> > + Status = gBS->CalculateCrc32 ((UINT8 *)Hdr, Size, &Crc);
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n"));
> > + return FALSE;
> > + }
> > + //
> > + // set results
> > + //
> > + Hdr->CRC32 = Crc;
> > +
> > + //
> > + // return status
> > + //
> > + DEBUG_CODE_BEGIN ();
> > + if (OrgCrc != Crc) {
> > + DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n"));
> > + }
> > + DEBUG_CODE_END ();
> > +
> > + return (BOOLEAN)(OrgCrc == Crc);
> > +}
> > +
> > +/**
> > + Converts a GUID into a unicode string.
> > +
> > + @param [in] Guid A GUID to be converted
> > + @param [out] Buffer A pointer to a buffer receiving the string
> > + @param [in] BufferSize Size of the buffer
> > +
> > + @return EFI_SUCCESS Successful conversion
> > + @return EFI_INVALID_PARAMETER Conversion failed
> > +
> > +**/
> > +
> > +STATIC
> > +EFI_STATUS
> > +GuidToString (
> > + IN EFI_GUID *Guid,
> > + OUT CHAR16 *Buffer,
> > + IN UINTN BufferSize
> > + )
> > +{
> > + UINTN Size;
> > + EFI_STATUS Status;
> > +
> > + Status = EFI_SUCCESS;
> > +
> > + Size = UnicodeSPrint (
> > + Buffer,
> > + BufferSize,
> > + L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
> > + (UINTN)Guid->Data1,
> > + (UINTN)Guid->Data2,
> > + (UINTN)Guid->Data3,
> > + (UINTN)Guid->Data4[0],
> > + (UINTN)Guid->Data4[1],
> > + (UINTN)Guid->Data4[2],
> > + (UINTN)Guid->Data4[3],
> > + (UINTN)Guid->Data4[4],
> > + (UINTN)Guid->Data4[5],
> > + (UINTN)Guid->Data4[6],
> > + (UINTN)Guid->Data4[7]
> > + );
> > + if (!Size) {
> > + Status = EFI_INVALID_PARAMETER;
> > + }
> > +
> > + return Status;
> > +}
> > +
> > +/**
> > + Get a string representation of a known
> > + partition type GUID. If partition GUID is not
> > + known, gets a string representation of the GUID
> > +
> > + @param GUID Guid to be searched for
> > + @param PartTypeStr Buffer receiving the string
> > + @param NoGuidStr Do not convert GUID to string
> > + for an unknown partition type
> > +
> > + @return EFI_SUCCESS GUID type is known
> > + @return EFI_NOT_FOUND Unknown GUID partition type
> > +
> > +**/
> > +EFI_STATUS
> > +GetPartitionTypeStr (
> > + IN EFI_GUID Guid,
> > + OUT CHAR16 *PartTypeStr,
> > + IN BOOLEAN NoGuidStr)
> > +{
> > + UINTN Index;
> > + EFI_STATUS Status;
> > +
> > + Status = EFI_SUCCESS;
> > + for (Index = 0; Index < ARRAY_SIZE (PartitionTypes); Index++) {
> > + if (CompareGuid (&Guid, &PartitionTypes[Index].TypeGuid)) {
> > + StrnCpy (PartTypeStr, PartitionTypes[Index].TypeName,
> > MAX_PARTITION_NAME_LENGTH);
> > + return Status;
> > + }
> > + }
> > + if (!NoGuidStr) {
> > + GuidToString (&Guid, PartTypeStr, (MAX_PARTITION_NAME_LENGTH +
> 1)
> > * sizeof(CHAR16));
> > + }
> > + return EFI_NOT_FOUND;
> > +}
> > +
> > +/**
> > + Lists partitions on a block device.
> > +
> > + @return Number of partitions used
> > +**/
> > +
> > +UINTN
> > +PartitionListGptEntries (VOID)
> > +{
> > + UINTN Index;
> > + EFI_PARTITION_ENTRY *Entry;
> > + EFI_LBA Length;
> > + UINTN NumEntries; // Used entries
> > + UINTN BlockSize;
> > + BOOLEAN FirstTime;
> > + UINT64 BlocksOccupied;
> > +
> > + NumEntries = 0;
> > + BlockSize = BlockIo->Media->BlockSize;
> > + FirstTime = TRUE;
> > +
> > + if (!GptValid) {
> > + return 0;
> > + }
> > +
> > + BlocksOccupied = 0;
> > +
> > + for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries;
> > Index++) {
> > +
> > + BOOLEAN Specific;
> > + CHAR16 PartTypeStr[MAX_PARTITION_NAME_LENGTH + 1];
> > +
> > + Specific = FALSE;
> > +
> > + Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + Index *
> > PrimaryHeader->SizeOfPartitionEntry);
> > +
> > + Length = Entry->EndingLBA - Entry->StartingLBA + 1;
> > +
> > + if (CompareGuid (&Entry->PartitionTypeGUID,
> > &gEfiPartTypeUnusedGuid)) {
> > + continue;
> > + }
> > +
> > + if (FirstTime) {
> > + Print (L" No \t%-36s\tStart (LBA)\tEnd (LBA)\tSize (MiB)\t Partition
> > Type\r\n", L"Name");
> > + Print (L" ---- -------------------------------------- ----------- ----------- ---
> --
> > ----- -------------------------------\r\n");
> > + FirstTime = FALSE;
> > + }
> > + NumEntries++;
> > + if (PEntryStatus[Index].OutOfRange ||
> > + PEntryStatus[Index].Overlap ||
> > + PEntryStatus[Index].OsSpecific) {
> > + Specific = TRUE;
> > + }
> > +
> > + BlocksOccupied += Length;
> > +
> > + GetPartitionTypeStr (Entry->PartitionTypeGUID, (CHAR16
> *)&PartTypeStr,
> > FALSE);
> > +
> > + Print (L"%1s %-3d\t%-36s\t0x%09llx\t0x%09llx\t%06llu\t %s\r\n",
> > + Specific ? L"S" : L"",
> > + Index + 1,
> > + Entry->PartitionName,
> > + (UINT64)Entry->StartingLBA,
> > + (UINT64)Entry->EndingLBA,
> > + (MultU64x32 (Length, BlockSize)) >> 20,
> > + PartTypeStr);
> > + }
> > +
> > + // This code block is to provide additional info
> > + {
> > + UINT64 DiskSizeMiB, SizeOccupiedMiB;
> > +
> > + DiskSizeMiB = MultU64x32 (PrimaryHeader->LastUsableLBA -
> > PrimaryHeader->FirstUsableLBA + 1, BlockIo->Media->BlockSize) >> 20;
> > + SizeOccupiedMiB = MultU64x32 (BlocksOccupied, BlockIo->Media-
> > >BlockSize) >> 20;
> > + Print (L"\r\n%d partition(s) used out of %d\r\n", NumEntries,
> > PrimaryHeader->NumberOfPartitionEntries);
> > + Print (L"Total device capacity (minus GPT service blocks): %llu
> > MiB\r\nPartitioned space: %llu MiB\r\n",
> > + DiskSizeMiB,
> > + SizeOccupiedMiB);
> > + Print (L"Unpartitioned space available: %llu MiB (%d%%)\n",
> > + DiskSizeMiB - SizeOccupiedMiB,
> > + (100 * (DiskSizeMiB - SizeOccupiedMiB)) / DiskSizeMiB);
> > + }
> > +
> > + return NumEntries;
> > +}
> > +
> > +/**
> > + Locate a partition by criteria
> > +
> > + @param Name Partition name (or ordinal represented a string)
> > + @param StartLba StartLba of the partition to search for
> > + @param EndingLba EndingLba of the partition to search for
> > + @param SearchType A combination (OR) of search options.
> > + Options are:
> > + SRC_BY_NAME = search by partition name
> > + SRC_BY_LBA = search by Start/Ending lba
> > + SRC_ANY = returns a first used partition
> > + SRC_BY_NUM = search by ordinal
> > +
> > +
> > + @return Non-NULL Pointer to th partition found
> > + @return NULL No partition found
> > +
> > +**/
> > +EFI_PARTITION_ENTRY *
> > +PartitionFindPartitionByCriteria (
> > + IN OPTIONAL CONST CHAR16 *Name,
> > + IN OPTIONAL EFI_LBA StartLba,
> > + IN OPTIONAL EFI_LBA EndingLba,
> > + IN SEARCH_TYPE SearchType
> > + )
> > +{
> > + UINTN Index;
> > + EFI_PARTITION_ENTRY *Entry;
> > +
> > + if (!GptValid) {
> > + return NULL;
> > + }
> > +
> > + if (!Name && (SearchType & SRC_BY_NAME)) {
> > + return NULL;
> > + }
> > +
> > + for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries;
> > Index++) {
> > + Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + Index *
> > PrimaryHeader->SizeOfPartitionEntry);
> > +
> > + if (CompareGuid (&Entry->PartitionTypeGUID,
> > &gEfiPartTypeUnusedGuid)) {
> > + continue;
> > + }
> > +
> > + if (SearchType & SRC_ANY) {
> > + return Entry;
> > + }
> > +
> > + if (SearchType & SRC_BY_NAME) {
> > + if (!StrCmp (Name, Entry->PartitionName)) {
> > + return Entry;
> > + }
> > + }
> > + if (SearchType & SRC_BY_NUM) {
> > + UINTN Ordinal;
> > +
> > + Ordinal = ShellStrToUintn (Name);
> > + if (Index == (Ordinal - 1)) {
> > + return Entry;
> > + }
> > + }
> > + if (SearchType & SRC_BY_LBA) {
> > + if (
> > + ((StartLba >= Entry->StartingLBA) &&
> > + (StartLba <= Entry->EndingLBA)
> > + ) ||
> > + ((EndingLba >= Entry->StartingLBA) &&
> > + (EndingLba <= Entry->EndingLBA)
> > + )
> > + ) {
> > + return Entry;
> > + }
> > + }
> > + }
> > + return NULL;
> > +}
> > +
> > +/**
> > + Prints information on a given partition.
> > +
> > + @param Entry Pointer to the Partition of interest
> > +**/
> > +
> > +VOID
> > +PartitionPrintGptPartInfo (
> > + IN EFI_PARTITION_ENTRY *Entry
> > + )
> > +{
> > + CONST CHAR16 PartStr[MAX_PARTITION_NAME_LENGTH + 1] = { L'\0' };
> > + CONST CHAR16 *StrUnknown = L"Unknown";
> > + EFI_STATUS Status;
> > + EFI_LBA Length;
> > +
> > + ASSERT (Entry);
> > +
> > + Status = GetPartitionTypeStr (Entry->PartitionTypeGUID, (CHAR16
> > *)&PartStr, TRUE);
> > + if (EFI_ERROR (Status)) {
> > + StrCpy ((CHAR16 *)&PartStr, StrUnknown);
> > + }
> > +
> > + Length = Entry->EndingLBA - Entry->StartingLBA + 1;
> > +
> > + Print (L"Partition name: %s\r\n", Entry->PartitionName);
> > + Print (L"Starting LBA : 0x%09llx\r\nEnding LBA : 0x%09llx\r\n",
> > + (UINT64)Entry->StartingLBA, (UINT64)Entry->EndingLBA);
> > + Print (L"Partition Size: %llu MiB (0x%llx blocks)\n",
> > + (MultU64x32 (Length, BlockIo->Media->BlockSize)) >> 20, Length);
> > + Print (L"Attributes : 0x%09llx\r\n", Entry->Attributes);
> > + Print (L"Type/GUID : %s/%g\r\n", PartStr, &Entry->PartitionTypeGUID);
> > + Print (L"Unique GUID : %g\n", &Entry->UniquePartitionGUID);
> > +}
> > +
> > +
> > +/**
> > + Writes protective MBR to a block device.
> > +
> > + @return EFI_SUCCESS MBR written successfully
> > + @return other Failed to write an MBR
> > +
> > +**/
> > +
> > +STATIC
> > +EFI_STATUS
> > +WriteProtectiveMbr (
> > + VOID
> > + )
> > +{
> > + UINT32 BlockSize;
> > + UINT64 DiskSize;
> > + EFI_STATUS Status;
> > + MBR_PARTITION_RECORD *Partition;
> > + MASTER_BOOT_RECORD *ProtectiveMbr;
> > +
> > + BlockSize = BlockIo->Media->BlockSize;
> > +
> > + ProtectiveMbr = NULL;
> > + ProtectiveMbr = AllocateZeroPool (BlockSize);
> > + if (ProtectiveMbr == NULL) {
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > +
> > + DiskSize = BlockIo->Media->LastBlock + 1;
> > + if (DiskSize > 0xffffffff) {
> > + DiskSize = 0xffffffff;
> > + }
> > +
> > + CopyMem (ProtectiveMbr, &ProtectiveMbrTemplate,
> > sizeof(MASTER_BOOT_RECORD));
> > +
> > + Partition = &ProtectiveMbr->Partition[0];
> > +
> > + Partition->BootIndicator = 0;
> > + Partition->StartSector = 1;
> > +
> > + //
> > + // We don't actually know this data, so we'll make up
> > + // something that seems likely.
> > + //
> > +
> > + //
> > + // Old software is expecting the Partition to start on
> > + // a Track boundary, so we'll set track to 1 to avoid "overlay"
> > + // with the MBR
> > + //
> > +
> > + Partition->StartTrack = 1;
> > +
> > + Status = DiskIo->WriteDisk (
> > + DiskIo,
> > + BlockIo->Media->MediaId,
> > + 0,
> > + BlockSize,
> > + ProtectiveMbr
> > + );
> > +
> > + MbrValid = !EFI_ERROR (Status);
> > +
> > + SHELL_FREE_NON_NULL (ProtectiveMbr);
> > +
> > + return Status;
> > +}
> > +
> > +/**
> > + Write GPT tables to the block device.
> > +
> > + @return EFI_SUCCESS GPT tables were successfully written/updated
> > + @return other Failed to write/update GPT tables
> > +
> > +**/
> > +
> > +STATIC
> > +EFI_STATUS
> > +WriteGPT (
> > + VOID
> > + )
> > +/*
> > + CALLER is expected to fill in:
> > + FirstUseableLBA
> > + LastUseableLBA
> > + EntryCount
> > + DiskGUID
> > +
> > + We fill in the rest, and blast it out.
> > +
> > + Returns a status.
> > +
> > +*/
> > +{
> > + UINT32 BlockSize;
> > + UINT32 TableSize;
> > + EFI_STATUS Status = EFI_SUCCESS;
> > +
> > + BlockSize = BlockIo->Media->BlockSize;
> > + TableSize = PrimaryHeader->NumberOfPartitionEntries *
> > sizeof(EFI_PARTITION_ENTRY);
> > +
> > + if (!MbrValid) {
> > + WriteProtectiveMbr ();
> > + }
> > + //
> > + // Write out the primary header...
> > + //
> > + PrimaryHeader->Header.Signature = EFI_PTAB_HEADER_ID;
> > + PrimaryHeader->Header.Revision = GPT_REVISION_1_0;
> > + PrimaryHeader->Header.HeaderSize =
> > sizeof(EFI_PARTITION_TABLE_HEADER);
> > +
> > + PrimaryHeader->AlternateLBA = BackupHeader->MyLBA;
> > +
> > + PrimaryHeader->SizeOfPartitionEntry = sizeof(EFI_PARTITION_ENTRY);
> > +
> > + Status = gBS->CalculateCrc32 ((UINT8 *)PartEntry, TableSize,
> > &PrimaryHeader->PartitionEntryArrayCRC32);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + // Write primary header
> > + PartitionSetCrc (&PrimaryHeader->Header);
> > +
> > + Status = DiskIo->WriteDisk (
> > + DiskIo,
> > + BlockIo->Media->MediaId,
> > + MultU64x32 (PrimaryHeader->MyLBA, (UINT32)BlockSize),
> > + BlockSize,
> > + PrimaryHeader
> > + );
> > +
> > +
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + //
> > + // Write out the primary table ...
> > + //
> > + Status = DiskIo->WriteDisk (
> > + DiskIo,
> > + BlockIo->Media->MediaId,
> > + MultU64x32 (PrimaryHeader->PartitionEntryLBA, (UINT32)BlockSize),
> > + TableSize,
> > + PartEntry
> > + );
> > +
> > +
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + //
> > + // Write out the secondary header and table by calling restore
> > + //
> > +
> > + if (!PartitionRestoreGptTable (PrimaryHeader)) {
> > + return EFI_VOLUME_CORRUPTED;
> > + }
> > + BlockIo->FlushBlocks (BlockIo);
> > + GptValid = !EFI_ERROR (Status);
> > +
> > + return Status;
> > +}
> > +
> > +/**
> > + (Re)initialize GPT tables on the block device
> > +
> > + @return EFI_SUCCESS Successfully (re)initialized GPT Tables
> > + @return other Failed to (re)initialize GPT tables
> > +
> > +**/
> > +STATIC
> > +EFI_STATUS
> > +TableCreateEmptyGpt (VOID)
> > +{
> > + UINTN EntryCount;
> > + UINTN BlockFit;
> > + UINTN BlockSize;
> > + UINTN EntryBlocks;
> > + UINT64 DiskSize;
> > + UINTN TableSize;
> > + EFI_LBA Header1_LBA;
> > + EFI_LBA Table1_LBA;
> > + EFI_LBA Header2_LBA;
> > + EFI_LBA Table2_LBA;
> > + EFI_LBA FirstUsableLBA;
> > + EFI_LBA LastUsableLBA;
> > + EFI_STATUS Status;
> > +
> > + EntryCount = ENTRY_DEFAULT;
> > + BlockSize = BlockIo->Media->BlockSize;
> > + BlockFit = BlockSize / sizeof(EFI_PARTITION_ENTRY);
> > +
> > + if (BlockFit > ENTRY_DEFAULT) {
> > + EntryCount = BlockFit;
> > + }
> > + EntryBlocks = EntryCount / BlockFit;
> > +
> > + if ((EntryBlocks * BlockFit) != EntryCount) {
> > + Status = EFI_VOLUME_CORRUPTED;
> > + PrintErr (L"Invalid Entry blocks and Entry count combination\n", Status);
> > + return Status;
> > + }
> > +
> > + DiskSize = BlockIo->Media->LastBlock + 1;
> > +
> > + SHELL_FREE_NON_NULL (PrimaryHeader);
> > + SHELL_FREE_NON_NULL (BackupHeader);
> > + SHELL_FREE_NON_NULL (PartEntry);
> > +
> > + PrimaryHeader = AllocateZeroPool (BlockSize);
> > + if (PrimaryHeader == NULL) {
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > +
> > + BackupHeader = AllocateZeroPool (BlockSize);
> > + if (BackupHeader == NULL) {
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > +
> > + Header1_LBA = 1;
> > + Table1_LBA = 2;
> > + FirstUsableLBA = Table1_LBA + EntryBlocks;
> > +
> > + Header2_LBA = DiskSize - 1;
> > + Table2_LBA = Header2_LBA - EntryBlocks;
> > + LastUsableLBA = Table2_LBA - 1;
> > +
> > + TableSize = EntryBlocks * BlockSize;
> > +
> > + if (TableSize != (EntryCount * sizeof(EFI_PARTITION_ENTRY))) {
> > + Status = EFI_VOLUME_CORRUPTED;
> > + PrintErr (L"Invalid Table size and Entry count combination\n", Status);
> > + return Status;
> > + }
> > +
> > + if (GPT_DEBUG_LEVEL) {
> > + Print (L"DiskSize = %lx\n", DiskSize);
> > + Print (L"BlockSize = %x\n", BlockSize);
> > + Print (L"Header1_LBA = %lx\n", Header1_LBA);
> > + Print (L"Table1_LBA = %lx\n", Table1_LBA);
> > + Print (L"FirstUsableLBA = %lx\n", FirstUsableLBA);
> > + Print (L"Header2_LBA = %lx\n", Header2_LBA);
> > + Print (L"Table2_LBA = %lx\n", Table2_LBA);
> > + Print (L"LastUsableLBA = %lx\n", LastUsableLBA);
> > + Print (L"EntryCount = %x\n", EntryCount);
> > + Print (L"EntryBlocks = %x\n", EntryBlocks);
> > + }
> > +
> > + //
> > + // Since we're making empty tables, we just write zeros...
> > + //
> > +
> > + PartEntry = AllocateZeroPool (TableSize);
> > + if (PartEntry == NULL) {
> > + SHELL_FREE_NON_NULL (PrimaryHeader);
> > + SHELL_FREE_NON_NULL (BackupHeader);
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > +
> > + PEntryStatus = AllocateZeroPool (TableSize);
> > +
> > + PrimaryHeader->FirstUsableLBA = FirstUsableLBA;
> > + PrimaryHeader->LastUsableLBA = LastUsableLBA;
> > + PrimaryHeader->NumberOfPartitionEntries = (UINT32)EntryCount;
> > + GenerateGuid (&PrimaryHeader->DiskGUID);
> > +
> > + PrimaryHeader->MyLBA = Header1_LBA;
> > + BackupHeader->MyLBA = Header2_LBA;
> > + PrimaryHeader->PartitionEntryLBA = Table1_LBA;
> > + BackupHeader->PartitionEntryLBA = Table2_LBA;
> > +
> > + Status = WriteGPT ();
> > +
> > + return Status;
> > +}
> > +
> > +/**
> > + Clear GPT partitions.
> > +
> > + @return EFI_SUCCESS Cleared successfully
> > + @return FALSE Failed to clear
> > +
> > +**/
> > +
> > +EFI_STATUS
> > +PartitionGptClearAll (VOID)
> > +{
> > + GptCleanupGlobals ();
> > + GptValid = FALSE;
> > + MbrValid = FALSE;
> > + return TableCreateEmptyGpt ();
> > +}
> > +
> > +/**
> > + Create a GPT partition.
> > +
> > + @param PartName Partition Name
> > + @param StartLba Starting LBA of the partition.
> > + if zero, will be calculated
> > + @param SizeInMegaBytes Size of the partition in MB
> > + @param Attributes Partition attributes
> > + @param PartTypeGuid a Type GUID to be assigned to the partition
> > (not a partition unique GUID)
> > +
> > +
> > + @return EFI_SUCCESS Partition successfully created
> > + @return EFI_INVALID_PARAMETER Either partition exists, or wrong
> > parameters specified
> > + @return other Failed to create a partition
> > +**/
> > +EFI_STATUS
> > +PartitionGptCreatePartition (
> > + IN CONST CHAR16 *PartName,
> > + IN EFI_LBA StartLba,
> > + IN UINT64 SizeInMegabytes,
> > + IN UINT64 Attributes,
> > + IN EFI_GUID PartTypeGuid)
> > +{
> > + EFI_GUID Guid, PartitionIdGuid;
> > + EFI_STATUS Status;
> > + UINT64 StartBlock;
> > + UINT64 EndBlock;
> > + UINT64 SizeInBytes = 0;
> > + UINT32 BlockSize;
> > + UINT64 DiskSizeBlocks;
> > + UINT8 *p;
> > + BOOLEAN OffsetSpecified = FALSE;
> > + BOOLEAN AllZeros;
> > + INTN AllZeroEntry;
> > + INTN OldFreeEntry;
> > + UINT64 AvailBlocks;
> > + UINT64 BlocksToAllocate;
> > + UINT64 HighSeen;
> > + UINTN Slot;
> > + UINT64 LowestAlignedLba;
> > + UINT32 OptimalTransferBlocks;
> > + UINTN i, j;
> > + CHAR16 PartNameUsed[MAX_PARTITION_NAME_LENGTH + 1] =
> { L'\0' };
> > + EFI_PARTITION_ENTRY *Entry;
> > +
> > + LowestAlignedLba = 0;
> > + OptimalTransferBlocks = 1;
> > +
> > + AllZeroEntry = -1;
> > + OldFreeEntry = -1;
> > +
> > + BlockSize = BlockIo->Media->BlockSize;
> > + OffsetSpecified = (StartLba != 0);
> > + CopyMem (&PartNameUsed, PartName, sizeof(CHAR16) * StrSize
> > (PartName));
> > +
> > + GenerateGuid (&Guid);
> > +
> > + // Creating a new partition
> > + if (!GptValid) {
> > + // Creating a GPT for the first time
> > + Status = TableCreateEmptyGpt ();
> > + if (!EFI_ERROR (Status)) {
> > + // Fill in the structures
> > + Status = PartitionGetGptTables (DiskIo, BlockIo);
> > + }
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > + }
> > +
> > + Entry = PartitionFindPartitionByCriteria (PartName, 0, 0, SRC_BY_NAME);
> > + if (Entry) {
> > + Status = EFI_INVALID_PARAMETER;
> > + PrintErr (L"Partition with this name already exists", Status);
> > + return Status;
> > + }
> > + HighSeen = PrimaryHeader->FirstUsableLBA - 1;
> > +
> > + if (StartLba) {
> > + //
> > + // if offset is specified, compute the start and end blocks
> > + //
> > + StartBlock = StartLba;
> > + //
> > + // StartBlock should be aligned to OptimalTransferBlocks, the least
> > common multiple of:
> > + // a). the physical block boundary, if any
> > + // b). the optimal transfer length granularity, if any
> > + //
> > + if (StartBlock < LowestAlignedLba) {
> > + StartBlock = LowestAlignedLba;
> > + } else {
> > + while (((StartBlock - LowestAlignedLba) % OptimalTransferBlocks) != 0)
> {
> > + StartBlock++;
> > + }
> > + }
> > +
> > + if (StartBlock < PrimaryHeader->FirstUsableLBA ||
> > + StartBlock > PrimaryHeader->LastUsableLBA) {
> > + //
> > + // Offset specified is too large
> > + //
> > + Status = EFI_INVALID_PARAMETER;
> > + PrintErr (L"Specified offset is too large", EFI_INVALID_PARAMETER);
> > + goto Exit;
> > + }
> > +
> > + SizeInBytes = MultU64x32 (SizeInMegabytes, (1024 * 1024));
> > + if (SizeInBytes < SizeInMegabytes || SizeInBytes == 0) {
> > + //
> > + // If size is not specified or too large,
> > + // try to make the partition as big as it can be
> > + //
> > + BlocksToAllocate = EndBlock = SizeInBytes = 0xffffffffffffffff;
> > + } else {
> > + BlocksToAllocate = DivU64x32 (SizeInBytes, BlockSize);
> > + EndBlock = StartBlock + BlocksToAllocate - 1;
> > + if (EndBlock > PrimaryHeader->LastUsableLBA) {
> > + EndBlock = PrimaryHeader->LastUsableLBA;
> > + BlocksToAllocate = EndBlock - StartBlock + 1;
> > + }
> > + }
> > + }
> > +
> > + for (i = 0; i < PrimaryHeader->NumberOfPartitionEntries; i++) {
> > + Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + i *
> > PrimaryHeader->SizeOfPartitionEntry);
> > + if (!CompareGuid (&Entry->PartitionTypeGUID,
> > &gEfiPartTypeUnusedGuid)) {
> > +
> > + //
> > + // Type not null, so it's allocated
> > + //
> > + if (Entry->EndingLBA > HighSeen) {
> > + HighSeen = Entry->EndingLBA;
> > + }
> > + if (OffsetSpecified) {
> > + //
> > + // make sure new partition does not overlap with existing partitions
> > + //
> > + if (Entry->StartingLBA <= StartBlock &&
> > + StartBlock <= Entry->EndingLBA) {
> > + //
> > + // starting block is inside an existing partition
> > + //
> > + Status = EFI_INVALID_PARAMETER;
> > + PrintErr (L"Starting block is inside an existing partition", Status);
> > + goto Exit;
> > + }
> > + if ((Entry->StartingLBA <= EndBlock &&
> > + EndBlock <= Entry->EndingLBA) ||
> > + (StartBlock <= Entry->StartingLBA &&
> > + Entry->StartingLBA <= EndBlock) ||
> > + (StartBlock <= Entry->EndingLBA &&
> > + Entry->EndingLBA <= EndBlock)) {
> > + //
> > + // new partition overlaps with an existing partition
> > + // readjust new partition size to avoid overlapping
> > + //
> > + EndBlock = Entry->StartingLBA - 1;
> > + if (EndBlock < StartBlock) {
> > + Status = EFI_INVALID_PARAMETER;
> > + PrintErr (L"Cannot readjust new partition size - overlapping", Status);
> > + goto Exit;
> > + } else {
> > + BlocksToAllocate = EndBlock - StartBlock + 1;
> > + }
> > + }
> > + }
> > + } else {
> > + p = (UINT8 *)(Entry);
> > + AllZeros = TRUE;
> > + for (j = 0; j < sizeof(EFI_PARTITION_ENTRY); j++) {
> > + if (p[j] != 0) {
> > + AllZeros = FALSE;
> > + }
> > + }
> > + if (AllZeros) {
> > + if (AllZeroEntry == -1) {
> > + AllZeroEntry = i;
> > + }
> > + } else if (OldFreeEntry == -1) {
> > + OldFreeEntry = i;
> > + }
> > + }
> > + }
> > +
> > + //
> > + // AllZeroEntry - if not -1, is pointer to a never before used entry (free)
> > + // OldFreeEntry - if not -1, is pointer to some pre-used free entry
> > + //
> > + if ((AllZeroEntry == -1) && (OldFreeEntry == -1)) {
> > + //
> > + // TABLE IS FULL!!
> > + //
> > + Status = EFI_OUT_OF_RESOURCES;
> > + PrintErr (L"Table is full", Status);
> > + goto Exit;
> > + }
> > +
> > + if (OffsetSpecified) {
> > + //
> > + // the user haven't specified the new partition size and we haven't
> > + // run into any partition that will limit the size of this new partition.
> > + // So, use the max it can
> > + //
> > + if (BlocksToAllocate == -1) {
> > + EndBlock = PrimaryHeader->LastUsableLBA;
> > + BlocksToAllocate = EndBlock - StartBlock + 1;
> > + }
> > + } else {
> > + //
> > + // Because HighSeen is the last LBA of the used blocks, let HighSeen
> align
> > to the least common multiple of:
> > + // a). the physical block boundary, if any
> > + // b). the optimal transfer length granularity, if any
> > + //
> > + if (HighSeen + 1 < LowestAlignedLba) {
> > + HighSeen = LowestAlignedLba - 1;
> > + } else {
> > + while (((HighSeen + 1 - LowestAlignedLba) % OptimalTransferBlocks) !=
> 0)
> > {
> > + HighSeen++;
> > + }
> > + }
> > +
> > + if (PrimaryHeader->LastUsableLBA <= HighSeen) {
> > + Status = EFI_OUT_OF_RESOURCES;
> > + PrintErr (L"Disk has no free blocks (FULL) cannot create", Status);
> > + goto Exit;
> > + }
> > + //
> > + // [HighSeen+1 ... LastUsableLBA] is available...
> > + // avail = (LastUsableLBA - (HighSeen+1)) + 1 => LastUsabbleLBA -
> > HighSeen
> > + //
> > + AvailBlocks = PrimaryHeader->LastUsableLBA - HighSeen;
> > +
> > + SizeInBytes = MultU64x32 (SizeInMegabytes, (1024 * 1024));
> > + if (SizeInBytes < SizeInMegabytes) {
> > + //
> > + // overflow, force a very big answer
> > + //
> > + SizeInBytes = 0xffffffffffffffff;
> > + }
> > +
> > + if ((SizeInBytes == 0) ||
> > + (SizeInBytes > (MultU64x32 (AvailBlocks, BlockSize)))) {
> > + //
> > + // User asked for zero, or for more than we've got,
> > + // so give them all that is left
> > + //
> > + BlocksToAllocate = AvailBlocks;
> > +
> > + } else {
> > +
> > + //
> > + // We would have to have a BlockSize > 1mb for Remainder to
> > + // not be 0. Since we cannot actually test this case, we
> > + // ingore it...
> > + //
> > + BlocksToAllocate = DivU64x32 (SizeInBytes, BlockSize);
> > +
> > + }
> > + }
> > +
> > + //
> > + // We have a name
> > + // We have a type guid
> > + // We have a size in blocks
> > + // We have an attribute mask
> > + //
> > +
> > + if (BlocksToAllocate < ((1024 * 1024) / BlockSize)) {
> > + Status = EFI_OUT_OF_RESOURCES;
> > + PrintErr (L"Partition is too small to be created", Status);
> > + goto Exit;
> > + }
> > +
> > + if (GPT_DEBUG_LEVEL) {
> > + Print (L"Requested SizeInMegaBytes = %ld\n", SizeInMegabytes);
> > + Print (L"Resulting size in Blocks = %ld\n", BlocksToAllocate);
> > + Print (L"Results size in Bytes = %ld\n", MultU64x32 (BlocksToAllocate,
> > BlockSize));
> > + }
> > +
> > + if (AllZeroEntry != -1) {
> > + Slot = AllZeroEntry;
> > + } else {
> > + Slot = OldFreeEntry;
> > + }
> > +
> > + GenerateGuid (&PartitionIdGuid);
> > + Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartEntry + Slot *
> > PrimaryHeader->SizeOfPartitionEntry);
> > +
> > + CopyMem (&Entry->PartitionTypeGUID, &PartTypeGuid,
> > sizeof(EFI_GUID));
> > + CopyMem (&Entry->UniquePartitionGUID, &PartitionIdGuid,
> > sizeof(EFI_GUID));
> > + if (OffsetSpecified) {
> > + PartEntry[Slot].StartingLBA = StartBlock;
> > + PartEntry[Slot].EndingLBA = EndBlock;
> > + } else {
> > + PartEntry[Slot].StartingLBA = HighSeen + 1;
> > + PartEntry[Slot].EndingLBA = HighSeen + BlocksToAllocate;
> > + }
> > +
> > + if (!(((Entry->EndingLBA - Entry->StartingLBA) + 1) == BlocksToAllocate)) {
> > + PrintErr (L"Wrong Size for new partiton", EFI_INVALID_PARAMETER);
> > + goto Exit;
> > + }
> > +
> > + if ((Entry->StartingLBA < PrimaryHeader->FirstUsableLBA) ||
> > + (Entry->EndingLBA > PrimaryHeader->LastUsableLBA)) {
> > + PrintErr (L"New Partition out of bounds", EFI_INVALID_PARAMETER);
> > + goto Exit;
> > + }
> > +
> > + Entry->Attributes = Attributes;
> > + CopyMem (&(Entry->PartitionName[0]), PartName,
> > MAX_PARTITION_NAME_LENGTH * sizeof(CHAR16));
> > +
> > + DiskSizeBlocks = BlockIo->Media->LastBlock + 1;
> > + if (DiskSizeBlocks > 0xffffffff) {
> > + DiskSizeBlocks = 0xffffffff;
> > + }
> > +
> > + Status = WriteGPT ();
> > +
> > + if (EFI_ERROR (Status)) {
> > + PrintErr (L"Attempt to Write out partition table failed", Status);
> > + }
> > +
> > + Exit:
> > + return Status;
> > +}
> > +
> > +/**
> > + Modifiy a partition based on parameters.
> > +
> > + @param Entry Pointer to an existing partition
> > + @param Params Parameters to be modified
> > + @param Flags Which parameter is to be modified
> > +
> > + @return EFI_SUCCESS Successfully modified the partition
> > + @return other Failed to modify a partition
> > +
> > +**/
> > +
> > +EFI_STATUS
> > +PartitionGptModifyPartition (
> > + IN EFI_PARTITION_ENTRY *Entry,
> > + IN MOD_PARAMS *Params,
> > + IN MOD_FLAGS Flags
> > + )
> > +{
> > + EFI_STATUS Status;
> > +
> > + ASSERT (Entry);
> > +
> > + Status = EFI_INVALID_PARAMETER;
> > +
> > + switch (Flags) {
> > + case MOD_DELETE:
> > + ZeroMem (Entry, sizeof(EFI_PARTITION_ENTRY));
> > + break;
> > + case MOD_ATTR:
> > + Entry->Attributes = Params->Attributes;
> > + break;
> > + case MOD_TYPE:
> > + Entry->PartitionTypeGUID = Params->PartTypeGuid;
> > + break;
> > + case MOD_RENAME:
> > + StrCpy (Entry->PartitionName, Params->NewName);
> > + break;
> > + default:
> > + PrintErr (L"Unknown modification flag(s)", Status);
> > + return Status;
> > + }
> > +
> > + return WriteGPT ();
> > +}
> > +
> > +EFI_KNOWN_PARTITION_TYPE *PartitionGetKnownType (
> > + IN UINTN Index,
> > + IN OUT OPTIONAL UINTN *NumEntries
> > + )
> > +{
> > + if (NumEntries) {
> > + *NumEntries = ARRAY_SIZE(PartitionTypes);
> > + }
> > + if (Index > ARRAY_SIZE(PartitionTypes)) {
> > + return NULL;
> > + }
> > +
> > + return &PartitionTypes[Index];
> > +}
> > +
> > diff --git a/ShellPkg/Library/UefiShellGptCommandLib/GptWorker.h
> > b/ShellPkg/Library/UefiShellGptCommandLib/GptWorker.h
> > new file mode 100644
> > index 000000000000..9efec5cefe94
> > --- /dev/null
> > +++ b/ShellPkg/Library/UefiShellGptCommandLib/GptWorker.h
> > @@ -0,0 +1,186 @@
> > +/*
> > + * BSD LICENSE
> > + *
> > + * Copyright(c) 2016 Broadcom. All rights reserved.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + *
> > + * * Redistributions of source code must retain the above copyright
> > + * notice, this list of conditions and the following disclaimer.
> > + * * Redistributions in binary form must reproduce the above copyright
> > + * notice, this list of conditions and the following disclaimer in
> > + * the documentation and/or other materials provided with the
> > + * distribution.
> > + * * Neither the name of Broadcom nor the names of its
> > + * contributors may be used to endorse or promote products derived
> > + * from this software without specific prior written permission.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > CONTRIBUTORS
> > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> > NOT
> > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> > FITNESS FOR
> > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> > COPYRIGHT
> > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> > INCIDENTAL,
> > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
> BUT
> > NOT
> > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> LOSS
> > OF USE,
> > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> > AND ON ANY
> > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> > TORT
> > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
> OF
> > THE USE
> > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> > DAMAGE.
> > + */
> > +
> > +/* GPT partitioner header file */
> > +
> > +#ifndef _GPTWORKER_H_
> > +#define _GPTWORKER_H_
> > +
> > +#include <Uefi.h>
> > +#include <ShellBase.h>
> > +
> > +#include <Library/BaseLib.h>
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/MemoryAllocationLib.h>
> > +#include <Library/ShellCommandLib.h>
> > +#include <Library/ShellLib.h>
> > +#include <Library/UefiLib.h>
> > +#include <Library/UefiShellLib/UefiShellLib.h>
> > +#include <Library/UefiBootServicesTableLib.h>
> > +#include <Library/UefiRuntimeServicesTableLib.h>
> > +#include <Library/PrintLib.h>
> > +#include <Library/ShellCEntryLib.h>
> > +#include <Library/HiiLib.h>
> > +#include <Library/FileHandleLib.h>
> > +#include <Protocol/DevicePath.h>
> > +#include <Library/DevicePathLib.h>
> > +#include <Protocol/BlockIo.h>
> > +#include <Protocol/DiskIo.h>
> > +#include <IndustryStandard/Mbr.h>
> > +
> > +typedef enum {
> > + MOD_NAME = BIT0,
> > + MOD_ATTR = BIT1,
> > + MOD_TYPE = BIT2,
> > + MOD_DELETE = BIT3,
> > + MOD_RENAME = BIT4
> > +} MOD_FLAGS;
> > +
> > +typedef struct {
> > + UINTN Attributes;
> > + EFI_GUID PartTypeGuid;
> > + CONST CHAR16 *PartName;
> > + CONST CHAR16 *NewName;
> > +} MOD_PARAMS;
> > +
> > +typedef enum {
> > + SRC_BY_NAME = BIT0,
> > + SRC_BY_LBA = BIT1,
> > + SRC_BY_NUM = BIT2,
> > + SRC_ANY = BIT3
> > +} SEARCH_TYPE;
> > +
> > +#define MAX_PARTITION_NAME_LENGTH 36
> > +#define ENTRY_DEFAULT 128
> > +#define GPT_REVISION_1_0 0x00010000
> > +
> > +#define ARRAY_SIZE(x) \
> > + (sizeof(x) / sizeof((x)[0]))
> > +
> > +//
> > +// Extract INT32 from char array
> > +//
> > +#define UNPACK_INT32(a) (INT32)( (((UINT8 *) a)[0] << 0) | \
> > + (((UINT8 *) a)[1] << 8) | \
> > + (((UINT8 *) a)[2] << 16) | \
> > + (((UINT8 *) a)[3] << 24) )
> > +
> > +//
> > +// Extract UINT32 from char array
> > +//
> > +#define UNPACK_UINT32(a) (UINT32)( (((UINT8 *) a)[0] << 0) | \
> > + (((UINT8 *) a)[1] << 8) | \
> > + (((UINT8 *) a)[2] << 16) | \
> > + (((UINT8 *) a)[3] << 24) )
> > +
> > +
> > +//
> > +// GPT Partition Entry Status
> > +//
> > +typedef struct {
> > + BOOLEAN OutOfRange;
> > + BOOLEAN Overlap;
> > + BOOLEAN OsSpecific;
> > +} EFI_PARTITION_ENTRY_STATUS;
> > +
> > +typedef struct {
> > + CONST EFI_GUID TypeGuid;
> > + CONST CHAR16 *TypeName;
> > +
> > +} EFI_KNOWN_PARTITION_TYPE;
> > +
> > +EFI_KNOWN_PARTITION_TYPE *PartitionGetKnownType (
> > + IN UINTN Index,
> > + IN OUT OPTIONAL UINTN *NumEntries
> > + );
> > +
> > +EFI_STATUS
> > +PartitionGetGptTables (
> > + IN EFI_DISK_IO_PROTOCOL *DiskIoProt,
> > + IN EFI_BLOCK_IO_PROTOCOL *BlockIoProt
> > + );
> > +
> > +UINTN
> > +PartitionListGptEntries (
> > + VOID
> > + );
> > +
> > +VOID
> > +PartitionPrintGptPartInfo (
> > + IN EFI_PARTITION_ENTRY *Entry
> > + );
> > +
> > +EFI_STATUS
> > +GetPartitionTypeStr (
> > + EFI_GUID Guid,
> > + CHAR16 *PartTypeStr,
> > + BOOLEAN NoGuidStr
> > + );
> > +
> > +
> > +EFI_STATUS
> > +PartitionGptClearAll (
> > + VOID
> > + );
> > +
> > +EFI_STATUS
> > +PartitionGptCreatePartition (
> > + CONST CHAR16 *PartName,
> > + EFI_LBA StartLba,
> > + EFI_LBA PartitionSize,
> > + UINT64 Attributes,
> > + EFI_GUID PartTypeGuid);
> > +
> > +EFI_STATUS
> > +PartitionGptModifyPartition (
> > + EFI_PARTITION_ENTRY *Entry,
> > + MOD_PARAMS *Params,
> > + MOD_FLAGS Flags
> > + );
> > +
> > +VOID
> > +GptCleanupGlobals (
> > + VOID
> > + );
> > +
> > +EFI_PARTITION_ENTRY *
> > +PartitionFindPartitionByCriteria (
> > + CONST CHAR16 *Name,
> > + EFI_LBA StartLba,
> > + EFI_LBA EndingLba,
> > + SEARCH_TYPE SearchType);
> > +
> > +VOID
> > +PrintErr (IN CONST CHAR16 *Message, IN EFI_STATUS Status);
> > +
> > +#endif //_GPTWORKER_H_
> > diff --git
> > a/ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.c
> > b/ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.c
> > new file mode 100644
> > index 000000000000..a9d74a780911
> > --- /dev/null
> > +++
> > b/ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.c
> > @@ -0,0 +1,1135 @@
> >
> +/*********************************************************
> > **********************
> > +Copyright (C) 2016 Marvell International Ltd.
> > +
> > +Marvell BSD License Option
> > +
> > +If you received this File from Marvell, you may opt to use, redistribute
> > and/or
> > +modify this File under the following licensing terms.
> > +Redistribution and use in source and binary forms, with or without
> > modification,
> > +are permitted provided that the following conditions are met:
> > +
> > +* Redistributions of source code must retain the above copyright notice,
> > + this list of conditions and the following disclaimer.
> > +
> > +* Redistributions in binary form must reproduce the above copyright
> > + notice, this list of conditions and the following disclaimer in the
> > + documentation and/or other materials provided with the distribution.
> > +
> > +* Neither the name of Marvell nor the names of its contributors may be
> > + used to endorse or promote products derived from this software
> without
> > + specific prior written permission.
> > +
> > +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > CONTRIBUTORS "AS IS" AND
> > +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> TO,
> > THE IMPLIED
> > +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> > PURPOSE ARE
> > +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > CONTRIBUTORS BE LIABLE FOR
> > +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > CONSEQUENTIAL DAMAGES
> > +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
> GOODS
> > OR SERVICES;
> > +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> HOWEVER
> > CAUSED AND ON
> > +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> > TORT
> > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> > THE USE OF THIS
> > +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > +
> >
> +*********************************************************
> > **********************/
> > +
> > +/* Portions Copyright (C) 2016 Broadcom */
> > +
> > +#include "FatFormat.h"
> > +#include
> > <Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h>
> > +#include <Library/TimerLib.h>
> > +
> > +CONST CHAR16 gShellGptFileName[] = L"ShellCommand";
> > +STATIC CONST CHAR16 gAppName[] = L"gpt";
> > +EFI_HANDLE gShellGptHiiHandle = NULL;
> > +
> > +STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
> > + // Partition-related operations
> > + { L"clear", TypeFlag }, // Clears all partitions
> > + { L"create", TypeFlag }, // Creates a partition
> > + { L"delete", TypeFlag }, // Deletes a partition
> > + { L"list", TypeFlag }, // Lists all partitions
> > + { L"rename", TypeFlag }, // Renames a partition
> > + { L"setattr", TypeFlag }, // Set attributes for a partition in partition
> > table
> > + { L"settype", TypeFlag },
> > + { L"sync", TypeFlag }, // Synchronizes either master or
> alternative
> > partition table
> > + { L"typesinfo", TypeFlag }, // Verifies correctness of master and
> > alternative partition tables
> > + // BlockIo-related operations
> > + { L"read", TypeFlag }, // Reads n bytes into memory address
> from
> > a partition starting from a certain lba
> > + { L"readfile", TypeFlag }, // Same as above, but instead of store it
> in
> > memory saves into a file system
> > + { L"write", TypeFlag }, // Writes n bytes from memory into a
> > partition starting from a certain lba
> > + { L"writefile", TypeFlag }, // Same as above, but instead of getting
> > data from memory reads a file
> > + { L"info", TypeFlag }, // Get information on a certain partition
> > (startLba, lastLba, attributes)
> > + { L"fatformat", TypeFlag }, // FAT format of a partition
> > + { L"-type", TypeValue },
> > + { L"-yes", TypeFlag },
> > + { L"-verbose", TypeFlag },
> > + { NULL, TypeMax }
> > +};
> > +
> > +typedef enum {
> > + // Not requires presence
> > + CLEAR = BIT0,
> > + CREATE = BIT1,
> > + LIST = BIT2,
> > + SYNC = BIT3,
> > + TYPES_INFO = BIT4,
> > +
> > + // Requires presence
> > + DELETE = BIT5,
> > + INFO = BIT6,
> > + READ = BIT7,
> > + READ_FILE = BIT8,
> > + RENAME = BIT9,
> > + SETATTR = BIT10,
> > + SETTYPE = BIT11,
> > + WRITE = BIT12,
> > + WRITE_FILE = BIT13,
> > + FAT_FORMAT = BIT14,
> > +} Flags;
> > +
> > +/**
> > + Return the file name of the help text file if not using HII.
> > +
> > + @return The string pointer to the file name.
> > +**/
> > +CONST CHAR16 *
> > +EFIAPI
> > +ShellCommandGetManFileNameGpt (
> > + VOID
> > + )
> > +{
> > +
> > + return gShellGptFileName;
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +OpenAndPrepareFile (
> > + IN CHAR16 *FilePath,
> > + OUT SHELL_FILE_HANDLE *FileHandle,
> > + IN BOOLEAN WriteNeeded
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT64 OpenMode;
> > +
> > + OpenMode = EFI_FILE_MODE_READ;
> > +
> > + if (WriteNeeded) {
> > + OpenMode |= EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE;
> > + }
> > +
> > + Status = ShellOpenFileByName (FilePath, FileHandle, OpenMode, 0);
> > + if (EFI_ERROR (Status)) {
> > + ShellPrintHiiEx (-1, -1,
> > + NULL, STRING_TOKEN (STR_GPT_ERROR),
> > + gShellGptHiiHandle,
> > + gAppName,
> > + Status,
> > + L"Cannot open file"
> > + );
> > + return Status;
> > + }
> > +
> > + Status = FileHandleSetPosition (*FileHandle, 0);
> > +
> > + if (EFI_ERROR (Status)) {
> > + ShellPrintHiiEx (-1, -1,
> > + NULL, STRING_TOKEN (STR_GPT_ERROR),
> > + gShellGptHiiHandle,
> > + gAppName,
> > + Status,
> > + "Cannot set file position to the first byte"
> > + );
> > +
> > + ShellCloseFile (FileHandle);
> > + return Status;
> > + }
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +VOID
> > +PrintErr (
> > + IN CONST CHAR16 *Message,
> > + IN EFI_STATUS Status
> > + )
> > +{
> > + ShellPrintHiiEx (-1, -1,
> > + NULL, STRING_TOKEN (STR_GPT_ERROR),
> > + gShellGptHiiHandle,
> > + gAppName,
> > + Status,
> > + Message
> > + );
> > +}
> > +
> > +STATIC
> > +BOOLEAN
> > +IsPartitionableDevicePath (
> > + IN EFI_DEVICE_PATH *DevicePath
> > + )
> > +{
> > + UINTN PathSize;
> > + EFI_DEVICE_PATH *PathInstance;
> > + BOOLEAN Partitionable;
> > +
> > + Partitionable = TRUE;
> > + while (DevicePath != NULL) {
> > + PathInstance = GetNextDevicePathInstance (&DevicePath, &PathSize);
> > +
> > + while (!IsDevicePathEnd (PathInstance)) {
> > + if ((DevicePathType (PathInstance) == MEDIA_DEVICE_PATH)) {
> > + Partitionable = FALSE;
> > + }
> > +
> > + PathInstance = NextDevicePathNode (PathInstance);
> > + }
> > + }
> > + return Partitionable;
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +GptPromptYesNo (
> > + IN CONST EFI_STRING_ID HiiFormatStringId
> > + )
> > +{
> > + EFI_STATUS Status;
> > + VOID *Response;
> > +
> > + Status = ShellPromptForResponseHii (ShellPromptResponseTypeYesNo,
> > HiiFormatStringId, gShellGptHiiHandle, &Response);
> > + if ((EFI_ERROR (Status)) || (*(SHELL_PROMPT_RESPONSE
> *)Response) !=
> > ShellPromptResponseYes) {
> > + return EFI_ABORTED;
> > + }
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +STATIC
> > +VOID FormatSize(
> > + UINT64 Size, CHAR16 *Buffer)
> > +{
> > +#define MAX_SIZE_BUF_SIZE 32
> > + UINT64 Base, Frac;
> > + CHAR16 Metric;
> > +
> > + Metric = L'B';
> > + Frac = 0;
> > + if (Size < SIZE_1KB) {
> > + Base = Size;
> > + } else if (Size < SIZE_1MB) {
> > + Base = Size / SIZE_1KB;
> > + Frac = ((Size % SIZE_1KB) * 10) >> 10;
> > + Metric = L'K';
> > + } else if (Size < SIZE_1GB) {
> > + Base = Size / SIZE_1MB;
> > + Frac = ((Size % SIZE_1MB) * 10) >> 20;
> > + Metric = L'M';
> > + } else if (Size < SIZE_1TB) {
> > + Base = Size / SIZE_1GB;
> > + Frac = ((Size % SIZE_1GB) * 10) >> 30;
> > + Metric = L'G';
> > + } else {
> > + Base = Size / SIZE_1TB;
> > + Frac = ((Size % SIZE_1TB) * 10) >> 40;
> > + Metric = L'T';
> > + }
> > + if (Frac) {
> > + UnicodeSPrint (Buffer, MAX_SIZE_BUF_SIZE, L"%d.%d%c", Base, Frac,
> > Metric);
> > + } else {
> > + UnicodeSPrint (Buffer, MAX_SIZE_BUF_SIZE, L"%d%c", Base, Metric);
> > + }
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +FindAndPrintPartitionableDevices (VOID)
> > +{
> > + UINTN Index;
> > + EFI_HANDLE *HandlePointer;
> > + UINTN HandleCount;
> > + UINTN DevCount;
> > + EFI_STATUS Status;
> > + BOOLEAN FirstTime;
> > +
> > + Status = gBS->LocateHandleBuffer (ByProtocol,
> &gEfiBlockIoProtocolGuid,
> > NULL, &HandleCount, &HandlePointer);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + DevCount = 0;
> > + FirstTime = TRUE;
> > +
> > + for (Index = 0; Index < HandleCount; Index++) {
> > + EFI_DEVICE_PATH *DevicePath;
> > + CONST CHAR16 *MapPath;
> > + CHAR16 *Match;
> > + EFI_BLOCK_IO *BlkIo;
> > + EFI_DISK_IO *DiskIo;
> > + CHAR16 *BufferForSize;
> > +
> > + Status = gBS->HandleProtocol (HandlePointer[Index],
> > &gEfiBlockIoProtocolGuid, (VOID **)&BlkIo);
> > + if (EFI_ERROR (Status)) {
> > + continue;
> > + }
> > +
> > + DevicePath = DevicePathFromHandle (HandlePointer[Index]);
> > + if (!IsPartitionableDevicePath (DevicePath)) {
> > + continue;
> > + }
> > + MapPath = gEfiShellProtocol->GetMapFromDevicePath (&DevicePath);
> > + if (MapPath == NULL) {
> > + continue;
> > + }
> > +
> > + Status = gBS->HandleProtocol (HandlePointer[Index],
> > &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);
> > + if (EFI_ERROR (Status)) {
> > + continue;
> > + }
> > +
> > + Match = StrStr (MapPath, L";BLK");
> > + if (Match) {
> > + MapPath = Match;
> > + MapPath++;
> > + }
> > +
> > + if (FirstTime) {
> > + BufferForSize = AllocateZeroPool (MAX_SIZE_BUF_SIZE * sizeof
> > (CHAR16));
> > + ASSERT (BufferForSize);
> > + Print (L" Device\t Size Comments\n");
> > + Print (L" ------ ------- ------------------------------------------------------------
> > \n");
> > + FirstTime = FALSE;
> > + }
> > + GptCleanupGlobals ();
> > + FormatSize (MultU64x32 (BlkIo->Media->LastBlock + 1, BlkIo->Media-
> > >BlockSize), BufferForSize);
> > + ShellPrintHiiEx (-1, -1,
> > + NULL, STRING_TOKEN (STR_GPT_LIST_DEVS),
> > + gShellGptHiiHandle,
> > + MapPath,
> > + BufferForSize);
> > + if (BlkIo->Media->ReadOnly) {
> > + Print (L"Read-Only! ");
> > + }
> > + if (!BlkIo->Media->MediaPresent) {
> > + Print (L"No Media! ");
> > + }
> > + if (!EFI_ERROR (PartitionGetGptTables (DiskIo, BlkIo))) {
> > + Print (L"Valid GPT. ");
> > + }
> > + if (BlkIo->Media->RemovableMedia) {
> > + Print (L"Removable device.");
> > + }
> > + Print (L"\n");
> > + DevCount++;
> > + }
> > + Print (L"\r\n");
> > + if (DevCount) {
> > + Print (L"%d potentially partitionable device(s) found\n", DevCount);
> > + } else {
> > + Print (L"No potentially partitionable device(s) found\n");
> > + }
> > +
> > + GptCleanupGlobals ();
> > + return EFI_SUCCESS;
> > +}
> > +
> > +SHELL_STATUS
> > +EFIAPI
> > +ShellCommandRunGpt (
> > + IN EFI_HANDLE ImageHandle,
> > + IN EFI_SYSTEM_TABLE *SystemTable
> > + )
> > +{
> > + EFI_STATUS Status;
> > + LIST_ENTRY *CheckPackage;
> > + EFI_PHYSICAL_ADDRESS Address = 0, Offset = 0;
> > + UINT64 PartAttributes = 0;
> > + EFI_GUID PartTypeGuid = { 0 };
> > + SHELL_FILE_HANDLE FileHandle = NULL;
> > + UINT64 ByteCount, FileSize;
> > + UINTN I;
> > + UINT8 *Buffer = NULL, *FileBuffer = NULL;
> > +
> > + CHAR16 * ProblemParam,*FilePath;
> > + CONST CHAR16 *AddressStr = NULL, *OffsetStr = NULL;
> > + CONST CHAR16 *PartName = NULL, *NewPartName = NULL,
> > *AttrStr = NULL,
> > + *GuidStr = NULL, *VolumeName = NULL;
> > + CONST CHAR16 *LengthStr = NULL, *FileStr = NULL;
> > + BOOLEAN AddrFlag = FALSE, LengthFlag = TRUE, FileFlag = FALSE,
> > GuidFlag = FALSE, OffsetFlag = TRUE;
> > + BOOLEAN PartNameFlag = TRUE, NewPartNameFlag = FALSE,
> > AttrFlag = FALSE;
> > + UINTN Flag = 0, CheckFlag = 0;
> > + CONST CHAR16 *BlockName;
> > + EFI_DEVICE_PATH_PROTOCOL *DevPath;
> > + EFI_BLOCK_IO_PROTOCOL *BlockIo;
> > + EFI_DISK_IO_PROTOCOL *DiskIo;
> > + EFI_HANDLE BlockIoHandle;
> > + MOD_PARAMS ModParams;
> > + EFI_PARTITION_ENTRY *Entry;
> > + UINTN NumKnownPartTypesEntries;
> > + BOOLEAN TableNotEmpty, NoPrompt = FALSE, Quiet = TRUE;
> > + UINT64 TimeStampB, TimeStampE, SpeedKB, Freq;
> > +
> > + // Parse Shell command line
> > + Status = ShellInitialize ();
> > + if (EFI_ERROR (Status)) {
> > + PrintErr (L"Cannot initialize Shell", Status);
> > + ASSERT_EFI_ERROR (Status);
> > + return SHELL_ABORTED;
> > + }
> > +
> > + Status = ShellCommandLineParse (ParamList, &CheckPackage,
> > &ProblemParam, TRUE);
> > + if (EFI_ERROR (Status)) {
> > + PrintErr (L"Error while parsing command line", Status);
> > + return SHELL_ABORTED;
> > + }
> > +
> > + TimeStampB = 0;
> > + TimeStampE = 0;
> > +
> > + NoPrompt = ShellCommandLineGetFlag (CheckPackage, L"-yes");
> > + Quiet = !ShellCommandLineGetFlag (CheckPackage, L"-verbose");
> > +
> > + Freq = GetPerformanceCounterProperties (NULL, NULL);
> > +
> > + // Check flags provided by user
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"clear") << 0);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"create") << 1);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"list") << 2);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"sync") << 3);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"typesinfo") << 4);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"delete") << 5);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"info") << 6);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"read") << 7);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"readfile") << 8);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"rename") << 9);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"setattr") << 10);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"settype") << 11);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"write") << 12);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"writefile") << 13);
> > + Flag |= (ShellCommandLineGetFlag (CheckPackage, L"fatformat") << 14);
> > +
> > + PartitionGetKnownType ((UINTN)(-1), &NumKnownPartTypesEntries);
> > +
> > + if (Flag & TYPES_INFO) {
> > + UINTN Index;
> > +
> > + Print (L" No\t%-36s\tGUID\r\n", L"Type name");
> > + Print (L" ---- ---------------------------------- ----------------------------------
> --
> > \n");
> > + for (Index = 0; Index < NumKnownPartTypesEntries; Index++) {
> > + EFI_KNOWN_PARTITION_TYPE *PartType;
> > +
> > + PartType = PartitionGetKnownType (Index, NULL);
> > + if (PartType == NULL) {
> > + break;
> > + }
> > + Print (L" %3d\t%-36s\t%g\n", Index, PartType->TypeName,
> &PartType-
> > >TypeGuid);
> > + }
> > + if (Flag == TYPES_INFO) {
> > + return SHELL_SUCCESS;
> > + }
> > + }
> > + // Start parsing the command.
> > + // Generally command is:
> > + // block_name:bootpart_no addr or filename offset
> > +
> > + BlockName = ShellCommandLineGetRawValue (CheckPackage, 1);
> > + if (BlockName == NULL) {
> > + if (Flag & LIST) {
> > + Status = FindAndPrintPartitionableDevices ();
> > + if (EFI_ERROR (Status)) {
> > + PrintErr (L"Error getting list of partitionable devices", Status);
> > + Status = SHELL_ABORTED;
> > + }
> > + return Status;
> > + }
> > + PrintErr (L"Missing block device name", EFI_INVALID_PARAMETER);
> > + return SHELL_INVALID_PARAMETER;
> > + }
> > +
> > + // Find device handle by mapped name
> > + if (gEfiShellProtocol->GetDevicePathFromMap (BlockName) == NULL) {
> > + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
> > gShellGptHiiHandle, gAppName, BlockName);
> > + Status = SHELL_INVALID_PARAMETER;
> > + } else {
> > + DevPath = (EFI_DEVICE_PATH_PROTOCOL *)gEfiShellProtocol-
> > >GetDevicePathFromMap (BlockName);
> > + if (gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevPath, NULL)
> > == EFI_NOT_FOUND) {
> > + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN
> > (STR_GEN_MAP_PROTOCOL), gShellGptHiiHandle, gAppName, BlockName,
> > L"BlockIo");
> > + Status = SHELL_INVALID_PARAMETER;
> > + }
> > + }
> > +
> > + if (Status) {
> > + return SHELL_INVALID_PARAMETER;
> > + }
> > +
> > + BlockIoHandle = 0;
> > +
> > + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid,
> > (EFI_DEVICE_PATH_PROTOCOL **)&DevPath, &BlockIoHandle);
> > + if (EFI_ERROR (Status)) {
> > + goto CleanUp;
> > + }
> > +
> > + Status = gBS->OpenProtocol (BlockIoHandle, &gEfiBlockIoProtocolGuid,
> > (VOID **)&BlockIo, gImageHandle, NULL,
> > EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> > + if (EFI_ERROR (Status)) {
> > + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN
> > (STR_GEN_MAP_PROTOCOL), gShellGptHiiHandle, gAppName, BlockName,
> > L"BlockIo");
> > + goto CleanUp;
> > + }
> > +
> > + Status = gBS->HandleProtocol (
> > + BlockIoHandle,
> > + &gEfiDiskIoProtocolGuid,
> > + (VOID **)&DiskIo
> > + );
> > + if (EFI_ERROR (Status)) {
> > + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN
> > (STR_GEN_MAP_PROTOCOL), gShellGptHiiHandle, gAppName, BlockName,
> > L"DiskIo");
> > + goto CleanUp;
> > + }
> > +
> > + CheckFlag = Flag;
> > + for (I = 0; CheckFlag; CheckFlag >>= 1) {
> > + I += CheckFlag & 1;
> > + if (I > 1) {
> > + PrintErr (L"Too many flags", EFI_INVALID_PARAMETER);
> > + Status = SHELL_INVALID_PARAMETER;
> > + goto CleanUp;
> > + }
> > + }
> > +
> > + if (Flag & SYNC) {
> > + // Let the Partition table driver know that
> > + // we want to reread the tables
> > + Status = gBS->ReinstallProtocolInterface (
> > + BlockIoHandle,
> > + &gEfiBlockIoProtocolGuid,
> > + BlockIo,
> > + BlockIo
> > + );
> > + Status = SHELL_SUCCESS;
> > + goto CleanUp;
> > + }
> > +
> > + if (!IsPartitionableDevicePath (DevicePathFromHandle (BlockIoHandle)))
> {
> > + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
> > gShellGptHiiHandle, gAppName, BlockName);
> > + Print (L"%s is not a raw block device\n", BlockName);
> > + Status = SHELL_INVALID_PARAMETER;
> > + goto CleanUp;
> > + }
> > +
> > + if (!BlockIo->Media->MediaPresent) {
> > + PrintErr (L"Media is not present!\n", EFI_NO_MEDIA);
> > + Status = EFI_NO_MEDIA;
> > + goto CleanUp;
> > + }
> > +
> > + // Preload GPT tables with validation
> > + Status = PartitionGetGptTables (DiskIo, BlockIo);
> > + if (EFI_ERROR (Status)) {
> > + BOOLEAN CanContinue;
> > +
> > + CanContinue = (Flag & CREATE) || (Flag & CLEAR) || (Flag &
> > FAT_FORMAT);
> > + if (Status != EFI_NOT_FOUND) {
> > + PrintErr (L"Unexpected error getting GPT tables", Status);
> > + goto CleanUp;
> > + } else {
> > + if (!CanContinue) {
> > + PrintErr (L"No GPT table found. Create first", Status);
> > + goto CleanUp;
> > + }
> > + }
> > + }
> > +
> > + // Do we have any partitions already?
> > + TableNotEmpty = (PartitionFindPartitionByCriteria (NULL, 0, 0,
> SRC_ANY) !=
> > NULL);
> > +
> > + Status = SHELL_INVALID_PARAMETER;
> > +
> > + if ((Flag < LIST) ||
> > + (Flag & DELETE) ||
> > + (Flag > READ_FILE)
> > + ) {
> > + if (BlockIo->Media->ReadOnly) {
> > + Status = EFI_INVALID_PARAMETER;
> > + PrintErr (L"Cannot write to a read-only device", Status);
> > + goto CleanUp;
> > + }
> > + }
> > +
> > + if (BlockIo->Media->RemovableMedia) {
> > + Print (L"%s is a removable device. Just a note\n", BlockName);
> > + }
> > +
> > + switch (Flag) {
> > + case INFO:
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + OffsetFlag = FALSE;
> > + LengthFlag = FALSE;
> > + break;
> > + case LIST:
> > + {
> > + UINTN NumEntries;
> > +
> > + NumEntries = PartitionListGptEntries ();
> > + if (NumEntries == 0) {
> > + Print (L"gpt: GPT is valid on %s, but no partition(s) defined yet. Use
> > create\n", BlockName);
> > + }
> > + Status = SHELL_SUCCESS;
> > + goto CleanUp;
> > + break;
> > + }
> > + case CLEAR:
> > + if (TableNotEmpty) {
> > + // Tell the user what he/she is doing...
> > + ShellPrintHiiEx (-1, -1,
> > + NULL, STRING_TOKEN (STR_GPT_NOT_EMPTY),
> > + gShellGptHiiHandle,
> > + BlockName
> > + );
> > + }
> > +
> > + // Even if GPT tables do not exist, there might be something.
> > + // Warn the user and double sure it is the intention,
> > + // to prevent a user from bricking a device (JTAG would be needed to
> > recover)
> > + // by overwriting an ATF boot device. However with NoPrompt on, the
> > user is
> > + // responsible for operation because there is no confirmation
> (assuming
> > yes on all queries).
> > + if ((NoPrompt) || (!GptPromptYesNo (STRING_TOKEN
> > (STR_GPT_CLEAR_SURE)) &&
> > + (!GptPromptYesNo (STRING_TOKEN
> > (STR_GPT_ABSOLUTELY_SURE))))
> > + ) {
> > + PartitionGptClearAll ();
> > + }
> > + Status = SHELL_SUCCESS;
> > + goto CleanUp;
> > + break;
> > + case CREATE:
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + OffsetStr = ShellCommandLineGetRawValue (CheckPackage, 3);
> > + LengthStr = ShellCommandLineGetRawValue (CheckPackage, 4);
> > + AttrStr = ShellCommandLineGetRawValue (CheckPackage, 5);
> > + GuidStr = ShellCommandLineGetValue (CheckPackage, L"-type");
> > + GuidFlag = TRUE;
> > + break;
> > + case DELETE:
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + LengthFlag = FALSE;
> > + OffsetFlag = FALSE;
> > + break;
> > + case RENAME:
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + NewPartName = ShellCommandLineGetRawValue (CheckPackage, 3);
> > + NewPartNameFlag = TRUE;
> > + LengthFlag = FALSE;
> > + OffsetFlag = FALSE;
> > + break;
> > + case SETATTR:
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + AttrStr = ShellCommandLineGetRawValue (CheckPackage, 3);
> > + AttrFlag = TRUE;
> > + LengthFlag = FALSE;
> > + OffsetFlag = FALSE;
> > + break;
> > + case SETTYPE:
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + GuidStr = ShellCommandLineGetValue (CheckPackage, L"-type");
> > + GuidFlag = TRUE;
> > + LengthFlag = FALSE;
> > + OffsetFlag = FALSE;
> > + break;
> > + case FAT_FORMAT:
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + VolumeName = ShellCommandLineGetRawValue (CheckPackage, 3);
> > + LengthFlag = FALSE;
> > + OffsetFlag = FALSE;
> > + PartNameFlag = (PartName != NULL);
> > + if (!PartNameFlag && TableNotEmpty) {
> > + // Tell the user what he/she is doing...
> > + ShellPrintHiiEx (-1, -1,
> > + NULL, STRING_TOKEN (STR_GPT_NOT_EMPTY),
> > + gShellGptHiiHandle,
> > + BlockName
> > + );
> > + }
> > + break;
> > + // Fall through
> > + case READ:
> > + case WRITE:
> > + AddressStr = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 3);
> > + OffsetStr = ShellCommandLineGetRawValue (CheckPackage, 4);
> > + LengthStr = ShellCommandLineGetRawValue (CheckPackage, 5);
> > + AddrFlag = TRUE;
> > + break;
> > + case READ_FILE:
> > + FileStr = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 3);
> > + OffsetStr = ShellCommandLineGetRawValue (CheckPackage, 4);
> > + LengthStr = ShellCommandLineGetRawValue (CheckPackage, 5);
> > + FileFlag = TRUE;
> > + break;
> > + case WRITE_FILE:
> > + FileStr = ShellCommandLineGetRawValue (CheckPackage, 2);
> > + PartName = ShellCommandLineGetRawValue (CheckPackage, 3);
> > + OffsetStr = ShellCommandLineGetRawValue (CheckPackage, 4);
> > + LengthFlag = FALSE;
> > + FileFlag = TRUE;
> > + break;
> > + default:
> > + Print (L"%s: Unsupported command. Try \"help %s\"", gAppName);
> > + Status = SHELL_INVALID_PARAMETER;
> > + goto CleanUp;
> > + }
> > +
> > + // Read address parameter
> > + if ((AddressStr == NULL) & AddrFlag) {
> > + PrintErr (L"No address parameter", EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + } else if (AddrFlag) {
> > + Address = ShellHexStrToUintn (AddressStr);
> > + if (Address == (UINTN)(-1)) {
> > + PrintErr (L"Wrong address parameter", EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + }
> > + }
> > +
> > + if ((PartName == NULL) & PartNameFlag) {
> > + PrintErr (L"Missing partition name", EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + } else if (PartNameFlag) {
> > + if (StrSize (PartName) > MAX_PARTITION_NAME_LENGTH) {
> > + PrintErr (L"Partition name is too long (max 36 chars)",
> > EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + }
> > + }
> > +
> > + // Read offset parameter
> > + if ((OffsetStr == NULL) & OffsetFlag) {
> > + PrintErr (L"No offset Parameter", EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + } else if (OffsetFlag) {
> > + Offset = ShellHexStrToUintn (OffsetStr);
> > + if (Offset < 0) {
> > + Print (L"%s: Wrong offset parameter: %s\n", gAppName, OffsetStr);
> > + goto CleanUp;
> > + }
> > + }
> > +
> > + // Read length parameter
> > + if ((LengthStr == NULL) & LengthFlag) {
> > + PrintErr (L"No length parameter", EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + } else if (LengthFlag) {
> > + ByteCount = (UINT64)ShellStrToUintn (LengthStr);
> > + if (ByteCount < 0) {
> > + Print (L"%s: Wrong length parameter %s!\n", gAppName, LengthStr);
> > + goto CleanUp;
> > + }
> > + }
> > +
> > + if ((NewPartName == NULL) & NewPartNameFlag) {
> > + PrintErr (L"Missing name to be assigned to partition",
> > EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + } else if (NewPartNameFlag) {
> > + if (StrSize (NewPartName) > MAX_PARTITION_NAME_LENGTH) {
> > + PrintErr (L"Partition name is too long (max 36 chars)",
> > EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + }
> > + }
> > +
> > + if ((AttrStr == NULL) & AttrFlag) {
> > + PrintErr (L"Missing attributes parameter", EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + } else if (AttrStr) {
> > + PartAttributes = (UINT64)ShellStrToUintn (AttrStr);
> > + }
> > +
> > + if ((GuidStr == NULL) & GuidFlag) {
> > + PrintErr (L"Missing partition type GUID parameter",
> > EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + } else if (GuidFlag) {
> > + Status = SHELL_INVALID_PARAMETER;
> > + if (InternalShellIsHexOrDecimalNumber (GuidStr, FALSE, TRUE, FALSE)) {
> > + UINTN Ordinal;
> > +
> > + Ordinal = ShellStrToUintn (GuidStr);
> > + if (Ordinal < NumKnownPartTypesEntries) {
> > + PartTypeGuid = PartitionGetKnownType (Ordinal, NULL)->TypeGuid;
> > + Status = SHELL_SUCCESS;
> > + } else {
> > + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
> > gShellGptHiiHandle, gAppName, GuidStr);
> > + goto CleanUp;
> > + }
> > + } else {
> > + Status = ConvertStringToGuid (GuidStr, &PartTypeGuid);
> > + if ((EFI_ERROR (Status)) || (IsZeroGuid (&PartTypeGuid))) {
> > + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
> > gShellGptHiiHandle, gAppName, GuidStr);
> > + Status = SHELL_INVALID_PARAMETER;
> > + goto CleanUp;
> > + }
> > + }
> > + }
> > +
> > + if (FileFlag) {
> > + // Read FilePath parameter
> > + if (FileStr == NULL) {
> > + PrintErr (L"No FilePath parameter", EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + } else {
> > + FilePath = (CHAR16 *)FileStr;
> > + Status = ShellIsFile (FilePath);
> > + // When read file into flash, file doesn't have to exist
> > + if (EFI_ERROR (Status && !(Flag & READ_FILE))) {
> > + PrintErr (L"Wrong FilePath parameter", Status);
> > + Status = SHELL_INVALID_PARAMETER;
> > + goto CleanUp;
> > + }
> > + }
> > +
> > + Status = OpenAndPrepareFile (FilePath, &FileHandle, ((Flag &
> > READ_FILE) != 0));
> > + if (EFI_ERROR (Status)) {
> > + Print (L"Error %r while preparing file %s", Status, FilePath);
> > + Status = SHELL_ABORTED;
> > + goto CleanUp;
> > + }
> > +
> > + // Get file size in order to check correctness at the end of transfer
> > + if (Flag & (WRITE_FILE)) {
> > + Status = FileHandleGetSize (FileHandle, &FileSize);
> > + if (EFI_ERROR (Status)) {
> > + PrintErr (L"Cannot get file size", Status);
> > + Status = SHELL_ABORTED;
> > + goto CleanUp;
> > + }
> > + ByteCount = (UINT64)FileSize;
> > + }
> > +
> > + FileBuffer = AllocateZeroPool ((UINTN)ByteCount);
> > + if (FileBuffer == NULL) {
> > + PrintErr (L"Cannot allocate memory", EFI_OUT_OF_RESOURCES);
> > + Status = SHELL_OUT_OF_RESOURCES;
> > + goto Error_Close_File;
> > + }
> > +
> > + // Read file content and store it in FileBuffer
> > + if (Flag & (WRITE_FILE)) {
> > + if (!Quiet) {
> > + Print (L"Reading %s...\r", FilePath);
> > + }
> > + Status = FileHandleRead (FileHandle, &ByteCount, FileBuffer);
> > + if (EFI_ERROR (Status)) {
> > + PrintErr (L"Read from file error", Status);
> > + Status = SHELL_ABORTED;
> > + goto Error_Free_Buffer;
> > + } else if (ByteCount != (UINTN)FileSize) {
> > + PrintErr (L"Not whole file read. Abort", EFI_DEVICE_ERROR);
> > + Status = SHELL_DEVICE_ERROR;
> > + goto Error_Free_Buffer;
> > + }
> > + if (!Quiet) {
> > + Print (L"Writing %s into device %s, partition %s...\n", FilePath,
> > BlockName, PartName);
> > + }
> > + }
> > + }
> > +
> > + Buffer = (UINT8 *)Address;
> > + if (FileFlag) {
> > + Buffer = FileBuffer;
> > + }
> > +
> > + if (Flag > TYPES_INFO) {
> > + Entry = PartitionFindPartitionByCriteria (PartName, 0, 0, SRC_BY_NAME);
> > + if (!Entry && PartName && (InternalShellIsHexOrDecimalNumber
> > (PartName, FALSE, TRUE, FALSE))) {
> > + Entry = PartitionFindPartitionByCriteria (PartName, 0, 0, SRC_BY_NUM);
> > + }
> > + if ((!Entry) && (PartNameFlag)) {
> > + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
> > gShellGptHiiHandle, gAppName, PartName);
> > + Print (L"Could not find partition %s (case-sensitive). Make sure the
> name
> > is spelled properly\n", PartName);
> > + Status = SHELL_NOT_FOUND;
> > + goto CleanUp;
> > + }
> > + }
> > +
> > + switch (Flag) {
> > + case CREATE:
> > + PartitionGptCreatePartition (
> > + PartName,
> > + Offset, // Lba. If 0, the next available is assumed
> > + ByteCount, // in MegaBytes. If 0 the whole remaining space is
> assumed
> > + PartAttributes,
> > + PartTypeGuid);
> > + break;
> > + case DELETE:
> > + ModParams.PartName = PartName;
> > + ShellPrintHiiEx (-1, -1,
> > + NULL, STRING_TOKEN (STR_GPT_DELETE_WARNING),
> > + gShellGptHiiHandle,
> > + Entry->PartitionName
> > + );
> > + if ((NoPrompt) || (!GptPromptYesNo (STRING_TOKEN
> > (STR_GPT_ABSOLUTELY_SURE)))) {
> > + Status = PartitionGptModifyPartition (
> > + Entry, &ModParams, MOD_DELETE);
> > + if (EFI_ERROR (Status)) {
> > + PrintErr (L"Error deleting the partition", Status);
> > + Status = SHELL_ABORTED;
> > + goto CleanUp;
> > + }
> > + Status = SHELL_SUCCESS;
> > + } else {
> > + Status = SHELL_ABORTED;
> > + }
> > + break;
> > + case FAT_FORMAT:
> > + {
> > + EFI_LBA StartingLBA, EndingLBA;
> > + CHAR8 LabelName[12];
> > +
> > + if (VolumeName) {
> > + if (StrLen (VolumeName) > 11) {
> > + Status = EFI_INVALID_PARAMETER;
> > + PrintErr (L"The volume label is too long", Status);
> > + Status = SHELL_INVALID_PARAMETER;
> > + goto CleanUp;
> > + }
> > + UnicodeStrToAsciiStr (VolumeName, (CHAR8 *)LabelName);
> > + }
> > + ShellPrintHiiEx (-1, -1,
> > + NULL, STRING_TOKEN (STR_GPT_FORMAT_WARNING),
> > + gShellGptHiiHandle,
> > + Entry ? Entry->PartitionName : BlockName
> > + );
> > +
> > + if ((NoPrompt) || (!GptPromptYesNo (STRING_TOKEN
> > (STR_GPT_FORMAT_SURE)) &&
> > + (!GptPromptYesNo (STRING_TOKEN
> > (STR_GPT_ABSOLUTELY_SURE))))
> > + ) {
> > + StartingLBA = 0;
> > + EndingLBA = BlockIo->Media->LastBlock;
> > + if (Entry) {
> > + StartingLBA = Entry->StartingLBA;
> > + EndingLBA = Entry->EndingLBA;
> > + }
> > + if (!Quiet) {
> > + Print (L"Formatting %s to FAT32...\r", PartNameFlag ? Entry-
> > >PartitionName : BlockName);
> > + }
> > + Status = FatFormat (StartingLBA, EndingLBA, BlockIo, DiskIo,
> > VolumeName ? LabelName : NULL, TRUE);
> > + if (EFI_ERROR (Status)) {
> > + PrintErr (L"Error formatting the partition to FAT ", Status);
> > + Status = SHELL_ABORTED;
> > + goto CleanUp;
> > + } else if (!Quiet) {
> > + Print (L"%s successfully formatted to FAT. Formatted size %llu
> MiB\n",
> > + PartNameFlag ? Entry->PartitionName : BlockName,
> > + MultU64x32 (EndingLBA - StartingLBA + 1, BlockIo->Media-
> > >BlockSize) >> 20
> > + );
> > + }
> > + } else {
> > + Status = SHELL_ABORTED;
> > + }
> > + }
> > + break;
> > + case RENAME:
> > + ModParams.PartName = PartName;
> > + ModParams.NewName = NewPartName;
> > + Status = PartitionGptModifyPartition (
> > + Entry, &ModParams, MOD_RENAME);
> > + break;
> > + case SETATTR:
> > + ModParams.Attributes = PartAttributes;
> > + Status = PartitionGptModifyPartition (
> > + Entry, &ModParams, MOD_ATTR);
> > + break;
> > + case SETTYPE:
> > + ModParams.PartTypeGuid = PartTypeGuid;
> > + Status = PartitionGptModifyPartition (
> > + Entry, &ModParams, MOD_TYPE);
> > + break;
> > + case INFO:
> > + PartitionPrintGptPartInfo (Entry);
> > + Status = SHELL_SUCCESS;
> > + break;
> > + case READ:
> > + case READ_FILE:
> > + case WRITE:
> > + case WRITE_FILE:
> > + {
> > + UINT64 MaxBytes;
> > + BOOLEAN OpRead;
> > +
> > + OpRead = ((Flag & READ) || (Flag & READ_FILE));
> > + MaxBytes = MultU64x32 (
> > + Entry->EndingLBA - Entry->StartingLBA,
> > + BlockIo->Media->BlockSize) +
> > + BlockIo->Media->BlockSize -
> > + MultU64x32 (Offset, BlockIo->Media->BlockSize);
> > + if (ByteCount > MaxBytes) {
> > + Status = EFI_INVALID_PARAMETER;
> > + ShellPrintHiiEx (-1, -1,
> > + NULL, (OpRead) ?
> > + STRING_TOKEN (STR_GPT_READ_BOUNDARY) :
> > + STRING_TOKEN (STR_GPT_WRITE_BOUNDARY),
> > + gShellGptHiiHandle,
> > + gAppName,
> > + Entry->PartitionName,
> > + MaxBytes,
> > + ByteCount
> > + );
> > + Status = SHELL_INVALID_PARAMETER;
> > + goto CleanUp;
> > + }
> > +
> > + TimeStampB = GetPerformanceCounter ();
> > + if (OpRead) {
> > + Status = DiskIo->ReadDisk (DiskIo,
> > + BlockIo->Media->MediaId,
> > + MultU64x32 (Offset + Entry->StartingLBA, BlockIo-
> > >Media->BlockSize), ByteCount, Buffer);
> > + } else {
> > + Status = DiskIo->WriteDisk (DiskIo, BlockIo->Media->MediaId,
> > + MultU64x32 (Offset + Entry->StartingLBA, BlockIo-
> > >Media->BlockSize), ByteCount, Buffer);
> > + }
> > + }
> > + break;
> > + default:
> > + Status = SHELL_INVALID_PARAMETER;
> > + PrintErr (L"Unknown command. Try \"help gpt\"",
> > EFI_INVALID_PARAMETER);
> > + goto CleanUp;
> > + }
> > +
> > + if (EFI_ERROR (Status)) {
> > + PrintErr (L"Error while performing transfer\n", Status);
> > + Status = SHELL_ABORTED;
> > + goto CleanUp;
> > + }
> > +
> > + TimeStampE = ((GetPerformanceCounter () - TimeStampB) * 1000) /
> Freq;
> > + SpeedKB = TimeStampE ? (ByteCount / (TimeStampE / 1000)) >> 10 : 0;
> > +
> > + switch (Flag) {
> > + case WRITE:
> > + case WRITE_FILE:
> > + if (!Quiet) {
> > + ShellPrintHiiEx (-1, -1,
> > + NULL,
> > + STRING_TOKEN (STR_GPT_WRITE_OK),
> > + gShellGptHiiHandle,
> > + ByteCount,
> > + Offset,
> > + Entry->PartitionName,
> > + TimeStampE,
> > + SpeedKB
> > + );
> > + }
> > + break;
> > + case READ:
> > + if (!Quiet) {
> > + ShellPrintHiiEx (-1, -1,
> > + NULL,
> > + STRING_TOKEN (STR_GPT_READ_OK),
> > + gShellGptHiiHandle,
> > + ByteCount,
> > + Offset,
> > + Entry->PartitionName,
> > + TimeStampE,
> > + SpeedKB
> > + );
> > + }
> > + break;
> > + case READ_FILE:
> > + Status = FileHandleWrite (FileHandle, &ByteCount, FileBuffer);
> > + if (EFI_ERROR (Status)) {
> > + ShellPrintHiiEx (-1, -1,
> > + NULL,
> > + STRING_TOKEN (STR_GPT_FILE_WRITE_FAIL),
> > + gShellGptHiiHandle,
> > + gAppName,
> > + FilePath,
> > + Status
> > + );
> > + Status = SHELL_DEVICE_ERROR;
> > + goto Error_Free_Buffer;
> > + }
> > +
> > + if (!Quiet) {
> > + ShellPrintHiiEx (-1, -1,
> > + NULL,
> > + STRING_TOKEN (STR_GPT_READFILE_OK),
> > + gShellGptHiiHandle,
> > + ByteCount,
> > + Offset,
> > + Entry->PartitionName,
> > + FilePath,
> > + TimeStampE,
> > + SpeedKB
> > + );
> > + }
> > + break;
> > + }
> > +
> > + if (FileFlag) {
> > + SHELL_FREE_NON_NULL (FileBuffer);
> > + if (FileHandle != NULL) {
> > + ShellCloseFile (&FileHandle);
> > + FileHandle = NULL;
> > + }
> > + }
> > +
> > + Status = SHELL_SUCCESS;
> > +
> > + Error_Free_Buffer:
> > + SHELL_FREE_NON_NULL (FileBuffer);
> > + Error_Close_File:
> > + if (FileHandle) {
> > + ShellCloseFile (&FileHandle);
> > + }
> > + CleanUp:
> > + if (BlockIoHandle) {
> > + // By UEFI Spec blocks must be flushed
> > + BlockIo->FlushBlocks (BlockIo);
> > + gBS->CloseProtocol (BlockIoHandle, &gEfiBlockIoProtocolGuid,
> > gImageHandle, NULL);
> > + }
> > +
> > + GptCleanupGlobals ();
> > +
> > + ShellCommandLineFreeVarList (CheckPackage);
> > +
> > + if (EFI_ERROR (Status)) {
> > + Status = SHELL_ABORTED;
> > + }
> > +
> > + return Status;
> > +}
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +ShellGptLibConstructor (
> > + IN EFI_HANDLE ImageHandle,
> > + IN EFI_SYSTEM_TABLE *SystemTable
> > + )
> > +{
> > + gShellGptHiiHandle = NULL;
> > +
> > + gShellGptHiiHandle = HiiAddPackages (
> > + &gShellGptHiiGuid, gImageHandle,
> > + UefiShellGptCommandLibStrings, NULL
> > + );
> > + if (gShellGptHiiHandle == NULL) {
> > + return EFI_DEVICE_ERROR;
> > + }
> > +
> > + ShellCommandRegisterCommandName (
> > + gAppName, ShellCommandRunGpt,
> ShellCommandGetManFileNameGpt,
> > 0,
> > + gAppName, TRUE, gShellGptHiiHandle, STRING_TOKEN
> > (STR_GET_HELP_GPT)
> > + );
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +ShellGptLibDestructor (
> > + IN EFI_HANDLE ImageHandle,
> > + IN EFI_SYSTEM_TABLE *SystemTable
> > + )
> > +{
> > +
> > + if (gShellGptHiiHandle != NULL) {
> > + HiiRemovePackages (gShellGptHiiHandle);
> > + }
> > + return EFI_SUCCESS;
> > +}
> > diff --git
> > a/ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.inf
> >
> b/ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.inf
> > new file mode 100644
> > index 000000000000..1be4b1ab0f11
> > --- /dev/null
> > +++
> >
> b/ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.inf
> > @@ -0,0 +1,79 @@
> > +#
> > +# Marvell BSD License Option
> > +#
> > +# If you received this File from Marvell, you may opt to use, redistribute
> > +# and/or modify this File under the following licensing terms.
> > +# Redistribution and use in source and binary forms, with or without
> > +# modification, are permitted provided that the following conditions are
> > met:
> > +#
> > +# * Redistributions of source code must retain the above copyright notice,
> > +# this list of conditions and the following disclaimer.
> > +#
> > +# * Redistributions in binary form must reproduce the above copyright
> > +# notice, this list of conditions and the following disclaimer in the
> > +# documentation and/or other materials provided with the distribution.
> > +#
> > +# * Neither the name of Marvell nor the names of its contributors may be
> > +# used to endorse or promote products derived from this software
> without
> > +# specific prior written permission.
> > +#
> > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > CONTRIBUTORS "AS IS"
> > +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> > LIMITED TO, THE
> > +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> > PARTICULAR PURPOSE ARE
> > +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > CONTRIBUTORS BE LIABLE
> > +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > CONSEQUENTIAL
> > +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> > SUBSTITUTE GOODS OR
> > +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> INTERRUPTION)
> > HOWEVER
> > +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> > STRICT LIABILITY,
> > +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
> WAY
> > OUT OF THE USE
> > +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> > DAMAGE.
> > +#
> > +
> > +#
> > +# Portions Copyright (C) 2016 Broadcom
> > +#
> > +
> > +[Defines]
> > + INF_VERSION = 0x00010006
> > + BASE_NAME = UefiShellGptCommandLib
> > + FILE_GUID = F62ACF25-0D15-22F5-E642-FFB6515E00D7
> > + MODULE_TYPE = UEFI_APPLICATION
> > + VERSION_STRING = 0.1
> > + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
> > + CONSTRUCTOR = ShellGptLibConstructor
> > + DESTRUCTOR = ShellGptLibDestructor
> > +
> > +[Sources]
> > + FatFormat.c
> > + GptWorker.c
> > + UefiShellGptCommandLib.c
> > + UefiShellGptCommandLib.uni
> > +
> > +[Packages]
> > + MdeModulePkg/MdeModulePkg.dec
> > + MdePkg/MdePkg.dec
> > + ShellPkg/ShellPkg.dec
> > +
> > +[LibraryClasses]
> > + BaseLib
> > + BaseMemoryLib
> > + DebugLib
> > + DevicePathLib
> > + FileHandleLib
> > + HiiLib
> > + MemoryAllocationLib
> > + PcdLib
> > + ShellCommandLib
> > + ShellLib
> > + UefiBootServicesTableLib
> > + UefiRuntimeServicesTableLib
> > + UefiLib
> > +
> > +[Protocols]
> > + gEfiBlockIoProtocolGuid
> > + gEfiDevicePathProtocolGuid
> > + gEfiDiskIoProtocolGuid
> > +
> > +[Guids]
> > + gShellGptHiiGuid
> > + gEfiPartTypeUnusedGuid ## SOMETIMES_CONSUMES ##
> GUID
> > diff --git
> >
> a/ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.uni
> >
> b/ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.uni
> > new file mode 100644
> > index 000000000000..55bcb42cfeb3
> > --- /dev/null
> > +++
> >
> b/ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.uni
> > @@ -0,0 +1,117 @@
> >
> +/*********************************************************
> > **********************
> > +Copyright (C) 2016 Marvell International Ltd.
> > +
> > +Marvell BSD License Option
> > +
> > +If you received this File from Marvell, you may opt to use, redistribute
> > and/or
> > +modify this File under the following licensing terms.
> > +Redistribution and use in source and binary forms, with or without
> > modification,
> > +are permitted provided that the following conditions are met:
> > +
> > + * Redistributions of source code must retain the above copyright
> notice,
> > + this list of conditions and the following disclaimer.
> > +
> > + * Redistributions in binary form must reproduce the above copyright
> > + notice, this list of conditions and the following disclaimer in the
> > + documentation and/or other materials provided with the distribution.
> > +
> > + * Neither the name of Marvell nor the names of its contributors may
> be
> > + used to endorse or promote products derived from this software
> > without
> > + specific prior written permission.
> > +
> > +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > CONTRIBUTORS "AS IS" AND
> > +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> TO,
> > THE IMPLIED
> > +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> > PURPOSE ARE
> > +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > CONTRIBUTORS BE LIABLE FOR
> > +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > CONSEQUENTIAL DAMAGES
> > +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
> GOODS
> > OR SERVICES;
> > +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> HOWEVER
> > CAUSED AND ON
> > +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> > TORT
> > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> > THE USE OF THIS
> > +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > +
> >
> +*********************************************************
> > **********************/
> > +
> > +/* Portions Copyright (C) 2016 Broadcom */
> > +/=#
> > +
> > +#langdef en-US "english"
> > +
> > +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid
> > argument - '%H%s%N'\r\n"
> > +#string STR_GEN_MAP_PROTOCOL #language en-US "%H%s%N:
> > Mapped device '%B%s%N' does not have protocol %B%s%N\r\n"
> > +
> > +#string STR_GPT_ERROR #language en-US "%H%s%N: %r - %s\r\n"
> > +#string STR_GPT_NOT_EMPTY #language en-US "%H%s%N:
> WARNING!!!
> > This device has valid GPT partition tables!\r\n"
> > +#string STR_GPT_CLEAR_SURE #language en-US "Are you sure you
> want
> > to clear the GPT tables on this device? %BY%Nes, %BN%No "
> > +#string STR_GPT_ABSOLUTELY_SURE #language en-US "\r\nAre you ***
> > ABSOLUTELY SURE *** you want to perform this
> > operation ? %BY%Nes, %BN%No "
> > +#string STR_GPT_FORMAT_WARNING #language en-US "%H%s%N:
> > WARNING!!! Formatting of this partition will destroy all data on it!\r\n"
> > +#string STR_GPT_FORMAT_SURE #language en-US "Are you sure you
> > want to format this partition to FAT32 and destroy all data on
> > it ? %BY%Nes, %BN%No "
> > +#string STR_GPT_DELETE_WARNING #language en-US "%H%s%N:
> Deleting
> > of this partition will make data on it unreachable!\r\n"
> > +#string STR_GPT_READ_BOUNDARY #language en-US "%H%s%N:
> Attempt
> > to read beyond %H%s%N partition boundary (can read upto %llu bytes
> from
> > the given offset, requested %llu bytes)\r\n"
> > +#string STR_GPT_WRITE_BOUNDARY #language en-US "%H%s%N:
> > Attempt to write beyond %H%s%N partition boundary (can write upto %llu
> > bytes from the given offset, requested %llu bytes)\r\n"
> > +#string STR_GPT_FILE_WRITE_FAIL #language en-US "%H%s%N: Failed to
> > write to the file %s, error %r\r\n"
> > +
> > +#string STR_GPT_WRITE_OK #language en-US "Written %llu bytes at
> > offset 0x%x, partition %s. Elapsed time %llums (%llu KB/s)\r\n"
> > +#string STR_GPT_READ_OK #language en-US "Read %llu bytes from
> > offset 0x%x, partition %s. Elapsed time %llums (%llu KB/s)\r\n"
> > +#string STR_GPT_READFILE_OK #language en-US "Read %llu bytes from
> > offset 0x%x, partition %s into file %s. Elapsed time %llums (%llu KB/s)\r\n"
> > +#string STR_GPT_LIST_DEVS #language en-US " %H%+6s%N %+8s "
> > +
> > +#string STR_GET_HELP_GPT #language en-US ""
> > +".TH gpt 0 "GPT partition manager."\r\n"
> > +".SH NAME\r\n"
> > +"Manages GPT partitions on a block device.\r\n"
> > +".SH SYNOPSIS\r\n"
> > +" \r\n"
> > +"gpt [read | readfile | write | writefile | list | info | clear |\r\n"
> > +" create | delete | rename | setattrs | sync | fatformat | -typesinfo | -
> yes]
> > \r\n"
> > +"This is a complex utility. Please see examples for usage info\r\n"
> > +".SH OPTIONS\r\n"
> > +" \r\n"
> > +" Device - Block device to be used for the operation\r\n"
> > +" Length - Number of bytes to transfer (for read/write))\r\n"
> > +" Address - Address in RAM to store/load data\r\n"
> > +" Offset - Offset (in blocks) from beggining of the specifie partition to
> > store/load data\r\n"
> > +" FilePath - Path to file to read data into or write/update data
> from\r\n"
> > +" -yes - Assume yes for all queries, do not prompt\r\n\r\n"
> > +".SH EXAMPLES\r\n"
> > +" \r\n"
> > +"EXAMPLES:\r\n"
> > +"Get the list of available partitionable block device(s)\r\n"
> > +" gpt %Hlist%N\r\n"
> > +"Get info on the particular partition with name PartitionName on the
> block
> > device blk0:\r\n"
> > +" gpt %Hinfo%N blk0: PartitionName\r\n"
> > +"List all available GPT partitions on the block device blk0:\r\n"
> > +" gpt list blk0:\r\n"
> > +"Note: the ordinal number shown by this command can be used as a
> > partition name in any command requiring partition name\r\n"
> > +"Thus gpt info blk0: 1 is valid if there is a partition with ordinal 1 present in
> > the output of gpt list command\r\n"
> > +"Get information on all recognized partition types\r\n"
> > +" gpt %Htypesinfo%N\r\n"
> > +"Clear partitions information and install empty GPT tables for a block
> device
> > blk0:\r\n"
> > +" gpt %Hclear%N blk0:\r\n"
> > +"Create a GPT partition with name PartitionName and type EFI SYSTEM in
> > the GPT table, using the next available LBA, with size\r\n"
> > +"64MiB, with system attribute, on block device blk0:\r\n"
> > +" gpt %Hcreate%N blk0: PartitionName 0 64 1 -type 0\r\n"
> > +"Same as above, but now the partition type is not known to the gpt utility,
> > so use some GUID known to a 3rd party\r\n"
> > +" gpt create blk0: PartitionName 0 64 1 -type 44581A4A-C834-D1A6-2602-
> > 9D522A8F2307\r\n"
> > +"Rename the GPT partition PartitionName on blk0: to
> > NewPartitionName\r\n"
> > +" gpt %Hrename%N blk0: PartitionName NewPartitionName\r\n"
> > +"Have the PartitionDxe driver to re-read GPT tables on a block device
> > blk0:(after they were updated with gpt utility)\r\n"
> > +" gpt %Hsync%N blk0:\r\n"
> > +"Read 4K from block offset 0x0e000 in Partition named PartitionName of
> > the block device at blk0: into RAM at address 0x100000\r\n"
> > +" gpt %Hread%N blk0: 0x100000 PartitionName 0xe000 4096\r\n"
> > +"Write 512 bytes from 0x200000 at RAM into the block device at blk0:
> > partition PartitionName at offset 0x1000\r\n"
> > +" gpt %Hwrite%N blk0: 0x200000 PartitionName 0x1000 512\r\n"
> > +"Read 0x3000 bytes from 0x0 offset of Partition PartitionName at the
> block
> > device blk0: into file fs2:file.bin\r\n"
> > +" gpt %Hreadfile%N blk0: fs2:file.bin PartitionName 0x0 0x3000\r\n"
> > +"Write contents of file fs2:file.bin into partition named PartitionName
> with
> > offset (in lba) 0x10 on a block device blk0:\r\n"
> > +" gpt %Hwritefile%N blk0: fs2:file.bin PartitionName 0x10\r\n"
> > +"FAT Format the partition PartitionName on block device blk0:\r\n"
> > +" gpt %Hfatformat%N blk0: PartitionName\r\n"
> > +"FAT Format the whole device blk0:\r\n"
> > +" gpt fatformat blk0:\r\n"
> > +
> > +".SH RETURNVALUES\r\n"
> > +" \r\n"
> > +"RETURN VALUES:\r\n"
> > +" SHELL_SUCCESS The action was completed as requested.\r\n"
> > +" Specific Shell error Error while processing command\r\n"
> > diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec
> > index 39f8012b98c1..5374a2a62d5f 100644
> > --- a/ShellPkg/ShellPkg.dec
> > +++ b/ShellPkg/ShellPkg.dec
> > @@ -56,6 +56,7 @@ [Guids]
> > gShellNetwork2HiiGuid = {0x174b2b5, 0xf505, 0x4b12, {0xaa, 0x60,
> > 0x59, 0xdf, 0xf8, 0xd6, 0xea, 0x37}}
> > gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592, {0x8f, 0xf7, 0xc1,
> > 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}}
> > gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb,
> > 0x12, 0xda, 0xb4, 0xa2, 0xb6}}
> > + gShellGptHiiGuid = {0x5a1ed739, 0x5ef1, 0x429a, {0x8d, 0xf8, 0x28,
> > 0xc9, 0x92, 0x64, 0xd7, 0xf8}}
> >
> > [Protocols]
> > gEfiShellProtocolGuid = {0x6302d008, 0x7f9b, 0x4f30, {0x87, 0xac,
> > 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e}}
> > diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
> > index 809bd4220af2..984c1d0ad48b 100644
> > --- a/ShellPkg/ShellPkg.dsc
> > +++ b/ShellPkg/ShellPkg.dsc
> > @@ -89,6 +89,7 @@ [Components]
> >
> >
> ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib
> > .inf
> >
> >
> ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib
> > .inf
> >
> >
> ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsL
> > ib.inf
> > +
> ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.inf
> >
> >
> ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLi
> > b.inf
> >
> >
> ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1Commands
> > Lib.inf
> >
> >
> ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1Comm
> > andsLib.inf
> > @@ -119,6 +120,9 @@ [Components]
> > !ifdef $(INCLUDE_TFTP_COMMAND)
> >
> >
> NULL|ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib
> > .inf
> > !endif #$(INCLUDE_TFTP_COMMAND)
> > +!ifdef $(INCLUDE_GPT_COMMAND)
> > +
> >
> NULL|ShellPkg/Library/UefiShellGptCommandLib/UefiShellGptCommandLib.
> > inf
> > +!endif #$(INCLUDE_GPT_COMMAND)
> > !endif #$(NO_SHELL_PROFILES)
> > }
> >
> > --
> > 1.9.1
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
next prev parent reply other threads:[~2016-10-18 1:55 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-16 5:23 [PATCH] GPT Shell Application/Library Vladimir Olovyannikov
2016-10-16 20:05 ` Laszlo Ersek
[not found] ` <CACmgjazi_K4Qo5=TeO_tCGK2cB26d0rqOEZh6TthP1UYbo6J6w@mail.gmail.com>
[not found] ` <CACmgjaziUEF2EsSn73HY5JvL2rmRWrXS+rHMtOQ1HaRwPpXS+g@mail.gmail.com>
2016-10-17 6:49 ` Vladimir Olovyannikov
2016-10-17 7:24 ` Michael Zimmermann
2016-10-17 17:52 ` Vladimir Olovyannikov
2016-10-17 17:56 ` Carsey, Jaben
2016-10-18 13:59 ` Shah, Tapan
2016-10-18 16:58 ` Vladimir Olovyannikov
2016-10-18 17:04 ` Carsey, Jaben
2016-10-18 18:03 ` Shah, Tapan
2016-10-18 19:09 ` Vladimir Olovyannikov
2016-10-18 17:23 ` Laszlo Ersek
2016-10-18 18:03 ` Vladimir Olovyannikov
2016-10-18 18:12 ` Laszlo Ersek
2016-10-17 9:43 ` Laszlo Ersek
2016-10-17 16:35 ` Carsey, Jaben
2016-10-18 1:45 ` Ni, Ruiyu
2016-10-18 1:48 ` Tim Lewis
2016-10-18 1:55 ` Ni, Ruiyu [this message]
2016-10-18 2:59 ` Carsey, Jaben
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=734D49CCEBEEF84792F5B80ED585239D58E36F85@SHSMSX104.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