Applications/SpiTool: Add 'sf' command utility

sf command uses MARVELL_SPI_FLASH_PROTOCOL and MARVELL_SPI_MASTER_PROTOCOL.
It allows read/write/erase/update operations on SPI flash.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jan Dabros <jsd@semihalf.com>
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
diff --git a/Applications/SpiTool/SpiFlashCmd.c b/Applications/SpiTool/SpiFlashCmd.c
new file mode 100644
index 0000000..184e3d7
--- /dev/null
+++ b/Applications/SpiTool/SpiFlashCmd.c
@@ -0,0 +1,526 @@
+/*******************************************************************************

+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.

+

+*******************************************************************************/

+#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/UefiBootServicesTableLib.h>

+#include <Library/PrintLib.h>

+#include <Library/ShellCEntryLib.h>

+#include <Library/HiiLib.h>

+#include <Library/FileHandleLib.h>

+

+#include <Protocol/Spi.h>

+#include <Protocol/SpiFlash.h>

+

+MARVELL_SPI_FLASH_PROTOCOL *SpiFlashProtocol;

+MARVELL_SPI_MASTER_PROTOCOL *SpiMasterProtocol;

+

+CONST CHAR16 gShellSpiFlashFileName[] = L"ShellCommand";

+EFI_HANDLE gShellSfHiiHandle = NULL;

+

+BOOLEAN InitFlag = 1;

+

+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {

+  {L"read", TypeFlag},

+  {L"readfile", TypeFlag},

+  {L"write", TypeFlag},

+  {L"writefile", TypeFlag},

+  {L"erase", TypeFlag},

+  {L"update", TypeFlag},

+  {L"updatefile", TypeFlag},

+  {L"probe", TypeFlag},

+  {L"help", TypeFlag},

+  {NULL , TypeMax}

+  };

+

+typedef enum {

+  PROBE       = 1,

+  READ        = 2,

+  READ_FILE   = 4,

+  WRITE       = 8,

+  WRITE_FILE  = 16,

+  ERASE       = 32,

+  UPDATE      = 64,

+  UPDATE_FILE = 128,

+} 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

+ShellCommandGetManFileNameSpiFlash (

+  VOID

+  )

+{

+

+  return gShellSpiFlashFileName;

+}

+

+VOID

+SfUsage (

+  VOID

+  )

+{

+  Print (L"\nBasic SPI command\n"

+         "sf [probe | read | readfile | write | writefile | erase |"

+         "update | updatefile]"

+         "[<Address> | <FilePath>] <Offset> <Length>\n\n"

+         "Length   - Number of bytes to send\n"

+         "Address  - Address in RAM to store/load data\n"

+         "FilePath - Path to file to read/write data from/to\n"

+         "Offset   - Offset from beggining of SPI flash to store/load data\n"

+         "Examples:\n"

+         "Check if there is response from SPI flash\n"

+         "  sf probe\n"

+         "Read 32 bytes from 0xe00000 of SPI flash into RAM at address 0x100000\n"

+         "  sf read 0x100000 0xe00000 32\n"

+         "Read 0x20 bytes from 0x200000 of SPI flash into RAM at address 0x300000\n"

+         "  sf read 0x300000 0x200000 0x20\n"

+         "Erase 0x10000 bytes from offset 0x100000 of SPI flash\n"

+         "  sf erase 0x100000 0x100000\n"

+         "Write 16 bytes from 0x200000 at RAM into SPI flash at address 0x4000000\n"

+         "  sf write 0x200000 0x4000000 16\n"

+         "Update 100 bytes from 0x100000 at RAM in SPI flash at address 0xe00000\n"

+         "  sf update 0x100000 0xe00000 100\n"

+         "Read 0x3000 bytes from 0x0 of SPI flash into file fs2:file.bin\n"

+         "  sf readfile fs2:file.bin 0x0 0x3000 \n"

+         "Update data in SPI flash at 0x3000000 from file Linux.efi\n"

+         "  sf updatefile Linux.efi 0x3000000\n"

+  );

+}

+

+STATIC

+EFI_STATUS

+OpenAndPrepareFile (

+  IN CHAR16 *FilePath,

+  SHELL_FILE_HANDLE *FileHandle

+  )

+{

+  EFI_STATUS Status;

+  UINT64 OpenMode;

+

+  OpenMode = EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE;

+

+  Status = ShellOpenFileByName (FilePath, FileHandle, OpenMode, 0);

+  if (EFI_ERROR (Status)) {

+    Print (L"sf: Cannot open file\n");

+    return Status;

+  }

+

+  Status = FileHandleSetPosition(*FileHandle, 0);

+

+  if (EFI_ERROR(Status)) {

+    Print (L"sf: Cannot set file position to first byte\n");

+    ShellCloseFile (FileHandle);

+    return Status;

+  }

+

+  return EFI_SUCCESS;

+}

+

+STATIC

+EFI_STATUS

+FlashProbe (

+  IN SPI_DEVICE       *Slave

+  )

+{

+  EFI_STATUS Status;

+  UINT8  IdBuffer[4];

+  UINT32 Id, RefId;

+

+  Id = PcdGet32 (PcdSpiFlashId);

+

+  IdBuffer[0] = CMD_READ_ID;

+

+  SpiFlashProtocol->ReadId (

+    Slave,

+    4,

+    IdBuffer

+    );

+

+  RefId = (IdBuffer[0] << 16) + (IdBuffer[1] << 8) + IdBuffer[2];

+

+  if (RefId == Id) {

+    Print (L"sf: Detected supported SPI flash with ID=%3x\n", RefId);

+    Status = SpiFlashProtocol->Init (SpiFlashProtocol, Slave);

+    if (EFI_ERROR(Status)) {

+      Print (L"sf: Cannot initialize flash device\n");

+      return SHELL_ABORTED;

+    }

+    InitFlag = 0;

+    return EFI_SUCCESS;

+  } else if (RefId != 0) {

+    Print (L"sf: Unsupported SPI flash detected with ID=%2x\n", RefId);

+    return SHELL_ABORTED;

+  }

+

+  Print (L"sf: No SPI flash detected");

+  return SHELL_ABORTED;

+}

+

+SHELL_STATUS

+EFIAPI

+ShellCommandRunSpiFlash (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+EFI_STATUS              Status;

+  SPI_DEVICE            *Slave;

+  LIST_ENTRY            *CheckPackage;

+  EFI_PHYSICAL_ADDRESS  Address = 0, Offset = 0;

+  SHELL_FILE_HANDLE     FileHandle = NULL;

+  UINTN                 ByteCount, FileSize, I;

+  UINT8                 *Buffer = NULL, *FileBuffer = NULL;

+  CHAR16                *ProblemParam, *FilePath;

+  CONST CHAR16          *AddressStr = NULL, *OffsetStr = NULL;

+  CONST CHAR16          *LengthStr = NULL, *FileStr = NULL;

+  BOOLEAN               AddrFlag = FALSE, LengthFlag = TRUE, FileFlag = FALSE;

+  UINT8                 Flag = 0, CheckFlag = 0;

+

+  Status = gBS->LocateProtocol (

+    &gMarvellSpiFlashProtocolGuid,

+    NULL,

+    (VOID **)&SpiFlashProtocol

+  );

+  if (EFI_ERROR(Status)) {

+    Print (L"sf: Cannot locate SpiFlash protocol\n");

+    return SHELL_ABORTED;

+  }

+

+  Status = gBS->LocateProtocol (

+    &gMarvellSpiMasterProtocolGuid,

+    NULL,

+    (VOID **)&SpiMasterProtocol

+  );

+  if (EFI_ERROR(Status)) {

+    Print (L"sf: Cannot locate SpiMaster protocol\n");

+    return SHELL_ABORTED;

+  }

+

+  // Parse Shell command line

+  Status = ShellInitialize ();

+  if (EFI_ERROR (Status)) {

+    Print (L"sf: Cannot initialize Shell\n");

+    ASSERT_EFI_ERROR (Status);

+    return SHELL_ABORTED;

+  }

+

+  Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE);

+  if (EFI_ERROR (Status)) {

+    Print (L"sf: Error while parsing command line\n");

+    return SHELL_ABORTED;

+  }

+

+  if (ShellCommandLineGetFlag (CheckPackage, L"help")) {

+    SfUsage();

+    return EFI_SUCCESS;

+  }

+

+  // Check flags provided by user

+  Flag |= (ShellCommandLineGetFlag (CheckPackage, L"probe") << 0);

+  Flag |= (ShellCommandLineGetFlag (CheckPackage, L"read") << 1);

+  Flag |= (ShellCommandLineGetFlag (CheckPackage, L"readfile") << 2);

+  Flag |= (ShellCommandLineGetFlag (CheckPackage, L"write") << 3);

+  Flag |= (ShellCommandLineGetFlag (CheckPackage, L"writefile") << 4);

+  Flag |= (ShellCommandLineGetFlag (CheckPackage, L"erase") << 5);

+  Flag |= (ShellCommandLineGetFlag (CheckPackage, L"update") << 6);

+  Flag |= (ShellCommandLineGetFlag (CheckPackage, L"updatefile") << 7);

+

+  if (InitFlag && !(Flag & PROBE)) {

+    Print (L"Please run sf probe\n");

+    return EFI_SUCCESS;

+  }

+

+  CheckFlag = Flag;

+  for (I = 0; CheckFlag; CheckFlag >>= 1) {

+    I += CheckFlag & 1;

+    if (I > 1) {

+      Print (L"sf: Too many flags\n");

+      SfUsage();

+      return SHELL_ABORTED;

+    }

+  }

+

+  // Setup new spi device

+  Slave = SpiMasterProtocol->SetupDevice (SpiMasterProtocol, 0, 0);

+    if (Slave == NULL) {

+      Print(L"sf: Cannot allocate SPI device!\n");

+      return SHELL_ABORTED;

+    }

+

+  switch (Flag) {

+  case PROBE:

+    // Probe spi bus

+    Status = FlashProbe (Slave);

+    if (EFI_ERROR(Status)) {

+      // No supported spi flash detected

+      return SHELL_ABORTED;

+    } else {

+      return Status;

+    }

+    break;

+  // Fall through

+  case READ:

+  case WRITE:

+  case UPDATE:

+    AddressStr = ShellCommandLineGetRawValue (CheckPackage, 1);

+    OffsetStr = ShellCommandLineGetRawValue (CheckPackage, 2);

+    LengthStr = ShellCommandLineGetRawValue (CheckPackage, 3);

+    AddrFlag = TRUE;

+    break;

+  case ERASE:

+    OffsetStr = ShellCommandLineGetRawValue (CheckPackage, 1);

+    LengthStr = ShellCommandLineGetRawValue (CheckPackage, 2);

+    break;

+  case READ_FILE:

+    FileStr = ShellCommandLineGetRawValue (CheckPackage, 1);

+    OffsetStr = ShellCommandLineGetRawValue (CheckPackage, 2);

+    LengthStr = ShellCommandLineGetRawValue (CheckPackage, 3);

+    FileFlag = TRUE;

+    break;

+  case WRITE_FILE:

+  case UPDATE_FILE:

+    FileStr = ShellCommandLineGetRawValue (CheckPackage, 1);

+    OffsetStr = ShellCommandLineGetRawValue (CheckPackage, 2);

+    LengthFlag = FALSE;

+    FileFlag = TRUE;

+    break;

+  }

+

+  // Read address parameter

+  if ((AddressStr == NULL) & AddrFlag) {

+    Print (L"sf: No address parameter!\n");

+    return SHELL_ABORTED;

+  } else if (AddrFlag) {

+    Address = ShellHexStrToUintn (AddressStr);

+    if (Address == (UINTN)(-1)) {

+      Print (L"sf: Wrong address parameter\n");

+      return SHELL_ABORTED;

+    }

+  }

+

+  // Read offset parameter

+  if (OffsetStr == NULL) {

+    Print (L"sf: No offset Parameter!\n");

+    return SHELL_ABORTED;

+  } else {

+    Offset = ShellHexStrToUintn (OffsetStr);

+    if (Offset < 0) {

+      Print (L"sf: Wrong offset parameter: %s", OffsetStr);

+      return SHELL_ABORTED;

+    }

+  }

+

+  // Read length parameter

+  if ((LengthStr == NULL) & LengthFlag) {

+    Print (L"sf: No lenght parameter!\n");

+    return SHELL_ABORTED;

+  } else if (LengthFlag) {

+    ByteCount = ShellStrToUintn (LengthStr);

+    if (ByteCount < 0) {

+      Print (L"sf: Wrong length parameter %s!\n", LengthStr);

+      return SHELL_ABORTED;

+    }

+  }

+

+  if (FileFlag) {

+    // Read FilePath parameter

+    if (FileStr == NULL) {

+      Print (L"sf: No FilePath parameter!\n");

+      return SHELL_ABORTED;

+    } 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))) {

+        Print (L"sf: Wrong FilePath parameter!\n");

+        return SHELL_ABORTED;

+      }

+    }

+

+    Status = OpenAndPrepareFile (FilePath, &FileHandle);

+    if (EFI_ERROR(Status)) {

+      Print (L"sf: Error while preparing file\n");

+      return SHELL_ABORTED;

+    }

+

+    // Get file size in order to check correctness at the end of transfer

+    if (Flag & (WRITE_FILE | UPDATE_FILE)) {

+      Status = FileHandleGetSize (FileHandle, &FileSize);

+      if (EFI_ERROR (Status)) {

+        Print (L"sf: Cannot get file size\n");

+      }

+      ByteCount = (UINTN) FileSize;

+    }

+

+    FileBuffer = AllocateZeroPool ((UINTN) ByteCount);

+    if (FileBuffer == NULL) {

+      Print (L"sf: Cannot allocate memory\n");

+      goto Error_Close_File;

+    }

+

+    // Read file content and store it in FileBuffer

+    if (Flag & (WRITE_FILE | UPDATE_FILE)) {

+      Status = FileHandleRead (FileHandle, &ByteCount, FileBuffer);

+      if (EFI_ERROR (Status)) {

+        Print (L"sf: Read from file error\n");

+        goto Error_Free_Buffer;

+      } else if (ByteCount != (UINTN) FileSize) {

+        Print (L"sf: Not whole file read. Abort\n");

+        goto Error_Free_Buffer;

+      }

+    }

+  }

+

+  Buffer = (UINT8 *) Address;

+  if (FileFlag) {

+    Buffer = FileBuffer;

+  }

+

+  switch (Flag) {

+  case READ:

+  case READ_FILE:

+    Status = SpiFlashProtocol->Read (Slave, Offset, ByteCount, Buffer);

+    break;

+  case ERASE:

+    Status = SpiFlashProtocol->Erase (Slave, Offset, ByteCount);

+    break;

+  case WRITE:

+  case WRITE_FILE:

+    Status = SpiFlashProtocol->Write (Slave, Offset, ByteCount, Buffer);

+    break;

+  case UPDATE:

+  case UPDATE_FILE:

+    Status = SpiFlashProtocol->Update (Slave, Offset, ByteCount, Buffer);

+    break;

+  }

+

+  SpiMasterProtocol->FreeDevice(Slave);

+

+  if (EFI_ERROR (Status)) {

+    Print (L"sf: Error while performing spi transfer\n");

+    return SHELL_ABORTED;

+  }

+

+  switch (Flag) {

+  case ERASE:

+    Print (L"sf: %d bytes succesfully erased at offset 0x%x\n", ByteCount,

+      Offset);

+    break;

+  case WRITE:

+  case WRITE_FILE:

+    Print (L"sf: Write %d bytes at offset 0x%x\n", ByteCount, Offset);

+    break;

+  case UPDATE:

+  case UPDATE_FILE:

+    Print (L"sf: Update %d bytes at offset 0x%x\n", ByteCount, Offset);

+    break;

+  case READ:

+    Print (L"sf: Read %d bytes from offset 0x%x\n", ByteCount, Offset);

+    break;

+  case READ_FILE:

+    Status = FileHandleWrite (FileHandle, &ByteCount, FileBuffer);

+    if (EFI_ERROR(Status)) {

+      Print (L"sf: Error while writing into file\n");

+      goto Error_Free_Buffer;

+    }

+    break;

+  }

+

+  if (FileFlag) {

+    FreePool (FileBuffer);

+

+    if (FileHandle != NULL) {

+      ShellCloseFile (&FileHandle);

+    }

+  }

+

+  return EFI_SUCCESS;

+

+Error_Free_Buffer:

+  FreePool (FileBuffer);

+Error_Close_File:

+  ShellCloseFile (&FileHandle);

+  return SHELL_ABORTED;

+}

+

+EFI_STATUS

+EFIAPI

+ShellSpiFlashLibConstructor (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+  gShellSfHiiHandle = NULL;

+

+  gShellSfHiiHandle = HiiAddPackages (

+                        &gShellSfHiiGuid, gImageHandle,

+                        UefiShellSpiFlashLibStrings, NULL

+                        );

+  if (gShellSfHiiHandle == NULL) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  ShellCommandRegisterCommandName (

+     L"sf", ShellCommandRunSpiFlash, ShellCommandGetManFileNameSpiFlash, 0,

+     L"sf", TRUE , gShellSfHiiHandle, STRING_TOKEN (STR_GET_HELP_SF)

+     );

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+ShellSpiFlashLibDestructor (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+

+  if (gShellSfHiiHandle != NULL) {

+    HiiRemovePackages (gShellSfHiiHandle);

+  }

+  return EFI_SUCCESS;

+}

diff --git a/Applications/SpiTool/SpiFlashCmd.inf b/Applications/SpiTool/SpiFlashCmd.inf
new file mode 100644
index 0000000..d91fdf3
--- /dev/null
+++ b/Applications/SpiTool/SpiFlashCmd.inf
@@ -0,0 +1,75 @@
+#

+# 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.

+#

+

+[Defines]

+ INF_VERSION = 0x00010006

+ BASE_NAME = UefiShellSpiFlashLib

+ FILE_GUID = 2f2dd8c9-221f-4acf-afe5-5897264c5774

+ MODULE_TYPE = UEFI_APPLICATION

+ VERSION_STRING = 0.1

+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER

+ CONSTRUCTOR = ShellSpiFlashLibConstructor

+ DESTRUCTOR = ShellSpiFlashLibDestructor

+

+[Sources]

+ SpiFlashCmd.c

+ SpiFlashCmd.uni

+

+[Packages]

+ MdePkg/MdePkg.dec

+ ShellPkg/ShellPkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ OpenPlatformPkg/Platforms/Marvell/Marvell.dec

+

+[LibraryClasses]

+ UefiLib

+ UefiBootServicesTableLib

+ MemoryAllocationLib

+ BaseLib

+ BaseMemoryLib

+ DebugLib

+ ShellCommandLib

+ ShellLib

+ UefiLib

+ UefiRuntimeServicesTableLib

+ PcdLib

+ HiiLib

+ FileHandleLib

+

+[Pcd]

+ gMarvellTokenSpaceGuid.PcdSpiFlashId

+

+[Protocols]

+ gMarvellSpiFlashProtocolGuid

+ gMarvellSpiMasterProtocolGuid

+

+[Guids]

+ gShellSfHiiGuid

diff --git a/Applications/SpiTool/SpiFlashCmd.uni b/Applications/SpiTool/SpiFlashCmd.uni
new file mode 100644
index 0000000..3f25663
--- /dev/null
+++ b/Applications/SpiTool/SpiFlashCmd.uni
Binary files differ
diff --git a/Platforms/Marvell/Marvell.dec b/Platforms/Marvell/Marvell.dec
index a2d1956..e63add4 100644
--- a/Platforms/Marvell/Marvell.dec
+++ b/Platforms/Marvell/Marvell.dec
@@ -53,6 +53,7 @@
   gMarvellTokenSpaceGuid = { 0xf995c6c8, 0xbc9b, 0x4e93, { 0xbd, 0xcf, 0x49, 0x90, 0xc6, 0xe7, 0x8c, 0x7f } }

 

   gShellEepromHiiGuid = { 0xb2f4c714, 0x147f, 0x4ff7, { 0x82, 0x1b, 0xce, 0x7b, 0x91, 0x7f, 0x5f, 0x2f } }

+  gShellSfHiiGuid = { 0x03a67756, 0x8cde, 0x4638, { 0x82, 0x34, 0x4a, 0x0f, 0x6d, 0x58, 0x81, 0x39 } }

 

 [PcdsFixedAtBuild.common]

 #MPP