Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf | 13 +- Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c | 542 +++++++++++++++++--- Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni | Bin 5190 -> 6758 bytes 3 files changed, 485 insertions(+), 70 deletions(-)
From: Tomasz Michalec <tm@semihalf.com>
Extend fupdate shell application to be able to flash firmware
on SD/MMC. Device on which firmware will be updated
is selected via third argument of command.
The SPI is still used as default.
Command uses BlockIo protocol to communicate with SD/MMC. It is possible
to list all valid devices and specify selection via handle number or
device path string. Example output (detailed usage can be found in
updated command's 'help'):
Shell> fupdate list
Handle Path
spi spi
8F VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,00006EF00000000000)/SD(0x0)
93 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/eMMC(0x0)/Ctrl(0x0)
94 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/eMMC(0x0)/Ctrl(0x1)
95 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/eMMC(0x0)/Ctrl(0x2)
The code was restructured, to dynamically assign appropriate
firmware update routine, depending on the user choice
(SPI vs BlockDevice).
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf | 13 +-
Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c | 542 +++++++++++++++++---
Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni | Bin 5190 -> 6758 bytes
3 files changed, 485 insertions(+), 70 deletions(-)
diff --git a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf
index 69ee0f8..46847fc 100644
--- a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf
+++ b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf
@@ -55,6 +55,7 @@
BaseMemoryLib
DebugLib
FileHandleLib
+ HandleParsingLib
HiiLib
MemoryAllocationLib
PcdLib
@@ -62,12 +63,18 @@
ShellLib
UefiBootServicesTableLib
UefiLib
- UefiLib
UefiRuntimeServicesTableLib
+[Pcd]
+ gMarvellTokenSpaceGuid.PcdSpiFlashCs
+ gMarvellTokenSpaceGuid.PcdSpiFlashMode
+
[Protocols]
- gMarvellSpiFlashProtocolGuid
- gMarvellSpiMasterProtocolGuid
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathFromTextProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gMarvellSpiFlashProtocolGuid
+ gMarvellSpiMasterProtocolGuid
[Guids]
gShellFUpdateHiiGuid
diff --git a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c
index 22a9b8f..3a496f0 100644
--- a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c
+++ b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c
@@ -36,7 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
#include <Library/FileHandleLib.h>
+#include <Library/HandleParsingLib.h>
#include <Library/HiiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PrintLib.h>
@@ -46,22 +48,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/DevicePathFromText.h>
#include <Protocol/Spi.h>
#include <Protocol/SpiFlash.h>
#define CMD_NAME_STRING L"fupdate"
+#define SHELL_USE_DEVICE_PATH_PARAM L"-p"
+#define SHELL_DEVICE_NAME_PARAM L"DeviceName"
+#define SHELL_FILE_NAME_PARAM L"LocalFileName"
+#define SHELL_HELP_PARAM L"help"
+#define SHELL_LIST_PARAM L"list"
+
#define MAIN_HDR_MAGIC 0xB105B002
-STATIC MARVELL_SPI_FLASH_PROTOCOL *SpiFlashProtocol;
-STATIC MARVELL_SPI_MASTER_PROTOCOL *SpiMasterProtocol;
+STATIC EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
+STATIC MARVELL_SPI_MASTER_PROTOCOL *SpiMasterProtocol;
+STATIC MARVELL_SPI_FLASH_PROTOCOL *SpiFlashProtocol;
+STATIC EFI_BLOCK_IO_PROTOCOL *BlkIo;
STATIC CONST CHAR16 gShellFUpdateFileName[] = L"ShellCommands";
STATIC EFI_HANDLE gShellFUpdateHiiHandle = NULL;
STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
- {L"help", TypeFlag},
- {NULL , TypeMax}
+ {SHELL_HELP_PARAM, TypeFlag},
+ {SHELL_LIST_PARAM, TypeFlag},
+ {SHELL_USE_DEVICE_PATH_PARAM, TypeFlag},
+ {SHELL_FILE_NAME_PARAM, TypePosition},
+ {SHELL_DEVICE_NAME_PARAM, TypePosition},
+ {NULL , TypeMax}
};
typedef struct { // Bytes
@@ -86,6 +103,14 @@ typedef struct { // Bytes
UINT32 Reserved3; // 60-63
} MV_FIRMWARE_IMAGE_HEADER;
+typedef
+EFI_STATUS
+(EFIAPI *FLASH_COMMAND) (
+ UINT64 FileSize,
+ UINTN *FileBuffer,
+ EFI_LBA Offset
+);
+
STATIC
EFI_STATUS
SpiFlashProbe (
@@ -109,6 +134,156 @@ SpiFlashProbe (
return EFI_SUCCESS;
}
+/**
+ Verify if selected device is valid for the firmware update.
+
+ @param[in] Handle Handle of verified device
+ @param[in] Offset [OPTIONAL] Additional parameter
+ required for BlkIo->WriteBlocks,
+ filled depending on detected device
+ type.
+
+**/
+STATIC
+EFI_STATUS
+IsDeviceSupported (
+ IN EFI_HANDLE Handle,
+ OUT EFI_LBA *Offset OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ //
+ // Skip handles that do not have device path protocol
+ //
+ Status = gBS->OpenProtocol (Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&DevicePath,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Skip handles that are not block devices
+ //
+ Status = gBS->OpenProtocol (Handle,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ while (!IsDevicePathEnd (DevicePath)) {
+ if (DevicePath->Type == MESSAGING_DEVICE_PATH) {
+ //
+ // Search for SD/MMC devices.
+ //
+ if (DevicePath->SubType == MSG_SD_DP) {
+ //
+ // Only flashing in the beginning of SD card makes sense.
+ //
+ DevicePath = NextDevicePathNode (DevicePath);
+ if (!IsDevicePathEnd (DevicePath)) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Offset != NULL) {
+ *Offset = 1;
+ }
+ return EFI_SUCCESS;
+ }
+ if (DevicePath->SubType == MSG_EMMC_DP) {
+ //
+ // Filter out entire MMC device (ctrl(0x0))
+ // and boot partitions (ctrl(0x1)/ctrl(0x2)) as valid for
+ // the firmware update.
+ //
+ DevicePath = NextDevicePathNode (DevicePath);
+ if (IsDevicePathEnd (DevicePath)) {
+ return EFI_UNSUPPORTED;
+ }
+ DevicePath = NextDevicePathNode (DevicePath);
+ if (!IsDevicePathEnd (DevicePath)) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Offset != NULL) {
+ *Offset = 0;
+ }
+ return EFI_SUCCESS;
+ }
+ }
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Print information about single device supporting the firmware update.
+
+ @param[in] Handle Handle of verified device
+
+**/
+STATIC
+EFI_STATUS
+PrintSupportedDevice (
+ IN EFI_HANDLE Handle
+ )
+{
+ CHAR16 *Name;
+
+ gEfiShellProtocol->GetDeviceName (Handle,
+ EFI_DEVICE_NAME_USE_DEVICE_PATH,
+ NULL,
+ &Name);
+ if (Name != NULL) {
+ ShellPrintEx (-1,
+ -1,
+ L"%H%02x%N %s\n",
+ ConvertHandleToHandleIndex (Handle),
+ Name);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Print information about all devices supporting the firmware update.
+
+**/
+STATIC
+EFI_STATUS
+ListSupportedDevices (
+ )
+{
+ UINTN LoopVar;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ ShellPrintEx (-1, -1, L"%BHandle Path%N\n");
+ ShellPrintEx (-1, -1, L"%Hspi%N spi\n");
+
+ for (LoopVar = 1; ; LoopVar++) {
+ Handle = ConvertHandleIndexToHandle (LoopVar);
+ if (Handle == NULL) {
+ break;
+ }
+
+ Status = IsDeviceSupported (Handle, NULL);
+ if (!EFI_ERROR (Status)) {
+ PrintSupportedDevice (Handle);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
STATIC
EFI_STATUS
CheckImageHeader (
@@ -149,13 +324,15 @@ PrepareFirmwareImage (
IN LIST_ENTRY *CheckPackage,
IN OUT SHELL_FILE_HANDLE *FileHandle,
IN OUT UINTN **FileBuffer,
- IN OUT UINT64 *FileSize
+ IN OUT UINT64 *FileSize,
+ IN UINT64 Alignment
)
{
CONST CHAR16 *FileStr;
EFI_STATUS Status;
UINT64 OpenMode;
UINTN *Buffer;
+ UINTN AlignedFileSize;
// Parse string from commandline
FileStr = ShellCommandLineGetRawValue (CheckPackage, 1);
@@ -184,8 +361,20 @@ PrepareFirmwareImage (
Print (L"%s: Cannot get Image file size\n", CMD_NAME_STRING);
}
+ // Allocate aligned buffer in case of updating firmware in a BlockDevice
+ if (Alignment > 0) {
+ AlignedFileSize = *FileSize + (Alignment - (*FileSize % Alignment));
+ } else {
+ AlignedFileSize = *FileSize;
+ }
+
// Read Image header into buffer
- Buffer = AllocateZeroPool (*FileSize);
+ Buffer = AllocateZeroPool (AlignedFileSize);
+ if (Buffer == NULL) {
+ Print (L"%s: Fail to allocate buffer\n", CMD_NAME_STRING);
+ ShellCloseFile (FileHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
Status = FileHandleRead (*FileHandle, (UINTN *)FileSize, Buffer);
if (EFI_ERROR (Status)) {
@@ -196,6 +385,233 @@ PrepareFirmwareImage (
}
*FileBuffer = Buffer;
+ *FileSize = AlignedFileSize;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update firmware image in the block device.
+
+ @param[in] FileSize Size of the file to be flashed
+ @param[in] *FileBuffer Pointer to the file in memory
+ @param[in] Offset First logical block to be updated.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProgramBlockDevice (
+ IN UINT64 FileSize,
+ IN UINTN *FileBuffer,
+ IN EFI_LBA Offset
+ )
+{
+ EFI_STATUS Status;
+
+ Print (L"Updating image in BlockDevice\n");
+
+ Status = BlkIo->WriteBlocks (BlkIo,
+ BlkIo->Media->MediaId,
+ Offset,
+ FileSize,
+ FileBuffer);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: Cannot write to device (Status: %r)\n",
+ CMD_NAME_STRING,
+ Status);
+ return Status;
+ }
+
+ Status = BlkIo->FlushBlocks (BlkIo);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: Cannot flush to device (Status: %r)\n",
+ CMD_NAME_STRING,
+ Status);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Update firmware image in the SPI flash.
+
+ @param[in] FileSize Size of the file to be flashed
+ @param[in] *FileBuffer Pointer to the file in memory
+ @param[in] Offset First logical block to be updated.
+ Irrelevant for SPI.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProgramSpiFlash (
+ IN UINT64 FileSize,
+ IN UINTN *FileBuffer,
+ IN EFI_LBA Offset
+ )
+{
+ SPI_DEVICE *SpiFlash;
+ EFI_STATUS Status;
+
+ // Locate SPI protocols
+ Status = gBS->LocateProtocol (&gMarvellSpiFlashProtocolGuid,
+ NULL,
+ (VOID **)&SpiFlashProtocol);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: Cannot locate SpiFlash protocol\n", CMD_NAME_STRING);
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (&gMarvellSpiMasterProtocolGuid,
+ NULL,
+ (VOID **)&SpiMasterProtocol);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: Cannot locate SpiMaster protocol\n", CMD_NAME_STRING);
+ return Status;
+ }
+
+ // Setup and probe SPI flash
+ SpiFlash = NULL;
+ SpiFlash = SpiMasterProtocol->SetupDevice (SpiMasterProtocol,
+ SpiFlash,
+ PcdGet32 (PcdSpiFlashCs),
+ PcdGet32 (PcdSpiFlashMode));
+ if (SpiFlash == NULL) {
+ Print(L"%s: Cannot allocate SPI device!\n", CMD_NAME_STRING);
+ return EFI_ABORTED;
+ }
+
+ Status = SpiFlashProbe (SpiFlash);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: Error while performing SPI flash probe\n", CMD_NAME_STRING);
+ goto FlashProbeError;
+ }
+
+ // Update firmware image in flash at offset 0x0
+ Status = SpiFlashProtocol->Update (SpiFlash,
+ 0x0,
+ FileSize,
+ (UINT8 *)FileBuffer);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: Error while performing flash update\n", CMD_NAME_STRING);
+ goto FlashProbeError;
+ }
+
+ // Release resources
+ SpiMasterProtocol->FreeDevice (SpiFlash);
+
+ return EFI_SUCCESS;
+
+FlashProbeError:
+ SpiMasterProtocol->FreeDevice (SpiFlash);
+
+ return Status;
+}
+
+/**
+ Parse commandline parameters and pick device for the firmware update.
+
+ @param[in] *CheckPackage Shell command argument list.
+ @param[in/out] *FlashCommand Pointer to firmware update command.
+ Picked, depending on the device type.
+ @param[in/out] *Alignment File buffer alignment value.
+ @param[in/out] *Offset First logical block to be updated.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SelectDevice (
+ IN LIST_ENTRY *CheckPackage,
+ IN OUT FLASH_COMMAND *FlashCommand,
+ IN OUT UINT64 *Alignment,
+ IN OUT EFI_LBA *Offset
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ CONST CHAR16 *DeviceName;
+ EFI_HANDLE Handle;
+ UINTN HandleIndex;
+ EFI_STATUS Status;
+
+ //
+ // SPI flash
+ //
+ DeviceName = ShellCommandLineGetRawValue (CheckPackage, 2);
+ if (DeviceName == NULL || StrnCmp(DeviceName, L"spi", 4) == 0) {
+ *FlashCommand = ProgramSpiFlash;
+ *Alignment = 0;
+ *Offset = 0;
+ return EFI_SUCCESS;
+ }
+
+ if (ShellCommandLineGetFlag (CheckPackage, SHELL_USE_DEVICE_PATH_PARAM)) {
+ //
+ // SD/MMC is selected using device path string.
+ //
+ Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid,
+ NULL,
+ (VOID **)&EfiDevicePathFromTextProtocol);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: cannot locate EfiDevicePathFromText protocol\n",
+ CMD_NAME_STRING);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DeviceName);
+ if (DevicePath == NULL) {
+ Print (L"%s: cannot locate EfiDevicePathFromText protocol\n",
+ CMD_NAME_STRING);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid,
+ &DevicePath,
+ &Handle);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: cannot locate selected block device\n", CMD_NAME_STRING);
+ return Status;
+ }
+ } else {
+ //
+ // SD/MMC device is selected using handle number.
+ //
+ HandleIndex = ShellHexStrToUintn (DeviceName);
+ if (HandleIndex == (UINTN)(-1)) {
+ Print (L"%s: handle to device have to be hex number\n", CMD_NAME_STRING);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Handle = ConvertHandleIndexToHandle (HandleIndex);
+ if (Handle == NULL) {
+ Print (L"%s: %x is not correct device handle\n",
+ CMD_NAME_STRING,
+ HandleIndex);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ Status = IsDeviceSupported (Handle, Offset);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: device not supported\n", CMD_NAME_STRING);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->OpenProtocol (Handle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID**)&BlkIo,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ Print (L"%s: Cannot open device BlokIo protocol\n", CMD_NAME_STRING);
+ return Status;
+ }
+ *FlashCommand = ProgramBlockDevice;
+ *Alignment = BlkIo->Media->BlockSize;
return EFI_SUCCESS;
}
@@ -222,11 +638,23 @@ FUpdateUsage (
)
{
Print (L"\nFirmware update command\n"
- "fupdate <LocalFilePath>\n\n"
+ "fupdate <LocalFilePath> [-p] [Device]\n\n"
"LocalFilePath - path to local firmware image file\n"
- "Example:\n"
- "Update firmware from file fs2:flash-image.bin\n"
- " fupdate fs2:flash-image.bin\n"
+ "-p - When flag is selected Device is interpreted\n"
+ " as device path, not device handle.\n"
+ "Device - Select device which will be flashed.\n"
+ " Supported devices can be listed using \"fupdate list\"\n"
+ " command. Device is represented by its handle.\n"
+ " The default value is spi.\n"
+ "EXAMPLES:\n"
+ " * Update firmware in SPI flash from file fs2:flash-image.bin\n"
+ " fupdate fs2:flash-image.bin\n"
+ " * Update firmware in device with handle 5F from file flash-image.bin\n"
+ " fupdate flash-image.bin 5F\n"
+ " * Update firmware in device with selected path from file flash.bin\n"
+ " fupdate flash.bin -p VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/SD(0x0)\n"
+ " * List supported devices\n"
+ " fupdate list\n"
);
}
@@ -238,36 +666,17 @@ ShellCommandRunFUpdate (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- IN SHELL_FILE_HANDLE FileHandle;
- SPI_DEVICE *Slave = NULL;
- UINT64 FileSize;
- UINTN *FileBuffer = NULL;
- CHAR16 *ProblemParam;
- LIST_ENTRY *CheckPackage;
- EFI_STATUS Status;
-
- // Locate SPI protocols
- Status = gBS->LocateProtocol (
- &gMarvellSpiFlashProtocolGuid,
- NULL,
- (VOID **)&SpiFlashProtocol
- );
-
- if (EFI_ERROR(Status)) {
- Print (L"%s: Cannot locate SpiFlash protocol\n", CMD_NAME_STRING);
- return SHELL_ABORTED;
- }
-
- Status = gBS->LocateProtocol (
- &gMarvellSpiMasterProtocolGuid,
- NULL,
- (VOID **)&SpiMasterProtocol
- );
-
- if (EFI_ERROR(Status)) {
- Print (L"%s: Cannot locate SpiMaster protocol\n", CMD_NAME_STRING);
- return SHELL_ABORTED;
- }
+ SHELL_FILE_HANDLE FileHandle;
+ FLASH_COMMAND FlashCommand;
+ LIST_ENTRY *CheckPackage;
+ EFI_LBA Offset;
+ UINT64 Alignment;
+ UINT64 FileSize;
+ UINTN *FileBuffer;
+ CHAR16 *ProblemParam;
+ EFI_STATUS Status;
+
+ FileBuffer = NULL;
// Parse command line
Status = ShellInitialize ();
@@ -283,14 +692,29 @@ ShellCommandRunFUpdate (
return SHELL_ABORTED;
}
- if (ShellCommandLineGetFlag (CheckPackage, L"help")) {
- FUpdateUsage();
+ if (ShellCommandLineGetFlag (CheckPackage, SHELL_HELP_PARAM)) {
+ FUpdateUsage ();
return EFI_SUCCESS;
}
+ if (ShellCommandLineGetFlag (CheckPackage, SHELL_LIST_PARAM)) {
+ ListSupportedDevices ();
+ return EFI_SUCCESS;
+ }
+
+ // Select device to flash
+ Status = SelectDevice (CheckPackage, &FlashCommand, &Alignment, &Offset);
+ if (EFI_ERROR (Status)) {
+ return SHELL_ABORTED;
+ }
+
// Prepare local file to be burned into flash
- Status = PrepareFirmwareImage (CheckPackage, &FileHandle, &FileBuffer, &FileSize);
- if (EFI_ERROR(Status)) {
+ Status = PrepareFirmwareImage (CheckPackage,
+ &FileHandle,
+ &FileBuffer,
+ &FileSize,
+ Alignment);
+ if (EFI_ERROR (Status)) {
return SHELL_ABORTED;
}
@@ -300,38 +724,22 @@ ShellCommandRunFUpdate (
goto HeaderError;
}
- // Setup and probe SPI flash
- Slave = SpiMasterProtocol->SetupDevice (SpiMasterProtocol, Slave, 0, 0);
- if (Slave == NULL) {
- Print(L"%s: Cannot allocate SPI device!\n", CMD_NAME_STRING);
+ // Update firmware image
+ Status = FlashCommand (FileSize, FileBuffer, Offset);
+ if (EFI_ERROR (Status)) {
goto HeaderError;
}
- Status = SpiFlashProbe (Slave);
- if (EFI_ERROR(Status)) {
- Print (L"%s: Error while performing SPI flash probe\n", CMD_NAME_STRING);
- goto FlashProbeError;
- }
-
- // Update firmware image in flash at offset 0x0
- Status = SpiFlashProtocol->Update (Slave, 0, FileSize, (UINT8 *)FileBuffer);
-
- // Release resources
- SpiMasterProtocol->FreeDevice(Slave);
FreePool (FileBuffer);
ShellCloseFile (&FileHandle);
- if (EFI_ERROR(Status)) {
- Print (L"%s: Error while performing flash update\n", CMD_NAME_STRING);
- return SHELL_ABORTED;
- }
-
- Print (L"%s: Update %d bytes at offset 0x0 succeeded!\n", CMD_NAME_STRING, FileSize);
+ Print (L"%s: Update %d bytes at offset 0x%x succeeded!\n",
+ CMD_NAME_STRING,
+ FileSize,
+ Offset * Alignment);
return EFI_SUCCESS;
-FlashProbeError:
- SpiMasterProtocol->FreeDevice(Slave);
HeaderError:
FreePool (FileBuffer);
ShellCloseFile (&FileHandle);
diff --git a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni
index 146f624737d96e2cd354857dbb63390ebe2f347e..3ea892aa2a982827ad235c505270acbca21ea27b 100644
GIT binary patch
delta 1093
zcmah|(P|Sx6g@$uNPXDuTB`)<=u@MnS*4*0zNBf3VttT^MNE-2v2I|EF`G2{<TuDg
z@FxU|U!V{Ehai3S*(cAP$>^GjGVIKqnRDmfd(Pc2ONT2TJ_kjEM<}C@9jLXAC)h_9
zZLT}=DaZ<asm?V{7{$ofs3`Hw@rPw%w~-LjqqT<=Ej*>wMaDVfdCISiA?FTH@~?VS
zm%e&GVC(@`i<K8aB;TU5@;y4Gk!mgbVu$xWD?@yX=mb~zau3gG8%D_^5+Zs$V-|7{
zEzIWP%e`n}L-TLY!)H0|Kj!PoK|<V^R?1<pOAlXdhD6?zjl<}S&-HEtBj(m;Mgvz3
z(fPcTo3_o&zm;0XJWC_is;nrJO?eYUv;Mw`i_^?(w;AUdhpTj%KDjEnb6O~~j$c*9
zF|La2;+4e=Ex%KI<*TaPw>rB@_84tME|l?o+9`L+iPyc4F8Q99A3-4R=9=u9OE7XW
zxFDy)q+nzm-uZo2(OUmx$g!>38h*bt<gSWMxg4I8tuUT9+^Y`Cc84hC&&cg?k#8%G
zJ#=gmxBBlGM?2N_mXyNcjP|su{5U-S`mYfueNPOQ$)}5?f0Dri%k?ex&JtqkQpHu=
zpjE{h|D!dma%|9A;mI}BXw|sZi74~D&Rxv8j_c0%CV@4!dpsGdyx63J-{;p7Ds1g_
m8~7y=C8eW6I<RGBQt7h)HLCh7x}uK|P0>~E;m3pUZQ&;(bkkG-
delta 54
zcmV-60LlO6G{z{f!Vr_v7#NfG5Ly9HlTi^<liCz)lL`<ZlP(tqlX4Yelf)Jhlk62V
MlkN}*v+5Xp0aXzc(f|Me
--
2.7.4
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#39915): https://edk2.groups.io/g/devel/message/39915
Mute This Topic: https://groups.io/mt/31453651/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
On Thu, 2 May 2019 at 13:31, Marcin Wojtas <mw@semihalf.com> wrote: > > From: Tomasz Michalec <tm@semihalf.com> > > Extend fupdate shell application to be able to flash firmware > on SD/MMC. Device on which firmware will be updated > is selected via third argument of command. > The SPI is still used as default. > > Command uses BlockIo protocol to communicate with SD/MMC. It is possible > to list all valid devices and specify selection via handle number or > device path string. Example output (detailed usage can be found in > updated command's 'help'): > > Shell> fupdate list > Handle Path > spi spi > 8F VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,00006EF00000000000)/SD(0x0) > 93 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/eMMC(0x0)/Ctrl(0x0) > 94 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/eMMC(0x0)/Ctrl(0x1) > 95 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/eMMC(0x0)/Ctrl(0x2) > > The code was restructured, to dynamically assign appropriate > firmware update routine, depending on the user choice > (SPI vs BlockDevice). > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Marcin Wojtas <mw@semihalf.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Pushed as cee103d37d6b..4795747fe477 > --- > Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf | 13 +- > Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c | 542 +++++++++++++++++--- > Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni | Bin 5190 -> 6758 bytes > 3 files changed, 485 insertions(+), 70 deletions(-) > > diff --git a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf > index 69ee0f8..46847fc 100644 > --- a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf > +++ b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf > @@ -55,6 +55,7 @@ > BaseMemoryLib > DebugLib > FileHandleLib > + HandleParsingLib > HiiLib > MemoryAllocationLib > PcdLib > @@ -62,12 +63,18 @@ > ShellLib > UefiBootServicesTableLib > UefiLib > - UefiLib > UefiRuntimeServicesTableLib > > +[Pcd] > + gMarvellTokenSpaceGuid.PcdSpiFlashCs > + gMarvellTokenSpaceGuid.PcdSpiFlashMode > + > [Protocols] > - gMarvellSpiFlashProtocolGuid > - gMarvellSpiMasterProtocolGuid > + gEfiBlockIoProtocolGuid > + gEfiDevicePathFromTextProtocolGuid > + gEfiDevicePathProtocolGuid > + gMarvellSpiFlashProtocolGuid > + gMarvellSpiMasterProtocolGuid > > [Guids] > gShellFUpdateHiiGuid > diff --git a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c > index 22a9b8f..3a496f0 100644 > --- a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c > +++ b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c > @@ -36,7 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > #include <Library/BaseLib.h> > #include <Library/BaseMemoryLib.h> > #include <Library/DebugLib.h> > +#include <Library/DevicePathLib.h> > #include <Library/FileHandleLib.h> > +#include <Library/HandleParsingLib.h> > #include <Library/HiiLib.h> > #include <Library/MemoryAllocationLib.h> > #include <Library/PrintLib.h> > @@ -46,22 +48,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > #include <Library/UefiBootServicesTableLib.h> > #include <Library/UefiLib.h> > > +#include <Protocol/BlockIo.h> > +#include <Protocol/DevicePath.h> > +#include <Protocol/DevicePathFromText.h> > #include <Protocol/Spi.h> > #include <Protocol/SpiFlash.h> > > #define CMD_NAME_STRING L"fupdate" > > +#define SHELL_USE_DEVICE_PATH_PARAM L"-p" > +#define SHELL_DEVICE_NAME_PARAM L"DeviceName" > +#define SHELL_FILE_NAME_PARAM L"LocalFileName" > +#define SHELL_HELP_PARAM L"help" > +#define SHELL_LIST_PARAM L"list" > + > #define MAIN_HDR_MAGIC 0xB105B002 > > -STATIC MARVELL_SPI_FLASH_PROTOCOL *SpiFlashProtocol; > -STATIC MARVELL_SPI_MASTER_PROTOCOL *SpiMasterProtocol; > +STATIC EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; > +STATIC MARVELL_SPI_MASTER_PROTOCOL *SpiMasterProtocol; > +STATIC MARVELL_SPI_FLASH_PROTOCOL *SpiFlashProtocol; > +STATIC EFI_BLOCK_IO_PROTOCOL *BlkIo; > > STATIC CONST CHAR16 gShellFUpdateFileName[] = L"ShellCommands"; > STATIC EFI_HANDLE gShellFUpdateHiiHandle = NULL; > > STATIC CONST SHELL_PARAM_ITEM ParamList[] = { > - {L"help", TypeFlag}, > - {NULL , TypeMax} > + {SHELL_HELP_PARAM, TypeFlag}, > + {SHELL_LIST_PARAM, TypeFlag}, > + {SHELL_USE_DEVICE_PATH_PARAM, TypeFlag}, > + {SHELL_FILE_NAME_PARAM, TypePosition}, > + {SHELL_DEVICE_NAME_PARAM, TypePosition}, > + {NULL , TypeMax} > }; > > typedef struct { // Bytes > @@ -86,6 +103,14 @@ typedef struct { // Bytes > UINT32 Reserved3; // 60-63 > } MV_FIRMWARE_IMAGE_HEADER; > > +typedef > +EFI_STATUS > +(EFIAPI *FLASH_COMMAND) ( > + UINT64 FileSize, > + UINTN *FileBuffer, > + EFI_LBA Offset > +); > + > STATIC > EFI_STATUS > SpiFlashProbe ( > @@ -109,6 +134,156 @@ SpiFlashProbe ( > return EFI_SUCCESS; > } > > +/** > + Verify if selected device is valid for the firmware update. > + > + @param[in] Handle Handle of verified device > + @param[in] Offset [OPTIONAL] Additional parameter > + required for BlkIo->WriteBlocks, > + filled depending on detected device > + type. > + > +**/ > +STATIC > +EFI_STATUS > +IsDeviceSupported ( > + IN EFI_HANDLE Handle, > + OUT EFI_LBA *Offset OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > + > + // > + // Skip handles that do not have device path protocol > + // > + Status = gBS->OpenProtocol (Handle, > + &gEfiDevicePathProtocolGuid, > + (VOID**)&DevicePath, > + gImageHandle, > + NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Skip handles that are not block devices > + // > + Status = gBS->OpenProtocol (Handle, > + &gEfiBlockIoProtocolGuid, > + NULL, > + NULL, > + NULL, > + EFI_OPEN_PROTOCOL_TEST_PROTOCOL); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + while (!IsDevicePathEnd (DevicePath)) { > + if (DevicePath->Type == MESSAGING_DEVICE_PATH) { > + // > + // Search for SD/MMC devices. > + // > + if (DevicePath->SubType == MSG_SD_DP) { > + // > + // Only flashing in the beginning of SD card makes sense. > + // > + DevicePath = NextDevicePathNode (DevicePath); > + if (!IsDevicePathEnd (DevicePath)) { > + return EFI_UNSUPPORTED; > + } > + if (Offset != NULL) { > + *Offset = 1; > + } > + return EFI_SUCCESS; > + } > + if (DevicePath->SubType == MSG_EMMC_DP) { > + // > + // Filter out entire MMC device (ctrl(0x0)) > + // and boot partitions (ctrl(0x1)/ctrl(0x2)) as valid for > + // the firmware update. > + // > + DevicePath = NextDevicePathNode (DevicePath); > + if (IsDevicePathEnd (DevicePath)) { > + return EFI_UNSUPPORTED; > + } > + DevicePath = NextDevicePathNode (DevicePath); > + if (!IsDevicePathEnd (DevicePath)) { > + return EFI_UNSUPPORTED; > + } > + if (Offset != NULL) { > + *Offset = 0; > + } > + return EFI_SUCCESS; > + } > + } > + DevicePath = NextDevicePathNode (DevicePath); > + } > + > + return EFI_UNSUPPORTED; > +} > + > +/** > + Print information about single device supporting the firmware update. > + > + @param[in] Handle Handle of verified device > + > +**/ > +STATIC > +EFI_STATUS > +PrintSupportedDevice ( > + IN EFI_HANDLE Handle > + ) > +{ > + CHAR16 *Name; > + > + gEfiShellProtocol->GetDeviceName (Handle, > + EFI_DEVICE_NAME_USE_DEVICE_PATH, > + NULL, > + &Name); > + if (Name != NULL) { > + ShellPrintEx (-1, > + -1, > + L"%H%02x%N %s\n", > + ConvertHandleToHandleIndex (Handle), > + Name); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Print information about all devices supporting the firmware update. > + > +**/ > +STATIC > +EFI_STATUS > +ListSupportedDevices ( > + ) > +{ > + UINTN LoopVar; > + EFI_HANDLE Handle; > + EFI_STATUS Status; > + > + ShellPrintEx (-1, -1, L"%BHandle Path%N\n"); > + ShellPrintEx (-1, -1, L"%Hspi%N spi\n"); > + > + for (LoopVar = 1; ; LoopVar++) { > + Handle = ConvertHandleIndexToHandle (LoopVar); > + if (Handle == NULL) { > + break; > + } > + > + Status = IsDeviceSupported (Handle, NULL); > + if (!EFI_ERROR (Status)) { > + PrintSupportedDevice (Handle); > + } > + } > + > + return EFI_SUCCESS; > +} > + > STATIC > EFI_STATUS > CheckImageHeader ( > @@ -149,13 +324,15 @@ PrepareFirmwareImage ( > IN LIST_ENTRY *CheckPackage, > IN OUT SHELL_FILE_HANDLE *FileHandle, > IN OUT UINTN **FileBuffer, > - IN OUT UINT64 *FileSize > + IN OUT UINT64 *FileSize, > + IN UINT64 Alignment > ) > { > CONST CHAR16 *FileStr; > EFI_STATUS Status; > UINT64 OpenMode; > UINTN *Buffer; > + UINTN AlignedFileSize; > > // Parse string from commandline > FileStr = ShellCommandLineGetRawValue (CheckPackage, 1); > @@ -184,8 +361,20 @@ PrepareFirmwareImage ( > Print (L"%s: Cannot get Image file size\n", CMD_NAME_STRING); > } > > + // Allocate aligned buffer in case of updating firmware in a BlockDevice > + if (Alignment > 0) { > + AlignedFileSize = *FileSize + (Alignment - (*FileSize % Alignment)); > + } else { > + AlignedFileSize = *FileSize; > + } > + > // Read Image header into buffer > - Buffer = AllocateZeroPool (*FileSize); > + Buffer = AllocateZeroPool (AlignedFileSize); > + if (Buffer == NULL) { > + Print (L"%s: Fail to allocate buffer\n", CMD_NAME_STRING); > + ShellCloseFile (FileHandle); > + return EFI_OUT_OF_RESOURCES; > + } > > Status = FileHandleRead (*FileHandle, (UINTN *)FileSize, Buffer); > if (EFI_ERROR (Status)) { > @@ -196,6 +385,233 @@ PrepareFirmwareImage ( > } > > *FileBuffer = Buffer; > + *FileSize = AlignedFileSize; > + > + return EFI_SUCCESS; > +} > + > +/** > + Update firmware image in the block device. > + > + @param[in] FileSize Size of the file to be flashed > + @param[in] *FileBuffer Pointer to the file in memory > + @param[in] Offset First logical block to be updated. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +ProgramBlockDevice ( > + IN UINT64 FileSize, > + IN UINTN *FileBuffer, > + IN EFI_LBA Offset > + ) > +{ > + EFI_STATUS Status; > + > + Print (L"Updating image in BlockDevice\n"); > + > + Status = BlkIo->WriteBlocks (BlkIo, > + BlkIo->Media->MediaId, > + Offset, > + FileSize, > + FileBuffer); > + if (EFI_ERROR (Status)) { > + Print (L"%s: Cannot write to device (Status: %r)\n", > + CMD_NAME_STRING, > + Status); > + return Status; > + } > + > + Status = BlkIo->FlushBlocks (BlkIo); > + if (EFI_ERROR (Status)) { > + Print (L"%s: Cannot flush to device (Status: %r)\n", > + CMD_NAME_STRING, > + Status); > + return Status; > + } > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Update firmware image in the SPI flash. > + > + @param[in] FileSize Size of the file to be flashed > + @param[in] *FileBuffer Pointer to the file in memory > + @param[in] Offset First logical block to be updated. > + Irrelevant for SPI. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +ProgramSpiFlash ( > + IN UINT64 FileSize, > + IN UINTN *FileBuffer, > + IN EFI_LBA Offset > + ) > +{ > + SPI_DEVICE *SpiFlash; > + EFI_STATUS Status; > + > + // Locate SPI protocols > + Status = gBS->LocateProtocol (&gMarvellSpiFlashProtocolGuid, > + NULL, > + (VOID **)&SpiFlashProtocol); > + if (EFI_ERROR (Status)) { > + Print (L"%s: Cannot locate SpiFlash protocol\n", CMD_NAME_STRING); > + return Status; > + } > + > + Status = gBS->LocateProtocol (&gMarvellSpiMasterProtocolGuid, > + NULL, > + (VOID **)&SpiMasterProtocol); > + if (EFI_ERROR (Status)) { > + Print (L"%s: Cannot locate SpiMaster protocol\n", CMD_NAME_STRING); > + return Status; > + } > + > + // Setup and probe SPI flash > + SpiFlash = NULL; > + SpiFlash = SpiMasterProtocol->SetupDevice (SpiMasterProtocol, > + SpiFlash, > + PcdGet32 (PcdSpiFlashCs), > + PcdGet32 (PcdSpiFlashMode)); > + if (SpiFlash == NULL) { > + Print(L"%s: Cannot allocate SPI device!\n", CMD_NAME_STRING); > + return EFI_ABORTED; > + } > + > + Status = SpiFlashProbe (SpiFlash); > + if (EFI_ERROR (Status)) { > + Print (L"%s: Error while performing SPI flash probe\n", CMD_NAME_STRING); > + goto FlashProbeError; > + } > + > + // Update firmware image in flash at offset 0x0 > + Status = SpiFlashProtocol->Update (SpiFlash, > + 0x0, > + FileSize, > + (UINT8 *)FileBuffer); > + if (EFI_ERROR (Status)) { > + Print (L"%s: Error while performing flash update\n", CMD_NAME_STRING); > + goto FlashProbeError; > + } > + > + // Release resources > + SpiMasterProtocol->FreeDevice (SpiFlash); > + > + return EFI_SUCCESS; > + > +FlashProbeError: > + SpiMasterProtocol->FreeDevice (SpiFlash); > + > + return Status; > +} > + > +/** > + Parse commandline parameters and pick device for the firmware update. > + > + @param[in] *CheckPackage Shell command argument list. > + @param[in/out] *FlashCommand Pointer to firmware update command. > + Picked, depending on the device type. > + @param[in/out] *Alignment File buffer alignment value. > + @param[in/out] *Offset First logical block to be updated. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +SelectDevice ( > + IN LIST_ENTRY *CheckPackage, > + IN OUT FLASH_COMMAND *FlashCommand, > + IN OUT UINT64 *Alignment, > + IN OUT EFI_LBA *Offset > + ) > +{ > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > + CONST CHAR16 *DeviceName; > + EFI_HANDLE Handle; > + UINTN HandleIndex; > + EFI_STATUS Status; > + > + // > + // SPI flash > + // > + DeviceName = ShellCommandLineGetRawValue (CheckPackage, 2); > + if (DeviceName == NULL || StrnCmp(DeviceName, L"spi", 4) == 0) { > + *FlashCommand = ProgramSpiFlash; > + *Alignment = 0; > + *Offset = 0; > + return EFI_SUCCESS; > + } > + > + if (ShellCommandLineGetFlag (CheckPackage, SHELL_USE_DEVICE_PATH_PARAM)) { > + // > + // SD/MMC is selected using device path string. > + // > + Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, > + NULL, > + (VOID **)&EfiDevicePathFromTextProtocol); > + if (EFI_ERROR (Status)) { > + Print (L"%s: cannot locate EfiDevicePathFromText protocol\n", > + CMD_NAME_STRING); > + return EFI_INVALID_PARAMETER; > + } > + > + DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DeviceName); > + if (DevicePath == NULL) { > + Print (L"%s: cannot locate EfiDevicePathFromText protocol\n", > + CMD_NAME_STRING); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, > + &DevicePath, > + &Handle); > + if (EFI_ERROR (Status)) { > + Print (L"%s: cannot locate selected block device\n", CMD_NAME_STRING); > + return Status; > + } > + } else { > + // > + // SD/MMC device is selected using handle number. > + // > + HandleIndex = ShellHexStrToUintn (DeviceName); > + if (HandleIndex == (UINTN)(-1)) { > + Print (L"%s: handle to device have to be hex number\n", CMD_NAME_STRING); > + return EFI_INVALID_PARAMETER; > + } > + > + Handle = ConvertHandleIndexToHandle (HandleIndex); > + if (Handle == NULL) { > + Print (L"%s: %x is not correct device handle\n", > + CMD_NAME_STRING, > + HandleIndex); > + return EFI_INVALID_PARAMETER; > + } > + } > + > + Status = IsDeviceSupported (Handle, Offset); > + if (EFI_ERROR (Status)) { > + Print (L"%s: device not supported\n", CMD_NAME_STRING); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = gBS->OpenProtocol (Handle, > + &gEfiBlockIoProtocolGuid, > + (VOID**)&BlkIo, > + gImageHandle, > + NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL); > + if (EFI_ERROR (Status)) { > + Print (L"%s: Cannot open device BlokIo protocol\n", CMD_NAME_STRING); > + return Status; > + } > + *FlashCommand = ProgramBlockDevice; > + *Alignment = BlkIo->Media->BlockSize; > > return EFI_SUCCESS; > } > @@ -222,11 +638,23 @@ FUpdateUsage ( > ) > { > Print (L"\nFirmware update command\n" > - "fupdate <LocalFilePath>\n\n" > + "fupdate <LocalFilePath> [-p] [Device]\n\n" > "LocalFilePath - path to local firmware image file\n" > - "Example:\n" > - "Update firmware from file fs2:flash-image.bin\n" > - " fupdate fs2:flash-image.bin\n" > + "-p - When flag is selected Device is interpreted\n" > + " as device path, not device handle.\n" > + "Device - Select device which will be flashed.\n" > + " Supported devices can be listed using \"fupdate list\"\n" > + " command. Device is represented by its handle.\n" > + " The default value is spi.\n" > + "EXAMPLES:\n" > + " * Update firmware in SPI flash from file fs2:flash-image.bin\n" > + " fupdate fs2:flash-image.bin\n" > + " * Update firmware in device with handle 5F from file flash-image.bin\n" > + " fupdate flash-image.bin 5F\n" > + " * Update firmware in device with selected path from file flash.bin\n" > + " fupdate flash.bin -p VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/SD(0x0)\n" > + " * List supported devices\n" > + " fupdate list\n" > ); > } > > @@ -238,36 +666,17 @@ ShellCommandRunFUpdate ( > IN EFI_SYSTEM_TABLE *SystemTable > ) > { > - IN SHELL_FILE_HANDLE FileHandle; > - SPI_DEVICE *Slave = NULL; > - UINT64 FileSize; > - UINTN *FileBuffer = NULL; > - CHAR16 *ProblemParam; > - LIST_ENTRY *CheckPackage; > - EFI_STATUS Status; > - > - // Locate SPI protocols > - Status = gBS->LocateProtocol ( > - &gMarvellSpiFlashProtocolGuid, > - NULL, > - (VOID **)&SpiFlashProtocol > - ); > - > - if (EFI_ERROR(Status)) { > - Print (L"%s: Cannot locate SpiFlash protocol\n", CMD_NAME_STRING); > - return SHELL_ABORTED; > - } > - > - Status = gBS->LocateProtocol ( > - &gMarvellSpiMasterProtocolGuid, > - NULL, > - (VOID **)&SpiMasterProtocol > - ); > - > - if (EFI_ERROR(Status)) { > - Print (L"%s: Cannot locate SpiMaster protocol\n", CMD_NAME_STRING); > - return SHELL_ABORTED; > - } > + SHELL_FILE_HANDLE FileHandle; > + FLASH_COMMAND FlashCommand; > + LIST_ENTRY *CheckPackage; > + EFI_LBA Offset; > + UINT64 Alignment; > + UINT64 FileSize; > + UINTN *FileBuffer; > + CHAR16 *ProblemParam; > + EFI_STATUS Status; > + > + FileBuffer = NULL; > > // Parse command line > Status = ShellInitialize (); > @@ -283,14 +692,29 @@ ShellCommandRunFUpdate ( > return SHELL_ABORTED; > } > > - if (ShellCommandLineGetFlag (CheckPackage, L"help")) { > - FUpdateUsage(); > + if (ShellCommandLineGetFlag (CheckPackage, SHELL_HELP_PARAM)) { > + FUpdateUsage (); > return EFI_SUCCESS; > } > > + if (ShellCommandLineGetFlag (CheckPackage, SHELL_LIST_PARAM)) { > + ListSupportedDevices (); > + return EFI_SUCCESS; > + } > + > + // Select device to flash > + Status = SelectDevice (CheckPackage, &FlashCommand, &Alignment, &Offset); > + if (EFI_ERROR (Status)) { > + return SHELL_ABORTED; > + } > + > // Prepare local file to be burned into flash > - Status = PrepareFirmwareImage (CheckPackage, &FileHandle, &FileBuffer, &FileSize); > - if (EFI_ERROR(Status)) { > + Status = PrepareFirmwareImage (CheckPackage, > + &FileHandle, > + &FileBuffer, > + &FileSize, > + Alignment); > + if (EFI_ERROR (Status)) { > return SHELL_ABORTED; > } > > @@ -300,38 +724,22 @@ ShellCommandRunFUpdate ( > goto HeaderError; > } > > - // Setup and probe SPI flash > - Slave = SpiMasterProtocol->SetupDevice (SpiMasterProtocol, Slave, 0, 0); > - if (Slave == NULL) { > - Print(L"%s: Cannot allocate SPI device!\n", CMD_NAME_STRING); > + // Update firmware image > + Status = FlashCommand (FileSize, FileBuffer, Offset); > + if (EFI_ERROR (Status)) { > goto HeaderError; > } > > - Status = SpiFlashProbe (Slave); > - if (EFI_ERROR(Status)) { > - Print (L"%s: Error while performing SPI flash probe\n", CMD_NAME_STRING); > - goto FlashProbeError; > - } > - > - // Update firmware image in flash at offset 0x0 > - Status = SpiFlashProtocol->Update (Slave, 0, FileSize, (UINT8 *)FileBuffer); > - > - // Release resources > - SpiMasterProtocol->FreeDevice(Slave); > FreePool (FileBuffer); > ShellCloseFile (&FileHandle); > > - if (EFI_ERROR(Status)) { > - Print (L"%s: Error while performing flash update\n", CMD_NAME_STRING); > - return SHELL_ABORTED; > - } > - > - Print (L"%s: Update %d bytes at offset 0x0 succeeded!\n", CMD_NAME_STRING, FileSize); > + Print (L"%s: Update %d bytes at offset 0x%x succeeded!\n", > + CMD_NAME_STRING, > + FileSize, > + Offset * Alignment); > > return EFI_SUCCESS; > > -FlashProbeError: > - SpiMasterProtocol->FreeDevice(Slave); > HeaderError: > FreePool (FileBuffer); > ShellCloseFile (&FileHandle); > diff --git a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni > index 146f624737d96e2cd354857dbb63390ebe2f347e..3ea892aa2a982827ad235c505270acbca21ea27b 100644 > GIT binary patch > delta 1093 > zcmah|(P|Sx6g@$uNPXDuTB`)<=u@MnS*4*0zNBf3VttT^MNE-2v2I|EF`G2{<TuDg > z@FxU|U!V{Ehai3S*(cAP$>^GjGVIKqnRDmfd(Pc2ONT2TJ_kjEM<}C@9jLXAC)h_9 > zZLT}=DaZ<asm?V{7{$ofs3`Hw@rPw%w~-LjqqT<=Ej*>wMaDVfdCISiA?FTH@~?VS > zm%e&GVC(@`i<K8aB;TU5@;y4Gk!mgbVu$xWD?@yX=mb~zau3gG8%D_^5+Zs$V-|7{ > zEzIWP%e`n}L-TLY!)H0|Kj!PoK|<V^R?1<pOAlXdhD6?zjl<}S&-HEtBj(m;Mgvz3 > z(fPcTo3_o&zm;0XJWC_is;nrJO?eYUv;Mw`i_^?(w;AUdhpTj%KDjEnb6O~~j$c*9 > zF|La2;+4e=Ex%KI<*TaPw>rB@_84tME|l?o+9`L+iPyc4F8Q99A3-4R=9=u9OE7XW > zxFDy)q+nzm-uZo2(OUmx$g!>38h*bt<gSWMxg4I8tuUT9+^Y`Cc84hC&&cg?k#8%G > zJ#=gmxBBlGM?2N_mXyNcjP|su{5U-S`mYfueNPOQ$)}5?f0Dri%k?ex&JtqkQpHu= > zpjE{h|D!dma%|9A;mI}BXw|sZi74~D&Rxv8j_c0%CV@4!dpsGdyx63J-{;p7Ds1g_ > m8~7y=C8eW6I<RGBQt7h)HLCh7x}uK|P0>~E;m3pUZQ&;(bkkG- > > delta 54 > zcmV-60LlO6G{z{f!Vr_v7#NfG5Ly9HlTi^<liCz)lL`<ZlP(tqlX4Yelf)Jhlk62V > MlkN}*v+5Xp0aXzc(f|Me > > -- > 2.7.4 > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#39916): https://edk2.groups.io/g/devel/message/39916 Mute This Topic: https://groups.io/mt/31453651/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
Hi Ard, czw., 2 maj 2019 o 14:58 Ard Biesheuvel <ard.biesheuvel@linaro.org> napisał(a): > > On Thu, 2 May 2019 at 13:31, Marcin Wojtas <mw@semihalf.com> wrote: > > > > From: Tomasz Michalec <tm@semihalf.com> > > > > Extend fupdate shell application to be able to flash firmware > > on SD/MMC. Device on which firmware will be updated > > is selected via third argument of command. > > The SPI is still used as default. > > > > Command uses BlockIo protocol to communicate with SD/MMC. It is possible > > to list all valid devices and specify selection via handle number or > > device path string. Example output (detailed usage can be found in > > updated command's 'help'): > > > > Shell> fupdate list > > Handle Path > > spi spi > > 8F VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,00006EF00000000000)/SD(0x0) > > 93 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/eMMC(0x0)/Ctrl(0x0) > > 94 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/eMMC(0x0)/Ctrl(0x1) > > 95 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/eMMC(0x0)/Ctrl(0x2) > > > > The code was restructured, to dynamically assign appropriate > > firmware update routine, depending on the user choice > > (SPI vs BlockDevice). > > > > Contributed-under: TianoCore Contribution Agreement 1.1 > > Signed-off-by: Marcin Wojtas <mw@semihalf.com> > > Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> > > Pushed as cee103d37d6b..4795747fe477 > Wow, thanks - I didn't expect it to happen that fast :) If so, I'm submitting the last 3 small patches I have on my stack. PCIE most likely tomorrow. Afterwards SMBIOS and we'd be functionally ahead of any other branch for this SoC :) Best regard, Marcin > > --- > > Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf | 13 +- > > Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c | 542 +++++++++++++++++--- > > Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni | Bin 5190 -> 6758 bytes > > 3 files changed, 485 insertions(+), 70 deletions(-) > > > > diff --git a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf > > index 69ee0f8..46847fc 100644 > > --- a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf > > +++ b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.inf > > @@ -55,6 +55,7 @@ > > BaseMemoryLib > > DebugLib > > FileHandleLib > > + HandleParsingLib > > HiiLib > > MemoryAllocationLib > > PcdLib > > @@ -62,12 +63,18 @@ > > ShellLib > > UefiBootServicesTableLib > > UefiLib > > - UefiLib > > UefiRuntimeServicesTableLib > > > > +[Pcd] > > + gMarvellTokenSpaceGuid.PcdSpiFlashCs > > + gMarvellTokenSpaceGuid.PcdSpiFlashMode > > + > > [Protocols] > > - gMarvellSpiFlashProtocolGuid > > - gMarvellSpiMasterProtocolGuid > > + gEfiBlockIoProtocolGuid > > + gEfiDevicePathFromTextProtocolGuid > > + gEfiDevicePathProtocolGuid > > + gMarvellSpiFlashProtocolGuid > > + gMarvellSpiMasterProtocolGuid > > > > [Guids] > > gShellFUpdateHiiGuid > > diff --git a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c > > index 22a9b8f..3a496f0 100644 > > --- a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c > > +++ b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.c > > @@ -36,7 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > > #include <Library/BaseLib.h> > > #include <Library/BaseMemoryLib.h> > > #include <Library/DebugLib.h> > > +#include <Library/DevicePathLib.h> > > #include <Library/FileHandleLib.h> > > +#include <Library/HandleParsingLib.h> > > #include <Library/HiiLib.h> > > #include <Library/MemoryAllocationLib.h> > > #include <Library/PrintLib.h> > > @@ -46,22 +48,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > > #include <Library/UefiBootServicesTableLib.h> > > #include <Library/UefiLib.h> > > > > +#include <Protocol/BlockIo.h> > > +#include <Protocol/DevicePath.h> > > +#include <Protocol/DevicePathFromText.h> > > #include <Protocol/Spi.h> > > #include <Protocol/SpiFlash.h> > > > > #define CMD_NAME_STRING L"fupdate" > > > > +#define SHELL_USE_DEVICE_PATH_PARAM L"-p" > > +#define SHELL_DEVICE_NAME_PARAM L"DeviceName" > > +#define SHELL_FILE_NAME_PARAM L"LocalFileName" > > +#define SHELL_HELP_PARAM L"help" > > +#define SHELL_LIST_PARAM L"list" > > + > > #define MAIN_HDR_MAGIC 0xB105B002 > > > > -STATIC MARVELL_SPI_FLASH_PROTOCOL *SpiFlashProtocol; > > -STATIC MARVELL_SPI_MASTER_PROTOCOL *SpiMasterProtocol; > > +STATIC EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; > > +STATIC MARVELL_SPI_MASTER_PROTOCOL *SpiMasterProtocol; > > +STATIC MARVELL_SPI_FLASH_PROTOCOL *SpiFlashProtocol; > > +STATIC EFI_BLOCK_IO_PROTOCOL *BlkIo; > > > > STATIC CONST CHAR16 gShellFUpdateFileName[] = L"ShellCommands"; > > STATIC EFI_HANDLE gShellFUpdateHiiHandle = NULL; > > > > STATIC CONST SHELL_PARAM_ITEM ParamList[] = { > > - {L"help", TypeFlag}, > > - {NULL , TypeMax} > > + {SHELL_HELP_PARAM, TypeFlag}, > > + {SHELL_LIST_PARAM, TypeFlag}, > > + {SHELL_USE_DEVICE_PATH_PARAM, TypeFlag}, > > + {SHELL_FILE_NAME_PARAM, TypePosition}, > > + {SHELL_DEVICE_NAME_PARAM, TypePosition}, > > + {NULL , TypeMax} > > }; > > > > typedef struct { // Bytes > > @@ -86,6 +103,14 @@ typedef struct { // Bytes > > UINT32 Reserved3; // 60-63 > > } MV_FIRMWARE_IMAGE_HEADER; > > > > +typedef > > +EFI_STATUS > > +(EFIAPI *FLASH_COMMAND) ( > > + UINT64 FileSize, > > + UINTN *FileBuffer, > > + EFI_LBA Offset > > +); > > + > > STATIC > > EFI_STATUS > > SpiFlashProbe ( > > @@ -109,6 +134,156 @@ SpiFlashProbe ( > > return EFI_SUCCESS; > > } > > > > +/** > > + Verify if selected device is valid for the firmware update. > > + > > + @param[in] Handle Handle of verified device > > + @param[in] Offset [OPTIONAL] Additional parameter > > + required for BlkIo->WriteBlocks, > > + filled depending on detected device > > + type. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +IsDeviceSupported ( > > + IN EFI_HANDLE Handle, > > + OUT EFI_LBA *Offset OPTIONAL > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > > + > > + // > > + // Skip handles that do not have device path protocol > > + // > > + Status = gBS->OpenProtocol (Handle, > > + &gEfiDevicePathProtocolGuid, > > + (VOID**)&DevicePath, > > + gImageHandle, > > + NULL, > > + EFI_OPEN_PROTOCOL_GET_PROTOCOL); > > + if (EFI_ERROR (Status)) { > > + return EFI_UNSUPPORTED; > > + } > > + > > + // > > + // Skip handles that are not block devices > > + // > > + Status = gBS->OpenProtocol (Handle, > > + &gEfiBlockIoProtocolGuid, > > + NULL, > > + NULL, > > + NULL, > > + EFI_OPEN_PROTOCOL_TEST_PROTOCOL); > > + if (EFI_ERROR (Status)) { > > + return EFI_UNSUPPORTED; > > + } > > + > > + while (!IsDevicePathEnd (DevicePath)) { > > + if (DevicePath->Type == MESSAGING_DEVICE_PATH) { > > + // > > + // Search for SD/MMC devices. > > + // > > + if (DevicePath->SubType == MSG_SD_DP) { > > + // > > + // Only flashing in the beginning of SD card makes sense. > > + // > > + DevicePath = NextDevicePathNode (DevicePath); > > + if (!IsDevicePathEnd (DevicePath)) { > > + return EFI_UNSUPPORTED; > > + } > > + if (Offset != NULL) { > > + *Offset = 1; > > + } > > + return EFI_SUCCESS; > > + } > > + if (DevicePath->SubType == MSG_EMMC_DP) { > > + // > > + // Filter out entire MMC device (ctrl(0x0)) > > + // and boot partitions (ctrl(0x1)/ctrl(0x2)) as valid for > > + // the firmware update. > > + // > > + DevicePath = NextDevicePathNode (DevicePath); > > + if (IsDevicePathEnd (DevicePath)) { > > + return EFI_UNSUPPORTED; > > + } > > + DevicePath = NextDevicePathNode (DevicePath); > > + if (!IsDevicePathEnd (DevicePath)) { > > + return EFI_UNSUPPORTED; > > + } > > + if (Offset != NULL) { > > + *Offset = 0; > > + } > > + return EFI_SUCCESS; > > + } > > + } > > + DevicePath = NextDevicePathNode (DevicePath); > > + } > > + > > + return EFI_UNSUPPORTED; > > +} > > + > > +/** > > + Print information about single device supporting the firmware update. > > + > > + @param[in] Handle Handle of verified device > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +PrintSupportedDevice ( > > + IN EFI_HANDLE Handle > > + ) > > +{ > > + CHAR16 *Name; > > + > > + gEfiShellProtocol->GetDeviceName (Handle, > > + EFI_DEVICE_NAME_USE_DEVICE_PATH, > > + NULL, > > + &Name); > > + if (Name != NULL) { > > + ShellPrintEx (-1, > > + -1, > > + L"%H%02x%N %s\n", > > + ConvertHandleToHandleIndex (Handle), > > + Name); > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Print information about all devices supporting the firmware update. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +ListSupportedDevices ( > > + ) > > +{ > > + UINTN LoopVar; > > + EFI_HANDLE Handle; > > + EFI_STATUS Status; > > + > > + ShellPrintEx (-1, -1, L"%BHandle Path%N\n"); > > + ShellPrintEx (-1, -1, L"%Hspi%N spi\n"); > > + > > + for (LoopVar = 1; ; LoopVar++) { > > + Handle = ConvertHandleIndexToHandle (LoopVar); > > + if (Handle == NULL) { > > + break; > > + } > > + > > + Status = IsDeviceSupported (Handle, NULL); > > + if (!EFI_ERROR (Status)) { > > + PrintSupportedDevice (Handle); > > + } > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > STATIC > > EFI_STATUS > > CheckImageHeader ( > > @@ -149,13 +324,15 @@ PrepareFirmwareImage ( > > IN LIST_ENTRY *CheckPackage, > > IN OUT SHELL_FILE_HANDLE *FileHandle, > > IN OUT UINTN **FileBuffer, > > - IN OUT UINT64 *FileSize > > + IN OUT UINT64 *FileSize, > > + IN UINT64 Alignment > > ) > > { > > CONST CHAR16 *FileStr; > > EFI_STATUS Status; > > UINT64 OpenMode; > > UINTN *Buffer; > > + UINTN AlignedFileSize; > > > > // Parse string from commandline > > FileStr = ShellCommandLineGetRawValue (CheckPackage, 1); > > @@ -184,8 +361,20 @@ PrepareFirmwareImage ( > > Print (L"%s: Cannot get Image file size\n", CMD_NAME_STRING); > > } > > > > + // Allocate aligned buffer in case of updating firmware in a BlockDevice > > + if (Alignment > 0) { > > + AlignedFileSize = *FileSize + (Alignment - (*FileSize % Alignment)); > > + } else { > > + AlignedFileSize = *FileSize; > > + } > > + > > // Read Image header into buffer > > - Buffer = AllocateZeroPool (*FileSize); > > + Buffer = AllocateZeroPool (AlignedFileSize); > > + if (Buffer == NULL) { > > + Print (L"%s: Fail to allocate buffer\n", CMD_NAME_STRING); > > + ShellCloseFile (FileHandle); > > + return EFI_OUT_OF_RESOURCES; > > + } > > > > Status = FileHandleRead (*FileHandle, (UINTN *)FileSize, Buffer); > > if (EFI_ERROR (Status)) { > > @@ -196,6 +385,233 @@ PrepareFirmwareImage ( > > } > > > > *FileBuffer = Buffer; > > + *FileSize = AlignedFileSize; > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Update firmware image in the block device. > > + > > + @param[in] FileSize Size of the file to be flashed > > + @param[in] *FileBuffer Pointer to the file in memory > > + @param[in] Offset First logical block to be updated. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +EFIAPI > > +ProgramBlockDevice ( > > + IN UINT64 FileSize, > > + IN UINTN *FileBuffer, > > + IN EFI_LBA Offset > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Print (L"Updating image in BlockDevice\n"); > > + > > + Status = BlkIo->WriteBlocks (BlkIo, > > + BlkIo->Media->MediaId, > > + Offset, > > + FileSize, > > + FileBuffer); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: Cannot write to device (Status: %r)\n", > > + CMD_NAME_STRING, > > + Status); > > + return Status; > > + } > > + > > + Status = BlkIo->FlushBlocks (BlkIo); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: Cannot flush to device (Status: %r)\n", > > + CMD_NAME_STRING, > > + Status); > > + return Status; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > + > > +/** > > + Update firmware image in the SPI flash. > > + > > + @param[in] FileSize Size of the file to be flashed > > + @param[in] *FileBuffer Pointer to the file in memory > > + @param[in] Offset First logical block to be updated. > > + Irrelevant for SPI. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +EFIAPI > > +ProgramSpiFlash ( > > + IN UINT64 FileSize, > > + IN UINTN *FileBuffer, > > + IN EFI_LBA Offset > > + ) > > +{ > > + SPI_DEVICE *SpiFlash; > > + EFI_STATUS Status; > > + > > + // Locate SPI protocols > > + Status = gBS->LocateProtocol (&gMarvellSpiFlashProtocolGuid, > > + NULL, > > + (VOID **)&SpiFlashProtocol); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: Cannot locate SpiFlash protocol\n", CMD_NAME_STRING); > > + return Status; > > + } > > + > > + Status = gBS->LocateProtocol (&gMarvellSpiMasterProtocolGuid, > > + NULL, > > + (VOID **)&SpiMasterProtocol); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: Cannot locate SpiMaster protocol\n", CMD_NAME_STRING); > > + return Status; > > + } > > + > > + // Setup and probe SPI flash > > + SpiFlash = NULL; > > + SpiFlash = SpiMasterProtocol->SetupDevice (SpiMasterProtocol, > > + SpiFlash, > > + PcdGet32 (PcdSpiFlashCs), > > + PcdGet32 (PcdSpiFlashMode)); > > + if (SpiFlash == NULL) { > > + Print(L"%s: Cannot allocate SPI device!\n", CMD_NAME_STRING); > > + return EFI_ABORTED; > > + } > > + > > + Status = SpiFlashProbe (SpiFlash); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: Error while performing SPI flash probe\n", CMD_NAME_STRING); > > + goto FlashProbeError; > > + } > > + > > + // Update firmware image in flash at offset 0x0 > > + Status = SpiFlashProtocol->Update (SpiFlash, > > + 0x0, > > + FileSize, > > + (UINT8 *)FileBuffer); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: Error while performing flash update\n", CMD_NAME_STRING); > > + goto FlashProbeError; > > + } > > + > > + // Release resources > > + SpiMasterProtocol->FreeDevice (SpiFlash); > > + > > + return EFI_SUCCESS; > > + > > +FlashProbeError: > > + SpiMasterProtocol->FreeDevice (SpiFlash); > > + > > + return Status; > > +} > > + > > +/** > > + Parse commandline parameters and pick device for the firmware update. > > + > > + @param[in] *CheckPackage Shell command argument list. > > + @param[in/out] *FlashCommand Pointer to firmware update command. > > + Picked, depending on the device type. > > + @param[in/out] *Alignment File buffer alignment value. > > + @param[in/out] *Offset First logical block to be updated. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +EFIAPI > > +SelectDevice ( > > + IN LIST_ENTRY *CheckPackage, > > + IN OUT FLASH_COMMAND *FlashCommand, > > + IN OUT UINT64 *Alignment, > > + IN OUT EFI_LBA *Offset > > + ) > > +{ > > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > > + CONST CHAR16 *DeviceName; > > + EFI_HANDLE Handle; > > + UINTN HandleIndex; > > + EFI_STATUS Status; > > + > > + // > > + // SPI flash > > + // > > + DeviceName = ShellCommandLineGetRawValue (CheckPackage, 2); > > + if (DeviceName == NULL || StrnCmp(DeviceName, L"spi", 4) == 0) { > > + *FlashCommand = ProgramSpiFlash; > > + *Alignment = 0; > > + *Offset = 0; > > + return EFI_SUCCESS; > > + } > > + > > + if (ShellCommandLineGetFlag (CheckPackage, SHELL_USE_DEVICE_PATH_PARAM)) { > > + // > > + // SD/MMC is selected using device path string. > > + // > > + Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, > > + NULL, > > + (VOID **)&EfiDevicePathFromTextProtocol); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: cannot locate EfiDevicePathFromText protocol\n", > > + CMD_NAME_STRING); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DeviceName); > > + if (DevicePath == NULL) { > > + Print (L"%s: cannot locate EfiDevicePathFromText protocol\n", > > + CMD_NAME_STRING); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, > > + &DevicePath, > > + &Handle); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: cannot locate selected block device\n", CMD_NAME_STRING); > > + return Status; > > + } > > + } else { > > + // > > + // SD/MMC device is selected using handle number. > > + // > > + HandleIndex = ShellHexStrToUintn (DeviceName); > > + if (HandleIndex == (UINTN)(-1)) { > > + Print (L"%s: handle to device have to be hex number\n", CMD_NAME_STRING); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Handle = ConvertHandleIndexToHandle (HandleIndex); > > + if (Handle == NULL) { > > + Print (L"%s: %x is not correct device handle\n", > > + CMD_NAME_STRING, > > + HandleIndex); > > + return EFI_INVALID_PARAMETER; > > + } > > + } > > + > > + Status = IsDeviceSupported (Handle, Offset); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: device not supported\n", CMD_NAME_STRING); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Status = gBS->OpenProtocol (Handle, > > + &gEfiBlockIoProtocolGuid, > > + (VOID**)&BlkIo, > > + gImageHandle, > > + NULL, > > + EFI_OPEN_PROTOCOL_GET_PROTOCOL); > > + if (EFI_ERROR (Status)) { > > + Print (L"%s: Cannot open device BlokIo protocol\n", CMD_NAME_STRING); > > + return Status; > > + } > > + *FlashCommand = ProgramBlockDevice; > > + *Alignment = BlkIo->Media->BlockSize; > > > > return EFI_SUCCESS; > > } > > @@ -222,11 +638,23 @@ FUpdateUsage ( > > ) > > { > > Print (L"\nFirmware update command\n" > > - "fupdate <LocalFilePath>\n\n" > > + "fupdate <LocalFilePath> [-p] [Device]\n\n" > > "LocalFilePath - path to local firmware image file\n" > > - "Example:\n" > > - "Update firmware from file fs2:flash-image.bin\n" > > - " fupdate fs2:flash-image.bin\n" > > + "-p - When flag is selected Device is interpreted\n" > > + " as device path, not device handle.\n" > > + "Device - Select device which will be flashed.\n" > > + " Supported devices can be listed using \"fupdate list\"\n" > > + " command. Device is represented by its handle.\n" > > + " The default value is spi.\n" > > + "EXAMPLES:\n" > > + " * Update firmware in SPI flash from file fs2:flash-image.bin\n" > > + " fupdate fs2:flash-image.bin\n" > > + " * Update firmware in device with handle 5F from file flash-image.bin\n" > > + " fupdate flash-image.bin 5F\n" > > + " * Update firmware in device with selected path from file flash.bin\n" > > + " fupdate flash.bin -p VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000078F20000000000)/SD(0x0)\n" > > + " * List supported devices\n" > > + " fupdate list\n" > > ); > > } > > > > @@ -238,36 +666,17 @@ ShellCommandRunFUpdate ( > > IN EFI_SYSTEM_TABLE *SystemTable > > ) > > { > > - IN SHELL_FILE_HANDLE FileHandle; > > - SPI_DEVICE *Slave = NULL; > > - UINT64 FileSize; > > - UINTN *FileBuffer = NULL; > > - CHAR16 *ProblemParam; > > - LIST_ENTRY *CheckPackage; > > - EFI_STATUS Status; > > - > > - // Locate SPI protocols > > - Status = gBS->LocateProtocol ( > > - &gMarvellSpiFlashProtocolGuid, > > - NULL, > > - (VOID **)&SpiFlashProtocol > > - ); > > - > > - if (EFI_ERROR(Status)) { > > - Print (L"%s: Cannot locate SpiFlash protocol\n", CMD_NAME_STRING); > > - return SHELL_ABORTED; > > - } > > - > > - Status = gBS->LocateProtocol ( > > - &gMarvellSpiMasterProtocolGuid, > > - NULL, > > - (VOID **)&SpiMasterProtocol > > - ); > > - > > - if (EFI_ERROR(Status)) { > > - Print (L"%s: Cannot locate SpiMaster protocol\n", CMD_NAME_STRING); > > - return SHELL_ABORTED; > > - } > > + SHELL_FILE_HANDLE FileHandle; > > + FLASH_COMMAND FlashCommand; > > + LIST_ENTRY *CheckPackage; > > + EFI_LBA Offset; > > + UINT64 Alignment; > > + UINT64 FileSize; > > + UINTN *FileBuffer; > > + CHAR16 *ProblemParam; > > + EFI_STATUS Status; > > + > > + FileBuffer = NULL; > > > > // Parse command line > > Status = ShellInitialize (); > > @@ -283,14 +692,29 @@ ShellCommandRunFUpdate ( > > return SHELL_ABORTED; > > } > > > > - if (ShellCommandLineGetFlag (CheckPackage, L"help")) { > > - FUpdateUsage(); > > + if (ShellCommandLineGetFlag (CheckPackage, SHELL_HELP_PARAM)) { > > + FUpdateUsage (); > > return EFI_SUCCESS; > > } > > > > + if (ShellCommandLineGetFlag (CheckPackage, SHELL_LIST_PARAM)) { > > + ListSupportedDevices (); > > + return EFI_SUCCESS; > > + } > > + > > + // Select device to flash > > + Status = SelectDevice (CheckPackage, &FlashCommand, &Alignment, &Offset); > > + if (EFI_ERROR (Status)) { > > + return SHELL_ABORTED; > > + } > > + > > // Prepare local file to be burned into flash > > - Status = PrepareFirmwareImage (CheckPackage, &FileHandle, &FileBuffer, &FileSize); > > - if (EFI_ERROR(Status)) { > > + Status = PrepareFirmwareImage (CheckPackage, > > + &FileHandle, > > + &FileBuffer, > > + &FileSize, > > + Alignment); > > + if (EFI_ERROR (Status)) { > > return SHELL_ABORTED; > > } > > > > @@ -300,38 +724,22 @@ ShellCommandRunFUpdate ( > > goto HeaderError; > > } > > > > - // Setup and probe SPI flash > > - Slave = SpiMasterProtocol->SetupDevice (SpiMasterProtocol, Slave, 0, 0); > > - if (Slave == NULL) { > > - Print(L"%s: Cannot allocate SPI device!\n", CMD_NAME_STRING); > > + // Update firmware image > > + Status = FlashCommand (FileSize, FileBuffer, Offset); > > + if (EFI_ERROR (Status)) { > > goto HeaderError; > > } > > > > - Status = SpiFlashProbe (Slave); > > - if (EFI_ERROR(Status)) { > > - Print (L"%s: Error while performing SPI flash probe\n", CMD_NAME_STRING); > > - goto FlashProbeError; > > - } > > - > > - // Update firmware image in flash at offset 0x0 > > - Status = SpiFlashProtocol->Update (Slave, 0, FileSize, (UINT8 *)FileBuffer); > > - > > - // Release resources > > - SpiMasterProtocol->FreeDevice(Slave); > > FreePool (FileBuffer); > > ShellCloseFile (&FileHandle); > > > > - if (EFI_ERROR(Status)) { > > - Print (L"%s: Error while performing flash update\n", CMD_NAME_STRING); > > - return SHELL_ABORTED; > > - } > > - > > - Print (L"%s: Update %d bytes at offset 0x0 succeeded!\n", CMD_NAME_STRING, FileSize); > > + Print (L"%s: Update %d bytes at offset 0x%x succeeded!\n", > > + CMD_NAME_STRING, > > + FileSize, > > + Offset * Alignment); > > > > return EFI_SUCCESS; > > > > -FlashProbeError: > > - SpiMasterProtocol->FreeDevice(Slave); > > HeaderError: > > FreePool (FileBuffer); > > ShellCloseFile (&FileHandle); > > diff --git a/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni b/Silicon/Marvell/Applications/FirmwareUpdate/FUpdate.uni > > index 146f624737d96e2cd354857dbb63390ebe2f347e..3ea892aa2a982827ad235c505270acbca21ea27b 100644 > > GIT binary patch > > delta 1093 > > zcmah|(P|Sx6g@$uNPXDuTB`)<=u@MnS*4*0zNBf3VttT^MNE-2v2I|EF`G2{<TuDg > > z@FxU|U!V{Ehai3S*(cAP$>^GjGVIKqnRDmfd(Pc2ONT2TJ_kjEM<}C@9jLXAC)h_9 > > zZLT}=DaZ<asm?V{7{$ofs3`Hw@rPw%w~-LjqqT<=Ej*>wMaDVfdCISiA?FTH@~?VS > > zm%e&GVC(@`i<K8aB;TU5@;y4Gk!mgbVu$xWD?@yX=mb~zau3gG8%D_^5+Zs$V-|7{ > > zEzIWP%e`n}L-TLY!)H0|Kj!PoK|<V^R?1<pOAlXdhD6?zjl<}S&-HEtBj(m;Mgvz3 > > z(fPcTo3_o&zm;0XJWC_is;nrJO?eYUv;Mw`i_^?(w;AUdhpTj%KDjEnb6O~~j$c*9 > > zF|La2;+4e=Ex%KI<*TaPw>rB@_84tME|l?o+9`L+iPyc4F8Q99A3-4R=9=u9OE7XW > > zxFDy)q+nzm-uZo2(OUmx$g!>38h*bt<gSWMxg4I8tuUT9+^Y`Cc84hC&&cg?k#8%G > > zJ#=gmxBBlGM?2N_mXyNcjP|su{5U-S`mYfueNPOQ$)}5?f0Dri%k?ex&JtqkQpHu= > > zpjE{h|D!dma%|9A;mI}BXw|sZi74~D&Rxv8j_c0%CV@4!dpsGdyx63J-{;p7Ds1g_ > > m8~7y=C8eW6I<RGBQt7h)HLCh7x}uK|P0>~E;m3pUZQ&;(bkkG- > > > > delta 54 > > zcmV-60LlO6G{z{f!Vr_v7#NfG5Ly9HlTi^<liCz)lL`<ZlP(tqlX4Yelf)Jhlk62V > > MlkN}*v+5Xp0aXzc(f|Me > > > > -- > > 2.7.4 > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#39917): https://edk2.groups.io/g/devel/message/39917 Mute This Topic: https://groups.io/mt/31453651/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.