summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Application/CapsuleApp
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Application/CapsuleApp
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-trunk.tar.xz
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Application/CapsuleApp')
-rw-r--r--MdeModulePkg/Application/CapsuleApp/AppSupport.c464
-rw-r--r--MdeModulePkg/Application/CapsuleApp/CapsuleApp.c2094
-rw-r--r--MdeModulePkg/Application/CapsuleApp/CapsuleApp.h468
-rw-r--r--MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf138
-rw-r--r--MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni34
-rw-r--r--MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni28
-rw-r--r--MdeModulePkg/Application/CapsuleApp/CapsuleDump.c2936
-rw-r--r--MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c1714
8 files changed, 3938 insertions, 3938 deletions
diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
index 3b98ad07bf..d75c532352 100644
--- a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
+++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
@@ -1,232 +1,232 @@
-/** @file
- A shell application that triggers capsule update process.
-
- Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "CapsuleApp.h"
-
-UINTN Argc;
-CHAR16 **Argv;
-EFI_SHELL_PROTOCOL *mShellProtocol = NULL;
-
-/**
-
- This function parse application ARG.
-
- @return Status
-**/
-EFI_STATUS
-GetArg (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;
-
- Status = gBS->HandleProtocol (
- gImageHandle,
- &gEfiShellParametersProtocolGuid,
- (VOID **)&ShellParameters
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Argc = ShellParameters->Argc;
- Argv = ShellParameters->Argv;
- return EFI_SUCCESS;
-}
-
-/**
- Get shell protocol.
-
- @return Pointer to shell protocol.
-**/
-EFI_SHELL_PROTOCOL *
-GetShellProtocol (
- VOID
- )
-{
- EFI_STATUS Status;
-
- if (mShellProtocol == NULL) {
- Status = gBS->LocateProtocol (
- &gEfiShellProtocolGuid,
- NULL,
- (VOID **)&mShellProtocol
- );
- if (EFI_ERROR (Status)) {
- mShellProtocol = NULL;
- }
- }
-
- return mShellProtocol;
-}
-
-/**
- Read a file.
-
- @param[in] FileName The file to be read.
- @param[out] BufferSize The file buffer size
- @param[out] Buffer The file buffer
-
- @retval EFI_SUCCESS Read file successfully
- @retval EFI_NOT_FOUND Shell protocol or file not found
- @retval others Read file failed
-**/
-EFI_STATUS
-ReadFileToBuffer (
- IN CHAR16 *FileName,
- OUT UINTN *BufferSize,
- OUT VOID **Buffer
- )
-{
- EFI_STATUS Status;
- EFI_SHELL_PROTOCOL *ShellProtocol;
- SHELL_FILE_HANDLE Handle;
- UINT64 FileSize;
- UINTN TempBufferSize;
- VOID *TempBuffer;
-
- ShellProtocol = GetShellProtocol ();
- if (ShellProtocol == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Open file by FileName.
- //
- Status = ShellProtocol->OpenFileByName (
- FileName,
- &Handle,
- EFI_FILE_MODE_READ
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Get the file size.
- //
- Status = ShellProtocol->GetFileSize (Handle, &FileSize);
- if (EFI_ERROR (Status)) {
- ShellProtocol->CloseFile (Handle);
- return Status;
- }
-
- TempBufferSize = (UINTN)FileSize;
- TempBuffer = AllocateZeroPool (TempBufferSize);
- if (TempBuffer == NULL) {
- ShellProtocol->CloseFile (Handle);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Read the file data to the buffer
- //
- Status = ShellProtocol->ReadFile (
- Handle,
- &TempBufferSize,
- TempBuffer
- );
- if (EFI_ERROR (Status)) {
- ShellProtocol->CloseFile (Handle);
- return Status;
- }
-
- ShellProtocol->CloseFile (Handle);
-
- *BufferSize = TempBufferSize;
- *Buffer = TempBuffer;
- return EFI_SUCCESS;
-}
-
-/**
- Write a file.
-
- @param[in] FileName The file to be written.
- @param[in] BufferSize The file buffer size
- @param[in] Buffer The file buffer
-
- @retval EFI_SUCCESS Write file successfully
- @retval EFI_NOT_FOUND Shell protocol not found
- @retval others Write file failed
-**/
-EFI_STATUS
-WriteFileFromBuffer (
- IN CHAR16 *FileName,
- IN UINTN BufferSize,
- IN VOID *Buffer
- )
-{
- EFI_STATUS Status;
- EFI_SHELL_PROTOCOL *ShellProtocol;
- SHELL_FILE_HANDLE Handle;
- EFI_FILE_INFO *FileInfo;
- UINTN TempBufferSize;
-
- ShellProtocol = GetShellProtocol ();
- if (ShellProtocol == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Open file by FileName.
- //
- Status = ShellProtocol->OpenFileByName (
- FileName,
- &Handle,
- EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Empty the file contents.
- //
- FileInfo = ShellProtocol->GetFileInfo (Handle);
- if (FileInfo == NULL) {
- ShellProtocol->CloseFile (Handle);
- return EFI_DEVICE_ERROR;
- }
-
- //
- // If the file size is already 0, then it has been empty.
- //
- if (FileInfo->FileSize != 0) {
- //
- // Set the file size to 0.
- //
- FileInfo->FileSize = 0;
- Status = ShellProtocol->SetFileInfo (Handle, FileInfo);
- if (EFI_ERROR (Status)) {
- FreePool (FileInfo);
- ShellProtocol->CloseFile (Handle);
- return Status;
- }
- }
-
- FreePool (FileInfo);
-
- //
- // Write the file data from the buffer
- //
- TempBufferSize = BufferSize;
- Status = ShellProtocol->WriteFile (
- Handle,
- &TempBufferSize,
- Buffer
- );
- if (EFI_ERROR (Status)) {
- ShellProtocol->CloseFile (Handle);
- return Status;
- }
-
- ShellProtocol->CloseFile (Handle);
-
- return EFI_SUCCESS;
-}
+/** @file
+ A shell application that triggers capsule update process.
+
+ Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CapsuleApp.h"
+
+UINTN Argc;
+CHAR16 **Argv;
+EFI_SHELL_PROTOCOL *mShellProtocol = NULL;
+
+/**
+
+ This function parse application ARG.
+
+ @return Status
+**/
+EFI_STATUS
+GetArg (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;
+
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID **)&ShellParameters
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Argc = ShellParameters->Argc;
+ Argv = ShellParameters->Argv;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get shell protocol.
+
+ @return Pointer to shell protocol.
+**/
+EFI_SHELL_PROTOCOL *
+GetShellProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (mShellProtocol == NULL) {
+ Status = gBS->LocateProtocol (
+ &gEfiShellProtocolGuid,
+ NULL,
+ (VOID **)&mShellProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ mShellProtocol = NULL;
+ }
+ }
+
+ return mShellProtocol;
+}
+
+/**
+ Read a file.
+
+ @param[in] FileName The file to be read.
+ @param[out] BufferSize The file buffer size
+ @param[out] Buffer The file buffer
+
+ @retval EFI_SUCCESS Read file successfully
+ @retval EFI_NOT_FOUND Shell protocol or file not found
+ @retval others Read file failed
+**/
+EFI_STATUS
+ReadFileToBuffer (
+ IN CHAR16 *FileName,
+ OUT UINTN *BufferSize,
+ OUT VOID **Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_PROTOCOL *ShellProtocol;
+ SHELL_FILE_HANDLE Handle;
+ UINT64 FileSize;
+ UINTN TempBufferSize;
+ VOID *TempBuffer;
+
+ ShellProtocol = GetShellProtocol ();
+ if (ShellProtocol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Open file by FileName.
+ //
+ Status = ShellProtocol->OpenFileByName (
+ FileName,
+ &Handle,
+ EFI_FILE_MODE_READ
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the file size.
+ //
+ Status = ShellProtocol->GetFileSize (Handle, &FileSize);
+ if (EFI_ERROR (Status)) {
+ ShellProtocol->CloseFile (Handle);
+ return Status;
+ }
+
+ TempBufferSize = (UINTN)FileSize;
+ TempBuffer = AllocateZeroPool (TempBufferSize);
+ if (TempBuffer == NULL) {
+ ShellProtocol->CloseFile (Handle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Read the file data to the buffer
+ //
+ Status = ShellProtocol->ReadFile (
+ Handle,
+ &TempBufferSize,
+ TempBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ ShellProtocol->CloseFile (Handle);
+ return Status;
+ }
+
+ ShellProtocol->CloseFile (Handle);
+
+ *BufferSize = TempBufferSize;
+ *Buffer = TempBuffer;
+ return EFI_SUCCESS;
+}
+
+/**
+ Write a file.
+
+ @param[in] FileName The file to be written.
+ @param[in] BufferSize The file buffer size
+ @param[in] Buffer The file buffer
+
+ @retval EFI_SUCCESS Write file successfully
+ @retval EFI_NOT_FOUND Shell protocol not found
+ @retval others Write file failed
+**/
+EFI_STATUS
+WriteFileFromBuffer (
+ IN CHAR16 *FileName,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_PROTOCOL *ShellProtocol;
+ SHELL_FILE_HANDLE Handle;
+ EFI_FILE_INFO *FileInfo;
+ UINTN TempBufferSize;
+
+ ShellProtocol = GetShellProtocol ();
+ if (ShellProtocol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Open file by FileName.
+ //
+ Status = ShellProtocol->OpenFileByName (
+ FileName,
+ &Handle,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Empty the file contents.
+ //
+ FileInfo = ShellProtocol->GetFileInfo (Handle);
+ if (FileInfo == NULL) {
+ ShellProtocol->CloseFile (Handle);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // If the file size is already 0, then it has been empty.
+ //
+ if (FileInfo->FileSize != 0) {
+ //
+ // Set the file size to 0.
+ //
+ FileInfo->FileSize = 0;
+ Status = ShellProtocol->SetFileInfo (Handle, FileInfo);
+ if (EFI_ERROR (Status)) {
+ FreePool (FileInfo);
+ ShellProtocol->CloseFile (Handle);
+ return Status;
+ }
+ }
+
+ FreePool (FileInfo);
+
+ //
+ // Write the file data from the buffer
+ //
+ TempBufferSize = BufferSize;
+ Status = ShellProtocol->WriteFile (
+ Handle,
+ &TempBufferSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ ShellProtocol->CloseFile (Handle);
+ return Status;
+ }
+
+ ShellProtocol->CloseFile (Handle);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
index d6fb9283d3..e7936633e6 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
@@ -1,1047 +1,1047 @@
-/** @file
- A shell application that triggers capsule update process.
-
- Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "CapsuleApp.h"
-
-//
-// Define how many block descriptors we want to test with.
-//
-UINTN NumberOfDescriptors = 1;
-UINTN CapsuleFirstIndex;
-UINTN CapsuleLastIndex;
-
-/**
- Create UX capsule.
-
- @retval EFI_SUCCESS The capsule header is appended.
- @retval EFI_UNSUPPORTED Input parameter is not valid.
- @retval EFI_OUT_OF_RESOURCES No enough resource to create UX capsule.
-**/
-EFI_STATUS
-CreateBmpFmp (
- VOID
- )
-{
- CHAR16 *OutputCapsuleName;
- VOID *BmpBuffer;
- UINTN FileSize;
- CHAR16 *BmpName;
- UINT8 *FullCapsuleBuffer;
- UINTN FullCapsuleBufferSize;
- EFI_DISPLAY_CAPSULE *DisplayCapsule;
- EFI_STATUS Status;
- EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
- EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt;
- UINTN GopBltSize;
- UINTN Height;
- UINTN Width;
-
- Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: NO GOP is found.\n");
- return EFI_UNSUPPORTED;
- }
-
- Info = Gop->Mode->Info;
- Print (L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
- Print (L"HorizontalResolution - %d, ", Info->HorizontalResolution);
- Print (L"VerticalResolution - %d\n", Info->VerticalResolution);
- // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
- // VerticalResolution >= BMP_IMAGE_HEADER.PixelHeight
-
- if (Argc != 5) {
- Print (L"CapsuleApp: Incorrect parameter count.\n");
- return EFI_UNSUPPORTED;
- }
-
- if (StrCmp (Argv[3], L"-O") != 0) {
- Print (L"CapsuleApp: NO output capsule name.\n");
- return EFI_UNSUPPORTED;
- }
-
- OutputCapsuleName = Argv[4];
-
- BmpBuffer = NULL;
- FileSize = 0;
- FullCapsuleBuffer = NULL;
-
- BmpName = Argv[2];
- Status = ReadFileToBuffer (BmpName, &FileSize, &BmpBuffer);
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
- goto Done;
- }
-
- GopBlt = NULL;
- Status = TranslateBmpToGopBlt (
- BmpBuffer,
- FileSize,
- &GopBlt,
- &GopBltSize,
- &Height,
- &Width
- );
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: BMP image (%s) is not valid.\n", BmpName);
- goto Done;
- }
-
- if (GopBlt != NULL) {
- FreePool (GopBlt);
- }
-
- Print (L"BMP image (%s), Width - %d, Height - %d\n", BmpName, Width, Height);
-
- if (Height > Info->VerticalResolution) {
- Status = EFI_INVALID_PARAMETER;
- Print (L"CapsuleApp: BMP image (%s) height is larger than current resolution.\n", BmpName);
- goto Done;
- }
-
- if (Width > Info->HorizontalResolution) {
- Status = EFI_INVALID_PARAMETER;
- Print (L"CapsuleApp: BMP image (%s) width is larger than current resolution.\n", BmpName);
- goto Done;
- }
-
- FullCapsuleBufferSize = sizeof (EFI_DISPLAY_CAPSULE) + FileSize;
- FullCapsuleBuffer = AllocatePool (FullCapsuleBufferSize);
- if (FullCapsuleBuffer == NULL) {
- Print (L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
- CopyGuid (&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
- DisplayCapsule->CapsuleHeader.HeaderSize = sizeof (DisplayCapsule->CapsuleHeader);
- DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
- DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
-
- DisplayCapsule->ImagePayload.Version = 1;
- DisplayCapsule->ImagePayload.Checksum = 0;
- DisplayCapsule->ImagePayload.ImageType = 0; // BMP
- DisplayCapsule->ImagePayload.Reserved = 0;
- DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
-
- //
- // Center the bitmap horizontally
- //
- DisplayCapsule->ImagePayload.OffsetX = (UINT32)((Info->HorizontalResolution - Width) / 2);
-
- //
- // Put bitmap 3/4 down the display. If bitmap is too tall, then align bottom
- // of bitmap at bottom of display.
- //
- DisplayCapsule->ImagePayload.OffsetY =
- MIN (
- (UINT32)(Info->VerticalResolution - Height),
- (UINT32)(((3 * Info->VerticalResolution) - (2 * Height)) / 4)
- );
-
- Print (
- L"BMP image (%s), OffsetX - %d, OffsetY - %d\n",
- BmpName,
- DisplayCapsule->ImagePayload.OffsetX,
- DisplayCapsule->ImagePayload.OffsetY
- );
-
- CopyMem ((DisplayCapsule + 1), BmpBuffer, FileSize);
-
- DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8 (FullCapsuleBuffer, FullCapsuleBufferSize);
-
- Status = WriteFileFromBuffer (OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
- Print (L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
-
-Done:
- if (BmpBuffer != NULL) {
- FreePool (BmpBuffer);
- }
-
- if (FullCapsuleBuffer != NULL) {
- FreePool (FullCapsuleBuffer);
- }
-
- return Status;
-}
-
-/**
- Get ImageTypeId in the FMP capsule header.
-
- @param[in] CapsuleHeader The FMP capsule image header.
-
- @return ImageTypeId
-**/
-EFI_GUID *
-GetCapsuleImageTypeId (
- IN EFI_CAPSULE_HEADER *CapsuleHeader
- )
-{
- EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
- UINT64 *ItemOffsetList;
- EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
-
- FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
- ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
- if (FmpCapsuleHeader->PayloadItemCount == 0) {
- return NULL;
- }
-
- ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
- return &ImageHeader->UpdateImageTypeId;
-}
-
-/**
- Get ESRT FwType according to ImageTypeId
-
- @param[in] ImageTypeId ImageTypeId of an FMP capsule.
-
- @return ESRT FwType
-**/
-UINT32
-GetEsrtFwType (
- IN EFI_GUID *ImageTypeId
- )
-{
- EFI_STATUS Status;
- EFI_SYSTEM_RESOURCE_TABLE *Esrt;
- EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
- UINTN Index;
-
- //
- // Check ESRT
- //
- Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
- if (!EFI_ERROR (Status)) {
- ASSERT (Esrt != NULL);
- EsrtEntry = (VOID *)(Esrt + 1);
- for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
- if (CompareGuid (&EsrtEntry->FwClass, ImageTypeId)) {
- return EsrtEntry->FwType;
- }
- }
- }
-
- return ESRT_FW_TYPE_UNKNOWN;
-}
-
-/**
- Validate if it is valid capsule header
-
- This function assumes the caller provided correct CapsuleHeader pointer
- and CapsuleSize.
-
- This function validates the fields in EFI_CAPSULE_HEADER.
-
- @param[in] CapsuleHeader Points to a capsule header.
- @param[in] CapsuleSize Size of the whole capsule image.
-
-**/
-BOOLEAN
-IsValidCapsuleHeader (
- IN EFI_CAPSULE_HEADER *CapsuleHeader,
- IN UINT64 CapsuleSize
- )
-{
- if (CapsuleSize < sizeof (EFI_CAPSULE_HEADER)) {
- return FALSE;
- }
-
- if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
- return FALSE;
- }
-
- if (CapsuleHeader->HeaderSize > CapsuleHeader->CapsuleImageSize) {
- return FALSE;
- }
-
- if (CapsuleHeader->HeaderSize < sizeof (EFI_CAPSULE_HEADER)) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- Return if this CapsuleGuid is a FMP capsule GUID or not.
-
- @param[in] CapsuleGuid A pointer to EFI_GUID
-
- @retval TRUE It is a FMP capsule GUID.
- @retval FALSE It is not a FMP capsule GUID.
-**/
-BOOLEAN
-IsFmpCapsuleGuid (
- IN EFI_GUID *CapsuleGuid
- )
-{
- if (CompareGuid (&gEfiFmpCapsuleGuid, CapsuleGuid)) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Append a capsule header on top of current image.
- This function follows Windows UEFI Firmware Update Platform document.
-
- @retval EFI_SUCCESS The capsule header is appended.
- @retval EFI_UNSUPPORTED Input parameter is not valid.
- @retval EFI_OUT_OF_RESOURCES No enough resource to append capsule header.
-**/
-EFI_STATUS
-CreateNestedFmp (
- VOID
- )
-{
- CHAR16 *OutputCapsuleName;
- VOID *CapsuleBuffer;
- UINTN FileSize;
- CHAR16 *CapsuleName;
- UINT8 *FullCapsuleBuffer;
- UINTN FullCapsuleBufferSize;
- EFI_CAPSULE_HEADER *NestedCapsuleHeader;
- EFI_GUID *ImageTypeId;
- UINT32 FwType;
- EFI_STATUS Status;
-
- if (Argc != 5) {
- Print (L"CapsuleApp: Incorrect parameter count.\n");
- return EFI_UNSUPPORTED;
- }
-
- if (StrCmp (Argv[3], L"-O") != 0) {
- Print (L"CapsuleApp: NO output capsule name.\n");
- return EFI_UNSUPPORTED;
- }
-
- OutputCapsuleName = Argv[4];
-
- CapsuleBuffer = NULL;
- FileSize = 0;
- FullCapsuleBuffer = NULL;
-
- CapsuleName = Argv[2];
- Status = ReadFileToBuffer (CapsuleName, &FileSize, &CapsuleBuffer);
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
- goto Done;
- }
-
- if (!IsValidCapsuleHeader (CapsuleBuffer, FileSize)) {
- Print (L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- if (!IsFmpCapsuleGuid (&((EFI_CAPSULE_HEADER *)CapsuleBuffer)->CapsuleGuid)) {
- Print (L"CapsuleApp: Capsule image (%s) is not a FMP capsule.\n", CapsuleName);
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- ImageTypeId = GetCapsuleImageTypeId (CapsuleBuffer);
- if (ImageTypeId == NULL) {
- Print (L"CapsuleApp: Capsule ImageTypeId is not found.\n");
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- FwType = GetEsrtFwType (ImageTypeId);
- if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType != ESRT_FW_TYPE_DEVICEFIRMWARE)) {
- Print (L"CapsuleApp: Capsule FwType is invalid.\n");
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
- FullCapsuleBuffer = AllocatePool (FullCapsuleBufferSize);
- if (FullCapsuleBuffer == NULL) {
- Print (L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
- ZeroMem (NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
- CopyGuid (&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
- NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
- NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_SYSTEMFIRMWARE) ? SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
- NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
-
- CopyMem ((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize, CapsuleBuffer, FileSize);
-
- Status = WriteFileFromBuffer (OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
- Print (L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
-
-Done:
- if (CapsuleBuffer != NULL) {
- FreePool (CapsuleBuffer);
- }
-
- if (FullCapsuleBuffer != NULL) {
- FreePool (FullCapsuleBuffer);
- }
-
- return Status;
-}
-
-/**
- Clear capsule status variable.
-
- @retval EFI_SUCCESS The capsule status variable is cleared.
-**/
-EFI_STATUS
-ClearCapsuleStatusVariable (
- VOID
- )
-{
- EFI_STATUS Status;
- UINT32 Index;
- CHAR16 CapsuleVarName[20];
- CHAR16 *TempVarName;
- BOOLEAN Found;
-
- StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CapsuleVarName[0]), L"Capsule");
- TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
- Index = 0;
-
- Found = FALSE;
- while (TRUE) {
- UnicodeSPrint (TempVarName, 5 * sizeof (CHAR16), L"%04x", Index);
-
- Status = gRT->SetVariable (
- CapsuleVarName,
- &gEfiCapsuleReportGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
- 0,
- (VOID *)NULL
- );
- if (Status == EFI_NOT_FOUND) {
- //
- // There is no more capsule variables, quit
- //
- break;
- }
-
- Found = TRUE;
-
- Print (L"Clear %s %r\n", CapsuleVarName, Status);
-
- Index++;
- if (Index > 0xFFFF) {
- break;
- }
- }
-
- if (!Found) {
- Print (L"No any Capsule#### variable found\n");
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Build Gather list for a list of capsule images.
-
- @param[in] CapsuleBuffer An array of pointer to capsule images
- @param[in] FileSize An array of UINTN to capsule images size
- @param[in] CapsuleNum The count of capsule images
- @param[out] BlockDescriptors The block descriptors for the capsule images
-
- @retval EFI_SUCCESS The block descriptors for the capsule images are constructed.
-**/
-EFI_STATUS
-BuildGatherList (
- IN VOID **CapsuleBuffer,
- IN UINTN *FileSize,
- IN UINTN CapsuleNum,
- OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
- )
-{
- EFI_STATUS Status;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors1;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors2;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorPre;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorsHeader;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr;
- UINT8 *TempDataPtr;
- UINTN SizeLeft;
- UINTN Size;
- INT32 Count;
- INT32 Number;
- UINTN Index;
-
- TempBlockPtr = NULL;
- BlockDescriptors1 = NULL;
- BlockDescriptors2 = NULL;
- BlockDescriptorPre = NULL;
- BlockDescriptorsHeader = NULL;
-
- for (Index = 0; Index < CapsuleNum; Index++) {
- //
- // Allocate memory for the descriptors.
- //
- if (NumberOfDescriptors == 1) {
- Count = 2;
- } else {
- Count = (INT32)(NumberOfDescriptors + 2) / 2;
- }
-
- Size = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
- BlockDescriptors1 = AllocateRuntimeZeroPool (Size);
- if (BlockDescriptors1 == NULL) {
- Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
- Status = EFI_OUT_OF_RESOURCES;
- goto ERREXIT;
- } else {
- Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)BlockDescriptors1);
- Print (L"CapsuleApp: capsule data starts at 0x%X with size 0x%X\n", (UINTN)CapsuleBuffer[Index], FileSize[Index]);
- }
-
- //
- // Record descriptor header
- //
- if (Index == 0) {
- BlockDescriptorsHeader = BlockDescriptors1;
- }
-
- if (BlockDescriptorPre != NULL) {
- BlockDescriptorPre->Union.ContinuationPointer = (UINTN)BlockDescriptors1;
- BlockDescriptorPre->Length = 0;
- }
-
- //
- // Fill them in
- //
- TempBlockPtr = BlockDescriptors1;
- TempDataPtr = CapsuleBuffer[Index];
- SizeLeft = FileSize[Index];
- for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
- //
- // Divide remaining data in half
- //
- if (NumberOfDescriptors != 1) {
- if (SizeLeft == 1) {
- Size = 1;
- } else {
- Size = SizeLeft / 2;
- }
- } else {
- Size = SizeLeft;
- }
-
- TempBlockPtr->Union.DataBlock = (UINTN)TempDataPtr;
- TempBlockPtr->Length = Size;
- Print (L"CapsuleApp: capsule block/size 0x%X/0x%X\n", (UINTN)TempDataPtr, Size);
- SizeLeft -= Size;
- TempDataPtr += Size;
- TempBlockPtr++;
- }
-
- //
- // Allocate the second list, point the first block's last entry to point
- // to this one, and fill this one in. Worst case is that the previous
- // list only had one element that pointed here, so we need at least two
- // elements -- one to point to all the data, another to terminate the list.
- //
- if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
- Count = (INT32)(NumberOfDescriptors + 2) - Count;
- if (Count == 1) {
- Count++;
- }
-
- Size = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
- BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
- if (BlockDescriptors2 == NULL) {
- Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
- Status = EFI_OUT_OF_RESOURCES;
- goto ERREXIT;
- }
-
- //
- // Point the first list's last element to point to this second list.
- //
- TempBlockPtr->Union.ContinuationPointer = (UINTN)BlockDescriptors2;
-
- TempBlockPtr->Length = 0;
- TempBlockPtr = BlockDescriptors2;
- for (Number = 0; Number < Count - 1; Number++) {
- //
- // If second-to-last one, then dump rest to this element
- //
- if (Number == (Count - 2)) {
- Size = SizeLeft;
- } else {
- //
- // Divide remaining data in half
- //
- if (SizeLeft == 1) {
- Size = 1;
- } else {
- Size = SizeLeft / 2;
- }
- }
-
- TempBlockPtr->Union.DataBlock = (UINTN)TempDataPtr;
- TempBlockPtr->Length = Size;
- Print (L"CapsuleApp: capsule block/size 0x%X/0x%X\n", (UINTN)TempDataPtr, Size);
- SizeLeft -= Size;
- TempDataPtr += Size;
- TempBlockPtr++;
- if (SizeLeft == 0) {
- break;
- }
- }
- }
-
- BlockDescriptorPre = TempBlockPtr;
- BlockDescriptors1 = NULL;
- }
-
- //
- // Null-terminate.
- //
- if (TempBlockPtr != NULL) {
- TempBlockPtr->Union.ContinuationPointer = (UINTN)NULL;
- TempBlockPtr->Length = 0;
- *BlockDescriptors = BlockDescriptorsHeader;
- }
-
- return EFI_SUCCESS;
-
-ERREXIT:
- if (BlockDescriptors1 != NULL) {
- FreePool (BlockDescriptors1);
- }
-
- if (BlockDescriptors2 != NULL) {
- FreePool (BlockDescriptors2);
- }
-
- return Status;
-}
-
-/**
- Clear the Gather list for a list of capsule images.
-
- @param[in] BlockDescriptors The block descriptors for the capsule images
- @param[in] CapsuleNum The count of capsule images
-**/
-VOID
-CleanGatherList (
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors,
- IN UINTN CapsuleNum
- )
-{
- EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr1;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr2;
- UINTN Index;
-
- if (BlockDescriptors != NULL) {
- TempBlockPtr1 = BlockDescriptors;
- while (1) {
- TempBlockPtr = TempBlockPtr1;
- for (Index = 0; Index < CapsuleNum; Index++) {
- if (TempBlockPtr[Index].Length == 0) {
- break;
- }
- }
-
- if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
- break;
- }
-
- TempBlockPtr2 = (VOID *)((UINTN)TempBlockPtr[Index].Union.ContinuationPointer);
- FreePool (TempBlockPtr1);
- TempBlockPtr1 = TempBlockPtr2;
- }
- }
-}
-
-/**
- Print APP usage.
-**/
-VOID
-PrintUsage (
- VOID
- )
-{
- Print (L"CapsuleApp: usage\n");
- Print (L" CapsuleApp <Capsule...> [-NR] [-OD [FSx]]\n");
- Print (L" CapsuleApp -S\n");
- Print (L" CapsuleApp -C\n");
- Print (L" CapsuleApp -P\n");
- Print (L" CapsuleApp -E\n");
- Print (L" CapsuleApp -L\n");
- Print (L" CapsuleApp -L INFO\n");
- Print (L" CapsuleApp -F\n");
- Print (L" CapsuleApp -G <BMP> -O <Capsule>\n");
- Print (L" CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
- Print (L" CapsuleApp -D <Capsule>\n");
- Print (L" CapsuleApp -P GET <ImageTypeId> <Index> -O <FileName>\n");
- Print (L"Parameter:\n");
- Print (L" -NR: No reset will be triggered for the capsule\n");
- Print (L" with CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without CAPSULE_FLAGS_INITIATE_RESET.\n");
- Print (L" -OD: Delivery of Capsules via file on Mass Storage device.\n");
- Print (L" -S: Dump capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
- Print (L" which is defined in UEFI specification.\n");
- Print (L" -C: Clear capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
- Print (L" which is defined in UEFI specification.\n");
- Print (L" -P: Dump UEFI FMP protocol info, or get image with specified\n");
- Print (L" ImageTypeId and Index (decimal format) to a file if 'GET'\n");
- Print (L" option is used.\n");
- Print (L" -E: Dump UEFI ESRT table info.\n");
- Print (L" -L: Dump provisioned capsule image information.\n");
- Print (L" -F: Dump all EFI System Partition.\n");
- Print (L" -G: Convert a BMP file to be an UX capsule,\n");
- Print (L" according to Windows Firmware Update document\n");
- Print (L" -N: Append a Capsule Header to an existing FMP capsule image\n");
- Print (L" with its ImageTypeId supported by the system,\n");
- Print (L" according to Windows Firmware Update document\n");
- Print (L" -O: Output new Capsule file name\n");
- Print (L" -D: Dump Capsule image header information, image payload\n");
- Print (L" information if it is an UX capsule and FMP header\n");
- Print (L" information if it is a FMP capsule.\n");
-}
-
-/**
- Update Capsule image.
-
- @param[in] ImageHandle The image handle.
- @param[in] SystemTable The system table.
-
- @retval EFI_SUCCESS Command completed successfully.
- @retval EFI_UNSUPPORTED Command usage unsupported.
- @retval EFI_INVALID_PARAMETER Command usage invalid.
- @retval EFI_NOT_FOUND The input file can't be found.
-**/
-EFI_STATUS
-EFIAPI
-UefiMain (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- RETURN_STATUS RStatus;
- UINTN CapsuleBufferSize[MAX_CAPSULE_NUM];
- VOID *CapsuleBuffer[MAX_CAPSULE_NUM];
- EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors;
- EFI_CAPSULE_HEADER *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
- UINT64 MaxCapsuleSize;
- EFI_RESET_TYPE ResetType;
- BOOLEAN NeedReset;
- BOOLEAN NoReset;
- BOOLEAN CapsuleOnDisk;
- CHAR16 *CapsuleName;
- CHAR16 *CapsuleNames[MAX_CAPSULE_NUM];
- CHAR16 *MapFsStr;
- UINTN CapsuleNum;
- UINTN Index;
- UINTN ParaOdIndex;
- UINTN ParaNrIndex;
- EFI_GUID ImageTypeId;
- UINTN ImageIndex;
-
- BlockDescriptors = NULL;
- MapFsStr = NULL;
- CapsuleNum = 0;
-
- Status = GetArg ();
- if (EFI_ERROR (Status)) {
- Print (L"Please use UEFI SHELL to run this application!\n", Status);
- return Status;
- }
-
- if (Argc < 2) {
- PrintUsage ();
- return EFI_UNSUPPORTED;
- }
-
- if (StrCmp (Argv[1], L"-D") == 0) {
- if (Argc != 3) {
- Print (L"CapsuleApp: Incorrect parameter count.\n");
- return EFI_UNSUPPORTED;
- }
-
- Status = DumpCapsule (Argv[2]);
- return Status;
- }
-
- if (StrCmp (Argv[1], L"-G") == 0) {
- Status = CreateBmpFmp ();
- return Status;
- }
-
- if (StrCmp (Argv[1], L"-N") == 0) {
- Status = CreateNestedFmp ();
- return Status;
- }
-
- if (StrCmp (Argv[1], L"-S") == 0) {
- Status = DumpCapsuleStatusVariable ();
- return EFI_SUCCESS;
- }
-
- if (StrCmp (Argv[1], L"-C") == 0) {
- Status = ClearCapsuleStatusVariable ();
- return Status;
- }
-
- if (StrCmp (Argv[1], L"-P") == 0) {
- if (Argc == 2) {
- DumpFmpData ();
- }
-
- if (Argc >= 3) {
- if (StrCmp (Argv[2], L"GET") != 0) {
- Print (L"CapsuleApp: Unrecognized option(%s).\n", Argv[2]);
- return EFI_UNSUPPORTED;
- } else {
- if (Argc != 7) {
- Print (L"CapsuleApp: Incorrect parameter count.\n");
- return EFI_UNSUPPORTED;
- }
-
- //
- // FMP->GetImage()
- //
- RStatus = StrToGuid (Argv[3], &ImageTypeId);
- if (RETURN_ERROR (RStatus) || (Argv[3][GUID_STRING_LENGTH] != L'\0')) {
- Print (L"Invalid ImageTypeId - %s\n", Argv[3]);
- return EFI_INVALID_PARAMETER;
- }
-
- ImageIndex = StrDecimalToUintn (Argv[4]);
- if (StrCmp (Argv[5], L"-O") != 0) {
- Print (L"CapsuleApp: NO output file name.\n");
- return EFI_UNSUPPORTED;
- }
-
- DumpFmpImage (&ImageTypeId, ImageIndex, Argv[6]);
- }
- }
-
- return EFI_SUCCESS;
- }
-
- if (StrCmp (Argv[1], L"-E") == 0) {
- DumpEsrtData ();
- return EFI_SUCCESS;
- }
-
- if (StrCmp (Argv[1], L"-L") == 0) {
- if ((Argc >= 3) && (StrCmp (Argv[2], L"INFO") == 0)) {
- DumpProvisionedCapsule (TRUE);
- } else {
- DumpProvisionedCapsule (FALSE);
- }
-
- return EFI_SUCCESS;
- }
-
- if (StrCmp (Argv[1], L"-F") == 0) {
- DumpAllEfiSysPartition ();
- return EFI_SUCCESS;
- }
-
- if (Argv[1][0] == L'-') {
- Print (L"CapsuleApp: Unrecognized option(%s).\n", Argv[1]);
- return EFI_UNSUPPORTED;
- }
-
- CapsuleFirstIndex = 1;
- NoReset = FALSE;
- CapsuleOnDisk = FALSE;
- ParaOdIndex = 0;
- ParaNrIndex = 0;
-
- for (Index = 1; Index < Argc; Index++) {
- if (StrCmp (Argv[Index], L"-OD") == 0) {
- ParaOdIndex = Index;
- CapsuleOnDisk = TRUE;
- } else if (StrCmp (Argv[Index], L"-NR") == 0) {
- ParaNrIndex = Index;
- NoReset = TRUE;
- }
- }
-
- if (ParaOdIndex > ParaNrIndex) {
- if (ParaNrIndex != 0) {
- CapsuleLastIndex = ParaNrIndex - 1;
- } else {
- CapsuleLastIndex = ParaOdIndex - 1;
- }
-
- if (ParaOdIndex == Argc -1) {
- MapFsStr = NULL;
- } else if (ParaOdIndex == Argc - 2) {
- MapFsStr = Argv[Argc-1];
- } else {
- Print (L"CapsuleApp: Cannot specify more than one FS mapping!\n");
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- } else if (ParaOdIndex < ParaNrIndex) {
- if (ParaOdIndex != 0) {
- CapsuleLastIndex = ParaOdIndex - 1;
- if (ParaOdIndex == ParaNrIndex - 1) {
- MapFsStr = NULL;
- } else if (ParaOdIndex == ParaNrIndex - 2) {
- MapFsStr = Argv[ParaOdIndex + 1];
- } else {
- Print (L"CapsuleApp: Cannot specify more than one FS mapping!\n");
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- } else {
- CapsuleLastIndex = ParaNrIndex - 1;
- }
- } else {
- CapsuleLastIndex = Argc - 1;
- }
-
- CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
-
- if (CapsuleFirstIndex > CapsuleLastIndex) {
- Print (L"CapsuleApp: NO capsule image.\n");
- return EFI_UNSUPPORTED;
- }
-
- if (CapsuleNum > MAX_CAPSULE_NUM) {
- Print (L"CapsuleApp: Too many capsule images.\n");
- return EFI_UNSUPPORTED;
- }
-
- ZeroMem (&CapsuleBuffer, sizeof (CapsuleBuffer));
- ZeroMem (&CapsuleBufferSize, sizeof (CapsuleBufferSize));
- BlockDescriptors = NULL;
-
- for (Index = 0; Index < CapsuleNum; Index++) {
- CapsuleName = Argv[CapsuleFirstIndex + Index];
- Status = ReadFileToBuffer (CapsuleName, &CapsuleBufferSize[Index], &CapsuleBuffer[Index]);
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
- goto Done;
- }
-
- if (!IsValidCapsuleHeader (CapsuleBuffer[Index], CapsuleBufferSize[Index])) {
- Print (L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
- return EFI_INVALID_PARAMETER;
- }
-
- CapsuleNames[Index] = CapsuleName;
- }
-
- //
- // Every capsule use 2 descriptor 1 for data 1 for end
- //
- Status = BuildGatherList (CapsuleBuffer, CapsuleBufferSize, CapsuleNum, &BlockDescriptors);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // Call the runtime service capsule.
- //
- NeedReset = FALSE;
- for (Index = 0; Index < CapsuleNum; Index++) {
- CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *)CapsuleBuffer[Index];
- if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
- NeedReset = TRUE;
- }
- }
-
- CapsuleHeaderArray[CapsuleNum] = NULL;
-
- //
- // Inquire platform capability of UpdateCapsule.
- //
- Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum, &MaxCapsuleSize, &ResetType);
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
- goto Done;
- }
-
- for (Index = 0; Index < CapsuleNum; Index++) {
- if (CapsuleBufferSize[Index] > MaxCapsuleSize) {
- Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n", MaxCapsuleSize);
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
- }
-
- //
- // Check whether is capsule on disk.
- //
- if (CapsuleOnDisk) {
- Status = ProcessCapsuleOnDisk (CapsuleBuffer, CapsuleBufferSize, CapsuleNames, MapFsStr, CapsuleNum);
- if (Status != EFI_SUCCESS) {
- Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
- goto Done;
- } else {
- if (!NoReset) {
- gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
- } else {
- goto Done;
- }
- }
- }
-
- //
- // Check whether the input capsule image has the flag of persist across system reset.
- //
- if (NeedReset) {
- Status = gRT->UpdateCapsule (CapsuleHeaderArray, CapsuleNum, (UINTN)BlockDescriptors);
- if (Status != EFI_SUCCESS) {
- Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
- goto Done;
- }
-
- //
- // For capsule with CAPSULE_FLAGS_PERSIST_ACROSS_RESET + CAPSULE_FLAGS_INITIATE_RESET,
- // a system reset should have been triggered by gRT->UpdateCapsule() calling above.
- //
- // For capsule with CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without CAPSULE_FLAGS_INITIATE_RESET,
- // check if -NR (no-reset) has been specified or not.
- //
- if (!NoReset) {
- //
- // For capsule who has reset flag and no -NR (no-reset) has been specified, after calling UpdateCapsule service,
- // trigger a system reset to process capsule persist across a system reset.
- //
- gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
- }
- } else {
- //
- // For capsule who has no reset flag, only call UpdateCapsule Service without a
- // system reset. The service will process the capsule immediately.
- //
- Status = gRT->UpdateCapsule (CapsuleHeaderArray, CapsuleNum, (UINTN)BlockDescriptors);
- if (Status != EFI_SUCCESS) {
- Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
- }
- }
-
- Status = EFI_SUCCESS;
-
-Done:
- for (Index = 0; Index < CapsuleNum; Index++) {
- if (CapsuleBuffer[Index] != NULL) {
- FreePool (CapsuleBuffer[Index]);
- }
- }
-
- CleanGatherList (BlockDescriptors, CapsuleNum);
-
- return Status;
-}
+/** @file
+ A shell application that triggers capsule update process.
+
+ Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CapsuleApp.h"
+
+//
+// Define how many block descriptors we want to test with.
+//
+UINTN NumberOfDescriptors = 1;
+UINTN CapsuleFirstIndex;
+UINTN CapsuleLastIndex;
+
+/**
+ Create UX capsule.
+
+ @retval EFI_SUCCESS The capsule header is appended.
+ @retval EFI_UNSUPPORTED Input parameter is not valid.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to create UX capsule.
+**/
+EFI_STATUS
+CreateBmpFmp (
+ VOID
+ )
+{
+ CHAR16 *OutputCapsuleName;
+ VOID *BmpBuffer;
+ UINTN FileSize;
+ CHAR16 *BmpName;
+ UINT8 *FullCapsuleBuffer;
+ UINTN FullCapsuleBufferSize;
+ EFI_DISPLAY_CAPSULE *DisplayCapsule;
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt;
+ UINTN GopBltSize;
+ UINTN Height;
+ UINTN Width;
+
+ Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: NO GOP is found.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ Info = Gop->Mode->Info;
+ Print (L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
+ Print (L"HorizontalResolution - %d, ", Info->HorizontalResolution);
+ Print (L"VerticalResolution - %d\n", Info->VerticalResolution);
+ // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
+ // VerticalResolution >= BMP_IMAGE_HEADER.PixelHeight
+
+ if (Argc != 5) {
+ Print (L"CapsuleApp: Incorrect parameter count.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ if (StrCmp (Argv[3], L"-O") != 0) {
+ Print (L"CapsuleApp: NO output capsule name.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ OutputCapsuleName = Argv[4];
+
+ BmpBuffer = NULL;
+ FileSize = 0;
+ FullCapsuleBuffer = NULL;
+
+ BmpName = Argv[2];
+ Status = ReadFileToBuffer (BmpName, &FileSize, &BmpBuffer);
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
+ goto Done;
+ }
+
+ GopBlt = NULL;
+ Status = TranslateBmpToGopBlt (
+ BmpBuffer,
+ FileSize,
+ &GopBlt,
+ &GopBltSize,
+ &Height,
+ &Width
+ );
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: BMP image (%s) is not valid.\n", BmpName);
+ goto Done;
+ }
+
+ if (GopBlt != NULL) {
+ FreePool (GopBlt);
+ }
+
+ Print (L"BMP image (%s), Width - %d, Height - %d\n", BmpName, Width, Height);
+
+ if (Height > Info->VerticalResolution) {
+ Status = EFI_INVALID_PARAMETER;
+ Print (L"CapsuleApp: BMP image (%s) height is larger than current resolution.\n", BmpName);
+ goto Done;
+ }
+
+ if (Width > Info->HorizontalResolution) {
+ Status = EFI_INVALID_PARAMETER;
+ Print (L"CapsuleApp: BMP image (%s) width is larger than current resolution.\n", BmpName);
+ goto Done;
+ }
+
+ FullCapsuleBufferSize = sizeof (EFI_DISPLAY_CAPSULE) + FileSize;
+ FullCapsuleBuffer = AllocatePool (FullCapsuleBufferSize);
+ if (FullCapsuleBuffer == NULL) {
+ Print (L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
+ CopyGuid (&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
+ DisplayCapsule->CapsuleHeader.HeaderSize = sizeof (DisplayCapsule->CapsuleHeader);
+ DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
+ DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
+
+ DisplayCapsule->ImagePayload.Version = 1;
+ DisplayCapsule->ImagePayload.Checksum = 0;
+ DisplayCapsule->ImagePayload.ImageType = 0; // BMP
+ DisplayCapsule->ImagePayload.Reserved = 0;
+ DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
+
+ //
+ // Center the bitmap horizontally
+ //
+ DisplayCapsule->ImagePayload.OffsetX = (UINT32)((Info->HorizontalResolution - Width) / 2);
+
+ //
+ // Put bitmap 3/4 down the display. If bitmap is too tall, then align bottom
+ // of bitmap at bottom of display.
+ //
+ DisplayCapsule->ImagePayload.OffsetY =
+ MIN (
+ (UINT32)(Info->VerticalResolution - Height),
+ (UINT32)(((3 * Info->VerticalResolution) - (2 * Height)) / 4)
+ );
+
+ Print (
+ L"BMP image (%s), OffsetX - %d, OffsetY - %d\n",
+ BmpName,
+ DisplayCapsule->ImagePayload.OffsetX,
+ DisplayCapsule->ImagePayload.OffsetY
+ );
+
+ CopyMem ((DisplayCapsule + 1), BmpBuffer, FileSize);
+
+ DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8 (FullCapsuleBuffer, FullCapsuleBufferSize);
+
+ Status = WriteFileFromBuffer (OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
+ Print (L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
+
+Done:
+ if (BmpBuffer != NULL) {
+ FreePool (BmpBuffer);
+ }
+
+ if (FullCapsuleBuffer != NULL) {
+ FreePool (FullCapsuleBuffer);
+ }
+
+ return Status;
+}
+
+/**
+ Get ImageTypeId in the FMP capsule header.
+
+ @param[in] CapsuleHeader The FMP capsule image header.
+
+ @return ImageTypeId
+**/
+EFI_GUID *
+GetCapsuleImageTypeId (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ UINT64 *ItemOffsetList;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+ if (FmpCapsuleHeader->PayloadItemCount == 0) {
+ return NULL;
+ }
+
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
+ return &ImageHeader->UpdateImageTypeId;
+}
+
+/**
+ Get ESRT FwType according to ImageTypeId
+
+ @param[in] ImageTypeId ImageTypeId of an FMP capsule.
+
+ @return ESRT FwType
+**/
+UINT32
+GetEsrtFwType (
+ IN EFI_GUID *ImageTypeId
+ )
+{
+ EFI_STATUS Status;
+ EFI_SYSTEM_RESOURCE_TABLE *Esrt;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
+ UINTN Index;
+
+ //
+ // Check ESRT
+ //
+ Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
+ if (!EFI_ERROR (Status)) {
+ ASSERT (Esrt != NULL);
+ EsrtEntry = (VOID *)(Esrt + 1);
+ for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
+ if (CompareGuid (&EsrtEntry->FwClass, ImageTypeId)) {
+ return EsrtEntry->FwType;
+ }
+ }
+ }
+
+ return ESRT_FW_TYPE_UNKNOWN;
+}
+
+/**
+ Validate if it is valid capsule header
+
+ This function assumes the caller provided correct CapsuleHeader pointer
+ and CapsuleSize.
+
+ This function validates the fields in EFI_CAPSULE_HEADER.
+
+ @param[in] CapsuleHeader Points to a capsule header.
+ @param[in] CapsuleSize Size of the whole capsule image.
+
+**/
+BOOLEAN
+IsValidCapsuleHeader (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN UINT64 CapsuleSize
+ )
+{
+ if (CapsuleSize < sizeof (EFI_CAPSULE_HEADER)) {
+ return FALSE;
+ }
+
+ if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
+ return FALSE;
+ }
+
+ if (CapsuleHeader->HeaderSize > CapsuleHeader->CapsuleImageSize) {
+ return FALSE;
+ }
+
+ if (CapsuleHeader->HeaderSize < sizeof (EFI_CAPSULE_HEADER)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Return if this CapsuleGuid is a FMP capsule GUID or not.
+
+ @param[in] CapsuleGuid A pointer to EFI_GUID
+
+ @retval TRUE It is a FMP capsule GUID.
+ @retval FALSE It is not a FMP capsule GUID.
+**/
+BOOLEAN
+IsFmpCapsuleGuid (
+ IN EFI_GUID *CapsuleGuid
+ )
+{
+ if (CompareGuid (&gEfiFmpCapsuleGuid, CapsuleGuid)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Append a capsule header on top of current image.
+ This function follows Windows UEFI Firmware Update Platform document.
+
+ @retval EFI_SUCCESS The capsule header is appended.
+ @retval EFI_UNSUPPORTED Input parameter is not valid.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to append capsule header.
+**/
+EFI_STATUS
+CreateNestedFmp (
+ VOID
+ )
+{
+ CHAR16 *OutputCapsuleName;
+ VOID *CapsuleBuffer;
+ UINTN FileSize;
+ CHAR16 *CapsuleName;
+ UINT8 *FullCapsuleBuffer;
+ UINTN FullCapsuleBufferSize;
+ EFI_CAPSULE_HEADER *NestedCapsuleHeader;
+ EFI_GUID *ImageTypeId;
+ UINT32 FwType;
+ EFI_STATUS Status;
+
+ if (Argc != 5) {
+ Print (L"CapsuleApp: Incorrect parameter count.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ if (StrCmp (Argv[3], L"-O") != 0) {
+ Print (L"CapsuleApp: NO output capsule name.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ OutputCapsuleName = Argv[4];
+
+ CapsuleBuffer = NULL;
+ FileSize = 0;
+ FullCapsuleBuffer = NULL;
+
+ CapsuleName = Argv[2];
+ Status = ReadFileToBuffer (CapsuleName, &FileSize, &CapsuleBuffer);
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
+ goto Done;
+ }
+
+ if (!IsValidCapsuleHeader (CapsuleBuffer, FileSize)) {
+ Print (L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (!IsFmpCapsuleGuid (&((EFI_CAPSULE_HEADER *)CapsuleBuffer)->CapsuleGuid)) {
+ Print (L"CapsuleApp: Capsule image (%s) is not a FMP capsule.\n", CapsuleName);
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ ImageTypeId = GetCapsuleImageTypeId (CapsuleBuffer);
+ if (ImageTypeId == NULL) {
+ Print (L"CapsuleApp: Capsule ImageTypeId is not found.\n");
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ FwType = GetEsrtFwType (ImageTypeId);
+ if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType != ESRT_FW_TYPE_DEVICEFIRMWARE)) {
+ Print (L"CapsuleApp: Capsule FwType is invalid.\n");
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
+ FullCapsuleBuffer = AllocatePool (FullCapsuleBufferSize);
+ if (FullCapsuleBuffer == NULL) {
+ Print (L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
+ ZeroMem (NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
+ CopyGuid (&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
+ NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
+ NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_SYSTEMFIRMWARE) ? SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
+ NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
+
+ CopyMem ((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize, CapsuleBuffer, FileSize);
+
+ Status = WriteFileFromBuffer (OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
+ Print (L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
+
+Done:
+ if (CapsuleBuffer != NULL) {
+ FreePool (CapsuleBuffer);
+ }
+
+ if (FullCapsuleBuffer != NULL) {
+ FreePool (FullCapsuleBuffer);
+ }
+
+ return Status;
+}
+
+/**
+ Clear capsule status variable.
+
+ @retval EFI_SUCCESS The capsule status variable is cleared.
+**/
+EFI_STATUS
+ClearCapsuleStatusVariable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ CHAR16 CapsuleVarName[20];
+ CHAR16 *TempVarName;
+ BOOLEAN Found;
+
+ StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CapsuleVarName[0]), L"Capsule");
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+ Index = 0;
+
+ Found = FALSE;
+ while (TRUE) {
+ UnicodeSPrint (TempVarName, 5 * sizeof (CHAR16), L"%04x", Index);
+
+ Status = gRT->SetVariable (
+ CapsuleVarName,
+ &gEfiCapsuleReportGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ (VOID *)NULL
+ );
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // There is no more capsule variables, quit
+ //
+ break;
+ }
+
+ Found = TRUE;
+
+ Print (L"Clear %s %r\n", CapsuleVarName, Status);
+
+ Index++;
+ if (Index > 0xFFFF) {
+ break;
+ }
+ }
+
+ if (!Found) {
+ Print (L"No any Capsule#### variable found\n");
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Build Gather list for a list of capsule images.
+
+ @param[in] CapsuleBuffer An array of pointer to capsule images
+ @param[in] FileSize An array of UINTN to capsule images size
+ @param[in] CapsuleNum The count of capsule images
+ @param[out] BlockDescriptors The block descriptors for the capsule images
+
+ @retval EFI_SUCCESS The block descriptors for the capsule images are constructed.
+**/
+EFI_STATUS
+BuildGatherList (
+ IN VOID **CapsuleBuffer,
+ IN UINTN *FileSize,
+ IN UINTN CapsuleNum,
+ OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
+ )
+{
+ EFI_STATUS Status;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors1;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors2;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorPre;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorsHeader;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr;
+ UINT8 *TempDataPtr;
+ UINTN SizeLeft;
+ UINTN Size;
+ INT32 Count;
+ INT32 Number;
+ UINTN Index;
+
+ TempBlockPtr = NULL;
+ BlockDescriptors1 = NULL;
+ BlockDescriptors2 = NULL;
+ BlockDescriptorPre = NULL;
+ BlockDescriptorsHeader = NULL;
+
+ for (Index = 0; Index < CapsuleNum; Index++) {
+ //
+ // Allocate memory for the descriptors.
+ //
+ if (NumberOfDescriptors == 1) {
+ Count = 2;
+ } else {
+ Count = (INT32)(NumberOfDescriptors + 2) / 2;
+ }
+
+ Size = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
+ BlockDescriptors1 = AllocateRuntimeZeroPool (Size);
+ if (BlockDescriptors1 == NULL) {
+ Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERREXIT;
+ } else {
+ Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)BlockDescriptors1);
+ Print (L"CapsuleApp: capsule data starts at 0x%X with size 0x%X\n", (UINTN)CapsuleBuffer[Index], FileSize[Index]);
+ }
+
+ //
+ // Record descriptor header
+ //
+ if (Index == 0) {
+ BlockDescriptorsHeader = BlockDescriptors1;
+ }
+
+ if (BlockDescriptorPre != NULL) {
+ BlockDescriptorPre->Union.ContinuationPointer = (UINTN)BlockDescriptors1;
+ BlockDescriptorPre->Length = 0;
+ }
+
+ //
+ // Fill them in
+ //
+ TempBlockPtr = BlockDescriptors1;
+ TempDataPtr = CapsuleBuffer[Index];
+ SizeLeft = FileSize[Index];
+ for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
+ //
+ // Divide remaining data in half
+ //
+ if (NumberOfDescriptors != 1) {
+ if (SizeLeft == 1) {
+ Size = 1;
+ } else {
+ Size = SizeLeft / 2;
+ }
+ } else {
+ Size = SizeLeft;
+ }
+
+ TempBlockPtr->Union.DataBlock = (UINTN)TempDataPtr;
+ TempBlockPtr->Length = Size;
+ Print (L"CapsuleApp: capsule block/size 0x%X/0x%X\n", (UINTN)TempDataPtr, Size);
+ SizeLeft -= Size;
+ TempDataPtr += Size;
+ TempBlockPtr++;
+ }
+
+ //
+ // Allocate the second list, point the first block's last entry to point
+ // to this one, and fill this one in. Worst case is that the previous
+ // list only had one element that pointed here, so we need at least two
+ // elements -- one to point to all the data, another to terminate the list.
+ //
+ if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
+ Count = (INT32)(NumberOfDescriptors + 2) - Count;
+ if (Count == 1) {
+ Count++;
+ }
+
+ Size = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
+ BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
+ if (BlockDescriptors2 == NULL) {
+ Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERREXIT;
+ }
+
+ //
+ // Point the first list's last element to point to this second list.
+ //
+ TempBlockPtr->Union.ContinuationPointer = (UINTN)BlockDescriptors2;
+
+ TempBlockPtr->Length = 0;
+ TempBlockPtr = BlockDescriptors2;
+ for (Number = 0; Number < Count - 1; Number++) {
+ //
+ // If second-to-last one, then dump rest to this element
+ //
+ if (Number == (Count - 2)) {
+ Size = SizeLeft;
+ } else {
+ //
+ // Divide remaining data in half
+ //
+ if (SizeLeft == 1) {
+ Size = 1;
+ } else {
+ Size = SizeLeft / 2;
+ }
+ }
+
+ TempBlockPtr->Union.DataBlock = (UINTN)TempDataPtr;
+ TempBlockPtr->Length = Size;
+ Print (L"CapsuleApp: capsule block/size 0x%X/0x%X\n", (UINTN)TempDataPtr, Size);
+ SizeLeft -= Size;
+ TempDataPtr += Size;
+ TempBlockPtr++;
+ if (SizeLeft == 0) {
+ break;
+ }
+ }
+ }
+
+ BlockDescriptorPre = TempBlockPtr;
+ BlockDescriptors1 = NULL;
+ }
+
+ //
+ // Null-terminate.
+ //
+ if (TempBlockPtr != NULL) {
+ TempBlockPtr->Union.ContinuationPointer = (UINTN)NULL;
+ TempBlockPtr->Length = 0;
+ *BlockDescriptors = BlockDescriptorsHeader;
+ }
+
+ return EFI_SUCCESS;
+
+ERREXIT:
+ if (BlockDescriptors1 != NULL) {
+ FreePool (BlockDescriptors1);
+ }
+
+ if (BlockDescriptors2 != NULL) {
+ FreePool (BlockDescriptors2);
+ }
+
+ return Status;
+}
+
+/**
+ Clear the Gather list for a list of capsule images.
+
+ @param[in] BlockDescriptors The block descriptors for the capsule images
+ @param[in] CapsuleNum The count of capsule images
+**/
+VOID
+CleanGatherList (
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors,
+ IN UINTN CapsuleNum
+ )
+{
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr1;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr2;
+ UINTN Index;
+
+ if (BlockDescriptors != NULL) {
+ TempBlockPtr1 = BlockDescriptors;
+ while (1) {
+ TempBlockPtr = TempBlockPtr1;
+ for (Index = 0; Index < CapsuleNum; Index++) {
+ if (TempBlockPtr[Index].Length == 0) {
+ break;
+ }
+ }
+
+ if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
+ break;
+ }
+
+ TempBlockPtr2 = (VOID *)((UINTN)TempBlockPtr[Index].Union.ContinuationPointer);
+ FreePool (TempBlockPtr1);
+ TempBlockPtr1 = TempBlockPtr2;
+ }
+ }
+}
+
+/**
+ Print APP usage.
+**/
+VOID
+PrintUsage (
+ VOID
+ )
+{
+ Print (L"CapsuleApp: usage\n");
+ Print (L" CapsuleApp <Capsule...> [-NR] [-OD [FSx]]\n");
+ Print (L" CapsuleApp -S\n");
+ Print (L" CapsuleApp -C\n");
+ Print (L" CapsuleApp -P\n");
+ Print (L" CapsuleApp -E\n");
+ Print (L" CapsuleApp -L\n");
+ Print (L" CapsuleApp -L INFO\n");
+ Print (L" CapsuleApp -F\n");
+ Print (L" CapsuleApp -G <BMP> -O <Capsule>\n");
+ Print (L" CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
+ Print (L" CapsuleApp -D <Capsule>\n");
+ Print (L" CapsuleApp -P GET <ImageTypeId> <Index> -O <FileName>\n");
+ Print (L"Parameter:\n");
+ Print (L" -NR: No reset will be triggered for the capsule\n");
+ Print (L" with CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without CAPSULE_FLAGS_INITIATE_RESET.\n");
+ Print (L" -OD: Delivery of Capsules via file on Mass Storage device.\n");
+ Print (L" -S: Dump capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
+ Print (L" which is defined in UEFI specification.\n");
+ Print (L" -C: Clear capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
+ Print (L" which is defined in UEFI specification.\n");
+ Print (L" -P: Dump UEFI FMP protocol info, or get image with specified\n");
+ Print (L" ImageTypeId and Index (decimal format) to a file if 'GET'\n");
+ Print (L" option is used.\n");
+ Print (L" -E: Dump UEFI ESRT table info.\n");
+ Print (L" -L: Dump provisioned capsule image information.\n");
+ Print (L" -F: Dump all EFI System Partition.\n");
+ Print (L" -G: Convert a BMP file to be an UX capsule,\n");
+ Print (L" according to Windows Firmware Update document\n");
+ Print (L" -N: Append a Capsule Header to an existing FMP capsule image\n");
+ Print (L" with its ImageTypeId supported by the system,\n");
+ Print (L" according to Windows Firmware Update document\n");
+ Print (L" -O: Output new Capsule file name\n");
+ Print (L" -D: Dump Capsule image header information, image payload\n");
+ Print (L" information if it is an UX capsule and FMP header\n");
+ Print (L" information if it is a FMP capsule.\n");
+}
+
+/**
+ Update Capsule image.
+
+ @param[in] ImageHandle The image handle.
+ @param[in] SystemTable The system table.
+
+ @retval EFI_SUCCESS Command completed successfully.
+ @retval EFI_UNSUPPORTED Command usage unsupported.
+ @retval EFI_INVALID_PARAMETER Command usage invalid.
+ @retval EFI_NOT_FOUND The input file can't be found.
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ RETURN_STATUS RStatus;
+ UINTN CapsuleBufferSize[MAX_CAPSULE_NUM];
+ VOID *CapsuleBuffer[MAX_CAPSULE_NUM];
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors;
+ EFI_CAPSULE_HEADER *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
+ UINT64 MaxCapsuleSize;
+ EFI_RESET_TYPE ResetType;
+ BOOLEAN NeedReset;
+ BOOLEAN NoReset;
+ BOOLEAN CapsuleOnDisk;
+ CHAR16 *CapsuleName;
+ CHAR16 *CapsuleNames[MAX_CAPSULE_NUM];
+ CHAR16 *MapFsStr;
+ UINTN CapsuleNum;
+ UINTN Index;
+ UINTN ParaOdIndex;
+ UINTN ParaNrIndex;
+ EFI_GUID ImageTypeId;
+ UINTN ImageIndex;
+
+ BlockDescriptors = NULL;
+ MapFsStr = NULL;
+ CapsuleNum = 0;
+
+ Status = GetArg ();
+ if (EFI_ERROR (Status)) {
+ Print (L"Please use UEFI SHELL to run this application!\n", Status);
+ return Status;
+ }
+
+ if (Argc < 2) {
+ PrintUsage ();
+ return EFI_UNSUPPORTED;
+ }
+
+ if (StrCmp (Argv[1], L"-D") == 0) {
+ if (Argc != 3) {
+ Print (L"CapsuleApp: Incorrect parameter count.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = DumpCapsule (Argv[2]);
+ return Status;
+ }
+
+ if (StrCmp (Argv[1], L"-G") == 0) {
+ Status = CreateBmpFmp ();
+ return Status;
+ }
+
+ if (StrCmp (Argv[1], L"-N") == 0) {
+ Status = CreateNestedFmp ();
+ return Status;
+ }
+
+ if (StrCmp (Argv[1], L"-S") == 0) {
+ Status = DumpCapsuleStatusVariable ();
+ return EFI_SUCCESS;
+ }
+
+ if (StrCmp (Argv[1], L"-C") == 0) {
+ Status = ClearCapsuleStatusVariable ();
+ return Status;
+ }
+
+ if (StrCmp (Argv[1], L"-P") == 0) {
+ if (Argc == 2) {
+ DumpFmpData ();
+ }
+
+ if (Argc >= 3) {
+ if (StrCmp (Argv[2], L"GET") != 0) {
+ Print (L"CapsuleApp: Unrecognized option(%s).\n", Argv[2]);
+ return EFI_UNSUPPORTED;
+ } else {
+ if (Argc != 7) {
+ Print (L"CapsuleApp: Incorrect parameter count.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // FMP->GetImage()
+ //
+ RStatus = StrToGuid (Argv[3], &ImageTypeId);
+ if (RETURN_ERROR (RStatus) || (Argv[3][GUID_STRING_LENGTH] != L'\0')) {
+ Print (L"Invalid ImageTypeId - %s\n", Argv[3]);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ImageIndex = StrDecimalToUintn (Argv[4]);
+ if (StrCmp (Argv[5], L"-O") != 0) {
+ Print (L"CapsuleApp: NO output file name.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ DumpFmpImage (&ImageTypeId, ImageIndex, Argv[6]);
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ if (StrCmp (Argv[1], L"-E") == 0) {
+ DumpEsrtData ();
+ return EFI_SUCCESS;
+ }
+
+ if (StrCmp (Argv[1], L"-L") == 0) {
+ if ((Argc >= 3) && (StrCmp (Argv[2], L"INFO") == 0)) {
+ DumpProvisionedCapsule (TRUE);
+ } else {
+ DumpProvisionedCapsule (FALSE);
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ if (StrCmp (Argv[1], L"-F") == 0) {
+ DumpAllEfiSysPartition ();
+ return EFI_SUCCESS;
+ }
+
+ if (Argv[1][0] == L'-') {
+ Print (L"CapsuleApp: Unrecognized option(%s).\n", Argv[1]);
+ return EFI_UNSUPPORTED;
+ }
+
+ CapsuleFirstIndex = 1;
+ NoReset = FALSE;
+ CapsuleOnDisk = FALSE;
+ ParaOdIndex = 0;
+ ParaNrIndex = 0;
+
+ for (Index = 1; Index < Argc; Index++) {
+ if (StrCmp (Argv[Index], L"-OD") == 0) {
+ ParaOdIndex = Index;
+ CapsuleOnDisk = TRUE;
+ } else if (StrCmp (Argv[Index], L"-NR") == 0) {
+ ParaNrIndex = Index;
+ NoReset = TRUE;
+ }
+ }
+
+ if (ParaOdIndex > ParaNrIndex) {
+ if (ParaNrIndex != 0) {
+ CapsuleLastIndex = ParaNrIndex - 1;
+ } else {
+ CapsuleLastIndex = ParaOdIndex - 1;
+ }
+
+ if (ParaOdIndex == Argc -1) {
+ MapFsStr = NULL;
+ } else if (ParaOdIndex == Argc - 2) {
+ MapFsStr = Argv[Argc-1];
+ } else {
+ Print (L"CapsuleApp: Cannot specify more than one FS mapping!\n");
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ } else if (ParaOdIndex < ParaNrIndex) {
+ if (ParaOdIndex != 0) {
+ CapsuleLastIndex = ParaOdIndex - 1;
+ if (ParaOdIndex == ParaNrIndex - 1) {
+ MapFsStr = NULL;
+ } else if (ParaOdIndex == ParaNrIndex - 2) {
+ MapFsStr = Argv[ParaOdIndex + 1];
+ } else {
+ Print (L"CapsuleApp: Cannot specify more than one FS mapping!\n");
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ } else {
+ CapsuleLastIndex = ParaNrIndex - 1;
+ }
+ } else {
+ CapsuleLastIndex = Argc - 1;
+ }
+
+ CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
+
+ if (CapsuleFirstIndex > CapsuleLastIndex) {
+ Print (L"CapsuleApp: NO capsule image.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ if (CapsuleNum > MAX_CAPSULE_NUM) {
+ Print (L"CapsuleApp: Too many capsule images.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ ZeroMem (&CapsuleBuffer, sizeof (CapsuleBuffer));
+ ZeroMem (&CapsuleBufferSize, sizeof (CapsuleBufferSize));
+ BlockDescriptors = NULL;
+
+ for (Index = 0; Index < CapsuleNum; Index++) {
+ CapsuleName = Argv[CapsuleFirstIndex + Index];
+ Status = ReadFileToBuffer (CapsuleName, &CapsuleBufferSize[Index], &CapsuleBuffer[Index]);
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
+ goto Done;
+ }
+
+ if (!IsValidCapsuleHeader (CapsuleBuffer[Index], CapsuleBufferSize[Index])) {
+ Print (L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CapsuleNames[Index] = CapsuleName;
+ }
+
+ //
+ // Every capsule use 2 descriptor 1 for data 1 for end
+ //
+ Status = BuildGatherList (CapsuleBuffer, CapsuleBufferSize, CapsuleNum, &BlockDescriptors);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Call the runtime service capsule.
+ //
+ NeedReset = FALSE;
+ for (Index = 0; Index < CapsuleNum; Index++) {
+ CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *)CapsuleBuffer[Index];
+ if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
+ NeedReset = TRUE;
+ }
+ }
+
+ CapsuleHeaderArray[CapsuleNum] = NULL;
+
+ //
+ // Inquire platform capability of UpdateCapsule.
+ //
+ Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum, &MaxCapsuleSize, &ResetType);
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
+ goto Done;
+ }
+
+ for (Index = 0; Index < CapsuleNum; Index++) {
+ if (CapsuleBufferSize[Index] > MaxCapsuleSize) {
+ Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n", MaxCapsuleSize);
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+ }
+
+ //
+ // Check whether is capsule on disk.
+ //
+ if (CapsuleOnDisk) {
+ Status = ProcessCapsuleOnDisk (CapsuleBuffer, CapsuleBufferSize, CapsuleNames, MapFsStr, CapsuleNum);
+ if (Status != EFI_SUCCESS) {
+ Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
+ goto Done;
+ } else {
+ if (!NoReset) {
+ gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
+ } else {
+ goto Done;
+ }
+ }
+ }
+
+ //
+ // Check whether the input capsule image has the flag of persist across system reset.
+ //
+ if (NeedReset) {
+ Status = gRT->UpdateCapsule (CapsuleHeaderArray, CapsuleNum, (UINTN)BlockDescriptors);
+ if (Status != EFI_SUCCESS) {
+ Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
+ goto Done;
+ }
+
+ //
+ // For capsule with CAPSULE_FLAGS_PERSIST_ACROSS_RESET + CAPSULE_FLAGS_INITIATE_RESET,
+ // a system reset should have been triggered by gRT->UpdateCapsule() calling above.
+ //
+ // For capsule with CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without CAPSULE_FLAGS_INITIATE_RESET,
+ // check if -NR (no-reset) has been specified or not.
+ //
+ if (!NoReset) {
+ //
+ // For capsule who has reset flag and no -NR (no-reset) has been specified, after calling UpdateCapsule service,
+ // trigger a system reset to process capsule persist across a system reset.
+ //
+ gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
+ }
+ } else {
+ //
+ // For capsule who has no reset flag, only call UpdateCapsule Service without a
+ // system reset. The service will process the capsule immediately.
+ //
+ Status = gRT->UpdateCapsule (CapsuleHeaderArray, CapsuleNum, (UINTN)BlockDescriptors);
+ if (Status != EFI_SUCCESS) {
+ Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+ for (Index = 0; Index < CapsuleNum; Index++) {
+ if (CapsuleBuffer[Index] != NULL) {
+ FreePool (CapsuleBuffer[Index]);
+ }
+ }
+
+ CleanGatherList (BlockDescriptors, CapsuleNum);
+
+ return Status;
+}
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.h b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.h
index 255a2e0e1e..05cdce8313 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.h
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.h
@@ -1,234 +1,234 @@
-/** @file
- A shell application that triggers capsule update process.
-
- Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _CAPSULE_APP_H_
-#define _CAPSULE_APP_H_
-
-#include <Uefi.h>
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/PrintLib.h>
-#include <Library/BmpSupportLib.h>
-#include <Library/FileHandleLib.h>
-#include <Library/SortLib.h>
-#include <Library/UefiBootManagerLib.h>
-#include <Library/DevicePathLib.h>
-#include <Protocol/GraphicsOutput.h>
-#include <Protocol/SimpleFileSystem.h>
-#include <Protocol/ShellParameters.h>
-#include <Protocol/Shell.h>
-#include <Protocol/FirmwareManagement.h>
-#include <Guid/GlobalVariable.h>
-#include <Guid/CapsuleReport.h>
-#include <Guid/SystemResourceTable.h>
-#include <Guid/FmpCapsule.h>
-#include <Guid/FileInfo.h>
-#include <Guid/ImageAuthentication.h>
-#include <Guid/CapsuleVendor.h>
-#include <Guid/Gpt.h>
-#include <IndustryStandard/WindowsUxCapsule.h>
-
-#define CAPSULE_HEADER_SIZE 0x20
-
-#define NESTED_CAPSULE_HEADER_SIZE SIZE_4KB
-#define SYSTEM_FIRMWARE_FLAG 0x50000
-#define DEVICE_FIRMWARE_FLAG 0x78010
-
-#define MAJOR_VERSION 1
-#define MINOR_VERSION 0
-
-#define MAX_CAPSULE_NUM 10
-
-//
-// (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)
-//
-#define MAX_FILE_NAME_SIZE 522
-#define MAX_FILE_NAME_LEN (MAX_FILE_NAME_SIZE / sizeof(CHAR16))
-
-extern UINTN Argc;
-extern CHAR16 **Argv;
-
-/**
-
- This function parse application ARG.
-
- @return Status
-**/
-EFI_STATUS
-GetArg (
- VOID
- );
-
-/**
- Get shell protocol.
-
- @return Pointer to shell protocol.
-
-**/
-EFI_SHELL_PROTOCOL *
-GetShellProtocol (
- VOID
- );
-
-/**
- Read a file.
-
- @param[in] FileName The file to be read.
- @param[out] BufferSize The file buffer size
- @param[out] Buffer The file buffer
-
- @retval EFI_SUCCESS Read file successfully
- @retval EFI_NOT_FOUND Shell protocol or file not found
- @retval others Read file failed
-**/
-EFI_STATUS
-ReadFileToBuffer (
- IN CHAR16 *FileName,
- OUT UINTN *BufferSize,
- OUT VOID **Buffer
- );
-
-/**
- Write a file.
-
- @param[in] FileName The file to be written.
- @param[in] BufferSize The file buffer size
- @param[in] Buffer The file buffer
-
- @retval EFI_SUCCESS Write file successfully
- @retval EFI_NOT_FOUND Shell protocol not found
- @retval others Write file failed
-**/
-EFI_STATUS
-WriteFileFromBuffer (
- IN CHAR16 *FileName,
- IN UINTN BufferSize,
- IN VOID *Buffer
- );
-
-/**
- Dump capsule information
-
- @param[in] CapsuleName The name of the capsule image.
-
- @retval EFI_SUCCESS The capsule information is dumped.
- @retval EFI_UNSUPPORTED Input parameter is not valid.
-**/
-EFI_STATUS
-DumpCapsule (
- IN CHAR16 *CapsuleName
- );
-
-/**
- Dump capsule status variable.
-
- @retval EFI_SUCCESS The capsule status variable is dumped.
- @retval EFI_UNSUPPORTED Input parameter is not valid.
-**/
-EFI_STATUS
-DumpCapsuleStatusVariable (
- VOID
- );
-
-/**
- Dump FMP protocol info.
-**/
-VOID
-DumpFmpData (
- VOID
- );
-
-/**
- Dump FMP image data.
-
- @param[in] ImageTypeId The ImageTypeId of the FMP image.
- It is used to identify the FMP protocol.
- @param[in] ImageIndex The ImageIndex of the FMP image.
- It is the input parameter for FMP->GetImage().
- @param[in] ImageName The file name to hold the output FMP image.
-**/
-VOID
-DumpFmpImage (
- IN EFI_GUID *ImageTypeId,
- IN UINTN ImageIndex,
- IN CHAR16 *ImageName
- );
-
-/**
- Dump ESRT info.
-**/
-VOID
-DumpEsrtData (
- VOID
- );
-
-/**
- Dump Provisioned Capsule.
-
- @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation.
-**/
-VOID
-DumpProvisionedCapsule (
- IN BOOLEAN DumpCapsuleInfo
- );
-
-/**
- Dump all EFI System Partition.
-**/
-VOID
-DumpAllEfiSysPartition (
- VOID
- );
-
-/**
- Get SimpleFileSystem from boot option file path.
-
- @param[in] DevicePath The file path of boot option
- @param[out] FullPath The full device path of boot device
- @param[out] Fs The file system within EfiSysPartition
-
- @retval EFI_SUCCESS Get file system successfully
- @retval EFI_NOT_FOUND No valid file system found
- @retval others Get file system failed
-
-**/
-EFI_STATUS
-GetEfiSysPartitionFromBootOptionFilePath (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
- OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
- );
-
-/**
- Process Capsule On Disk.
-
- @param[in] CapsuleBuffer An array of pointer to capsule images
- @param[in] CapsuleBufferSize An array of UINTN to capsule images size
- @param[in] FilePath An array of capsule images file path
- @param[in] Map File system mapping string
- @param[in] CapsuleNum The count of capsule images
-
- @retval EFI_SUCCESS Capsule on disk success.
- @retval others Capsule on disk fail.
-
-**/
-EFI_STATUS
-ProcessCapsuleOnDisk (
- IN VOID **CapsuleBuffer,
- IN UINTN *CapsuleBufferSize,
- IN CHAR16 **FilePath,
- IN CHAR16 *Map,
- IN UINTN CapsuleNum
- );
-
-#endif
+/** @file
+ A shell application that triggers capsule update process.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _CAPSULE_APP_H_
+#define _CAPSULE_APP_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BmpSupportLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/DevicePathLib.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/ShellParameters.h>
+#include <Protocol/Shell.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/CapsuleReport.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FmpCapsule.h>
+#include <Guid/FileInfo.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/CapsuleVendor.h>
+#include <Guid/Gpt.h>
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+#define CAPSULE_HEADER_SIZE 0x20
+
+#define NESTED_CAPSULE_HEADER_SIZE SIZE_4KB
+#define SYSTEM_FIRMWARE_FLAG 0x50000
+#define DEVICE_FIRMWARE_FLAG 0x78010
+
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 0
+
+#define MAX_CAPSULE_NUM 10
+
+//
+// (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)
+//
+#define MAX_FILE_NAME_SIZE 522
+#define MAX_FILE_NAME_LEN (MAX_FILE_NAME_SIZE / sizeof(CHAR16))
+
+extern UINTN Argc;
+extern CHAR16 **Argv;
+
+/**
+
+ This function parse application ARG.
+
+ @return Status
+**/
+EFI_STATUS
+GetArg (
+ VOID
+ );
+
+/**
+ Get shell protocol.
+
+ @return Pointer to shell protocol.
+
+**/
+EFI_SHELL_PROTOCOL *
+GetShellProtocol (
+ VOID
+ );
+
+/**
+ Read a file.
+
+ @param[in] FileName The file to be read.
+ @param[out] BufferSize The file buffer size
+ @param[out] Buffer The file buffer
+
+ @retval EFI_SUCCESS Read file successfully
+ @retval EFI_NOT_FOUND Shell protocol or file not found
+ @retval others Read file failed
+**/
+EFI_STATUS
+ReadFileToBuffer (
+ IN CHAR16 *FileName,
+ OUT UINTN *BufferSize,
+ OUT VOID **Buffer
+ );
+
+/**
+ Write a file.
+
+ @param[in] FileName The file to be written.
+ @param[in] BufferSize The file buffer size
+ @param[in] Buffer The file buffer
+
+ @retval EFI_SUCCESS Write file successfully
+ @retval EFI_NOT_FOUND Shell protocol not found
+ @retval others Write file failed
+**/
+EFI_STATUS
+WriteFileFromBuffer (
+ IN CHAR16 *FileName,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Dump capsule information
+
+ @param[in] CapsuleName The name of the capsule image.
+
+ @retval EFI_SUCCESS The capsule information is dumped.
+ @retval EFI_UNSUPPORTED Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsule (
+ IN CHAR16 *CapsuleName
+ );
+
+/**
+ Dump capsule status variable.
+
+ @retval EFI_SUCCESS The capsule status variable is dumped.
+ @retval EFI_UNSUPPORTED Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsuleStatusVariable (
+ VOID
+ );
+
+/**
+ Dump FMP protocol info.
+**/
+VOID
+DumpFmpData (
+ VOID
+ );
+
+/**
+ Dump FMP image data.
+
+ @param[in] ImageTypeId The ImageTypeId of the FMP image.
+ It is used to identify the FMP protocol.
+ @param[in] ImageIndex The ImageIndex of the FMP image.
+ It is the input parameter for FMP->GetImage().
+ @param[in] ImageName The file name to hold the output FMP image.
+**/
+VOID
+DumpFmpImage (
+ IN EFI_GUID *ImageTypeId,
+ IN UINTN ImageIndex,
+ IN CHAR16 *ImageName
+ );
+
+/**
+ Dump ESRT info.
+**/
+VOID
+DumpEsrtData (
+ VOID
+ );
+
+/**
+ Dump Provisioned Capsule.
+
+ @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation.
+**/
+VOID
+DumpProvisionedCapsule (
+ IN BOOLEAN DumpCapsuleInfo
+ );
+
+/**
+ Dump all EFI System Partition.
+**/
+VOID
+DumpAllEfiSysPartition (
+ VOID
+ );
+
+/**
+ Get SimpleFileSystem from boot option file path.
+
+ @param[in] DevicePath The file path of boot option
+ @param[out] FullPath The full device path of boot device
+ @param[out] Fs The file system within EfiSysPartition
+
+ @retval EFI_SUCCESS Get file system successfully
+ @retval EFI_NOT_FOUND No valid file system found
+ @retval others Get file system failed
+
+**/
+EFI_STATUS
+GetEfiSysPartitionFromBootOptionFilePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
+ OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
+ );
+
+/**
+ Process Capsule On Disk.
+
+ @param[in] CapsuleBuffer An array of pointer to capsule images
+ @param[in] CapsuleBufferSize An array of UINTN to capsule images size
+ @param[in] FilePath An array of capsule images file path
+ @param[in] Map File system mapping string
+ @param[in] CapsuleNum The count of capsule images
+
+ @retval EFI_SUCCESS Capsule on disk success.
+ @retval others Capsule on disk fail.
+
+**/
+EFI_STATUS
+ProcessCapsuleOnDisk (
+ IN VOID **CapsuleBuffer,
+ IN UINTN *CapsuleBufferSize,
+ IN CHAR16 **FilePath,
+ IN CHAR16 *Map,
+ IN UINTN CapsuleNum
+ );
+
+#endif
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
index 6ed0659835..e76b4fb265 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
@@ -1,69 +1,69 @@
-## @file
-# A shell application that triggers capsule update process.
-#
-# This application can trigger capsule update process. It can also
-# generate capsule image, or dump capsule variable information.
-#
-# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010006
- BASE_NAME = CapsuleApp
- MODULE_UNI_FILE = CapsuleApp.uni
- FILE_GUID = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
- MODULE_TYPE = UEFI_APPLICATION
- VERSION_STRING = 1.0
- ENTRY_POINT = UefiMain
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64
-#
-
-[Sources]
- CapsuleApp.c
- CapsuleApp.h
- CapsuleDump.c
- CapsuleOnDisk.c
- AppSupport.c
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[Guids]
- gEfiGlobalVariableGuid ## CONSUMES ## GUID
- gEfiCapsuleReportGuid ## CONSUMES ## GUID
- gEfiFmpCapsuleGuid ## CONSUMES ## GUID
- gWindowsUxCapsuleGuid ## CONSUMES ## GUID
- gEfiSystemResourceTableGuid ## CONSUMES ## GUID
- gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variable:L"CapsuleUpdateData"
- gEfiPartTypeSystemPartGuid ## SOMETIMES_CONSUMES ## GUID
-
-[Protocols]
- gEfiGraphicsOutputProtocolGuid ## CONSUMES
- gEfiFirmwareManagementProtocolGuid ## CONSUMES
- gEfiShellParametersProtocolGuid ## CONSUMES
- gEfiShellProtocolGuid ## CONSUMES
- gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
-
-[LibraryClasses]
- BaseLib
- UefiApplicationEntryPoint
- DebugLib
- MemoryAllocationLib
- UefiBootServicesTableLib
- UefiRuntimeServicesTableLib
- UefiLib
- PrintLib
- BmpSupportLib
- FileHandleLib
- UefiBootManagerLib
- SortLib
-
-[UserExtensions.TianoCore."ExtraFiles"]
- CapsuleAppExtra.uni
+## @file
+# A shell application that triggers capsule update process.
+#
+# This application can trigger capsule update process. It can also
+# generate capsule image, or dump capsule variable information.
+#
+# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = CapsuleApp
+ MODULE_UNI_FILE = CapsuleApp.uni
+ FILE_GUID = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ CapsuleApp.c
+ CapsuleApp.h
+ CapsuleDump.c
+ CapsuleOnDisk.c
+ AppSupport.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[Guids]
+ gEfiGlobalVariableGuid ## CONSUMES ## GUID
+ gEfiCapsuleReportGuid ## CONSUMES ## GUID
+ gEfiFmpCapsuleGuid ## CONSUMES ## GUID
+ gWindowsUxCapsuleGuid ## CONSUMES ## GUID
+ gEfiSystemResourceTableGuid ## CONSUMES ## GUID
+ gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variable:L"CapsuleUpdateData"
+ gEfiPartTypeSystemPartGuid ## SOMETIMES_CONSUMES ## GUID
+
+[Protocols]
+ gEfiGraphicsOutputProtocolGuid ## CONSUMES
+ gEfiFirmwareManagementProtocolGuid ## CONSUMES
+ gEfiShellParametersProtocolGuid ## CONSUMES
+ gEfiShellProtocolGuid ## CONSUMES
+ gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
+
+[LibraryClasses]
+ BaseLib
+ UefiApplicationEntryPoint
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiLib
+ PrintLib
+ BmpSupportLib
+ FileHandleLib
+ UefiBootManagerLib
+ SortLib
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ CapsuleAppExtra.uni
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
index 955979dcc3..f978fa93b7 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
@@ -1,17 +1,17 @@
-// /** @file
-// A shell application that triggers capsule update process.
-//
-// This application can trigger capsule update process. It can also
-// generate capsule image, or dump capsule variable information.
-//
-// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-
-#string STR_MODULE_ABSTRACT #language en-US "A shell application that triggers capsule update process."
-
-#string STR_MODULE_DESCRIPTION #language en-US "This application can trigger capsule update process. It can also generate capsule image, or dump capsule variable information."
-
+// /** @file
+// A shell application that triggers capsule update process.
+//
+// This application can trigger capsule update process. It can also
+// generate capsule image, or dump capsule variable information.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "A shell application that triggers capsule update process."
+
+#string STR_MODULE_DESCRIPTION #language en-US "This application can trigger capsule update process. It can also generate capsule image, or dump capsule variable information."
+
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
index 42bd212a93..13515585e3 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
@@ -1,14 +1,14 @@
-// /** @file
-// CapsuleApp Localized Strings and Content
-//
-// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-#string STR_PROPERTIES_MODULE_NAME
-#language en-US
-"Capsule Application"
-
-
+// /** @file
+// CapsuleApp Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Capsule Application"
+
+
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
index 7605153e97..11bc505353 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
@@ -1,1468 +1,1468 @@
-/** @file
- Dump Capsule image information.
-
- Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "CapsuleApp.h"
-
-/**
- Validate if it is valid capsule header
-
- This function assumes the caller provided correct CapsuleHeader pointer
- and CapsuleSize.
-
- This function validates the fields in EFI_CAPSULE_HEADER.
-
- @param[in] CapsuleHeader Points to a capsule header.
- @param[in] CapsuleSize Size of the whole capsule image.
-
-**/
-BOOLEAN
-IsValidCapsuleHeader (
- IN EFI_CAPSULE_HEADER *CapsuleHeader,
- IN UINT64 CapsuleSize
- );
-
-/**
- Dump UX capsule information.
-
- @param[in] CapsuleHeader The UX capsule header
-**/
-VOID
-DumpUxCapsule (
- IN EFI_CAPSULE_HEADER *CapsuleHeader
- )
-{
- EFI_DISPLAY_CAPSULE *DisplayCapsule;
-
- DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
- Print (L"[UxCapsule]\n");
- Print (L"CapsuleHeader:\n");
- Print (L" CapsuleGuid - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
- Print (L" HeaderSize - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
- Print (L" Flags - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
- Print (L" CapsuleImageSize - 0x%x\n", DisplayCapsule->CapsuleHeader.CapsuleImageSize);
- Print (L"ImagePayload:\n");
- Print (L" Version - 0x%x\n", DisplayCapsule->ImagePayload.Version);
- Print (L" Checksum - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
- Print (L" ImageType - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
- Print (L" Mode - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
- Print (L" OffsetX - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
- Print (L" OffsetY - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
-}
-
-/**
- Dump a non-nested FMP capsule.
-
- @param[in] CapsuleHeader A pointer to CapsuleHeader
-**/
-VOID
-DumpFmpCapsule (
- IN EFI_CAPSULE_HEADER *CapsuleHeader
- )
-{
- EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
- UINT64 *ItemOffsetList;
- UINTN Index;
- UINTN Count;
- EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *FmpImageHeader;
-
- Print (L"[FmpCapsule]\n");
- Print (L"CapsuleHeader:\n");
- Print (L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid);
- Print (L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize);
- Print (L" Flags - 0x%x\n", CapsuleHeader->Flags);
- Print (L" CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
-
- FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
- ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
- Print (L"FmpHeader:\n");
- Print (L" Version - 0x%x\n", FmpCapsuleHeader->Version);
- Print (L" EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
- Print (L" PayloadItemCount - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
- Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
- for (Index = 0; Index < Count; Index++) {
- Print (L" Offset[%d] - 0x%x\n", Index, ItemOffsetList[Index]);
- }
-
- for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
- Print (L"FmpPayload[%d] ImageHeader:\n", Index);
- FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
- Print (L" Version - 0x%x\n", FmpImageHeader->Version);
- Print (L" UpdateImageTypeId - %g\n", &FmpImageHeader->UpdateImageTypeId);
- Print (L" UpdateImageIndex - 0x%x\n", FmpImageHeader->UpdateImageIndex);
- Print (L" UpdateImageSize - 0x%x\n", FmpImageHeader->UpdateImageSize);
- Print (L" UpdateVendorCodeSize - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
- if (FmpImageHeader->Version >= 2) {
- Print (L" UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);
- if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
- Print (L" ImageCapsuleSupport - 0x%lx\n", FmpImageHeader->ImageCapsuleSupport);
- }
- }
- }
-}
-
-/**
- Return if there is a FMP header below capsule header.
-
- @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
-
- @retval TRUE There is a FMP header below capsule header.
- @retval FALSE There is not a FMP header below capsule header
-**/
-BOOLEAN
-IsNestedFmpCapsule (
- IN EFI_CAPSULE_HEADER *CapsuleHeader
- )
-{
- EFI_STATUS Status;
- EFI_SYSTEM_RESOURCE_TABLE *Esrt;
- EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
- UINTN Index;
- BOOLEAN EsrtGuidFound;
- EFI_CAPSULE_HEADER *NestedCapsuleHeader;
- UINTN NestedCapsuleSize;
-
- //
- // Check ESRT
- //
- EsrtGuidFound = FALSE;
- Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
- if (!EFI_ERROR (Status)) {
- ASSERT (Esrt != NULL);
- EsrtEntry = (VOID *)(Esrt + 1);
- for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
- if (CompareGuid (&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
- EsrtGuidFound = TRUE;
- break;
- }
- }
- }
-
- if (!EsrtGuidFound) {
- return FALSE;
- }
-
- //
- // Check nested capsule header
- // FMP GUID after ESRT one
- //
- NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
- NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize- (UINTN)NestedCapsuleHeader;
- if (NestedCapsuleSize < sizeof (EFI_CAPSULE_HEADER)) {
- return FALSE;
- }
-
- if (!CompareGuid (&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- Dump capsule information
-
- @param[in] CapsuleName The name of the capsule image.
-
- @retval EFI_SUCCESS The capsule information is dumped.
- @retval EFI_UNSUPPORTED Input parameter is not valid.
-**/
-EFI_STATUS
-DumpCapsule (
- IN CHAR16 *CapsuleName
- )
-{
- VOID *Buffer;
- UINTN FileSize;
- EFI_CAPSULE_HEADER *CapsuleHeader;
- EFI_STATUS Status;
-
- Buffer = NULL;
- Status = ReadFileToBuffer (CapsuleName, &FileSize, &Buffer);
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
- goto Done;
- }
-
- if (!IsValidCapsuleHeader (Buffer, FileSize)) {
- Print (L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- CapsuleHeader = Buffer;
- if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
- DumpUxCapsule (CapsuleHeader);
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
- DumpFmpCapsule (CapsuleHeader);
- }
-
- if (IsNestedFmpCapsule (CapsuleHeader)) {
- Print (L"[NestedCapsule]\n");
- Print (L"CapsuleHeader:\n");
- Print (L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid);
- Print (L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize);
- Print (L" Flags - 0x%x\n", CapsuleHeader->Flags);
- Print (L" CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
- DumpFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
- }
-
-Done:
- if (Buffer != NULL) {
- FreePool (Buffer);
- }
-
- return Status;
-}
-
-/**
- Dump capsule status variable.
-
- @retval EFI_SUCCESS The capsule status variable is dumped.
- @retval EFI_UNSUPPORTED Input parameter is not valid.
-**/
-EFI_STATUS
-DumpCapsuleStatusVariable (
- VOID
- )
-{
- EFI_STATUS Status;
- UINT32 Index;
- CHAR16 CapsuleVarName[20];
- CHAR16 *TempVarName;
- EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResult;
- EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultFmp;
- UINTN CapsuleFileNameSize;
- CHAR16 CapsuleIndexData[12];
- CHAR16 *CapsuleIndex;
- CHAR16 *CapsuleFileName;
- CHAR16 *CapsuleTarget;
-
- Status = GetVariable2 (
- L"CapsuleMax",
- &gEfiCapsuleReportGuid,
- (VOID **)&CapsuleIndex,
- NULL
- );
- if (!EFI_ERROR (Status)) {
- ASSERT (CapsuleIndex != NULL);
- CopyMem (CapsuleIndexData, CapsuleIndex, 11 * sizeof (CHAR16));
- CapsuleIndexData[11] = 0;
- Print (L"CapsuleMax - %s\n", CapsuleIndexData);
- FreePool (CapsuleIndex);
- }
-
- Status = GetVariable2 (
- L"CapsuleLast",
- &gEfiCapsuleReportGuid,
- (VOID **)&CapsuleIndex,
- NULL
- );
- if (!EFI_ERROR (Status)) {
- ASSERT (CapsuleIndex != NULL);
- CopyMem (CapsuleIndexData, CapsuleIndex, 11 * sizeof (CHAR16));
- CapsuleIndexData[11] = 0;
- Print (L"CapsuleLast - %s\n", CapsuleIndexData);
- FreePool (CapsuleIndex);
- }
-
- StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CapsuleVarName[0]), L"Capsule");
- TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
- Index = 0;
-
- while (TRUE) {
- UnicodeSPrint (TempVarName, 5 * sizeof (CHAR16), L"%04x", Index);
-
- Status = GetVariable2 (
- CapsuleVarName,
- &gEfiCapsuleReportGuid,
- (VOID **)&CapsuleResult,
- NULL
- );
- if (Status == EFI_NOT_FOUND) {
- break;
- } else if (EFI_ERROR (Status)) {
- continue;
- }
-
- ASSERT (CapsuleResult != NULL);
-
- //
- // display capsule process status
- //
- if (CapsuleResult->VariableTotalSize >= sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
- Print (L"CapsuleName: %s\n", CapsuleVarName);
- Print (L" Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
- Print (L" Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
- Print (L" Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
- }
-
- if (CompareGuid (&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
- if (CapsuleResult->VariableTotalSize >= sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof (CHAR16) * 2) {
- CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
- Print (L" Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
- Print (L" Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
- Print (L" Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex);
- Print (L" Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId);
- CapsuleFileName = (CHAR16 *)(CapsuleResultFmp + 1);
- Print (L" Capsule FMP CapsuleFileName: \"%s\"\n", CapsuleFileName);
- CapsuleFileNameSize = StrSize (CapsuleFileName);
- CapsuleTarget = (CHAR16 *)((UINTN)CapsuleFileName + CapsuleFileNameSize);
- Print (L" Capsule FMP CapsuleTarget: \"%s\"\n", CapsuleTarget);
- }
- }
-
- FreePool (CapsuleResult);
-
- Index++;
- if (Index > 0xFFFF) {
- break;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-CHAR8 *mFwTypeString[] = {
- "Unknown",
- "SystemFirmware",
- "DeviceFirmware",
- "UefiDriver",
-};
-
-CHAR8 *mLastAttemptStatusString[] = {
- "Success",
- "Error: Unsuccessful",
- "Error: Insufficient Resources",
- "Error: Incorrect Version",
- "Error: Invalid Format",
- "Error: Auth Error",
- "Error: Power Event AC",
- "Error: Power Event Battery",
- "Error: Unsatisfied Dependencies",
-};
-
-/**
- Convert FwType to a string.
-
- @param[in] FwType FwType in ESRT
-
- @return a string for FwType.
-**/
-CHAR8 *
-FwTypeToString (
- IN UINT32 FwType
- )
-{
- if (FwType < sizeof (mFwTypeString) / sizeof (mFwTypeString[0])) {
- return mFwTypeString[FwType];
- } else {
- return "Invalid";
- }
-}
-
-/**
- Convert LastAttemptStatus to a string.
-
- @param[in] LastAttemptStatus LastAttemptStatus in FMP or ESRT
-
- @return a string for LastAttemptStatus.
-**/
-CHAR8 *
-LastAttemptStatusToString (
- IN UINT32 LastAttemptStatus
- )
-{
- if (LastAttemptStatus < sizeof (mLastAttemptStatusString) / sizeof (mLastAttemptStatusString[0])) {
- return mLastAttemptStatusString[LastAttemptStatus];
- } else {
- return "Error: Unknown";
- }
-}
-
-/**
- Dump ESRT entry.
-
- @param[in] EsrtEntry ESRT entry
-**/
-VOID
-DumpEsrtEntry (
- IN EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry
- )
-{
- Print (L" FwClass - %g\n", &EsrtEntry->FwClass);
- Print (L" FwType - 0x%x (%a)\n", EsrtEntry->FwType, FwTypeToString (EsrtEntry->FwType));
- Print (L" FwVersion - 0x%x\n", EsrtEntry->FwVersion);
- Print (L" LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
- Print (L" CapsuleFlags - 0x%x\n", EsrtEntry->CapsuleFlags);
- Print (L" LastAttemptVersion - 0x%x\n", EsrtEntry->LastAttemptVersion);
- Print (L" LastAttemptStatus - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString (EsrtEntry->LastAttemptStatus));
-}
-
-/**
- Dump ESRT table.
-
- @param[in] Esrt ESRT table
-**/
-VOID
-DumpEsrt (
- IN EFI_SYSTEM_RESOURCE_TABLE *Esrt
- )
-{
- UINTN Index;
- EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
-
- if (Esrt == NULL) {
- return;
- }
-
- Print (L"EFI_SYSTEM_RESOURCE_TABLE:\n");
- Print (L"FwResourceCount - 0x%x\n", Esrt->FwResourceCount);
- Print (L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
- Print (L"FwResourceVersion - 0x%lx\n", Esrt->FwResourceVersion);
-
- EsrtEntry = (VOID *)(Esrt + 1);
- for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
- Print (L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
- DumpEsrtEntry (EsrtEntry);
- EsrtEntry++;
- }
-}
-
-/**
- Dump ESRT info.
-**/
-VOID
-DumpEsrtData (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_SYSTEM_RESOURCE_TABLE *Esrt;
-
- Print (L"##############\n");
- Print (L"# ESRT TABLE #\n");
- Print (L"##############\n");
-
- Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
- if (EFI_ERROR (Status)) {
- Print (L"ESRT - %r\n", Status);
- return;
- }
-
- DumpEsrt (Esrt);
- Print (L"\n");
-}
-
-/**
- Dump capsule information from CapsuleHeader
-
- @param[in] CapsuleHeader The CapsuleHeader of the capsule image.
-
- @retval EFI_SUCCESS The capsule information is dumped.
-
-**/
-EFI_STATUS
-DumpCapsuleFromBuffer (
- IN EFI_CAPSULE_HEADER *CapsuleHeader
- )
-{
- if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
- DumpUxCapsule (CapsuleHeader);
- return EFI_SUCCESS;
- }
-
- if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
- DumpFmpCapsule (CapsuleHeader);
- }
-
- if (IsNestedFmpCapsule (CapsuleHeader)) {
- Print (L"[NestedCapusule]\n");
- Print (L"CapsuleHeader:\n");
- Print (L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid);
- Print (L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize);
- Print (L" Flags - 0x%x\n", CapsuleHeader->Flags);
- Print (L" CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
- DumpFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This routine is called to upper case given unicode string.
-
- @param[in] Str String to upper case
-
- @retval upper cased string after process
-
-**/
-STATIC
-CHAR16 *
-UpperCaseString (
- IN CHAR16 *Str
- )
-{
- CHAR16 *Cptr;
-
- for (Cptr = Str; *Cptr != L'\0'; Cptr++) {
- if ((L'a' <= *Cptr) && (*Cptr <= L'z')) {
- *Cptr = *Cptr - L'a' + L'A';
- }
- }
-
- return Str;
-}
-
-/**
- This routine is used to return substring before period '.' or '\0'
- Caller should respsonsible of substr space allocation & free
-
- @param[in] Str String to check
- @param[out] SubStr First part of string before period or '\0'
- @param[out] SubStrLen Length of first part of string
-
-**/
-STATIC
-VOID
-GetSubStringBeforePeriod (
- IN CHAR16 *Str,
- OUT CHAR16 *SubStr,
- OUT UINTN *SubStrLen
- )
-{
- UINTN Index;
-
- for (Index = 0; Str[Index] != L'.' && Str[Index] != L'\0'; Index++) {
- SubStr[Index] = Str[Index];
- }
-
- SubStr[Index] = L'\0';
- *SubStrLen = Index;
-}
-
-/**
- This routine pad the string in tail with input character.
-
- @param[in] StrBuf Str buffer to be padded, should be enough room for
- @param[in] PadLen Expected padding length
- @param[in] Character Character used to pad
-
-**/
-STATIC
-VOID
-PadStrInTail (
- IN CHAR16 *StrBuf,
- IN UINTN PadLen,
- IN CHAR16 Character
- )
-{
- UINTN Index;
-
- for (Index = 0; StrBuf[Index] != L'\0'; Index++) {
- }
-
- while (PadLen != 0) {
- StrBuf[Index] = Character;
- Index++;
- PadLen--;
- }
-
- StrBuf[Index] = L'\0';
-}
-
-/**
- This routine find the offset of the last period '.' of string. if No period exists
- function FileNameExtension is set to L'\0'
-
- @param[in] FileName File name to split between last period
- @param[out] FileNameFirst First FileName before last period
- @param[out] FileNameExtension FileName after last period
-
-**/
-STATIC
-VOID
-SplitFileNameExtension (
- IN CHAR16 *FileName,
- OUT CHAR16 *FileNameFirst,
- OUT CHAR16 *FileNameExtension
- )
-{
- UINTN Index;
- UINTN StringLen;
-
- StringLen = StrLen (FileName);
- for (Index = StringLen; Index > 0 && FileName[Index] != L'.'; Index--) {
- }
-
- //
- // No period exists. No FileName Extension
- //
- if ((Index == 0) && (FileName[Index] != L'.')) {
- FileNameExtension[0] = L'\0';
- Index = StringLen;
- } else {
- StrCpyS (FileNameExtension, MAX_FILE_NAME_LEN, &FileName[Index+1]);
- }
-
- //
- // Copy First file name
- //
- StrnCpyS (FileNameFirst, MAX_FILE_NAME_LEN, FileName, Index);
- FileNameFirst[Index] = L'\0';
-}
-
-/**
- The function is called by PerformQuickSort to sort file name in alphabet.
-
- @param[in] Left The pointer to first buffer.
- @param[in] Right The pointer to second buffer.
-
- @retval 0 Buffer1 equal to Buffer2.
- @return <0 Buffer1 is less than Buffer2.
- @return >0 Buffer1 is greater than Buffer2.
-
-**/
-INTN
-EFIAPI
-CompareFileNameInAlphabet (
- IN VOID *Left,
- IN VOID *Right
- )
-{
- EFI_FILE_INFO *FileInfo1;
- EFI_FILE_INFO *FileInfo2;
- CHAR16 FileName1[MAX_FILE_NAME_SIZE];
- CHAR16 FileExtension1[MAX_FILE_NAME_SIZE];
- CHAR16 FileName2[MAX_FILE_NAME_SIZE];
- CHAR16 FileExtension2[MAX_FILE_NAME_SIZE];
- CHAR16 TempSubStr1[MAX_FILE_NAME_SIZE];
- CHAR16 TempSubStr2[MAX_FILE_NAME_SIZE];
- UINTN SubStrLen1;
- UINTN SubStrLen2;
- INTN SubStrCmpResult;
-
- FileInfo1 = (EFI_FILE_INFO *)(*(UINTN *)Left);
- FileInfo2 = (EFI_FILE_INFO *)(*(UINTN *)Right);
-
- SplitFileNameExtension (FileInfo1->FileName, FileName1, FileExtension1);
- SplitFileNameExtension (FileInfo2->FileName, FileName2, FileExtension2);
-
- UpperCaseString (FileName1);
- UpperCaseString (FileName2);
-
- GetSubStringBeforePeriod (FileName1, TempSubStr1, &SubStrLen1);
- GetSubStringBeforePeriod (FileName2, TempSubStr2, &SubStrLen2);
-
- if (SubStrLen1 > SubStrLen2) {
- //
- // Substr in NewFileName is longer. Pad tail with SPACE
- //
- PadStrInTail (TempSubStr2, SubStrLen1 - SubStrLen2, L' ');
- } else if (SubStrLen1 < SubStrLen2) {
- //
- // Substr in ListedFileName is longer. Pad tail with SPACE
- //
- PadStrInTail (TempSubStr1, SubStrLen2 - SubStrLen1, L' ');
- }
-
- SubStrCmpResult = StrnCmp (TempSubStr1, TempSubStr2, MAX_FILE_NAME_LEN);
- if (SubStrCmpResult != 0) {
- return SubStrCmpResult;
- }
-
- UpperCaseString (FileExtension1);
- UpperCaseString (FileExtension2);
-
- return StrnCmp (FileExtension1, FileExtension2, MAX_FILE_NAME_LEN);
-}
-
-/**
- Dump capsule information from disk.
-
- @param[in] Fs The device path of disk.
- @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation.
-
- @retval EFI_SUCCESS The capsule information is dumped.
-
-**/
-EFI_STATUS
-DumpCapsuleFromDisk (
- IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs,
- IN BOOLEAN DumpCapsuleInfo
- )
-{
- EFI_STATUS Status;
- EFI_FILE *Root;
- EFI_FILE *DirHandle;
- EFI_FILE *FileHandle;
- UINTN Index;
- UINTN FileSize;
- VOID *FileBuffer;
- EFI_FILE_INFO **FileInfoBuffer;
- EFI_FILE_INFO *FileInfo;
- UINTN FileCount;
- BOOLEAN NoFile;
-
- DirHandle = NULL;
- FileHandle = NULL;
- Index = 0;
- FileInfoBuffer = NULL;
- FileInfo = NULL;
- FileCount = 0;
- NoFile = FALSE;
-
- Status = Fs->OpenVolume (Fs, &Root);
- if (EFI_ERROR (Status)) {
- Print (L"Cannot open volume. Status = %r\n", Status);
- goto Done;
- }
-
- Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
- if (EFI_ERROR (Status)) {
- Print (L"Cannot open %s. Status = %r\n", EFI_CAPSULE_FILE_DIRECTORY, Status);
- goto Done;
- }
-
- //
- // Get file count first
- //
- Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
- do {
- if (EFI_ERROR (Status) || (FileInfo == NULL)) {
- Print (L"Get File Info Fail. Status = %r\n", Status);
- goto Done;
- }
-
- if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {
- FileCount++;
- }
-
- Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);
- if (EFI_ERROR (Status)) {
- Print (L"Get Next File Fail. Status = %r\n", Status);
- goto Done;
- }
- } while (!NoFile);
-
- if (FileCount == 0) {
- Print (L"Error: No capsule file found!\n");
- Status = EFI_NOT_FOUND;
- goto Done;
- }
-
- FileInfoBuffer = AllocateZeroPool (sizeof (FileInfo) * FileCount);
- if (FileInfoBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- NoFile = FALSE;
-
- //
- // Get all file info
- //
- Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
- do {
- if (EFI_ERROR (Status) || (FileInfo == NULL)) {
- Print (L"Get File Info Fail. Status = %r\n", Status);
- goto Done;
- }
-
- if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {
- FileInfoBuffer[Index++] = AllocateCopyPool ((UINTN)FileInfo->Size, FileInfo);
- }
-
- Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);
- if (EFI_ERROR (Status)) {
- Print (L"Get Next File Fail. Status = %r\n", Status);
- goto Done;
- }
- } while (!NoFile);
-
- //
- // Sort FileInfoBuffer by alphabet order
- //
- PerformQuickSort (
- FileInfoBuffer,
- FileCount,
- sizeof (FileInfo),
- (SORT_COMPARE)CompareFileNameInAlphabet
- );
-
- Print (L"The capsules will be performed by following order:\n");
-
- for (Index = 0; Index < FileCount; Index++) {
- Print (L" %d.%s\n", Index + 1, FileInfoBuffer[Index]->FileName);
- }
-
- if (!DumpCapsuleInfo) {
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- Print (L"The infomation of the capsules:\n");
-
- for (Index = 0; Index < FileCount; Index++) {
- FileHandle = NULL;
- Status = DirHandle->Open (DirHandle, &FileHandle, FileInfoBuffer[Index]->FileName, EFI_FILE_MODE_READ, 0);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = FileHandleGetSize (FileHandle, (UINT64 *)&FileSize);
- if (EFI_ERROR (Status)) {
- Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
- FileHandleClose (FileHandle);
- goto Done;
- }
-
- FileBuffer = AllocatePool (FileSize);
- if (FileBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- Status = FileHandleRead (FileHandle, &FileSize, FileBuffer);
- if (EFI_ERROR (Status)) {
- Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
- FileHandleClose (FileHandle);
- FreePool (FileBuffer);
- goto Done;
- }
-
- Print (L"**************************\n");
- Print (L" %d.%s:\n", Index + 1, FileInfoBuffer[Index]->FileName);
- Print (L"**************************\n");
- DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *)FileBuffer);
- FileHandleClose (FileHandle);
- FreePool (FileBuffer);
- }
-
-Done:
- if (FileInfoBuffer != NULL) {
- for (Index = 0; Index < FileCount; Index++) {
- if (FileInfoBuffer[Index] != NULL) {
- FreePool (FileInfoBuffer[Index]);
- }
- }
-
- FreePool (FileInfoBuffer);
- }
-
- return Status;
-}
-
-/**
- Dump capsule inforomation form Gather list.
-
- @param[in] BlockDescriptors The block descriptors for the capsule images
- @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation.
-
-**/
-VOID
-DumpBlockDescriptors (
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors,
- IN BOOLEAN DumpCapsuleInfo
- )
-{
- EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr;
-
- TempBlockPtr = BlockDescriptors;
-
- while (TRUE) {
- if (TempBlockPtr->Length != 0) {
- if (DumpCapsuleInfo) {
- Print (L"******************************************************\n");
- }
-
- Print (L"Capsule data starts at 0x%08x with size 0x%08x\n", TempBlockPtr->Union.DataBlock, TempBlockPtr->Length);
- if (DumpCapsuleInfo) {
- Print (L"******************************************************\n");
- DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *)(UINTN)TempBlockPtr->Union.DataBlock);
- }
-
- TempBlockPtr += 1;
- } else {
- if (TempBlockPtr->Union.ContinuationPointer == (UINTN)NULL) {
- break;
- } else {
- TempBlockPtr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)TempBlockPtr->Union.ContinuationPointer;
- }
- }
- }
-}
-
-/**
- Dump Provisioned Capsule.
-
- @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation.
-
-**/
-VOID
-DumpProvisionedCapsule (
- IN BOOLEAN DumpCapsuleInfo
- )
-{
- EFI_STATUS Status;
- CHAR16 CapsuleVarName[30];
- CHAR16 *TempVarName;
- UINTN Index;
- EFI_PHYSICAL_ADDRESS *CapsuleDataPtr64;
- UINT16 *BootNext;
- CHAR16 BootOptionName[20];
- EFI_BOOT_MANAGER_LOAD_OPTION BootNextOptionEntry;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
- EFI_SHELL_PROTOCOL *ShellProtocol;
-
- Index = 0;
- CapsuleDataPtr64 = NULL;
- BootNext = NULL;
-
- ShellProtocol = GetShellProtocol ();
- if (ShellProtocol == NULL) {
- Print (L"Get Shell Protocol Fail\n");
- return;
- }
-
- //
- // Dump capsule provisioned on Memory
- //
- Print (L"#########################\n");
- Print (L"### Capsule on Memory ###\n");
- Print (L"#########################\n");
- StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CHAR16), EFI_CAPSULE_VARIABLE_NAME);
- TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
- while (TRUE) {
- if (Index > 0) {
- UnicodeValueToStringS (
- TempVarName,
- sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),
- 0,
- Index,
- 0
- );
- }
-
- Status = GetVariable2 (
- CapsuleVarName,
- &gEfiCapsuleVendorGuid,
- (VOID **)&CapsuleDataPtr64,
- NULL
- );
- if (EFI_ERROR (Status) || (CapsuleDataPtr64 == NULL)) {
- if (Index == 0) {
- Print (L"No data.\n");
- }
-
- break;
- }
-
- Index++;
- Print (L"Capsule Description at 0x%08x\n", *CapsuleDataPtr64);
- DumpBlockDescriptors ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)*CapsuleDataPtr64, DumpCapsuleInfo);
- }
-
- //
- // Dump capsule provisioned on Disk
- //
- Print (L"#########################\n");
- Print (L"### Capsule on Disk #####\n");
- Print (L"#########################\n");
- Status = GetVariable2 (
- L"BootNext",
- &gEfiGlobalVariableGuid,
- (VOID **)&BootNext,
- NULL
- );
- if (EFI_ERROR (Status) || (BootNext == NULL)) {
- Print (L"Get BootNext Variable Fail. Status = %r\n", Status);
- } else {
- UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", *BootNext);
- Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOptionEntry);
- if (!EFI_ERROR (Status)) {
- //
- // Display description and device path
- //
- GetEfiSysPartitionFromBootOptionFilePath (BootNextOptionEntry.FilePath, &DevicePath, &Fs);
- if (!EFI_ERROR (Status)) {
- Print (L"Capsules are provisioned on BootOption: %s\n", BootNextOptionEntry.Description);
- Print (L" %s %s\n", ShellProtocol->GetMapFromDevicePath (&DevicePath), ConvertDevicePathToText (DevicePath, TRUE, TRUE));
- DumpCapsuleFromDisk (Fs, DumpCapsuleInfo);
- }
- }
- }
-}
-
-/**
- Dump FMP information.
-
- @param[in] ImageInfoSize The size of ImageInfo, in bytes.
- @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
- @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
- @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
- @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
- @param[in] PackageVersion The version of package.
- @param[in] PackageVersionName The version name of package.
-**/
-VOID
-DumpFmpImageInfo (
- IN UINTN ImageInfoSize,
- IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
- IN UINT32 DescriptorVersion,
- IN UINT8 DescriptorCount,
- IN UINTN DescriptorSize,
- IN UINT32 PackageVersion,
- IN CHAR16 *PackageVersionName
- )
-{
- EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo;
- UINTN Index;
- UINTN Index2;
-
- Print (L" DescriptorVersion - 0x%x\n", DescriptorVersion);
- Print (L" DescriptorCount - 0x%x\n", DescriptorCount);
- Print (L" DescriptorSize - 0x%x\n", DescriptorSize);
- Print (L" PackageVersion - 0x%x\n", PackageVersion);
- Print (L" PackageVersionName - \"%s\"\n", PackageVersionName);
- CurrentImageInfo = ImageInfo;
- for (Index = 0; Index < DescriptorCount; Index++) {
- Print (L" ImageDescriptor (%d)\n", Index);
- Print (L" ImageIndex - 0x%x\n", CurrentImageInfo->ImageIndex);
- Print (L" ImageTypeId - %g\n", &CurrentImageInfo->ImageTypeId);
- Print (L" ImageId - 0x%lx\n", CurrentImageInfo->ImageId);
- Print (L" ImageIdName - \"%s\"\n", CurrentImageInfo->ImageIdName);
- Print (L" Version - 0x%x\n", CurrentImageInfo->Version);
- Print (L" VersionName - \"%s\"\n", CurrentImageInfo->VersionName);
- Print (L" Size - 0x%x\n", CurrentImageInfo->Size);
- Print (L" AttributesSupported - 0x%lx\n", CurrentImageInfo->AttributesSupported);
- Print (L" IMAGE_UPDATABLE - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
- Print (L" RESET_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
- Print (L" AUTHENTICATION_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
- Print (L" IN_USE - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
- Print (L" UEFI_IMAGE - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
- Print (L" AttributesSetting - 0x%lx\n", CurrentImageInfo->AttributesSetting);
- Print (L" IMAGE_UPDATABLE - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
- Print (L" RESET_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
- Print (L" AUTHENTICATION_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
- Print (L" IN_USE - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
- Print (L" UEFI_IMAGE - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
- Print (L" Compatibilities - 0x%lx\n", CurrentImageInfo->Compatibilities);
- Print (L" COMPATIB_CHECK_SUPPORTED - 0x%lx\n", CurrentImageInfo->Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
- if (DescriptorVersion > 1) {
- Print (L" LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion);
- if (DescriptorVersion > 2) {
- Print (L" LastAttemptVersion - 0x%x\n", CurrentImageInfo->LastAttemptVersion);
- Print (L" LastAttemptStatus - 0x%x (%a)\n", CurrentImageInfo->LastAttemptStatus, LastAttemptStatusToString (CurrentImageInfo->LastAttemptStatus));
- Print (L" HardwareInstance - 0x%lx\n", CurrentImageInfo->HardwareInstance);
- if (DescriptorVersion > 3) {
- Print (L" Dependencies - ");
- if (CurrentImageInfo->Dependencies == NULL) {
- Print (L"NULL\n");
- } else {
- Index2 = 0;
- do {
- Print (L"%02x ", CurrentImageInfo->Dependencies->Dependencies[Index2]);
- } while (CurrentImageInfo->Dependencies->Dependencies[Index2++] != EFI_FMP_DEP_END);
-
- Print (L"\n");
- }
- }
- }
- }
-
- //
- // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
- //
- CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
- }
-}
-
-/**
- Dump FMP package information.
-
- @param[in] PackageVersion The version of package.
- @param[in] PackageVersionName The version name of package.
- @param[in] PackageVersionNameMaxLen The maximum length of PackageVersionName.
- @param[in] AttributesSupported Package attributes that are supported by this device.
- @param[in] AttributesSetting Package attributes.
-**/
-VOID
-DumpFmpPackageInfo (
- IN UINT32 PackageVersion,
- IN CHAR16 *PackageVersionName,
- IN UINT32 PackageVersionNameMaxLen,
- IN UINT64 AttributesSupported,
- IN UINT64 AttributesSetting
- )
-{
- Print (L" PackageVersion - 0x%x\n", PackageVersion);
- Print (L" PackageVersionName - \"%s\"\n", PackageVersionName);
- Print (L" PackageVersionNameMaxLen - 0x%x\n", PackageVersionNameMaxLen);
- Print (L" AttributesSupported - 0x%lx\n", AttributesSupported);
- Print (L" IMAGE_UPDATABLE - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
- Print (L" RESET_REQUIRED - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
- Print (L" AUTHENTICATION_REQUIRED - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
- Print (L" AttributesSetting - 0x%lx\n", AttributesSetting);
- Print (L" IMAGE_UPDATABLE - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
- Print (L" RESET_REQUIRED - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
- Print (L" AUTHENTICATION_REQUIRED - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
-}
-
-/**
- Dump FMP protocol info.
-**/
-VOID
-DumpFmpData (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
- EFI_HANDLE *HandleBuffer;
- UINTN NumberOfHandles;
- UINTN Index;
- EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
- UINTN ImageInfoSize;
- UINT32 FmpImageInfoDescriptorVer;
- UINT8 FmpImageInfoCount;
- UINTN DescriptorSize;
- UINT32 PackageVersion;
- CHAR16 *PackageVersionName;
- UINT32 PackageVersionNameMaxLen;
- UINT64 AttributesSupported;
- UINT64 AttributesSetting;
-
- Print (L"############\n");
- Print (L"# FMP DATA #\n");
- Print (L"############\n");
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiFirmwareManagementProtocolGuid,
- NULL,
- &NumberOfHandles,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- Print (L"FMP protocol - %r\n", EFI_NOT_FOUND);
- return;
- }
-
- for (Index = 0; Index < NumberOfHandles; Index++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiFirmwareManagementProtocolGuid,
- (VOID **)&Fmp
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- ImageInfoSize = 0;
- Status = Fmp->GetImageInfo (
- Fmp,
- &ImageInfoSize,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- );
- if (Status != EFI_BUFFER_TOO_SMALL) {
- continue;
- }
-
- FmpImageInfoBuf = NULL;
- FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
- if (FmpImageInfoBuf == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto EXIT;
- }
-
- PackageVersionName = NULL;
- Status = Fmp->GetImageInfo (
- Fmp,
- &ImageInfoSize, // ImageInfoSize
- FmpImageInfoBuf, // ImageInfo
- &FmpImageInfoDescriptorVer, // DescriptorVersion
- &FmpImageInfoCount, // DescriptorCount
- &DescriptorSize, // DescriptorSize
- &PackageVersion, // PackageVersion
- &PackageVersionName // PackageVersionName
- );
-
- //
- // If FMP GetInformation interface failed, skip this resource
- //
- if (EFI_ERROR (Status)) {
- Print (L"FMP (%d) ImageInfo - %r\n", Index, Status);
- FreePool (FmpImageInfoBuf);
- continue;
- }
-
- Print (L"FMP (%d) ImageInfo:\n", Index);
- DumpFmpImageInfo (
- ImageInfoSize, // ImageInfoSize
- FmpImageInfoBuf, // ImageInfo
- FmpImageInfoDescriptorVer, // DescriptorVersion
- FmpImageInfoCount, // DescriptorCount
- DescriptorSize, // DescriptorSize
- PackageVersion, // PackageVersion
- PackageVersionName // PackageVersionName
- );
-
- if (PackageVersionName != NULL) {
- FreePool (PackageVersionName);
- }
-
- FreePool (FmpImageInfoBuf);
-
- //
- // Get package info
- //
- PackageVersionName = NULL;
- Status = Fmp->GetPackageInfo (
- Fmp,
- &PackageVersion, // PackageVersion
- &PackageVersionName, // PackageVersionName
- &PackageVersionNameMaxLen, // PackageVersionNameMaxLen
- &AttributesSupported, // AttributesSupported
- &AttributesSetting // AttributesSetting
- );
- if (EFI_ERROR (Status)) {
- Print (L"FMP (%d) PackageInfo - %r\n", Index, Status);
- } else {
- Print (L"FMP (%d) ImageInfo:\n", Index);
- DumpFmpPackageInfo (
- PackageVersion, // PackageVersion
- PackageVersionName, // PackageVersionName
- PackageVersionNameMaxLen, // PackageVersionNameMaxLen
- AttributesSupported, // AttributesSupported
- AttributesSetting // AttributesSetting
- );
-
- if (PackageVersionName != NULL) {
- FreePool (PackageVersionName);
- }
- }
- }
-
- Print (L"\n");
-
-EXIT:
- FreePool (HandleBuffer);
-}
-
-/**
- Check if the ImageInfo includes the ImageTypeId.
-
- @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
- @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
- @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
- @param[in] ImageTypeId A unique GUID identifying the firmware image type.
-
- @return TRUE This ImageInfo includes the ImageTypeId
- @return FALSE This ImageInfo does not include the ImageTypeId
-**/
-BOOLEAN
-IsThisFmpImageInfo (
- IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
- IN UINT8 DescriptorCount,
- IN UINTN DescriptorSize,
- IN EFI_GUID *ImageTypeId
- )
-{
- EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo;
- UINTN Index;
-
- CurrentImageInfo = ImageInfo;
- for (Index = 0; Index < DescriptorCount; Index++) {
- if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) {
- return TRUE;
- }
-
- CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
- }
-
- return FALSE;
-}
-
-/**
- return the FMP whoes ImageInfo includes the ImageTypeId.
-
- @param[in] ImageTypeId A unique GUID identifying the firmware image type.
-
- @return The FMP whoes ImageInfo includes the ImageTypeId
-**/
-EFI_FIRMWARE_MANAGEMENT_PROTOCOL *
-FindFmpFromImageTypeId (
- IN EFI_GUID *ImageTypeId
- )
-{
- EFI_STATUS Status;
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *TargetFmp;
- EFI_HANDLE *HandleBuffer;
- UINTN NumberOfHandles;
- UINTN Index;
- EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
- UINTN ImageInfoSize;
- UINT32 FmpImageInfoDescriptorVer;
- UINT8 FmpImageInfoCount;
- UINTN DescriptorSize;
- UINT32 PackageVersion;
- CHAR16 *PackageVersionName;
-
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiFirmwareManagementProtocolGuid,
- NULL,
- &NumberOfHandles,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- Print (L"FMP protocol - %r\n", EFI_NOT_FOUND);
- return NULL;
- }
-
- TargetFmp = NULL;
- for (Index = 0; Index < NumberOfHandles; Index++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiFirmwareManagementProtocolGuid,
- (VOID **)&Fmp
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- ImageInfoSize = 0;
- Status = Fmp->GetImageInfo (
- Fmp,
- &ImageInfoSize,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- );
- if (Status != EFI_BUFFER_TOO_SMALL) {
- continue;
- }
-
- FmpImageInfoBuf = NULL;
- FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
- if (FmpImageInfoBuf == NULL) {
- FreePool (HandleBuffer);
- Print (L"Out of resource\n");
- return NULL;
- }
-
- PackageVersionName = NULL;
- Status = Fmp->GetImageInfo (
- Fmp,
- &ImageInfoSize, // ImageInfoSize
- FmpImageInfoBuf, // ImageInfo
- &FmpImageInfoDescriptorVer, // DescriptorVersion
- &FmpImageInfoCount, // DescriptorCount
- &DescriptorSize, // DescriptorSize
- &PackageVersion, // PackageVersion
- &PackageVersionName // PackageVersionName
- );
-
- //
- // If FMP GetInformation interface failed, skip this resource
- //
- if (EFI_ERROR (Status)) {
- FreePool (FmpImageInfoBuf);
- continue;
- }
-
- if (PackageVersionName != NULL) {
- FreePool (PackageVersionName);
- }
-
- if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, DescriptorSize, ImageTypeId)) {
- TargetFmp = Fmp;
- }
-
- FreePool (FmpImageInfoBuf);
- if (TargetFmp != NULL) {
- break;
- }
- }
-
- FreePool (HandleBuffer);
- return TargetFmp;
-}
-
-/**
- Dump FMP image data.
-
- @param[in] ImageTypeId The ImageTypeId of the FMP image.
- It is used to identify the FMP protocol.
- @param[in] ImageIndex The ImageIndex of the FMP image.
- It is the input parameter for FMP->GetImage().
- @param[in] ImageName The file name to hold the output FMP image.
-**/
-VOID
-DumpFmpImage (
- IN EFI_GUID *ImageTypeId,
- IN UINTN ImageIndex,
- IN CHAR16 *ImageName
- )
-{
- EFI_STATUS Status;
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
- VOID *Image;
- UINTN ImageSize;
-
- Fmp = FindFmpFromImageTypeId (ImageTypeId);
- if (Fmp == NULL) {
- Print (L"No FMP include ImageTypeId %g\n", ImageTypeId);
- return;
- }
-
- if (ImageIndex > 0xFF) {
- Print (L"ImageIndex 0x%x too big\n", ImageIndex);
- return;
- }
-
- Image = Fmp;
- ImageSize = 0;
- Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
- if (Status != EFI_BUFFER_TOO_SMALL) {
- Print (L"Fmp->GetImage - %r\n", Status);
- return;
- }
-
- Image = AllocatePool (ImageSize);
- if (Image == NULL) {
- Print (L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES);
- return;
- }
-
- Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
- if (EFI_ERROR (Status)) {
- Print (L"Fmp->GetImage - %r\n", Status);
- return;
- }
-
- Status = WriteFileFromBuffer (ImageName, ImageSize, Image);
- Print (L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status);
-
- FreePool (Image);
-
- return;
-}
+/** @file
+ Dump Capsule image information.
+
+ Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CapsuleApp.h"
+
+/**
+ Validate if it is valid capsule header
+
+ This function assumes the caller provided correct CapsuleHeader pointer
+ and CapsuleSize.
+
+ This function validates the fields in EFI_CAPSULE_HEADER.
+
+ @param[in] CapsuleHeader Points to a capsule header.
+ @param[in] CapsuleSize Size of the whole capsule image.
+
+**/
+BOOLEAN
+IsValidCapsuleHeader (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN UINT64 CapsuleSize
+ );
+
+/**
+ Dump UX capsule information.
+
+ @param[in] CapsuleHeader The UX capsule header
+**/
+VOID
+DumpUxCapsule (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_DISPLAY_CAPSULE *DisplayCapsule;
+
+ DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
+ Print (L"[UxCapsule]\n");
+ Print (L"CapsuleHeader:\n");
+ Print (L" CapsuleGuid - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
+ Print (L" HeaderSize - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
+ Print (L" Flags - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
+ Print (L" CapsuleImageSize - 0x%x\n", DisplayCapsule->CapsuleHeader.CapsuleImageSize);
+ Print (L"ImagePayload:\n");
+ Print (L" Version - 0x%x\n", DisplayCapsule->ImagePayload.Version);
+ Print (L" Checksum - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
+ Print (L" ImageType - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
+ Print (L" Mode - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
+ Print (L" OffsetX - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
+ Print (L" OffsetY - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
+}
+
+/**
+ Dump a non-nested FMP capsule.
+
+ @param[in] CapsuleHeader A pointer to CapsuleHeader
+**/
+VOID
+DumpFmpCapsule (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ UINT64 *ItemOffsetList;
+ UINTN Index;
+ UINTN Count;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *FmpImageHeader;
+
+ Print (L"[FmpCapsule]\n");
+ Print (L"CapsuleHeader:\n");
+ Print (L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid);
+ Print (L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize);
+ Print (L" Flags - 0x%x\n", CapsuleHeader->Flags);
+ Print (L" CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+ Print (L"FmpHeader:\n");
+ Print (L" Version - 0x%x\n", FmpCapsuleHeader->Version);
+ Print (L" EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
+ Print (L" PayloadItemCount - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
+ Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+ for (Index = 0; Index < Count; Index++) {
+ Print (L" Offset[%d] - 0x%x\n", Index, ItemOffsetList[Index]);
+ }
+
+ for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
+ Print (L"FmpPayload[%d] ImageHeader:\n", Index);
+ FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+ Print (L" Version - 0x%x\n", FmpImageHeader->Version);
+ Print (L" UpdateImageTypeId - %g\n", &FmpImageHeader->UpdateImageTypeId);
+ Print (L" UpdateImageIndex - 0x%x\n", FmpImageHeader->UpdateImageIndex);
+ Print (L" UpdateImageSize - 0x%x\n", FmpImageHeader->UpdateImageSize);
+ Print (L" UpdateVendorCodeSize - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
+ if (FmpImageHeader->Version >= 2) {
+ Print (L" UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);
+ if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ Print (L" ImageCapsuleSupport - 0x%lx\n", FmpImageHeader->ImageCapsuleSupport);
+ }
+ }
+ }
+}
+
+/**
+ Return if there is a FMP header below capsule header.
+
+ @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+ @retval TRUE There is a FMP header below capsule header.
+ @retval FALSE There is not a FMP header below capsule header
+**/
+BOOLEAN
+IsNestedFmpCapsule (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_STATUS Status;
+ EFI_SYSTEM_RESOURCE_TABLE *Esrt;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
+ UINTN Index;
+ BOOLEAN EsrtGuidFound;
+ EFI_CAPSULE_HEADER *NestedCapsuleHeader;
+ UINTN NestedCapsuleSize;
+
+ //
+ // Check ESRT
+ //
+ EsrtGuidFound = FALSE;
+ Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
+ if (!EFI_ERROR (Status)) {
+ ASSERT (Esrt != NULL);
+ EsrtEntry = (VOID *)(Esrt + 1);
+ for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
+ if (CompareGuid (&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
+ EsrtGuidFound = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!EsrtGuidFound) {
+ return FALSE;
+ }
+
+ //
+ // Check nested capsule header
+ // FMP GUID after ESRT one
+ //
+ NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+ NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize- (UINTN)NestedCapsuleHeader;
+ if (NestedCapsuleSize < sizeof (EFI_CAPSULE_HEADER)) {
+ return FALSE;
+ }
+
+ if (!CompareGuid (&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Dump capsule information
+
+ @param[in] CapsuleName The name of the capsule image.
+
+ @retval EFI_SUCCESS The capsule information is dumped.
+ @retval EFI_UNSUPPORTED Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsule (
+ IN CHAR16 *CapsuleName
+ )
+{
+ VOID *Buffer;
+ UINTN FileSize;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ EFI_STATUS Status;
+
+ Buffer = NULL;
+ Status = ReadFileToBuffer (CapsuleName, &FileSize, &Buffer);
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
+ goto Done;
+ }
+
+ if (!IsValidCapsuleHeader (Buffer, FileSize)) {
+ Print (L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ CapsuleHeader = Buffer;
+ if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
+ DumpUxCapsule (CapsuleHeader);
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+ DumpFmpCapsule (CapsuleHeader);
+ }
+
+ if (IsNestedFmpCapsule (CapsuleHeader)) {
+ Print (L"[NestedCapsule]\n");
+ Print (L"CapsuleHeader:\n");
+ Print (L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid);
+ Print (L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize);
+ Print (L" Flags - 0x%x\n", CapsuleHeader->Flags);
+ Print (L" CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
+ DumpFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
+ }
+
+Done:
+ if (Buffer != NULL) {
+ FreePool (Buffer);
+ }
+
+ return Status;
+}
+
+/**
+ Dump capsule status variable.
+
+ @retval EFI_SUCCESS The capsule status variable is dumped.
+ @retval EFI_UNSUPPORTED Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsuleStatusVariable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ CHAR16 CapsuleVarName[20];
+ CHAR16 *TempVarName;
+ EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResult;
+ EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultFmp;
+ UINTN CapsuleFileNameSize;
+ CHAR16 CapsuleIndexData[12];
+ CHAR16 *CapsuleIndex;
+ CHAR16 *CapsuleFileName;
+ CHAR16 *CapsuleTarget;
+
+ Status = GetVariable2 (
+ L"CapsuleMax",
+ &gEfiCapsuleReportGuid,
+ (VOID **)&CapsuleIndex,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ ASSERT (CapsuleIndex != NULL);
+ CopyMem (CapsuleIndexData, CapsuleIndex, 11 * sizeof (CHAR16));
+ CapsuleIndexData[11] = 0;
+ Print (L"CapsuleMax - %s\n", CapsuleIndexData);
+ FreePool (CapsuleIndex);
+ }
+
+ Status = GetVariable2 (
+ L"CapsuleLast",
+ &gEfiCapsuleReportGuid,
+ (VOID **)&CapsuleIndex,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ ASSERT (CapsuleIndex != NULL);
+ CopyMem (CapsuleIndexData, CapsuleIndex, 11 * sizeof (CHAR16));
+ CapsuleIndexData[11] = 0;
+ Print (L"CapsuleLast - %s\n", CapsuleIndexData);
+ FreePool (CapsuleIndex);
+ }
+
+ StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CapsuleVarName[0]), L"Capsule");
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+ Index = 0;
+
+ while (TRUE) {
+ UnicodeSPrint (TempVarName, 5 * sizeof (CHAR16), L"%04x", Index);
+
+ Status = GetVariable2 (
+ CapsuleVarName,
+ &gEfiCapsuleReportGuid,
+ (VOID **)&CapsuleResult,
+ NULL
+ );
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ } else if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ ASSERT (CapsuleResult != NULL);
+
+ //
+ // display capsule process status
+ //
+ if (CapsuleResult->VariableTotalSize >= sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
+ Print (L"CapsuleName: %s\n", CapsuleVarName);
+ Print (L" Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
+ Print (L" Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
+ Print (L" Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
+ }
+
+ if (CompareGuid (&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+ if (CapsuleResult->VariableTotalSize >= sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof (CHAR16) * 2) {
+ CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
+ Print (L" Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
+ Print (L" Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
+ Print (L" Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex);
+ Print (L" Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId);
+ CapsuleFileName = (CHAR16 *)(CapsuleResultFmp + 1);
+ Print (L" Capsule FMP CapsuleFileName: \"%s\"\n", CapsuleFileName);
+ CapsuleFileNameSize = StrSize (CapsuleFileName);
+ CapsuleTarget = (CHAR16 *)((UINTN)CapsuleFileName + CapsuleFileNameSize);
+ Print (L" Capsule FMP CapsuleTarget: \"%s\"\n", CapsuleTarget);
+ }
+ }
+
+ FreePool (CapsuleResult);
+
+ Index++;
+ if (Index > 0xFFFF) {
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+CHAR8 *mFwTypeString[] = {
+ "Unknown",
+ "SystemFirmware",
+ "DeviceFirmware",
+ "UefiDriver",
+};
+
+CHAR8 *mLastAttemptStatusString[] = {
+ "Success",
+ "Error: Unsuccessful",
+ "Error: Insufficient Resources",
+ "Error: Incorrect Version",
+ "Error: Invalid Format",
+ "Error: Auth Error",
+ "Error: Power Event AC",
+ "Error: Power Event Battery",
+ "Error: Unsatisfied Dependencies",
+};
+
+/**
+ Convert FwType to a string.
+
+ @param[in] FwType FwType in ESRT
+
+ @return a string for FwType.
+**/
+CHAR8 *
+FwTypeToString (
+ IN UINT32 FwType
+ )
+{
+ if (FwType < sizeof (mFwTypeString) / sizeof (mFwTypeString[0])) {
+ return mFwTypeString[FwType];
+ } else {
+ return "Invalid";
+ }
+}
+
+/**
+ Convert LastAttemptStatus to a string.
+
+ @param[in] LastAttemptStatus LastAttemptStatus in FMP or ESRT
+
+ @return a string for LastAttemptStatus.
+**/
+CHAR8 *
+LastAttemptStatusToString (
+ IN UINT32 LastAttemptStatus
+ )
+{
+ if (LastAttemptStatus < sizeof (mLastAttemptStatusString) / sizeof (mLastAttemptStatusString[0])) {
+ return mLastAttemptStatusString[LastAttemptStatus];
+ } else {
+ return "Error: Unknown";
+ }
+}
+
+/**
+ Dump ESRT entry.
+
+ @param[in] EsrtEntry ESRT entry
+**/
+VOID
+DumpEsrtEntry (
+ IN EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry
+ )
+{
+ Print (L" FwClass - %g\n", &EsrtEntry->FwClass);
+ Print (L" FwType - 0x%x (%a)\n", EsrtEntry->FwType, FwTypeToString (EsrtEntry->FwType));
+ Print (L" FwVersion - 0x%x\n", EsrtEntry->FwVersion);
+ Print (L" LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
+ Print (L" CapsuleFlags - 0x%x\n", EsrtEntry->CapsuleFlags);
+ Print (L" LastAttemptVersion - 0x%x\n", EsrtEntry->LastAttemptVersion);
+ Print (L" LastAttemptStatus - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString (EsrtEntry->LastAttemptStatus));
+}
+
+/**
+ Dump ESRT table.
+
+ @param[in] Esrt ESRT table
+**/
+VOID
+DumpEsrt (
+ IN EFI_SYSTEM_RESOURCE_TABLE *Esrt
+ )
+{
+ UINTN Index;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
+
+ if (Esrt == NULL) {
+ return;
+ }
+
+ Print (L"EFI_SYSTEM_RESOURCE_TABLE:\n");
+ Print (L"FwResourceCount - 0x%x\n", Esrt->FwResourceCount);
+ Print (L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
+ Print (L"FwResourceVersion - 0x%lx\n", Esrt->FwResourceVersion);
+
+ EsrtEntry = (VOID *)(Esrt + 1);
+ for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
+ Print (L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
+ DumpEsrtEntry (EsrtEntry);
+ EsrtEntry++;
+ }
+}
+
+/**
+ Dump ESRT info.
+**/
+VOID
+DumpEsrtData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_SYSTEM_RESOURCE_TABLE *Esrt;
+
+ Print (L"##############\n");
+ Print (L"# ESRT TABLE #\n");
+ Print (L"##############\n");
+
+ Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
+ if (EFI_ERROR (Status)) {
+ Print (L"ESRT - %r\n", Status);
+ return;
+ }
+
+ DumpEsrt (Esrt);
+ Print (L"\n");
+}
+
+/**
+ Dump capsule information from CapsuleHeader
+
+ @param[in] CapsuleHeader The CapsuleHeader of the capsule image.
+
+ @retval EFI_SUCCESS The capsule information is dumped.
+
+**/
+EFI_STATUS
+DumpCapsuleFromBuffer (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
+ DumpUxCapsule (CapsuleHeader);
+ return EFI_SUCCESS;
+ }
+
+ if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+ DumpFmpCapsule (CapsuleHeader);
+ }
+
+ if (IsNestedFmpCapsule (CapsuleHeader)) {
+ Print (L"[NestedCapusule]\n");
+ Print (L"CapsuleHeader:\n");
+ Print (L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid);
+ Print (L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize);
+ Print (L" Flags - 0x%x\n", CapsuleHeader->Flags);
+ Print (L" CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
+ DumpFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine is called to upper case given unicode string.
+
+ @param[in] Str String to upper case
+
+ @retval upper cased string after process
+
+**/
+STATIC
+CHAR16 *
+UpperCaseString (
+ IN CHAR16 *Str
+ )
+{
+ CHAR16 *Cptr;
+
+ for (Cptr = Str; *Cptr != L'\0'; Cptr++) {
+ if ((L'a' <= *Cptr) && (*Cptr <= L'z')) {
+ *Cptr = *Cptr - L'a' + L'A';
+ }
+ }
+
+ return Str;
+}
+
+/**
+ This routine is used to return substring before period '.' or '\0'
+ Caller should respsonsible of substr space allocation & free
+
+ @param[in] Str String to check
+ @param[out] SubStr First part of string before period or '\0'
+ @param[out] SubStrLen Length of first part of string
+
+**/
+STATIC
+VOID
+GetSubStringBeforePeriod (
+ IN CHAR16 *Str,
+ OUT CHAR16 *SubStr,
+ OUT UINTN *SubStrLen
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Str[Index] != L'.' && Str[Index] != L'\0'; Index++) {
+ SubStr[Index] = Str[Index];
+ }
+
+ SubStr[Index] = L'\0';
+ *SubStrLen = Index;
+}
+
+/**
+ This routine pad the string in tail with input character.
+
+ @param[in] StrBuf Str buffer to be padded, should be enough room for
+ @param[in] PadLen Expected padding length
+ @param[in] Character Character used to pad
+
+**/
+STATIC
+VOID
+PadStrInTail (
+ IN CHAR16 *StrBuf,
+ IN UINTN PadLen,
+ IN CHAR16 Character
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; StrBuf[Index] != L'\0'; Index++) {
+ }
+
+ while (PadLen != 0) {
+ StrBuf[Index] = Character;
+ Index++;
+ PadLen--;
+ }
+
+ StrBuf[Index] = L'\0';
+}
+
+/**
+ This routine find the offset of the last period '.' of string. if No period exists
+ function FileNameExtension is set to L'\0'
+
+ @param[in] FileName File name to split between last period
+ @param[out] FileNameFirst First FileName before last period
+ @param[out] FileNameExtension FileName after last period
+
+**/
+STATIC
+VOID
+SplitFileNameExtension (
+ IN CHAR16 *FileName,
+ OUT CHAR16 *FileNameFirst,
+ OUT CHAR16 *FileNameExtension
+ )
+{
+ UINTN Index;
+ UINTN StringLen;
+
+ StringLen = StrLen (FileName);
+ for (Index = StringLen; Index > 0 && FileName[Index] != L'.'; Index--) {
+ }
+
+ //
+ // No period exists. No FileName Extension
+ //
+ if ((Index == 0) && (FileName[Index] != L'.')) {
+ FileNameExtension[0] = L'\0';
+ Index = StringLen;
+ } else {
+ StrCpyS (FileNameExtension, MAX_FILE_NAME_LEN, &FileName[Index+1]);
+ }
+
+ //
+ // Copy First file name
+ //
+ StrnCpyS (FileNameFirst, MAX_FILE_NAME_LEN, FileName, Index);
+ FileNameFirst[Index] = L'\0';
+}
+
+/**
+ The function is called by PerformQuickSort to sort file name in alphabet.
+
+ @param[in] Left The pointer to first buffer.
+ @param[in] Right The pointer to second buffer.
+
+ @retval 0 Buffer1 equal to Buffer2.
+ @return <0 Buffer1 is less than Buffer2.
+ @return >0 Buffer1 is greater than Buffer2.
+
+**/
+INTN
+EFIAPI
+CompareFileNameInAlphabet (
+ IN VOID *Left,
+ IN VOID *Right
+ )
+{
+ EFI_FILE_INFO *FileInfo1;
+ EFI_FILE_INFO *FileInfo2;
+ CHAR16 FileName1[MAX_FILE_NAME_SIZE];
+ CHAR16 FileExtension1[MAX_FILE_NAME_SIZE];
+ CHAR16 FileName2[MAX_FILE_NAME_SIZE];
+ CHAR16 FileExtension2[MAX_FILE_NAME_SIZE];
+ CHAR16 TempSubStr1[MAX_FILE_NAME_SIZE];
+ CHAR16 TempSubStr2[MAX_FILE_NAME_SIZE];
+ UINTN SubStrLen1;
+ UINTN SubStrLen2;
+ INTN SubStrCmpResult;
+
+ FileInfo1 = (EFI_FILE_INFO *)(*(UINTN *)Left);
+ FileInfo2 = (EFI_FILE_INFO *)(*(UINTN *)Right);
+
+ SplitFileNameExtension (FileInfo1->FileName, FileName1, FileExtension1);
+ SplitFileNameExtension (FileInfo2->FileName, FileName2, FileExtension2);
+
+ UpperCaseString (FileName1);
+ UpperCaseString (FileName2);
+
+ GetSubStringBeforePeriod (FileName1, TempSubStr1, &SubStrLen1);
+ GetSubStringBeforePeriod (FileName2, TempSubStr2, &SubStrLen2);
+
+ if (SubStrLen1 > SubStrLen2) {
+ //
+ // Substr in NewFileName is longer. Pad tail with SPACE
+ //
+ PadStrInTail (TempSubStr2, SubStrLen1 - SubStrLen2, L' ');
+ } else if (SubStrLen1 < SubStrLen2) {
+ //
+ // Substr in ListedFileName is longer. Pad tail with SPACE
+ //
+ PadStrInTail (TempSubStr1, SubStrLen2 - SubStrLen1, L' ');
+ }
+
+ SubStrCmpResult = StrnCmp (TempSubStr1, TempSubStr2, MAX_FILE_NAME_LEN);
+ if (SubStrCmpResult != 0) {
+ return SubStrCmpResult;
+ }
+
+ UpperCaseString (FileExtension1);
+ UpperCaseString (FileExtension2);
+
+ return StrnCmp (FileExtension1, FileExtension2, MAX_FILE_NAME_LEN);
+}
+
+/**
+ Dump capsule information from disk.
+
+ @param[in] Fs The device path of disk.
+ @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation.
+
+ @retval EFI_SUCCESS The capsule information is dumped.
+
+**/
+EFI_STATUS
+DumpCapsuleFromDisk (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs,
+ IN BOOLEAN DumpCapsuleInfo
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE *Root;
+ EFI_FILE *DirHandle;
+ EFI_FILE *FileHandle;
+ UINTN Index;
+ UINTN FileSize;
+ VOID *FileBuffer;
+ EFI_FILE_INFO **FileInfoBuffer;
+ EFI_FILE_INFO *FileInfo;
+ UINTN FileCount;
+ BOOLEAN NoFile;
+
+ DirHandle = NULL;
+ FileHandle = NULL;
+ Index = 0;
+ FileInfoBuffer = NULL;
+ FileInfo = NULL;
+ FileCount = 0;
+ NoFile = FALSE;
+
+ Status = Fs->OpenVolume (Fs, &Root);
+ if (EFI_ERROR (Status)) {
+ Print (L"Cannot open volume. Status = %r\n", Status);
+ goto Done;
+ }
+
+ Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
+ if (EFI_ERROR (Status)) {
+ Print (L"Cannot open %s. Status = %r\n", EFI_CAPSULE_FILE_DIRECTORY, Status);
+ goto Done;
+ }
+
+ //
+ // Get file count first
+ //
+ Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
+ do {
+ if (EFI_ERROR (Status) || (FileInfo == NULL)) {
+ Print (L"Get File Info Fail. Status = %r\n", Status);
+ goto Done;
+ }
+
+ if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {
+ FileCount++;
+ }
+
+ Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);
+ if (EFI_ERROR (Status)) {
+ Print (L"Get Next File Fail. Status = %r\n", Status);
+ goto Done;
+ }
+ } while (!NoFile);
+
+ if (FileCount == 0) {
+ Print (L"Error: No capsule file found!\n");
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ FileInfoBuffer = AllocateZeroPool (sizeof (FileInfo) * FileCount);
+ if (FileInfoBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ NoFile = FALSE;
+
+ //
+ // Get all file info
+ //
+ Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
+ do {
+ if (EFI_ERROR (Status) || (FileInfo == NULL)) {
+ Print (L"Get File Info Fail. Status = %r\n", Status);
+ goto Done;
+ }
+
+ if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {
+ FileInfoBuffer[Index++] = AllocateCopyPool ((UINTN)FileInfo->Size, FileInfo);
+ }
+
+ Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);
+ if (EFI_ERROR (Status)) {
+ Print (L"Get Next File Fail. Status = %r\n", Status);
+ goto Done;
+ }
+ } while (!NoFile);
+
+ //
+ // Sort FileInfoBuffer by alphabet order
+ //
+ PerformQuickSort (
+ FileInfoBuffer,
+ FileCount,
+ sizeof (FileInfo),
+ (SORT_COMPARE)CompareFileNameInAlphabet
+ );
+
+ Print (L"The capsules will be performed by following order:\n");
+
+ for (Index = 0; Index < FileCount; Index++) {
+ Print (L" %d.%s\n", Index + 1, FileInfoBuffer[Index]->FileName);
+ }
+
+ if (!DumpCapsuleInfo) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ Print (L"The infomation of the capsules:\n");
+
+ for (Index = 0; Index < FileCount; Index++) {
+ FileHandle = NULL;
+ Status = DirHandle->Open (DirHandle, &FileHandle, FileInfoBuffer[Index]->FileName, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = FileHandleGetSize (FileHandle, (UINT64 *)&FileSize);
+ if (EFI_ERROR (Status)) {
+ Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
+ FileHandleClose (FileHandle);
+ goto Done;
+ }
+
+ FileBuffer = AllocatePool (FileSize);
+ if (FileBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = FileHandleRead (FileHandle, &FileSize, FileBuffer);
+ if (EFI_ERROR (Status)) {
+ Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
+ FileHandleClose (FileHandle);
+ FreePool (FileBuffer);
+ goto Done;
+ }
+
+ Print (L"**************************\n");
+ Print (L" %d.%s:\n", Index + 1, FileInfoBuffer[Index]->FileName);
+ Print (L"**************************\n");
+ DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *)FileBuffer);
+ FileHandleClose (FileHandle);
+ FreePool (FileBuffer);
+ }
+
+Done:
+ if (FileInfoBuffer != NULL) {
+ for (Index = 0; Index < FileCount; Index++) {
+ if (FileInfoBuffer[Index] != NULL) {
+ FreePool (FileInfoBuffer[Index]);
+ }
+ }
+
+ FreePool (FileInfoBuffer);
+ }
+
+ return Status;
+}
+
+/**
+ Dump capsule inforomation form Gather list.
+
+ @param[in] BlockDescriptors The block descriptors for the capsule images
+ @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation.
+
+**/
+VOID
+DumpBlockDescriptors (
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors,
+ IN BOOLEAN DumpCapsuleInfo
+ )
+{
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr;
+
+ TempBlockPtr = BlockDescriptors;
+
+ while (TRUE) {
+ if (TempBlockPtr->Length != 0) {
+ if (DumpCapsuleInfo) {
+ Print (L"******************************************************\n");
+ }
+
+ Print (L"Capsule data starts at 0x%08x with size 0x%08x\n", TempBlockPtr->Union.DataBlock, TempBlockPtr->Length);
+ if (DumpCapsuleInfo) {
+ Print (L"******************************************************\n");
+ DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *)(UINTN)TempBlockPtr->Union.DataBlock);
+ }
+
+ TempBlockPtr += 1;
+ } else {
+ if (TempBlockPtr->Union.ContinuationPointer == (UINTN)NULL) {
+ break;
+ } else {
+ TempBlockPtr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)TempBlockPtr->Union.ContinuationPointer;
+ }
+ }
+ }
+}
+
+/**
+ Dump Provisioned Capsule.
+
+ @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation.
+
+**/
+VOID
+DumpProvisionedCapsule (
+ IN BOOLEAN DumpCapsuleInfo
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 CapsuleVarName[30];
+ CHAR16 *TempVarName;
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS *CapsuleDataPtr64;
+ UINT16 *BootNext;
+ CHAR16 BootOptionName[20];
+ EFI_BOOT_MANAGER_LOAD_OPTION BootNextOptionEntry;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
+ EFI_SHELL_PROTOCOL *ShellProtocol;
+
+ Index = 0;
+ CapsuleDataPtr64 = NULL;
+ BootNext = NULL;
+
+ ShellProtocol = GetShellProtocol ();
+ if (ShellProtocol == NULL) {
+ Print (L"Get Shell Protocol Fail\n");
+ return;
+ }
+
+ //
+ // Dump capsule provisioned on Memory
+ //
+ Print (L"#########################\n");
+ Print (L"### Capsule on Memory ###\n");
+ Print (L"#########################\n");
+ StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CHAR16), EFI_CAPSULE_VARIABLE_NAME);
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+ while (TRUE) {
+ if (Index > 0) {
+ UnicodeValueToStringS (
+ TempVarName,
+ sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),
+ 0,
+ Index,
+ 0
+ );
+ }
+
+ Status = GetVariable2 (
+ CapsuleVarName,
+ &gEfiCapsuleVendorGuid,
+ (VOID **)&CapsuleDataPtr64,
+ NULL
+ );
+ if (EFI_ERROR (Status) || (CapsuleDataPtr64 == NULL)) {
+ if (Index == 0) {
+ Print (L"No data.\n");
+ }
+
+ break;
+ }
+
+ Index++;
+ Print (L"Capsule Description at 0x%08x\n", *CapsuleDataPtr64);
+ DumpBlockDescriptors ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)*CapsuleDataPtr64, DumpCapsuleInfo);
+ }
+
+ //
+ // Dump capsule provisioned on Disk
+ //
+ Print (L"#########################\n");
+ Print (L"### Capsule on Disk #####\n");
+ Print (L"#########################\n");
+ Status = GetVariable2 (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ (VOID **)&BootNext,
+ NULL
+ );
+ if (EFI_ERROR (Status) || (BootNext == NULL)) {
+ Print (L"Get BootNext Variable Fail. Status = %r\n", Status);
+ } else {
+ UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", *BootNext);
+ Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOptionEntry);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Display description and device path
+ //
+ GetEfiSysPartitionFromBootOptionFilePath (BootNextOptionEntry.FilePath, &DevicePath, &Fs);
+ if (!EFI_ERROR (Status)) {
+ Print (L"Capsules are provisioned on BootOption: %s\n", BootNextOptionEntry.Description);
+ Print (L" %s %s\n", ShellProtocol->GetMapFromDevicePath (&DevicePath), ConvertDevicePathToText (DevicePath, TRUE, TRUE));
+ DumpCapsuleFromDisk (Fs, DumpCapsuleInfo);
+ }
+ }
+ }
+}
+
+/**
+ Dump FMP information.
+
+ @param[in] ImageInfoSize The size of ImageInfo, in bytes.
+ @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
+ @param[in] PackageVersion The version of package.
+ @param[in] PackageVersionName The version name of package.
+**/
+VOID
+DumpFmpImageInfo (
+ IN UINTN ImageInfoSize,
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
+ IN UINT32 DescriptorVersion,
+ IN UINT8 DescriptorCount,
+ IN UINTN DescriptorSize,
+ IN UINT32 PackageVersion,
+ IN CHAR16 *PackageVersionName
+ )
+{
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo;
+ UINTN Index;
+ UINTN Index2;
+
+ Print (L" DescriptorVersion - 0x%x\n", DescriptorVersion);
+ Print (L" DescriptorCount - 0x%x\n", DescriptorCount);
+ Print (L" DescriptorSize - 0x%x\n", DescriptorSize);
+ Print (L" PackageVersion - 0x%x\n", PackageVersion);
+ Print (L" PackageVersionName - \"%s\"\n", PackageVersionName);
+ CurrentImageInfo = ImageInfo;
+ for (Index = 0; Index < DescriptorCount; Index++) {
+ Print (L" ImageDescriptor (%d)\n", Index);
+ Print (L" ImageIndex - 0x%x\n", CurrentImageInfo->ImageIndex);
+ Print (L" ImageTypeId - %g\n", &CurrentImageInfo->ImageTypeId);
+ Print (L" ImageId - 0x%lx\n", CurrentImageInfo->ImageId);
+ Print (L" ImageIdName - \"%s\"\n", CurrentImageInfo->ImageIdName);
+ Print (L" Version - 0x%x\n", CurrentImageInfo->Version);
+ Print (L" VersionName - \"%s\"\n", CurrentImageInfo->VersionName);
+ Print (L" Size - 0x%x\n", CurrentImageInfo->Size);
+ Print (L" AttributesSupported - 0x%lx\n", CurrentImageInfo->AttributesSupported);
+ Print (L" IMAGE_UPDATABLE - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
+ Print (L" RESET_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
+ Print (L" AUTHENTICATION_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+ Print (L" IN_USE - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
+ Print (L" UEFI_IMAGE - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
+ Print (L" AttributesSetting - 0x%lx\n", CurrentImageInfo->AttributesSetting);
+ Print (L" IMAGE_UPDATABLE - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
+ Print (L" RESET_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
+ Print (L" AUTHENTICATION_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+ Print (L" IN_USE - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
+ Print (L" UEFI_IMAGE - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
+ Print (L" Compatibilities - 0x%lx\n", CurrentImageInfo->Compatibilities);
+ Print (L" COMPATIB_CHECK_SUPPORTED - 0x%lx\n", CurrentImageInfo->Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
+ if (DescriptorVersion > 1) {
+ Print (L" LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion);
+ if (DescriptorVersion > 2) {
+ Print (L" LastAttemptVersion - 0x%x\n", CurrentImageInfo->LastAttemptVersion);
+ Print (L" LastAttemptStatus - 0x%x (%a)\n", CurrentImageInfo->LastAttemptStatus, LastAttemptStatusToString (CurrentImageInfo->LastAttemptStatus));
+ Print (L" HardwareInstance - 0x%lx\n", CurrentImageInfo->HardwareInstance);
+ if (DescriptorVersion > 3) {
+ Print (L" Dependencies - ");
+ if (CurrentImageInfo->Dependencies == NULL) {
+ Print (L"NULL\n");
+ } else {
+ Index2 = 0;
+ do {
+ Print (L"%02x ", CurrentImageInfo->Dependencies->Dependencies[Index2]);
+ } while (CurrentImageInfo->Dependencies->Dependencies[Index2++] != EFI_FMP_DEP_END);
+
+ Print (L"\n");
+ }
+ }
+ }
+ }
+
+ //
+ // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
+ //
+ CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
+ }
+}
+
+/**
+ Dump FMP package information.
+
+ @param[in] PackageVersion The version of package.
+ @param[in] PackageVersionName The version name of package.
+ @param[in] PackageVersionNameMaxLen The maximum length of PackageVersionName.
+ @param[in] AttributesSupported Package attributes that are supported by this device.
+ @param[in] AttributesSetting Package attributes.
+**/
+VOID
+DumpFmpPackageInfo (
+ IN UINT32 PackageVersion,
+ IN CHAR16 *PackageVersionName,
+ IN UINT32 PackageVersionNameMaxLen,
+ IN UINT64 AttributesSupported,
+ IN UINT64 AttributesSetting
+ )
+{
+ Print (L" PackageVersion - 0x%x\n", PackageVersion);
+ Print (L" PackageVersionName - \"%s\"\n", PackageVersionName);
+ Print (L" PackageVersionNameMaxLen - 0x%x\n", PackageVersionNameMaxLen);
+ Print (L" AttributesSupported - 0x%lx\n", AttributesSupported);
+ Print (L" IMAGE_UPDATABLE - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
+ Print (L" RESET_REQUIRED - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
+ Print (L" AUTHENTICATION_REQUIRED - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+ Print (L" AttributesSetting - 0x%lx\n", AttributesSetting);
+ Print (L" IMAGE_UPDATABLE - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
+ Print (L" RESET_REQUIRED - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
+ Print (L" AUTHENTICATION_REQUIRED - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+}
+
+/**
+ Dump FMP protocol info.
+**/
+VOID
+DumpFmpData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ UINTN Index;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
+ UINTN ImageInfoSize;
+ UINT32 FmpImageInfoDescriptorVer;
+ UINT8 FmpImageInfoCount;
+ UINTN DescriptorSize;
+ UINT32 PackageVersion;
+ CHAR16 *PackageVersionName;
+ UINT32 PackageVersionNameMaxLen;
+ UINT64 AttributesSupported;
+ UINT64 AttributesSetting;
+
+ Print (L"############\n");
+ Print (L"# FMP DATA #\n");
+ Print (L"############\n");
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareManagementProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ Print (L"FMP protocol - %r\n", EFI_NOT_FOUND);
+ return;
+ }
+
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareManagementProtocolGuid,
+ (VOID **)&Fmp
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ ImageInfoSize = 0;
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ continue;
+ }
+
+ FmpImageInfoBuf = NULL;
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
+ if (FmpImageInfoBuf == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ PackageVersionName = NULL;
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize, // ImageInfoSize
+ FmpImageInfoBuf, // ImageInfo
+ &FmpImageInfoDescriptorVer, // DescriptorVersion
+ &FmpImageInfoCount, // DescriptorCount
+ &DescriptorSize, // DescriptorSize
+ &PackageVersion, // PackageVersion
+ &PackageVersionName // PackageVersionName
+ );
+
+ //
+ // If FMP GetInformation interface failed, skip this resource
+ //
+ if (EFI_ERROR (Status)) {
+ Print (L"FMP (%d) ImageInfo - %r\n", Index, Status);
+ FreePool (FmpImageInfoBuf);
+ continue;
+ }
+
+ Print (L"FMP (%d) ImageInfo:\n", Index);
+ DumpFmpImageInfo (
+ ImageInfoSize, // ImageInfoSize
+ FmpImageInfoBuf, // ImageInfo
+ FmpImageInfoDescriptorVer, // DescriptorVersion
+ FmpImageInfoCount, // DescriptorCount
+ DescriptorSize, // DescriptorSize
+ PackageVersion, // PackageVersion
+ PackageVersionName // PackageVersionName
+ );
+
+ if (PackageVersionName != NULL) {
+ FreePool (PackageVersionName);
+ }
+
+ FreePool (FmpImageInfoBuf);
+
+ //
+ // Get package info
+ //
+ PackageVersionName = NULL;
+ Status = Fmp->GetPackageInfo (
+ Fmp,
+ &PackageVersion, // PackageVersion
+ &PackageVersionName, // PackageVersionName
+ &PackageVersionNameMaxLen, // PackageVersionNameMaxLen
+ &AttributesSupported, // AttributesSupported
+ &AttributesSetting // AttributesSetting
+ );
+ if (EFI_ERROR (Status)) {
+ Print (L"FMP (%d) PackageInfo - %r\n", Index, Status);
+ } else {
+ Print (L"FMP (%d) ImageInfo:\n", Index);
+ DumpFmpPackageInfo (
+ PackageVersion, // PackageVersion
+ PackageVersionName, // PackageVersionName
+ PackageVersionNameMaxLen, // PackageVersionNameMaxLen
+ AttributesSupported, // AttributesSupported
+ AttributesSetting // AttributesSetting
+ );
+
+ if (PackageVersionName != NULL) {
+ FreePool (PackageVersionName);
+ }
+ }
+ }
+
+ Print (L"\n");
+
+EXIT:
+ FreePool (HandleBuffer);
+}
+
+/**
+ Check if the ImageInfo includes the ImageTypeId.
+
+ @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
+ @param[in] ImageTypeId A unique GUID identifying the firmware image type.
+
+ @return TRUE This ImageInfo includes the ImageTypeId
+ @return FALSE This ImageInfo does not include the ImageTypeId
+**/
+BOOLEAN
+IsThisFmpImageInfo (
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
+ IN UINT8 DescriptorCount,
+ IN UINTN DescriptorSize,
+ IN EFI_GUID *ImageTypeId
+ )
+{
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo;
+ UINTN Index;
+
+ CurrentImageInfo = ImageInfo;
+ for (Index = 0; Index < DescriptorCount; Index++) {
+ if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) {
+ return TRUE;
+ }
+
+ CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
+ }
+
+ return FALSE;
+}
+
+/**
+ return the FMP whoes ImageInfo includes the ImageTypeId.
+
+ @param[in] ImageTypeId A unique GUID identifying the firmware image type.
+
+ @return The FMP whoes ImageInfo includes the ImageTypeId
+**/
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL *
+FindFmpFromImageTypeId (
+ IN EFI_GUID *ImageTypeId
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *TargetFmp;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ UINTN Index;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
+ UINTN ImageInfoSize;
+ UINT32 FmpImageInfoDescriptorVer;
+ UINT8 FmpImageInfoCount;
+ UINTN DescriptorSize;
+ UINT32 PackageVersion;
+ CHAR16 *PackageVersionName;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareManagementProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ Print (L"FMP protocol - %r\n", EFI_NOT_FOUND);
+ return NULL;
+ }
+
+ TargetFmp = NULL;
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareManagementProtocolGuid,
+ (VOID **)&Fmp
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ ImageInfoSize = 0;
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ continue;
+ }
+
+ FmpImageInfoBuf = NULL;
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
+ if (FmpImageInfoBuf == NULL) {
+ FreePool (HandleBuffer);
+ Print (L"Out of resource\n");
+ return NULL;
+ }
+
+ PackageVersionName = NULL;
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize, // ImageInfoSize
+ FmpImageInfoBuf, // ImageInfo
+ &FmpImageInfoDescriptorVer, // DescriptorVersion
+ &FmpImageInfoCount, // DescriptorCount
+ &DescriptorSize, // DescriptorSize
+ &PackageVersion, // PackageVersion
+ &PackageVersionName // PackageVersionName
+ );
+
+ //
+ // If FMP GetInformation interface failed, skip this resource
+ //
+ if (EFI_ERROR (Status)) {
+ FreePool (FmpImageInfoBuf);
+ continue;
+ }
+
+ if (PackageVersionName != NULL) {
+ FreePool (PackageVersionName);
+ }
+
+ if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, DescriptorSize, ImageTypeId)) {
+ TargetFmp = Fmp;
+ }
+
+ FreePool (FmpImageInfoBuf);
+ if (TargetFmp != NULL) {
+ break;
+ }
+ }
+
+ FreePool (HandleBuffer);
+ return TargetFmp;
+}
+
+/**
+ Dump FMP image data.
+
+ @param[in] ImageTypeId The ImageTypeId of the FMP image.
+ It is used to identify the FMP protocol.
+ @param[in] ImageIndex The ImageIndex of the FMP image.
+ It is the input parameter for FMP->GetImage().
+ @param[in] ImageName The file name to hold the output FMP image.
+**/
+VOID
+DumpFmpImage (
+ IN EFI_GUID *ImageTypeId,
+ IN UINTN ImageIndex,
+ IN CHAR16 *ImageName
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ VOID *Image;
+ UINTN ImageSize;
+
+ Fmp = FindFmpFromImageTypeId (ImageTypeId);
+ if (Fmp == NULL) {
+ Print (L"No FMP include ImageTypeId %g\n", ImageTypeId);
+ return;
+ }
+
+ if (ImageIndex > 0xFF) {
+ Print (L"ImageIndex 0x%x too big\n", ImageIndex);
+ return;
+ }
+
+ Image = Fmp;
+ ImageSize = 0;
+ Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ Print (L"Fmp->GetImage - %r\n", Status);
+ return;
+ }
+
+ Image = AllocatePool (ImageSize);
+ if (Image == NULL) {
+ Print (L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES);
+ return;
+ }
+
+ Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
+ if (EFI_ERROR (Status)) {
+ Print (L"Fmp->GetImage - %r\n", Status);
+ return;
+ }
+
+ Status = WriteFileFromBuffer (ImageName, ImageSize, Image);
+ Print (L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status);
+
+ FreePool (Image);
+
+ return;
+}
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c b/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
index 5ce5a50f7b..41e4c21a35 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
@@ -1,857 +1,857 @@
-/** @file
- Process Capsule On Disk.
-
- Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "CapsuleApp.h"
-
-EFI_GUID mCapsuleOnDiskBootOptionGuid = {
- 0x4CC29BB7, 0x2413, 0x40A2, { 0xB0, 0x6D, 0x25, 0x3E, 0x37, 0x10, 0xF5, 0x32 }
-};
-
-/**
- Get file name from file path.
-
- @param FilePath File path.
-
- @return Pointer to file name.
-
-**/
-CHAR16 *
-GetFileNameFromPath (
- CHAR16 *FilePath
- )
-{
- EFI_STATUS Status;
- EFI_SHELL_PROTOCOL *ShellProtocol;
- SHELL_FILE_HANDLE Handle;
- EFI_FILE_INFO *FileInfo;
-
- ShellProtocol = GetShellProtocol ();
- if (ShellProtocol == NULL) {
- return NULL;
- }
-
- //
- // Open file by FileName.
- //
- Status = ShellProtocol->OpenFileByName (
- FilePath,
- &Handle,
- EFI_FILE_MODE_READ
- );
- if (EFI_ERROR (Status)) {
- return NULL;
- }
-
- //
- // Get file name from EFI_FILE_INFO.
- //
- FileInfo = ShellProtocol->GetFileInfo (Handle);
- ShellProtocol->CloseFile (Handle);
- if (FileInfo == NULL) {
- return NULL;
- }
-
- return FileInfo->FileName;
-}
-
-/**
- Check if the device path is EFI system Partition.
-
- @param DevicePath The ESP device path.
-
- @retval TRUE DevicePath is a device path for ESP.
- @retval FALSE DevicePath is not a device path for ESP.
-
-**/
-BOOLEAN
-IsEfiSysPartitionDevicePath (
- EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- HARDDRIVE_DEVICE_PATH *Hd;
- EFI_HANDLE Handle;
-
- //
- // Check if the device path contains GPT node
- //
- TempDevicePath = DevicePath;
-
- while (!IsDevicePathEnd (TempDevicePath)) {
- if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&
- (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP))
- {
- Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;
- if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {
- break;
- }
- }
-
- TempDevicePath = NextDevicePathNode (TempDevicePath);
- }
-
- if (!IsDevicePathEnd (TempDevicePath)) {
- //
- // Search for EFI system partition protocol on full device path in Boot Option
- //
- Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid, &DevicePath, &Handle);
- return EFI_ERROR (Status) ? FALSE : TRUE;
- } else {
- return FALSE;
- }
-}
-
-/**
- Dump all EFI System Partition.
-
-**/
-VOID
-DumpAllEfiSysPartition (
- VOID
- )
-{
- EFI_HANDLE *SimpleFileSystemHandles;
- UINTN NumberSimpleFileSystemHandles;
- UINTN Index;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- UINTN NumberEfiSystemPartitions;
- EFI_SHELL_PROTOCOL *ShellProtocol;
-
- NumberEfiSystemPartitions = 0;
-
- ShellProtocol = GetShellProtocol ();
- if (ShellProtocol == NULL) {
- Print (L"Get Shell Protocol Fail\n");
- return;
- }
-
- Print (L"EFI System Partition list:\n");
-
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimpleFileSystemProtocolGuid,
- NULL,
- &NumberSimpleFileSystemHandles,
- &SimpleFileSystemHandles
- );
-
- for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
- DevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
- if (IsEfiSysPartitionDevicePath (DevicePath)) {
- NumberEfiSystemPartitions++;
- Print (L" %s\n %s\n", ShellProtocol->GetMapFromDevicePath (&DevicePath), ConvertDevicePathToText (DevicePath, TRUE, TRUE));
- }
- }
-
- if (NumberEfiSystemPartitions == 0) {
- Print (L" No ESP found.\n");
- }
-}
-
-/**
- Check if capsule is provisioned.
-
- @retval TRUE Capsule is provisioned previously.
- @retval FALSE No capsule is provisioned.
-
-**/
-BOOLEAN
-IsCapsuleProvisioned (
- VOID
- )
-{
- EFI_STATUS Status;
- UINT64 OsIndication;
- UINTN DataSize;
-
- OsIndication = 0;
- DataSize = sizeof (UINT64);
- Status = gRT->GetVariable (
- L"OsIndications",
- &gEfiGlobalVariableGuid,
- NULL,
- &DataSize,
- &OsIndication
- );
- if (!EFI_ERROR (Status) &&
- ((OsIndication & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0))
- {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Get one active Efi System Partition.
-
- @param[out] FsDevicePath The device path of Fs
- @param[out] Fs The file system within EfiSysPartition
-
- @retval EFI_SUCCESS Get file system successfully
- @retval EFI_NOT_FOUND No valid file system found
-
-**/
-EFI_STATUS
-GetEfiSysPartition (
- OUT EFI_DEVICE_PATH_PROTOCOL **FsDevicePath,
- OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
- )
-{
- EFI_HANDLE *SimpleFileSystemHandles;
- UINTN NumberSimpleFileSystemHandles;
- UINTN Index;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_STATUS Status;
-
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimpleFileSystemProtocolGuid,
- NULL,
- &NumberSimpleFileSystemHandles,
- &SimpleFileSystemHandles
- );
-
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
-
- for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
- DevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
- if (IsEfiSysPartitionDevicePath (DevicePath)) {
- Status = gBS->HandleProtocol (SimpleFileSystemHandles[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)Fs);
- if (!EFI_ERROR (Status)) {
- *FsDevicePath = DevicePath;
- return EFI_SUCCESS;
- }
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Check if Active Efi System Partition within GPT is in the device path.
-
- @param[in] DevicePath The device path
- @param[out] FsDevicePath The device path of Fs
- @param[out] Fs The file system within EfiSysPartition
-
- @retval EFI_SUCCESS Get file system successfully
- @retval EFI_NOT_FOUND No valid file system found
- @retval others Get file system failed
-
-**/
-EFI_STATUS
-GetEfiSysPartitionFromDevPath (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- OUT EFI_DEVICE_PATH_PROTOCOL **FsDevicePath,
- OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- HARDDRIVE_DEVICE_PATH *Hd;
- EFI_HANDLE Handle;
-
- //
- // Check if the device path contains GPT node
- //
- TempDevicePath = DevicePath;
- while (!IsDevicePathEnd (TempDevicePath)) {
- if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&
- (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP))
- {
- Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;
- if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {
- break;
- }
- }
-
- TempDevicePath = NextDevicePathNode (TempDevicePath);
- }
-
- if (!IsDevicePathEnd (TempDevicePath)) {
- //
- // Search for EFI system partition protocol on full device path in Boot Option
- //
- Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid, &DevicePath, &Handle);
-
- //
- // Search for simple file system on this handler
- //
- if (!EFI_ERROR (Status)) {
- Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)Fs);
- if (!EFI_ERROR (Status)) {
- *FsDevicePath = DevicePathFromHandle (Handle);
- return EFI_SUCCESS;
- }
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Get SimpleFileSystem from boot option file path.
-
- @param[in] DevicePath The file path of boot option
- @param[out] FullPath The full device path of boot device
- @param[out] Fs The file system within EfiSysPartition
-
- @retval EFI_SUCCESS Get file system successfully
- @retval EFI_NOT_FOUND No valid file system found
- @retval others Get file system failed
-
-**/
-EFI_STATUS
-GetEfiSysPartitionFromBootOptionFilePath (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
- OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *CurFullPath;
- EFI_DEVICE_PATH_PROTOCOL *PreFullPath;
- EFI_DEVICE_PATH_PROTOCOL *FsFullPath;
-
- CurFullPath = NULL;
- FsFullPath = NULL;
- //
- // Try every full device Path generated from bootoption
- //
- do {
- PreFullPath = CurFullPath;
- CurFullPath = EfiBootManagerGetNextLoadOptionDevicePath (DevicePath, CurFullPath);
-
- if (PreFullPath != NULL) {
- FreePool (PreFullPath);
- }
-
- if (CurFullPath == NULL) {
- //
- // No Active EFI system partition is found in BootOption device path
- //
- Status = EFI_NOT_FOUND;
- break;
- }
-
- DEBUG_CODE_BEGIN ();
- CHAR16 *DevicePathStr;
-
- DevicePathStr = ConvertDevicePathToText (CurFullPath, TRUE, TRUE);
- if (DevicePathStr != NULL) {
- DEBUG ((DEBUG_INFO, "Full device path %s\n", DevicePathStr));
- FreePool (DevicePathStr);
- }
-
- DEBUG_CODE_END ();
-
- Status = GetEfiSysPartitionFromDevPath (CurFullPath, &FsFullPath, Fs);
- } while (EFI_ERROR (Status));
-
- if (*Fs != NULL) {
- *FullPath = FsFullPath;
- return EFI_SUCCESS;
- } else {
- return EFI_NOT_FOUND;
- }
-}
-
-/**
- Get a valid SimpleFileSystem within EFI system partition.
-
- @param[in] Map The FS mapping capsule write to
- @param[out] BootNext The value of BootNext Variable
- @param[out] Fs The file system within EfiSysPartition
- @param[out] UpdateBootNext The flag to indicate whether update BootNext Variable
-
- @retval EFI_SUCCESS Get FS successfully
- @retval EFI_NOT_FOUND No valid FS found
- @retval others Get FS failed
-
-**/
-EFI_STATUS
-GetUpdateFileSystem (
- IN CHAR16 *Map,
- OUT UINT16 *BootNext,
- OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs,
- OUT BOOLEAN *UpdateBootNext
- )
-{
- EFI_STATUS Status;
- CHAR16 BootOptionName[20];
- UINTN Index;
- CONST EFI_DEVICE_PATH_PROTOCOL *MappedDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *FullPath;
- UINT16 *BootNextData;
- EFI_BOOT_MANAGER_LOAD_OPTION BootNextOption;
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptionBuffer;
- UINTN BootOptionCount;
- EFI_SHELL_PROTOCOL *ShellProtocol;
- EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
-
- MappedDevicePath = NULL;
- BootOptionBuffer = NULL;
-
- ShellProtocol = GetShellProtocol ();
- if (ShellProtocol == NULL) {
- Print (L"Get Shell Protocol Fail\n");
- return EFI_NOT_FOUND;
- }
-
- //
- // 1. If Fs is not assigned and there are capsule provisioned before,
- // Get EFI system partition from BootNext.
- //
- if (IsCapsuleProvisioned () && (Map == NULL)) {
- Status = GetVariable2 (
- L"BootNext",
- &gEfiGlobalVariableGuid,
- (VOID **)&BootNextData,
- NULL
- );
- if (EFI_ERROR (Status) || (BootNextData == NULL)) {
- Print (L"Get Boot Next Data Fail. Status = %r\n", Status);
- return EFI_NOT_FOUND;
- } else {
- UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", *BootNextData);
- Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOption);
- if (!EFI_ERROR (Status)) {
- DevicePath = BootNextOption.FilePath;
- Status = GetEfiSysPartitionFromBootOptionFilePath (DevicePath, &FullPath, Fs);
- if (!EFI_ERROR (Status)) {
- *UpdateBootNext = FALSE;
- Print (L"Get EFI system partition from BootNext : %s\n", BootNextOption.Description);
- Print (L"%s %s\n", ShellProtocol->GetMapFromDevicePath (&FullPath), ConvertDevicePathToText (FullPath, TRUE, TRUE));
- return EFI_SUCCESS;
- }
- }
- }
- }
-
- //
- // Check if Map is valid.
- //
- if (Map != NULL) {
- MappedDevicePath = ShellProtocol->GetDevicePathFromMap (Map);
- if (MappedDevicePath == NULL) {
- Print (L"'%s' is not a valid mapping.\n", Map);
- return EFI_INVALID_PARAMETER;
- } else if (!IsEfiSysPartitionDevicePath (DuplicateDevicePath (MappedDevicePath))) {
- Print (L"'%s' is not a EFI System Partition.\n", Map);
- return EFI_INVALID_PARAMETER;
- }
- }
-
- //
- // 2. Get EFI system partition form boot options.
- //
- BootOptionBuffer = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
- if ((BootOptionBuffer == NULL) ||
- ((BootOptionCount == 0) && (Map == NULL))
- )
- {
- return EFI_NOT_FOUND;
- }
-
- for (Index = 0; Index < BootOptionCount; Index++) {
- //
- // Get the boot option from the link list
- //
- DevicePath = BootOptionBuffer[Index].FilePath;
-
- //
- // Skip inactive or legacy boot options
- //
- if (((BootOptionBuffer[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) ||
- (DevicePathType (DevicePath) == BBS_DEVICE_PATH))
- {
- continue;
- }
-
- DEBUG_CODE_BEGIN ();
- CHAR16 *DevicePathStr;
-
- DevicePathStr = ConvertDevicePathToText (DevicePath, TRUE, TRUE);
- if (DevicePathStr != NULL) {
- DEBUG ((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr));
- FreePool (DevicePathStr);
- } else {
- DEBUG ((DEBUG_INFO, "DevicePathToStr failed\n"));
- }
-
- DEBUG_CODE_END ();
-
- Status = GetEfiSysPartitionFromBootOptionFilePath (DevicePath, &FullPath, Fs);
- if (!EFI_ERROR (Status)) {
- if (Map == NULL) {
- *BootNext = (UINT16)BootOptionBuffer[Index].OptionNumber;
- *UpdateBootNext = TRUE;
- Print (L"Found EFI system partition on Boot%04x: %s\n", *BootNext, BootOptionBuffer[Index].Description);
- Print (L"%s %s\n", ShellProtocol->GetMapFromDevicePath (&FullPath), ConvertDevicePathToText (FullPath, TRUE, TRUE));
- return EFI_SUCCESS;
- }
-
- if (StrnCmp (Map, ShellProtocol->GetMapFromDevicePath (&FullPath), StrLen (Map)) == 0) {
- *BootNext = (UINT16)BootOptionBuffer[Index].OptionNumber;
- *UpdateBootNext = TRUE;
- Print (L"Found Boot Option on %s : %s\n", Map, BootOptionBuffer[Index].Description);
- return EFI_SUCCESS;
- }
- }
- }
-
- //
- // 3. If no ESP is found on boot option, try to find a ESP and create boot option for it.
- //
- if (Map != NULL) {
- //
- // If map is assigned, try to get ESP from mapped Fs.
- //
- DevicePath = DuplicateDevicePath (MappedDevicePath);
- Status = GetEfiSysPartitionFromDevPath (DevicePath, &FullPath, Fs);
- if (EFI_ERROR (Status)) {
- Print (L"Error: Cannot get EFI system partition from '%s' - %r\n", Map, Status);
- return EFI_NOT_FOUND;
- }
-
- Print (L"Warning: Cannot find Boot Option on '%s'!\n", Map);
- } else {
- Status = GetEfiSysPartition (&DevicePath, Fs);
- if (EFI_ERROR (Status)) {
- Print (L"Error: Cannot find a EFI system partition!\n");
- return EFI_NOT_FOUND;
- }
- }
-
- Print (L"Create Boot option for capsule on disk:\n");
- Status = EfiBootManagerInitializeLoadOption (
- &NewOption,
- LoadOptionNumberUnassigned,
- LoadOptionTypeBoot,
- LOAD_OPTION_ACTIVE,
- L"UEFI Capsule On Disk",
- DevicePath,
- (UINT8 *)&mCapsuleOnDiskBootOptionGuid,
- sizeof (EFI_GUID)
- );
- if (!EFI_ERROR (Status)) {
- Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN)-1);
- {
- if (!EFI_ERROR (Status)) {
- *UpdateBootNext = TRUE;
- *BootNext = (UINT16)NewOption.OptionNumber;
- Print (L" Boot%04x: %s\n", *BootNext, ConvertDevicePathToText (DevicePath, TRUE, TRUE));
- return EFI_SUCCESS;
- }
- }
- }
-
- Print (L"ERROR: Cannot create boot option! - %r\n", Status);
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Write files to a given SimpleFileSystem.
-
- @param[in] Buffer The buffer array
- @param[in] BufferSize The buffer size array
- @param[in] FileName The file name array
- @param[in] BufferNum The buffer number
- @param[in] Fs The SimpleFileSystem handle to be written
-
- @retval EFI_SUCCESS Write file successfully
- @retval EFI_NOT_FOUND SFS protocol not found
- @retval others Write file failed
-
-**/
-EFI_STATUS
-WriteUpdateFile (
- IN VOID **Buffer,
- IN UINTN *BufferSize,
- IN CHAR16 **FileName,
- IN UINTN BufferNum,
- IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs
- )
-{
- EFI_STATUS Status;
- EFI_FILE *Root;
- EFI_FILE *FileHandle;
- EFI_FILE_PROTOCOL *DirHandle;
- UINT64 FileInfo;
- VOID *Filebuffer;
- UINTN FileSize;
- UINTN Index;
-
- DirHandle = NULL;
- FileHandle = NULL;
- Index = 0;
-
- //
- // Open Root from SFS
- //
- Status = Fs->OpenVolume (Fs, &Root);
- if (EFI_ERROR (Status)) {
- Print (L"Cannot open volume. Status = %r\n", Status);
- return EFI_NOT_FOUND;
- }
-
- //
- // Ensure that efi and updatecapsule directories exist
- //
- Status = Root->Open (Root, &DirHandle, L"\\EFI", EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
- if (EFI_ERROR (Status)) {
- Status = Root->Open (Root, &DirHandle, L"\\EFI", EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, EFI_FILE_DIRECTORY);
- if (EFI_ERROR (Status)) {
- Print (L"Unable to create %s directory\n", L"\\EFI");
- return EFI_NOT_FOUND;
- }
- }
-
- Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
- if (EFI_ERROR (Status)) {
- Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, EFI_FILE_DIRECTORY);
- if (EFI_ERROR (Status)) {
- Print (L"Unable to create %s directory\n", EFI_CAPSULE_FILE_DIRECTORY);
- return EFI_NOT_FOUND;
- }
- }
-
- for (Index = 0; Index < BufferNum; Index++) {
- FileHandle = NULL;
-
- //
- // Open UpdateCapsule file
- //
- Status = DirHandle->Open (DirHandle, &FileHandle, FileName[Index], EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
- if (EFI_ERROR (Status)) {
- Print (L"Unable to create %s file\n", FileName[Index]);
- return EFI_NOT_FOUND;
- }
-
- //
- // Empty the file contents
- //
- Status = FileHandleGetSize (FileHandle, &FileInfo);
- if (EFI_ERROR (Status)) {
- FileHandleClose (FileHandle);
- Print (L"Error Reading %s\n", FileName[Index]);
- return EFI_DEVICE_ERROR;
- }
-
- //
- // If the file size is already 0, then it has been empty.
- //
- if (FileInfo != 0) {
- //
- // Set the file size to 0.
- //
- FileInfo = 0;
- Status = FileHandleSetSize (FileHandle, FileInfo);
- if (EFI_ERROR (Status)) {
- Print (L"Error Deleting %s\n", FileName[Index]);
- FileHandleClose (FileHandle);
- return Status;
- }
- }
-
- //
- // Write Filebuffer to file
- //
- Filebuffer = Buffer[Index];
- FileSize = BufferSize[Index];
- Status = FileHandleWrite (FileHandle, &FileSize, Filebuffer);
- if (EFI_ERROR (Status)) {
- Print (L"Unable to write Capsule Update to %s, Status = %r\n", FileName[Index], Status);
- return EFI_NOT_FOUND;
- }
-
- Print (L"Succeed to write %s\n", FileName[Index]);
- FileHandleClose (FileHandle);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Set capsule status variable.
-
- @param[in] SetCap Set or clear the capsule flag.
-
- @retval EFI_SUCCESS Succeed to set SetCap variable.
- @retval others Fail to set the variable.
-
-**/
-EFI_STATUS
-SetCapsuleStatusVariable (
- BOOLEAN SetCap
- )
-{
- EFI_STATUS Status;
- UINT64 OsIndication;
- UINTN DataSize;
-
- OsIndication = 0;
- DataSize = sizeof (UINT64);
- Status = gRT->GetVariable (
- L"OsIndications",
- &gEfiGlobalVariableGuid,
- NULL,
- &DataSize,
- &OsIndication
- );
- if (EFI_ERROR (Status)) {
- OsIndication = 0;
- }
-
- if (SetCap) {
- OsIndication |= ((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);
- } else {
- OsIndication &= ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);
- }
-
- Status = gRT->SetVariable (
- L"OsIndications",
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- sizeof (UINT64),
- &OsIndication
- );
-
- return Status;
-}
-
-/**
- Check if Capsule On Disk is supported.
-
- @retval TRUE Capsule On Disk is supported.
- @retval FALSE Capsule On Disk is not supported.
-
-**/
-BOOLEAN
-IsCapsuleOnDiskSupported (
- VOID
- )
-{
- EFI_STATUS Status;
- UINT64 OsIndicationsSupported;
- UINTN DataSize;
-
- DataSize = sizeof (UINT64);
- Status = gRT->GetVariable (
- L"OsIndicationsSupported",
- &gEfiGlobalVariableGuid,
- NULL,
- &DataSize,
- &OsIndicationsSupported
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
-
- if ((OsIndicationsSupported & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Process Capsule On Disk.
-
- @param[in] CapsuleBuffer An array of pointer to capsule images
- @param[in] CapsuleBufferSize An array of UINTN to capsule images size
- @param[in] FilePath An array of capsule images file path
- @param[in] Map File system mapping string
- @param[in] CapsuleNum The count of capsule images
-
- @retval EFI_SUCCESS Capsule on disk success.
- @retval others Capsule on disk fail.
-
-**/
-EFI_STATUS
-ProcessCapsuleOnDisk (
- IN VOID **CapsuleBuffer,
- IN UINTN *CapsuleBufferSize,
- IN CHAR16 **FilePath,
- IN CHAR16 *Map,
- IN UINTN CapsuleNum
- )
-{
- EFI_STATUS Status;
- UINT16 BootNext;
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
- BOOLEAN UpdateBootNext;
- CHAR16 *FileName[MAX_CAPSULE_NUM];
- UINTN Index;
-
- //
- // Check if Capsule On Disk is supported
- //
- if (!IsCapsuleOnDiskSupported ()) {
- Print (L"CapsuleApp: Capsule On Disk is not supported.\n");
- return EFI_UNSUPPORTED;
- }
-
- //
- // Get a valid file system from boot path
- //
- Fs = NULL;
-
- Status = GetUpdateFileSystem (Map, &BootNext, &Fs, &UpdateBootNext);
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: cannot find a valid file system on boot devices. Status = %r\n", Status);
- return Status;
- }
-
- //
- // Get file name from file path
- //
- for (Index = 0; Index < CapsuleNum; Index++) {
- FileName[Index] = GetFileNameFromPath (FilePath[Index]);
- }
-
- //
- // Copy capsule image to '\efi\UpdateCapsule\'
- //
- Status = WriteUpdateFile (CapsuleBuffer, CapsuleBufferSize, FileName, CapsuleNum, Fs);
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: capsule image could not be copied for update.\n");
- return Status;
- }
-
- //
- // Set variable then reset
- //
- Status = SetCapsuleStatusVariable (TRUE);
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: unable to set OSIndication variable.\n");
- return Status;
- }
-
- if (UpdateBootNext) {
- Status = gRT->SetVariable (
- L"BootNext",
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- sizeof (UINT16),
- &BootNext
- );
- if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: unable to set BootNext variable.\n");
- return Status;
- }
- }
-
- return EFI_SUCCESS;
-}
+/** @file
+ Process Capsule On Disk.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CapsuleApp.h"
+
+EFI_GUID mCapsuleOnDiskBootOptionGuid = {
+ 0x4CC29BB7, 0x2413, 0x40A2, { 0xB0, 0x6D, 0x25, 0x3E, 0x37, 0x10, 0xF5, 0x32 }
+};
+
+/**
+ Get file name from file path.
+
+ @param FilePath File path.
+
+ @return Pointer to file name.
+
+**/
+CHAR16 *
+GetFileNameFromPath (
+ CHAR16 *FilePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_PROTOCOL *ShellProtocol;
+ SHELL_FILE_HANDLE Handle;
+ EFI_FILE_INFO *FileInfo;
+
+ ShellProtocol = GetShellProtocol ();
+ if (ShellProtocol == NULL) {
+ return NULL;
+ }
+
+ //
+ // Open file by FileName.
+ //
+ Status = ShellProtocol->OpenFileByName (
+ FilePath,
+ &Handle,
+ EFI_FILE_MODE_READ
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ //
+ // Get file name from EFI_FILE_INFO.
+ //
+ FileInfo = ShellProtocol->GetFileInfo (Handle);
+ ShellProtocol->CloseFile (Handle);
+ if (FileInfo == NULL) {
+ return NULL;
+ }
+
+ return FileInfo->FileName;
+}
+
+/**
+ Check if the device path is EFI system Partition.
+
+ @param DevicePath The ESP device path.
+
+ @retval TRUE DevicePath is a device path for ESP.
+ @retval FALSE DevicePath is not a device path for ESP.
+
+**/
+BOOLEAN
+IsEfiSysPartitionDevicePath (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ HARDDRIVE_DEVICE_PATH *Hd;
+ EFI_HANDLE Handle;
+
+ //
+ // Check if the device path contains GPT node
+ //
+ TempDevicePath = DevicePath;
+
+ while (!IsDevicePathEnd (TempDevicePath)) {
+ if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP))
+ {
+ Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;
+ if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {
+ break;
+ }
+ }
+
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+
+ if (!IsDevicePathEnd (TempDevicePath)) {
+ //
+ // Search for EFI system partition protocol on full device path in Boot Option
+ //
+ Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid, &DevicePath, &Handle);
+ return EFI_ERROR (Status) ? FALSE : TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Dump all EFI System Partition.
+
+**/
+VOID
+DumpAllEfiSysPartition (
+ VOID
+ )
+{
+ EFI_HANDLE *SimpleFileSystemHandles;
+ UINTN NumberSimpleFileSystemHandles;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN NumberEfiSystemPartitions;
+ EFI_SHELL_PROTOCOL *ShellProtocol;
+
+ NumberEfiSystemPartitions = 0;
+
+ ShellProtocol = GetShellProtocol ();
+ if (ShellProtocol == NULL) {
+ Print (L"Get Shell Protocol Fail\n");
+ return;
+ }
+
+ Print (L"EFI System Partition list:\n");
+
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &NumberSimpleFileSystemHandles,
+ &SimpleFileSystemHandles
+ );
+
+ for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
+ DevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
+ if (IsEfiSysPartitionDevicePath (DevicePath)) {
+ NumberEfiSystemPartitions++;
+ Print (L" %s\n %s\n", ShellProtocol->GetMapFromDevicePath (&DevicePath), ConvertDevicePathToText (DevicePath, TRUE, TRUE));
+ }
+ }
+
+ if (NumberEfiSystemPartitions == 0) {
+ Print (L" No ESP found.\n");
+ }
+}
+
+/**
+ Check if capsule is provisioned.
+
+ @retval TRUE Capsule is provisioned previously.
+ @retval FALSE No capsule is provisioned.
+
+**/
+BOOLEAN
+IsCapsuleProvisioned (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT64 OsIndication;
+ UINTN DataSize;
+
+ OsIndication = 0;
+ DataSize = sizeof (UINT64);
+ Status = gRT->GetVariable (
+ L"OsIndications",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &DataSize,
+ &OsIndication
+ );
+ if (!EFI_ERROR (Status) &&
+ ((OsIndication & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Get one active Efi System Partition.
+
+ @param[out] FsDevicePath The device path of Fs
+ @param[out] Fs The file system within EfiSysPartition
+
+ @retval EFI_SUCCESS Get file system successfully
+ @retval EFI_NOT_FOUND No valid file system found
+
+**/
+EFI_STATUS
+GetEfiSysPartition (
+ OUT EFI_DEVICE_PATH_PROTOCOL **FsDevicePath,
+ OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
+ )
+{
+ EFI_HANDLE *SimpleFileSystemHandles;
+ UINTN NumberSimpleFileSystemHandles;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &NumberSimpleFileSystemHandles,
+ &SimpleFileSystemHandles
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
+ DevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
+ if (IsEfiSysPartitionDevicePath (DevicePath)) {
+ Status = gBS->HandleProtocol (SimpleFileSystemHandles[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)Fs);
+ if (!EFI_ERROR (Status)) {
+ *FsDevicePath = DevicePath;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Check if Active Efi System Partition within GPT is in the device path.
+
+ @param[in] DevicePath The device path
+ @param[out] FsDevicePath The device path of Fs
+ @param[out] Fs The file system within EfiSysPartition
+
+ @retval EFI_SUCCESS Get file system successfully
+ @retval EFI_NOT_FOUND No valid file system found
+ @retval others Get file system failed
+
+**/
+EFI_STATUS
+GetEfiSysPartitionFromDevPath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT EFI_DEVICE_PATH_PROTOCOL **FsDevicePath,
+ OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ HARDDRIVE_DEVICE_PATH *Hd;
+ EFI_HANDLE Handle;
+
+ //
+ // Check if the device path contains GPT node
+ //
+ TempDevicePath = DevicePath;
+ while (!IsDevicePathEnd (TempDevicePath)) {
+ if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP))
+ {
+ Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;
+ if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {
+ break;
+ }
+ }
+
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+
+ if (!IsDevicePathEnd (TempDevicePath)) {
+ //
+ // Search for EFI system partition protocol on full device path in Boot Option
+ //
+ Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid, &DevicePath, &Handle);
+
+ //
+ // Search for simple file system on this handler
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)Fs);
+ if (!EFI_ERROR (Status)) {
+ *FsDevicePath = DevicePathFromHandle (Handle);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Get SimpleFileSystem from boot option file path.
+
+ @param[in] DevicePath The file path of boot option
+ @param[out] FullPath The full device path of boot device
+ @param[out] Fs The file system within EfiSysPartition
+
+ @retval EFI_SUCCESS Get file system successfully
+ @retval EFI_NOT_FOUND No valid file system found
+ @retval others Get file system failed
+
+**/
+EFI_STATUS
+GetEfiSysPartitionFromBootOptionFilePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
+ OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *CurFullPath;
+ EFI_DEVICE_PATH_PROTOCOL *PreFullPath;
+ EFI_DEVICE_PATH_PROTOCOL *FsFullPath;
+
+ CurFullPath = NULL;
+ FsFullPath = NULL;
+ //
+ // Try every full device Path generated from bootoption
+ //
+ do {
+ PreFullPath = CurFullPath;
+ CurFullPath = EfiBootManagerGetNextLoadOptionDevicePath (DevicePath, CurFullPath);
+
+ if (PreFullPath != NULL) {
+ FreePool (PreFullPath);
+ }
+
+ if (CurFullPath == NULL) {
+ //
+ // No Active EFI system partition is found in BootOption device path
+ //
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ CHAR16 *DevicePathStr;
+
+ DevicePathStr = ConvertDevicePathToText (CurFullPath, TRUE, TRUE);
+ if (DevicePathStr != NULL) {
+ DEBUG ((DEBUG_INFO, "Full device path %s\n", DevicePathStr));
+ FreePool (DevicePathStr);
+ }
+
+ DEBUG_CODE_END ();
+
+ Status = GetEfiSysPartitionFromDevPath (CurFullPath, &FsFullPath, Fs);
+ } while (EFI_ERROR (Status));
+
+ if (*Fs != NULL) {
+ *FullPath = FsFullPath;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+}
+
+/**
+ Get a valid SimpleFileSystem within EFI system partition.
+
+ @param[in] Map The FS mapping capsule write to
+ @param[out] BootNext The value of BootNext Variable
+ @param[out] Fs The file system within EfiSysPartition
+ @param[out] UpdateBootNext The flag to indicate whether update BootNext Variable
+
+ @retval EFI_SUCCESS Get FS successfully
+ @retval EFI_NOT_FOUND No valid FS found
+ @retval others Get FS failed
+
+**/
+EFI_STATUS
+GetUpdateFileSystem (
+ IN CHAR16 *Map,
+ OUT UINT16 *BootNext,
+ OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs,
+ OUT BOOLEAN *UpdateBootNext
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 BootOptionName[20];
+ UINTN Index;
+ CONST EFI_DEVICE_PATH_PROTOCOL *MappedDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *FullPath;
+ UINT16 *BootNextData;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootNextOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptionBuffer;
+ UINTN BootOptionCount;
+ EFI_SHELL_PROTOCOL *ShellProtocol;
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
+
+ MappedDevicePath = NULL;
+ BootOptionBuffer = NULL;
+
+ ShellProtocol = GetShellProtocol ();
+ if (ShellProtocol == NULL) {
+ Print (L"Get Shell Protocol Fail\n");
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // 1. If Fs is not assigned and there are capsule provisioned before,
+ // Get EFI system partition from BootNext.
+ //
+ if (IsCapsuleProvisioned () && (Map == NULL)) {
+ Status = GetVariable2 (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ (VOID **)&BootNextData,
+ NULL
+ );
+ if (EFI_ERROR (Status) || (BootNextData == NULL)) {
+ Print (L"Get Boot Next Data Fail. Status = %r\n", Status);
+ return EFI_NOT_FOUND;
+ } else {
+ UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", *BootNextData);
+ Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOption);
+ if (!EFI_ERROR (Status)) {
+ DevicePath = BootNextOption.FilePath;
+ Status = GetEfiSysPartitionFromBootOptionFilePath (DevicePath, &FullPath, Fs);
+ if (!EFI_ERROR (Status)) {
+ *UpdateBootNext = FALSE;
+ Print (L"Get EFI system partition from BootNext : %s\n", BootNextOption.Description);
+ Print (L"%s %s\n", ShellProtocol->GetMapFromDevicePath (&FullPath), ConvertDevicePathToText (FullPath, TRUE, TRUE));
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ //
+ // Check if Map is valid.
+ //
+ if (Map != NULL) {
+ MappedDevicePath = ShellProtocol->GetDevicePathFromMap (Map);
+ if (MappedDevicePath == NULL) {
+ Print (L"'%s' is not a valid mapping.\n", Map);
+ return EFI_INVALID_PARAMETER;
+ } else if (!IsEfiSysPartitionDevicePath (DuplicateDevicePath (MappedDevicePath))) {
+ Print (L"'%s' is not a EFI System Partition.\n", Map);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // 2. Get EFI system partition form boot options.
+ //
+ BootOptionBuffer = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+ if ((BootOptionBuffer == NULL) ||
+ ((BootOptionCount == 0) && (Map == NULL))
+ )
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < BootOptionCount; Index++) {
+ //
+ // Get the boot option from the link list
+ //
+ DevicePath = BootOptionBuffer[Index].FilePath;
+
+ //
+ // Skip inactive or legacy boot options
+ //
+ if (((BootOptionBuffer[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) ||
+ (DevicePathType (DevicePath) == BBS_DEVICE_PATH))
+ {
+ continue;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ CHAR16 *DevicePathStr;
+
+ DevicePathStr = ConvertDevicePathToText (DevicePath, TRUE, TRUE);
+ if (DevicePathStr != NULL) {
+ DEBUG ((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr));
+ FreePool (DevicePathStr);
+ } else {
+ DEBUG ((DEBUG_INFO, "DevicePathToStr failed\n"));
+ }
+
+ DEBUG_CODE_END ();
+
+ Status = GetEfiSysPartitionFromBootOptionFilePath (DevicePath, &FullPath, Fs);
+ if (!EFI_ERROR (Status)) {
+ if (Map == NULL) {
+ *BootNext = (UINT16)BootOptionBuffer[Index].OptionNumber;
+ *UpdateBootNext = TRUE;
+ Print (L"Found EFI system partition on Boot%04x: %s\n", *BootNext, BootOptionBuffer[Index].Description);
+ Print (L"%s %s\n", ShellProtocol->GetMapFromDevicePath (&FullPath), ConvertDevicePathToText (FullPath, TRUE, TRUE));
+ return EFI_SUCCESS;
+ }
+
+ if (StrnCmp (Map, ShellProtocol->GetMapFromDevicePath (&FullPath), StrLen (Map)) == 0) {
+ *BootNext = (UINT16)BootOptionBuffer[Index].OptionNumber;
+ *UpdateBootNext = TRUE;
+ Print (L"Found Boot Option on %s : %s\n", Map, BootOptionBuffer[Index].Description);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // 3. If no ESP is found on boot option, try to find a ESP and create boot option for it.
+ //
+ if (Map != NULL) {
+ //
+ // If map is assigned, try to get ESP from mapped Fs.
+ //
+ DevicePath = DuplicateDevicePath (MappedDevicePath);
+ Status = GetEfiSysPartitionFromDevPath (DevicePath, &FullPath, Fs);
+ if (EFI_ERROR (Status)) {
+ Print (L"Error: Cannot get EFI system partition from '%s' - %r\n", Map, Status);
+ return EFI_NOT_FOUND;
+ }
+
+ Print (L"Warning: Cannot find Boot Option on '%s'!\n", Map);
+ } else {
+ Status = GetEfiSysPartition (&DevicePath, Fs);
+ if (EFI_ERROR (Status)) {
+ Print (L"Error: Cannot find a EFI system partition!\n");
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ Print (L"Create Boot option for capsule on disk:\n");
+ Status = EfiBootManagerInitializeLoadOption (
+ &NewOption,
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ LOAD_OPTION_ACTIVE,
+ L"UEFI Capsule On Disk",
+ DevicePath,
+ (UINT8 *)&mCapsuleOnDiskBootOptionGuid,
+ sizeof (EFI_GUID)
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN)-1);
+ {
+ if (!EFI_ERROR (Status)) {
+ *UpdateBootNext = TRUE;
+ *BootNext = (UINT16)NewOption.OptionNumber;
+ Print (L" Boot%04x: %s\n", *BootNext, ConvertDevicePathToText (DevicePath, TRUE, TRUE));
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ Print (L"ERROR: Cannot create boot option! - %r\n", Status);
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Write files to a given SimpleFileSystem.
+
+ @param[in] Buffer The buffer array
+ @param[in] BufferSize The buffer size array
+ @param[in] FileName The file name array
+ @param[in] BufferNum The buffer number
+ @param[in] Fs The SimpleFileSystem handle to be written
+
+ @retval EFI_SUCCESS Write file successfully
+ @retval EFI_NOT_FOUND SFS protocol not found
+ @retval others Write file failed
+
+**/
+EFI_STATUS
+WriteUpdateFile (
+ IN VOID **Buffer,
+ IN UINTN *BufferSize,
+ IN CHAR16 **FileName,
+ IN UINTN BufferNum,
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE *Root;
+ EFI_FILE *FileHandle;
+ EFI_FILE_PROTOCOL *DirHandle;
+ UINT64 FileInfo;
+ VOID *Filebuffer;
+ UINTN FileSize;
+ UINTN Index;
+
+ DirHandle = NULL;
+ FileHandle = NULL;
+ Index = 0;
+
+ //
+ // Open Root from SFS
+ //
+ Status = Fs->OpenVolume (Fs, &Root);
+ if (EFI_ERROR (Status)) {
+ Print (L"Cannot open volume. Status = %r\n", Status);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Ensure that efi and updatecapsule directories exist
+ //
+ Status = Root->Open (Root, &DirHandle, L"\\EFI", EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
+ if (EFI_ERROR (Status)) {
+ Status = Root->Open (Root, &DirHandle, L"\\EFI", EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, EFI_FILE_DIRECTORY);
+ if (EFI_ERROR (Status)) {
+ Print (L"Unable to create %s directory\n", L"\\EFI");
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
+ if (EFI_ERROR (Status)) {
+ Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, EFI_FILE_DIRECTORY);
+ if (EFI_ERROR (Status)) {
+ Print (L"Unable to create %s directory\n", EFI_CAPSULE_FILE_DIRECTORY);
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ for (Index = 0; Index < BufferNum; Index++) {
+ FileHandle = NULL;
+
+ //
+ // Open UpdateCapsule file
+ //
+ Status = DirHandle->Open (DirHandle, &FileHandle, FileName[Index], EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR (Status)) {
+ Print (L"Unable to create %s file\n", FileName[Index]);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Empty the file contents
+ //
+ Status = FileHandleGetSize (FileHandle, &FileInfo);
+ if (EFI_ERROR (Status)) {
+ FileHandleClose (FileHandle);
+ Print (L"Error Reading %s\n", FileName[Index]);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // If the file size is already 0, then it has been empty.
+ //
+ if (FileInfo != 0) {
+ //
+ // Set the file size to 0.
+ //
+ FileInfo = 0;
+ Status = FileHandleSetSize (FileHandle, FileInfo);
+ if (EFI_ERROR (Status)) {
+ Print (L"Error Deleting %s\n", FileName[Index]);
+ FileHandleClose (FileHandle);
+ return Status;
+ }
+ }
+
+ //
+ // Write Filebuffer to file
+ //
+ Filebuffer = Buffer[Index];
+ FileSize = BufferSize[Index];
+ Status = FileHandleWrite (FileHandle, &FileSize, Filebuffer);
+ if (EFI_ERROR (Status)) {
+ Print (L"Unable to write Capsule Update to %s, Status = %r\n", FileName[Index], Status);
+ return EFI_NOT_FOUND;
+ }
+
+ Print (L"Succeed to write %s\n", FileName[Index]);
+ FileHandleClose (FileHandle);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set capsule status variable.
+
+ @param[in] SetCap Set or clear the capsule flag.
+
+ @retval EFI_SUCCESS Succeed to set SetCap variable.
+ @retval others Fail to set the variable.
+
+**/
+EFI_STATUS
+SetCapsuleStatusVariable (
+ BOOLEAN SetCap
+ )
+{
+ EFI_STATUS Status;
+ UINT64 OsIndication;
+ UINTN DataSize;
+
+ OsIndication = 0;
+ DataSize = sizeof (UINT64);
+ Status = gRT->GetVariable (
+ L"OsIndications",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &DataSize,
+ &OsIndication
+ );
+ if (EFI_ERROR (Status)) {
+ OsIndication = 0;
+ }
+
+ if (SetCap) {
+ OsIndication |= ((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);
+ } else {
+ OsIndication &= ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);
+ }
+
+ Status = gRT->SetVariable (
+ L"OsIndications",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (UINT64),
+ &OsIndication
+ );
+
+ return Status;
+}
+
+/**
+ Check if Capsule On Disk is supported.
+
+ @retval TRUE Capsule On Disk is supported.
+ @retval FALSE Capsule On Disk is not supported.
+
+**/
+BOOLEAN
+IsCapsuleOnDiskSupported (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT64 OsIndicationsSupported;
+ UINTN DataSize;
+
+ DataSize = sizeof (UINT64);
+ Status = gRT->GetVariable (
+ L"OsIndicationsSupported",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &DataSize,
+ &OsIndicationsSupported
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ if ((OsIndicationsSupported & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Process Capsule On Disk.
+
+ @param[in] CapsuleBuffer An array of pointer to capsule images
+ @param[in] CapsuleBufferSize An array of UINTN to capsule images size
+ @param[in] FilePath An array of capsule images file path
+ @param[in] Map File system mapping string
+ @param[in] CapsuleNum The count of capsule images
+
+ @retval EFI_SUCCESS Capsule on disk success.
+ @retval others Capsule on disk fail.
+
+**/
+EFI_STATUS
+ProcessCapsuleOnDisk (
+ IN VOID **CapsuleBuffer,
+ IN UINTN *CapsuleBufferSize,
+ IN CHAR16 **FilePath,
+ IN CHAR16 *Map,
+ IN UINTN CapsuleNum
+ )
+{
+ EFI_STATUS Status;
+ UINT16 BootNext;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
+ BOOLEAN UpdateBootNext;
+ CHAR16 *FileName[MAX_CAPSULE_NUM];
+ UINTN Index;
+
+ //
+ // Check if Capsule On Disk is supported
+ //
+ if (!IsCapsuleOnDiskSupported ()) {
+ Print (L"CapsuleApp: Capsule On Disk is not supported.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get a valid file system from boot path
+ //
+ Fs = NULL;
+
+ Status = GetUpdateFileSystem (Map, &BootNext, &Fs, &UpdateBootNext);
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: cannot find a valid file system on boot devices. Status = %r\n", Status);
+ return Status;
+ }
+
+ //
+ // Get file name from file path
+ //
+ for (Index = 0; Index < CapsuleNum; Index++) {
+ FileName[Index] = GetFileNameFromPath (FilePath[Index]);
+ }
+
+ //
+ // Copy capsule image to '\efi\UpdateCapsule\'
+ //
+ Status = WriteUpdateFile (CapsuleBuffer, CapsuleBufferSize, FileName, CapsuleNum, Fs);
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: capsule image could not be copied for update.\n");
+ return Status;
+ }
+
+ //
+ // Set variable then reset
+ //
+ Status = SetCapsuleStatusVariable (TRUE);
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: unable to set OSIndication variable.\n");
+ return Status;
+ }
+
+ if (UpdateBootNext) {
+ Status = gRT->SetVariable (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (UINT16),
+ &BootNext
+ );
+ if (EFI_ERROR (Status)) {
+ Print (L"CapsuleApp: unable to set BootNext variable.\n");
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}