mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-30 17:14:07 +02:00
MdeModulePkg/CapsuleApp: Enhance CapsuleApp to support Capsule-on-Disk
BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=1482 CapsuleApp is used for trigger capsule update. Add -OD option in CapsuleApp to support doing capsule update via storage. Add -F and -L options to support dumping information feature. Finish unit test for -F and -L options. Already verify this feature on Denlow platform, success to update capsule via hard disk with -OD option. Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Hao Wu <hao.a.wu@intel.com> Cc: Zhang Chao B <chao.b.zhang@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Chen A Chen <chen.a.chen@intel.com> Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
This commit is contained in:
parent
d67ade0994
commit
9747329114
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
A shell application that triggers capsule update process.
|
A shell application that triggers capsule update process.
|
||||||
|
|
||||||
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -23,6 +23,7 @@
|
|||||||
#include <Library/PrintLib.h>
|
#include <Library/PrintLib.h>
|
||||||
#include <Library/BmpSupportLib.h>
|
#include <Library/BmpSupportLib.h>
|
||||||
#include <Protocol/GraphicsOutput.h>
|
#include <Protocol/GraphicsOutput.h>
|
||||||
|
#include <Guid/GlobalVariable.h>
|
||||||
#include <Guid/CapsuleReport.h>
|
#include <Guid/CapsuleReport.h>
|
||||||
#include <Guid/SystemResourceTable.h>
|
#include <Guid/SystemResourceTable.h>
|
||||||
#include <Guid/FmpCapsule.h>
|
#include <Guid/FmpCapsule.h>
|
||||||
@ -105,6 +106,46 @@ DumpEsrtData (
|
|||||||
VOID
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Read a file.
|
Read a file.
|
||||||
|
|
||||||
@ -799,19 +840,22 @@ PrintUsage (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
Print(L"CapsuleApp: usage\n");
|
Print(L"CapsuleApp: usage\n");
|
||||||
Print(L" CapsuleApp <Capsule...> [-NR]\n");
|
Print(L" CapsuleApp <Capsule...> [-NR] [-OD [FSx]]\n");
|
||||||
Print(L" CapsuleApp -S\n");
|
Print(L" CapsuleApp -S\n");
|
||||||
Print(L" CapsuleApp -C\n");
|
Print(L" CapsuleApp -C\n");
|
||||||
Print(L" CapsuleApp -P\n");
|
Print(L" CapsuleApp -P\n");
|
||||||
Print(L" CapsuleApp -E\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 -G <BMP> -O <Capsule>\n");
|
||||||
Print(L" CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
|
Print(L" CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
|
||||||
Print(L" CapsuleApp -D <Capsule>\n");
|
Print(L" CapsuleApp -D <Capsule>\n");
|
||||||
Print(L" CapsuleApp -P GET <ImageTypeId> <Index> -O <FileName>\n");
|
Print(L" CapsuleApp -P GET <ImageTypeId> <Index> -O <FileName>\n");
|
||||||
Print(L"Parameter:\n");
|
Print(L"Parameter:\n");
|
||||||
Print(L" -NR: No reset will be triggered for the capsule with\n");
|
Print(L" -NR: No reset will be triggered for the capsule\n");
|
||||||
Print(L" CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without\n");
|
Print(L" with CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without CAPSULE_FLAGS_INITIATE_RESET.\n");
|
||||||
Print(L" CAPSULE_FLAGS_INITIATE_RESET.\n");
|
Print(L" -OD: Delivery of Capsules via file on Mass Storage device.");
|
||||||
Print(L" -S: Dump capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
|
Print(L" -S: Dump capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
|
||||||
Print(L" which is defined in UEFI specification.\n");
|
Print(L" which is defined in UEFI specification.\n");
|
||||||
Print(L" -C: Clear capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
|
Print(L" -C: Clear capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
|
||||||
@ -820,6 +864,8 @@ PrintUsage (
|
|||||||
Print(L" ImageTypeId and Index (decimal format) to a file if 'GET'\n");
|
Print(L" ImageTypeId and Index (decimal format) to a file if 'GET'\n");
|
||||||
Print(L" option is used.\n");
|
Print(L" option is used.\n");
|
||||||
Print(L" -E: Dump UEFI ESRT table info.\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" -G: Convert a BMP file to be an UX capsule,\n");
|
||||||
Print(L" according to Windows Firmware Update document\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" -N: Append a Capsule Header to an existing FMP capsule image\n");
|
||||||
@ -851,7 +897,7 @@ UefiMain (
|
|||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
RETURN_STATUS RStatus;
|
RETURN_STATUS RStatus;
|
||||||
UINTN FileSize[MAX_CAPSULE_NUM];
|
UINTN CapsuleBufferSize[MAX_CAPSULE_NUM];
|
||||||
VOID *CapsuleBuffer[MAX_CAPSULE_NUM];
|
VOID *CapsuleBuffer[MAX_CAPSULE_NUM];
|
||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors;
|
EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors;
|
||||||
EFI_CAPSULE_HEADER *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
|
EFI_CAPSULE_HEADER *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
|
||||||
@ -859,12 +905,20 @@ UefiMain (
|
|||||||
EFI_RESET_TYPE ResetType;
|
EFI_RESET_TYPE ResetType;
|
||||||
BOOLEAN NeedReset;
|
BOOLEAN NeedReset;
|
||||||
BOOLEAN NoReset;
|
BOOLEAN NoReset;
|
||||||
|
BOOLEAN CapsuleOnDisk;
|
||||||
CHAR16 *CapsuleName;
|
CHAR16 *CapsuleName;
|
||||||
|
CHAR16 *CapsuleNames[MAX_CAPSULE_NUM];
|
||||||
|
CHAR16 *MapFsStr;
|
||||||
UINTN CapsuleNum;
|
UINTN CapsuleNum;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
|
UINTN ParaOdIndex;
|
||||||
|
UINTN ParaNrIndex;
|
||||||
EFI_GUID ImageTypeId;
|
EFI_GUID ImageTypeId;
|
||||||
UINTN ImageIndex;
|
UINTN ImageIndex;
|
||||||
|
|
||||||
|
MapFsStr = NULL;
|
||||||
|
CapsuleNum = 0;
|
||||||
|
|
||||||
Status = GetArg();
|
Status = GetArg();
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
Print(L"Please use UEFI SHELL to run this application!\n", Status);
|
Print(L"Please use UEFI SHELL to run this application!\n", Status);
|
||||||
@ -936,6 +990,20 @@ UefiMain (
|
|||||||
return EFI_SUCCESS;
|
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'-') {
|
if (Argv[1][0] == L'-') {
|
||||||
Print(L"CapsuleApp: Unrecognized option(%s).\n", Argv[1]);
|
Print(L"CapsuleApp: Unrecognized option(%s).\n", Argv[1]);
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
@ -943,12 +1011,56 @@ UefiMain (
|
|||||||
|
|
||||||
CapsuleFirstIndex = 1;
|
CapsuleFirstIndex = 1;
|
||||||
NoReset = FALSE;
|
NoReset = FALSE;
|
||||||
if ((Argc > 1) && (StrCmp(Argv[Argc - 1], L"-NR") == 0)) {
|
CapsuleOnDisk = FALSE;
|
||||||
NoReset = TRUE;
|
ParaOdIndex = 0;
|
||||||
CapsuleLastIndex = Argc - 2;
|
ParaNrIndex = 0;
|
||||||
} else {
|
|
||||||
CapsuleLastIndex = Argc - 1;
|
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 != 0) {
|
||||||
|
if (ParaOdIndex == Argc - 1) {
|
||||||
|
MapFsStr = NULL;
|
||||||
|
} else if (ParaOdIndex == Argc - 2) {
|
||||||
|
MapFsStr = Argv[Argc-1];
|
||||||
|
} else {
|
||||||
|
Print (L"CapsuleApp: Invalid Position for -OD Options\n");
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ParaNrIndex != 0) {
|
||||||
|
if (ParaNrIndex + 1 == ParaOdIndex) {
|
||||||
|
CapsuleLastIndex = ParaNrIndex - 1;
|
||||||
|
} else {
|
||||||
|
Print (L"CapsuleApp: Invalid Position for -NR Options\n");
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CapsuleLastIndex = ParaOdIndex - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ParaNrIndex != 0) {
|
||||||
|
if (ParaNrIndex == Argc -1) {
|
||||||
|
CapsuleLastIndex = ParaNrIndex - 1;
|
||||||
|
} else {
|
||||||
|
Print (L"CapsuleApp: Invalid Position for -NR Options\n");
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CapsuleLastIndex = Argc - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
|
CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
|
||||||
|
|
||||||
if (CapsuleFirstIndex > CapsuleLastIndex) {
|
if (CapsuleFirstIndex > CapsuleLastIndex) {
|
||||||
@ -961,26 +1073,27 @@ UefiMain (
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
|
ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
|
||||||
ZeroMem(&FileSize, sizeof(FileSize));
|
ZeroMem(&CapsuleBufferSize, sizeof(CapsuleBufferSize));
|
||||||
BlockDescriptors = NULL;
|
BlockDescriptors = NULL;
|
||||||
|
|
||||||
for (Index = 0; Index < CapsuleNum; Index++) {
|
for (Index = 0; Index < CapsuleNum; Index++) {
|
||||||
CapsuleName = Argv[CapsuleFirstIndex + Index];
|
CapsuleName = Argv[CapsuleFirstIndex + Index];
|
||||||
Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
|
Status = ReadFileToBuffer(CapsuleName, &CapsuleBufferSize[Index], &CapsuleBuffer[Index]);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
|
Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
if (!IsValidCapsuleHeader (CapsuleBuffer[Index], FileSize[Index])) {
|
if (!IsValidCapsuleHeader (CapsuleBuffer[Index], CapsuleBufferSize[Index])) {
|
||||||
Print(L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
|
Print(L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
CapsuleNames[Index] = CapsuleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Every capsule use 2 descriptor 1 for data 1 for end
|
// Every capsule use 2 descriptor 1 for data 1 for end
|
||||||
//
|
//
|
||||||
Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
|
Status = BuildGatherList(CapsuleBuffer, CapsuleBufferSize, CapsuleNum, &BlockDescriptors);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
@ -1007,13 +1120,30 @@ UefiMain (
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Index = 0; Index < CapsuleNum; Index++) {
|
for (Index = 0; Index < CapsuleNum; Index++) {
|
||||||
if (FileSize[Index] > MaxCapsuleSize) {
|
if (CapsuleBufferSize[Index] > MaxCapsuleSize) {
|
||||||
Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n", MaxCapsuleSize);
|
Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n", MaxCapsuleSize);
|
||||||
Status = EFI_UNSUPPORTED;
|
Status = EFI_UNSUPPORTED;
|
||||||
goto Done;
|
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.
|
// Check whether the input capsule image has the flag of persist across system reset.
|
||||||
//
|
//
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
[Sources]
|
[Sources]
|
||||||
CapsuleApp.c
|
CapsuleApp.c
|
||||||
CapsuleDump.c
|
CapsuleDump.c
|
||||||
|
CapsuleOnDisk.c
|
||||||
AppSupport.c
|
AppSupport.c
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
@ -40,16 +41,20 @@
|
|||||||
MdeModulePkg/MdeModulePkg.dec
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
[Guids]
|
[Guids]
|
||||||
|
gEfiGlobalVariableGuid ## CONSUMES ## GUID
|
||||||
gEfiCapsuleReportGuid ## CONSUMES ## GUID
|
gEfiCapsuleReportGuid ## CONSUMES ## GUID
|
||||||
gEfiFmpCapsuleGuid ## CONSUMES ## GUID
|
gEfiFmpCapsuleGuid ## CONSUMES ## GUID
|
||||||
gWindowsUxCapsuleGuid ## CONSUMES ## GUID
|
gWindowsUxCapsuleGuid ## CONSUMES ## GUID
|
||||||
gEfiSystemResourceTableGuid ## CONSUMES ## GUID
|
gEfiSystemResourceTableGuid ## CONSUMES ## GUID
|
||||||
|
gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variable:L"CapsuleUpdateData"
|
||||||
|
gEfiPartTypeSystemPartGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiGraphicsOutputProtocolGuid ## CONSUMES
|
gEfiGraphicsOutputProtocolGuid ## CONSUMES
|
||||||
gEfiFirmwareManagementProtocolGuid ## CONSUMES
|
gEfiFirmwareManagementProtocolGuid ## CONSUMES
|
||||||
gEfiShellParametersProtocolGuid ## CONSUMES
|
gEfiShellParametersProtocolGuid ## CONSUMES
|
||||||
gEfiShellProtocolGuid ## CONSUMES
|
gEfiShellProtocolGuid ## CONSUMES
|
||||||
|
gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
BaseLib
|
BaseLib
|
||||||
@ -61,6 +66,9 @@
|
|||||||
UefiLib
|
UefiLib
|
||||||
PrintLib
|
PrintLib
|
||||||
BmpSupportLib
|
BmpSupportLib
|
||||||
|
FileHandleLib
|
||||||
|
UefiBootManagerLib
|
||||||
|
SortLib
|
||||||
|
|
||||||
[UserExtensions.TianoCore."ExtraFiles"]
|
[UserExtensions.TianoCore."ExtraFiles"]
|
||||||
CapsuleAppExtra.uni
|
CapsuleAppExtra.uni
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
Dump Capsule image information.
|
Dump Capsule image information.
|
||||||
|
|
||||||
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -21,13 +21,26 @@
|
|||||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||||
#include <Library/UefiLib.h>
|
#include <Library/UefiLib.h>
|
||||||
#include <Library/PrintLib.h>
|
#include <Library/PrintLib.h>
|
||||||
|
#include <Library/FileHandleLib.h>
|
||||||
|
#include <Library/SortLib.h>
|
||||||
|
#include <Library/UefiBootManagerLib.h>
|
||||||
|
#include <Library/DevicePathLib.h>
|
||||||
#include <Protocol/FirmwareManagement.h>
|
#include <Protocol/FirmwareManagement.h>
|
||||||
|
#include <Protocol/SimpleFileSystem.h>
|
||||||
|
#include <Protocol/Shell.h>
|
||||||
#include <Guid/ImageAuthentication.h>
|
#include <Guid/ImageAuthentication.h>
|
||||||
#include <Guid/CapsuleReport.h>
|
#include <Guid/CapsuleReport.h>
|
||||||
#include <Guid/SystemResourceTable.h>
|
#include <Guid/SystemResourceTable.h>
|
||||||
#include <Guid/FmpCapsule.h>
|
#include <Guid/FmpCapsule.h>
|
||||||
|
#include <Guid/CapsuleVendor.h>
|
||||||
#include <IndustryStandard/WindowsUxCapsule.h>
|
#include <IndustryStandard/WindowsUxCapsule.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// (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))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Read a file.
|
Read a file.
|
||||||
|
|
||||||
@ -61,6 +74,37 @@ WriteFileFromBuffer (
|
|||||||
IN VOID *Buffer
|
IN VOID *Buffer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get shell protocol.
|
||||||
|
|
||||||
|
@return Pointer to shell protocol.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_SHELL_PROTOCOL *
|
||||||
|
GetShellProtocol (
|
||||||
|
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
|
||||||
|
EFIAPI
|
||||||
|
GetEfiSysPartitionFromBootOptionFilePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||||
|
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
||||||
|
OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Validate if it is valid capsule header
|
Validate if it is valid capsule header
|
||||||
|
|
||||||
@ -123,7 +167,7 @@ DumpFmpCapsule (
|
|||||||
UINTN Count;
|
UINTN Count;
|
||||||
EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *FmpImageHeader;
|
EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *FmpImageHeader;
|
||||||
|
|
||||||
Print(L"[FmpCapusule]\n");
|
Print(L"[FmpCapsule]\n");
|
||||||
Print(L"CapsuleHeader:\n");
|
Print(L"CapsuleHeader:\n");
|
||||||
Print(L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid);
|
Print(L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid);
|
||||||
Print(L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize);
|
Print(L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize);
|
||||||
@ -504,6 +548,496 @@ DumpEsrtData (
|
|||||||
Print(L"\n");
|
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;
|
||||||
|
FileCount = 0;
|
||||||
|
NoFile = FALSE;
|
||||||
|
|
||||||
|
Status = Fs->OpenVolume (Fs, &Root);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Print (L"Cannot open volume. Status = %r\n", Status);
|
||||||
|
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)) {
|
||||||
|
Print (L"Cannot open %s. Status = %r\n", EFI_CAPSULE_FILE_DIRECTORY, Status);
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get file count first
|
||||||
|
//
|
||||||
|
for ( Status = FileHandleFindFirstFile (DirHandle, &FileInfo)
|
||||||
|
; !EFI_ERROR(Status) && !NoFile
|
||||||
|
; Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile)
|
||||||
|
){
|
||||||
|
if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FileCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileCount == 0) {
|
||||||
|
Print (L"Error: No capsule file found!\n");
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInfoBuffer = AllocatePool (sizeof(FileInfo) * FileCount);
|
||||||
|
NoFile = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get all file info
|
||||||
|
//
|
||||||
|
for ( Status = FileHandleFindFirstFile (DirHandle, &FileInfo)
|
||||||
|
; !EFI_ERROR (Status) && !NoFile
|
||||||
|
; Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile)
|
||||||
|
){
|
||||||
|
if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FileInfoBuffer[Index++] = AllocateCopyPool ((UINTN)FileInfo->Size, FileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FileHandleGetSize (FileHandle, (UINT64 *) &FileSize);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
|
||||||
|
FileHandleClose (FileHandle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileBuffer = AllocatePool (FileSize);
|
||||||
|
if (FileBuffer == NULL) {
|
||||||
|
return RETURN_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FileHandleRead (FileHandle, &FileSize, FileBuffer);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
|
||||||
|
FreePool (FileBuffer);
|
||||||
|
FileHandleClose (FileHandle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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;
|
||||||
|
|
||||||
|
ShellProtocol = GetShellProtocol ();
|
||||||
|
|
||||||
|
Index = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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)) {
|
||||||
|
if (Index == 0) {
|
||||||
|
Print (L"No data.\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
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)) {
|
||||||
|
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.
|
Dump FMP information.
|
||||||
|
|
||||||
|
@ -167,6 +167,7 @@
|
|||||||
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
|
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
|
||||||
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
|
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
|
||||||
DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
|
DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
|
||||||
|
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
|
||||||
|
|
||||||
[LibraryClasses.common.MM_STANDALONE]
|
[LibraryClasses.common.MM_STANDALONE]
|
||||||
HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
|
HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
|
||||||
|
Loading…
x
Reference in New Issue
Block a user