Date   

[PATCH 19/45] IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules() interface.

Yao, Jiewen
 

Add NULL ProcessCapsules() interface for DxeCapsuleLib.
IntelFrameworkModulePkg is under maintenance phase.
We stop adding new feature there.
Just add NULL function to make it pass build.

Cc: Jeff Fan <jeff.fan@...>
Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c | 39 +++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c b/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
index fc9b533..c964b2d 100644
--- a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
+++ b/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
@@ -1,7 +1,7 @@
/** @file
Capsule Library instance to process capsule images.

- Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>

This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -515,4 +515,41 @@ ProcessCapsuleImage (
return Status;
}

+/**
+
+ This routine is called to process capsules.
+
+ Caution: This function may receive untrusted input.
+
+ If the current boot mode is NOT BOOT_ON_FLASH_UPDATE, this routine does nothing.
+ If the current boot mode is BOOT_ON_FLASH_UPDATE, the capsules reported in
+ EFI_HOB_UEFI_CAPSULE are processed. If there is no EFI_HOB_UEFI_CAPSULE, this
+ routine does nothing.
+
+ This routine should be called twice in BDS.
+ 1) The first call must be before EndOfDxe. The system capsules is processed.
+ If device capsule FMP protocols are exposted at this time and device FMP
+ capsule has zero EmbeddedDriverCount, the device capsules are processed.
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ 2) The second call must be after EndOfDxe and after ConnectAll, so that all
+ device capsule FMP protocols are exposed.
+ The system capsules are skipped. If the device capsules are NOT processed
+ in first call, they are processed here.
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ @retval EFI_SUCCESS There is no error when processing capsules.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsules(
+ VOID
+ )
+{
+ return EFI_UNSUPPORTED;
+}

--
2.7.4.windows.1


[PATCH 18/45] MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.

Yao, Jiewen
 

Add capsule related component to check build.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/MdeModulePkg.dsc | 24 ++++++++++++++++++++
1 file changed, 24 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 05120c7..2195b84 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -103,6 +103,11 @@
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf

+ EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+ FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+ IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+ PlatformFlashAccessLib|MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
+
[LibraryClasses.EBC.PEIM]
IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf

@@ -126,12 +131,14 @@
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf

[LibraryClasses.common.DXE_RUNTIME_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf

[LibraryClasses.common.SMM_CORE]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
@@ -158,6 +165,7 @@
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf

[LibraryClasses.ARM, LibraryClasses.AARCH64]
#
@@ -187,6 +195,9 @@
[PcdsFixedAtBuild.IPF]
gEfiMdePkgTokenSpaceGuid.PcdIoBlockBaseAddressForIpf|0x0ffffc000000

+[PcdsDynamicExDefault]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+
###################################################################################################
#
# Components Section - list of the modules and components that will be processed by compilation
@@ -408,6 +419,19 @@
MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf

+ MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+ MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+ MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+ MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
+ MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+
+ MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+
+ MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+ MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+ MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+
[Components.IA32, Components.X64, Components.IPF]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
--
2.7.4.windows.1


[PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Yao, Jiewen
 

This CapsuleApp can help perform capsule update in UEFI shell environment.
It can also dump capsule information, capsule status variable, ESRT and FMP.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Application/CapsuleApp/AppSupport.c | 480 +++++++++
MdeModulePkg/Application/CapsuleApp/CapsuleApp.c | 1047 ++++++++++++++++++++
MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf | 71 ++
MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni | 22 +
MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni | 19 +
MdeModulePkg/Application/CapsuleApp/CapsuleDump.c | 840 ++++++++++++++++
6 files changed, 2479 insertions(+)

diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
new file mode 100644
index 0000000..365067d
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
@@ -0,0 +1,480 @@
+/** @file
+ A shell application that triggers capsule update process.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <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 <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Guid/FileInfo.h>
+#include <Guid/Gpt.h>
+
+#define MAX_ARG_NUM 11
+
+UINTN Argc = 0;
+CHAR16 *Argv[MAX_ARG_NUM];
+CHAR16 *ArgBuffer;
+
+/**
+
+ This function parse application ARG.
+
+ @return Status
+**/
+EFI_STATUS
+GetArg (
+ VOID
+ )
+{
+ UINT8 *Data;
+ UINTN DataSize;
+ CHAR16 *Index;
+ CHAR16 *End;
+ CHAR16 *DIndex;
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&LoadedImage
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Data = LoadedImage->LoadOptions;
+ DataSize = LoadedImage->LoadOptionsSize;
+
+ End = (CHAR16*)(UINTN)(Data + DataSize);
+ Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
+ ASSERT_EFI_ERROR (Status);
+ DIndex = ArgBuffer;
+ Argv[Argc++] = ArgBuffer;
+ for (Index = (CHAR16*)Data; Index < End; ) {
+ if (*Index == L' ') {
+ *DIndex = L'\0';
+ if (Argc >= MAX_ARG_NUM) {
+ return EFI_UNSUPPORTED;
+ }
+ Argv[Argc++] = (++ DIndex);
+ while(*Index == L' ') {
+ Index ++;
+ }
+ }
+ (*(DIndex ++)) = (*(Index ++));
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Clear APP ARG.
+**/
+VOID
+CleanArg (
+ VOID
+ )
+{
+ FreePool (Argv[0]);
+}
+
+/**
+ Return File System Volume containing this shell application.
+
+ @return File System Volume containing this shell application.
+**/
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
+GetMyVol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;
+
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->HandleProtocol (
+ LoadedImage->DeviceHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID **)&Vol
+ );
+ if (!EFI_ERROR (Status)) {
+ return Vol;
+ }
+
+ return NULL;
+}
+
+/**
+ Read a file from this volume.
+
+ @param Vol File System Volume
+ @param FileName The file to be read.
+ @param BufferSize The file buffer size
+ @param Buffer The file buffer
+
+ @retval EFI_SUCCESS Read file successfully
+ @retval EFI_NOT_FOUND File not found
+**/
+EFI_STATUS
+ReadFileFromVol (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol,
+ IN CHAR16 *FileName,
+ OUT UINTN *BufferSize,
+ OUT VOID **Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE RootDir;
+ EFI_FILE_HANDLE Handle;
+ UINTN FileInfoSize;
+ EFI_FILE_INFO *FileInfo;
+ UINTN TempBufferSize;
+ VOID *TempBuffer;
+
+ //
+ // Open the root directory
+ //
+ Status = Vol->OpenVolume (Vol, &RootDir);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open the file
+ //
+ Status = RootDir->Open (
+ RootDir,
+ &Handle,
+ FileName,
+ EFI_FILE_MODE_READ,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ RootDir->Close (RootDir);
+ return Status;
+ }
+
+ RootDir->Close (RootDir);
+
+ //
+ // Get the file information
+ //
+ FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
+
+ FileInfo = AllocateZeroPool (FileInfoSize);
+ if (FileInfo == NULL) {
+ Handle->Close (Handle);
+ return Status;
+ }
+
+ Status = Handle->GetInfo (
+ Handle,
+ &gEfiFileInfoGuid,
+ &FileInfoSize,
+ FileInfo
+ );
+ if (EFI_ERROR (Status)) {
+ Handle->Close (Handle);
+ gBS->FreePool (FileInfo);
+ return Status;
+ }
+
+ //
+ // Allocate buffer for the file data. The last CHAR16 is for L'\0'
+ //
+ TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
+ TempBuffer = AllocateZeroPool (TempBufferSize);
+ if (TempBuffer == NULL) {
+ Handle->Close (Handle);
+ gBS->FreePool (FileInfo);
+ return Status;
+ }
+
+ gBS->FreePool (FileInfo);
+
+ //
+ // Read the file data to the buffer
+ //
+ Status = Handle->Read (
+ Handle,
+ &TempBufferSize,
+ TempBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ Handle->Close (Handle);
+ gBS->FreePool (TempBuffer);
+ return Status;
+ }
+
+ Handle->Close (Handle);
+
+ *BufferSize = TempBufferSize;
+ *Buffer = TempBuffer;
+ return EFI_SUCCESS;
+}
+
+/**
+ Read a file.
+ If ScanFs is FLASE, it will use this Vol as default Fs.
+ If ScanFs is TRUE, it will scan all FS and check the file.
+ If there is only one file match the name, it will be read.
+ If there is more than one file match the name, it will return Error.
+
+ @param ThisVol File System Volume
+ @param FileName The file to be read.
+ @param BufferSize The file buffer size
+ @param Buffer The file buffer
+ @param ScanFs Need Scan all FS
+
+ @retval EFI_SUCCESS Read file successfully
+ @retval EFI_NOT_FOUND File not found
+ @retval EFI_NO_MAPPING There is duplicated files found
+**/
+EFI_STATUS
+ReadFileToBufferEx (
+ IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **ThisVol,
+ IN CHAR16 *FileName,
+ OUT UINTN *BufferSize,
+ OUT VOID **Buffer,
+ IN BOOLEAN ScanFs
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;
+ UINTN TempBufferSize;
+ VOID *TempBuffer;
+ UINTN NoHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+
+ //
+ // Check parameters
+ //
+ if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // not scan fs
+ //
+ if (!ScanFs) {
+ if (*ThisVol == NULL) {
+ *ThisVol = GetMyVol ();
+ if (*ThisVol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Read file directly from Vol
+ //
+ return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
+ }
+
+ //
+ // need scan fs
+ //
+
+ //
+ // Get all Vol handle
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &NoHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) && (NoHandles == 0)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Walk through each Vol
+ //
+ *ThisVol = NULL;
+ *BufferSize = 0;
+ *Buffer = NULL;
+ for (Index = 0; Index < NoHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID **)&Vol
+ );
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Read file OK, check duplication
+ //
+ if (*ThisVol != NULL) {
+ //
+ // Find the duplicated file
+ //
+ gBS->FreePool (TempBuffer);
+ gBS->FreePool (*Buffer);
+ Print (L"Duplicated FileName found!\n");
+ return EFI_NO_MAPPING;
+ } else {
+ //
+ // Record value
+ //
+ *ThisVol = Vol;
+ *BufferSize = TempBufferSize;
+ *Buffer = TempBuffer;
+ }
+ }
+ }
+
+ //
+ // Scan Fs done
+ //
+ if (*ThisVol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Done
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Read a file.
+
+ @param FileName The file to be read.
+ @param BufferSize The file buffer size
+ @param Buffer The file buffer
+
+ @retval EFI_SUCCESS Read file successfully
+ @retval EFI_NOT_FOUND File not found
+**/
+EFI_STATUS
+ReadFileToBuffer (
+ IN CHAR16 *FileName,
+ OUT UINTN *BufferSize,
+ OUT VOID **Buffer
+ )
+{
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;
+ Vol = NULL;
+ return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
+}
+
+/**
+ Write a file.
+
+ @param FileName The file to be written.
+ @param BufferSize The file buffer size
+ @param Buffer The file buffer
+
+ @retval EFI_SUCCESS Write file successfully
+**/
+EFI_STATUS
+WriteFileFromBuffer(
+ IN CHAR16 *FileName,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE RootDir;
+ EFI_FILE_HANDLE Handle;
+ UINTN TempBufferSize;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;
+
+ Vol = GetMyVol();
+
+ //
+ // Open the root directory
+ //
+ Status = Vol->OpenVolume (Vol, &RootDir);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open the file
+ //
+ Status = RootDir->Open (
+ RootDir,
+ &Handle,
+ FileName,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ RootDir->Close (RootDir);
+ return Status;
+ }
+
+ //
+ // Delete file
+ //
+ Status = Handle->Delete(Handle);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Open the file again
+ //
+ Status = RootDir->Open (
+ RootDir,
+ &Handle,
+ FileName,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ RootDir->Close (RootDir);
+ return Status;
+ }
+
+ RootDir->Close (RootDir);
+
+ //
+ // Write the file data from the buffer
+ //
+ TempBufferSize = BufferSize;
+ Status = Handle->Write (
+ Handle,
+ &TempBufferSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ Handle->Close (Handle);
+ return Status;
+ }
+
+ Handle->Close (Handle);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
new file mode 100644
index 0000000..0a28557
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
@@ -0,0 +1,1047 @@
+/** @file
+ A shell application that triggers capsule update process.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <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 <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Guid/FileInfo.h>
+#include <Guid/Gpt.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/CapsuleReport.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FmpCapsule.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 EFI_CAPSULE_FROM_FILE_DIR L"\\EFI\\UpdateCapsule\\"
+#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED 0x0000000000000004
+
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 0
+
+#define MAX_ARG_NUM 11
+#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
+
+extern UINTN Argc;
+extern CHAR16 *Argv[];
+
+//
+// Define how many block descriptors we want to test with.
+//
+UINTN NumberOfDescriptors = 1;
+UINTN CapsuleFirstIndex;
+UINTN CapsuleLastIndex;
+
+/**
+ Dump capsule information
+
+ @retval EFI_SUCCESS The capsule information is dumped.
+ @retval EFI_UNSUPPORTED Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsule(
+ VOID
+ );
+
+/**
+ Dump capsule status variable.
+
+ @retval EFI_SUCCESS The capsule status variable is dumped.
+ @retval EFI_UNSUPPORTED Input parameter is not valid.
+**/
+EFI_STATUS
+DmpCapsuleStatusVariable(
+ VOID
+ );
+
+/**
+ Dump FMP protocol info.
+**/
+VOID
+DumpFmpData(
+ VOID
+ );
+
+/**
+ Dump ESRT info.
+**/
+VOID
+DumpEsrtData(
+ VOID
+ );
+
+/**
+ Read a file.
+
+ @param FileName The file to be read.
+ @param BufferSize The file buffer size
+ @param Buffer The file buffer
+
+ @retval EFI_SUCCESS Read file successfully
+ @retval EFI_NOT_FOUND File not found
+**/
+EFI_STATUS
+ReadFileToBuffer(
+ IN CHAR16 *FileName,
+ OUT UINTN *BufferSize,
+ OUT VOID **Buffer
+ );
+
+/**
+ Write a file.
+
+ @param FileName The file to be written.
+ @param BufferSize The file buffer size
+ @param Buffer The file buffer
+
+ @retval EFI_SUCCESS Write file successfully
+**/
+EFI_STATUS
+WriteFileFromBuffer(
+ IN CHAR16 *FileName,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+
+ This function parse application ARG.
+
+ @return Status
+**/
+EFI_STATUS
+GetArg (
+ VOID
+ );
+
+/**
+ Clear APP ARG.
+**/
+VOID
+CleanArg (
+ VOID
+ );
+
+/**
+ 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;
+
+ Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
+ if (EFI_ERROR(Status)) {
+ Print(L"CapsuleApp: NO GOP is found.\n");
+ return EFI_UNSUPPORTED;
+ }
+ Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
+ Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
+ Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
+ // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
+ // VerticalResolution >= BMP_IMAGE_HEADER.PixelHeight
+
+ if (Argc != 5) {
+ Print(L"CapsuleApp: Invalid Parameter.\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;
+ }
+
+ 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;
+ DisplayCapsule->ImagePayload.OffsetX = 0;
+ DisplayCapsule->ImagePayload.OffsetY = 0;
+
+ 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 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 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)) {
+ 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;
+}
+
+/**
+ 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: Invalid Parameter.\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;
+ }
+
+ ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
+ if (ImageTypeId == NULL) {
+ Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
+ goto Done;
+ }
+ FwType = GetEsrtFwType(ImageTypeId);
+ if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType != ESRT_FW_TYPE_DEVICEFIRMWARE)) {
+ Print(L"CapsuleApp: Capsule FwType is invalid.\n");
+ 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_DEVICEFIRMWARE) ? 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;
+
+ 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 = gRT->SetVariable (
+ CapsuleVarName,
+ &gEfiCapsuleReportGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ (VOID *)NULL
+ );
+ if (EFI_ERROR(Status)) {
+ //
+ // There is no capsule variables, quit
+ //
+ break;
+ }
+
+ Index++;
+ if (Index > 0xFFFF) {
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the active UEFI system partition from bootoption list.
+
+ @param[out] Fs Simple File System protocol on the active UEFI system partition
+
+ @retval EFI_SUCCESS active UEFI system partition found
+**/
+EFI_STATUS
+GetEfiSysPartition(
+ OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsTemp;
+ UINTN NoHandles;
+ EFI_HANDLE *Handles;
+ UINTN Index;
+
+ Handles = NULL;
+
+ //
+ // search for EFI system partition protocol on Boot option device path
+ //
+ Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL, &NoHandles, &Handles);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Skip BootOptions within FV
+ //
+ for (Index = 0; Index < NoHandles; Index++) {
+ Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsTemp);
+ if (!EFI_ERROR (Status)){
+ *Fs = FsTemp;
+ break;
+ }
+ }
+ return Status;
+}
+
+/**
+ Copy a list of capsule images to the active UEFI system partition from bootoption list.
+
+ @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
+
+ @retval EFI_SUCCESS Capsule images are copied to the active UEFI system partition
+**/
+EFI_STATUS
+CopyCapsuleToActiveEfiPartition(
+ IN VOID **CapsuleBuffer,
+ IN UINTN *FileSize,
+ IN UINTN CapsuleNum
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *CapsuleName;
+ UINTN Index;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
+ EFI_FILE_HANDLE RootDir;
+ EFI_FILE_HANDLE CapsuleDir;
+ EFI_FILE_HANDLE DestHandle;
+ UINTN DataSize;
+ UINT64 OsIndication;
+
+ RootDir = NULL;
+ CapsuleDir = NULL;
+
+ Status = GetEfiSysPartition(&Fs);
+ if (EFI_ERROR(Status)) {
+ Print (L"Can not find active UEFI System Partition\n");
+ return Status;
+ }
+
+ Status = Fs->OpenVolume(Fs, &RootDir);
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+
+ Status = RootDir->Open(
+ RootDir,
+ &CapsuleDir,
+ EFI_CAPSULE_FROM_FILE_DIR,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+ EFI_FILE_DIRECTORY
+ );
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+
+ //
+ // Read the input files.
+ //
+ for (Index = 0; Index < CapsuleNum; Index++) {
+ CapsuleName = Argv[CapsuleFirstIndex + Index];
+ Status = CapsuleDir->Open(
+ CapsuleDir,
+ &DestHandle,
+ CapsuleName,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+ EFI_FILE_ARCHIVE
+ );
+ if (EFI_ERROR(Status)) {
+ Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
+ continue;
+ }
+
+ DataSize = FileSize[Index];
+ Status = DestHandle->Write(
+ DestHandle,
+ &DataSize,
+ CapsuleBuffer[Index]
+ );
+ DestHandle->Close(DestHandle);
+ if (EFI_ERROR(Status)) {
+ Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName, Status, FileSize[Index]);
+ }
+ }
+
+ Status = gRT->GetVariable (
+ L"OsIndications",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &DataSize,
+ (VOID *) &OsIndication
+ );
+
+ if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
+ OsIndication = 0;
+ }
+
+ //
+ // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
+ //
+ OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
+ Status = gRT->SetVariable (
+ L"OsIndications",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(OsIndication),
+ (VOID *)&OsIndication
+ );
+
+
+EXIT:
+ if (RootDir != NULL) {
+ RootDir->Close(RootDir);
+ }
+
+ if (CapsuleDir != NULL) {
+ CapsuleDir->Close(CapsuleDir);
+ }
+
+ return Status;
+}
+
+/**
+ 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, FileSize);
+ }
+
+ //
+ // Record descirptor 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->Union.ContinuationPointer);
+ FreePool(TempBlockPtr1);
+ TempBlockPtr1 = TempBlockPtr2;
+ }
+ }
+}
+
+/**
+ Print APP usage.
+**/
+VOID
+PrintUsage (
+ VOID
+ )
+{
+ Print(L"CapsuleApp: usage\n");
+ Print(L" CapsuleApp [-F] <Capsule...> [-NR]\n");
+ Print(L" CapsuleApp -S\n");
+ Print(L" CapsuleApp -C\n");
+ Print(L" CapsuleApp -P\n");
+ Print(L" CapsuleApp -E\n");
+ Print(L" CapsuleApp -G <BMP> -O <Capsule>\n");
+ Print(L" CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
+ Print(L" CapsuleApp -D|-DS <Capsule>\n");
+ Print(L"Parameter:\n");
+ Print(L" -F: Put capsule file to disk.\n");
+ Print(L" No -F means to put capsule file in memory.\n");
+ Print(L" -NR: No Reset.\n");
+ Print(L" -S: Dump capsule status.\n");
+ Print(L" -C: Clear capsule status.\n");
+ Print(L" -P: Dump FMP protocol info.\n");
+ Print(L" -E: Dump ESRT table info.\n");
+ Print(L" -G: Input BMP file name\n");
+ Print(L" -N: Append Capsule Header accroding to Windows Firmware Update\n");
+ Print(L" -O: Output Capsule file name\n");
+ Print(L" -D: Dump Capsule\n");
+ Print(L" -DS: Dump Capsule with System FMP format\n");
+}
+
+/**
+ Update Capsule image.
+
+ @param[in] ImageHandle The image handle.
+ @param[in] SystemTable The system table.
+
+ @retval EFI_SUCCESS Command completed successfully.
+ @retval EFI_INVALID_PARAMETER Command usage error.
+ @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;
+ UINTN FileSize[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 NeedCopyOnDisk;
+ CHAR16 *CapsuleName;
+ UINTN CapsuleNum;
+ UINTN Index;
+
+ Status = GetArg();
+ if (EFI_ERROR(Status)) {
+ PrintUsage();
+ return Status;
+ }
+ if (Argc < 2) {
+ PrintUsage();
+ CleanArg();
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((StrCmp(Argv[1], L"-D") == 0) ||
+ (StrCmp(Argv[1], L"-DS") == 0)) {
+ Status = DumpCapsule();
+ CleanArg();
+ return Status;
+ }
+ if (StrCmp(Argv[1], L"-G") == 0) {
+ Status = CreateBmpFmp();
+ CleanArg();
+ return Status;
+ }
+ if (StrCmp(Argv[1], L"-N") == 0) {
+ Status = CreateNestedFmp();
+ CleanArg();
+ return Status;
+ }
+ if (StrCmp(Argv[1], L"-S") == 0) {
+ Status = DmpCapsuleStatusVariable();
+ CleanArg();
+ return EFI_SUCCESS;
+ }
+ if (StrCmp(Argv[1], L"-C") == 0) {
+ Status = ClearCapsuleStatusVariable();
+ CleanArg();
+ return Status;
+ }
+ if (StrCmp(Argv[1], L"-P") == 0) {
+ DumpFmpData();
+ CleanArg();
+ return EFI_SUCCESS;
+ }
+ if (StrCmp(Argv[1], L"-E") == 0) {
+ DumpEsrtData();
+ CleanArg();
+ return EFI_SUCCESS;
+ }
+ if (StrCmp(Argv[1], L"-F") == 0) {
+ NeedCopyOnDisk = TRUE;
+ CapsuleFirstIndex = 2;
+ } else {
+ NeedCopyOnDisk = FALSE;
+ CapsuleFirstIndex = 1;
+ }
+ if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
+ NoReset = TRUE;
+ CapsuleLastIndex = Argc - 2;
+ } else {
+ NoReset = FALSE;
+ CapsuleLastIndex = Argc - 1;
+ }
+ CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
+
+ if (CapsuleFirstIndex > CapsuleLastIndex) {
+ Print(L"CapsuleApp: NO capsule image.\n");
+ CleanArg();
+ return EFI_UNSUPPORTED;
+ }
+ if (CapsuleNum > MAX_CAPSULE_NUM) {
+ Print(L"CapsuleApp: Too many capsule images.\n");
+ CleanArg();
+ return EFI_UNSUPPORTED;
+ }
+
+ ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
+ ZeroMem(&FileSize, sizeof(FileSize));
+ BlockDescriptors = NULL;
+
+ for (Index = 0; Index < CapsuleNum; Index++) {
+ CapsuleName = Argv[CapsuleFirstIndex + Index];
+ Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
+ if (EFI_ERROR(Status)) {
+ Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
+ goto Done;
+ }
+ }
+
+ if (NeedCopyOnDisk) {
+ Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
+ } else {
+ //
+ // Every capsule use 2 descriptor 1 for data 1 for end
+ //
+ Status = BuildGatherList(CapsuleBuffer, FileSize, 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;
+ if (NoReset) {
+ NeedReset = FALSE;
+ }
+
+ //
+ // 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 (FileSize[Index] > MaxCapsuleSize) {
+ Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n", MaxCapsuleSize);
+ Status = EFI_UNSUPPORTED;
+ 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 who has reset flag, after calling UpdateCapsule service,triger 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);
+ CleanArg();
+
+ return Status;
+}
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
new file mode 100644
index 0000000..7ee44fc
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
@@ -0,0 +1,71 @@
+## @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>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[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
+ CapsuleDump.c
+ AppSupport.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[Guids]
+ gEfiFileInfoGuid
+ gEfiPartTypeSystemPartGuid
+ gEfiGlobalVariableGuid
+ gEfiCapsuleReportGuid
+ gEfiFmpCapsuleGuid
+ gWindowsUxCapsuleGuid
+ gEfiCertTypeRsa2048Sha256Guid
+ gEfiCertPkcs7Guid
+ gEfiSystemResourceTableGuid
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
+ gEfiGraphicsOutputProtocolGuid
+ gEfiFirmwareManagementProtocolGuid
+
+[LibraryClasses]
+ BaseLib
+ UefiApplicationEntryPoint
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiLib
+ PrintLib
+ EdkiiSystemCapsuleLib
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ CapsuleAppExtra.uni
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
new file mode 100644
index 0000000..54d6e12
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
@@ -0,0 +1,22 @@
+// /** @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>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#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
new file mode 100644
index 0000000..b5a8840
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// CapsuleApp Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Capsule Application"
+
+
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
new file mode 100644
index 0000000..c56f41f
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
@@ -0,0 +1,840 @@
+/** @file
+ Dump Capsule image information.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.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/EdkiiSystemCapsuleLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+#include <Guid/CapsuleReport.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FmpCapsule.h>
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+/**
+ Read a file.
+
+ @param FileName The file to be read.
+ @param BufferSize The file buffer size
+ @param Buffer The file buffer
+
+ @retval EFI_SUCCESS Read file successfully
+ @retval EFI_NOT_FOUND File not found
+**/
+EFI_STATUS
+ReadFileToBuffer(
+ IN CHAR16 *FileName,
+ OUT UINTN *BufferSize,
+ OUT VOID **Buffer
+ );
+
+extern UINTN Argc;
+extern CHAR16 *Argv[];
+
+/**
+ Dump UX capsule information.
+
+ @param CapsuleHeader The UX capsule header
+**/
+VOID
+DumpUxCapsule(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_DISPLAY_CAPSULE *DisplayCapsule;
+ DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
+ Print(L"[UxCapusule]\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 FMP image authentication information.
+
+ @param Image The FMP capsule image
+ @param ImageSize The size of the FMP capsule image in bytes.
+
+ @return the size of FMP authentication.
+**/
+UINTN
+DumpImageAuthentication(
+ IN VOID *Image,
+ IN UINTN ImageSize
+ )
+{
+ EFI_FIRMWARE_IMAGE_AUTHENTICATION *ImageAuthentication;
+
+ ImageAuthentication = Image;
+ if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
+ CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)) {
+ Print(L"[ImageAuthentication]\n");
+ Print(L" MonotonicCount - 0x%lx\n", ImageAuthentication->MonotonicCount);
+ Print(L"WIN_CERTIFICATE:\n");
+ Print(L" dwLength - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
+ Print(L" wRevision - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wRevision);
+ Print(L" wCertificateType - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wCertificateType);
+ Print(L" CertType - %g\n", &ImageAuthentication->AuthInfo.CertType);
+ return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication->AuthInfo.Hdr.dwLength;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ Dump EDKII system FMP capsule.
+
+ @param Image The EDKII system FMP capsule.
+ @param ImageSize The size of the EDKII system FMP capsule in bytes.
+**/
+VOID
+DumpEdkiiSystemFmpCapsule(
+ IN VOID *Image,
+ IN UINTN ImageSize
+ )
+{
+ UINTN ImageOffset;
+ VOID *BiosImage;
+ UINTN BiosImageSize;
+ BOOLEAN Result;
+ EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *TempImageFmpInfo;
+ EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageFmpInfo;
+ UINTN ImageFmpInfoSize;
+
+ //
+ // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ // so just *try* to parse it
+ //
+ ImageOffset = DumpImageAuthentication(Image, ImageSize);
+ Image = (UINT8 *)Image + ImageOffset;
+ ImageSize -= ImageOffset;
+ Print(L"[Image]\n");
+ Print(L" ImageSize - 0x%x\n", ImageSize);
+
+ Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
+ if (Result) {
+ Print(L" ConfigFileSize - 0x%x\n", BiosImageSize);
+ }
+ Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
+ if (Result) {
+ Print(L" DriverFvSize - 0x%x\n", BiosImageSize);
+ }
+ Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
+ if (Result) {
+ Print(L" BiosImageSize - 0x%x\n", BiosImageSize);
+ }
+ Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize, &TempImageFmpInfo, &ImageFmpInfoSize);
+ if (Result) {
+ ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
+ if (ImageFmpInfo != NULL) {
+ Print(L"[ImageFmpInfo]\n");
+ Print(L" Signature - 0x%x\n", ImageFmpInfo->Signature);
+ Print(L" HeaderLength - 0x%x\n", ImageFmpInfo->HeaderLength);
+ Print(L" Length - 0x%x\n", ImageFmpInfo->Length);
+ Print(L" PackageVersion - 0x%x\n", ImageFmpInfo->PackageVersion);
+ Print(L" PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo->PackageVersionNameStringOffset);
+ if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
+ Print(L" - %s\n", (UINT8 *)ImageFmpInfo + ImageFmpInfo->PackageVersionNameStringOffset);
+ }
+ Print(L" ImageIndex - 0x%x\n", ImageFmpInfo->ImageIndex);
+ Print(L" ImageTypeId - %g\n", &ImageFmpInfo->ImageTypeId);
+ Print(L" ImageId - 0x%lx\n", ImageFmpInfo->ImageId);
+ Print(L" ImageIdNameStringOffset - 0x%x\n", ImageFmpInfo->ImageIdNameStringOffset);
+ if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
+ Print(L" - %s\n", (UINT8 *)ImageFmpInfo + ImageFmpInfo->ImageIdNameStringOffset);
+ }
+ Print(L" Version - 0x%x\n", ImageFmpInfo->Version);
+ Print(L" VersionNameStringOffset - 0x%x\n", ImageFmpInfo->VersionNameStringOffset);
+ if (ImageFmpInfo->VersionNameStringOffset != 0) {
+ Print(L" - %s\n", (UINT8 *)ImageFmpInfo + ImageFmpInfo->VersionNameStringOffset);
+ }
+ Print(L" Size - 0x%lx\n", ImageFmpInfo->Size);
+ Print(L" AttributesSupported - 0x%lx\n", ImageFmpInfo->AttributesSupported);
+ Print(L" AttributesSetting - 0x%lx\n", ImageFmpInfo->AttributesSetting);
+ Print(L" Compatibilities - 0x%lx\n", ImageFmpInfo->Compatibilities);
+ Print(L" LowestSupportedImageVersion - 0x%x\n", ImageFmpInfo->LowestSupportedImageVersion);
+ Print(L" LastAttemptVersion - 0x%x\n", ImageFmpInfo->LastAttemptVersion);
+ Print(L" LastAttemptStatus - 0x%x\n", ImageFmpInfo->LastAttemptStatus);
+ Print(L" HardwareInstance - 0x%lx\n", ImageFmpInfo->HardwareInstance);
+ Print(L" Version - 0x%x\n", ImageFmpInfo->Version);
+ FreePool(ImageFmpInfo);
+ }
+ }
+}
+
+/**
+ Dump a non-nested FMP capsule.
+
+ @param CapsuleHeader A pointer to CapsuleHeader
+ @param IsSystemFmp If it is a system FMP
+**/
+VOID
+DumpFmpCapsule(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN BOOLEAN IsSystemFmp
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ UINT64 *ItemOffsetList;
+ UINTN Index;
+ UINTN Count;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *FmpImageHeader;
+ VOID *Image;
+
+ Print(L"[FmpCapusule]\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 >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ Print(L" UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);
+ }
+ if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ Image = (UINT8 *)(FmpImageHeader + 1);
+ } else {
+ Image = (UINT8 *)FmpImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+ }
+ if (IsSystemFmp) {
+ DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
+ }
+ }
+}
+
+/**
+ 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)) {
+ 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->HeaderSize - (UINTN)NestedCapsuleHeader;
+ if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
+ return FALSE;
+ }
+ if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Dump capsule information
+
+ @retval EFI_SUCCESS The capsule information is dumped.
+ @retval EFI_UNSUPPORTED Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsule(
+ VOID
+ )
+{
+ CHAR16 *CapsuleName;
+ VOID *Buffer;
+ UINTN FileSize;
+ BOOLEAN IsSystemFmp;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ EFI_STATUS Status;
+
+ if (Argc != 3) {
+ Print(L"CapsuleApp: Invalid Parameter.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ IsSystemFmp = FALSE;
+ if (StrCmp(Argv[1], L"-DS") == 0) {
+ IsSystemFmp = TRUE;
+ }
+
+ CapsuleName = Argv[2];
+ Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
+ if (EFI_ERROR(Status)) {
+ Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
+ goto Done;
+ }
+
+ CapsuleHeader = Buffer;
+ if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
+ DumpUxCapsule(CapsuleHeader);
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+ DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
+ }
+ 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), IsSystemFmp);
+ }
+
+Done:
+ 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
+DmpCapsuleStatusVariable(
+ 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;
+
+ Status = GetVariable2(
+ L"CapsuleMax",
+ &gEfiCapsuleReportGuid,
+ (VOID **)&CapsuleIndex,
+ NULL
+ );
+ if (!EFI_ERROR(Status)) {
+ 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)) {
+ 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;
+ }
+
+ //
+ // 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)) {
+ 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);
+ if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
+ Print(L" Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
+ CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
+ if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapsuleFileNameSize) {
+ Print(L" Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp + 1) + CapsuleFileNameSize);
+ }
+ }
+ }
+ }
+
+ 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",
+};
+
+/**
+ Convert FwType to a string.
+
+ @param 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 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 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" PERSIST_ACROSS_RESET - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
+ Print(L" POPULATE_SYSTEM_TABLE - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
+ Print(L" INITIATE_RESET - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_INITIATE_RESET);
+ Print(L" LastAttemptVersion - 0x%x\n", EsrtEntry->LastAttemptVersion);
+ Print(L" LastAttemptStatus - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
+}
+
+/**
+ Dump ESRT table.
+
+ @param Esrt ESRT table
+**/
+VOID
+DumpEsrt(
+ IN EFI_SYSTEM_RESOURCE_TABLE *Esrt
+ )
+{
+ UINTN Index;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
+
+ 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 FMP information.
+
+ @param ImageInfoSize The size of ImageInfo, in bytes.
+ @param ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
+ @param PackageVersion The version of package.
+ @param 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;
+
+ 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);
+ }
+ }
+ //
+ // 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 PackageVersion The version of package.
+ @param PackageVersionName The version name of package.
+ @param PackageVersionNameMaxLen The maximum length of PackageVersionName.
+ @param AttributesSupported Package attributes that are supported by this device.
+ @param 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);
+}
--
2.7.4.windows.1


[PATCH 16/45] MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.

Yao, Jiewen
 

RecoveryModuleLoadPei supports recovery system BIOS via UEFI FMP capsule.

RecoveryModuleLoadPei produces EFI_PEI_RECOVERY_MODULE_PPI. It is invoked
by DxeIpl in recovery boot mode.

LoadRecoveryCapsule() will scan all possible
gEfiPeiDeviceRecoveryModulePpiGuid and get EDKII system FMP capsule there.

LoadRecoveryCapsule() will perform the FMP authentication and version
check. If and only if the FMP authentication passes, and EDKII system FMP
capsule version is equal to the current BIOS Version, the recovery will
be performed. Or this capsule image is discard.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c | 158 +++++
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c | 746 ++++++++++++++++++++
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h | 44 ++
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf | 71 ++
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni | 21 +
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni | 20 +
6 files changed, 1060 insertions(+)

diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c b/MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
new file mode 100644
index 0000000..1d739cb
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
@@ -0,0 +1,158 @@
+/** @file
+ Parse the INI configuration file and pass the information to the recovery driver
+ so that the driver can perform recovery accordingly.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RecoveryModuleLoadPei.h"
+#include <Library/IniParsingLib.h>
+#include <Library/PrintLib.h>
+
+#define MAX_LINE_LENGTH 512
+
+/**
+ Parse Config data file to get the updated data array.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+ @param ConfigHeader Pointer to the config header.
+ @param RecoveryArray Pointer to the config of recovery data.
+
+ @retval EFI_NOT_FOUND No config data is found.
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseRecoveryDataFile (
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize,
+ IN OUT CONFIG_HEADER *ConfigHeader,
+ IN OUT RECOVERY_CONFIG_DATA **RecoveryArray
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *SectionName;
+ CHAR8 Entry[MAX_LINE_LENGTH];
+ UINTN Num;
+ UINTN Index;
+ EFI_GUID FileGuid;
+ VOID *Context;
+
+ //
+ // First process the data buffer and get all sections and entries
+ //
+ Context = OpenDataFile(DataBuffer, BufferSize);
+ if (Context == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Now get NumOfUpdate
+ //
+ Status = GetDecimalUintnFromDataFile(
+ Context,
+ "Head",
+ "NumOfRecovery",
+ &Num
+ );
+ if (EFI_ERROR(Status) || (Num == 0)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+
+ ConfigHeader->NumOfRecovery = Num;
+ *RecoveryArray = AllocateZeroPool ((sizeof (RECOVERY_CONFIG_DATA) * Num));
+ if (*RecoveryArray == NULL) {
+ CloseDataFile(Context);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0 ; Index < ConfigHeader->NumOfRecovery; Index++) {
+ //
+ // Get the section name of each update
+ //
+ AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Recovery");
+ AsciiValueToString(Entry + AsciiStrLen(Entry), 0, Index, 0);
+ Status = GetStringFromDataFile(
+ Context,
+ "Head",
+ Entry,
+ &SectionName
+ );
+ if (EFI_ERROR(Status) || (SectionName == NULL)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // The section name of this update has been found.
+ // Now looks for all the config data of this update
+ //
+
+ //
+ // FileBuid
+ //
+ Status = GetGuidFromDataFile(
+ Context,
+ SectionName,
+ "FileGuid",
+ &FileGuid
+ );
+ if (EFI_ERROR(Status)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+
+ CopyMem (&((*RecoveryArray)[Index].FileGuid), &FileGuid, sizeof(EFI_GUID));
+
+ //
+ // Length
+ //
+ Status = GetHexUintnFromDataFile(
+ Context,
+ SectionName,
+ "Length",
+ &Num
+ );
+ if (EFI_ERROR(Status)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+ (*RecoveryArray)[Index].Length = Num;
+
+ //
+ // ImageOffset
+ //
+ Status = GetHexUintnFromDataFile(
+ Context,
+ SectionName,
+ "ImageOffset",
+ &Num
+ );
+ if (EFI_ERROR(Status)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+ (*RecoveryArray)[Index].ImageOffset = Num;
+ }
+
+ //
+ // Now all configuration data got. Free those temporary buffers
+ //
+ CloseDataFile(Context);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
new file mode 100644
index 0000000..9369df5
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
@@ -0,0 +1,746 @@
+/** @file
+ Recovery module.
+
+ Caution: This module requires additional review when modified.
+ This module will have external input - capsule image.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ ProcessRecoveryCapsule(), ProcessFmpCapsuleImage(), ProcessRecoveryImage() will
+ receive untrusted input and do basic validation.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <Uefi.h>
+#include <PiPei.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/BootInRecoveryMode.h>
+#include <Ppi/RecoveryModule.h>
+#include <Ppi/DeviceRecoveryModule.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Guid/FirmwareFileSystem2.h>
+#include <Guid/FmpCapsule.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+#include "RecoveryModuleLoadPei.h"
+
+/**
+ Loads a DXE capsule from some media into memory and updates the HOB table
+ with the DXE firmware volume information.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param This Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
+
+ @retval EFI_SUCCESS The capsule was loaded correctly.
+ @retval EFI_DEVICE_ERROR A device error occurred.
+ @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
+
+**/
+EFI_STATUS
+EFIAPI
+LoadRecoveryCapsule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_MODULE_PPI *This
+ );
+
+EFI_PEI_RECOVERY_MODULE_PPI mRecoveryPpi = {
+ LoadRecoveryCapsule
+};
+
+EFI_PEI_PPI_DESCRIPTOR mRecoveryPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiRecoveryModulePpiGuid,
+ &mRecoveryPpi
+};
+
+/**
+ Parse Config data file to get the updated data array.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+ @param ConfigHeader Pointer to the config header.
+ @param RecoveryArray Pointer to the config of recovery data.
+
+ @retval EFI_NOT_FOUND No config data is found.
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseRecoveryDataFile(
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize,
+ IN OUT CONFIG_HEADER *ConfigHeader,
+ IN OUT RECOVERY_CONFIG_DATA **RecoveryArray
+ );
+
+/**
+ Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+ @param[in] FmpImageHeader A pointer to EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
+
+ @return TRUE It is a system FMP.
+ @return FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmpImage (
+ IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *FmpImageHeader
+ )
+{
+ GUID *Guid;
+ UINTN Count;
+ UINTN Index;
+
+ Guid = PcdGetPtr(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid);
+ Count = PcdGetSize(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID);
+
+ for (Index = 0; Index < Count; Index++, Guid++) {
+ if (CompareGuid(&FmpImageHeader->UpdateImageTypeId, Guid)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Return if this CapsuleGuid is a FMP capsule GUID or not.
+
+ @param[in] CapsuleGuid A pointer to EFI_GUID
+
+ @return TRUE It is a FMP capsule GUID.
+ @return FALSE It is not a FMP capsule GUID.
+**/
+BOOLEAN
+IsFmpCapsuleGuid(
+ IN EFI_GUID *CapsuleGuid
+ )
+{
+ if (CompareGuid(&gEfiFmpCapsuleGuid, CapsuleGuid)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ This function assumes the input Capusule image already passes basic check in
+ ValidateFmpCapsule().
+
+ Criteria of system FMP capsule is:
+ 1) FmpCapsuleHeader->EmbeddedDriverCount is 0.
+ 2) FmpCapsuleHeader->PayloadItemCount is not 0.
+ 3) All ImageHeader->UpdateImageTypeId matches PcdEdkiiSystemFmpCapsuleImageTypeIdGuid.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval TRUE Input capsule is a correct system FMP capsule.
+ @retval FALSE Input capsule is not a correct system FMP capsule.
+**/
+BOOLEAN
+IsSystemFmpCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT64 *ItemOffsetList;
+ UINT32 ItemNum;
+ UINTN Index;
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+
+ if (FmpCapsuleHeader->EmbeddedDriverCount != 0) {
+ return FALSE;
+ }
+
+ if (FmpCapsuleHeader->PayloadItemCount == 0) {
+ return FALSE;
+ }
+
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ for (Index = 0; Index < ItemNum; Index++) {
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+ if (!IsSystemFmpImage(ImageHeader)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ 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 CapsuleHeader Points to a capsule header.
+ @param CapsuleSize Size of the whole capsule image.
+
+**/
+BOOLEAN
+IsValidCapsuleHeader(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN UINT64 CapsuleSize
+ )
+{
+ if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
+ return FALSE;
+ }
+ if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Validate Fmp capsules layout.
+
+ This function assumes the caller validated the capsule by using
+ IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
+ The capsule buffer size is CapsuleHeader->CapsuleImageSize.
+
+ This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+ and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
+
+ @param[in] CapsuleHeader Points to a capsule header.
+ @param[out] IsSystemFmp If it is a system FMP.
+ @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
+
+ @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+ @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
+**/
+EFI_STATUS
+ValidateFmpCapsule (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ OUT BOOLEAN *IsSystemFmp, OPTIONAL
+ OUT UINT16 *EmbeddedDriverCount OPTIONAL
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ UINT8 *EndOfCapsule;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT8 *EndOfPayload;
+ UINT64 *ItemOffsetList;
+ UINT32 ItemNum;
+ UINTN Index;
+ UINTN FmpCapsuleSize;
+ UINTN FmpCapsuleHeaderSize;
+ UINT64 FmpImageSize;
+ UINTN FmpImageHeaderSize;
+
+ if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
+ DEBUG((EFI_D_ERROR, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+ EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
+ FmpCapsuleSize = (UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader;
+
+ if (FmpCapsuleSize < sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER)) {
+ DEBUG((EFI_D_ERROR, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+ if (FmpCapsuleHeader->Version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+ DEBUG((EFI_D_ERROR, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader->Version));
+ return EFI_INVALID_PARAMETER;
+ }
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ // No overflow
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+ if ((FmpCapsuleSize - sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER))/sizeof(UINT64) < ItemNum) {
+ DEBUG((EFI_D_ERROR, "ItemNum(0x%x) too big\n", ItemNum));
+ return EFI_INVALID_PARAMETER;
+ }
+ FmpCapsuleHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64)*ItemNum;
+
+ // Check ItemOffsetList
+ for (Index = 0; Index < ItemNum; Index++) {
+ if (ItemOffsetList[Index] >= FmpCapsuleSize) {
+ DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ItemOffsetList[Index] < FmpCapsuleHeaderSize) {
+ DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleHeaderSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // All the address in ItemOffsetList must be stored in ascending order
+ //
+ if (Index > 0) {
+ if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {
+ DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index, ItemOffsetList[Index - 1]));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
+ for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+ if (Index == ItemNum - 1) {
+ EndOfPayload = (UINT8 *)((UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader);
+ } else {
+ EndOfPayload = (UINT8 *)(UINTN)ItemOffsetList[Index+1];
+ }
+ FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];
+
+ if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) {
+ DEBUG((EFI_D_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);
+ if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||
+ (ImageHeader->Version < 1)) {
+ DEBUG((EFI_D_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+ }
+
+ // No overflow
+ if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) {
+ DEBUG((EFI_D_ERROR, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize, ImageHeader->UpdateImageSize, ImageHeader->UpdateVendorCodeSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (ItemNum == 0) {
+ //
+ // No driver & payload element in FMP
+ //
+ EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);
+ if (EndOfPayload != EndOfCapsule) {
+ DEBUG((EFI_D_ERROR, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload, EndOfCapsule));
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check in system FMP capsule
+ //
+ if (IsSystemFmp != NULL) {
+ *IsSystemFmp = IsSystemFmpCapsuleImage(CapsuleHeader);
+ }
+
+ if (EmbeddedDriverCount != NULL) {
+ *EmbeddedDriverCount = FmpCapsuleHeader->EmbeddedDriverCount;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Recovery module entrypoint
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @return EFI_SUCCESS Recovery module is initialized.
+**/
+EFI_STATUS
+EFIAPI
+InitializeRecoveryModule(
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN BootMode;
+
+ BootMode = GetBootModeHob();
+ ASSERT(BootMode == BOOT_IN_RECOVERY_MODE);
+
+ Status = (**PeiServices).InstallPpi (PeiServices, &mRecoveryPpiList);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Create hob and install FvInfo PPI for recovery capsule.
+
+ @param FvImage Points to the DXE FV image.
+ @param FvImageSize The length of the DXE FV image in bytes.
+
+ @retval EFI_SUCESS Create hob and install FvInfo PPI successfully.
+**/
+EFI_STATUS
+EFIAPI
+CreateHobForRecoveryCapsule(
+ IN VOID *FvImage,
+ IN UINTN FvImageSize
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvImage;
+ BuildFvHob((UINT64)(UINTN)FvHeader, FvHeader->FvLength);
+ DEBUG((EFI_D_INFO, "BuildFvHob (FvMain in recovery) - 0x%lx - 0x%lx\n", (UINT64)(UINTN)FvHeader, FvHeader->FvLength));
+
+ PeiServicesInstallFvInfoPpi(
+ NULL,
+ (VOID *)FvHeader,
+ (UINT32)FvHeader->FvLength,
+ NULL,
+ NULL
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Create recovery context based upon BIOS image and config file.
+
+ @param BiosImage Points to the BIOS image.
+ @param BiosImageSize The length of the BIOS image in bytes.
+ @param ConfigImage Points to the config file image.
+ @param ConfigImageSize The length of the config file image in bytes.
+
+ @retval EFI_SUCESS Process Recovery Image successfully.
+**/
+EFI_STATUS
+RecoverImage (
+ IN VOID *BiosImage,
+ IN UINTN BiosImageSize,
+ IN VOID *ConfigImage,
+ IN UINTN ConfigImageSize
+ )
+{
+ EFI_STATUS Status;
+ RECOVERY_CONFIG_DATA *ConfigData;
+ RECOVERY_CONFIG_DATA *RecoveryConfigData;
+ CONFIG_HEADER ConfigHeader;
+ UINTN Index;
+
+ if (ConfigImage == NULL) {
+ DEBUG((EFI_D_INFO, "RecoverImage (NoConfig):"));
+ Status = CreateHobForRecoveryCapsule(
+ BiosImage,
+ BiosImageSize
+ );
+ return Status;
+ }
+
+ ConfigData = NULL;
+ ZeroMem (&ConfigHeader, sizeof(ConfigHeader));
+ Status = ParseRecoveryDataFile (
+ ConfigImage,
+ ConfigImageSize,
+ &ConfigHeader,
+ &ConfigData
+ );
+
+ Index = 0;
+ RecoveryConfigData = ConfigData;
+ while (Index < ConfigHeader.NumOfRecovery) {
+ Status = CreateHobForRecoveryCapsule (
+ (UINT8 *)BiosImage + RecoveryConfigData->ImageOffset,
+ RecoveryConfigData->Length
+ );
+ //
+ // Shall updates be serialized so that if an update is not successfully completed,
+ // the remaining updates won't be performed.
+ //
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Index++;
+ RecoveryConfigData++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Process recovery image.
+
+ Caution: This function may receive untrusted input.
+
+ @param Image Points to the recovery image.
+ @param Length The length of the recovery image in bytes.
+
+ @retval EFI_SUCESS Process Recovery Image successfully.
+ @retval EFI_SECURITY_VIOLATION Recovery image is not processed due to security violation.
+**/
+EFI_STATUS
+ProcessRecoveryImage (
+ IN VOID *Image,
+ IN UINTN Length
+ )
+{
+ UINT32 LastAttemptVersion;
+ UINT32 LastAttemptStatus;
+ EFI_STATUS Status;
+ VOID *BiosImage;
+ UINTN BiosImageSize;
+ VOID *ConfigImage;
+ UINTN ConfigImageSize;
+ VOID *AuthenticatedImage;
+ UINTN AuthenticatedImageSize;
+
+ Status = CapsuleAuthenticateSystemFirmware(Image, Length, TRUE, &LastAttemptVersion, &LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_INFO, "CapsuleAuthenticateSystemFirmware - %r\n", Status));
+ return Status;
+ }
+
+ ExtractSystemFirmwareImage(AuthenticatedImage, AuthenticatedImageSize, &BiosImage, &BiosImageSize);
+ ExtractConfigImage(AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize);
+
+ Status = RecoverImage(BiosImage, BiosImageSize, ConfigImage, ConfigImageSize);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_INFO, "RecoverImage - %r\n", Status));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Process Firmware management protocol data capsule.
+
+ Caution: This function may receive untrusted input.
+
+ This function assumes the caller validated the capsule by using
+ ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
+
+ @param CapsuleHeader Points to a capsule header.
+ @param IsSystemFmp If this capsule is a system FMP capsule.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+EFI_STATUS
+ProcessFmpCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN BOOLEAN IsSystemFmp
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT8 *Image;
+ UINT64 *ItemOffsetList;
+ UINTN ItemIndex;
+
+ if (!IsSystemFmp) {
+ return EFI_UNSUPPORTED;
+ }
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ for (ItemIndex = 0; ItemIndex < FmpCapsuleHeader->PayloadItemCount; ItemIndex++) {
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemIndex]);
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ Image = (UINT8 *)(ImageHeader + 1);
+ } else {
+ //
+ // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
+ // Header should exclude UpdateHardwareInstance field
+ //
+ Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+ }
+
+ Status = ProcessRecoveryImage (Image, ImageHeader->UpdateImageSize);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Process recovery capsule image.
+
+ Caution: This function may receive untrusted input.
+
+ @param CapsuleBuffer The capsule image buffer.
+ @param CapsuleSize The size of the capsule image in bytes.
+
+ @retval EFI_SUCCESS The recovery capsule is processed.
+ @retval EFI_SECURITY_VIOLATION The recovery capsule is not process because of security violation.
+ @retval EFI_NOT_FOUND The recovery capsule is not process because of unrecognization.
+**/
+EFI_STATUS
+EFIAPI
+ProcessRecoveryCapsule (
+ IN VOID *CapsuleBuffer,
+ IN UINTN CapsuleSize
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN IsSystemFmp;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+
+ CapsuleHeader = CapsuleBuffer;
+ if (!IsValidCapsuleHeader (CapsuleHeader, CapsuleSize)) {
+ DEBUG((EFI_D_ERROR, "CapsuleImageSize incorrect\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ //
+ // Check FMP capsule layout
+ //
+ if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
+ DEBUG((EFI_D_INFO, "CreateHobForRecoveryCapsule\n"));
+
+ DEBUG((EFI_D_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));
+ DEBUG((EFI_D_INFO, "ValidateFmpCapsule ...\n"));
+ Status = ValidateFmpCapsule(CapsuleHeader, &IsSystemFmp, NULL);
+ DEBUG((EFI_D_INFO, "ValidateFmpCapsule - %r\n", Status));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Press EFI FMP Capsule
+ //
+ DEBUG((EFI_D_INFO, "ProcessFmpCapsuleImage ...\n"));
+ Status = ProcessFmpCapsuleImage(CapsuleHeader, IsSystemFmp);
+ DEBUG((EFI_D_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
+
+ DEBUG((EFI_D_INFO, "CreateHobForRecoveryCapsule Done\n"));
+ return Status;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Loads a DXE capsule from some media into memory and updates the HOB table
+ with the DXE firmware volume information.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param This Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
+
+ @retval EFI_SUCCESS The capsule was loaded correctly.
+ @retval EFI_DEVICE_ERROR A device error occurred.
+ @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
+
+**/
+EFI_STATUS
+EFIAPI
+LoadRecoveryCapsule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_MODULE_PPI *This
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *DeviceRecoveryPpi;
+ UINTN NumberRecoveryCapsules;
+ UINTN Instance;
+ UINTN CapsuleInstance;
+ UINTN CapsuleSize;
+ EFI_GUID CapsuleType;
+ VOID *CapsuleBuffer;
+
+ DEBUG((DEBUG_INFO | DEBUG_LOAD, "Recovery Entry\n"));
+
+ for (Instance = 0; ; Instance++) {
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiDeviceRecoveryModulePpiGuid,
+ Instance,
+ NULL,
+ (VOID **)&DeviceRecoveryPpi
+ );
+ DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - LocateRecoveryPpi (%d) - %r\n", Instance, Status));
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ NumberRecoveryCapsules = 0;
+ Status = DeviceRecoveryPpi->GetNumberRecoveryCapsules (
+ (EFI_PEI_SERVICES **)PeiServices,
+ DeviceRecoveryPpi,
+ &NumberRecoveryCapsules
+ );
+ DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - GetNumberRecoveryCapsules (%d) - %r\n", NumberRecoveryCapsules, Status));
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ for (CapsuleInstance = 1; CapsuleInstance <= NumberRecoveryCapsules; CapsuleInstance++) {
+ CapsuleSize = 0;
+ Status = DeviceRecoveryPpi->GetRecoveryCapsuleInfo (
+ (EFI_PEI_SERVICES **)PeiServices,
+ DeviceRecoveryPpi,
+ FeaturePcdGet(PcdFrameworkCompatibilitySupport) ? CapsuleInstance - 1 : CapsuleInstance,
+ &CapsuleSize,
+ &CapsuleType
+ );
+ DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - GetRecoveryCapsuleInfo (%d - %x) - %r\n", CapsuleInstance, CapsuleSize, Status));
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ CapsuleBuffer = AllocatePages (EFI_SIZE_TO_PAGES(CapsuleSize));
+ if (CapsuleBuffer == NULL) {
+ DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - AllocatePool fail\n"));
+ continue;
+ }
+ Status = DeviceRecoveryPpi->LoadRecoveryCapsule (
+ (EFI_PEI_SERVICES **)PeiServices,
+ DeviceRecoveryPpi,
+ FeaturePcdGet(PcdFrameworkCompatibilitySupport) ? CapsuleInstance - 1 : CapsuleInstance,
+ CapsuleBuffer
+ );
+ DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - LoadRecoveryCapsule (%d) - %r\n", CapsuleInstance, Status));
+ if (EFI_ERROR (Status)) {
+ FreePages (CapsuleBuffer, EFI_SIZE_TO_PAGES(CapsuleSize));
+ break;
+ }
+ //
+ // good, load capsule buffer
+ //
+ Status = ProcessRecoveryCapsule (CapsuleBuffer, CapsuleSize);
+ return Status;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
new file mode 100644
index 0000000..ce3a35f
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
@@ -0,0 +1,44 @@
+/** @file
+ Recovery module header file.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _RECOVERY_MODULE_LOAD_PEI_H_
+#define _RECOVERY_MODULE_LOAD_PEI_H_
+
+#include <PiPei.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+
+//
+// Update data
+//
+
+typedef struct {
+ UINTN NumOfRecovery;
+} CONFIG_HEADER;
+
+typedef struct {
+ UINTN Index;
+ EFI_GUID FileGuid;
+ UINTN Length;
+ UINTN ImageOffset;
+} RECOVERY_CONFIG_DATA;
+
+#endif
+
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
new file mode 100644
index 0000000..2f3bd7a
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
@@ -0,0 +1,71 @@
+## @file
+# Recovery module.
+#
+# Load Recovery capsule and install FV.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = RecoveryModuleLoadPei
+ MODULE_UNI_FILE = RecoveryModuleLoadPei.uni
+ FILE_GUID = 4278A574-4769-4D60-B090-DD4916691590
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeRecoveryModule
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ RecoveryModuleLoadPei.c
+ ParseConfigProfile.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ DebugLib
+ HobLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ EdkiiSystemCapsuleLib
+ IniParsingLib
+ PrintLib
+
+[Ppis]
+ gEfiPeiMasterBootModePpiGuid # PPI ALWAYS_PRODUCED
+ gEfiPeiBootInRecoveryModePpiGuid # PPI SOMETIMES_PRODUCED
+ gEfiPeiRecoveryModulePpiGuid
+ gEfiPeiDeviceRecoveryModulePpiGuid
+
+[Guids]
+ gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid ## CONSUMES
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES
+
+[depex]
+ gEfiPeiBootInRecoveryModePpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ RecoveryModuleLoadPeiExtra.uni
+
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
new file mode 100644
index 0000000..44e6cdc
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
@@ -0,0 +1,21 @@
+// /** @file
+// Recovery module.
+//
+// Load Recovery capsule and install FV.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Recovery module."
+
+#string STR_MODULE_DESCRIPTION #language en-US "Load Recovery capsule and install FV."
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
new file mode 100644
index 0000000..56057c6
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// RecoveryModuleLoadPei Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"RecoveryModuleLoad PEI Driver"
+
+
--
2.7.4.windows.1


[PATCH 15/45] MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.

Yao, Jiewen
 

SystemBiosUpdate supports udpate system BIOS via UEFI FMP capsule.

SystemBiosReportDxe.inf can be included in system BIOS. It is a lightweight
FMP protocol implementation and it only reports FMP information, so that
ESRT table can report the system firmware information. It does not support
SetImage().

SystemBiosUpdateDxe.inf can be included in EDKII system capsule image.
It is a full feature FMP protocol implementation and supports SetImage().
It can be used to update the system firmware.
SystemBiosUpdateDxe.inf can also be included in system BIOS.
If so SystemBiosReportDxe.inf is not needed.

SystemBiosUpdateDxe SetImage() will perform the FMP authentication and
version check. If and only if the FMP authentication passes, and new
EDKII system capsule version is no less than current BIOS
LowestSupportedVersion, the system firmware will be udpated.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c | 219 +++++++++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h | 393 ++++++++++++++++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c | 484 ++++++++++++++++++++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c | 453 ++++++++++++++++++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c | 90 ++++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf | 66 +++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni | 21 +
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni | 20 +
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf | 70 +++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni | 21 +
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni | 20 +
11 files changed, 1857 insertions(+)

diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c b/MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
new file mode 100644
index 0000000..365b8c5
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
@@ -0,0 +1,219 @@
+/** @file
+ Parse the INI configuration file and pass the information to the update driver
+ so that the driver can perform update accordingly.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SystemBiosDxe.h"
+#include <Library/IniParsingLib.h>
+#include <Library/PrintLib.h>
+
+#define MAX_LINE_LENGTH 512
+
+/**
+ Parse Config data file to get the updated data array.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+ @param ConfigHeader Pointer to the config header.
+ @param UpdateArray Pointer to the config of update data.
+
+ @retval EFI_NOT_FOUND No config data is found.
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseUpdateDataFile (
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize,
+ IN OUT CONFIG_HEADER *ConfigHeader,
+ IN OUT UPDATE_CONFIG_DATA **UpdateArray
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *SectionName;
+ CHAR8 Entry[MAX_LINE_LENGTH];
+ UINTN Num;
+ UINT64 Num64;
+ UINTN Index;
+ EFI_GUID FileGuid;
+ VOID *Context;
+
+ //
+ // First process the data buffer and get all sections and entries
+ //
+ Context = OpenDataFile(DataBuffer, BufferSize);
+ if (Context == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Now get NumOfUpdate
+ //
+ Status = GetDecimalUintnFromDataFile(
+ Context,
+ "Head",
+ "NumOfUpdate",
+ &Num
+ );
+ if (EFI_ERROR(Status) || (Num == 0)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+
+ ConfigHeader->NumOfUpdates = Num;
+ *UpdateArray = AllocateZeroPool ((sizeof (UPDATE_CONFIG_DATA) * Num));
+ if (*UpdateArray == NULL) {
+ CloseDataFile(Context);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0 ; Index < ConfigHeader->NumOfUpdates ; Index++) {
+ //
+ // Get the section name of each update
+ //
+ AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update");
+ AsciiValueToString(Entry + AsciiStrLen(Entry), 0, Index, 0);
+ Status = GetStringFromDataFile(
+ Context,
+ "Head",
+ Entry,
+ &SectionName
+ );
+ if (EFI_ERROR(Status) || (SectionName == NULL)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // The section name of this update has been found.
+ // Now looks for all the config data of this update
+ //
+ (*UpdateArray)[Index].Index = Index;
+
+ //
+ // ImageTypeId
+ //
+ Status = GetGuidFromDataFile(
+ Context,
+ SectionName,
+ "ImageTypeId",
+ &FileGuid
+ );
+ if (EFI_ERROR(Status)) {
+ ZeroMem(&((*UpdateArray)[Index].ImageTypeId), sizeof(EFI_GUID));
+ } else {
+ CopyGuid(&((*UpdateArray)[Index].ImageTypeId), &FileGuid);
+ }
+
+ //
+ // FirmwareType
+ //
+ Status = GetDecimalUintnFromDataFile(
+ Context,
+ SectionName,
+ "FirmwareType",
+ &Num
+ );
+ if (EFI_ERROR(Status)) {
+ Num = PlatformFirmwareTypeBios;
+ }
+ (*UpdateArray)[Index].FirmwareType = (PLATFORM_FIRMWARE_TYPE) Num;
+
+ //
+ // AddressType
+ //
+ Status = GetDecimalUintnFromDataFile(
+ Context,
+ SectionName,
+ "AddressType",
+ &Num
+ );
+ if (EFI_ERROR(Status)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+ (*UpdateArray)[Index].AddressType = (FLASH_ADDRESS_TYPE) Num;
+
+ //
+ // BaseAddress
+ //
+ Status = GetHexUint64FromDataFile(
+ Context,
+ SectionName,
+ "BaseAddress",
+ &Num64
+ );
+ if (EFI_ERROR(Status)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+ (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num64;
+
+ //
+ // FileBuid
+ //
+ Status = GetGuidFromDataFile(
+ Context,
+ SectionName,
+ "FileGuid",
+ &FileGuid
+ );
+ if (EFI_ERROR(Status)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+
+ CopyGuid(&((*UpdateArray)[Index].FileGuid), &FileGuid);
+
+ //
+ // Length
+ //
+ Status = GetHexUintnFromDataFile(
+ Context,
+ SectionName,
+ "Length",
+ &Num
+ );
+ if (EFI_ERROR(Status)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+ (*UpdateArray)[Index].Length = (UINTN) Num;
+
+ //
+ // ImageOffset
+ //
+ Status = GetHexUintnFromDataFile(
+ Context,
+ SectionName,
+ "ImageOffset",
+ &Num
+ );
+ if (EFI_ERROR(Status)) {
+ CloseDataFile(Context);
+ return EFI_NOT_FOUND;
+ }
+ (*UpdateArray)[Index].ImageOffset = (UINTN) Num;
+ }
+
+ //
+ // Now all configuration data got. Free those temporary buffers
+ //
+ CloseDataFile(Context);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
new file mode 100644
index 0000000..ce4cbd0
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
@@ -0,0 +1,393 @@
+/** @file
+ System BIOS update header file.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SYSTEM_BIOS_UPDATE_H_
+#define _SYSTEM_BIOS_UPDATE_H_
+
+#include <PiDxe.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FirmwareContentsSigned.h>
+#include <Guid/WinCertificate.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+
+typedef struct {
+ UINT32 LastAttemptVersion;
+ UINT32 LastAttemptStatus;
+} SYSTEM_FMP_LAST_ATTEMPT_VARIABLE;
+
+#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME L"SystemLastAttempVar"
+
+#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID {0x2f564d6f, 0xcc2c, 0x4838, { 0xb9, 0xa8, 0xbe, 0x59, 0x48, 0xb0, 0x3d, 0x59 }}
+
+#define BIOS_FMP_PRIVATE_DATA_SIGNATURE SIGNATURE_32('B', 'I', 'O', 'F')
+
+//
+// BIOS FMP private data structure.
+//
+
+struct _BIOS_FMP_PRIVATE_DATA {
+ UINT32 Signature;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL Fmp;
+ EFI_HANDLE Handle;
+ UINT8 DescriptorCount;
+ EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
+ SYSTEM_FMP_LAST_ATTEMPT_VARIABLE LastAttempt;
+};
+
+typedef struct _BIOS_FMP_PRIVATE_DATA BIOS_FMP_PRIVATE_DATA;
+
+/**
+ Returns a pointer to the BIOS_FMP_PRIVATE_DATA structure from the input a as Fmp.
+
+ If the signatures matches, then a pointer to the data structure that contains
+ a specified field of that data structure is returned.
+
+ @param a Pointer to the field specified by ServiceBinding within
+ a data structure of type BIOS_FMP_PRIVATE_DATA.
+
+**/
+#define BIOS_FMP_PRIVATE_DATA_FROM_FMP(a) \
+ CR ( \
+ (a), \
+ BIOS_FMP_PRIVATE_DATA, \
+ Fmp, \
+ BIOS_FMP_PRIVATE_DATA_SIGNATURE \
+ )
+
+
+//
+// Update data
+//
+
+typedef struct {
+ UINTN NumOfUpdates;
+} CONFIG_HEADER;
+
+typedef struct {
+ UINTN Index;
+ EFI_GUID ImageTypeId;
+ PLATFORM_FIRMWARE_TYPE FirmwareType;
+ FLASH_ADDRESS_TYPE AddressType;
+ EFI_GUID FileGuid;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINTN Length;
+ UINTN ImageOffset;
+} UPDATE_CONFIG_DATA;
+
+//
+// System Firmware Update SMM Communication
+//
+
+#define SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_FUNCTION_SET_IMAGE 1
+
+typedef struct {
+ UINTN Function;
+ EFI_STATUS ReturnStatus;
+//UINT8 Data[];
+} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_HEAD;
+
+#define ABORT_REASON_MAX_SIZE 0x40 // UnicodeStringSize including final L'\0'
+
+#define CAPSULE_IMAGE_ADDITIONAL_MAX_SIZE (0x20020 + 0xA0000) // Addtional size for Capsule Header, FV block alignment + DispatchImage.
+
+typedef struct {
+ UINT8 ImageIndex;
+ UINTN ImageSize;
+ UINTN AbortReasonSize;
+ UINT32 LastAttemptVersion;
+ UINT32 LastAttemptStatus;
+//UINT8 Data[AbortReasonMaxSize + ImageSize];
+} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_SET_IMAGE;
+
+
+/**
+ Returns information about the current firmware image(s) of the device.
+
+ This function allows a copy of the current firmware image to be created and saved.
+ The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
+ On input, this is the size of the buffer allocated by the caller.
+ On output, it is the size of the buffer returned by the firmware
+ if the buffer was large enough, or the size of the buffer needed
+ to contain the image(s) information if the buffer was too small.
+ @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
+ information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+ @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
+ associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] DescriptorCount A pointer to the location in which firmware returns the number of
+ descriptors or firmware images within this device.
+ @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
+ of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] PackageVersion A version number that represents all the firmware images in the device.
+ The format is vendor specific and new version must have a greater value
+ than the old version. If PackageVersion is not supported, the value is
+ 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+ is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+ that package version update is in progress.
+ @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
+ package version name. The buffer is allocated by this function with
+ AllocatePool(), and it is the caller's responsibility to free it with a call
+ to FreePool().
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
+ needed to hold the image(s) information is returned in ImageInfoSize.
+ @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
+ @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN OUT UINTN *ImageInfoSize,
+ IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
+ OUT UINT32 *DescriptorVersion,
+ OUT UINT8 *DescriptorCount,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *PackageVersion,
+ OUT CHAR16 **PackageVersionName
+ );
+
+/**
+ Retrieves a copy of the current firmware image of the device.
+
+ This function allows a copy of the current firmware image to be created and saved.
+ The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in,out] Image Points to the buffer where the current image is copied to.
+ @param[in,out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
+ On return, points to the length of the image, in bytes.
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
+ image. The current buffer size needed to hold the image is returned
+ in ImageSize.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_NOT_FOUND The current image is not copied to the buffer.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN OUT VOID *Image,
+ IN OUT UINTN *ImageSize
+ );
+
+/**
+ Updates the firmware image of the device.
+
+ This function updates the hardware with the new firmware image.
+ This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+ If the firmware image is updatable, the function should perform the following minimal validations
+ before proceeding to do the firmware image update.
+ - Validate the image authentication if image has attribute
+ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+ EFI_SECURITY_VIOLATION if the validation fails.
+ - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+ the image is unsupported. The function can optionally provide more detailed information on
+ why the image is not a supported image.
+ - Validate the data from VendorCode if not null. Image validation must be performed before
+ VendorCode data validation. VendorCode data is ignored or considered invalid if image
+ validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+ VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+ the caller did not specify the policy or use the default policy. As an example, vendor can implement
+ a policy to allow an option to force a firmware image update when the abort reason is due to the new
+ firmware image version is older than the current firmware image version or bad image checksum.
+ Sensitive operations such as those wiping the entire firmware image and render the device to be
+ non-functional should be encoded in the image itself rather than passed with the VendorCode.
+ AbortReason enables vendor to have the option to provide a more detailed description of the abort
+ reason to the caller.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in] Image Points to the new image.
+ @param[in] ImageSize Size of the new image in bytes.
+ @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
+ Null indicates the caller did not specify the policy or use the default policy.
+ @param[in] Progress A function used by the driver to report the progress of the firmware update.
+ @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
+ details for the aborted operation. The buffer is allocated by this function
+ with AllocatePool(), and it is the caller's responsibility to free it with a
+ call to FreePool().
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_ABORTED The operation is aborted.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode,
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
+ OUT CHAR16 **AbortReason
+ );
+
+/**
+ Checks if the firmware image is valid for the device.
+
+ This function allows firmware update application to validate the firmware image without
+ invoking the SetImage() first.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in] Image Points to the new image.
+ @param[in] ImageSize Size of the new image in bytes.
+ @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
+ if available, additional information if the image is invalid.
+
+ @retval EFI_SUCCESS The image was successfully checked.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *ImageUpdatable
+ );
+
+/**
+ Returns information about the firmware package.
+
+ This function returns package information.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[out] PackageVersion A version number that represents all the firmware images in the device.
+ The format is vendor specific and new version must have a greater value
+ than the old version. If PackageVersion is not supported, the value is
+ 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+ comparison is to be performed using PackageVersionName. A value of
+ 0xFFFFFFFD indicates that package version update is in progress.
+ @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
+ the package version name. The buffer is allocated by this function with
+ AllocatePool(), and it is the caller's responsibility to free it with a
+ call to FreePool().
+ @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+ package version name. A value of 0 indicates the device does not support
+ update of package version name. Length is the number of Unicode characters,
+ including the terminating null character.
+ @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
+ Definitions' for possible returned values of this parameter. A value of 1
+ indicates the attribute is supported and the current setting value is
+ indicated in AttributesSetting. A value of 0 indicates the attribute is not
+ supported and the current setting value in AttributesSetting is meaningless.
+ @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
+ values of this parameter
+
+ @retval EFI_SUCCESS The package information was successfully returned.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ OUT UINT32 *PackageVersion,
+ OUT CHAR16 **PackageVersionName,
+ OUT UINT32 *PackageVersionNameMaxLen,
+ OUT UINT64 *AttributesSupported,
+ OUT UINT64 *AttributesSetting
+ );
+
+/**
+ Updates information about the firmware package.
+
+ This function updates package information.
+ This function returns EFI_UNSUPPORTED if the package information is not updatable.
+ VendorCode enables vendor to implement vendor-specific package information update policy.
+ Null if the caller did not specify this policy or use the default policy.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] Image Points to the authentication image.
+ Null if authentication is not required.
+ @param[in] ImageSize Size of the authentication image in bytes.
+ 0 if authentication is not required.
+ @param[in] VendorCode This enables vendor to implement vendor-specific firmware
+ image update policy.
+ Null indicates the caller did not specify this policy or use
+ the default policy.
+ @param[in] PackageVersion The new package version.
+ @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
+ the package version name.
+ The string length is equal to or less than the value returned in
+ PackageVersionNameMaxLen.
+
+ @retval EFI_SUCCESS The device was successfully updated with the new package
+ information.
+ @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
+ returned in PackageVersionNameMaxLen.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode,
+ IN UINT32 PackageVersion,
+ IN CONST CHAR16 *PackageVersionName
+ );
+
+extern EFI_GUID gSystemFmpLastAttemptVariableGuid;
+extern EFI_GUID mCurrentImageTypeId;
+
+#endif
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
new file mode 100644
index 0000000..d3c2aeb
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
@@ -0,0 +1,484 @@
+/** @file
+ Produce FMP instance for system firmware.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SystemBiosDxe.h"
+
+EFI_GUID gSystemFmpLastAttemptVariableGuid = SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID;
+
+//
+// BiosFmp driver private data
+//
+BIOS_FMP_PRIVATE_DATA *mBiosFmpPrivate = NULL;
+
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {
+ FmpGetImageInfo,
+ FmpGetImage,
+ FmpSetImage,
+ FmpCheckImage,
+ FmpGetPackageInfo,
+ FmpSetPackageInfo
+};
+
+/**
+ Returns information about the current firmware image(s) of the device.
+
+ This function allows a copy of the current firmware image to be created and saved.
+ The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
+ On input, this is the size of the buffer allocated by the caller.
+ On output, it is the size of the buffer returned by the firmware
+ if the buffer was large enough, or the size of the buffer needed
+ to contain the image(s) information if the buffer was too small.
+ @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
+ information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+ @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
+ associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] DescriptorCount A pointer to the location in which firmware returns the number of
+ descriptors or firmware images within this device.
+ @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
+ of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] PackageVersion A version number that represents all the firmware images in the device.
+ The format is vendor specific and new version must have a greater value
+ than the old version. If PackageVersion is not supported, the value is
+ 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+ is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+ that package version update is in progress.
+ @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
+ package version name. The buffer is allocated by this function with
+ AllocatePool(), and it is the caller's responsibility to free it with a call
+ to FreePool().
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
+ needed to hold the image(s) information is returned in ImageInfoSize.
+ @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
+ @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo (
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN OUT UINTN *ImageInfoSize,
+ IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
+ OUT UINT32 *DescriptorVersion,
+ OUT UINT8 *DescriptorCount,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *PackageVersion,
+ OUT CHAR16 **PackageVersionName
+ )
+{
+ BIOS_FMP_PRIVATE_DATA *BiosFmpPrivate;
+ EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
+
+ BiosFmpPrivate = BIOS_FMP_PRIVATE_DATA_FROM_FMP(This);
+
+ if(ImageInfoSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*ImageInfoSize < sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * BiosFmpPrivate->DescriptorCount) {
+ *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * BiosFmpPrivate->DescriptorCount;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (ImageInfo == NULL ||
+ DescriptorVersion == NULL ||
+ DescriptorCount == NULL ||
+ DescriptorSize == NULL ||
+ PackageVersion == NULL ||
+ PackageVersionName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * BiosFmpPrivate->DescriptorCount;
+ *DescriptorSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
+ *DescriptorCount = BiosFmpPrivate->DescriptorCount;
+ *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+
+ //
+ // supports 1 ImageInfo descriptor
+ //
+ ImageDescriptor = BiosFmpPrivate->ImageDescriptor;
+ ImageInfo->ImageIndex = ImageDescriptor->ImageIndex;
+ CopyGuid (&ImageInfo->ImageTypeId, &ImageDescriptor->ImageTypeId);
+ ImageInfo->ImageId = ImageDescriptor->ImageId;
+ if (ImageDescriptor->ImageIdNameStringOffset != 0) {
+ ImageInfo->ImageIdName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->ImageIdNameStringOffset);
+ } else {
+ ImageInfo->ImageIdName = NULL;
+ }
+ ImageInfo->Version = ImageDescriptor->Version;
+ if (ImageDescriptor->VersionNameStringOffset != 0) {
+ ImageInfo->VersionName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->VersionNameStringOffset);
+ } else {
+ ImageInfo->VersionName = NULL;
+ }
+ ImageInfo->Size = (UINTN)ImageDescriptor->Size;
+ ImageInfo->AttributesSupported = ImageDescriptor->AttributesSupported;
+ ImageInfo->AttributesSetting = ImageDescriptor->AttributesSetting;
+ ImageInfo->Compatibilities = ImageDescriptor->Compatibilities;
+ ImageInfo->LowestSupportedImageVersion = ImageDescriptor->LowestSupportedImageVersion;
+ ImageInfo->LastAttemptVersion = BiosFmpPrivate->LastAttempt.LastAttemptVersion;
+ ImageInfo->LastAttemptStatus = BiosFmpPrivate->LastAttempt.LastAttemptStatus;
+ ImageInfo->HardwareInstance = ImageDescriptor->HardwareInstance;
+
+ //
+ // package version
+ //
+ *PackageVersion = ImageDescriptor->PackageVersion;
+ if (ImageDescriptor->PackageVersionNameStringOffset != 0) {
+ *PackageVersionName = (VOID *)((UINTN)ImageDescriptor + ImageDescriptor->PackageVersionNameStringOffset);
+ *PackageVersionName = AllocateCopyPool(StrSize(*PackageVersionName), *PackageVersionName);
+ } else {
+ *PackageVersionName = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Retrieves a copy of the current firmware image of the device.
+
+ This function allows a copy of the current firmware image to be created and saved.
+ The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in,out] Image Points to the buffer where the current image is copied to.
+ @param[in,out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
+ On return, points to the length of the image, in bytes.
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
+ image. The current buffer size needed to hold the image is returned
+ in ImageSize.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_NOT_FOUND The current image is not copied to the buffer.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN OUT VOID *Image,
+ IN OUT UINTN *ImageSize
+ )
+{
+ BIOS_FMP_PRIVATE_DATA *BiosFmpPrivate;
+
+ if (Image == NULL || ImageSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BiosFmpPrivate = BIOS_FMP_PRIVATE_DATA_FROM_FMP(This);
+
+ if (ImageIndex == 0 || ImageIndex > BiosFmpPrivate->DescriptorCount || ImageSize == NULL || Image == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Checks if the firmware image is valid for the device.
+
+ This function allows firmware update application to validate the firmware image without
+ invoking the SetImage() first.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in] Image Points to the new image.
+ @param[in] ImageSize Size of the new image in bytes.
+ @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
+ if available, additional information if the image is invalid.
+
+ @retval EFI_SUCCESS The image was successfully checked.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *ImageUpdatable
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Returns information about the firmware package.
+
+ This function returns package information.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[out] PackageVersion A version number that represents all the firmware images in the device.
+ The format is vendor specific and new version must have a greater value
+ than the old version. If PackageVersion is not supported, the value is
+ 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+ comparison is to be performed using PackageVersionName. A value of
+ 0xFFFFFFFD indicates that package version update is in progress.
+ @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
+ the package version name. The buffer is allocated by this function with
+ AllocatePool(), and it is the caller's responsibility to free it with a
+ call to FreePool().
+ @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+ package version name. A value of 0 indicates the device does not support
+ update of package version name. Length is the number of Unicode characters,
+ including the terminating null character.
+ @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
+ Definitions' for possible returned values of this parameter. A value of 1
+ indicates the attribute is supported and the current setting value is
+ indicated in AttributesSetting. A value of 0 indicates the attribute is not
+ supported and the current setting value in AttributesSetting is meaningless.
+ @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
+ values of this parameter
+
+ @retval EFI_SUCCESS The package information was successfully returned.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ OUT UINT32 *PackageVersion,
+ OUT CHAR16 **PackageVersionName,
+ OUT UINT32 *PackageVersionNameMaxLen,
+ OUT UINT64 *AttributesSupported,
+ OUT UINT64 *AttributesSetting
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Updates information about the firmware package.
+
+ This function updates package information.
+ This function returns EFI_UNSUPPORTED if the package information is not updatable.
+ VendorCode enables vendor to implement vendor-specific package information update policy.
+ Null if the caller did not specify this policy or use the default policy.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] Image Points to the authentication image.
+ Null if authentication is not required.
+ @param[in] ImageSize Size of the authentication image in bytes.
+ 0 if authentication is not required.
+ @param[in] VendorCode This enables vendor to implement vendor-specific firmware
+ image update policy.
+ Null indicates the caller did not specify this policy or use
+ the default policy.
+ @param[in] PackageVersion The new package version.
+ @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
+ the package version name.
+ The string length is equal to or less than the value returned in
+ PackageVersionNameMaxLen.
+
+ @retval EFI_SUCCESS The device was successfully updated with the new package
+ information.
+ @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
+ returned in PackageVersionNameMaxLen.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode,
+ IN UINT32 PackageVersion,
+ IN CONST CHAR16 *PackageVersionName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Initialize BiosFmpDriver private data structure.
+
+ @param BiosFmpPrivate private data structure to be initialized.
+
+ @return EFI_SUCCESS private data is initialized.
+**/
+EFI_STATUS
+InitializePrivateData(
+ IN BIOS_FMP_PRIVATE_DATA *BiosFmpPrivate
+ )
+{
+ EFI_STATUS VarStatus;
+ UINTN VarSize;
+
+ BiosFmpPrivate->Signature = BIOS_FMP_PRIVATE_DATA_SIGNATURE;
+ BiosFmpPrivate->Handle = NULL;
+ BiosFmpPrivate->DescriptorCount = 1;
+ CopyMem(&BiosFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
+
+ BiosFmpPrivate->ImageDescriptor = PcdGetPtr(PcdEdkiiSystemFirmwareImageDescriptor);
+
+ BiosFmpPrivate->LastAttempt.LastAttemptVersion = 0x0;
+ BiosFmpPrivate->LastAttempt.LastAttemptStatus = 0x0;
+ VarSize = sizeof(BiosFmpPrivate->LastAttempt);
+ VarStatus = gRT->GetVariable(
+ SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+ &gSystemFmpLastAttemptVariableGuid,
+ NULL,
+ &VarSize,
+ &BiosFmpPrivate->LastAttempt
+ );
+ DEBUG((EFI_D_INFO, "GetLastAttemp - %r\n", VarStatus));
+ DEBUG((EFI_D_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", BiosFmpPrivate->LastAttempt.LastAttemptVersion, BiosFmpPrivate->LastAttempt.LastAttemptStatus));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+ @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR
+
+ @retval TRUE It is a system FMP.
+ @retval FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmp(
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo
+ )
+{
+ GUID *Guid;
+ UINTN Count;
+ UINTN Index;
+
+ Guid = PcdGetPtr(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid);
+ Count = PcdGetSize(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID);
+
+ for (Index = 0; Index < Count; Index++, Guid++) {
+ if (CompareGuid(&FmpImageInfo->ImageTypeId, Guid)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ System BIOS FMP module entrypoint
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @return EFI_SUCCESS System BIOS FMP module is initialized.
+**/
+EFI_STATUS
+EFIAPI
+BiosUpdateMainDxe(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ UINTN NoHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo;
+ UINTN ImageInfoSize;
+ UINT32 DescriptorVersion;
+ UINT8 DescriptorCount;
+ UINTN DescriptorSize;
+ UINT32 PackageVersion;
+ CHAR16 *PackageVersionName;
+
+ //
+ // Make sure only one instance in system
+ //
+ Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiFirmwareManagementProtocolGuid, NULL, &NoHandles, &HandleBuffer);
+ if (!EFI_ERROR(Status)) {
+ for (Index = 0; Index < NoHandles; 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) {
+ FmpImageInfo = AllocateZeroPool(ImageInfoSize);
+ if (FmpImageInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ continue;
+ }
+ Status = Fmp->GetImageInfo (Fmp, &ImageInfoSize, FmpImageInfo, &DescriptorVersion, &DescriptorCount, &DescriptorSize, &PackageVersion, &PackageVersionName);
+ if (!IsSystemFmp(FmpImageInfo)) {
+ FreePool(FmpImageInfo);
+ continue;
+ }
+ FreePool(FmpImageInfo);
+ Status = gBS->UninstallProtocolInterface(HandleBuffer[Index], &gEfiFirmwareManagementProtocolGuid, Fmp);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "Fail to uninstall Fmp - 0x%x\n"));
+ }
+ }
+ FreePool(HandleBuffer);
+ }
+
+ //
+ // Initialize BiosFmpPrivateData
+ //
+ mBiosFmpPrivate = AllocateZeroPool (sizeof(BIOS_FMP_PRIVATE_DATA));
+ if (mBiosFmpPrivate == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = InitializePrivateData(mBiosFmpPrivate);
+ if (EFI_ERROR(Status)) {
+ FreePool(mBiosFmpPrivate);
+ mBiosFmpPrivate = NULL;
+ return Status;
+ }
+
+ //
+ // Install FMP protocol.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mBiosFmpPrivate->Handle,
+ &gEfiFirmwareManagementProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mBiosFmpPrivate->Fmp
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool(mBiosFmpPrivate);
+ mBiosFmpPrivate = NULL;
+ return Status;
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
new file mode 100644
index 0000000..a5cf77c
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
@@ -0,0 +1,453 @@
+/** @file
+ SetImage instance to update system firmware.
+
+ Caution: This module requires additional review when modified.
+ This module will have external input - capsule image.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ FmpSetImage() will receive untrusted input and do basic validation.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SystemBiosDxe.h"
+
+EFI_GUID mCurrentImageTypeId;
+
+BOOLEAN mNvRamUpdated = FALSE;
+
+/**
+ Parse Config data file to get the updated data array.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+ @param ConfigHeader Pointer to the config header.
+ @param UpdateArray Pointer to the config of update data.
+
+ @retval EFI_NOT_FOUND No config data is found.
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseUpdateDataFile(
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize,
+ IN OUT CONFIG_HEADER *ConfigHeader,
+ IN OUT UPDATE_CONFIG_DATA **UpdateArray
+ );
+
+/**
+ Update BIOS image component.
+
+ @param[in] BiosImage Points to the BIOS image.
+ @param[in] BiosImageSize The length of the BIOS image in bytes.
+ @param[in] ConfigData Points to the component configuration structure.
+ @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+ @retval EFI_SUCCESS The BIOS image is updated.
+ @retval EFI_WRITE_PROTECTED The flash device is read only.
+**/
+EFI_STATUS
+PerformUpdate (
+ IN VOID *BiosImage,
+ IN UINTN BiosImageSize,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ OUT UINT32 *LastAttemptVersion,
+ OUT UINT32 *LastAttemptStatus
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG((EFI_D_INFO, "PlatformUpdate:"));
+ DEBUG((EFI_D_INFO, " BaseAddress - 0x%lx,", ConfigData->BaseAddress));
+ DEBUG((EFI_D_INFO, " ImageOffset - 0x%x,", ConfigData->ImageOffset));
+ DEBUG((EFI_D_INFO, " Legnth - 0x%x\n", ConfigData->Length));
+ Status = PerformFlashWrite (
+ ConfigData->FirmwareType,
+ ConfigData->BaseAddress,
+ ConfigData->AddressType,
+ (VOID *)((UINTN)BiosImage + (UINTN)ConfigData->ImageOffset),
+ ConfigData->Length
+ );
+ if (!EFI_ERROR(Status)) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ if (ConfigData->FirmwareType == PlatformFirmwareTypeNvRam) {
+ mNvRamUpdated = TRUE;
+ }
+ } else {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ }
+ return Status;
+}
+
+/**
+ Update BIOS image.
+
+ @param[in] BiosImage Points to the BIOS image.
+ @param[in] BiosImageSize The length of the BIOS image in bytes.
+ @param[in] ConfigImage Points to the config file image.
+ @param[in] ConfigImageSize The length of the config file image in bytes.
+ @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+ @retval EFI_SUCCESS The BIOS image is updated.
+ @retval EFI_WRITE_PROTECTED The flash device is read only.
+**/
+EFI_STATUS
+UpdateImage(
+ IN VOID *BiosImage,
+ IN UINTN BiosImageSize,
+ IN VOID *ConfigImage,
+ IN UINTN ConfigImageSize,
+ OUT UINT32 *LastAttemptVersion,
+ OUT UINT32 *LastAttemptStatus
+ )
+{
+ EFI_STATUS Status;
+ UPDATE_CONFIG_DATA *ConfigData;
+ UPDATE_CONFIG_DATA *UpdateConfigData;
+ CONFIG_HEADER ConfigHeader;
+ UINTN Index;
+
+ if (ConfigImage == NULL) {
+ DEBUG((EFI_D_INFO, "PlatformUpdate (NoConfig):"));
+ DEBUG((EFI_D_INFO, " BaseAddress - 0x%x,", 0));
+ DEBUG((EFI_D_INFO, " Length - 0x%x\n", BiosImageSize));
+ // ASSUME the whole BIOS include NVRAM region.
+ Status = PerformFlashWrite (
+ PlatformFirmwareTypeNvRam,
+ 0,
+ FlashAddressTypeRelativeAddress,
+ BiosImage,
+ BiosImageSize
+ );
+ if (!EFI_ERROR(Status)) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ mNvRamUpdated = TRUE;
+ } else {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ }
+ return Status;
+ }
+
+ ConfigData = NULL;
+ ZeroMem (&ConfigHeader, sizeof(ConfigHeader));
+ Status = ParseUpdateDataFile (
+ ConfigImage,
+ ConfigImageSize,
+ &ConfigHeader,
+ &ConfigData
+ );
+
+ Index = 0;
+ UpdateConfigData = ConfigData;
+ while (Index < ConfigHeader.NumOfUpdates) {
+ if (IsZeroGuid(&UpdateConfigData->ImageTypeId) || CompareGuid(&UpdateConfigData->ImageTypeId, &mCurrentImageTypeId)) {
+ Status = PerformUpdate (
+ BiosImage,
+ BiosImageSize,
+ UpdateConfigData,
+ LastAttemptVersion,
+ LastAttemptStatus
+ );
+ //
+ // Shall updates be serialized so that if an update is not successfully completed,
+ // the remaining updates won't be performed.
+ //
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ Index++;
+ UpdateConfigData++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Authenticate and update BIOS image.
+
+ @param[in] Image The EDKII system FMP capsule image.
+ @param[in] ImageSize The size of the EDKII system FMP capsule image in bytes.
+ @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+ @retval EFI_SUCCESS EDKII system FMP capsule passes authentication and the BIOS image is updated.
+ @retval EFI_SECURITY_VIOLATION EDKII system FMP capsule fails authentication and the BIOS image is not updated.
+ @retval EFI_WRITE_PROTECTED The flash device is read only.
+**/
+EFI_STATUS
+BiosAuthenticatedUpdate(
+ IN VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *LastAttemptVersion,
+ OUT UINT32 *LastAttemptStatus
+ )
+{
+ EFI_STATUS Status;
+ VOID *BiosImage;
+ UINTN BiosImageSize;
+ VOID *ConfigImage;
+ UINTN ConfigImageSize;
+ VOID *AuthenticatedImage;
+ UINTN AuthenticatedImageSize;
+
+ DEBUG((EFI_D_INFO, "BiosAuthenticatedUpdate...\n"));
+
+ Status = CapsuleAuthenticateSystemFirmware(Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_INFO, "BiosAuthenticateImage - %r\n", Status));
+ return Status;
+ }
+
+ ExtractSystemFirmwareImage(AuthenticatedImage, AuthenticatedImageSize, &BiosImage, &BiosImageSize);
+ ExtractConfigImage(AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize);
+
+ Status = UpdateImage(BiosImage, BiosImageSize, ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_INFO, "UpdateImage - %r\n", Status));
+ return Status;
+ }
+
+ DEBUG((EFI_D_INFO, "BiosAuthenticatedUpdate Done\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This code finds variable in storage blocks (Volatile or Non-Volatile).
+
+ @param VariableName Name of Variable to be found.
+ @param VendorGuid Variable vendor GUID.
+ @param Attributes Attribute value of the variable found.
+ @param DataSize Size of Data found. If size is less than the
+ data, this value contains the required size.
+ @param Data Data pointer.
+
+ @return EFI_INVALID_PARAMETER Invalid parameter.
+ @return EFI_SUCCESS Find the specified variable.
+ @return EFI_NOT_FOUND Not found.
+ @return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
+
+**/
+EFI_STATUS
+EFIAPI
+GetVariableHook (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ OUT UINT32 *Attributes OPTIONAL,
+ IN OUT UINTN *DataSize,
+ OUT VOID *Data
+ )
+{
+ DEBUG((EFI_D_INFO, "GetVariableHook - %S, %g\n", VariableName, VendorGuid));
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+
+ This code Finds the Next available variable.
+
+ @param VariableNameSize Size of the variable name.
+ @param VariableName Pointer to variable name.
+ @param VendorGuid Variable Vendor Guid.
+
+ @return EFI_INVALID_PARAMETER Invalid parameter.
+ @return EFI_SUCCESS Find the specified variable.
+ @return EFI_NOT_FOUND Not found.
+ @return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextVariableNameHook (
+ IN OUT UINTN *VariableNameSize,
+ IN OUT CHAR16 *VariableName,
+ IN OUT EFI_GUID *VendorGuid
+ )
+{
+ DEBUG((EFI_D_INFO, "GetNextVariableNameHook - %S, %g\n", VariableName, VendorGuid));
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+
+ This code sets variable in storage blocks (Volatile or Non-Volatile).
+
+ @param VariableName Name of Variable to be found.
+ @param VendorGuid Variable vendor GUID.
+ @param Attributes Attribute value of the variable found
+ @param DataSize Size of Data found. If size is less than the
+ data, this value contains the required size.
+ @param Data Data pointer.
+
+ @return EFI_INVALID_PARAMETER Invalid parameter.
+ @return EFI_SUCCESS Set successfully.
+ @return EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @return EFI_NOT_FOUND Not found.
+ @return EFI_WRITE_PROTECTED Variable is read-only.
+
+**/
+EFI_STATUS
+EFIAPI
+SetVariableHook (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ DEBUG((EFI_D_INFO, "SetVariableHook - %S, %g, 0x%x (0x%x)\n", VariableName, VendorGuid, Attributes, DataSize));
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+
+ This code returns information about the EFI variables.
+
+ @param Attributes Attributes bitmask to specify the type of variables
+ on which to return information.
+ @param MaximumVariableStorageSize Pointer to the maximum size of the storage space available
+ for the EFI variables associated with the attributes specified.
+ @param RemainingVariableStorageSize Pointer to the remaining size of the storage space available
+ for EFI variables associated with the attributes specified.
+ @param MaximumVariableSize Pointer to the maximum size of an individual EFI variables
+ associated with the attributes specified.
+
+ @return EFI_SUCCESS Query successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+QueryVariableInfoHook (
+ IN UINT32 Attributes,
+ OUT UINT64 *MaximumVariableStorageSize,
+ OUT UINT64 *RemainingVariableStorageSize,
+ OUT UINT64 *MaximumVariableSize
+ )
+{
+ DEBUG((EFI_D_INFO, "QueryVariableInfoHook - 0x%x\n", Attributes));
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+ Updates the firmware image of the device.
+
+ This function updates the hardware with the new firmware image.
+ This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+ If the firmware image is updatable, the function should perform the following minimal validations
+ before proceeding to do the firmware image update.
+ - Validate the image authentication if image has attribute
+ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+ EFI_SECURITY_VIOLATION if the validation fails.
+ - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+ the image is unsupported. The function can optionally provide more detailed information on
+ why the image is not a supported image.
+ - Validate the data from VendorCode if not null. Image validation must be performed before
+ VendorCode data validation. VendorCode data is ignored or considered invalid if image
+ validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+ VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+ the caller did not specify the policy or use the default policy. As an example, vendor can implement
+ a policy to allow an option to force a firmware image update when the abort reason is due to the new
+ firmware image version is older than the current firmware image version or bad image checksum.
+ Sensitive operations such as those wiping the entire firmware image and render the device to be
+ non-functional should be encoded in the image itself rather than passed with the VendorCode.
+ AbortReason enables vendor to have the option to provide a more detailed description of the abort
+ reason to the caller.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in] Image Points to the new image.
+ @param[in] ImageSize Size of the new image in bytes.
+ @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
+ Null indicates the caller did not specify the policy or use the default policy.
+ @param[in] Progress A function used by the driver to report the progress of the firmware update.
+ @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
+ details for the aborted operation. The buffer is allocated by this function
+ with AllocatePool(), and it is the caller's responsibility to free it with a
+ call to FreePool().
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_ABORTED The operation is aborted.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode,
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
+ OUT CHAR16 **AbortReason
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS VarStatus;
+ BIOS_FMP_PRIVATE_DATA *BiosFmpPrivate;
+
+ if (Image == NULL || AbortReason == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BiosFmpPrivate = BIOS_FMP_PRIVATE_DATA_FROM_FMP(This);
+ *AbortReason = NULL;
+
+ if (ImageIndex == 0 || ImageIndex > BiosFmpPrivate->DescriptorCount || Image == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = BiosAuthenticatedUpdate((VOID *)Image, ImageSize, &BiosFmpPrivate->LastAttempt.LastAttemptVersion, &BiosFmpPrivate->LastAttempt.LastAttemptStatus);
+ DEBUG((EFI_D_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", BiosFmpPrivate->LastAttempt.LastAttemptVersion, BiosFmpPrivate->LastAttempt.LastAttemptStatus));
+
+ //
+ // If NVRAM is updated, we should no longer touch variable services, because
+ // the current variable driver may not manage the new NVRAM region.
+ //
+ if (mNvRamUpdated) {
+ DEBUG ((EFI_D_INFO, "NvRamUpdated, Update Variable Serivces\n"));
+ gRT->GetVariable = GetVariableHook;
+ gRT->GetNextVariableName = GetNextVariableNameHook;
+ gRT->SetVariable = SetVariableHook;
+ gRT->QueryVariableInfo = QueryVariableInfoHook;
+
+ gRT->Hdr.CRC32 = 0;
+ gBS->CalculateCrc32 (
+ (UINT8 *) &gRT->Hdr,
+ gRT->Hdr.HeaderSize,
+ &gRT->Hdr.CRC32
+ );
+ }
+
+ VarStatus = gRT->SetVariable(
+ SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+ &gSystemFmpLastAttemptVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(BiosFmpPrivate->LastAttempt),
+ &BiosFmpPrivate->LastAttempt
+ );
+ DEBUG((EFI_D_INFO, "SetLastAttemp - %r\n", VarStatus));
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
new file mode 100644
index 0000000..3a28f7f
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
@@ -0,0 +1,90 @@
+/** @file
+ Dummy SetImage instance.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SystemBiosDxe.h"
+
+/**
+ Updates the firmware image of the device.
+
+ This function updates the hardware with the new firmware image.
+ This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+ If the firmware image is updatable, the function should perform the following minimal validations
+ before proceeding to do the firmware image update.
+ - Validate the image authentication if image has attribute
+ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+ EFI_SECURITY_VIOLATION if the validation fails.
+ - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+ the image is unsupported. The function can optionally provide more detailed information on
+ why the image is not a supported image.
+ - Validate the data from VendorCode if not null. Image validation must be performed before
+ VendorCode data validation. VendorCode data is ignored or considered invalid if image
+ validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+ VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+ the caller did not specify the policy or use the default policy. As an example, vendor can implement
+ a policy to allow an option to force a firmware image update when the abort reason is due to the new
+ firmware image version is older than the current firmware image version or bad image checksum.
+ Sensitive operations such as those wiping the entire firmware image and render the device to be
+ non-functional should be encoded in the image itself rather than passed with the VendorCode.
+ AbortReason enables vendor to have the option to provide a more detailed description of the abort
+ reason to the caller.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in] Image Points to the new image.
+ @param[in] ImageSize Size of the new image in bytes.
+ @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
+ Null indicates the caller did not specify the policy or use the default policy.
+ @param[in] Progress A function used by the driver to report the progress of the firmware update.
+ @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
+ details for the aborted operation. The buffer is allocated by this function
+ with AllocatePool(), and it is the caller's responsibility to free it with a
+ call to FreePool().
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_ABORTED The operation is aborted.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode,
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
+ OUT CHAR16 **AbortReason
+ )
+{
+ BIOS_FMP_PRIVATE_DATA *BiosFmpPrivate;
+
+ if (Image == NULL || AbortReason == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BiosFmpPrivate = BIOS_FMP_PRIVATE_DATA_FROM_FMP(This);
+ *AbortReason = NULL;
+
+ if (ImageIndex == 0 || ImageIndex > BiosFmpPrivate->DescriptorCount || Image == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
new file mode 100644
index 0000000..9cda2ee
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
@@ -0,0 +1,66 @@
+## @file
+# SystemBios FMP report driver.
+#
+# Produce FMP instance to report system firmware EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SystemBiosReportDxe
+ MODULE_UNI_FILE = SystemBiosReportDxe.uni
+ FILE_GUID = BC1A046C-7DBD-41F2-94E5-D7595554CAF4
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = BiosUpdateMainDxe
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ SystemBiosMainDxe.c
+ SystemBiosMainSetImageDummy.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ HobLib
+ UefiRuntimeServicesTableLib
+ UefiDriverEntryPoint
+ DxeServicesLib
+ PrintLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+
+[Protocols]
+ gEfiFirmwareManagementProtocolGuid
+
+[Depex]
+ gEfiVariableArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ SystemBiosReportDxeExtra.uni
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
new file mode 100644
index 0000000..7d6fb22
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
@@ -0,0 +1,21 @@
+// /** @file
+// SystemBios FMP report driver.
+//
+// Produce FMP instance to report system firmware EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "SystemBios FMP report driver."
+
+#string STR_MODULE_DESCRIPTION #language en-US "Produce FMP instance to report system firmware EFI_FIRMWARE_IMAGE_DESCRIPTOR."
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
new file mode 100644
index 0000000..8eb2009
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// SystemBiosReportDxe Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"SystemBiosReport DXE Driver"
+
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
new file mode 100644
index 0000000..9e65641
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
@@ -0,0 +1,70 @@
+## @file
+# SystemBios FMP update driver.
+#
+# Produce FMP instance to update system firmware.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SystemBiosUpdateDxe
+ MODULE_UNI_FILE = SystemBiosUpdateDxe.uni
+ FILE_GUID = 0A2FBD15-1C25-407E-8915-60C5652BC2AA
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = BiosUpdateMainDxe
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ SystemBiosMainDxe.c
+ SystemBiosMainSetImage.c
+ ParseConfigProfile.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ HobLib
+ UefiRuntimeServicesTableLib
+ UefiDriverEntryPoint
+ DxeServicesLib
+ EdkiiSystemCapsuleLib
+ PlatformFlashAccessLib
+ IniParsingLib
+ PrintLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+
+[Protocols]
+ gEfiFirmwareManagementProtocolGuid
+
+[Depex]
+ gEfiVariableArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ SystemBiosUpdateDxeExtra.uni
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
new file mode 100644
index 0000000..39ae0e6
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
@@ -0,0 +1,21 @@
+// /** @file
+// SystemBios FMP update driver.
+//
+// Produce FMP instance to update system firmware.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "SystemBios FMP update driver."
+
+#string STR_MODULE_DESCRIPTION #language en-US "Produce FMP instance to update system firmware."
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
new file mode 100644
index 0000000..0ec28bc
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// SystemBiosUpdateDxe Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"SystemBiosUpdate DXE Driver"
+
+
--
2.7.4.windows.1


[PATCH 14/45] MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.

Yao, Jiewen
 

The previous ESRT driver unconditionally treat FMP to be
ESRT_FW_TYPE_DEVICEFIRMWARE.
EDKII System Capsule reuses FMP, but it is ESRT_FW_TYPE_SYSTEMFIRMWARE.

Add check to ImageTypeId check to see if it is ESRT_FW_TYPE_SYSTEMFIRMWARE.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf | 3 +-
MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c | 37 ++++++++++++++++++--
2 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
index 8fbc75b..8b28adc 100644
--- a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+++ b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
@@ -4,7 +4,7 @@
# This driver produces EsrtManagement protocol to manage cache ESRT repository for FMP/Non-FMP instances.
# ESRT table based on repository is published on gEfiEventReadyToBootGuid.
#
-# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
@@ -64,6 +64,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxFmpEsrtCacheNum ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxNonFmpEsrtCacheNum ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid ## CONSUMES

[Depex]
gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
index f6d1e97..f3c03bf 100644
--- a/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
+++ b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
@@ -1,7 +1,7 @@
/** @file
Esrt management implementation.

-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -391,6 +391,35 @@ EXIT:
}

/**
+ Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+ @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR
+
+ @return TRUE It is a system FMP.
+ @return FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmp (
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo
+ )
+{
+ GUID *Guid;
+ UINTN Count;
+ UINTN Index;
+
+ Guid = PcdGetPtr(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid);
+ Count = PcdGetSize(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid)/sizeof(GUID);
+
+ for (Index = 0; Index < Count; Index++, Guid++) {
+ if (CompareGuid(&FmpImageInfo->ImageTypeId, Guid)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
Init one ESRT entry according to input FmpImageInfo (V1, V2, V3) .

@param[in, out] EsrtEntry Esrt entry to be Init
@@ -407,7 +436,11 @@ SetEsrtEntryFromFmpInfo (
{
EsrtEntry->FwVersion = FmpImageInfo->Version;
EsrtEntry->FwClass = FmpImageInfo->ImageTypeId;
- EsrtEntry->FwType = ESRT_FW_TYPE_DEVICEFIRMWARE;
+ if (IsSystemFmp(FmpImageInfo)) {
+ EsrtEntry->FwType = ESRT_FW_TYPE_SYSTEMFIRMWARE;
+ } else {
+ EsrtEntry->FwType = ESRT_FW_TYPE_DEVICEFIRMWARE;
+ }
EsrtEntry->LowestSupportedFwVersion = 0;
EsrtEntry->CapsuleFlags = 0;
EsrtEntry->LastAttemptVersion = 0;
--
2.7.4.windows.1


[PATCH 13/45] MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib.

Yao, Jiewen
 

Add NULL instance to pass build.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c | 54 ++++++++++++++++++++
MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf | 40 +++++++++++++++
MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni | 21 ++++++++
3 files changed, 115 insertions(+)

diff --git a/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
new file mode 100644
index 0000000..7bbe37e
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
@@ -0,0 +1,54 @@
+/** @file
+ Platform flash device access library NULL instance.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+
+UINT64 mInternalFdAddress;
+
+/**
+ Perform flash write opreation.
+
+ @param FirmwareType The type of firmware.
+ @param FlashAddress The address of flash device to be accessed.
+ @param FlashAddressType The type of flash device address.
+ @param Buffer The pointer to the data buffer.
+ @param Length The length of data buffer in bytes.
+
+ @retval EFI_SUCCESS The operation returns successfully.
+ @retval EFI_WRITE_PROTECTED The flash device is read only.
+ @retval EFI_UNSUPPORTED The flash device access is unsupported.
+ @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite(
+ IN PLATFORM_FIRMWARE_TYPE FirmwareType,
+ IN EFI_PHYSICAL_ADDRESS FlashAddress,
+ IN FLASH_ADDRESS_TYPE FlashAddressType,
+ IN VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ if (FirmwareType >= PlatformFirmwareTypeMax) {
+ return EFI_UNSUPPORTED;
+ }
+ if (FlashAddressType == FlashAddressTypeRelativeAddress) {
+ FlashAddress = FlashAddress + mInternalFdAddress;
+ }
+ CopyMem((VOID *)(UINTN)(FlashAddress), Buffer, Length);
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
new file mode 100644
index 0000000..262821d
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
@@ -0,0 +1,40 @@
+## @file
+# Platform flash device access library.
+#
+# Platform flash device access library NULL instance.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformFlashAccessLibNull
+ MODULE_UNI_FILE = PlatformFlashAccessLibNull.uni
+ FILE_GUID = A0534D92-9776-4E4E-9234-C9DC1849DBB5
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformFlashAccessLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PlatformFlashAccessLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
diff --git a/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
new file mode 100644
index 0000000..ae2648e
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
@@ -0,0 +1,21 @@
+// /** @file
+// Platform flash device access library.
+//
+// Platform flash device access library NULL instance.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Platform flash device access library."
+
+#string STR_MODULE_DESCRIPTION #language en-US "Platform flash device access library NULL instance."
+
--
2.7.4.windows.1


[PATCH 12/45] MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib instance.

Yao, Jiewen
 

This library is used to abstract the action for EDKII system FMP capsule,
such as extracting a component from capsule, or authenticate the capsule.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c | 609 ++++++++++++++++++++
MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf | 55 ++
MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni | 22 +
3 files changed, 686 insertions(+)

diff --git a/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
new file mode 100644
index 0000000..e1bc0b6
--- /dev/null
+++ b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
@@ -0,0 +1,609 @@
+/** @file
+ EDKII System Capsule library.
+
+ EDKII System Capsule library instance.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FirmwareContentsSigned.h>
+#include <Guid/WinCertificate.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+#include <Library/FmpAuthenticationLib.h>
+
+#include <Protocol/FirmwareManagement.h>
+
+EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *mImageFmpInfo;
+UINTN mImageFmpInfoSize;
+EFI_GUID mEdkiiSystemFirmwareFileGuid;
+
+/**
+ Check if a block of buffer is erased.
+
+ @param[in] ErasePolarity Erase polarity attribute of the firmware volume
+ @param[in] InBuffer The buffer to be checked
+ @param[in] BufferSize Size of the buffer in bytes
+
+ @retval TRUE The block of buffer is erased
+ @retval FALSE The block of buffer is not erased
+**/
+BOOLEAN
+IsBufferErased (
+ IN UINT8 ErasePolarity,
+ IN VOID *InBuffer,
+ IN UINTN BufferSize
+ )
+{
+ UINTN Count;
+ UINT8 EraseByte;
+ UINT8 *Buffer;
+
+ if(ErasePolarity == 1) {
+ EraseByte = 0xFF;
+ } else {
+ EraseByte = 0;
+ }
+
+ Buffer = InBuffer;
+ for (Count = 0; Count < BufferSize; Count++) {
+ if (Buffer[Count] != EraseByte) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Get Section buffer pointer by SectionType and SectionInstance.
+
+ @param[in] SectionBuffer The buffer of section
+ @param[in] SectionBufferSize The size of SectionBuffer in bytes
+ @param[in] SectionType The SectionType of Section to be found
+ @param[in] SectionInstance The Instance of Section to be found
+ @param[out] OutSectionBuffer The section found, including SECTION_HEADER
+ @param[out] OutSectionSize The size of section found, including SECTION_HEADER
+
+ @retval TRUE The FFS buffer is found.
+ @retval FALSE The FFS buffer is not found.
+**/
+BOOLEAN
+GetSectionByType(
+ IN VOID *SectionBuffer,
+ IN UINT32 SectionBufferSize,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN SectionInstance,
+ OUT VOID **OutSectionBuffer,
+ OUT UINTN *OutSectionSize
+ )
+{
+ EFI_COMMON_SECTION_HEADER *SectionHeader;
+ UINTN SectionSize;
+ UINTN Instance;
+
+ DEBUG ((DEBUG_INFO, "GetSectionByType - Buffer: 0x%08x - 0x%08x\n", SectionBuffer, SectionBufferSize));
+
+ //
+ // Find Section
+ //
+ SectionHeader = SectionBuffer;
+
+ Instance = 0;
+ while ((UINTN)SectionHeader < (UINTN)SectionBuffer + SectionBufferSize) {
+ DEBUG ((DEBUG_INFO, "GetSectionByType - Section: 0x%08x\n", SectionHeader));
+ if (IS_SECTION2(SectionHeader)) {
+ SectionSize = SECTION2_SIZE(SectionHeader);
+ } else {
+ SectionSize = SECTION_SIZE(SectionHeader);
+ }
+
+ if (SectionHeader->Type == SectionType) {
+ if (Instance == SectionInstance) {
+ *OutSectionBuffer = (UINT8 *)SectionHeader;
+ *OutSectionSize = SectionSize;
+ DEBUG((DEBUG_INFO, "GetSectionByType - 0x%x - 0x%x\n", *OutSectionBuffer, *OutSectionSize));
+ return TRUE;
+ } else {
+ DEBUG((DEBUG_INFO, "GetSectionByType - find section instance %x\n", Instance));
+ Instance++;
+ }
+ } else {
+ //
+ // Skip other section type
+ //
+ DEBUG ((DEBUG_INFO, "GetSectionByType - other section type 0x%x\n", SectionHeader->Type));
+ }
+
+ //
+ // Next Section
+ //
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *)((UINTN)SectionHeader + ALIGN_VALUE(SectionSize, 4));
+ }
+
+ return FALSE;
+}
+
+/**
+ Get FFS buffer pointer by FileName GUID and FileType.
+
+ @param[in] FdStart The BIOS FD image
+ @param[in] FdSize The size of BIOS FD image
+ @param[in] FileName The FileName GUID of FFS to be found
+ @param[in] Type The FileType of FFS to be found
+ @param[out] OutFfsBuffer The FFS buffer found, including FFS_FILE_HEADER
+ @param[out] OutFfsBufferSize The size of FFS buffer found, including FFS_FILE_HEADER
+
+ @retval TRUE The FFS buffer is found.
+ @retval FALSE The FFS buffer is not found.
+**/
+BOOLEAN
+GetFfsByName (
+ IN VOID *FdStart,
+ IN UINTN FdSize,
+ IN EFI_GUID *FileName,
+ IN EFI_FV_FILETYPE Type,
+ OUT VOID **OutFfsBuffer,
+ OUT UINTN *OutFfsBufferSize
+ )
+{
+ UINTN FvSize;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ UINT32 FfsSize;
+ UINTN TestLength;
+ BOOLEAN FvFound;
+
+ DEBUG ((DEBUG_INFO, "GetFfsByName - FV: 0x%08x - 0x%08x\n", (UINTN)FdStart, (UINTN)FdSize));
+
+ FvFound = FALSE;
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FdStart;
+ while ((UINTN)FvHeader < (UINTN)FdStart + FdSize - 1) {
+ FvSize = (UINTN)FdStart + FdSize - (UINTN)FvHeader;
+
+ if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvHeader + SIZE_4KB);
+ continue;
+ }
+ DEBUG((DEBUG_ERROR, "checking FV....0x%08x - 0x%x\n", FvHeader, FvHeader->FvLength));
+ FvFound = TRUE;
+ if (FvHeader->FvLength > FvSize) {
+ DEBUG((DEBUG_ERROR, "GetFfsByName - FvSize: 0x%08x, MaxSize - 0x%08x\n", (UINTN)FvHeader->FvLength, (UINTN)FvSize));
+ return FALSE;
+ }
+ FvSize = (UINTN)FvHeader->FvLength;
+
+ //
+ // Find FFS
+ //
+ if (FvHeader->ExtHeaderOffset != 0) {
+ FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FvHeader + FvHeader->ExtHeaderOffset);
+ FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvExtHeader + FvExtHeader->ExtHeaderSize);
+ } else {
+ FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvHeader + FvHeader->HeaderLength);
+ }
+ FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FvHeader + ALIGN_VALUE((UINTN)FfsHeader - (UINTN)FvHeader, 8));
+
+ while ((UINTN)FfsHeader < (UINTN)FvHeader + FvSize - 1) {
+ DEBUG((DEBUG_INFO, "GetFfsByName - FFS: 0x%08x\n", FfsHeader));
+ TestLength = (UINTN)((UINTN)FvHeader + FvSize - (UINTN)FfsHeader);
+ if (TestLength > sizeof(EFI_FFS_FILE_HEADER)) {
+ TestLength = sizeof(EFI_FFS_FILE_HEADER);
+ }
+ if (IsBufferErased(1, FfsHeader, TestLength)) {
+ break;
+ }
+
+ if (IS_FFS_FILE2(FfsHeader)) {
+ FfsSize = FFS_FILE2_SIZE(FfsHeader);
+ } else {
+ FfsSize = FFS_FILE_SIZE(FfsHeader);
+ }
+
+ if (CompareGuid(FileName, &FfsHeader->Name) &&
+ ((Type == EFI_FV_FILETYPE_ALL) || (FfsHeader->Type == Type))) {
+ //
+ // Check section
+ //
+ *OutFfsBuffer = FfsHeader;
+ *OutFfsBufferSize = FfsSize;
+ return TRUE;
+ } else {
+ //
+ // Any other type is not allowed
+ //
+ DEBUG((DEBUG_INFO, "GetFfsByName - other FFS type 0x%x, name %g\n", FfsHeader->Type, &FfsHeader->Name));
+ }
+
+ //
+ // Next File
+ //
+ FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FfsHeader + ALIGN_VALUE(FfsSize, 8));
+ }
+
+ //
+ // Next FV
+ //
+ FvHeader = (VOID *)(UINTN)((UINTN)FvHeader + FvHeader->FvLength);
+ DEBUG((DEBUG_ERROR, "Next FV....0x%08x - 0x%x\n", FvHeader, FvHeader->FvLength));
+ }
+
+ if (!FvFound) {
+ DEBUG((DEBUG_ERROR, "GetFfsByName - NO FV Found\n"));
+ }
+ return FALSE;
+}
+
+/**
+ Extract the driver FV from an authenticated image.
+
+ @param[in] AuthenticatedImage The authenticated capsule image.
+ @param[in] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+ @param[out] DriverFvImage The driver FV image.
+ @param[out] DriverFvImageSize The size of the driver FV image in bytes.
+
+ @retval TRUE The driver Fv is extracted.
+ @retval FALSE The driver Fv is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractDriverFvImage(
+ IN VOID *AuthenticatedImage,
+ IN UINTN AuthenticatedImageSize,
+ OUT VOID **DriverFvImage,
+ OUT UINTN *DriverFvImageSize
+ )
+{
+ BOOLEAN Result;
+ UINT32 FileHeaderSize;
+
+ *DriverFvImage = NULL;
+ *DriverFvImageSize = 0;
+
+ Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &gEdkiiSystemFmpCapsuleDriverFvFileGuid, EFI_FV_FILETYPE_RAW, DriverFvImage, DriverFvImageSize);
+ if (!Result) {
+ return FALSE;
+ }
+
+ if (IS_FFS_FILE2(*DriverFvImage)) {
+ FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+ } else {
+ FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+ }
+ *DriverFvImage = (UINT8 *)*DriverFvImage + FileHeaderSize;
+ *DriverFvImageSize = *DriverFvImageSize - FileHeaderSize;
+
+ return Result;
+}
+
+/**
+ Extract the config image from an authenticated image.
+
+ @param[in] AuthenticatedImage The authenticated capsule image.
+ @param[in] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+ @param[out] ConfigImage The config image.
+ @param[out] ConfigImageSize The size of the config image in bytes.
+
+ @retval TRUE The config image is extracted.
+ @retval FALSE The config image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractConfigImage(
+ IN VOID *AuthenticatedImage,
+ IN UINTN AuthenticatedImageSize,
+ OUT VOID **ConfigImage,
+ OUT UINTN *ConfigImageSize
+ )
+{
+ BOOLEAN Result;
+ UINT32 FileHeaderSize;
+
+ *ConfigImage = NULL;
+ *ConfigImageSize = 0;
+
+ Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &gEdkiiSystemFmpCapsuleConfigFileGuid, EFI_FV_FILETYPE_RAW, ConfigImage, ConfigImageSize);
+ if (!Result) {
+ return FALSE;
+ }
+
+ if (IS_FFS_FILE2(*ConfigImage)) {
+ FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+ } else {
+ FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+ }
+ *ConfigImage = (UINT8 *)*ConfigImage + FileHeaderSize;
+ *ConfigImageSize = *ConfigImageSize - FileHeaderSize;
+
+ return Result;
+}
+
+/**
+ Extract the authenticated image from an FMP capsule image.
+
+ @param[in] Image The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[in] ImageSize The size of FMP capsule image in bytes.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] AuthenticatedImage The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[out] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+
+ @retval TRUE The authenticated image is extracted.
+ @retval FALSE The authenticated image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractAuthenticatedImage(
+ IN VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *LastAttemptStatus,
+ OUT VOID **AuthenticatedImage,
+ OUT UINTN *AuthenticatedImageSize
+ )
+{
+ EFI_FIRMWARE_IMAGE_AUTHENTICATION *ImageAuthentication;
+ UINTN ImageOffset;
+ EFI_STATUS Status;
+
+ DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - Image: 0x%08x - 0x%08x\n", (UINTN)Image, (UINTN)ImageSize));
+
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+
+ Status = ExecuteFmpAuthenticationHandler(
+ Image,
+ ImageSize,
+ LastAttemptStatus
+ );
+ if (EFI_ERROR(Status)) {
+ // Authentication fail
+ DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - %r\n", Status));
+ // LastAttemptStatus might not be updated. Double check.
+ if (*LastAttemptStatus == LAST_ATTEMPT_STATUS_SUCCESS) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ }
+ return FALSE;
+ }
+
+ //
+ // Authentication pass
+ // LastAttemptStatus must be updated.
+ //
+ if (*LastAttemptStatus == LAST_ATTEMPT_STATUS_SUCCESS) {
+ ImageAuthentication = (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image;
+ ImageOffset = ImageAuthentication->AuthInfo.Hdr.dwLength + sizeof(UINT64);
+ *AuthenticatedImage = (UINT8 *)Image + ImageOffset;
+ *AuthenticatedImageSize = ImageSize - ImageOffset;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Extract ImageFmpInfo from system firmware.
+
+ @param[in] BiosImage The BIOS image.
+ @param[in] BiosImageSize The size of the BIOS image in bytes.
+ @param[out] ImageFmpInfo The ImageFmpInfo.
+ @param[out] ImageFmpInfoSize The size of the ImageFmpInfo in bytes.
+
+ @retval TRUE The ImageFmpInfo is extracted.
+ @retval FALSE The ImageFmpInfo is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractSystemFirmwareImageFmpInfo(
+ IN VOID *BiosImage,
+ IN UINTN BiosImageSize,
+ OUT EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR **ImageFmpInfo,
+ OUT UINTN *ImageFmpInfoSize
+ )
+{
+ BOOLEAN Result;
+ UINT32 SectionHeaderSize;
+ UINT32 FileHeaderSize;
+
+ *ImageFmpInfo = NULL;
+ *ImageFmpInfoSize = 0;
+
+ Result = GetFfsByName(BiosImage, BiosImageSize, &gEdkiiSystemFirmwareImageDescriptorFileGuid, EFI_FV_FILETYPE_ALL, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
+ if (!Result) {
+ return FALSE;
+ }
+ if (IS_FFS_FILE2 (*ImageFmpInfo)) {
+ FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+ } else {
+ FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+ }
+ *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + FileHeaderSize);
+ *ImageFmpInfoSize = *ImageFmpInfoSize - FileHeaderSize;
+
+ Result = GetSectionByType(*ImageFmpInfo, (UINT32)*ImageFmpInfoSize, EFI_SECTION_RAW, 0, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
+ if (!Result) {
+ return FALSE;
+ }
+ if (IS_SECTION2(*ImageFmpInfo)) {
+ SectionHeaderSize = sizeof(EFI_RAW_SECTION2);
+ } else {
+ SectionHeaderSize = sizeof(EFI_RAW_SECTION);
+ }
+ *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + SectionHeaderSize);
+ *ImageFmpInfoSize = *ImageFmpInfoSize - SectionHeaderSize;
+
+ return TRUE;
+}
+
+/**
+ Extract the BIOS image from an authenticated image.
+
+ @param[in] AuthenticatedImage The authenticated capsule image.
+ @param[in] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+ @param[out] BiosImage The BIOS image.
+ @param[out] BiosImageSize The size of the BIOS image in bytes.
+
+ @retval TRUE The BIOS image is extracted.
+ @retval FALSE The BIOS image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractSystemFirmwareImage(
+ IN VOID *AuthenticatedImage,
+ IN UINTN AuthenticatedImageSize,
+ OUT VOID **BiosImage,
+ OUT UINTN *BiosImageSize
+ )
+{
+ BOOLEAN Result;
+ UINT32 FileHeaderSize;
+
+ *BiosImage = NULL;
+ *BiosImageSize = 0;
+
+ Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &mEdkiiSystemFirmwareFileGuid, EFI_FV_FILETYPE_RAW, BiosImage, BiosImageSize);
+ if (!Result) {
+ // no nested FV, just return all data.
+ *BiosImage = AuthenticatedImage;
+ *BiosImageSize = AuthenticatedImageSize;
+
+ return TRUE;
+ }
+ if (IS_FFS_FILE2 (*BiosImage)) {
+ FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+ } else {
+ FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+ }
+ *BiosImage = (UINT8 *)*BiosImage + FileHeaderSize;
+ *BiosImageSize = *BiosImageSize - FileHeaderSize;
+
+ return Result;
+}
+
+/**
+ Authenticated system firmware FMP capsule image.
+
+ @param[in] Image The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[in] ImageSize The size of FMP capsule image in bytes.
+ @param[in] ForceVersionMatch TRUE: The version of capsule must be as same as the version of current image.
+ FALSE: The version of capsule must be as same as greater than the lowest
+ supported version of current image.
+ @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] AuthenticatedImage The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[out] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+
+ @retval TRUE Authentication passes and the authenticated image is extracted.
+ @retval FALSE Authentication fails and the authenticated image is not extracted.
+**/
+EFI_STATUS
+EFIAPI
+CapsuleAuthenticateSystemFirmware (
+ IN VOID *Image,
+ IN UINTN ImageSize,
+ IN BOOLEAN ForceVersionMatch,
+ OUT UINT32 *LastAttemptVersion,
+ OUT UINT32 *LastAttemptStatus,
+ OUT VOID **AuthenticatedImage,
+ OUT UINTN *AuthenticatedImageSize
+ )
+{
+ BOOLEAN Result;
+ EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageFmpInfo;
+ UINTN ImageFmpInfoSize;
+ EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageFmpInfo;
+ UINTN CurrentImageFmpInfoSize;
+ VOID *BiosImage;
+ UINTN BiosImageSize;
+
+ *LastAttemptVersion = 0;
+
+ //
+ // NOTE: This function need run in an isolated environment.
+ // Do not touch FMP protocol and its private structure.
+ //
+
+ Result = ExtractAuthenticatedImage((VOID *)Image, ImageSize, LastAttemptStatus, AuthenticatedImage, AuthenticatedImageSize);
+ if (!Result) {
+ DEBUG((EFI_D_INFO, "ExtractAuthenticatedImage - fail\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ DEBUG((EFI_D_INFO, "AuthenticatedImage - 0x%x - 0x%x\n", *AuthenticatedImage, *AuthenticatedImageSize));
+
+ Result = ExtractSystemFirmwareImage(*AuthenticatedImage, *AuthenticatedImageSize, &BiosImage, &BiosImageSize);
+ if (!Result) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ DEBUG((EFI_D_INFO, "ExtractBiosImage - fail\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+ DEBUG((EFI_D_INFO, "BiosImage - 0x%x - 0x%x\n", BiosImage, BiosImageSize));
+
+ Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize, &ImageFmpInfo, &ImageFmpInfoSize);
+ if (!Result) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ DEBUG((EFI_D_INFO, "ExtractSystemFirmwareImageFmpInfo - fail\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ *LastAttemptVersion = ImageFmpInfo->Version;
+ DEBUG((EFI_D_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", ImageFmpInfo, ImageFmpInfoSize));
+ DEBUG((EFI_D_INFO, "NewImage Version - 0x%x\n", ImageFmpInfo->Version));
+ DEBUG((EFI_D_INFO, "NewImage LowestSupportedImageVersion - 0x%x\n", ImageFmpInfo->LowestSupportedImageVersion));
+
+ CurrentImageFmpInfo = mImageFmpInfo;
+ CurrentImageFmpInfoSize = mImageFmpInfoSize;
+
+ DEBUG((EFI_D_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", CurrentImageFmpInfo, CurrentImageFmpInfoSize));
+ DEBUG((EFI_D_INFO, "Current Version - 0x%x\n", CurrentImageFmpInfo->Version));
+ DEBUG((EFI_D_INFO, "Current LowestSupportedImageVersion - 0x%x\n", CurrentImageFmpInfo->LowestSupportedImageVersion));
+
+ if (ForceVersionMatch) {
+ if (CurrentImageFmpInfo->Version != ImageFmpInfo->Version) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+ DEBUG((EFI_D_INFO, "ForceVersionMatch check - fail\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+ } else {
+ if (CurrentImageFmpInfo->Version < ImageFmpInfo->LowestSupportedImageVersion) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+ DEBUG((EFI_D_INFO, "LowestSupportedImageVersion check - fail\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+ }
+
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ return EFI_SUCCESS;
+}
+
+/**
+ The constructor function.
+
+ @retval EFI_SUCCESS The constructor successfully .
+**/
+EFI_STATUS
+EFIAPI
+EdkiiSystemCapsuleLibConstructor(
+ VOID
+ )
+{
+ mImageFmpInfoSize = PcdGetSize(PcdEdkiiSystemFirmwareImageDescriptor);
+ mImageFmpInfo = AllocateCopyPool (mImageFmpInfoSize, PcdGetPtr(PcdEdkiiSystemFirmwareImageDescriptor));
+ ASSERT(mImageFmpInfo != NULL);
+ CopyGuid(&mEdkiiSystemFirmwareFileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid));
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
new file mode 100644
index 0000000..2657367
--- /dev/null
+++ b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
@@ -0,0 +1,55 @@
+## @file
+# EDKII System Capsule library.
+#
+# EDKII System Capsule library instance for DXE/PEI post memory phase.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EdkiiSystemCapsuleLib
+ MODULE_UNI_FILE = EdkiiSystemCapsuleLib.uni
+ FILE_GUID = 109D5FC6-56E6-481A-88EF-0CB828FBE0F6
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = EdkiiSystemCapsuleLib
+ CONSTRUCTOR = EdkiiSystemCapsuleLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ EdkiiSystemCapsuleLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ FmpAuthenticationLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareFileGuid
+
+[Guids]
+ gEdkiiSystemFirmwareImageDescriptorFileGuid
+ gEdkiiSystemFmpCapsuleConfigFileGuid
+ gEdkiiSystemFmpCapsuleDriverFvFileGuid
+
diff --git a/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
new file mode 100644
index 0000000..93e959e
--- /dev/null
+++ b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// EDKII System Capsule library.
+//
+// EDKII System Capsule library instance for DXE/PEI post memory phase.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "EDKII System Capsule library."
+
+#string STR_MODULE_DESCRIPTION #language en-US "EDKII System Capsule library instance for DXE/PEI post memory phase."
+
--
2.7.4.windows.1


[PATCH 11/45] MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.

Yao, Jiewen
 

Add ProcessCapsules() interface for DxeCapsuleLibNull.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c | 47 ++++++++++++++++++--
1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
index fb5c255..0f70e4f 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
@@ -1,7 +1,7 @@
/** @file
Null Dxe Capsule Library instance does nothing and returns unsupport status.

-Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -17,7 +17,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
/**
The firmware checks whether the capsule image is supported
by the CapsuleGuid in CapsuleHeader or other specific information in capsule image.
-
+
+ Caution: This function may receive untrusted input.
+
@param CapsuleHeader Point to the UEFI capsule image to be checked.

@retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
@@ -34,7 +36,9 @@ SupportCapsuleImage (
/**
The firmware specific implementation processes the capsule image
if it recognized the format of this capsule image.
-
+
+ Caution: This function may receive untrusted input.
+
@param CapsuleHeader Point to the UEFI capsule image to be processed.

@retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
@@ -48,4 +52,41 @@ ProcessCapsuleImage (
return EFI_UNSUPPORTED;
}

+/**
+
+ This routine is called to process capsules.
+
+ Caution: This function may receive untrusted input.
+
+ If the current boot mode is NOT BOOT_ON_FLASH_UPDATE, this routine does nothing.
+ If the current boot mode is BOOT_ON_FLASH_UPDATE, the capsules reported in
+ EFI_HOB_UEFI_CAPSULE are processed. If there is no EFI_HOB_UEFI_CAPSULE, this
+ routine does nothing.
+
+ This routine should be called twice in BDS.
+ 1) The first call must be before EndOfDxe. The system capsules is processed.
+ If device capsule FMP protocols are exposted at this time and device FMP
+ capsule has zero EmbeddedDriverCount, the device capsules are processed.
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ 2) The second call must be after EndOfDxe and after ConnectAll, so that all
+ device capsule FMP protocols are exposed.
+ The system capsules are skipped. If the device capsules are NOT processed
+ in first call, they are processed here.
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ @retval EFI_SUCCESS There is no error when processing capsules.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsules(
+ VOID
+ )
+{
+ return EFI_UNSUPPORTED;
+}

--
2.7.4.windows.1


[PATCH 10/45] MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.

Yao, Jiewen
 

This instance handles Microsoft UX capsule, UEFI defined device FMP capsule,
and EDKII system FMP capsule.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c | 1538 ++++++++++++++++++++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf | 82 ++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni | 22 +
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c | 517 +++++++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c | 447 ++++++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c | 112 ++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf | 85 ++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni | 22 +
8 files changed, 2825 insertions(+)

diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
new file mode 100644
index 0000000..4cb3044
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
@@ -0,0 +1,1538 @@
+/** @file
+ DXE capsule library.
+
+ Caution: This module requires additional review when modified.
+ This module will have external input - capsule image.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ SupportCapsuleImage(), ProcessCapsuleImage() will receive untrusted input
+ and do basic validation.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Bmp.h>
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+#include <Guid/FmpCapsule.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/EsrtManagement.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/DevicePath.h>
+
+EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable = NULL;
+BOOLEAN mIsVirtualAddrConverted = FALSE;
+BOOLEAN mDxeCapsuleLibEndOfDxe = FALSE;
+
+GUID *mEdkiiSystemFmpCapsuleImageTypeIdGuid;
+UINTN mEdkiiSystemFmpCapsuleImageTypeIdGuidCount;
+
+/**
+ Initialize capsule related variables.
+**/
+VOID
+InitCapsuleVariable(
+ VOID
+ );
+
+/**
+ Check if this FMP capsule is recorded.
+
+ @param CapsuleHeader The capsule image header
+ @param PayloadIndex FMP payload index
+ @param ImageHeader FMP image header
+
+ @retval TRUE This FMP capsule is recorded.
+ @retval FALSE This FMP capsule is not recorded.
+**/
+BOOLEAN
+IsFmpCapsuleVariableRecorded(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN UINTN PayloadIndex,
+ IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
+ );
+
+/**
+ Record capsule status variable.
+
+ @param CapsuleHeader The capsule image header
+ @param CapsuleStatus The capsule process stauts
+
+ @retval EFI_SUCCESS The capsule status variable is recorded.
+ @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
+**/
+EFI_STATUS
+RecordCapsuleStatusVariable(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN EFI_STATUS CapsuleStatus
+ );
+
+/**
+ Record FMP capsule status variable.
+
+ @param CapsuleHeader The capsule image header
+ @param CapsuleStatus The capsule process stauts
+ @param PayloadIndex FMP payload index
+ @param ImageHeader FMP image header
+
+ @retval EFI_SUCCESS The capsule status variable is recorded.
+ @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
+**/
+EFI_STATUS
+RecordFmpCapsuleStatusVariable(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN EFI_STATUS CapsuleStatus,
+ IN UINTN PayloadIndex,
+ IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
+ );
+
+/**
+ Function indicate the current completion progress of the firmware
+ update. Platform may override with own specific progress function.
+
+ @param Completion A value between 1 and 100 indicating the current completion progress of the firmware update
+
+ @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+**/
+EFI_STATUS
+EFIAPI
+Update_Image_Progress (
+ IN UINTN Completion
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+ @param[in] FmpImageHeader A pointer to EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
+
+ @retval TRUE It is a system FMP.
+ @retval FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmpImage (
+ IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *FmpImageHeader
+ )
+{
+ GUID *Guid;
+ UINTN Count;
+ UINTN Index;
+
+ Guid = mEdkiiSystemFmpCapsuleImageTypeIdGuid;
+ Count = mEdkiiSystemFmpCapsuleImageTypeIdGuidCount;
+
+ for (Index = 0; Index < Count; Index++, Guid++) {
+ if (CompareGuid(&FmpImageHeader->UpdateImageTypeId, Guid)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ 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;
+}
+
+/**
+ This function assumes the input Capusule image already passes basic check in
+ ValidateFmpCapsule().
+
+ Criteria of system FMP capsule is:
+ 1) FmpCapsuleHeader->EmbeddedDriverCount is 0.
+ 2) FmpCapsuleHeader->PayloadItemCount is not 0.
+ 3) All ImageHeader->UpdateImageTypeId matches PcdEdkiiSystemFmpCapsuleImageTypeIdGuid.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval TRUE Input capsule is a correct system FMP capsule.
+ @retval FALSE Input capsule is not a correct system FMP capsule.
+**/
+BOOLEAN
+IsSystemFmpCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT64 *ItemOffsetList;
+ UINT32 ItemNum;
+ UINTN Index;
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+
+ if (FmpCapsuleHeader->EmbeddedDriverCount != 0) {
+ return FALSE;
+ }
+
+ if (FmpCapsuleHeader->PayloadItemCount == 0) {
+ return FALSE;
+ }
+
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ for (Index = 0; Index < ItemNum; Index++) {
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+ if (!IsSystemFmpImage(ImageHeader)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Validate if it is valid capsule header
+
+ Caution: This function may receive untrusted input.
+
+ This function assumes the caller provided correct CapsuleHeader pointer
+ and CapsuleSize.
+
+ This function validates the fields in EFI_CAPSULE_HEADER.
+
+ @param CapsuleHeader Points to a capsule header.
+ @param CapsuleSize Size of the whole capsule image.
+
+**/
+BOOLEAN
+IsValidCapsuleHeader(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN UINT64 CapsuleSize
+ )
+{
+ if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
+ return FALSE;
+ }
+ if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Validate Fmp capsules layout.
+
+ Caution: This function may receive untrusted input.
+
+ This function assumes the caller validated the capsule by using
+ IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
+ The capsule buffer size is CapsuleHeader->CapsuleImageSize.
+
+ This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+ and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
+
+ This function need support nested FMP capsule.
+
+ @param[in] CapsuleHeader Points to a capsule header.
+ @param[out] IsSystemFmp If it is a system FMP.
+ @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
+
+ @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+ @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
+**/
+EFI_STATUS
+ValidateFmpCapsule (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ OUT BOOLEAN *IsSystemFmp, OPTIONAL
+ OUT UINT16 *EmbeddedDriverCount OPTIONAL
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ UINT8 *EndOfCapsule;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT8 *EndOfPayload;
+ UINT64 *ItemOffsetList;
+ UINT32 ItemNum;
+ UINTN Index;
+ UINTN FmpCapsuleSize;
+ UINTN FmpCapsuleHeaderSize;
+ UINT64 FmpImageSize;
+ UINTN FmpImageHeaderSize;
+
+ if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
+ return ValidateFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), IsSystemFmp, EmbeddedDriverCount);
+ }
+
+ if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
+ DEBUG((EFI_D_ERROR, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+ EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
+ FmpCapsuleSize = (UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader;
+
+ if (FmpCapsuleSize < sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER)) {
+ DEBUG((EFI_D_ERROR, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+ if (FmpCapsuleHeader->Version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+ DEBUG((EFI_D_ERROR, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader->Version));
+ return EFI_INVALID_PARAMETER;
+ }
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ // No overflow
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+ if ((FmpCapsuleSize - sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER))/sizeof(UINT64) < ItemNum) {
+ DEBUG((EFI_D_ERROR, "ItemNum(0x%x) too big\n", ItemNum));
+ return EFI_INVALID_PARAMETER;
+ }
+ FmpCapsuleHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64)*ItemNum;
+
+ // Check ItemOffsetList
+ for (Index = 0; Index < ItemNum; Index++) {
+ if (ItemOffsetList[Index] >= FmpCapsuleSize) {
+ DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ItemOffsetList[Index] < FmpCapsuleHeaderSize) {
+ DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleHeaderSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // All the address in ItemOffsetList must be stored in ascending order
+ //
+ if (Index > 0) {
+ if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {
+ DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index, ItemOffsetList[Index - 1]));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
+ for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+ if (Index == ItemNum - 1) {
+ EndOfPayload = (UINT8 *)((UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader);
+ } else {
+ EndOfPayload = (UINT8 *)(UINTN)ItemOffsetList[Index+1];
+ }
+ FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];
+
+ if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) {
+ DEBUG((EFI_D_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);
+ if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||
+ (ImageHeader->Version < 1)) {
+ DEBUG((EFI_D_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+ }
+
+ // No overflow
+ if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) {
+ DEBUG((EFI_D_ERROR, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize, ImageHeader->UpdateImageSize, ImageHeader->UpdateVendorCodeSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (ItemNum == 0) {
+ //
+ // No driver & payload element in FMP
+ //
+ EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);
+ if (EndOfPayload != EndOfCapsule) {
+ DEBUG((EFI_D_ERROR, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload, EndOfCapsule));
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check in system FMP capsule
+ //
+ if (IsSystemFmp != NULL) {
+ *IsSystemFmp = IsSystemFmpCapsuleImage(CapsuleHeader);
+ }
+
+ if (EmbeddedDriverCount != NULL) {
+ *EmbeddedDriverCount = FmpCapsuleHeader->EmbeddedDriverCount;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
+ is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
+ buffer is passed in it will be used if it is big enough.
+
+ @param BmpImage Pointer to BMP file
+ @param BmpImageSize Number of bytes in BmpImage
+ @param GopBlt Buffer containing GOP version of BmpImage.
+ @param GopBltSize Size of GopBlt in bytes.
+ @param PixelHeight Height of GopBlt/BmpImage in pixels
+ @param PixelWidth Width of GopBlt/BmpImage in pixels
+
+ @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
+ @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
+ @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
+ GopBltSize will contain the required size.
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
+
+**/
+STATIC
+EFI_STATUS
+ConvertBmpToGopBlt (
+ IN VOID *BmpImage,
+ IN UINTN BmpImageSize,
+ IN OUT VOID **GopBlt,
+ IN OUT UINTN *GopBltSize,
+ OUT UINTN *PixelHeight,
+ OUT UINTN *PixelWidth
+ )
+{
+ UINT8 *Image;
+ UINT8 *ImageHeader;
+ BMP_IMAGE_HEADER *BmpHeader;
+ BMP_COLOR_MAP *BmpColorMap;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINT64 BltBufferSize;
+ UINTN Index;
+ UINTN Height;
+ UINTN Width;
+ UINTN ImageIndex;
+ UINT32 DataSizePerLine;
+ BOOLEAN IsAllocated;
+ UINT32 ColorMapNum;
+
+ if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
+
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Doesn't support compress.
+ //
+ if (BmpHeader->CompressionType != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Only support BITMAPINFOHEADER format.
+ // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
+ //
+ if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // The data size in each line must be 4 byte alignment.
+ //
+ DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
+ BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
+ if (BltBufferSize > (UINT32) ~0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BmpHeader->Size != BmpImageSize) ||
+ (BmpHeader->Size < BmpHeader->ImageOffset) ||
+ (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Calculate Color Map offset in the image.
+ //
+ Image = BmpImage;
+ BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
+ if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ ColorMapNum = 2;
+ break;
+ case 4:
+ ColorMapNum = 16;
+ break;
+ case 8:
+ ColorMapNum = 256;
+ break;
+ default:
+ ColorMapNum = 0;
+ break;
+ }
+ //
+ // BMP file may has padding data between the bmp header section and the bmp data section.
+ //
+ if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Calculate graphics image data address in the image
+ //
+ Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
+ ImageHeader = Image;
+
+ //
+ // Calculate the BltBuffer needed size.
+ //
+ BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
+ //
+ // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+ //
+ if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+ return EFI_UNSUPPORTED;
+ }
+ BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ IsAllocated = FALSE;
+ if (*GopBlt == NULL) {
+ //
+ // GopBlt is not allocated by caller.
+ //
+ *GopBltSize = (UINTN) BltBufferSize;
+ *GopBlt = AllocatePool (*GopBltSize);
+ IsAllocated = TRUE;
+ if (*GopBlt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ //
+ // GopBlt has been allocated by caller.
+ //
+ if (*GopBltSize < (UINTN) BltBufferSize) {
+ *GopBltSize = (UINTN) BltBufferSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+
+ *PixelWidth = BmpHeader->PixelWidth;
+ *PixelHeight = BmpHeader->PixelHeight;
+
+ //
+ // Convert image from BMP to Blt buffer format
+ //
+ BltBuffer = *GopBlt;
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ //
+ // Convert 1-bit (2 colors) BMP to 24-bit color
+ //
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
+ Blt++;
+ Width++;
+ }
+
+ Blt--;
+ Width--;
+ break;
+
+ case 4:
+ //
+ // Convert 4-bit (16 colors) BMP Palette to 24-bit color
+ //
+ Index = (*Image) >> 4;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ if (Width < (BmpHeader->PixelWidth - 1)) {
+ Blt++;
+ Width++;
+ Index = (*Image) & 0x0f;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ }
+ break;
+
+ case 8:
+ //
+ // Convert 8-bit (256 colors) BMP Palette to 24-bit color
+ //
+ Blt->Red = BmpColorMap[*Image].Red;
+ Blt->Green = BmpColorMap[*Image].Green;
+ Blt->Blue = BmpColorMap[*Image].Blue;
+ break;
+
+ case 24:
+ //
+ // It is 24-bit BMP.
+ //
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image;
+ break;
+
+ case 32:
+ //
+ // it is 32-bit BMP. Skip pixel's highest byte
+ //
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image++;
+ break;
+
+ default:
+ //
+ // Other bit format BMP is not supported.
+ //
+ if (IsAllocated) {
+ FreePool (*GopBlt);
+ *GopBlt = NULL;
+ }
+ return EFI_UNSUPPORTED;
+ };
+
+ }
+
+ ImageIndex = (UINTN) (Image - ImageHeader);
+ if ((ImageIndex % 4) != 0) {
+ //
+ // Bmp Image starts each row on a 32-bit boundary!
+ //
+ Image = Image + (4 - (ImageIndex % 4));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Those capsules supported by the firmwares.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
+**/
+EFI_STATUS
+DisplayCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ DISPLAY_DISPLAY_PAYLOAD *ImagePayload;
+ UINTN PayloadSize;
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINTN BltSize;
+ UINTN Height;
+ UINTN Width;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+
+ ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)(CapsuleHeader + 1);
+ PayloadSize = (UINTN)(CapsuleHeader->CapsuleImageSize - sizeof(EFI_CAPSULE_HEADER));
+
+ if (ImagePayload->Version != 1) {
+ return EFI_UNSUPPORTED;
+ }
+ if (CalculateCheckSum8((UINT8 *)CapsuleHeader, CapsuleHeader->CapsuleImageSize) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Only Support Bitmap by now
+ //
+ if (ImagePayload->ImageType != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Try to open GOP
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
+ if (EFI_ERROR (Status)) {
+ Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&GraphicsOutput);
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ if (GraphicsOutput->Mode->Mode != ImagePayload->Mode) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Blt = NULL;
+ Width = 0;
+ Height = 0;
+ Status = ConvertBmpToGopBlt (
+ ImagePayload + 1,
+ PayloadSize - sizeof(DISPLAY_DISPLAY_PAYLOAD),
+ (VOID **)&Blt,
+ &BltSize,
+ &Height,
+ &Width
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ Blt,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) ImagePayload->OffsetX,
+ (UINTN) ImagePayload->OffsetY,
+ Width,
+ Height,
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+
+ FreePool(Blt);
+
+ return Status;
+}
+
+/**
+ Dump FMP information.
+
+ @param ImageInfoSize The size of ImageInfo, in bytes.
+ @param ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
+ @param PackageVersion The version of package.
+ @param 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;
+
+ DEBUG((DEBUG_VERBOSE, " DescriptorVersion - 0x%x\n", DescriptorVersion));
+ DEBUG((DEBUG_VERBOSE, " DescriptorCount - 0x%x\n", DescriptorCount));
+ DEBUG((DEBUG_VERBOSE, " DescriptorSize - 0x%x\n", DescriptorSize));
+ DEBUG((DEBUG_VERBOSE, " PackageVersion - 0x%x\n", PackageVersion));
+ DEBUG((DEBUG_VERBOSE, " PackageVersionName - %s\n\n", PackageVersionName));
+ CurrentImageInfo = ImageInfo;
+ for (Index = 0; Index < DescriptorCount; Index++) {
+ DEBUG((DEBUG_VERBOSE, " ImageDescriptor (%d)\n", Index));
+ DEBUG((DEBUG_VERBOSE, " ImageIndex - 0x%x\n", CurrentImageInfo->ImageIndex));
+ DEBUG((DEBUG_VERBOSE, " ImageTypeId - %g\n", &CurrentImageInfo->ImageTypeId));
+ DEBUG((DEBUG_VERBOSE, " ImageId - 0x%lx\n", CurrentImageInfo->ImageId));
+ DEBUG((DEBUG_VERBOSE, " ImageIdName - %s\n", CurrentImageInfo->ImageIdName));
+ DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", CurrentImageInfo->Version));
+ DEBUG((DEBUG_VERBOSE, " VersionName - %s\n", CurrentImageInfo->VersionName));
+ DEBUG((DEBUG_VERBOSE, " Size - 0x%x\n", CurrentImageInfo->Size));
+ DEBUG((DEBUG_VERBOSE, " AttributesSupported - 0x%lx\n", CurrentImageInfo->AttributesSupported));
+ DEBUG((DEBUG_VERBOSE, " AttributesSetting - 0x%lx\n", CurrentImageInfo->AttributesSetting));
+ DEBUG((DEBUG_VERBOSE, " Compatibilities - 0x%lx\n", CurrentImageInfo->Compatibilities));
+ if (DescriptorVersion > 1) {
+ DEBUG((DEBUG_VERBOSE, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion));
+ if (DescriptorVersion > 2) {
+ DEBUG((DEBUG_VERBOSE, " LastAttemptVersion - 0x%x\n", CurrentImageInfo->LastAttemptVersion));
+ DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", CurrentImageInfo->LastAttemptStatus));
+ DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", CurrentImageInfo->HardwareInstance));
+ }
+ }
+ //
+ // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
+ //
+ CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
+ }
+}
+
+/**
+ Dump a non-nested FMP capsule.
+
+ @param CapsuleHeader A pointer to CapsuleHeader
+**/
+VOID
+DumpFmpCapsule(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINTN Index;
+ UINT64 *ItemOffsetList;
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+
+ DEBUG((DEBUG_VERBOSE, "FmpCapsule:\n"));
+ DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", FmpCapsuleHeader->Version));
+ DEBUG((DEBUG_VERBOSE, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount));
+ DEBUG((DEBUG_VERBOSE, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader->PayloadItemCount));
+
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+ for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
+ DEBUG((DEBUG_VERBOSE, " ItemOffsetList[%d] - 0x%lx\n", Index, ItemOffsetList[Index]));
+ }
+ for (; Index < (UINTN)(FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount); Index++) {
+ DEBUG((DEBUG_VERBOSE, " ItemOffsetList[%d] - 0x%lx\n", Index, ItemOffsetList[Index]));
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+
+ DEBUG((DEBUG_VERBOSE, " ImageHeader:\n"));
+ DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", ImageHeader->Version));
+ DEBUG((DEBUG_VERBOSE, " UpdateImageTypeId - %g\n", &ImageHeader->UpdateImageTypeId));
+ DEBUG((DEBUG_VERBOSE, " UpdateImageIndex - 0x%x\n", ImageHeader->UpdateImageIndex));
+ DEBUG((DEBUG_VERBOSE, " UpdateImageSize - 0x%x\n", ImageHeader->UpdateImageSize));
+ DEBUG((DEBUG_VERBOSE, " UpdateVendorCodeSize - 0x%x\n", ImageHeader->UpdateVendorCodeSize));
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ DEBUG((DEBUG_VERBOSE, " UpdateHardwareInstance - 0x%lx\n", ImageHeader->UpdateHardwareInstance));
+ }
+ }
+}
+
+/**
+ Process System Firmware management protocol data capsule.
+
+ This function assumes the caller validated the capsule by using
+ ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
+
+ This function assumes nested FMP capsule is handled by ProcessFmpCapsuleImage.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+EFI_STATUS
+DispatchSystemFmpImages (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ UINTN Length;
+ VOID *Image;
+ EFI_STATUS Status;
+ VOID *AuthenticatedImage;
+ UINTN AuthenticatedImageSize;
+ UINT32 LastAttemptVersion;
+ UINT32 LastAttemptStatus;
+ VOID *DispatchFvImage;
+ UINTN DispatchFvImageSize;
+ EFI_HANDLE FvProtocolHandle;
+ EFI_FIRMWARE_VOLUME_HEADER *FvImage;
+ BOOLEAN Result;
+ UINTN ItemIndex;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT64 *ItemOffsetList;
+
+ DEBUG((EFI_D_INFO, "DispatchSystemFmpImages\n"));
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ for (ItemIndex = 0; ItemIndex < FmpCapsuleHeader->PayloadItemCount; ItemIndex++) {
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemIndex]);
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ Image = (UINT8 *)(ImageHeader + 1);
+ } else {
+ //
+ // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
+ // Header should exclude UpdateHardwareInstance field
+ //
+ Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+ }
+ Length = ImageHeader->UpdateImageSize;
+
+ //
+ // Verify
+ //
+ Status = CapsuleAuthenticateSystemFirmware(Image, Length, FALSE, &LastAttemptVersion, &LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_INFO, "BiosAuthenticateImage - %r\n", Status));
+ return Status;
+ }
+
+ //
+ // Get FV
+ //
+ Result = ExtractDriverFvImage(AuthenticatedImage, AuthenticatedImageSize, &DispatchFvImage, &DispatchFvImageSize);
+ if (Result) {
+ DEBUG((EFI_D_INFO, "ExtractDriverFvImage\n"));
+ //
+ // Dispatch
+ //
+ if (((EFI_FIRMWARE_VOLUME_HEADER *)DispatchFvImage)->FvLength == DispatchFvImageSize) {
+ FvImage = AllocatePages(EFI_SIZE_TO_PAGES(DispatchFvImageSize));
+ if (FvImage != NULL) {
+ CopyMem(FvImage, DispatchFvImage, DispatchFvImageSize);
+ Status = gDS->ProcessFirmwareVolume(
+ (VOID *)FvImage,
+ (UINTN)FvImage->FvLength,
+ &FvProtocolHandle
+ );
+ DEBUG((EFI_D_INFO, "ProcessFirmwareVolume - %r\n", Status));
+ if (!EFI_ERROR(Status)) {
+ gDS->Dispatch();
+ DEBUG((EFI_D_INFO, "Dispatch Done\n"));
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Process Firmware management protocol data capsule.
+
+ This function assumes the caller validated the capsule by using
+ ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
+
+ This function need support nested FMP capsule.
+
+ @param CapsuleHeader Points to a capsule header.
+ @param IsSystemFmp If this capsule is a system FMP capsule.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+EFI_STATUS
+ProcessFmpCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN BOOLEAN IsSystemFmp
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS StatusEsrt;
+ EFI_STATUS StatusRet;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT8 *Image;
+ EFI_HANDLE ImageHandle;
+ UINT64 *ItemOffsetList;
+ UINT32 ItemNum;
+ UINTN Index;
+ UINTN ExitDataSize;
+ EFI_HANDLE *HandleBuffer;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ UINTN NumberOfHandles;
+ UINTN DescriptorSize;
+ UINT8 FmpImageInfoCount;
+ UINT32 FmpImageInfoDescriptorVer;
+ UINTN ImageInfoSize;
+ UINT32 PackageVersion;
+ CHAR16 *PackageVersionName;
+ CHAR16 *AbortReason;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;
+ UINTN DriverLen;
+ UINTN Index1;
+ UINTN Index2;
+ MEMMAP_DEVICE_PATH MemMapNode;
+ EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
+ EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;
+ VOID *VendorCode;
+
+ if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
+ return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), IsSystemFmp);
+ }
+
+ Status = EFI_SUCCESS;
+ StatusRet = EFI_NOT_FOUND;
+ HandleBuffer = NULL;
+ ExitDataSize = 0;
+ DriverDevicePath = NULL;
+ EsrtProtocol = NULL;
+
+ DumpFmpCapsule(CapsuleHeader);
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+
+ if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+ //
+ // capsule in which driver count and payload count are both zero is not processed.
+ //
+ if (ItemNum == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Update corresponding ESRT entry LastAttemp Status
+ //
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
+ if (EFI_ERROR (Status)) {
+ EsrtProtocol = NULL;
+ }
+
+ //
+ // 1. For system FMP, the images are insides of FmpPayload
+ //
+ if (IsSystemFmp) {
+ Status = DispatchSystemFmpImages(CapsuleHeader);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // 2. Try to load & start all the drivers within capsule
+ //
+ SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));
+ MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;
+ MemMapNode.Header.SubType = HW_MEMMAP_DP;
+ MemMapNode.MemoryType = EfiBootServicesCode;
+ MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader;
+ MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1);
+
+ DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);
+ if (DriverDevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
+ if (FmpCapsuleHeader->PayloadItemCount == 0 && Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1) {
+ //
+ // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
+ //
+ DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];
+ } else {
+ DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];
+ }
+
+ DEBUG((EFI_D_INFO, "FmpCapsule: LoadImage ...\n"));
+ Status = gBS->LoadImage(
+ FALSE,
+ gImageHandle,
+ DriverDevicePath,
+ (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],
+ DriverLen,
+ &ImageHandle
+ );
+ DEBUG((EFI_D_INFO, "FmpCapsule: LoadImage - %r\n", Status));
+ if (EFI_ERROR(Status)) {
+ StatusRet = Status;
+ goto EXIT;
+ }
+
+ DEBUG((EFI_D_INFO, "FmpCapsule: StartImage ...\n"));
+ Status = gBS->StartImage(
+ ImageHandle,
+ &ExitDataSize,
+ NULL
+ );
+ DEBUG((EFI_D_INFO, "FmpCapsule: StartImage - %r\n", Status));
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
+ StatusRet = Status;
+ goto EXIT;
+ }
+ }
+
+ //
+ // 3. Route payload to right FMP instance
+ //
+ DEBUG((EFI_D_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareManagementProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+
+ if (!EFI_ERROR(Status)) {
+ for(Index1 = 0; Index1 < NumberOfHandles; Index1++) {
+ Status = gBS->HandleProtocol(
+ HandleBuffer[Index1],
+ &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) {
+ StatusRet = 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)) {
+ FreePool(FmpImageInfoBuf);
+ continue;
+ }
+
+ DEBUG((EFI_D_INFO, "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);
+ }
+
+ TempFmpImageInfo = FmpImageInfoBuf;
+ for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
+ //
+ // Check all the payload entry in capsule payload list
+ //
+ for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+
+ if (IsFmpCapsuleVariableRecorded(CapsuleHeader, Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader)) {
+ DEBUG((EFI_D_INFO, "FMP Capsule already processed (%g):", CapsuleHeader));
+ DEBUG((EFI_D_INFO, "ImageTypeId - %g, ", ImageHeader->UpdateImageTypeId));
+ DEBUG((EFI_D_INFO, "PayloadIndex - 0x%x, ImageIndex - 0x%x\n", Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader->UpdateImageIndex));
+ continue;
+ }
+
+ if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) &&
+ ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) {
+ AbortReason = NULL;
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ if(ImageHeader->UpdateHardwareInstance != 0){
+ //
+ // FMP Version is >=2 & UpdateHardwareInstance Skip 2 case
+ // 1. FMP Image info Version < 3
+ // 2. HardwareInstance doesn't match
+ //
+ if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION ||
+ ImageHeader->UpdateHardwareInstance != TempFmpImageInfo->HardwareInstance) {
+ continue;
+ }
+ }
+ Image = (UINT8 *)(ImageHeader + 1);
+ } else {
+ //
+ // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
+ // Header should exclude UpdateHardwareInstance field
+ //
+ Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+ }
+
+ if (ImageHeader->UpdateVendorCodeSize == 0) {
+ VendorCode = NULL;
+ } else {
+ VendorCode = Image + ImageHeader->UpdateImageSize;
+ }
+ DEBUG((EFI_D_INFO, "Fmp->SetImage ...\n"));
+ Status = Fmp->SetImage(
+ Fmp,
+ ImageHeader->UpdateImageIndex, // ImageIndex
+ Image, // Image
+ ImageHeader->UpdateImageSize, // ImageSize
+ VendorCode, // VendorCode
+ Update_Image_Progress, // Progress
+ &AbortReason // AbortReason
+ );
+ DEBUG((EFI_D_INFO, "Fmp->SetImage - %r\n", Status));
+ if (AbortReason != NULL) {
+ DEBUG ((EFI_D_ERROR, "%s\n", AbortReason));
+ FreePool(AbortReason);
+ }
+ RecordFmpCapsuleStatusVariable(
+ CapsuleHeader, // CapsuleGuid
+ Status, // CapsuleStatus
+ Index - FmpCapsuleHeader->EmbeddedDriverCount, // PayloadIndex
+ ImageHeader // ImageHeader
+ );
+ if (StatusRet != EFI_SUCCESS) {
+ StatusRet = Status;
+ }
+ //
+ // Update EsrtEntry For V1, V2 FMP instance. V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
+ //
+ if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION && EsrtProtocol != NULL) {
+ StatusEsrt = EsrtProtocol->GetEsrtEntry(&TempFmpImageInfo->ImageTypeId, &EsrtEntry);
+ if (!EFI_ERROR(StatusEsrt)){
+ if (!EFI_ERROR(Status)) {
+ EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ } else {
+ EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ }
+ EsrtEntry.LastAttemptVersion = 0;
+ EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);
+ }
+ }
+ }
+ }
+ //
+ // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
+ //
+ TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
+ }
+ FreePool(FmpImageInfoBuf);
+ }
+ }
+
+EXIT:
+
+ if (HandleBuffer != NULL) {
+ FreePool(HandleBuffer);
+ }
+
+ if (DriverDevicePath != NULL) {
+ FreePool(DriverDevicePath);
+ }
+
+ return StatusRet;
+}
+
+/**
+ 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;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
+ EFI_SYSTEM_RESOURCE_ENTRY Entry;
+
+ EsrtGuidFound = FALSE;
+
+ //
+ // Check ESRT protocol
+ //
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
+ if (!EFI_ERROR(Status)) {
+ Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);
+ if (!EFI_ERROR(Status)) {
+ EsrtGuidFound = TRUE;
+ }
+ }
+
+ //
+ // Check ESRT configuration table
+ //
+ if (!EsrtGuidFound) {
+ Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
+ if (!EFI_ERROR(Status)) {
+ 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 (!IsValidCapsuleHeader(NestedCapsuleHeader, NestedCapsuleSize)) {
+ return FALSE;
+ }
+ if (!IsFmpCapsuleGuid(&NestedCapsuleHeader->CapsuleGuid)) {
+ return FALSE;
+ }
+ DEBUG ((EFI_D_INFO, "IsNestedFmpCapsule\n"));
+ return TRUE;
+}
+
+/**
+ Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
+
+ @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+ @retval TRUE It is a system FMP.
+ @retval FALSE It is a device FMP.
+**/
+BOOLEAN
+IsFmpCapsule(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
+ return TRUE;
+ }
+ if (IsNestedFmpCapsule(CapsuleHeader)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Those capsules supported by the firmwares.
+
+ Caution: This function may receive untrusted input.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
+ @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
+**/
+EFI_STATUS
+EFIAPI
+SupportCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ //
+ // check Display Capsule Guid
+ //
+ if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+ return EFI_SUCCESS;
+ }
+
+ if (IsFmpCapsule(CapsuleHeader)) {
+ //
+ // Check layout of FMP capsule
+ //
+ return ValidateFmpCapsule(CapsuleHeader, NULL, NULL);
+ }
+ DEBUG((EFI_D_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The firmware implements to process the capsule image.
+
+ Caution: This function may receive untrusted input.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN IsSystemFmp;
+
+ if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Display image in firmware update display capsule
+ //
+ if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+ DEBUG((EFI_D_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
+ Status = DisplayCapsuleImage(CapsuleHeader);
+ RecordCapsuleStatusVariable(CapsuleHeader, Status);
+ return Status;
+ }
+
+ //
+ // Check FMP capsule layout
+ //
+ if (IsFmpCapsule (CapsuleHeader)) {
+ DEBUG((EFI_D_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));
+ DEBUG((EFI_D_INFO, "ValidateFmpCapsule ...\n"));
+ Status = ValidateFmpCapsule(CapsuleHeader, &IsSystemFmp, NULL);
+ DEBUG((EFI_D_INFO, "ValidateFmpCapsule - %r\n", Status));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Press EFI FMP Capsule
+ //
+ DEBUG((EFI_D_INFO, "ProcessFmpCapsuleImage ...\n"));
+ Status = ProcessFmpCapsuleImage(CapsuleHeader, IsSystemFmp);
+ DEBUG((EFI_D_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
+
+ return Status;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Callback function executed when the EndOfDxe event group is signaled.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context The pointer to the notification function's context, which
+ is implementation-dependent.
+**/
+VOID
+EFIAPI
+DxeCapsuleLibEndOfDxe(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ mDxeCapsuleLibEndOfDxe = TRUE;
+}
+
+/**
+ The constructor function.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor successfully .
+**/
+EFI_STATUS
+EFIAPI
+DxeCapsuleLibConstructor(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_EVENT EndOfDxeEvent;
+ EFI_STATUS Status;
+
+ mEdkiiSystemFmpCapsuleImageTypeIdGuidCount = PcdGetSize(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID);
+ mEdkiiSystemFmpCapsuleImageTypeIdGuid = AllocateCopyPool(mEdkiiSystemFmpCapsuleImageTypeIdGuidCount * sizeof(GUID), PcdGetPtr(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid));
+ ASSERT(mEdkiiSystemFmpCapsuleImageTypeIdGuid != NULL);
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ DxeCapsuleLibEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ InitCapsuleVariable();
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
new file mode 100644
index 0000000..e957b7b
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
@@ -0,0 +1,82 @@
+## @file
+# Capsule library instance for DXE_DRIVER.
+#
+# Capsule library instance for DXE_DRIVER module types.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeCapsuleLib
+ MODULE_UNI_FILE = DxeCapsuleLib.uni
+ FILE_GUID = 534E35DE-8EB3-47b3-A4E0-72A571E50733
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CapsuleLib|DXE_DRIVER UEFI_APPLICATION
+ CONSTRUCTOR = DxeCapsuleLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ DxeCapsuleLib.c
+ DxeCapsuleProcessLib.c
+ DxeCapsuleReportLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ DxeServicesTableLib
+ UefiBootServicesTableLib
+ DevicePathLib
+ ReportStatusCodeLib
+ PrintLib
+ HobLib
+ EdkiiSystemCapsuleLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeSubClassCapsule
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesBegin
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem
+
+[Protocols]
+ gEsrtManagementProtocolGuid ## CONSUMES
+ gEfiFirmwareManagementProtocolGuid ## SOMETIMES_CONSUMES
+ gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
+ gWindowsUxCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiSystemResourceTableGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiCapsuleReportGuid ## CONSUMES ## Variable
+ gEfiCapsuleVendorGuid ## CONSUMES ## Variable
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
+
+[Depex]
+ gEfiVariableWriteArchProtocolGuid
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
new file mode 100644
index 0000000..05a80d0
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// Capsule library instance for DXE_DRIVER.
+//
+// Capsule library instance for DXE_DRIVER module types.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Capsule Support Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Capsule library instance for DXE_DRIVER module types."
+
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
new file mode 100644
index 0000000..13379b2
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
@@ -0,0 +1,517 @@
+/** @file
+ DXE capsule process.
+
+ Caution: This module requires additional review when modified.
+ This module will have external input - capsule image.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ ProcessCapsules(), ProcessTheseCapsules() will receive untrusted
+ input and do basic validation.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Protocol/EsrtManagement.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/CapsuleLib.h>
+
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+/**
+ Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
+
+ @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+ @retval TRUE It is a system FMP.
+ @retval FALSE It is a device FMP.
+**/
+BOOLEAN
+IsFmpCapsule(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ );
+
+/**
+ Validate Fmp capsules layout.
+
+ Caution: This function may receive untrusted input.
+
+ This function assumes the caller validated the capsule by using
+ IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
+ The capsule buffer size is CapsuleHeader->CapsuleImageSize.
+
+ This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+ and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
+
+ This function need support nested FMP capsule.
+
+ @param[in] CapsuleHeader Points to a capsule header.
+ @param[out] IsSystemFmp If it is a system FMP.
+ @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
+
+ @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+ @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
+**/
+EFI_STATUS
+ValidateFmpCapsule(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ OUT BOOLEAN *IsSystemFmp, OPTIONAL
+ OUT UINT16 *EmbeddedDriverCount OPTIONAL
+ );
+
+/**
+ 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 CapsuleHeader Points to a capsule header.
+ @param CapsuleSize Size of the whole capsule image.
+
+**/
+BOOLEAN
+IsValidCapsuleHeader(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN UINT64 CapsuleSize
+ );
+
+extern BOOLEAN mDxeCapsuleLibEndOfDxe;
+
+/**
+
+ This routine is called to process capsules.
+
+ Caution: This function may receive untrusted input.
+
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ @param IsSystemCapsule TRUE: This function need process system capsules only.
+ FALSE: This function need process non-system capsules only.
+ @param NeedBlockDriver TRUE: Need skip the FMP capsules with non zero EmbeddedDriverCount.
+ FALSE: No need to skip any FMP capsules.
+
+ @retval EFI_SUCCESS There is no error when processing capsules.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
+
+**/
+EFI_STATUS
+ProcessTheseCapsules (
+ IN BOOLEAN IsSystemCapsule,
+ IN BOOLEAN NeedBlockDriver
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS HobPointer;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ UINT32 Size;
+ UINT32 CapsuleNumber;
+ UINT32 CapsuleTotalNumber;
+ EFI_CAPSULE_TABLE *CapsuleTable;
+ UINT32 Index;
+ UINT32 CacheIndex;
+ UINT32 CacheNumber;
+ VOID **CapsulePtr;
+ VOID **CapsulePtrCache;
+ EFI_GUID *CapsuleGuidCache;
+ BOOLEAN NeedReset;
+ EFI_STATUS *CapsuleStatusArray;
+ BOOLEAN DisplayCapsuleExist;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+ BOOLEAN IsSystemFmp;
+ UINT16 EmbeddedDriverCount;
+
+ REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));
+
+ CapsuleNumber = 0;
+ CapsuleTotalNumber = 0;
+ CacheIndex = 0;
+ CacheNumber = 0;
+ CapsulePtr = NULL;
+ CapsulePtrCache = NULL;
+ CapsuleGuidCache = NULL;
+ NeedReset = FALSE;
+ DisplayCapsuleExist = FALSE;
+ EsrtManagement = NULL;
+
+ Status = EFI_SUCCESS;
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
+ if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule->BaseAddress, HobPointer.Capsule->Length)) {
+ HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this hob as invalid
+ } else {
+ CapsuleTotalNumber++;
+ }
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ if (CapsuleTotalNumber == 0) {
+ //
+ // We didn't find a hob, so had no errors.
+ //
+ DEBUG ((EFI_D_ERROR, "We can not find capsule data in capsule update boot mode.\n"));
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // Init temp Capsule Data table.
+ //
+ CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtr != NULL);
+ if (CapsulePtr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtrCache != NULL);
+ if (CapsulePtrCache == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);
+ ASSERT (CapsuleGuidCache != NULL);
+ if (CapsuleGuidCache == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ CapsuleStatusArray = (EFI_STATUS *) AllocateZeroPool (sizeof (EFI_STATUS) * CapsuleTotalNumber);
+ ASSERT (CapsuleStatusArray != NULL);
+ if (CapsuleStatusArray == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
+ CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ if (!IsSystemCapsule) {
+ //
+ //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install
+ //capsuleTable to configure table with EFI_CAPSULE_GUID
+ //
+
+ //
+ // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating
+ // System to have information persist across a system reset. EFI System Table must
+ // point to an array of capsules that contains the same CapsuleGuid value. And agents
+ // searching for this type capsule will look in EFI System Table and search for the
+ // capsule's Guid and associated pointer to retrieve the data. Two steps below describes
+ // how to sorting the capsules by the unique guid and install the array to EFI System Table.
+ // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an
+ // array for later sorting capsules by CapsuleGuid.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleStatusArray [Index] = EFI_UNSUPPORTED;
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ //
+ // For each capsule, we compare it with known CapsuleGuid in the CacheArray.
+ // If already has the Guid, skip it. Whereas, record it in the CacheArray as
+ // an additional one.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {
+ break;
+ }
+ CacheIndex++;
+ }
+ if (CacheIndex == CacheNumber) {
+ CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));
+ }
+ }
+ }
+
+ //
+ // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules
+ // whose guid is the same as it, and malloc memory for an array which preceding
+ // with UINT32. The array fills with entry point of capsules that have the same
+ // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install
+ // this array into EFI System Table, so that agents searching for this type capsule
+ // will look in EFI System Table and search for the capsule's Guid and associated
+ // pointer to retrieve the data.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ CapsuleNumber = 0;
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {
+ //
+ // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.
+ //
+ CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;
+ //
+ // When a Capsule is listed in CapsulePtrCache, it will be reported in ConfigurationTable
+ // So, report the CapsuleStatus as "processed successfully".
+ //
+ CapsuleStatusArray [Index] = EFI_SUCCESS;
+ }
+ }
+ }
+ if (CapsuleNumber != 0) {
+ Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);
+ CapsuleTable = AllocateRuntimePool (Size);
+ ASSERT (CapsuleTable != NULL);
+ if (CapsuleTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CapsuleTable->CapsuleArrayNumber = CapsuleNumber;
+ CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));
+ Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);
+ ASSERT_EFI_ERROR (Status);
+ }
+ CacheIndex++;
+ }
+ }
+
+ REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdatingFirmware)));
+
+ //
+ // If Windows UX capsule exist, process it first
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if (CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {
+ DEBUG ((EFI_D_INFO, "ProcessCapsuleImage (Ux) - 0x%x\n", CapsuleHeader));
+ DisplayCapsuleExist = TRUE;
+ DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));
+ Status = ProcessCapsuleImage (CapsuleHeader);
+ DEBUG((EFI_D_INFO, "ProcessCapsuleImage (Ux) - %r\n", Status));
+ CapsuleStatusArray [Index] = Status;
+ break;
+ }
+ }
+
+ if (!DisplayCapsuleExist) {
+ //
+ // Display Capsule not found. Display the default string.
+ //
+ Print (L"Updating the firmware ......\r\n");
+ }
+
+ //
+ // All capsules left are recognized by platform.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if (!CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {
+ //
+ // Call capsule library to process capsule image.
+ //
+ IsSystemFmp = FALSE;
+ EmbeddedDriverCount = 0;
+ if (IsFmpCapsule(CapsuleHeader)) {
+ Status = ValidateFmpCapsule(CapsuleHeader, &IsSystemFmp, &EmbeddedDriverCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR, "ValidateFmpCapsule failed. Ignore!\n"));
+ continue;
+ }
+ }
+
+ if ((IsSystemFmp == IsSystemCapsule) &&
+ ((!NeedBlockDriver) || (EmbeddedDriverCount == 0)) ) {
+ DEBUG((EFI_D_INFO, "ProcessCapsuleImage - 0x%x\n", CapsuleHeader));
+ Status = ProcessCapsuleImage (CapsuleHeader);
+ CapsuleStatusArray [Index] = Status;
+ DEBUG((EFI_D_INFO, "ProcessCapsuleImage - %r\n", Status));
+
+ if (EFI_ERROR(Status)) {
+ REPORT_STATUS_CODE(EFI_ERROR_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareFailed)));
+ DEBUG ((DEBUG_ERROR, "Capsule process failed. reset the system!\n"));
+ Print (L"Firmware update failed...\r\n");
+ NeedReset = TRUE;
+ } else {
+ REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareSuccess)));
+ }
+
+ if ((CapsuleHeader->Flags & PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag)) != 0 ||
+ IsFmpCapsule(CapsuleHeader)) {
+ NeedReset = TRUE;
+ }
+ }
+ }
+ }
+
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ //
+ // Always sync ESRT Cache from FMP Instance
+ //
+ if (!EFI_ERROR(Status)) {
+ EsrtManagement->SyncEsrtFmp();
+ }
+ Status = EFI_SUCCESS;
+
+ //
+ // Reboot System if required after all capsule processed
+ //
+ if (NeedReset) {
+ REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesEnd)));
+ REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeResettingSystem)));
+
+ Print(L"Capsule Request Cold Reboot.\n");
+ DEBUG((EFI_D_INFO, "Capsule Request Cold Reboot."));
+
+ for (Index = 5; Index > 0; Index--) {
+ Print(L"\rResetting system in %d seconds ...", Index);
+ DEBUG((EFI_D_INFO, "\rResetting system in %d seconds ...", Index));
+ gBS->Stall (1000000);
+ }
+
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+
+ CpuDeadLoop ();
+ }
+
+Done:
+ //
+ // Free the allocated temp memory space.
+ //
+ if (CapsuleGuidCache != NULL) {
+ FreePool(CapsuleGuidCache);
+ }
+ if (CapsulePtrCache != NULL) {
+ FreePool(CapsulePtrCache);
+ }
+ if (CapsulePtr != NULL) {
+ FreePool(CapsulePtr);
+ }
+
+ REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesEnd)));
+
+ return Status;
+}
+
+/**
+
+ This routine is called to process system capsules.
+
+ Caution: This function may receive untrusted input.
+
+ The non-system capsules are skipped.
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ @retval EFI_SUCCESS There is no error when processing capsules.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
+
+**/
+EFI_STATUS
+ProcessSystemCapsules(
+ VOID
+ )
+{
+ return ProcessTheseCapsules(TRUE, TRUE);
+}
+
+/**
+
+ This routine is called to process non-system capsules.
+
+ Caution: This function may receive untrusted input.
+
+ The system capsules are skipped.
+ Each individual capsule result is recorded in capsule record variable.
+
+ @param NeedBlockDriver TRUE: Need skip the FMP capsules with non zero EmbeddedDriverCount.
+ FALSE: No need to skip any FMP capsules.
+
+ @retval EFI_SUCCESS There is no error when processing capsules.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
+
+**/
+EFI_STATUS
+ProcessNonSystemCapsules(
+ IN BOOLEAN NeedBlockDriver
+ )
+{
+ return ProcessTheseCapsules(FALSE, NeedBlockDriver);
+}
+
+/**
+
+ This routine is called to process capsules.
+
+ Caution: This function may receive untrusted input.
+
+ If the current boot mode is NOT BOOT_ON_FLASH_UPDATE, this routine does nothing.
+ If the current boot mode is BOOT_ON_FLASH_UPDATE, the capsules reported in
+ EFI_HOB_UEFI_CAPSULE are processed. If there is no EFI_HOB_UEFI_CAPSULE, this
+ routine does nothing.
+
+ This routine should be called twice in BDS.
+ 1) The first call must be before EndOfDxe. The system capsules is processed.
+ If device capsule FMP protocols are exposted at this time and device FMP
+ capsule has zero EmbeddedDriverCount, the device capsules are processed.
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ 2) The second call must be after EndOfDxe and after ConnectAll, so that all
+ device capsule FMP protocols are exposed.
+ The system capsules are skipped. If the device capsules are NOT processed
+ in first call, they are processed here.
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ @retval EFI_SUCCESS There is no error when processing capsules.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsules(
+ VOID
+ )
+{
+ EFI_BOOT_MODE BootMode;
+ EFI_STATUS Status;
+ EFI_STATUS StatusRet;
+
+ BootMode = GetBootModeHob();
+ if (BootMode != BOOT_ON_FLASH_UPDATE) {
+ return EFI_SUCCESS;
+ }
+
+ if (!mDxeCapsuleLibEndOfDxe) {
+ Status = ProcessSystemCapsules();
+ StatusRet = ProcessNonSystemCapsules(TRUE);
+ if (EFI_ERROR(StatusRet)) {
+ StatusRet = Status;
+ }
+ } else {
+ StatusRet = ProcessNonSystemCapsules(FALSE);
+ }
+ return StatusRet;
+}
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
new file mode 100644
index 0000000..2f8f141
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
@@ -0,0 +1,447 @@
+/** @file
+ DXE capsule report related function.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/VariableLock.h>
+#include <Guid/CapsuleReport.h>
+#include <Guid/FmpCapsule.h>
+#include <Guid/CapsuleVendor.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/CapsuleLib.h>
+
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+/**
+ Get current capsule last variable index.
+
+ @return Current capsule last variable index.
+ @retval -1 No current capsule last variable.
+**/
+INTN
+GetCurrentCapsuleLastIndex(
+ VOID
+ )
+{
+ UINTN Size;
+ CHAR16 CapsuleLastStr[sizeof("Capsule####")];
+ EFI_STATUS Status;
+ UINT16 CurrentIndex;
+
+ Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator
+ Status = gRT->GetVariable(
+ L"CapsuleLast",
+ &gEfiCapsuleReportGuid,
+ NULL,
+ &Size,
+ CapsuleLastStr
+ );
+ if (EFI_ERROR(Status)) {
+ return -1;
+ }
+ CurrentIndex = (UINT16)StrHexToUintn(&CapsuleLastStr[sizeof("Capsule") - 1]);
+ return CurrentIndex;
+}
+
+/**
+ Check if this FMP capsule is recorded.
+
+ @param CapsuleHeader The capsule image header
+ @param PayloadIndex FMP payload index
+ @param ImageHeader FMP image header
+
+ @retval TRUE This FMP capsule is recorded.
+ @retval FALSE This FMP capsule is not recorded.
+**/
+BOOLEAN
+IsFmpCapsuleVariableRecorded(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN UINTN PayloadIndex,
+ IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ INTN CurrentIndex;
+ CHAR16 CapsuleVarName[20];
+ CHAR16 *TempVarName;
+ EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResult;
+ EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultFmp;
+
+ CurrentIndex = GetCurrentCapsuleLastIndex();
+ if (CurrentIndex == -1) {
+ return FALSE;
+ }
+
+ StrCpyS(CapsuleVarName, sizeof(CapsuleVarName) / sizeof(CapsuleVarName[0]), L"Capsule");
+ TempVarName = CapsuleVarName + StrLen(CapsuleVarName);
+ for (Index = 0; Index < (UINT16)CurrentIndex; Index++) {
+ 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;
+ }
+ //
+ // Check
+ //
+ if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
+ if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+ if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
+ CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
+ if (CompareGuid(&CapsuleResultFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId) &&
+ (CapsuleResultFmp->UpdateImageIndex == ImageHeader->UpdateImageIndex) &&
+ (CapsuleResultFmp->PayloadIndex == PayloadIndex) ) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Get a new capsule status variable index.
+
+ @return A new capsule status variable index.
+ @retval -1 No new capsule status variable index.
+**/
+INTN
+GetNewCapsuleResultIndex(
+ VOID
+ )
+{
+ INTN CurrentIndex;
+
+ CurrentIndex = GetCurrentCapsuleLastIndex();
+ if (CurrentIndex >= PcdGet16(PcdCapsuleMax)) {
+ return -1;
+ }
+
+ return CurrentIndex + 1;
+}
+
+/**
+ Write a new capsule status variable.
+
+ @param CapsuleResult The capsule status variable
+ @param CapsuleResultSize The size of the capsule stauts variable in bytes
+
+ @retval EFI_SUCCESS The capsule status variable is recorded.
+ @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
+**/
+EFI_STATUS
+WriteNewCapsuleResultVariable(
+ IN VOID *CapsuleResult,
+ IN UINTN CapsuleResultSize
+ )
+{
+ INTN CapsuleResultIndex;
+ CHAR16 CapsuleResultStr[sizeof("Capsule####")];
+ UINTN Size;
+ EFI_STATUS Status;
+
+ CapsuleResultIndex = GetNewCapsuleResultIndex();
+ DEBUG((EFI_D_INFO, "New CapsuleResultIndex - 0x%x\n", CapsuleResultIndex));
+ if (CapsuleResultIndex == -1) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ UnicodeSPrint(
+ CapsuleResultStr,
+ sizeof(CapsuleResultStr),
+ L"Capsule%04x",
+ CapsuleResultIndex
+ );
+
+ Status = gRT->SetVariable(
+ CapsuleResultStr,
+ &gEfiCapsuleReportGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ CapsuleResultSize,
+ CapsuleResult
+ );
+ if (!EFI_ERROR(Status)) {
+ Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator
+ DEBUG((EFI_D_INFO, "Set CapsuleLast - %s\n", CapsuleResultStr));
+ Status = gRT->SetVariable(
+ L"CapsuleLast",
+ &gEfiCapsuleReportGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ CapsuleResultStr
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Record capsule status variable.
+
+ @param CapsuleHeader The capsule image header
+ @param CapsuleStatus The capsule process stauts
+
+ @retval EFI_SUCCESS The capsule status variable is recorded.
+ @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
+**/
+EFI_STATUS
+RecordCapsuleStatusVariable(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN EFI_STATUS CapsuleStatus
+ )
+{
+ EFI_CAPSULE_RESULT_VARIABLE_HEADER CapsuleResultVariable;
+
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ CapsuleResultVariable.VariableTotalSize = sizeof(CapsuleResultVariable);
+ CopyGuid (&CapsuleResultVariable.CapsuleGuid, &CapsuleHeader->CapsuleGuid);
+ ZeroMem(&CapsuleResultVariable.CapsuleProcessed, sizeof(CapsuleResultVariable.CapsuleProcessed));
+ gRT->GetTime(&CapsuleResultVariable.CapsuleProcessed, NULL);
+ CapsuleResultVariable.CapsuleStatus = CapsuleStatus;
+
+ return WriteNewCapsuleResultVariable(&CapsuleResultVariable, sizeof(CapsuleResultVariable));
+}
+
+/**
+ Record FMP capsule status variable.
+
+ @param CapsuleHeader The capsule image header
+ @param CapsuleStatus The capsule process stauts
+ @param PayloadIndex FMP payload index
+ @param ImageHeader FMP image header
+
+ @retval EFI_SUCCESS The capsule status variable is recorded.
+ @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
+**/
+EFI_STATUS
+RecordFmpCapsuleStatusVariable(
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN EFI_STATUS CapsuleStatus,
+ IN UINTN PayloadIndex,
+ IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
+ )
+{
+ UINT8 CapsuleResultVariable[sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)];
+ EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResultVariableHeader;
+ EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultVariableFmp;
+
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ CapsuleResultVariableHeader = (VOID *)&CapsuleResultVariable[0];
+ CapsuleResultVariableHeader->VariableTotalSize = sizeof(CapsuleResultVariable);
+ CopyGuid(&CapsuleResultVariableHeader->CapsuleGuid, &CapsuleHeader->CapsuleGuid);
+ ZeroMem(&CapsuleResultVariableHeader->CapsuleProcessed, sizeof(CapsuleResultVariableHeader->CapsuleProcessed));
+ gRT->GetTime(&CapsuleResultVariableHeader->CapsuleProcessed, NULL);
+ CapsuleResultVariableHeader->CapsuleStatus = CapsuleStatus;
+
+ CapsuleResultVariableFmp = (VOID *)&CapsuleResultVariable[sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)];
+ CapsuleResultVariableFmp->Version = 0x1;
+ CapsuleResultVariableFmp->PayloadIndex = (UINT8)PayloadIndex;
+ CapsuleResultVariableFmp->UpdateImageIndex = ImageHeader->UpdateImageIndex;
+ CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId);
+
+ return WriteNewCapsuleResultVariable(&CapsuleResultVariable, sizeof(CapsuleResultVariable));
+}
+
+/**
+ Initialize CapsuleMax variables.
+**/
+VOID
+InitCapsuleMaxVariable(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ CHAR16 CapsuleMaxStr[sizeof("Capsule####")];
+ EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
+
+ UnicodeSPrint(
+ CapsuleMaxStr,
+ sizeof(CapsuleMaxStr),
+ L"Capsule%04x",
+ PcdGet16(PcdCapsuleMax)
+ );
+
+ Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator
+ Status = gRT->SetVariable(
+ L"CapsuleMax",
+ &gEfiCapsuleReportGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ CapsuleMaxStr
+ );
+ if (!EFI_ERROR(Status)) {
+ // Lock it per UEFI spec.
+ Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
+ if (!EFI_ERROR(Status)) {
+ Status = VariableLock->RequestToLock(VariableLock, L"CapsuleMax", &gEfiCapsuleReportGuid);
+ ASSERT_EFI_ERROR(Status);
+ }
+ }
+}
+
+/**
+ Initialize CapsuleLast variables.
+**/
+VOID
+InitCapsuleLastVariable(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
+ VOID *CapsuleResult;
+ UINTN Size;
+ CHAR16 CapsuleLastStr[sizeof("Capsule####")];
+
+ BootMode = GetBootModeHob();
+ if (BootMode == BOOT_ON_FLASH_UPDATE) {
+ Status = gRT->SetVariable(
+ L"CapsuleLast",
+ &gEfiCapsuleReportGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ 0,
+ NULL
+ );
+ // Do not lock it because it will be updated later.
+ } else {
+ //
+ // Check if OS/APP cleared L"Capsule####"
+ //
+ ZeroMem(CapsuleLastStr, sizeof(CapsuleLastStr));
+ Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator
+ Status = gRT->GetVariable(
+ L"CapsuleLast",
+ &gEfiCapsuleReportGuid,
+ NULL,
+ &Size,
+ CapsuleLastStr
+ );
+ if (!EFI_ERROR(Status)) {
+ //
+ // L"CapsuleLast" is got, check if data is there.
+ //
+ Status = GetVariable2 (
+ CapsuleLastStr,
+ &gEfiCapsuleReportGuid,
+ (VOID **) &CapsuleResult,
+ NULL
+ );
+ if (EFI_ERROR(Status)) {
+ //
+ // If no data, delete L"CapsuleLast"
+ //
+ Status = gRT->SetVariable(
+ L"CapsuleLast",
+ &gEfiCapsuleReportGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ 0,
+ NULL
+ );
+ }
+ }
+
+ // Lock it in normal boot path per UEFI spec.
+ Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
+ if (!EFI_ERROR(Status)) {
+ Status = VariableLock->RequestToLock(VariableLock, L"CapsuleLast", &gEfiCapsuleReportGuid);
+ ASSERT_EFI_ERROR(Status);
+ }
+ }
+}
+
+/**
+ Initialize capsule update variables.
+**/
+VOID
+InitCapsuleUpdateVariable(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ CHAR16 CapsuleVarName[30];
+ CHAR16 *TempVarName;
+
+ //
+ // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
+ // as early as possible which will avoid the next time boot after the capsule update
+ // will still into the capsule loop
+ //
+ StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), EFI_CAPSULE_VARIABLE_NAME);
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+ Index = 0;
+ while (TRUE) {
+ if (Index > 0) {
+ UnicodeValueToString (TempVarName, 0, Index, 0);
+ }
+ Status = gRT->SetVariable (
+ CapsuleVarName,
+ &gEfiCapsuleVendorGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ (VOID *)NULL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // There is no capsule variables, quit
+ //
+ break;
+ }
+ Index++;
+ }
+}
+
+/**
+ Initialize capsule related variables.
+**/
+VOID
+InitCapsuleVariable(
+ VOID
+ )
+{
+ InitCapsuleUpdateVariable();
+ InitCapsuleMaxVariable();
+ InitCapsuleLastVariable();
+ //
+ // No need to clear L"Capsule####", because OS/APP should refer L"CapsuleLast"
+ // to check status and delete them.
+ //
+}
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
new file mode 100644
index 0000000..8801439
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
@@ -0,0 +1,112 @@
+/** @file
+ Capsule library runtime support.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Guid/FmpCapsule.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+extern EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable;
+extern BOOLEAN mIsVirtualAddrConverted;
+
+/**
+ Convert EsrtTable physical address to virtual address.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context The pointer to the notification function's context, which
+ is implementation-dependent.
+**/
+VOID
+EFIAPI
+DxeCapsuleLibVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Index;
+ EFI_CONFIGURATION_TABLE *ConfigEntry;
+
+ //
+ // Get Esrt table first
+ //
+ ConfigEntry = gST->ConfigurationTable;
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ if (CompareGuid(&gEfiSystemResourceTableGuid, &ConfigEntry->VendorGuid)) {
+ break;
+ }
+ ConfigEntry++;
+ }
+
+ //
+ // If no Esrt table installed in Configure Table
+ //
+ if (Index < gST->NumberOfTableEntries) {
+ //
+ // Search Esrt to check given capsule is qualified
+ //
+ mEsrtTable = (EFI_SYSTEM_RESOURCE_TABLE *) ConfigEntry->VendorTable;
+
+ //
+ // Update protocol pointer to Esrt Table.
+ //
+ gRT->ConvertPointer (0x00, (VOID**) &(mEsrtTable));
+ }
+
+ mIsVirtualAddrConverted = TRUE;
+
+}
+
+/**
+ The constructor function hook VirtualAddressChange event to use ESRT table as capsule routing table.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor successfully .
+**/
+EFI_STATUS
+EFIAPI
+DxeRuntimeCapsuleLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ //
+ // Make sure we can handle virtual address changes.
+ //
+ Event = NULL;
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ DxeCapsuleLibVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
new file mode 100644
index 0000000..2eed206
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
@@ -0,0 +1,85 @@
+## @file
+# Capsule library instance for DXE_RUNTIME_DRIVER.
+#
+# Capsule library instance for DXE_RUNTIME_DRIVER module types.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeRuntimeCapsuleLib
+ MODULE_UNI_FILE = DxeRuntimeCapsuleLib.uni
+ FILE_GUID = 19BE1E4B-1A9A-44c1-8F12-32DD0470516A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CapsuleLib|DXE_RUNTIME_DRIVER
+ CONSTRUCTOR = DxeCapsuleLibConstructor
+ CONSTRUCTOR = DxeRuntimeCapsuleLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ DxeCapsuleLib.c
+ DxeCapsuleProcessLib.c
+ DxeCapsuleReportLib.c
+ DxeCapsuleRuntime.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ DxeServicesTableLib
+ UefiBootServicesTableLib
+ DevicePathLib
+ ReportStatusCodeLib
+ PrintLib
+ HobLib
+ EdkiiSystemCapsuleLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeSubClassCapsule
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesBegin
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem
+
+[Protocols]
+ gEsrtManagementProtocolGuid ## CONSUMES
+ gEfiFirmwareManagementProtocolGuid ## SOMETIMES_CONSUMES
+ gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
+ gWindowsUxCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiSystemResourceTableGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiCapsuleReportGuid ## CONSUMES ## Variable
+ gEfiCapsuleVendorGuid ## CONSUMES ## Variable
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
+ gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
+
+[Depex]
+ gEfiVariableWriteArchProtocolGuid
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
new file mode 100644
index 0000000..cd89b13
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// Capsule library instance for DXE_RUNTIME_DRIVER.
+//
+// Capsule library instance for DXE_RUNTIME_DRIVER module types.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Capsule Support Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Capsule library instance for DXE_RUNTIME_DRIVER module types."
+
--
2.7.4.windows.1


[PATCH 09/45] MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance.

Yao, Jiewen
 

This library is used to authenticate a UEFI defined FMP Capsule.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c | 274 ++++++++++++++++++++
MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf | 47 ++++
MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni | 22 ++
3 files changed, 343 insertions(+)

diff --git a/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
new file mode 100644
index 0000000..2accbb4
--- /dev/null
+++ b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
@@ -0,0 +1,274 @@
+/** @file
+ Provide generic FMP authentication functions for DXE/PEI post memory phase.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/FmpAuthenticationLib.h>
+#include <Library/PcdLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/SystemResourceTable.h>
+
+#define FMP_AUTHENTICATION_HANDLER_TABLE_SIZE 0x10
+
+UINT64 mMonotonicCount;
+
+UINT32 mNumberOfFmpAuthenticationHandler = 0;
+UINT32 mMaxNumberOfFmpAuthenticationHandler = 0;
+
+GUID *mFmpAuthenticationHandlerGuidTable = NULL;
+FMP_AUTHENTICATION_HANDLER *mFmpAuthenticationHandlerTable = NULL;
+
+/**
+ Reallocates more global memory to store the registered guid and Handler list.
+
+ @retval RETURN_SUCCESS Reallocated more global memory space to store guid and function tables.
+ @retval RETURN_OUT_OF_RESOURCES Not enough memory to allocate.
+**/
+RETURN_STATUS
+EFIAPI
+ReallocateFmpAuthenticationHandlerTable (
+ )
+{
+ //
+ // Reallocate memory for GuidTable
+ //
+ mFmpAuthenticationHandlerGuidTable = ReallocatePool (
+ mMaxNumberOfFmpAuthenticationHandler * sizeof (GUID),
+ (mMaxNumberOfFmpAuthenticationHandler + FMP_AUTHENTICATION_HANDLER_TABLE_SIZE) * sizeof (GUID),
+ mFmpAuthenticationHandlerGuidTable
+ );
+ if (mFmpAuthenticationHandlerGuidTable == NULL) {
+ goto Done;
+ }
+
+ //
+ // Reallocate memory for Authentication handler Table
+ //
+ mFmpAuthenticationHandlerTable = ReallocatePool (
+ mMaxNumberOfFmpAuthenticationHandler * sizeof (FMP_AUTHENTICATION_HANDLER),
+ (mMaxNumberOfFmpAuthenticationHandler + FMP_AUTHENTICATION_HANDLER_TABLE_SIZE) * sizeof (FMP_AUTHENTICATION_HANDLER),
+ mFmpAuthenticationHandlerTable
+ );
+ if (mFmpAuthenticationHandlerTable == NULL) {
+ goto Done;
+ }
+
+ //
+ // Increase max handler number
+ //
+ mMaxNumberOfFmpAuthenticationHandler = mMaxNumberOfFmpAuthenticationHandler + FMP_AUTHENTICATION_HANDLER_TABLE_SIZE;
+ return RETURN_SUCCESS;
+
+Done:
+ if (mFmpAuthenticationHandlerGuidTable != NULL) {
+ FreePool (mFmpAuthenticationHandlerGuidTable);
+ }
+ if (mFmpAuthenticationHandlerTable != NULL) {
+ FreePool (mFmpAuthenticationHandlerTable);
+ }
+
+ return RETURN_OUT_OF_RESOURCES;
+}
+
+/**
+ Constructor allocates the global memory to store the registered guid and Handler list.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval RETURN_SUCCESS Allocated the global memory space to store guid and function tables.
+ @retval RETURN_OUT_OF_RESOURCES Not enough memory to allocate.
+**/
+RETURN_STATUS
+EFIAPI
+FmpAuthenticationLibConstructor (
+ VOID
+ )
+{
+ mMonotonicCount = PcdGet64(PcdEdkiiSystemFmpCapsuleMonotonicCount);
+
+ return ReallocateFmpAuthenticationHandlerTable ();
+}
+
+/**
+ Register FMP authentication handler with CertType.
+
+ If CertType is NULL, then ASSERT().
+ If FmpAuthenticationHandler is NULL, then ASSERT().
+
+ @param[in] CertType The certificate type associated with the FMP auth handler.
+ @param[in] FmpAuthenticationHandler The FMP authentication handler to be registered.
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to register the handlers.
+**/
+RETURN_STATUS
+EFIAPI
+RegisterFmpAuthenticationHandler(
+ IN GUID *CertType,
+ IN FMP_AUTHENTICATION_HANDLER FmpAuthenticationHandler
+ )
+{
+ UINTN Index;
+
+ //
+ // Check input paramter.
+ //
+ ASSERT (CertType != NULL);
+ ASSERT (FmpAuthenticationHandler != NULL);
+
+ //
+ // Search the match registered GetInfo handler for the input guided section.
+ //
+ for (Index = 0; Index < mNumberOfFmpAuthenticationHandler; Index ++) {
+ if (CompareGuid (&mFmpAuthenticationHandlerGuidTable[Index], CertType)) {
+ //
+ // If the guided handler has been registered before, only update its handler.
+ //
+ mFmpAuthenticationHandlerTable[Index] = FmpAuthenticationHandler;
+ return RETURN_SUCCESS;
+ }
+ }
+
+ //
+ // Check the global table is enough to contain new Handler.
+ //
+ if (mNumberOfFmpAuthenticationHandler >= mMaxNumberOfFmpAuthenticationHandler) {
+ if (ReallocateFmpAuthenticationHandlerTable () != RETURN_SUCCESS) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // Register new Handler and guid value.
+ //
+ CopyGuid (&mFmpAuthenticationHandlerGuidTable [mNumberOfFmpAuthenticationHandler], CertType);
+ mFmpAuthenticationHandlerTable [mNumberOfFmpAuthenticationHandler] = FmpAuthenticationHandler;
+ mNumberOfFmpAuthenticationHandler++;
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Execute FMP authentication handlers.
+
+ Caution: This function may receive untrusted input.
+
+ If Image is NULL, then ASSERT().
+ If ImageSize is 0, then ASSERT().
+ If LastAttemptStatus is NULL, then ASSERT().
+
+ @param[in] Image Points to the new FMP authentication image,
+ start from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[in] ImageSize Size of the authentication image in bytes.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded
+ in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+ @retval RETURN_SUCCESS Authentication pass.
+ @retval RETURN_SECURITY_VIOLATION Authentication fail.
+ The detail reson is recorded in LastAttemptStatus.
+ @retval RETURN_UNSUPPORTED No Authentication handler associated with CertType.
+**/
+RETURN_STATUS
+EFIAPI
+ExecuteFmpAuthenticationHandler(
+ IN VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *LastAttemptStatus
+ )
+{
+ EFI_FIRMWARE_IMAGE_AUTHENTICATION *ImageAuthentication;
+ UINTN ImageOffset;
+ UINTN Index;
+ GUID *CertType;
+
+ //
+ // Check the input parameters
+ //
+ ASSERT (Image != NULL);
+ ASSERT (ImageSize != 0);
+ ASSERT (LastAttemptStatus != NULL);
+
+ ASSERT (mNumberOfFmpAuthenticationHandler != 0);
+
+ ImageAuthentication = (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image;
+ if (ImageSize < sizeof(EFI_FIRMWARE_IMAGE_AUTHENTICATION)) {
+ DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - ImageSize too small\n"));
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ return RETURN_SECURITY_VIOLATION;
+ }
+ if (ImageAuthentication->AuthInfo.Hdr.dwLength <= sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID)) {
+ DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - dwLength too small\n"));
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ return RETURN_SECURITY_VIOLATION;
+ }
+ if (ImageAuthentication->AuthInfo.Hdr.dwLength > MAX_UINTN - sizeof(UINT64)) {
+ DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - dwLength too big\n"));
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ return RETURN_SECURITY_VIOLATION;
+ }
+ ImageOffset = sizeof(UINT64) + ImageAuthentication->AuthInfo.Hdr.dwLength;
+ if (ImageSize <= ImageOffset) {
+ DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - ImageSize too small\n"));
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ return RETURN_SECURITY_VIOLATION;
+ }
+ if (ImageAuthentication->AuthInfo.Hdr.wRevision != 0x0200) {
+ DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - wRevision: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuthentication->AuthInfo.Hdr.wRevision, (UINTN)0x0200));
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ return RETURN_SECURITY_VIOLATION;
+ }
+ if (ImageAuthentication->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) {
+ DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - wCertificateType: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuthentication->AuthInfo.Hdr.wCertificateType, (UINTN)WIN_CERT_TYPE_EFI_GUID));
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ return RETURN_SECURITY_VIOLATION;
+ }
+
+ //
+ // It is used to ensure freshness / no replay.
+ // It is incremented during each firmware image operation.
+ //
+ if (ImageAuthentication->MonotonicCount < mMonotonicCount) {
+ DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - MonotonicCount: 0x%016lx, current - 0x%016lx\n", ImageAuthentication->MonotonicCount, mMonotonicCount));
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+ return RETURN_SECURITY_VIOLATION;
+ }
+
+ CertType = &ImageAuthentication->AuthInfo.CertType;
+ DEBUG((DEBUG_INFO, "ExecuteFmpAuthenticationHandler - CertType: %g\n", CertType));
+
+ //
+ // Search the match registered extract handler for the input guided section.
+ //
+ for (Index = 0; Index < mNumberOfFmpAuthenticationHandler; Index ++) {
+ if (CompareGuid (&mFmpAuthenticationHandlerGuidTable[Index], CertType)) {
+ //
+ // Call the match handler to extract raw data for the input section data.
+ //
+ return mFmpAuthenticationHandlerTable [Index] (
+ Image,
+ ImageSize,
+ LastAttemptStatus
+ );
+ }
+ }
+
+ //
+ // Not found, the input guided section is not supported.
+ //
+ return RETURN_UNSUPPORTED;
+}
diff --git a/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
new file mode 100644
index 0000000..edd0a61
--- /dev/null
+++ b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
@@ -0,0 +1,47 @@
+## @file
+# FmpAuthenitcation Library
+#
+# Instance of FmpAuthenitcation Library for DXE/PEI post memory phase.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FmpAuthenitcationLib
+ MODULE_UNI_FILE = FmpAuthenitcationLib.uni
+ FILE_GUID = 5011522C-7B0E-4ACB-8E30-9B1D133CF2E0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FmpAuthenitcationLib
+ CONSTRUCTOR = FmpAuthenticationLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ FmpAuthenitcationLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleMonotonicCount
diff --git a/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
new file mode 100644
index 0000000..ea660c0
--- /dev/null
+++ b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// FmpAuthenitcation Library
+//
+// Instance of FmpAuthenitcation Library for DXE/PEI post memory phase.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "FmpAuthenitcation Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Instance of FmpAuthenitcation Library for DXE/PEI post memory phase."
+
--
2.7.4.windows.1


[PATCH 08/45] MdeModulePkg/IniParsingLib: Add InitParsingLib instance.

Yao, Jiewen
 

This library is used to parse the INI configuration file.
The INI configuration file is used in EDKII capsule image to describe
the capsule information.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Library/IniParsingLib/IniParsingLib.c | 1053 ++++++++++++++++++++
MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf | 42 +
MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni | 22 +
3 files changed, 1117 insertions(+)

diff --git a/MdeModulePkg/Library/IniParsingLib/IniParsingLib.c b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
new file mode 100644
index 0000000..e5dd813
--- /dev/null
+++ b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
@@ -0,0 +1,1053 @@
+/** @file
+ This library parses the INI configuration file.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define IS_HYPHEN(a) ((a) == '-')
+#define IS_NULL(a) ((a) == '\0')
+
+#define MAX_LINE_LENGTH 512
+
+typedef struct _SECTION_ITEM SECTION_ITEM;
+struct _SECTION_ITEM {
+ CHAR8 *ptrSection;
+ UINTN SecNameLen;
+ CHAR8 *ptrEntry;
+ CHAR8 *ptrValue;
+ SECTION_ITEM *ptrNext;
+};
+
+typedef struct _COMMENT_LINE COMMENT_LINE;
+struct _COMMENT_LINE {
+ CHAR8 *ptrComment;
+ COMMENT_LINE *ptrNext;
+};
+
+typedef struct {
+ SECTION_ITEM *SectionHead;
+ COMMENT_LINE *CommentHead;
+} INI_PARSING_LIB_CONTEXT;
+
+/**
+ Copy one line data from buffer data to the line buffer.
+
+ @param Buffer Buffer data.
+ @param BufferSize Buffer Size.
+ @param LineBuffer Line buffer to store the found line data.
+ @param LineSize On input, size of the input line buffer.
+ On output, size of the actual line buffer.
+
+ @retval EFI_BUFFER_TOO_SMALL The size of input line buffer is not enough.
+ @retval EFI_SUCCESS Copy line data into the line buffer.
+
+**/
+EFI_STATUS
+ProfileGetLine (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize,
+ IN OUT UINT8 *LineBuffer,
+ IN OUT UINTN *LineSize
+ )
+{
+ UINTN Length;
+ UINT8 *PtrBuf;
+ UINTN PtrEnd;
+
+ PtrBuf = Buffer;
+ PtrEnd = (UINTN)Buffer + BufferSize;
+
+ //
+ // 0x0D indicates a line break. Otherwise there is no line break
+ //
+ while ((UINTN)PtrBuf < PtrEnd) {
+ if (*PtrBuf == 0x0D) {
+ break;
+ }
+ PtrBuf++;
+ }
+
+ if ((UINTN)PtrBuf >= (PtrEnd - 1)) {
+ //
+ // The buffer ends without any line break
+ // or it is the last character of the buffer
+ //
+ Length = BufferSize;
+ } else if (*(PtrBuf + 1) == 0x0A) {
+ //
+ // Further check if a 0x0A follows. If yes, count 0xA
+ //
+ Length = (UINTN) PtrBuf - (UINTN) Buffer + 2;
+ } else {
+ Length = (UINTN) PtrBuf - (UINTN) Buffer + 1;
+ }
+
+ if (Length > (*LineSize)) {
+ *LineSize = Length;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ SetMem (LineBuffer, *LineSize, 0x0);
+ *LineSize = Length;
+ CopyMem (LineBuffer, Buffer, Length);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail.
+
+ @param Buffer On input, buffer data to be trimed.
+ On output, the trimmed buffer.
+ @param BufferSize On input, size of original buffer data.
+ On output, size of the trimmed buffer.
+
+**/
+VOID
+ProfileTrim (
+ IN OUT UINT8 *Buffer,
+ IN OUT UINTN *BufferSize
+ )
+{
+ UINTN Length;
+ UINT8 *PtrBuf;
+ UINT8 *PtrEnd;
+
+ if (*BufferSize == 0) {
+ return;
+ }
+
+ //
+ // Trim the tail first, include CR, LF, TAB, and SPACE.
+ //
+ Length = *BufferSize;
+ PtrBuf = (UINT8 *) ((UINTN) Buffer + Length - 1);
+ while (PtrBuf >= Buffer) {
+ if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
+ && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
+ break;
+ }
+ PtrBuf --;
+ }
+
+ //
+ // all spaces, a blank line, return directly;
+ //
+ if (PtrBuf < Buffer) {
+ *BufferSize = 0;
+ return;
+ }
+
+ Length = (UINTN)PtrBuf - (UINTN)Buffer + 1;
+ PtrEnd = PtrBuf;
+ PtrBuf = Buffer;
+
+ //
+ // Now skip the heading CR, LF, TAB and SPACE
+ //
+ while (PtrBuf <= PtrEnd) {
+ if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
+ && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
+ break;
+ }
+ PtrBuf++;
+ }
+
+ //
+ // If no heading CR, LF, TAB or SPACE, directly return
+ //
+ if (PtrBuf == Buffer) {
+ *BufferSize = Length;
+ return;
+ }
+
+ *BufferSize = (UINTN)PtrEnd - (UINTN)PtrBuf + 1;
+
+ //
+ // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE.
+ // Now move out all these characters.
+ //
+ while (PtrBuf <= PtrEnd) {
+ *Buffer = *PtrBuf;
+ Buffer++;
+ PtrBuf++;
+ }
+
+ return;
+}
+
+/**
+ Insert new comment item into comment head.
+
+ @param Buffer Comment buffer to be added.
+ @param BufferSize Size of comment buffer.
+ @param CommentHead Comment Item head entry.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS New comment item is inserted.
+
+**/
+EFI_STATUS
+ProfileGetComments (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize,
+ IN OUT COMMENT_LINE **CommentHead
+ )
+{
+ COMMENT_LINE *CommentItem;
+
+ CommentItem = NULL;
+ CommentItem = AllocatePool (sizeof (COMMENT_LINE));
+ if (CommentItem == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CommentItem->ptrNext = *CommentHead;
+ *CommentHead = CommentItem;
+
+ //
+ // Add a trailing '\0'
+ //
+ CommentItem->ptrComment = AllocatePool (BufferSize + 1);
+ if (CommentItem->ptrComment == NULL) {
+ FreePool (CommentItem);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (CommentItem->ptrComment, Buffer, BufferSize);
+ *(CommentItem->ptrComment + BufferSize) = '\0';
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add new section item into Section head.
+
+ @param Buffer Section item data buffer.
+ @param BufferSize Size of section item.
+ @param SectionHead Section item head entry.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Section item is NULL or Section item is added.
+
+**/
+EFI_STATUS
+ProfileGetSection (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize,
+ IN OUT SECTION_ITEM **SectionHead
+ )
+{
+ EFI_STATUS Status;
+ SECTION_ITEM *SectionItem;
+ UINTN Length;
+ UINT8 *PtrBuf;
+
+ Status = EFI_SUCCESS;
+ //
+ // The first character of Buffer is '[', now we want for ']'
+ //
+ PtrBuf = (UINT8 *)((UINTN)Buffer + BufferSize - 1);
+ while (PtrBuf > Buffer) {
+ if (*PtrBuf == ']') {
+ break;
+ }
+ PtrBuf --;
+ }
+ if (PtrBuf <= Buffer) {
+ //
+ // Not found. Omit this line
+ //
+ return Status;
+ }
+
+ //
+ // excluding the heading '[' and tailing ']'
+ //
+ Length = PtrBuf - Buffer - 1;
+ ProfileTrim (
+ Buffer + 1,
+ &Length
+ );
+
+ //
+ // omit this line if the section name is null
+ //
+ if (Length == 0) {
+ return Status;
+ }
+
+ SectionItem = AllocatePool (sizeof (SECTION_ITEM));
+ if (SectionItem == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SectionItem->ptrSection = NULL;
+ SectionItem->SecNameLen = Length;
+ SectionItem->ptrEntry = NULL;
+ SectionItem->ptrValue = NULL;
+ SectionItem->ptrNext = *SectionHead;
+ *SectionHead = SectionItem;
+
+ //
+ // Add a trailing '\0'
+ //
+ SectionItem->ptrSection = AllocatePool (Length + 1);
+ if (SectionItem->ptrSection == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // excluding the heading '['
+ //
+ CopyMem (SectionItem->ptrSection, Buffer + 1, Length);
+ *(SectionItem->ptrSection + Length) = '\0';
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add new section entry and entry value into Section head.
+
+ @param Buffer Section entry data buffer.
+ @param BufferSize Size of section entry.
+ @param SectionHead Section item head entry.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Section entry is NULL or Section entry is added.
+
+**/
+EFI_STATUS
+ProfileGetEntry (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize,
+ IN OUT SECTION_ITEM **SectionHead
+ )
+{
+ EFI_STATUS Status;
+ SECTION_ITEM *SectionItem;
+ SECTION_ITEM *PtrSection;
+ UINTN Length;
+ UINT8 *PtrBuf;
+ UINT8 *PtrEnd;
+
+ Status = EFI_SUCCESS;
+ PtrBuf = Buffer;
+ PtrEnd = (UINT8 *) ((UINTN)Buffer + BufferSize - 1);
+
+ //
+ // First search for '='
+ //
+ while (PtrBuf <= PtrEnd) {
+ if (*PtrBuf == '=') {
+ break;
+ }
+ PtrBuf++;
+ }
+ if (PtrBuf > PtrEnd) {
+ //
+ // Not found. Omit this line
+ //
+ return Status;
+ }
+
+ //
+ // excluding the tailing '='
+ //
+ Length = PtrBuf - Buffer;
+ ProfileTrim (
+ Buffer,
+ &Length
+ );
+
+ //
+ // Omit this line if the entry name is null
+ //
+ if (Length == 0) {
+ return Status;
+ }
+
+ //
+ // Omit this line if no section header has been found before
+ //
+ if (*SectionHead == NULL) {
+ return Status;
+ }
+ PtrSection = *SectionHead;
+
+ SectionItem = AllocatePool (sizeof (SECTION_ITEM));
+ if (SectionItem == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SectionItem->ptrSection = NULL;
+ SectionItem->ptrEntry = NULL;
+ SectionItem->ptrValue = NULL;
+ SectionItem->SecNameLen = PtrSection->SecNameLen;
+ SectionItem->ptrNext = *SectionHead;
+ *SectionHead = SectionItem;
+
+ //
+ // SectionName, add a trailing '\0'
+ //
+ SectionItem->ptrSection = AllocatePool (PtrSection->SecNameLen + 1);
+ if (SectionItem->ptrSection == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (SectionItem->ptrSection, PtrSection->ptrSection, PtrSection->SecNameLen + 1);
+
+ //
+ // EntryName, add a trailing '\0'
+ //
+ SectionItem->ptrEntry = AllocatePool (Length + 1);
+ if (SectionItem->ptrEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (SectionItem->ptrEntry, Buffer, Length);
+ *(SectionItem->ptrEntry + Length) = '\0';
+
+ //
+ // Next search for '#'
+ //
+ PtrBuf = PtrBuf + 1;
+ Buffer = PtrBuf;
+ while (PtrBuf <= PtrEnd) {
+ if (*PtrBuf == '#') {
+ break;
+ }
+ PtrBuf++;
+ }
+ Length = PtrBuf - Buffer;
+ ProfileTrim (
+ Buffer,
+ &Length
+ );
+
+ if (Length > 0) {
+ //
+ // EntryValue, add a trailing '\0'
+ //
+ SectionItem->ptrValue = AllocatePool (Length + 1);
+ if (SectionItem->ptrValue == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (SectionItem->ptrValue, Buffer, Length);
+ *(SectionItem->ptrValue + Length) = '\0';
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Free all comment entry and section entry.
+
+ @param Section Section entry list.
+ @param Comment Comment entry list.
+
+**/
+VOID
+FreeAllList (
+ IN SECTION_ITEM *Section,
+ IN COMMENT_LINE *Comment
+ )
+{
+ SECTION_ITEM *PtrSection;
+ COMMENT_LINE *PtrComment;
+
+ while (Section != NULL) {
+ PtrSection = Section;
+ Section = Section->ptrNext;
+ if (PtrSection->ptrEntry != NULL) {
+ FreePool (PtrSection->ptrEntry);
+ }
+ if (PtrSection->ptrSection != NULL) {
+ FreePool (PtrSection->ptrSection);
+ }
+ if (PtrSection->ptrValue != NULL) {
+ FreePool (PtrSection->ptrValue);
+ }
+ FreePool (PtrSection);
+ }
+
+ while (Comment != NULL) {
+ PtrComment = Comment;
+ Comment = Comment->ptrNext;
+ if (PtrComment->ptrComment != NULL) {
+ FreePool (PtrComment->ptrComment);
+ }
+ FreePool (PtrComment);
+ }
+
+ return;
+}
+
+/**
+ Get section entry value.
+
+ @param Section Section entry list.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param EntryValue Point to the got entry value.
+
+ @retval EFI_NOT_FOUND Section is not found.
+ @retval EFI_SUCCESS Section entry value is got.
+
+**/
+EFI_STATUS
+UpdateGetProfileString (
+ IN SECTION_ITEM *Section,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT CHAR8 **EntryValue
+ )
+{
+ *EntryValue = NULL;
+
+ while (Section != NULL) {
+ if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrSection, (CONST CHAR8 *) SectionName) == 0) {
+ if (Section->ptrEntry != NULL) {
+ if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrEntry, (CONST CHAR8 *) EntryName) == 0) {
+ break;
+ }
+ }
+ }
+ Section = Section->ptrNext;
+ }
+
+ if (Section == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ *EntryValue = Section->ptrValue;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Converts a list of string to a specified buffer.
+
+ @param Buf The output buffer that contains the string.
+ @param BufferLength The length of the buffer
+ @param Str The input string that contains the hex number
+
+ @retval EFI_SUCCESS The string was successfully converted to the buffer.
+
+**/
+EFI_STATUS
+AsciiStrToBuf (
+ OUT UINT8 *Buf,
+ IN UINTN BufferLength,
+ IN CHAR8 *Str
+ )
+{
+ UINTN Index;
+ UINTN StrLength;
+ UINT8 Digit;
+ UINT8 Byte;
+
+ Digit = 0;
+
+ //
+ // Two hex char make up one byte
+ //
+ StrLength = BufferLength * sizeof (CHAR8);
+
+ for(Index = 0; Index < StrLength; Index++, Str++) {
+
+ if ((*Str >= 'a') && (*Str <= 'f')) {
+ Digit = (UINT8) (*Str - 'a' + 0x0A);
+ } else if ((*Str >= 'A') && (*Str <= 'F')) {
+ Digit = (UINT8) (*Str - 'A' + 0x0A);
+ } else if ((*Str >= '0') && (*Str <= '9')) {
+ Digit = (UINT8) (*Str - '0');
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For odd characters, write the upper nibble for each buffer byte,
+ // and for even characters, the lower nibble.
+ //
+ if ((Index & 1) == 0) {
+ Byte = (UINT8) (Digit << 4);
+ } else {
+ Byte = Buf[Index / 2];
+ Byte &= 0xF0;
+ Byte = (UINT8) (Byte | Digit);
+ }
+
+ Buf[Index / 2] = Byte;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Converts a string to GUID value.
+ Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+ @param Str The registry format GUID string that contains the GUID value.
+ @param Guid A pointer to the converted GUID value.
+
+ @retval EFI_SUCCESS The GUID string was successfully converted to the GUID value.
+ @retval EFI_UNSUPPORTED The input string is not in registry format.
+ @return others Some error occurred when converting part of GUID value.
+
+**/
+EFI_STATUS
+AsciiStrToGuid (
+ IN CHAR8 *Str,
+ OUT EFI_GUID *Guid
+ )
+{
+ //
+ // Get the first UINT32 data
+ //
+ Guid->Data1 = (UINT32) AsciiStrHexToUint64 (Str);
+ while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
+ Str ++;
+ }
+
+ if (IS_HYPHEN (*Str)) {
+ Str++;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the second UINT16 data
+ //
+ Guid->Data2 = (UINT16) AsciiStrHexToUint64 (Str);
+ while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
+ Str ++;
+ }
+
+ if (IS_HYPHEN (*Str)) {
+ Str++;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the third UINT16 data
+ //
+ Guid->Data3 = (UINT16) AsciiStrHexToUint64 (Str);
+ while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
+ Str ++;
+ }
+
+ if (IS_HYPHEN (*Str)) {
+ Str++;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the following 8 bytes data
+ //
+ AsciiStrToBuf (&Guid->Data4[0], 2, Str);
+ //
+ // Skip 2 byte hex chars
+ //
+ Str += 2 * 2;
+
+ if (IS_HYPHEN (*Str)) {
+ Str++;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ AsciiStrToBuf (&Guid->Data4[2], 6, Str);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Pre process config data buffer into Section entry list and Comment entry list.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+ @param SectionHead Pointer to the section entry list.
+ @param CommentHead Pointer to the comment entry list.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Config data buffer is preprocessed.
+
+**/
+EFI_STATUS
+PreProcessDataFile (
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize,
+ IN OUT SECTION_ITEM **SectionHead,
+ IN OUT COMMENT_LINE **CommentHead
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *Source;
+ CHAR8 *CurrentPtr;
+ CHAR8 *BufferEnd;
+ CHAR8 *PtrLine;
+ UINTN LineLength;
+ UINTN SourceLength;
+ UINTN MaxLineLength;
+
+ *SectionHead = NULL;
+ *CommentHead = NULL;
+ BufferEnd = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize);
+ CurrentPtr = (CHAR8 *) DataBuffer;
+ MaxLineLength = MAX_LINE_LENGTH;
+ Status = EFI_SUCCESS;
+
+ PtrLine = AllocatePool (MaxLineLength);
+ if (PtrLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ while (CurrentPtr < BufferEnd) {
+ Source = CurrentPtr;
+ SourceLength = (UINTN)BufferEnd - (UINTN)CurrentPtr;
+ LineLength = MaxLineLength;
+ //
+ // With the assumption that line length is less than 512
+ // characters. Otherwise BUFFER_TOO_SMALL will be returned.
+ //
+ Status = ProfileGetLine (
+ (UINT8 *) Source,
+ SourceLength,
+ (UINT8 *) PtrLine,
+ &LineLength
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // If buffer too small, re-allocate the buffer according
+ // to the returned LineLength and try again.
+ //
+ FreePool (PtrLine);
+ PtrLine = NULL;
+ PtrLine = AllocatePool (LineLength);
+ if (PtrLine == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ SourceLength = LineLength;
+ Status = ProfileGetLine (
+ (UINT8 *) Source,
+ SourceLength,
+ (UINT8 *) PtrLine,
+ &LineLength
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ MaxLineLength = LineLength;
+ } else {
+ break;
+ }
+ }
+ CurrentPtr = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength);
+
+ //
+ // Line got. Trim the line before processing it.
+ //
+ ProfileTrim (
+ (UINT8 *) PtrLine,
+ &LineLength
+ );
+
+ //
+ // Blank line
+ //
+ if (LineLength == 0) {
+ continue;
+ }
+
+ if (PtrLine[0] == '#' || PtrLine[0] == ';') {
+ Status = ProfileGetComments (
+ (UINT8 *) PtrLine,
+ LineLength,
+ CommentHead
+ );
+ } else if (PtrLine[0] == '[') {
+ Status = ProfileGetSection (
+ (UINT8 *) PtrLine,
+ LineLength,
+ SectionHead
+ );
+ } else {
+ Status = ProfileGetEntry (
+ (UINT8 *) PtrLine,
+ LineLength,
+ SectionHead
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ //
+ // Free buffer
+ //
+ FreePool (PtrLine);
+
+ return Status;
+}
+
+/**
+ Open an INI config file and return a context.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+
+ @retval EFI_SUCCESS Config data buffer is opened and context is returned.
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+**/
+VOID *
+EFIAPI
+OpenDataFile (
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize
+ )
+{
+ EFI_STATUS Status;
+ INI_PARSING_LIB_CONTEXT *IniContext;
+
+ IniContext = AllocateZeroPool(sizeof(INI_PARSING_LIB_CONTEXT));
+ if (IniContext == NULL) {
+ return NULL;
+ }
+
+ //
+ // First process the data buffer and get all sections and entries
+ //
+ Status = PreProcessDataFile (
+ DataBuffer,
+ BufferSize,
+ &IniContext->SectionHead,
+ &IniContext->CommentHead
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool(IniContext);
+ return NULL;
+ }
+
+ return IniContext;
+}
+
+/**
+ Get section entry string value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param EntryValue Point to the got entry string value.
+
+ @retval EFI_SUCCESS Section entry string value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetStringFromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT CHAR8 **EntryValue
+ )
+{
+ INI_PARSING_LIB_CONTEXT *IniContext;
+ EFI_STATUS Status;
+
+ IniContext = Context;
+
+ *EntryValue = NULL;
+ Status = UpdateGetProfileString (
+ IniContext->SectionHead,
+ SectionName,
+ EntryName,
+ EntryValue
+ );
+ return Status;
+}
+
+/**
+ Get section entry GUID value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param Guid Point to the got GUID value.
+
+ @retval EFI_SUCCESS Section entry GUID value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetGuidFromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT EFI_GUID *Guid
+ )
+{
+ CHAR8 *Value;
+ EFI_STATUS Status;
+
+ Status = GetStringFromDataFile(
+ Context,
+ SectionName,
+ EntryName,
+ &Value
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = AsciiStrToGuid(Value, Guid);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get section entry decimal UINTN value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param Data Point to the got decimal UINTN value.
+
+ @retval EFI_SUCCESS Section entry decimal UINTN value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetDecimalUintnFromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT UINTN *Data
+ )
+{
+ CHAR8 *Value;
+ EFI_STATUS Status;
+
+ Status = GetStringFromDataFile(
+ Context,
+ SectionName,
+ EntryName,
+ &Value
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_NOT_FOUND;
+ }
+ *Data = AsciiStrDecimalToUintn(Value);
+ return EFI_SUCCESS;
+}
+
+/**
+ Get section entry heximal UINTN value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param Data Point to the got heximal UINTN value.
+
+ @retval EFI_SUCCESS Section entry heximal UINTN value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetHexUintnFromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT UINTN *Data
+ )
+{
+ CHAR8 *Value;
+ EFI_STATUS Status;
+
+ Status = GetStringFromDataFile(
+ Context,
+ SectionName,
+ EntryName,
+ &Value
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_NOT_FOUND;
+ }
+ *Data = AsciiStrHexToUintn(Value);
+ return EFI_SUCCESS;
+}
+
+/**
+ Get section entry heximal UINT64 value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param Data Point to the got heximal UINT64 value.
+
+ @retval EFI_SUCCESS Section entry heximal UINT64 value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetHexUint64FromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT UINT64 *Data
+ )
+{
+ CHAR8 *Value;
+ EFI_STATUS Status;
+
+ Status = GetStringFromDataFile(
+ Context,
+ SectionName,
+ EntryName,
+ &Value
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_NOT_FOUND;
+ }
+ *Data = AsciiStrHexToUint64(Value);
+ return EFI_SUCCESS;
+}
+
+/**
+ Close an INI config file and free the context.
+
+ @param Context INI Config file context.
+**/
+VOID
+EFIAPI
+CloseDataFile(
+ IN VOID *Context
+ )
+{
+ INI_PARSING_LIB_CONTEXT *IniContext;
+
+ IniContext = Context;
+ FreeAllList(IniContext->SectionHead, IniContext->CommentHead);
+
+ return;
+}
diff --git a/MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
new file mode 100644
index 0000000..4721388
--- /dev/null
+++ b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
@@ -0,0 +1,42 @@
+## @file
+# INI configuration parsing library.
+#
+# This library parses the INI configuration file.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IniParsingLib
+ MODULE_UNI_FILE = IniParsingLib.uni
+ FILE_GUID = 6E4CD200-43E5-43CE-89E9-D715CF9526C4
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = IniParsingLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ IniParsingLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
diff --git a/MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
new file mode 100644
index 0000000..9b198e8
--- /dev/null
+++ b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// INI configuration parsing library.
+//
+// This library parses the INI configuration file.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "INI configuration parsing library."
+
+#string STR_MODULE_DESCRIPTION #language en-US "This library parses the INI configuration file."
+
--
2.7.4.windows.1


[PATCH 07/45] MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.

Yao, Jiewen
 

1) Add capsule related GUID.
EdkiiSystemFmpCapsule
2) Add capsule related library.
EdkiiSystemCapsuleLib
FmpAuthenticationLib
IniParsingLib
PlatformFlashAccessLib.c
3) Add capsule related status code PCD.
PcdStatusCodeSubClassCapsule
PcdCapsuleStatusCodeProcessCapsulesBegin
PcdCapsuleStatusCodeProcessCapsulesEnd
PcdCapsuleStatusCodeUpdatingFirmware
PcdCapsuleStatusCodeUpdateFirmwareSuccess
PcdCapsuleStatusCodeUpdateFirmwareFailed
PcdCapsuleStatusCodeResettingSystem
4) Add capsule status variable PCD - CapsuleMax value.
PcdCapsuleMax
5) Add EDKII system capsule related DynamicEx PCD
PcdEdkiiSystemFmpCapsuleMonotonicCount
PcdEdkiiSystemFirmwareImageDescriptor
PcdEdkiiSystemFirmwareFileGuid
PcdEdkiiSystemFmpCapsuleImageTypeIdGuid
NOTE: We use DynamicEx here because the update driver may be in
the capsule FMP, instead of system BIOS.
The update driver MUST use the PCD info produced system BIOS.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/MdeModulePkg.dec | 106 ++++++++++++++++++++
1 file changed, 106 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 8d90f16..113abf7 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -157,6 +157,22 @@
#
MemoryProfileLib|Include/Library/MemoryProfileLib.h

+ ## @libraryclass Provides services to authenticate a UEFI defined FMP Capsule.
+ #
+ FmpAuthenticationLib|Include/Library/FmpAuthenticationLib.h
+
+ ## @libraryclass Provides services for EDKII system FMP capsule.
+ #
+ EdkiiSystemCapsuleLib|Include/Library/EdkiiSystemCapsuleLib.h
+
+ ## @libraryclass Provides services to parse the INI configuration file.
+ #
+ IniParsingLib|Include/Library/IniParsingLib.h
+
+ ## @libraryclass Provides services to access flash device.
+ #
+ PlatformFlashAccessLib|Include/Library/PlatformFlashAccessLib.h
+
[Guids]
## MdeModule package token space guid
# Include/Guid/MdeModulePkgTokenSpace.h
@@ -355,6 +371,11 @@
## Include/Guid/PiSmmCommunicationRegionTable.h
gEdkiiPiSmmCommunicationRegionTableGuid = { 0x4e28ca50, 0xd582, 0x44ac, {0xa1, 0x1f, 0xe3, 0xd5, 0x65, 0x26, 0xdb, 0x34}}

+ ## Include/Guid/EdkiiSystemFmpCapsule.h
+ gEdkiiSystemFirmwareImageDescriptorFileGuid = {0x90b2b846, 0xca6d, 0x4d6e, {0xa8, 0xd3, 0xc1, 0x40, 0xa8, 0xe1, 0x10, 0xac}}
+ gEdkiiSystemFmpCapsuleConfigFileGuid = {0x812136d3, 0x4d3a, 0x433a, {0x94, 0x18, 0x29, 0xbb, 0x9b, 0xf7, 0x8f, 0x6e}}
+ gEdkiiSystemFmpCapsuleDriverFvFileGuid = {0xce57b167, 0xb0e4, 0x41e8, {0xa8, 0x97, 0x5f, 0x4f, 0xeb, 0x78, 0x1d, 0x40}}
+
[Ppis]
## Include/Ppi/AtaController.h
gPeiAtaControllerPpiGuid = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
@@ -1130,6 +1151,52 @@
# @Prompt MAX repair count
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxRepairCount|0x00|UINT32|0x00010076

+ ## Status Code for Capsule subclass definitions.<BR><BR>
+ # EFI_SOFTWARE_CAPSULE = (EFI_SOFTWARE | 0x00150000) = 0x03150000<BR>
+ # @Prompt Status Code for Capsule subclass definitions
+ # @ValidList 0x80000003 | 0x03150000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeSubClassCapsule|0x03150000|UINT32|0x00000100
+
+ ## Status Code for Capsule definitions.<BR><BR>
+ # EFI_CAPSULE_PROCESS_CAPSULES_BEGIN = (EFI_SUBCLASS_SPECIFIC | 0x00000001) = 0x00010001<BR>
+ # @Prompt Status Code for Capsule definitions
+ # @ValidList 0x80000003 | 0x00010001
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesBegin|0x00010001|UINT32|0x00000101
+
+ ## Status Code for Capsule definitions.<BR><BR>
+ # EFI_CAPSULE_PROCESS_CAPSULES_END = (EFI_SUBCLASS_SPECIFIC | 0x00000002) = 0x00010002<BR>
+ # @Prompt Status Code for Capsule definitions
+ # @ValidList 0x80000003 | 0x00010002
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd|0x00010002|UINT32|0x00000102
+
+ ## Status Code for Capsule definitions.<BR><BR>
+ # EFI_CAPSULE_UPDATING_FIRMWARE = (EFI_SUBCLASS_SPECIFIC | 0x00000003) = 0x00010003<BR>
+ # @Prompt Status Code for Capsule definitions
+ # @ValidList 0x80000003 | 0x00010003
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware|0x00010003|UINT32|0x00000103
+
+ ## Status Code for Capsule definitions.<BR><BR>
+ # EFI_CAPSULE_UPDATE_FIRMWARE_SUCCESS = (EFI_SUBCLASS_SPECIFIC | 0x00000004) = 0x00010004<BR>
+ # @Prompt Status Code for Capsule definitions
+ # @ValidList 0x80000003 | 0x00010004
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess|0x00010004|UINT32|0x00000104
+
+ ## Status Code for Capsule definitions.<BR><BR>
+ # EFI_CAPSULE_UPDATE_FIRMWARE_FAILED = (EFI_SUBCLASS_SPECIFIC | 0x00000005) = 0x00010005<BR>
+ # @Prompt Status Code for Capsule definitions
+ # @ValidList 0x80000003 | 0x00010005
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed|0x00010005|UINT32|0x00000105
+
+ ## Status Code for Capsule definitions.<BR><BR>
+ # EFI_CAPSULE_RESETTING_SYSTEM = (EFI_SUBCLASS_SPECIFIC | 0x00000006) = 0x00010006<BR>
+ # @Prompt Status Code for Capsule definitions
+ # @ValidList 0x80000003 | 0x00010001
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem|0x00010006|UINT32|0x00000106
+
+ ## CapsuleMax value in capsule report variable.
+ # @Prompt CapsuleMax value in capsule report variable.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax|0xFFFF|UINT16|0x00000107
+
[PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## This PCD defines the Console output row. The default value is 25 according to UEFI spec.
# This PCD could be set to 0 then console output would be at max column and max row.
@@ -1621,5 +1688,44 @@
# @ValidList 0x80000001 | 0x0
gEfiMdeModulePkgTokenSpaceGuid.PcdIdentifyMappingPageTablePtr|0x0|UINT64|0x00030002

+[PcdsDynamicEx]
+ ## This dynamic PCD hold the FMP capsule monotonic count value for current
+ # BIOS. It is used to ensure freshness/no replay on firmware update.
+ # Only if the new system FmpCapsule EFI_FIRMWARE_IMAGE_AUTHENTICATION.MonotonicCount
+ # is no less than this PcdFmpCapsuleMonotonicCount, the EDKII system
+ # FmpCapsule will be processed.
+ # It must be dynamicEx, because the EDKII system firmware update module may
+ # consume the PCD produced in current BIOS.
+ # @Prompt EDKII system FMP capsule monotonic count.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleMonotonicCount|1|UINT64|0x000035
+
+ ## This dynamic PCD hold the EDKII system firmware image descriptor.
+ # This information can be used for version check in EDKII system FMP capsule.
+ # Only if the new EdkiiSystemFrimwareImageDescriptor.Version is no less than
+ # the current PcdEdkiiSystemFirmwareImageDescriptor.LowestSupportedVersion,
+ # the EDKII system FmpCapsule will be processed.
+ # It must be dynamicEx, because the EDKII system firmware update module may
+ # consume the PCD produced in current BIOS.
+ # @Prompt EDKII system firwmare image descriptor.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0}|VOID*|0x00000037
+
+ ## This dynamic PCD hold the GUID of a firmware FFS which includes EDKII
+ # system firmware image.
+ # An EDKII system firmware udpate module need consume this PCD to extract
+ # the EDKII system firmware from the capsule image.
+ # It must be dynamicEx, because the EDKII system firmware update module may
+ # consume the PCD produced in current BIOS.
+ # @Prompt EDKII system firmware image FFS GUID.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareFileGuid|{0xb2, 0x9e, 0x9c, 0xaf, 0xad, 0x12, 0x3e, 0x4d, 0xa4, 0xd4, 0x96, 0xf6, 0xc9, 0x96, 0x62, 0x15}|VOID*|0x00001010
+
+ ## This dynamic PCD hold a list GUIDs for the ImageTypeId to indicate the
+ # FMP capsule is EDKII system FMP.
+ # An EDKII system firmware udpate module need consume this PCD to know if
+ # This FMP capsule is a system FMP or device FMP.
+ # It must be dynamicEx, because the EDKII system firmware update module may
+ # consume the PCD produced in current BIOS.
+ # @Prompt A list of EDKII system FMP ImageTypeId GUIDs
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0xd3, 0xee, 0x7e, 0x3f, 0x91, 0xf4, 0x1e, 0x40, 0x9e, 0xce, 0x74, 0x31, 0x32, 0x2e, 0xad, 0xf6}|VOID*|0x00001011
+
[UserExtensions.TianoCore."ExtraFiles"]
MdeModulePkgExtra.uni
--
2.7.4.windows.1


[PATCH 06/45] MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.

Yao, Jiewen
 

ProcessCapsules() API can be used by platform BDS to process all capsules.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Include/Library/CapsuleLib.h | 45 ++++++++++++++++++--
1 file changed, 42 insertions(+), 3 deletions(-)

diff --git a/MdeModulePkg/Include/Library/CapsuleLib.h b/MdeModulePkg/Include/Library/CapsuleLib.h
index 487cb0f..659c077 100644
--- a/MdeModulePkg/Include/Library/CapsuleLib.h
+++ b/MdeModulePkg/Include/Library/CapsuleLib.h
@@ -2,7 +2,7 @@

This library class defines a set of interfaces for how to process capsule image updates.

-Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
@@ -20,7 +20,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
The firmware checks whether the capsule image is supported
by the CapsuleGuid in CapsuleHeader or if there is other specific information in
the capsule image.
-
+
+ Caution: This function may receive untrusted input.
+
@param CapsuleHeader Pointer to the UEFI capsule image to be checked.

@retval EFI_SUCESS Input capsule is supported by firmware.
@@ -35,7 +37,9 @@ SupportCapsuleImage (
/**
The firmware-specific implementation processes the capsule image
if it recognized the format of this capsule image.
-
+
+ Caution: This function may receive untrusted input.
+
@param CapsuleHeader Pointer to the UEFI capsule image to be processed.

@retval EFI_SUCESS Capsule Image processed successfully.
@@ -47,4 +51,39 @@ ProcessCapsuleImage (
IN EFI_CAPSULE_HEADER *CapsuleHeader
);

+/**
+
+ This routine is called to process capsules.
+
+ Caution: This function may receive untrusted input.
+
+ If the current boot mode is NOT BOOT_ON_FLASH_UPDATE, this routine does nothing.
+ If the current boot mode is BOOT_ON_FLASH_UPDATE, the capsules reported in
+ EFI_HOB_UEFI_CAPSULE are processed. If there is no EFI_HOB_UEFI_CAPSULE, this
+ routine does nothing.
+
+ This routine should be called twice in BDS.
+ 1) The first call must be before EndOfDxe. The system capsules is processed.
+ If device capsule FMP protocols are exposted at this time, the device
+ capsules are processed.
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ 2) The second call must be after EndOfDxe and after ConnectAll, so that all
+ device capsule FMP protocols are exposed.
+ The system capsules are skipped. If the device capsules are NOT processed
+ in first call, they are processed here.
+ Each individual capsule result is recorded in capsule record variable.
+ System may reset in this function, if reset is required by capsule.
+
+ @retval EFI_SUCCESS There is no error when processing capsules.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsules(
+ VOID
+ );
+
#endif
--
2.7.4.windows.1


[PATCH 05/45] MdeModulePkg/Include: Add PlatformFlashAccessLib header.

Yao, Jiewen
 

This library is used to abstract platform flash access.
This library is consumed by a capsule update module.
It may cover BIOS region and/or non-BIOS region.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Include/Library/PlatformFlashAccessLib.h | 59 ++++++++++++++++++++
1 file changed, 59 insertions(+)

diff --git a/MdeModulePkg/Include/Library/PlatformFlashAccessLib.h b/MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
new file mode 100644
index 0000000..694c1c5
--- /dev/null
+++ b/MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
@@ -0,0 +1,59 @@
+/** @file
+ Platform flash device access library.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __PLATFORM_FLASH_ACCESS_LIB_H__
+#define __PLATFORM_FLASH_ACCESS_LIB_H__
+
+typedef enum {
+ FlashAddressTypeRelativeAddress,
+ FlashAddressTypeAbsoluteAddress,
+ FlashAddressTypeMax,
+} FLASH_ADDRESS_TYPE;
+
+//
+// Type 0 ~ 0x7FFFFFFF is defined in this library.
+// Type 0x80000000 ~ 0xFFFFFFFF is reserved for OEM.
+//
+typedef enum {
+ PlatformFirmwareTypeBios,
+ PlatformFirmwareTypeNvRam,
+ PlatformFirmwareTypeMax,
+} PLATFORM_FIRMWARE_TYPE;
+
+/**
+ Perform flash write opreation.
+
+ @param FirmwareType The type of firmware.
+ @param FlashAddress The address of flash device to be accessed.
+ @param FlashAddressType The type of flash device address.
+ @param Buffer The pointer to the data buffer.
+ @param Length The length of data buffer in bytes.
+
+ @retval EFI_SUCCESS The operation returns successfully.
+ @retval EFI_WRITE_PROTECTED The flash device is read only.
+ @retval EFI_UNSUPPORTED The flash device access is unsupported.
+ @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite (
+ IN PLATFORM_FIRMWARE_TYPE FirmwareType,
+ IN EFI_PHYSICAL_ADDRESS FlashAddress,
+ IN FLASH_ADDRESS_TYPE FlashAddressType,
+ IN VOID *Buffer,
+ IN UINTN Length
+ );
+
+#endif
--
2.7.4.windows.1


[PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header.

Yao, Jiewen
 

This library is used to parse the INI configuration file.
The INI configuration file is used in EDKII capsule image to describe
the capsule information.

The INI file format is:
================
[SectionName]
EntryName=EntryValue
================

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Include/Library/IniParsingLib.h | 153 ++++++++++++++++++++
1 file changed, 153 insertions(+)

diff --git a/MdeModulePkg/Include/Library/IniParsingLib.h b/MdeModulePkg/Include/Library/IniParsingLib.h
new file mode 100644
index 0000000..e3ed18d
--- /dev/null
+++ b/MdeModulePkg/Include/Library/IniParsingLib.h
@@ -0,0 +1,153 @@
+/** @file
+ INI configuration parsing library.
+
+ The INI file format is:
+ ================
+ [SectionName]
+ EntryName=EntryValue
+ ================
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __INI_PARSING_LIB_H__
+#define __INI_PARSING_LIB_H__
+
+/**
+ Open an INI config file and return a context.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+
+ @retval EFI_SUCCESS Config data buffer is opened and context is returned.
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+**/
+VOID *
+EFIAPI
+OpenDataFile(
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize
+ );
+
+/**
+ Get section entry string value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param EntryValue Point to the got entry string value.
+
+ @retval EFI_SUCCESS Section entry string value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetStringFromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT CHAR8 **EntryValue
+ );
+
+/**
+ Get section entry GUID value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param Guid Point to the got GUID value.
+
+ @retval EFI_SUCCESS Section entry GUID value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetGuidFromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT EFI_GUID *Guid
+ );
+
+/**
+ Get section entry UINTN value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param Data Point to the got UINTN value.
+
+ @retval EFI_SUCCESS Section entry UINTN value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetDecimalUintnFromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT UINTN *Data
+ );
+
+/**
+ Get section entry heximal UINTN value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param Data Point to the got heximal UINTN value.
+
+ @retval EFI_SUCCESS Section entry heximal UINTN value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetHexUintnFromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT UINTN *Data
+ );
+
+/**
+ Get section entry heximal UINT64 value.
+
+ @param Context INI Config file context.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param Data Point to the got heximal UINT64 value.
+
+ @retval EFI_SUCCESS Section entry heximal UINT64 value is got.
+ @retval EFI_NOT_FOUND Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetHexUint64FromDataFile(
+ IN VOID *Context,
+ IN CHAR8 *SectionName,
+ IN CHAR8 *EntryName,
+ OUT UINT64 *Data
+ );
+
+/**
+ Close an INI config file and free the context.
+
+ @param Context INI Config file context.
+**/
+VOID
+EFIAPI
+CloseDataFile(
+ IN VOID *Context
+ );
+
+#endif
+
--
2.7.4.windows.1


[PATCH 03/45] MdeModulePkg/Include: Add FmpAuthenticationLib header.

Yao, Jiewen
 

This library is used to authenticate a UEFI defined FMP Capsule.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Include/Library/FmpAuthenticationLib.h | 91 ++++++++++++++++++++
1 file changed, 91 insertions(+)

diff --git a/MdeModulePkg/Include/Library/FmpAuthenticationLib.h b/MdeModulePkg/Include/Library/FmpAuthenticationLib.h
new file mode 100644
index 0000000..895698e
--- /dev/null
+++ b/MdeModulePkg/Include/Library/FmpAuthenticationLib.h
@@ -0,0 +1,91 @@
+/** @file
+ FMP capsule authenitcation Library.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __FMP_AUTHENTICATION_LIB_H__
+#define __FMP_AUTHENTICATION_LIB_H__
+
+/**
+ The handler is used to do the authentication for FMP capsule based upon
+ EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+
+ Caution: This function may receive untrusted input.
+
+ @param[in] Image Points to the new FMP authentication image,
+ start from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[in] ImageSize Size of the authentication image in bytes.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded
+ in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+ @retval RETURN_SUCCESS Authentication pass.
+ @retval RETURN_SECURITY_VIOLATION Authentication fail.
+ The detail reson is recorded in LastAttemptStatus.
+**/
+typedef
+RETURN_STATUS
+(EFIAPI *FMP_AUTHENTICATION_HANDLER) (
+ IN VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *LastAttemptStatus
+ );
+
+/**
+ Register FMP authentication handler with CertType.
+
+ If CertType is NULL, then ASSERT().
+ If FmpAuthenticationHandler is NULL, then ASSERT().
+
+ @param[in] CertType The certificate type associated with the FMP auth handler.
+ @param[in] FmpAuthenticationHandler The FMP authentication handler to be registered.
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to register the handlers.
+**/
+RETURN_STATUS
+EFIAPI
+RegisterFmpAuthenticationHandler(
+ IN GUID *CertType,
+ IN FMP_AUTHENTICATION_HANDLER FmpAuthenticationHandler
+ );
+
+/**
+ Execute FMP authentication handlers.
+
+ Caution: This function may receive untrusted input.
+
+ If Image is NULL, then ASSERT().
+ If ImageSize is 0, then ASSERT().
+ If LastAttemptStatus is NULL, then ASSERT().
+
+ @param[in] Image Points to the new FMP authentication image,
+ start from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[in] ImageSize Size of the authentication image in bytes.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded
+ in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+ @retval RETURN_SUCCESS Authentication pass.
+ @retval RETURN_SECURITY_VIOLATION Authentication fail.
+ The detail reson is recorded in LastAttemptStatus.
+ @retval RETURN_UNSUPPORTED No Authentication handler associated with CertType.
+**/
+RETURN_STATUS
+EFIAPI
+ExecuteFmpAuthenticationHandler(
+ IN VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *LastAttemptStatus
+ );
+
+#endif
+
--
2.7.4.windows.1


[PATCH 02/45] MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.

Yao, Jiewen
 

This library is used to abstract the action for EDKII system FMP capsule,
such as extracting a component from capsule, or authenticate the capsule.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h | 152 ++++++++++++++++++++
1 file changed, 152 insertions(+)

diff --git a/MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h b/MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
new file mode 100644
index 0000000..77d582b
--- /dev/null
+++ b/MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
@@ -0,0 +1,152 @@
+/** @file
+ EDKII System Capsule library.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __EDKII_SYSTEM_CAPSULE_LIB_H__
+#define __EDKII_SYSTEM_CAPSULE_LIB_H__
+
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+/**
+ Extract ImageFmpInfo from system firmware.
+
+ @param[in] BiosImage The BIOS image.
+ @param[in] BiosImageSize The size of the BIOS image in bytes.
+ @param[out] ImageFmpInfo The ImageFmpInfo.
+ @param[out] ImageFmpInfoSize The size of the ImageFmpInfo in bytes.
+
+ @retval TRUE The ImageFmpInfo is extracted.
+ @retval FALSE The ImageFmpInfo is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractSystemFirmwareImageFmpInfo(
+ IN VOID *BiosImage,
+ IN UINTN BiosImageSize,
+ OUT EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR **ImageFmpInfo,
+ OUT UINTN *ImageFmpInfoSize
+ );
+
+/**
+ Extract the driver FV from an authenticated image.
+
+ @param[in] AuthenticatedImage The authenticated capsule image.
+ @param[in] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+ @param[out] DriverFvImage The driver FV image.
+ @param[out] DriverFvImageSize The size of the driver FV image in bytes.
+
+ @retval TRUE The driver Fv is extracted.
+ @retval FALSE The driver Fv is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractDriverFvImage(
+ IN VOID *AuthenticatedImage,
+ IN UINTN AuthenticatedImageSize,
+ OUT VOID **DriverFvImage,
+ OUT UINTN *DriverFvImageSize
+ );
+
+/**
+ Extract the config image from an authenticated image.
+
+ @param[in] AuthenticatedImage The authenticated capsule image.
+ @param[in] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+ @param[out] ConfigImage The config image.
+ @param[out] ConfigImageSize The size of the config image in bytes.
+
+ @retval TRUE The config image is extracted.
+ @retval FALSE The config image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractConfigImage(
+ IN VOID *AuthenticatedImage,
+ IN UINTN AuthenticatedImageSize,
+ OUT VOID **ConfigImage,
+ OUT UINTN *ConfigImageSize
+ );
+
+/**
+ Extract the BIOS image from an authenticated image.
+
+ @param[in] AuthenticatedImage The authenticated capsule image.
+ @param[in] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+ @param[out] BiosImage The BIOS image.
+ @param[out] BiosImageSize The size of the BIOS image in bytes.
+
+ @retval TRUE The BIOS image is extracted.
+ @retval FALSE The BIOS image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractSystemFirmwareImage(
+ IN VOID *AuthenticatedImage,
+ IN UINTN AuthenticatedImageSize,
+ OUT VOID **BiosImage,
+ OUT UINTN *BiosImageSize
+ );
+
+/**
+ Extract the authenticated image from an FMP capsule image.
+
+ @param[in] Image The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[in] ImageSize The size of FMP capsule image in bytes.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] AuthenticatedImage The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[out] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+
+ @retval TRUE The authenticated image is extracted.
+ @retval FALSE The authenticated image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractAuthenticatedImage(
+ IN VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *LastAttemptStatus,
+ OUT VOID **AuthenticatedImage,
+ OUT UINTN *AuthenticatedImageSize
+ );
+
+/**
+ Authenticated system firmware FMP capsule image.
+
+ @param[in] Image The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[in] ImageSize The size of FMP capsule image in bytes.
+ @param[in] ForceVersionMatch TRUE: The version of capsule must be as same as the version of current image.
+ FALSE: The version of capsule must be as same as greater than the lowest
+ supported version of current image.
+ @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] AuthenticatedImage The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+ @param[out] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
+
+ @retval TRUE Authentication passes and the authenticated image is extracted.
+ @retval FALSE Authentication fails and the authenticated image is not extracted.
+**/
+EFI_STATUS
+EFIAPI
+CapsuleAuthenticateSystemFirmware(
+ IN VOID *Image,
+ IN UINTN ImageSize,
+ IN BOOLEAN ForceVersionMatch,
+ OUT UINT32 *LastAttemptVersion,
+ OUT UINT32 *LastAttemptStatus,
+ OUT VOID **AuthenticatedImage,
+ OUT UINTN *AuthenticatedImageSize
+ );
+
+#endif
+
--
2.7.4.windows.1


[PATCH 01/45] MdeModulePkg/Include: Add EDKII system FMP capsule header.

Yao, Jiewen
 

Add EDKII system FMP capsule header file.
This describes the EDKII system FMP capsule format.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Cc: Jeff Fan <jeff.fan@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>
---
MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h | 110 ++++++++++++++++++++
1 file changed, 110 insertions(+)

diff --git a/MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h b/MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
new file mode 100644
index 0000000..9f609c1
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
@@ -0,0 +1,110 @@
+/** @file
+ Guid & data structure used for Delivering Capsules Containing Updates to
+ EDKII System Firmware Management Protocol
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __EDKII_SYSTEM_FMP_CAPSULE_GUID_H__
+#define __EDKII_SYSTEM_FMP_CAPSULE_GUID_H__
+
+/**
+
+ Capsule Layout is below:
+ +------------------------------------------+
+ | Capsule Header (OPTIONAL, WFU) | <== ESRT.FwClass (Optional)
+ +------------------------------------------+
+ | FMP Capsule Header | <== EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID
+ +------------------------------------------+
+ | FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER | <== PcdEdkiiSystemFmpCapsuleImageTypeIdGuid
+ +------------------------------------------+
+ | EFI_FIRMWARE_IMAGE_AUTHENTICATION |
+ +------------------------------------------+
+ | FMP Payload |
+ +------------------------------------------+
+
+ System FMP Payload is below:
+ +------------------------------------------+
+ | EFI_FIRMWARE_VOLUME |
+ | +------------------------------------+ |
+ | | FFS (Configure File) | | <== gEdkiiSystemFmpCapsuleConfigFileGuid
+ | +------------------------------------+ |
+ | | FFS (Driver FV) | | <== gEdkiiSystemFmpCapsuleDriverFvFileGuid
+ | +------------------------------------+ |
+ | | FFS (BIOS Image) | | <== PcdEdkiiSystemFirmwareFileGuid
+ | | +------------------------------+ | |
+ | | | FV Recovery | | |
+ | | |------------------------------| | |
+ | | | Fv Main | | |
+ | | +------------------------------+ | |
+ | +------------------------------------+ |
+ +------------------------------------------+
+
+**/
+
+#define EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE SIGNATURE_32('S', 'F', 'I', 'D')
+
+#pragma pack(1)
+typedef struct {
+ UINT32 Signature;
+ UINT32 HeaderLength; // Length of EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR, excluding NameString
+ UINT32 Length; // Length of the data structure, including NameString
+ // Below structure is similar as UEFI EFI_FIRMWARE_MANAGEMENT_PROTOCOL.GetPackageInfo()
+ UINT32 PackageVersion;
+ UINT32 PackageVersionNameStringOffset; // Offset from head, CHAR16 string including NULL terminate char
+ // Below structure is similar as UEFI EFI_FIRMWARE_IMAGE_DESCRIPTOR
+ UINT8 ImageIndex;
+ UINT8 Reserved[3];
+ EFI_GUID ImageTypeId;
+ UINT64 ImageId;
+ UINT32 ImageIdNameStringOffset; // Offset from head, CHAR16 string including NULL terminate char
+ UINT32 Version;
+ UINT32 VersionNameStringOffset; // Offset from head, CHAR16 string including NULL terminate char
+ UINT8 Reserved2[4];
+ UINT64 Size;
+ UINT64 AttributesSupported;
+ UINT64 AttributesSetting;
+ UINT64 Compatibilities;
+ UINT32 LowestSupportedImageVersion;
+ UINT32 LastAttemptVersion;
+ UINT32 LastAttemptStatus;
+ UINT8 Reserved3[4];
+ UINT64 HardwareInstance;
+ // real string data
+//CHAR16 ImageIdNameStr[]; // CHAR16 string including NULL terminate char
+//CHAR16 VersionNameStr[]; // CHAR16 string including NULL terminate char
+//CHAR16 PackageVersionNameStr[]; // CHAR16 string including NULL terminate char
+} EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR;
+#pragma pack()
+
+/**
+ System Firmware Image Descriptor is below:
+ +----------------------+
+ | BIOS (BIOS.FV) |
+ |+--------------------+|
+ || FFS (Freeform) || <== gEdkiiSystemFirmwareImageDescriptorFileGuid
+ ||+------------------+||
+ ||| SECTION (RAW) |||
+ ||| System Firmware |||
+ ||| Image Descriptor |||
+ ||+------------------+||
+ |+--------------------+|
+ | |
+ | |
+ +----------------------+
+**/
+
+extern EFI_GUID gEdkiiSystemFirmwareImageDescriptorFileGuid;
+extern EFI_GUID gEdkiiSystemFmpCapsuleConfigFileGuid;
+extern EFI_GUID gEdkiiSystemFmpCapsuleDriverFvFileGuid;
+
+#endif
--
2.7.4.windows.1


[PATCH 00/45] Add capsule update and recovery sample.

Yao, Jiewen
 

This series patch provides sample on how to do signed capsule update
and recovery in EDKII.

This series patch is also checked into git@...:jyao1/edk2.git.

The feature includes:
1) Define EDKII signed system BIOS capsule format.
2) Provide EDKII signed system BIOS update sample.
3) Provide EDKII signed recovery sample.
4) Provide Microcode update sample for X86 system.
5) Update Quark to use new capsule/recovery solution.
6) Update Vlv2(MinnowMax) to use new capsule/recovery solution.

The signed capsule/recovery solution is in MdeModulePkg.
The capsule in IntelFrameworkModulePkg is deprecated.
The Microcode update solution is in UefiCpuPkg.

Cc: Feng Tian <feng.tian@...>
Cc: Star Zeng <star.zeng@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Liming Gao <liming.gao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Cc: Jeff Fan <jeff.fan@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@...>


Jiewen Yao (45):
MdeModulePkg/Include: Add EDKII system FMP capsule header.
MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
MdeModulePkg/Include: Add FmpAuthenticationLib header.
MdeModulePkg/Include: Add IniParsingLib header.
MdeModulePkg/Include: Add PlatformFlashAccessLib header.
MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance.
MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib
instance.
MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib.
MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
MdeModulePkg/CapsuleApp: Add CapsuleApp application.
MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules()
interface.
SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for FMP.
SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
UefiCpuPkg/Include: Add Microcode FMP definition.
UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule
update.
QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule
update.
QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling.
QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule
update.
Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule
update.
Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.
Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
Vlv2TbltDevicePkg/bat: add capsule generation in bat.

IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c | 39 +-
MdeModulePkg/Application/CapsuleApp/AppSupport.c | 480 ++++++
MdeModulePkg/Application/CapsuleApp/CapsuleApp.c | 1047 +++++++++++++
MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf | 71 +
MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni | 22 +
MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni | 19 +
MdeModulePkg/Application/CapsuleApp/CapsuleDump.c | 840 +++++++++++
MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h | 110 ++
MdeModulePkg/Include/Library/CapsuleLib.h | 45 +-
MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h | 152 ++
MdeModulePkg/Include/Library/FmpAuthenticationLib.h | 91 ++
MdeModulePkg/Include/Library/IniParsingLib.h | 153 ++
MdeModulePkg/Include/Library/PlatformFlashAccessLib.h | 59 +
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c | 1538 ++++++++++++++++++++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf | 82 ++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni | 22 +
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c | 517 +++++++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c | 447 ++++++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c | 112 ++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf | 85 ++
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni | 22 +
MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c | 47 +-
MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c | 609 ++++++++
MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf | 55 +
MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni | 22 +
MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c | 274 ++++
MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf | 47 +
MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni | 22 +
MdeModulePkg/Library/IniParsingLib/IniParsingLib.c | 1053 ++++++++++++++
MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf | 42 +
MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni | 22 +
MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c | 54 +
MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf | 40 +
MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni | 21 +
MdeModulePkg/MdeModulePkg.dec | 106 ++
MdeModulePkg/MdeModulePkg.dsc | 24 +
MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf | 3 +-
MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c | 37 +-
MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c | 158 ++
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c | 746 ++++++++++
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h | 44 +
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf | 71 +
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni | 21 +
MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni | 20 +
MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c | 219 +++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h | 393 +++++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c | 484 ++++++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c | 453 ++++++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c | 90 ++
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf | 66 +
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni | 21 +
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni | 20 +
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf | 70 +
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni | 21 +
MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni | 20 +
QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c | 200 +++
QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf | 52 +
QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c | 336 +++++
QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h | 186 +++
QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc | 88 ++
QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf | 45 +
QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c | 66 +
QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini | 62 +
QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c | 95 +-
QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h | 8 +-
QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf | 8 +-
QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c | 3 +-
QuarkPlatformPkg/Quark.dsc | 61 +-
QuarkPlatformPkg/Quark.fdf | 53 +
QuarkPlatformPkg/QuarkCapsule.dsc | 44 +
QuarkPlatformPkg/QuarkCapsule.fdf | 82 ++
QuarkPlatformPkg/QuarkMin.dsc | 7 +-
SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c | 144 ++
SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf | 52 +
SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni | 26 +
SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.c | 286 ++++
SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf | 53 +
SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.uni | 26 +
SecurityPkg/SecurityPkg.dec | 6 +
SecurityPkg/SecurityPkg.dsc | 3 +
UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c | 480 ++++++
UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c | 283 ++++
UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf | 62 +
UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni | 22 +
UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni | 19 +
UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c | 171 +++
UefiCpuPkg/Include/Guid/MicrocodeFmp.h | 21 +
UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h | 39 +
UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c | 42 +
UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf | 40 +
UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni | 21 +
UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c | 641 ++++++++
UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c | 775 ++++++++++
UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h | 299 ++++
UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf | 68 +
UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni | 21 +
UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni | 20 +
UefiCpuPkg/UefiCpuPkg.dec | 7 +
UefiCpuPkg/UefiCpuPkg.dsc | 3 +
Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c | 192 +++
Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf | 47 +
Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc | 86 ++
Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf | 45 +
Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c | 66 +
Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini | 72 +
Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini | 72 +
Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c | 156 +-
Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf | 8 +-
Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c | 62 +
Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf | 49 +
Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c | 188 +++
Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h | 5 +-
Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c | 117 +-
Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf | 2 +
Vlv2TbltDevicePkg/PlatformCapsule.dsc | 44 +
Vlv2TbltDevicePkg/PlatformCapsule.fdf | 81 ++
Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf | 81 ++
Vlv2TbltDevicePkg/PlatformPkg.fdf | 132 +-
Vlv2TbltDevicePkg/PlatformPkgConfig.dsc | 3 +-
Vlv2TbltDevicePkg/PlatformPkgGcc.fdf | 132 +-
Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc | 70 +-
Vlv2TbltDevicePkg/PlatformPkgIA32.dsc | 70 +-
Vlv2TbltDevicePkg/PlatformPkgX64.dsc | 70 +-
Vlv2TbltDevicePkg/bld_vlv.bat | 8 +-
124 files changed, 17848 insertions(+), 384 deletions(-)
create mode 100644 MdeModulePkg/Application/CapsuleApp/AppSupport.c
create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
create mode 100644 MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
create mode 100644 MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
create mode 100644 MdeModulePkg/Include/Library/FmpAuthenticationLib.h
create mode 100644 MdeModulePkg/Include/Library/IniParsingLib.h
create mode 100644 MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
create mode 100644 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
create mode 100644 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
create mode 100644 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
create mode 100644 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
create mode 100644 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
create mode 100644 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
create mode 100644 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
create mode 100644 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
create mode 100644 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
create mode 100644 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c
create mode 100644 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf
create mode 100644 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c
create mode 100644 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h
create mode 100644 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
create mode 100644 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
create mode 100644 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
create mode 100644 QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
create mode 100644 QuarkPlatformPkg/QuarkCapsule.dsc
create mode 100644 QuarkPlatformPkg/QuarkCapsule.fdf
create mode 100644 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c
create mode 100644 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
create mode 100644 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni
create mode 100644 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.c
create mode 100644 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
create mode 100644 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.uni
create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
create mode 100644 UefiCpuPkg/Include/Guid/MicrocodeFmp.h
create mode 100644 UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
create mode 100644 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c
create mode 100644 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
create mode 100644 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni
create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini
create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.dsc
create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.fdf
create mode 100644 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf

--
2.7.4.windows.1