From: "Chang, Abner via groups.io" <abner.chang=amd.com@groups.io>
To: "Zhai, MingXin (Duke)" <duke.zhai@amd.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Xing, Eric" <Eric.Xing@amd.com>, "Fu, Igniculus" <Igniculus.Fu@amd.com>
Subject: Re: [edk2-devel] [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule
Date: Fri, 26 Jan 2024 09:28:58 +0000 [thread overview]
Message-ID: <LV8PR12MB9452E17AC63DC9B0E7C810F3EA792@LV8PR12MB9452.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20240126060050.1725-22-duke.zhai@amd.com>
[AMD Official Use Only - General]
> -----Original Message-----
> From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> Sent: Friday, January 26, 2024 2:01 PM
> To: devel@edk2.groups.io
> Cc: Xing, Eric <Eric.Xing@amd.com>; Zhai, MingXin (Duke)
> <duke.zhai@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>; Chang,
> Abner <Abner.Chang@amd.com>
> Subject: [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule
>
> From: Duke Zhai <Duke.Zhai@amd.com>
>
> BZ #:4640
> In V2: Improve coding style.
> 1.Remove the leading underscore and use double underscore at trailing in C
> header files.
> 2.Remove old tianocore licenses and redundant license description.
> 3.Improve coding style. For example: remove space between @param.
>
> In V1:
> Initial SignedCapsule module for Signed Capsule.
> Produce FMP instance to update system firmware.
>
> Signed-off-by: Ken Yao <ken.yao@amd.com>
> Cc: Eric Xing <eric.xing@amd.com>
> Cc: Duke Zhai <duke.zhai@amd.com>
> Cc: Igniculus Fu <igniculus.fu@amd.com>
> Cc: Abner Chang <abner.chang@amd.com>
> ---
> .../BaseTools/Source/Python/GenFds/Capsule.py | 253 +++
> .../SystemFirmwareUpdate/ParseConfigProfile.c | 231 +++
> .../SystemFirmwareCommonDxe.c | 371 +++++
> .../SystemFirmwareUpdate/SystemFirmwareDxe.h | 421 +++++
> .../SystemFirmwareUpdateDxe.c | 1426 +++++++++++++++++
> .../SystemFirmwareUpdateDxe.inf | 91 ++
> .../SystemFirmwareUpdateDxe.uni | 15 +
> .../SystemFirmwareUpdateDxeExtra.uni | 15 +
> 8 files changed, 2823 insertions(+)
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/Ge
> nFds/Capsule.py
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/ParseConfigProfile.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareCommonDxe.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareDxe.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
>
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/G
> enFds/Capsule.py
> b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/G
> enFds/Capsule.py
> new file mode 100644
> index 0000000000..0ec0b3ca43
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/G
> enFds/Capsule.py
> @@ -0,0 +1,253 @@
> +## @file
> +# generate capsule
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc.
> +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +
> +##
> +# Import Modules
> +#
> +from __future__ import absolute_import
> +from .GenFdsGlobalVariable import GenFdsGlobalVariable, FindExtendTool
> +from CommonDataClass.FdfClass import CapsuleClassObject
> +import Common.LongFilePathOs as os
> +from io import BytesIO
> +from Common.Misc import SaveFileOnChange, PackGUID
> +import uuid
> +from struct import pack
> +from Common import EdkLogger
> +from Common.BuildToolError import GENFDS_ERROR
> +from Common.DataType import TAB_LINE_BREAK
> +
> +WIN_CERT_REVISION = 0x0200
> +WIN_CERT_TYPE_EFI_GUID = 0x0EF1
> +EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID('{4aafd29d-68df-49ee-8aa9-
> 347d375665a7}')
> +EFI_CERT_TYPE_RSA2048_SHA256_GUID = uuid.UUID('{a7717414-c616-
> 4977-9420-844712a735bf}')
> +
> +## create inf file describes what goes into capsule and call GenFv to generate
> capsule
> +#
> +#
> +class Capsule (CapsuleClassObject):
> + ## The constructor
> + #
> + # @param self The object pointer
> + #
> + def __init__(self):
> + CapsuleClassObject.__init__(self)
> + # For GenFv
> + self.BlockSize = None
> + # For GenFv
> + self.BlockNum = None
> + self.CapsuleName = None
> +
> + ## Generate FMP capsule
> + #
> + # @retval string Generated Capsule file path
> + #
> + def GenFmpCapsule(self):
> + #
> + # Generate capsule header
> + # typedef struct {
> + # EFI_GUID CapsuleGuid;
> + # UINT32 HeaderSize;
> + # UINT32 Flags;
> + # UINT32 CapsuleImageSize;
> + # } EFI_CAPSULE_HEADER;
> + #
> + Header = BytesIO()
> + #
> + # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A
> + #
> + Header.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-
> 7194199AD92A'.split('-')))
> + HdrSize = 0
> + if 'CAPSULE_HEADER_SIZE' in self.TokensDict:
> + Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'],
> 16)))
> + HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)
> + else:
> + Header.write(pack('=I', 0x20))
> + HdrSize = 0x20
> + Flags = 0
> + if 'CAPSULE_FLAGS' in self.TokensDict:
> + for flag in self.TokensDict['CAPSULE_FLAGS'].split(','):
> + flag = flag.strip()
> + if flag == 'PopulateSystemTable':
> + Flags |= 0x00010000 | 0x00020000
> + elif flag == 'PersistAcrossReset':
> + Flags |= 0x00010000
> + elif flag == 'InitiateReset':
> + Flags |= 0x00040000
> + if 'OEM_CAPSULE_FLAGS' in self.TokensDict:
> + Flags |= int(self.TokensDict['OEM_CAPSULE_FLAGS'],16)
> + Header.write(pack('=I', Flags))
> + #
> + # typedef struct {
> + # UINT32 Version;
> + # UINT16 EmbeddedDriverCount;
> + # UINT16 PayloadItemCount;
> + # // UINT64 ItemOffsetList[];
> + # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
> + #
> + FwMgrHdr = BytesIO()
> + if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict:
> + FwMgrHdr.write(pack('=I',
> int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16)))
> + else:
> + FwMgrHdr.write(pack('=I', 0x00000001))
> + FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList),
> len(self.FmpPayloadList)))
> + FwMgrHdrSize =
> 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))
> +
> + #
> + # typedef struct _WIN_CERTIFICATE {
> + # UINT32 dwLength;
> + # UINT16 wRevision;
> + # UINT16 wCertificateType;
> + # //UINT8 bCertificate[ANYSIZE_ARRAY];
> + # } WIN_CERTIFICATE;
> + #
> + # typedef struct _WIN_CERTIFICATE_UEFI_GUID {
> + # WIN_CERTIFICATE Hdr;
> + # EFI_GUID CertType;
> + # //UINT8 CertData[ANYSIZE_ARRAY];
> + # } WIN_CERTIFICATE_UEFI_GUID;
> + #
> + # typedef struct {
> + # UINT64 MonotonicCount;
> + # WIN_CERTIFICATE_UEFI_GUID AuthInfo;
> + # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
> + #
> + # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
> + # EFI_GUID HashType;
> + # UINT8 PublicKey[256];
> + # UINT8 Signature[256];
> + # } EFI_CERT_BLOCK_RSA_2048_SHA256;
> + #
> +
> + PreSize = FwMgrHdrSize
> + Content = BytesIO()
> + for driver in self.CapsuleDataList:
> + FileName = driver.GenCapsuleSubItem()
> + FwMgrHdr.write(pack('=Q', PreSize))
> + PreSize += os.path.getsize(FileName)
> + File = open(FileName, 'rb')
> + Content.write(File.read())
> + File.close()
> + for fmp in self.FmpPayloadList:
> + if fmp.Existed:
> + FwMgrHdr.write(pack('=Q', PreSize))
> + PreSize += len(fmp.Buffer)
> + Content.write(fmp.Buffer)
> + continue
> + if fmp.ImageFile:
> + for Obj in fmp.ImageFile:
> + fmp.ImageFile = Obj.GenCapsuleSubItem()
> + if fmp.VendorCodeFile:
> + for Obj in fmp.VendorCodeFile:
> + fmp.VendorCodeFile = Obj.GenCapsuleSubItem()
> + if fmp.Certificate_Guid:
> + ExternalTool, ExternalOption = FindExtendTool([],
> GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid)
> + CmdOption = ''
> + CapInputFile = fmp.ImageFile
> + if not os.path.isabs(fmp.ImageFile):
> + CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir,
> fmp.ImageFile)
> + CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir,
> self.UiCapsuleName) + '.tmp'
> + if ExternalTool is None:
> + EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with
> GUID %s" % fmp.Certificate_Guid)
> + else:
> + CmdOption += ExternalTool
> + if ExternalOption:
> + CmdOption = CmdOption + ' ' + ExternalOption
> + CmdOption += ' -e ' + ' --monotonic-count ' +
> str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile
> + CmdList = CmdOption.split()
> + GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate
> FMP auth capsule")
> + if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID:
> + dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) -
> os.path.getsize(CapInputFile)
> + else:
> + dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256
> + fmp.ImageFile = CapOutputTmp
> + AuthData = [fmp.MonotonicCount, dwLength,
> WIN_CERT_REVISION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid]
> + fmp.Buffer = fmp.GenCapsuleSubItem(AuthData)
> + else:
> + fmp.Buffer = fmp.GenCapsuleSubItem()
> + FwMgrHdr.write(pack('=Q', PreSize))
> + PreSize += len(fmp.Buffer)
> + Content.write(fmp.Buffer)
> + BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())
> + Header.write(pack('=I', HdrSize + BodySize))
> + #
> + # The real capsule header structure is 28 bytes
> + #
> + Header.write(b'\x00'*(HdrSize-28))
> + Header.write(FwMgrHdr.getvalue())
> + Header.write(Content.getvalue())
> + #
> + # Generate FMP capsule file
> + #
> + CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir,
> self.UiCapsuleName) + '.Cap'
> + SaveFileOnChange(CapOutputFile, Header.getvalue(), True)
> + return CapOutputFile
> +
> + ## Generate capsule
> + #
> + # @param self The object pointer
> + # @retval string Generated Capsule file path
> + #
> + def GenCapsule(self):
> + if self.UiCapsuleName.upper() + 'cap' in
> GenFdsGlobalVariable.ImageBinDict:
> + return
> GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap']
> +
> + GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule"
> %self.UiCapsuleName)
> + if ('CAPSULE_GUID' in self.TokensDict and
> + uuid.UUID(self.TokensDict['CAPSULE_GUID']) ==
> uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):
> + return self.GenFmpCapsule()
> +
> + CapInfFile = self.GenCapInf()
> + CapInfFile.append("[files]" + TAB_LINE_BREAK)
> + CapFileList = []
> + for CapsuleDataObj in self.CapsuleDataList:
> + CapsuleDataObj.CapsuleName = self.CapsuleName
> + FileName = CapsuleDataObj.GenCapsuleSubItem()
> + CapsuleDataObj.CapsuleName = None
> + CapFileList.append(FileName)
> + CapInfFile.append("EFI_FILE_NAME = " + \
> + FileName + \
> + TAB_LINE_BREAK)
> + SaveFileOnChange(self.CapInfFileName, ''.join(CapInfFile), False)
> + #
> + # Call GenFv tool to generate capsule
> + #
> + CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir,
> self.UiCapsuleName)
> + CapOutputFile = CapOutputFile + '.Cap'
> + GenFdsGlobalVariable.GenerateFirmwareVolume(
> + CapOutputFile,
> + [self.CapInfFileName],
> + Capsule=True,
> + FfsList=CapFileList
> + )
> +
> + GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule
> Successfully" %self.UiCapsuleName)
> + GenFdsGlobalVariable.SharpCounter = 0
> + GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap']
> = CapOutputFile
> + return CapOutputFile
> +
> + ## Generate inf file for capsule
> + #
> + # @param self The object pointer
> + # @retval file inf file object
> + #
> + def GenCapInf(self):
> + self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir,
> + self.UiCapsuleName + "_Cap" + '.inf')
> + CapInfFile = []
> +
> + CapInfFile.append("[options]" + TAB_LINE_BREAK)
> +
> + for Item in self.TokensDict:
> + CapInfFile.append("EFI_" + \
> + Item + \
> + ' = ' + \
> + self.TokensDict[Item] + \
> + TAB_LINE_BREAK)
> +
> + return CapInfFile
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal
> /SystemFirmwareUpdate/ParseConfigProfile.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/ParseConfigProfile.c
> new file mode 100644
> index 0000000000..b57586a267
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/ParseConfigProfile.c
> @@ -0,0 +1,231 @@
> +/** @file
> + Implements ParseConfigProfile.c
> +
> + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
Please put AMD copy right under Intel's.
Thanks
Abner
> +
> +/** @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 - 2017, 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 "SystemFirmwareDxe.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[in] DataBuffer Config raw file buffer.
> + @param[in] BufferSize Size of raw buffer.
> + @param[in, out] ConfigHeader Pointer to the config header.
> + @param[in, out] 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 = OpenIniFile (DataBuffer, BufferSize);
> + if (Context == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Now get NumOfUpdate
> + //
> + Status = GetDecimalUintnFromDataFile (
> + Context,
> + "Head",
> + "NumOfUpdate",
> + &Num
> + );
> + if (EFI_ERROR (Status) || (Num == 0)) {
> + DEBUG ((DEBUG_ERROR, "NumOfUpdate not found\n"));
> + CloseIniFile (Context);
> + return EFI_NOT_FOUND;
> + }
> +
> + ConfigHeader->NumOfUpdates = Num;
> + *UpdateArray = AllocateZeroPool ((sizeof (UPDATE_CONFIG_DATA) *
> Num));
> + if (*UpdateArray == NULL) {
> + CloseIniFile (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");
> + AsciiValueToStringS (
> + Entry + AsciiStrnLenS (Entry, MAX_LINE_LENGTH),
> + MAX_LINE_LENGTH - AsciiStrnLenS (Entry, MAX_LINE_LENGTH),
> + 0,
> + Index,
> + 0
> + );
> + Status = GetStringFromDataFile (
> + Context,
> + "Head",
> + Entry,
> + &SectionName
> + );
> + if (EFI_ERROR (Status) || (SectionName == NULL)) {
> + DEBUG ((DEBUG_ERROR, "[%d] %a not found\n", Index, Entry));
> + CloseIniFile (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;
> +
> + //
> + // FirmwareType
> + //
> + Status = GetDecimalUintnFromDataFile (
> + Context,
> + SectionName,
> + "FirmwareType",
> + &Num
> + );
> + if (EFI_ERROR (Status)) {
> + CloseIniFile (Context);
> + DEBUG ((DEBUG_ERROR, "[%d] FirmwareType not found\n", Index));
> + return EFI_NOT_FOUND;
> + }
> +
> + (*UpdateArray)[Index].FirmwareType =
> (PLATFORM_FIRMWARE_TYPE)Num;
> +
> + //
> + // AddressType
> + //
> + Status = GetDecimalUintnFromDataFile (
> + Context,
> + SectionName,
> + "AddressType",
> + &Num
> + );
> + if (EFI_ERROR (Status)) {
> + CloseIniFile (Context);
> + DEBUG ((DEBUG_ERROR, "[%d] AddressType not found\n", Index));
> + return EFI_NOT_FOUND;
> + }
> +
> + (*UpdateArray)[Index].AddressType = (FLASH_ADDRESS_TYPE)Num;
> +
> + //
> + // BaseAddress
> + //
> + Status = GetHexUint64FromDataFile (
> + Context,
> + SectionName,
> + "BaseAddress",
> + &Num64
> + );
> + if (EFI_ERROR (Status)) {
> + CloseIniFile (Context);
> + DEBUG ((DEBUG_ERROR, "[%d] BaseAddress not found\n", Index));
> + return EFI_NOT_FOUND;
> + }
> +
> + (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS)Num64;
> +
> + //
> + // FileBuid
> + //
> + Status = GetGuidFromDataFile (
> + Context,
> + SectionName,
> + "FileGuid",
> + &FileGuid
> + );
> + if (EFI_ERROR (Status)) {
> + CloseIniFile (Context);
> + DEBUG ((DEBUG_ERROR, "[%d] FileGuid not found\n", Index));
> + return EFI_NOT_FOUND;
> + }
> +
> + CopyGuid (&((*UpdateArray)[Index].FileGuid), &FileGuid);
> +
> + //
> + // Length
> + //
> + Status = GetHexUintnFromDataFile (
> + Context,
> + SectionName,
> + "Length",
> + &Num
> + );
> + if (EFI_ERROR (Status)) {
> + CloseIniFile (Context);
> + DEBUG ((DEBUG_ERROR, "[%d] Length not found\n", Index));
> + return EFI_NOT_FOUND;
> + }
> +
> + (*UpdateArray)[Index].Length = (UINTN)Num;
> +
> + //
> + // ImageOffset
> + //
> + Status = GetHexUintnFromDataFile (
> + Context,
> + SectionName,
> + "ImageOffset",
> + &Num
> + );
> + if (EFI_ERROR (Status)) {
> + CloseIniFile (Context);
> + DEBUG ((DEBUG_ERROR, "[%d] ImageOffset not found\n", Index));
> + return EFI_NOT_FOUND;
> + }
> +
> + (*UpdateArray)[Index].ImageOffset = (UINTN)Num;
> + }
> +
> + //
> + // Now all configuration data got. Free those temporary buffers
> + //
> + CloseIniFile (Context);
> +
> + return EFI_SUCCESS;
> +}
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal
> /SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
> new file mode 100644
> index 0000000000..05a36162d3
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
> @@ -0,0 +1,371 @@
> +/** @file
> + Produce FMP instance for system firmware.
> +
> + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "SystemFirmwareDxe.h"
> +
> +EFI_GUID gSystemFmpLastAttemptVariableGuid =
> SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID;
> +EFI_GUID gSystemFmpProtocolGuid =
> SYSTEM_FMP_PROTOCOL_GUID;
> +
> +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
> + )
> +{
> + SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate;
> + EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
> +
> + SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP (This);
> +
> + if (ImageInfoSize == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (*ImageInfoSize < sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR) *
> SystemFmpPrivate->DescriptorCount) {
> + *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR) *
> SystemFmpPrivate->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) *
> SystemFmpPrivate->DescriptorCount;
> + *DescriptorSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
> + *DescriptorCount = SystemFmpPrivate->DescriptorCount;
> + *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
> +
> + //
> + // supports 1 ImageInfo descriptor
> + //
> + ImageDescriptor = SystemFmpPrivate->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 = SystemFmpPrivate-
> >LastAttempt.LastAttemptVersion;
> + ImageInfo->LastAttemptStatus = SystemFmpPrivate-
> >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_VIOLATION 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
> + )
> +{
> + 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_VIOLATION 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_VIOLATION 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 SystemFmpDriver private data structure.
> +
> + @param[in] SystemFmpPrivate private data structure to be initialized.
> +
> + @return EFI_SUCCESS private data is initialized.
> +**/
> +EFI_STATUS
> +InitializePrivateData (
> + IN SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate
> + )
> +{
> + EFI_STATUS VarStatus;
> + UINTN VarSize;
> +
> + SystemFmpPrivate->Signature =
> SYSTEM_FMP_PRIVATE_DATA_SIGNATURE;
> + SystemFmpPrivate->Handle = NULL;
> + SystemFmpPrivate->DescriptorCount = 1;
> + CopyMem (&SystemFmpPrivate->Fmp, &mFirmwareManagementProtocol,
> sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
> +
> + SystemFmpPrivate->ImageDescriptor = PcdGetPtr
> (PcdEdkiiSystemFirmwareImageDescriptor);
> +
> + SystemFmpPrivate->LastAttempt.LastAttemptVersion = 0x0;
> + SystemFmpPrivate->LastAttempt.LastAttemptStatus = 0x0;
> + VarSize = sizeof (SystemFmpPrivate->LastAttempt);
> + VarStatus = gRT->GetVariable (
> +
> SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
> + &gSystemFmpLastAttemptVariableGuid,
> + NULL,
> + &VarSize,
> + &SystemFmpPrivate->LastAttempt
> + );
> + DEBUG ((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
> + DEBUG ((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n",
> SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate-
> >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 (PcdSystemFmpCapsuleImageTypeIdGuid);
> + Count = PcdGetSize (PcdSystemFmpCapsuleImageTypeIdGuid) / sizeof
> (GUID);
> +
> + for (Index = 0; Index < Count; Index++, Guid++) {
> + if (CompareGuid (&FmpImageInfo->ImageTypeId, Guid)) {
> + return TRUE;
> + }
> + }
> +
> + return FALSE;
> +}
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal
> /SystemFirmwareUpdate/SystemFirmwareDxe.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareDxe.h
> new file mode 100644
> index 0000000000..b1aab4c41e
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareDxe.h
> @@ -0,0 +1,421 @@
> +/** @file
> + System Firmware update header file.
> +
> + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef SYSTEM_FIRMWARE_UPDATE_H__
> +#define SYSTEM_FIRMWARE_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/DxeServicesTableLib.h>
> +#include <Library/PlatformFlashAccessLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Library/AmdPspBaseLibV2.h>
> +#include <OtaCapsuleUpdate.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 SYSTEM_FMP_PRIVATE_DATA_SIGNATURE SIGNATURE_32('S', 'Y',
> 'S', 'F')
> +
> +#define SYSTEM_FMP_PROTOCOL_GUID {0x6d16624a, 0x26a6, 0x4cb4,
> { 0x84, 0xfa, 0x6, 0x78, 0x5a, 0x7e, 0x82, 0x6a }}
> +
> +//
> +// SYSTEM FMP private data structure.
> +//
> +
> +struct _SYSTEM_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 _SYSTEM_FMP_PRIVATE_DATA SYSTEM_FMP_PRIVATE_DATA;
> +
> +/**
> + Returns a pointer to the SYSTEM_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 SYSTEM_FMP_PRIVATE_DATA.
> +
> +**/
> +#define SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(a) \
> + CR ( \
> + (a), \
> + SYSTEM_FMP_PRIVATE_DATA, \
> + Fmp, \
> + SYSTEM_FMP_PRIVATE_DATA_SIGNATURE \
> + )
> +
> +//
> +// Update data
> +//
> +
> +typedef struct {
> + UINTN NumOfUpdates;
> +} CONFIG_HEADER;
> +
> +typedef struct {
> + UINTN Index;
> + 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;
> +
> +/*
> +Name Offset(byte) Size(byte) Comments
> +SlotA_Priority 0x0 4 Read and Write the Slot A priority
> +SlotA_UpdateRetries 0x4 4 Read and Write the Slot A retries
> +SlotA_GlitchRetries 0x8 4 Read only, Slot A glitch
> +SlotB_Priority 0xC 4 Read and Write the Slot B priority
> +SlotB_UpdateRetries 0x10 4 Read and Write the Slot B retries
> +SlotB_GlitchRetries 0x14 4 Read only, Slot B glitch
> +
> +*/
> +typedef struct {
> + UINT32 SlotA_Priority;
> + UINT32 SlotA_UpdateRetries;
> + UINT32 SlotA_GlitchRetries;
> + UINT32 SlotB_Priority;
> + UINT32 SlotB_UpdateRetries;
> + UINT32 SlotB_GlitchRetries;
> +} IMAGE_SLOT_HEADER_INFO;
> +
> +/**
> + 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_VIOLATION 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_VIOLATION 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_VIOLATION 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_VIOLATION 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
> + );
> +
> +/**
> + Initialize SystemFmpDriver private data structure.
> +
> + @param[in] SystemFmpPrivate private data structure to be initialized.
> +
> + @return EFI_SUCCESS private data is initialized.
> +**/
> +EFI_STATUS
> +InitializePrivateData (
> + IN SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate
> + );
> +
> +extern EFI_GUID gSystemFmpLastAttemptVariableGuid;
> +extern EFI_GUID mCurrentImageTypeId;
> +extern EFI_GUID gSystemFmpProtocolGuid;
> +
> +#endif
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal
> /SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
> new file mode 100644
> index 0000000000..894d363de0
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
> @@ -0,0 +1,1426 @@
> +/** @file
> + SetImage instance to update system firmware.
> +
> + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "SystemFirmwareDxe.h"
> +
> +//
> +// SystemFmp driver private data
> +//
> +SYSTEM_FMP_PRIVATE_DATA *mSystemFmpPrivate = NULL;
> +
> +EFI_GUID mCurrentImageTypeId;
> +
> +BOOLEAN mNvRamUpdated = FALSE;
> +
> +UINT8 mUpdateSlot = 0;
> +
> +/**
> + Parse Config data file to get the updated data array.
> +
> + @param[in] DataBuffer Config raw file buffer.
> + @param[in] BufferSize Size of raw buffer.
> + @param[in, out] ConfigHeader Pointer to the config header.
> + @param[in, out] 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 System Firmware image component.
> +
> + @param[in] SystemFirmwareImage Points to the System Firmware
> image.
> + @param[in] SystemFirmwareImageSize The length of the System Firmware
> 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.
> + @param[in] Progress A function used by the driver to report the
> progress of the firmware update.
> + @param[in] StartPercentage The start completion percentage value
> that may be used to report progress during the flash write operation.
> + @param[in] EndPercentage The end completion percentage value that
> may be used to report progress during the flash write operation.
> +
> + @retval EFI_SUCCESS The System Firmware image is updated.
> + @retval EFI_WRITE_PROTECTED The flash device is read only.
> +**/
> +EFI_STATUS
> +PerformUpdate (
> + IN VOID *SystemFirmwareImage,
> + IN UINTN SystemFirmwareImageSize,
> + IN UPDATE_CONFIG_DATA *ConfigData,
> + OUT UINT32 *LastAttemptVersion,
> + OUT UINT32 *LastAttemptStatus,
> + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
> + IN UINTN StartPercentage,
> + IN UINTN EndPercentage
> + )
> +{
> + EFI_STATUS Status;
> +
> + DEBUG ((DEBUG_INFO, "PlatformUpdate:"));
> + DEBUG ((DEBUG_INFO, " BaseAddress - 0x%lx,", ConfigData-
> >BaseAddress));
> + DEBUG ((DEBUG_INFO, " ImageOffset - 0x%x,", ConfigData->ImageOffset));
> + DEBUG ((DEBUG_INFO, " Legnth - 0x%x\n", ConfigData->Length));
> + if (Progress != NULL) {
> + Progress (StartPercentage);
> + }
> +
> + Status = PerformFlashWriteWithProgress (
> + ConfigData->FirmwareType,
> + ConfigData->BaseAddress,
> + ConfigData->AddressType,
> + (VOID *)((UINTN)SystemFirmwareImage + (UINTN)ConfigData-
> >ImageOffset),
> + ConfigData->Length,
> + Progress,
> + StartPercentage,
> + EndPercentage
> + );
> + if (Progress != NULL) {
> + Progress (EndPercentage);
> + }
> +
> + if (!EFI_ERROR (Status)) {
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
> + if (ConfigData->FirmwareType == PlatformFirmwareTypeNvRam) {
> + mNvRamUpdated = TRUE;
> + }
> + } else {
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Get layout of system firmware image.
> +
> + @param[in] SystemFirmwareImage Points to the System firmware image.
> + @param[out] SlotAOffset Points to the offste of slot A image.
> + @param[out] SlotBOffset Points to the offste of slot B image.
> +
> + @retval EFI_SUCCESS Get system firmware image layout
> successfully.
> + @retval others Some error occurs when executing this routine.
> +
> +**/
> +EFI_STATUS
> +GetImageLayout (
> + IN VOID *SystemFirmwareImage,
> + OUT UINT32 *SlotAOffset,
> + OUT UINT32 *SlotBOffset,
> + OUT UINT8 *ActiveSlot
> + )
> +{
> + FIRMWARE_ENTRY_TABLEV2 *EfsAddressPtr;
> + PSP_DIRECTORY *PspL1DirectoryPtr;
> + UINT32 SlotCount;
> + UINT32 Index;
> + IMAGE_SLOT_HEADER *IshSlotAInfoPtr;
> + IMAGE_SLOT_HEADER *IshSlotBInfoPtr;
> +
> + if (SystemFirmwareImage == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if ((SlotAOffset == NULL) || (SlotBOffset == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Check EFS structure of firmware image
> + //
> + EfsAddressPtr = (FIRMWARE_ENTRY_TABLEV2 *)(UINTN)((UINT8
> *)SystemFirmwareImage + EFS_LOCATION);
> + if (EfsAddressPtr->Signature != FIRMWARE_TABLE_SIGNATURE) {
> + DEBUG ((DEBUG_ERROR, "EFS signature incorrect.\n"));
> + return EFI_NOT_FOUND;
> + }
> +
> + //
> + // Check PSP_L1_DIRECTORY of firmware image
> + //
> + DEBUG ((DEBUG_INFO, "Base Address for PSP directory: 0x%x\n",
> EfsAddressPtr->PspDirBase));
> + PspL1DirectoryPtr = (PSP_DIRECTORY *)(UINTN)((UINT8
> *)SystemFirmwareImage + EfsAddressPtr->PspDirBase);
> + if ((PspL1DirectoryPtr->Header.Cookie !=
> PSP_DIRECTORY_HEADER_SIGNATURE) ||
> + (!IS_VALID_ADDR32 (EfsAddressPtr->PspDirBase)) ||
> + (!ALIGN_4K_CHECK (EfsAddressPtr->PspDirBase)) ||
> + (PspL1DirectoryPtr->Header.TotalEntries == 0) ||
> + (PspL1DirectoryPtr->Header.TotalEntries > MAX_IMAGE_SLOT_COUNT)
> + )
> + {
> + DEBUG ((DEBUG_ERROR, "PSP L1 directory address, slot count or signature
> error!\n"));
> + return EFI_NOT_FOUND;
> + }
> +
> + //
> + // Check Image Slot entries of firmware image
> + //
> + SlotCount = PspL1DirectoryPtr->Header.TotalEntries;
> + for (Index = 0; Index < SlotCount; Index++) {
> + if (((PspL1DirectoryPtr->PspEntry[Index].Type.Value !=
> PSP_REGION_A_DIR) &&
> + (PspL1DirectoryPtr->PspEntry[Index].Type.Value !=
> PSP_REGION_B_DIR)) ||
> + (!IS_VALID_ADDR32 (PspL1DirectoryPtr->PspEntry[Index].Location)) ||
> + (!ALIGN_4K_CHECK (PspL1DirectoryPtr->PspEntry[Index].Location)) ||
> + (((PspL1DirectoryPtr->PspEntry[Index].Location) &
> 0xFFFFFFFF00000000) != 0)
> + )
> + {
> + DEBUG ((DEBUG_ERROR, "PSP L1 directory slot %d data error!\n",
> Index));
> + return EFI_NOT_FOUND;
> + }
> + }
> +
> + //
> + // Get offset of specific slot
> + //
> + IshSlotAInfoPtr = (IMAGE_SLOT_HEADER *)(UINTN)((UINT8
> *)SystemFirmwareImage + PspL1DirectoryPtr->PspEntry[0].Location);
> + *SlotAOffset = IshSlotAInfoPtr->ImageSlotAddr;
> + DEBUG ((DEBUG_ERROR, "Slot A image offset: 0x%x\n", *SlotAOffset));
> +
> + IshSlotBInfoPtr = (IMAGE_SLOT_HEADER *)(UINTN)((UINT8
> *)SystemFirmwareImage + PspL1DirectoryPtr->PspEntry[1].Location);
> + *SlotBOffset = IshSlotBInfoPtr->ImageSlotAddr;
> + DEBUG ((DEBUG_ERROR, "Slot B image offset: 0x%x\n", *SlotBOffset));
> +
> + if ((*SlotAOffset == 0) || (*SlotBOffset == 0)) {
> + return EFI_NOT_FOUND;
> + }
> +
> + if (ActiveSlot != NULL) {
> + if (IshSlotAInfoPtr->Priority > IshSlotBInfoPtr->Priority) {
> + *ActiveSlot = SLOT_A;
> + } else {
> + *ActiveSlot = SLOT_B;
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Verify layout of OTA Capsule firmware image, and return offset and size of
> required update slot.
> +
> + @param[in] SystemFirmwareImage Points to the System firmware image.
> + @param[in] UpdateSlot The slot number need to be updated.
> + @param[out] UpdateOffset The firmware image offset need to
> updated.
> + @param[out] UpdateSize The firmware image size need to updated.
> +
> + @retval EFI_SUCCESS Verify OTA capsule image and get updated
> offset/size successfully.
> + @retval others Some error occurs when executing this routine.
> +
> +**/
> +EFI_STATUS
> +VerifyImageLayout (
> + IN VOID *SystemFirmwareImage,
> + IN UINT8 UpdateSlot,
> + OUT UINT32 *UpdateOffset,
> + OUT UINT32 *UpdateSize
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 OtaSlotAOffset;
> + UINT32 OtaSlotBOffset;
> + UINT32 FlashSlotAOffset;
> + UINT32 FlashSlotBOffset;
> + UINT8 CurrentActiveSlot;
> +
> + if (SystemFirmwareImage == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if ((UpdateOffset == NULL) || (UpdateSize == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + OtaSlotAOffset = 0;
> + OtaSlotBOffset = 0;
> + FlashSlotAOffset = 0;
> + FlashSlotBOffset = 0;
> +
> + //
> + // Get image layout of OTA Capsule
> + //
> + DEBUG ((DEBUG_INFO, "Get image layout of OTA Capsule.\n"));
> + Status = GetImageLayout (SystemFirmwareImage, &OtaSlotAOffset,
> &OtaSlotBOffset, NULL);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "GetImageLayout of Capsule failed: %r\n",
> Status));
> + return Status;
> + }
> +
> + //
> + // Get image layout of firmware in flash ROM
> + //
> + DEBUG ((DEBUG_INFO, "Get image layout of flash ROM.\n"));
> + Status = GetImageLayout ((VOID *)(UINTN)(PcdGet32
> (PcdFlashAreaBaseAddress)), &FlashSlotAOffset, &FlashSlotBOffset,
> &CurrentActiveSlot);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "GetImageLayout of Flash failed: %r\n", Status));
> + return Status;
> + }
> +
> + //
> + // Check current active slot and update slot
> + //
> + // - if (CurrentActiveSlot == mUpdateSlot) {
> + // - DEBUG ((DEBUG_ERROR, "Can't update Capsule on current active slot.
> CurrentActiveSlot: %d, UpdateSlot: %d\n", CurrentActiveSlot, mUpdateSlot));
> + // - return EFI_INVALID_PARAMETER;
> + // - }
> + //
> + // Compare layout of OTA capsule image and flash firmware
> + //
> + if ((OtaSlotAOffset != FlashSlotAOffset) || (OtaSlotBOffset !=
> FlashSlotBOffset)) {
> + DEBUG ((DEBUG_ERROR, "Layout is different between Capsule and
> Flash.\n"));
> + return EFI_NOT_FOUND;
> + }
> +
> + if (UpdateSlot == SLOT_A) {
> + *UpdateOffset = OtaSlotAOffset;
> + } else if (UpdateSlot == SLOT_B) {
> + *UpdateOffset = OtaSlotBOffset;
> + } else {
> + DEBUG ((DEBUG_ERROR, "Invalid update slot number: %d\n",
> UpdateSlot));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + // - *UpdateSize = (UINT32) DivU64x64Remainder ((UINTN) PcdGet32
> (PcdFlashAreaSize) - OtaSlotAOffset, 2, NULL);
> + *UpdateSize = (UINT32)((UINTN)PcdGet32 (PcdFlashAreaSize) -
> OtaSlotAOffset);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Get OTA Capsule firmware image info.
> +
> + @param[in] SystemFirmwareImage Points to the System firmware image.
> + @param[in] SystemFirmwareImageSize The length of the System Firmware
> image in bytes.
> + @param[out] OtaCapsuleOffset The firmware image offset need to
> updated.
> + @param[out] OtaCapsuleSize The firmware image size need to
> updated.
> +
> + @retval EFI_SUCCESS Get OTA Capsule firmware image info
> successfully.
> + @retval others Some error occurs when executing this routine.
> +
> +**/
> +EFI_STATUS
> +GetOtaCapsuleInfo (
> + IN VOID *SystemFirmwareImage,
> + IN UINTN SystemFirmwareImageSize,
> + OUT UINT32 *OtaCapsuleOffset,
> + OUT UINT32 *OtaCapsuleSize
> + )
> +{
> + EFI_STATUS Status;
> + OTA_CAPSULE_UPDATE OtaCapsuleUpdateVal;
> + // - UINTN VarSize;
> + UINT32 UpdateOffset;
> + UINT32 UpdateSize;
> +
> + if ((OtaCapsuleOffset == NULL) || (OtaCapsuleSize == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + DEBUG ((DEBUG_INFO, "GetOtaCapsuleInfo:"));
> + DEBUG ((DEBUG_INFO, " Legnth - 0x%x\n", SystemFirmwareImageSize));
> +
> + // - if (SystemFirmwareImageSize != (UINTN) PcdGet32 (PcdFlashAreaSize))
> {
> + // - return EFI_INVALID_PARAMETER;
> + // - }
> + if (SystemFirmwareImageSize != (UINTN)(PcdGet32 (PcdFlashAreaSize)*2))
> {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (&OtaCapsuleUpdateVal, sizeof (OTA_CAPSULE_UPDATE));
> +
> + /*
> + VarSize = sizeof (OTA_CAPSULE_UPDATE);
> + Status = gRT->GetVariable (
> + OTA_CAPSULE_VAR_NAME,
> + &gOtaCapsuleUpdateGuid,
> + NULL,
> + &VarSize,
> + (VOID *) &OtaCapsuleUpdateVal
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo: GetVariable failed: %r\n",
> Status));
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, "UpdateFlag: 0x%x, UpdateSlot: 0x%x\n",
> OtaCapsuleUpdateVal.UpdateFlag, OtaCapsuleUpdateVal.UpdateSlot));
> +
> + mUpdateSlot = OtaCapsuleUpdateVal.UpdateSlot;
> + if (mUpdateSlot >= MAX_SLOT_NUM) {
> + DEBUG ((DEBUG_ERROR, "Invalid Slot number: %d\n", mUpdateSlot));
> + return EFI_NOT_FOUND;
> + }
> + */
> + mUpdateSlot = 0;
> +
> + Status = VerifyImageLayout (SystemFirmwareImage, mUpdateSlot,
> &UpdateOffset, &UpdateSize);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "VerifyImageLayout failed: %r\n", Status));
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, "UpdateSlot: %d, UpdateOffset: 0x%x, UpdateSize:
> 0x%x\n", mUpdateSlot, UpdateOffset, UpdateSize));
> +
> + *OtaCapsuleOffset = UpdateOffset;
> + *OtaCapsuleSize = UpdateSize;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Get OTA Capsule firmware image info.
> +
> + @param[in] SystemFirmwareImage Points to the System firmware image.
> + @param[in] SystemFirmwareImageSize The length of the System Firmware
> image in bytes.
> + @param[out] OtaCapsuleOffset The firmware image offset need to
> updated.
> + @param[out] OtaCapsuleSize The firmware image size need to
> updated.
> +
> + @retval EFI_SUCCESS Get OTA Capsule firmware image info
> successfully.
> + @retval others Some error occurs when executing this routine.
> +
> +**/
> +EFI_STATUS
> +GetOtaCapsuleInfoSlotB (
> + IN VOID *SystemFirmwareImage,
> + IN UINTN SystemFirmwareImageSize,
> + OUT UINT32 *OtaCapsuleOffset,
> + OUT UINT32 *OtaCapsuleSize
> + )
> +{
> + EFI_STATUS Status;
> + OTA_CAPSULE_UPDATE OtaCapsuleUpdateVal;
> + // - UINTN VarSize;
> + UINT32 UpdateOffset;
> + UINT32 UpdateSize;
> +
> + // - if ((OtaCapsuleOffset == NULL) || (OtaCapsuleSize == NULL)) {
> + // - return EFI_INVALID_PARAMETER;
> + // - }
> +
> + DEBUG ((DEBUG_INFO, "GetOtaCapsuleInfo:"));
> + DEBUG ((DEBUG_INFO, " Legnth - 0x%x\n", SystemFirmwareImageSize));
> + // - if (SystemFirmwareImageSize != (UINTN) PcdGet32 (PcdFlashAreaSize))
> {
> + // - return EFI_INVALID_PARAMETER;
> + // - }
> + // - if (SystemFirmwareImageSize != (UINTN) (PcdGet32
> (PcdFlashAreaSize)*2)) {
> + // - return EFI_INVALID_PARAMETER;
> + // - }
> + ZeroMem (&OtaCapsuleUpdateVal, sizeof (OTA_CAPSULE_UPDATE));
> +
> + /*
> + VarSize = sizeof (OTA_CAPSULE_UPDATE);
> + Status = gRT->GetVariable (
> + OTA_CAPSULE_VAR_NAME,
> + &gOtaCapsuleUpdateGuid,
> + NULL,
> + &VarSize,
> + (VOID *) &OtaCapsuleUpdateVal
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo: GetVariable failed: %r\n",
> Status));
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, "UpdateFlag: 0x%x, UpdateSlot: 0x%x\n",
> OtaCapsuleUpdateVal.UpdateFlag, OtaCapsuleUpdateVal.UpdateSlot));
> +
> + mUpdateSlot = OtaCapsuleUpdateVal.UpdateSlot;
> + if (mUpdateSlot >= MAX_SLOT_NUM) {
> + DEBUG ((DEBUG_ERROR, "Invalid Slot number: %d\n", mUpdateSlot));
> + return EFI_NOT_FOUND;
> + }
> + */
> + mUpdateSlot = 1;
> +
> + Status = VerifyImageLayout (SystemFirmwareImage, mUpdateSlot,
> &UpdateOffset, &UpdateSize);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "VerifyImageLayout failed: %r\n", Status));
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, "UpdateSlot: %d, UpdateOffset: 0x%x, UpdateSize:
> 0x%x\n", mUpdateSlot, UpdateOffset, UpdateSize));
> +
> + *OtaCapsuleOffset = UpdateOffset;
> + *OtaCapsuleSize = UpdateSize;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Update active slot information in ISH.
> +
> + @param[in] SlotNum The slot number will be set as active.
> +
> + @retval EFI_SUCCESS Set active slto successfully.
> + @retval others Some error occurs when executing this routine.
> +
> +**/
> +EFI_STATUS
> +UpdateAbActiveSlot (
> + IN UINT8 SlotNum
> + )
> +{
> + EFI_STATUS Status;
> + IMAGE_SLOT_HEADER_INFO IshInfo;
> + UINTN VarSize;
> +
> + DEBUG ((DEBUG_INFO, "UpdateAbActiveSlot...\n"));
> +
> + if (SlotNum >= MAX_SLOT_NUM) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (&IshInfo, sizeof (IMAGE_SLOT_HEADER_INFO));
> +
> + VarSize = sizeof (IMAGE_SLOT_HEADER_INFO);
> + Status = gRT->GetVariable (
> + ISH_VAR_NAME,
> + &gABSupportUpdateIshGuid,
> + NULL,
> + &VarSize,
> + (VOID *)&IshInfo
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "Get A/B slot info failed: %r\n", Status));
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotA_Priority: 0x%x\n",
> IshInfo.SlotA_Priority));
> + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotA_UpdateRetries: 0x%x\n",
> IshInfo.SlotA_UpdateRetries));
> + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotA_GlitchRetries: 0x%x\n",
> IshInfo.SlotA_GlitchRetries));
> + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotB_Priority: 0x%x\n",
> IshInfo.SlotB_Priority));
> + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotB_UpdateRetries: 0x%x\n",
> IshInfo.SlotB_UpdateRetries));
> + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotB_GlitchRetries: 0x%x\n\n",
> IshInfo.SlotB_GlitchRetries));
> +
> + if (SlotNum == SLOT_A) {
> + // Slot A
> + if (IshInfo.SlotB_Priority == MAX_UINT32) {
> + IshInfo.SlotA_Priority = PcdGet32 (PcdFlashAbImageSlotDefaultPriority);
> + IshInfo.SlotB_Priority = IshInfo.SlotA_Priority - 1;
> + } else {
> + IshInfo.SlotA_Priority = MAX (IshInfo.SlotA_Priority,
> IshInfo.SlotB_Priority) + 1;
> + }
> +
> + IshInfo.SlotA_UpdateRetries = 0xFF;
> + } else if (SlotNum == SLOT_B) {
> + // Slot B
> + if (IshInfo.SlotA_Priority == MAX_UINT32) {
> + IshInfo.SlotB_Priority = PcdGet32 (PcdFlashAbImageSlotDefaultPriority);
> + IshInfo.SlotA_Priority = IshInfo.SlotB_Priority - 1;
> + } else {
> + IshInfo.SlotB_Priority = MAX (IshInfo.SlotA_Priority,
> IshInfo.SlotB_Priority) + 1;
> + }
> +
> + IshInfo.SlotB_UpdateRetries = 0xFF;
> + }
> +
> + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotA_Priority: 0x%x\n",
> IshInfo.SlotA_Priority));
> + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotA_UpdateRetries: 0x%x\n",
> IshInfo.SlotA_UpdateRetries));
> + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotA_GlitchRetries: 0x%x\n",
> IshInfo.SlotA_GlitchRetries));
> + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotB_Priority: 0x%x\n",
> IshInfo.SlotB_Priority));
> + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotB_UpdateRetries: 0x%x\n",
> IshInfo.SlotB_UpdateRetries));
> + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotB_GlitchRetries: 0x%x\n",
> IshInfo.SlotB_GlitchRetries));
> +
> + Status = gRT->SetVariable (
> + ISH_VAR_NAME,
> + &gABSupportUpdateIshGuid,
> + EFI_VARIABLE_BOOTSERVICE_ACCESS |
> EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
> + sizeof (IMAGE_SLOT_HEADER_INFO),
> + (VOID *)&IshInfo
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "Set Slot info failed: %r\n", Status));
> + return Status;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Update System Firmware image.
> +
> + @param[in] SystemFirmwareImage Points to the System Firmware
> image.
> + @param[in] SystemFirmwareImageSize The length of the System Firmware
> 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.
> + @param[in] Progress A function used by the driver to report the
> progress of the firmware update.
> +
> + @retval EFI_SUCCESS The System Firmware image is updated.
> + @retval EFI_WRITE_PROTECTED The flash device is read only.
> +**/
> +EFI_STATUS
> +UpdateImage (
> + IN VOID *SystemFirmwareImage,
> + IN UINTN SystemFirmwareImageSize,
> + IN VOID *ConfigImage,
> + IN UINTN ConfigImageSize,
> + OUT UINT32 *LastAttemptVersion,
> + OUT UINT32 *LastAttemptStatus,
> + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress
> + )
> +{
> + EFI_STATUS Status;
> + UPDATE_CONFIG_DATA *ConfigData;
> + UPDATE_CONFIG_DATA *UpdateConfigData;
> + CONFIG_HEADER ConfigHeader;
> + UINTN Index;
> + UINTN TotalSize;
> + UINTN BytesWritten;
> + UINTN StartPercentage;
> + UINTN EndPercentage;
> + UINT32 OtaCapsuleOffset;
> + UINT32 OtaCapsuleSize;
> + UINT32 ECImageSize;
> + UINT32 ECImageOffset;
> +
> + if (ConfigImage == NULL) {
> + DEBUG ((DEBUG_INFO, "PlatformUpdate (NoConfig):"));
> + // ASSUME the whole System Firmware include NVRAM region.
> + StartPercentage = 0;
> + EndPercentage = 100;
> + if (Progress != NULL) {
> + Progress (StartPercentage);
> + }
> +
> + ECImageSize = 0x20000;
> + ECImageOffset = 0x0;
> +
> + DEBUG ((DEBUG_INFO, " BaseAddress - 0x%x,", ECImageOffset));
> + DEBUG ((DEBUG_INFO, " Length - 0x%x\n", ECImageSize));
> +
> + Status = PerformFlashWriteWithProgress (
> + PlatformFirmwareTypeNvRam,
> + (EFI_PHYSICAL_ADDRESS)ECImageOffset,
> + FlashAddressTypeRelativeAddress,
> + (VOID *)((UINT8 *)SystemFirmwareImage + ECImageOffset),
> + ECImageSize,
> + Progress,
> + StartPercentage,
> + EndPercentage
> + );
> + if (Progress != NULL) {
> + Progress (EndPercentage);
> + }
> +
> + if (!EFI_ERROR (Status)) {
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
> + mNvRamUpdated = TRUE;
> + } else {
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
> + }
> +
> + StartPercentage = 0;
> + EndPercentage = 100;
> + if (Progress != NULL) {
> + Progress (StartPercentage);
> + }
> +
> + Status = GetOtaCapsuleInfo (SystemFirmwareImage,
> SystemFirmwareImageSize, &OtaCapsuleOffset, &OtaCapsuleSize);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo failed: %r\n", Status));
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, " BaseAddress - 0x%x,", OtaCapsuleOffset));
> + DEBUG ((DEBUG_INFO, " Length - 0x%x\n", OtaCapsuleSize));
> +
> + Status = PerformFlashWriteWithProgress (
> + PlatformFirmwareTypeNvRam,
> + (EFI_PHYSICAL_ADDRESS)OtaCapsuleOffset,
> + FlashAddressTypeRelativeAddress,
> + (VOID *)((UINT8 *)SystemFirmwareImage + OtaCapsuleOffset),
> + OtaCapsuleSize,
> + Progress,
> + StartPercentage,
> + EndPercentage
> + );
> + if (Progress != NULL) {
> + Progress (EndPercentage);
> + }
> +
> + if (!EFI_ERROR (Status)) {
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
> + mNvRamUpdated = TRUE;
> + } else {
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
> + }
> +
> + Status = GetOtaCapsuleInfoSlotB (SystemFirmwareImage,
> SystemFirmwareImageSize, &OtaCapsuleOffset, &OtaCapsuleSize);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo failed: %r\n", Status));
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, " BaseAddress - 0x%x,", OtaCapsuleOffset));
> + DEBUG ((DEBUG_INFO, " Length - 0x%x\n", OtaCapsuleSize));
> +
> + Status = PerformFlashWriteWithProgress (
> + PlatformFirmwareTypeNvRam,
> + (EFI_PHYSICAL_ADDRESS)OtaCapsuleOffset,
> + FlashAddressTypeRelativeAddress,
> + (VOID *)((UINT8 *)SystemFirmwareImage + OtaCapsuleOffset),
> + OtaCapsuleSize,
> + Progress,
> + StartPercentage,
> + EndPercentage
> + );
> + if (Progress != NULL) {
> + Progress (EndPercentage);
> + }
> +
> + if (!EFI_ERROR (Status)) {
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
> + mNvRamUpdated = TRUE;
> + } else {
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
> + }
> +
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, "PlatformUpdate (With Config):\n"));
> + ConfigData = NULL;
> + ZeroMem (&ConfigHeader, sizeof (ConfigHeader));
> + Status = ParseUpdateDataFile (
> + ConfigImage,
> + ConfigImageSize,
> + &ConfigHeader,
> + &ConfigData
> + );
> + DEBUG ((DEBUG_INFO, "ParseUpdateDataFile - %r\n", Status));
> + if (EFI_ERROR (Status)) {
> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + DEBUG ((DEBUG_INFO, "ConfigHeader.NumOfUpdates - 0x%x\n",
> ConfigHeader.NumOfUpdates));
> + DEBUG ((DEBUG_INFO, "PcdEdkiiSystemFirmwareFileGuid - %g\n",
> PcdGetPtr (PcdEdkiiSystemFirmwareFileGuid)));
> +
> + TotalSize = 0;
> + for (Index = 0; Index < ConfigHeader.NumOfUpdates; Index++) {
> + if (CompareGuid (&ConfigData[Index].FileGuid, PcdGetPtr
> (PcdEdkiiSystemFirmwareFileGuid))) {
> + TotalSize = TotalSize + ConfigData[Index].Length;
> + }
> + }
> +
> + BytesWritten = 0;
> + Index = 0;
> + UpdateConfigData = ConfigData;
> + while (Index < ConfigHeader.NumOfUpdates) {
> + if (CompareGuid (&UpdateConfigData->FileGuid, PcdGetPtr
> (PcdEdkiiSystemFirmwareFileGuid))) {
> + DEBUG ((DEBUG_INFO, "FileGuid - %g (processing)\n",
> &UpdateConfigData->FileGuid));
> + StartPercentage = (BytesWritten * 100) / TotalSize;
> + EndPercentage = ((BytesWritten + UpdateConfigData->Length) * 100) /
> TotalSize;
> + Status = PerformUpdate (
> + SystemFirmwareImage,
> + SystemFirmwareImageSize,
> + UpdateConfigData,
> + LastAttemptVersion,
> + LastAttemptStatus,
> + Progress,
> + StartPercentage,
> + EndPercentage
> + );
> + //
> + // 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;
> + }
> + } else {
> + DEBUG ((DEBUG_INFO, "FileGuid - %g (ignored)\n", &UpdateConfigData-
> >FileGuid));
> + }
> +
> + BytesWritten += UpdateConfigData->Length;
> +
> + Index++;
> + UpdateConfigData++;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Authenticate and update System Firmware image.
> +
> + Caution: This function may receive untrusted input.
> +
> + @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.
> + @param[in] Progress A function used by the driver to report the
> progress of the firmware update.
> +
> + @retval EFI_SUCCESS EDKII system FMP capsule passes
> authentication and the System Firmware image is updated.
> + @retval EFI_SECURITY_VIOLATION EDKII system FMP capsule fails
> authentication and the System Firmware image is not updated.
> + @retval EFI_WRITE_PROTECTED The flash device is read only.
> +**/
> +EFI_STATUS
> +SystemFirmwareAuthenticatedUpdate (
> + IN VOID *Image,
> + IN UINTN ImageSize,
> + OUT UINT32 *LastAttemptVersion,
> + OUT UINT32 *LastAttemptStatus,
> + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress
> + )
> +{
> + EFI_STATUS Status;
> + VOID *SystemFirmwareImage;
> + UINTN SystemFirmwareImageSize;
> + VOID *ConfigImage;
> + UINTN ConfigImageSize;
> + VOID *AuthenticatedImage;
> + UINTN AuthenticatedImageSize;
> +
> + AuthenticatedImage = NULL;
> + AuthenticatedImageSize = 0;
> +
> + DEBUG ((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate...\n"));
> +
> + Status = CapsuleAuthenticateSystemFirmware (Image, ImageSize, FALSE,
> LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage,
> &AuthenticatedImageSize);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_INFO, "SystemFirmwareAuthenticateImage - %r\n",
> Status));
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, "ExtractSystemFirmwareImage ...\n"));
> + ExtractSystemFirmwareImage (AuthenticatedImage,
> AuthenticatedImageSize, &SystemFirmwareImage,
> &SystemFirmwareImageSize);
> + DEBUG ((DEBUG_INFO, "ExtractConfigImage ...\n"));
> + ExtractConfigImage (AuthenticatedImage, AuthenticatedImageSize,
> &ConfigImage, &ConfigImageSize);
> +
> + DEBUG ((DEBUG_INFO, "UpdateImage ...\n"));
> + Status = UpdateImage (SystemFirmwareImage, SystemFirmwareImageSize,
> ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus,
> Progress);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_INFO, "UpdateImage - %r\n", Status));
> + return Status;
> + }
> +
> + #if 0
> + // DO NOT KNOW THE REASON to update A/B Active Slot.
> + // Removed FOR NOW.
> +
> + //
> + // Update A/B active slot info
> + //
> + Status = UpdateAbActiveSlot (mUpdateSlot);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "UpdateAbActiveSlot failed: %r\n", Status));
> + return Status;
> + }
> +
> + DEBUG ((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate Done\n"));
> + #endif
> + return Status;
> +}
> +
> +/**
> +
> + This code finds variable in storage blocks (Volatile or Non-Volatile).
> +
> + @param[in] VariableName Name of Variable to be found.
> + @param[in] VendorGuid Variable vendor GUID.
> + @param[out] Attributes Attribute value of the variable found.
> + @param[in, out] DataSize Size of Data found. If size is less than the
> + data, this value contains the required size.
> + @param[out] 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 ((DEBUG_INFO, "GetVariableHook - %S, %g\n", VariableName,
> VendorGuid));
> + return EFI_NOT_AVAILABLE_YET;
> +}
> +
> +/**
> +
> + This code Finds the Next available variable.
> +
> + @param[in, out] VariableNameSize Size of the variable name.
> + @param[in, out] VariableName Pointer to variable name.
> + @param[in, out] 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 ((DEBUG_INFO, "GetNextVariableNameHook - %S, %g\n",
> VariableName, VendorGuid));
> + return EFI_NOT_AVAILABLE_YET;
> +}
> +
> +/**
> +
> + This code sets variable in storage blocks (Volatile or Non-Volatile).
> +
> + @param[in] VariableName Name of Variable to be found.
> + @param[in] VendorGuid Variable vendor GUID.
> + @param[in] Attributes Attribute value of the variable found
> + @param[in] DataSize Size of Data found. If size is less than the
> + data, this value contains the required size.
> + @param[in] 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 ((DEBUG_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[in] Attributes Attributes bitmask to specify the type of
> variables
> + on which to return information.
> + @param[out] MaximumVariableStorageSize Pointer to the maximum size
> of the storage space available
> + for the EFI variables associated with the attributes
> specified.
> + @param[out] RemainingVariableStorageSize Pointer to the remaining size
> of the storage space available
> + for EFI variables associated with the attributes
> specified.
> + @param[out] 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 ((DEBUG_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_VIOLATION 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;
> + SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate;
> +
> + if ((Image == NULL) || (ImageSize == 0) || (AbortReason == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP (This);
> + *AbortReason = NULL;
> +
> + if ((ImageIndex == 0) || (ImageIndex > SystemFmpPrivate-
> >DescriptorCount)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = SystemFirmwareAuthenticatedUpdate ((VOID *)Image, ImageSize,
> &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate-
> >LastAttempt.LastAttemptStatus, Progress);
> + DEBUG ((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, State -
> 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion,
> SystemFmpPrivate->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 ((DEBUG_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 (SystemFmpPrivate->LastAttempt),
> + &SystemFmpPrivate->LastAttempt
> + );
> + DEBUG ((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus));
> +
> + return Status;
> +}
> +
> +/**
> + Get the set of EFI_FIRMWARE_IMAGE_DESCRIPTOR structures from an FMP
> Protocol.
> +
> + @param[in] Handle Handle with an FMP Protocol or a System FMP
> + Protocol.
> + @param[in] ProtocolGuid Pointer to the FMP Protocol GUID or System
> FMP
> + Protocol GUID.
> + @param[out] FmpImageInfoCount Pointer to the number of
> + EFI_FIRMWARE_IMAGE_DESCRIPTOR structures.
> + @param[out] DescriptorSize Pointer to the size, in bytes, of each
> + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure.
> +
> + @return NULL No EFI_FIRMWARE_IMAGE_DESCRIPTOR structures found.
> + @return !NULL Pointer to a buffer of EFI_FIRMWARE_IMAGE_DESCRIPTOR
> structures
> + allocated using AllocatePool(). Caller must free buffer with
> + FreePool().
> +**/
> +EFI_FIRMWARE_IMAGE_DESCRIPTOR *
> +GetFmpImageDescriptors (
> + IN EFI_HANDLE Handle,
> + IN EFI_GUID *ProtocolGuid,
> + OUT UINT8 *FmpImageInfoCount,
> + OUT UINTN *DescriptorSize
> + )
> +{
> + EFI_STATUS Status;
> + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
> + UINTN ImageInfoSize;
> + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
> + UINT32 FmpImageInfoDescriptorVer;
> + UINT32 PackageVersion;
> + CHAR16 *PackageVersionName;
> +
> + *FmpImageInfoCount = 0;
> + *DescriptorSize = 0;
> +
> + Status = gBS->HandleProtocol (
> + Handle,
> + ProtocolGuid,
> + (VOID **)&Fmp
> + );
> + if (EFI_ERROR (Status)) {
> + return NULL;
> + }
> +
> + //
> + // Determine the size required for the set of
> EFI_FIRMWARE_IMAGE_DESCRIPTORs.
> + //
> + ImageInfoSize = 0;
> + Status = Fmp->GetImageInfo (
> + Fmp, // FMP Pointer
> + &ImageInfoSize, // Buffer Size (in this case 0)
> + NULL, // NULL so we can get size
> + &FmpImageInfoDescriptorVer, // DescriptorVersion
> + FmpImageInfoCount, // DescriptorCount
> + DescriptorSize, // DescriptorSize
> + &PackageVersion, // PackageVersion
> + &PackageVersionName // PackageVersionName
> + );
> + if (Status != EFI_BUFFER_TOO_SMALL) {
> + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Unexpected
> Failure. Status = %r\n", Status));
> + return NULL;
> + }
> +
> + //
> + // Allocate buffer for the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
> + //
> + FmpImageInfoBuf = NULL;
> + FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> + if (FmpImageInfoBuf == NULL) {
> + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to allocate
> memory for descriptors.\n"));
> + return NULL;
> + }
> +
> + //
> + // Retrieve the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
> + //
> + PackageVersionName = NULL;
> + Status = Fmp->GetImageInfo (
> + Fmp,
> + &ImageInfoSize, // ImageInfoSize
> + FmpImageInfoBuf, // ImageInfo
> + &FmpImageInfoDescriptorVer, // DescriptorVersion
> + FmpImageInfoCount, // DescriptorCount
> + DescriptorSize, // DescriptorSize
> + &PackageVersion, // PackageVersion
> + &PackageVersionName // PackageVersionName
> + );
> +
> + //
> + // Free unused PackageVersionName return buffer
> + //
> + if (PackageVersionName != NULL) {
> + FreePool (PackageVersionName);
> + PackageVersionName = NULL;
> + }
> +
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failure in
> GetImageInfo. Status = %r\n", Status));
> + if (FmpImageInfoBuf != NULL) {
> + FreePool (FmpImageInfoBuf);
> + }
> +
> + return NULL;
> + }
> +
> + return FmpImageInfoBuf;
> +}
> +
> +/**
> + Search for handles with an FMP protocol whose
> EFI_FIRMWARE_IMAGE_DESCRIPTOR
> + ImageTypeId matches the ImageTypeId produced by this module.
> +
> + @param[in] ProtocolGuid Pointer to the GUID of the protocol to search.
> + @param[out] HandleCount Pointer to the number of returned handles.
> +
> + @return NULL No matching handles found.
> + @return !NULL Pointer to a buffer of handles allocated using AllocatePool().
> + Caller must free buffer with FreePool().
> +**/
> +EFI_HANDLE *
> +FindMatchingFmpHandles (
> + IN EFI_GUID *ProtocolGuid,
> + OUT UINTN *HandleCount
> + )
> +{
> + EFI_STATUS Status;
> + UINTN TempHandleCount;
> + EFI_HANDLE *HandleBuffer;
> + UINTN Index;
> + UINTN Index2;
> + UINTN Index3;
> + EFI_FIRMWARE_IMAGE_DESCRIPTOR *OriginalFmpImageInfoBuf;
> + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
> + UINT8 FmpImageInfoCount;
> + UINTN DescriptorSize;
> + BOOLEAN MatchFound;
> +
> + *HandleCount = 0;
> + TempHandleCount = 0;
> + HandleBuffer = NULL;
> + Status = gBS->LocateHandleBuffer (
> + ByProtocol,
> + ProtocolGuid,
> + NULL,
> + &TempHandleCount,
> + &HandleBuffer
> + );
> + if (EFI_ERROR (Status)) {
> + return NULL;
> + }
> +
> + for (Index = 0; Index < TempHandleCount; Index++) {
> + OriginalFmpImageInfoBuf = GetFmpImageDescriptors (
> + HandleBuffer[Index],
> + ProtocolGuid,
> + &FmpImageInfoCount,
> + &DescriptorSize
> + );
> +
> + //
> + // Loop through the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
> + //
> + MatchFound = FALSE;
> + if (OriginalFmpImageInfoBuf != NULL) {
> + FmpImageInfoBuf = OriginalFmpImageInfoBuf;
> +
> + for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
> + for (Index3 = 0; Index3 < mSystemFmpPrivate->DescriptorCount;
> Index3++) {
> + MatchFound = CompareGuid (
> + &FmpImageInfoBuf->ImageTypeId,
> + &mSystemFmpPrivate->ImageDescriptor[Index3].ImageTypeId
> + );
> + if (MatchFound) {
> + break;
> + }
> + }
> +
> + if (MatchFound) {
> + break;
> + }
> +
> + //
> + // Increment the buffer pointer ahead by the size of the descriptor
> + //
> + FmpImageInfoBuf = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8
> *)FmpImageInfoBuf) + DescriptorSize);
> + }
> +
> + if (MatchFound) {
> + HandleBuffer[*HandleCount] = HandleBuffer[Index];
> + (*HandleCount)++;
> + }
> +
> + FreePool (OriginalFmpImageInfoBuf);
> + }
> + }
> +
> + if ((*HandleCount) == 0) {
> + //
> + // No any matching handle.
> + //
> + FreePool (HandleBuffer);
> + return NULL;
> + }
> +
> + return HandleBuffer;
> +}
> +
> +/**
> + Uninstall System FMP Protocol instances that may have been installed by
> + SystemFirmwareUpdateDxe drivers dispatches by other capsules.
> +
> + @retval EFI_SUCCESS All System FMP Protocols found were uninstalled.
> + @return Other One or more System FMP Protocols could not be
> uninstalled.
> +
> +**/
> +EFI_STATUS
> +UninstallMatchingSystemFmpProtocols (
> + VOID
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HANDLE *HandleBuffer;
> + UINTN HandleCount;
> + UINTN Index;
> + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *SystemFmp;
> +
> + //
> + // Uninstall SystemFmpProtocol instances that may have been produced by
> + // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules.
> + //
> + HandleBuffer = FindMatchingFmpHandles (
> + &gSystemFmpProtocolGuid,
> + &HandleCount
> + );
> + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching
> System FMP instances\n", HandleCount));
> +
> + for (Index = 0; Index < HandleCount; Index++) {
> + Status = gBS->HandleProtocol (
> + HandleBuffer[Index],
> + &gSystemFmpProtocolGuid,
> + (VOID **)&SystemFmp
> + );
> + if (EFI_ERROR (Status)) {
> + continue;
> + }
> +
> + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Uninstall
> SystemFmp produced by another capsule\n"));
> + Status = gBS->UninstallProtocolInterface (
> + HandleBuffer[Index],
> + &gSystemFmpProtocolGuid,
> + SystemFmp
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to uninstall
> SystemFmp %r. Exiting.\n", Status));
> + FreePool (HandleBuffer);
> + return Status;
> + }
> + }
> +
> + if (HandleBuffer != NULL) {
> + FreePool (HandleBuffer);
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + System FMP module entrypoint
> +
> + @param[in] ImageHandle The firmware allocated handle for the EFI image.
> + @param[in] SystemTable A pointer to the EFI System Table.
> +
> + @retval EFI_SUCCESS System FMP module is initialized.
> + @retval EFI_OUT_OF_RESOURCES There are not enough resources
> avaulable to
> + initialize this module.
> + @retval Other System FMP Protocols could not be uninstalled.
> + @retval Other System FMP Protocol could not be installed.
> + @retval Other FMP Protocol could not be installed.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SystemFirmwareUpdateMainDxe (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HANDLE *HandleBuffer;
> + UINTN HandleCount;
> +
> + //
> + // Initialize SystemFmpPrivateData
> + //
> + mSystemFmpPrivate = AllocateZeroPool (sizeof
> (SYSTEM_FMP_PRIVATE_DATA));
> + if (mSystemFmpPrivate == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Status = InitializePrivateData (mSystemFmpPrivate);
> + if (EFI_ERROR (Status)) {
> + FreePool (mSystemFmpPrivate);
> + mSystemFmpPrivate = NULL;
> + return Status;
> + }
> +
> + //
> + // Uninstall SystemFmpProtocol instances that may have been produced by
> + // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules.
> + //
> + Status = UninstallMatchingSystemFmpProtocols ();
> + if (EFI_ERROR (Status)) {
> + FreePool (mSystemFmpPrivate);
> + mSystemFmpPrivate = NULL;
> + return Status;
> + }
> +
> + //
> + // Look for a handle with matching Firmware Management Protocol
> + //
> + HandleCount = 0;
> + HandleBuffer = FindMatchingFmpHandles (
> + &gEfiFirmwareManagementProtocolGuid,
> + &HandleCount
> + );
> + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching
> FMP instances\n", HandleCount));
> +
> + switch (HandleCount) {
> + case 0:
> + //
> + // Install FMP protocol onto a new handle.
> + //
> + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install FMP onto a
> new handle\n"));
> + Status = gBS->InstallMultipleProtocolInterfaces (
> + &mSystemFmpPrivate->Handle,
> + &gEfiFirmwareManagementProtocolGuid,
> + &mSystemFmpPrivate->Fmp,
> + NULL
> + );
> + break;
> + case 1:
> + //
> + // Install System FMP protocol onto handle with matching FMP Protocol
> + //
> + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install System FMP
> onto matching FMP handle\n"));
> + mSystemFmpPrivate->Handle = HandleBuffer[0];
> + Status = gBS->InstallMultipleProtocolInterfaces (
> + &HandleBuffer[0],
> + &gSystemFmpProtocolGuid,
> + &mSystemFmpPrivate->Fmp,
> + NULL
> + );
> + break;
> + default:
> + //
> + // More than one matching handle is not expected. Unload driver.
> + //
> + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: More than one
> matching FMP handle. Unload driver.\n"));
> + Status = EFI_DEVICE_ERROR;
> + break;
> + }
> +
> + if (HandleBuffer != NULL) {
> + FreePool (HandleBuffer);
> + }
> +
> + if (EFI_ERROR (Status)) {
> + FreePool (mSystemFmpPrivate);
> + mSystemFmpPrivate = NULL;
> + }
> +
> + return Status;
> +}
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal
> /SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
> new file mode 100644
> index 0000000000..aff752007d
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
> @@ -0,0 +1,91 @@
> +## @file
> +# System Firmware Update Dxe
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +## @file
> +# SystemFirmware 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 = SystemFirmwareUpdateDxe
> + MODULE_UNI_FILE = SystemFirmwareUpdateDxe.uni
> + FILE_GUID = 0A2FBD15-1C25-407E-8915-60C5652BC2AA
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + ENTRY_POINT = SystemFirmwareUpdateMainDxe
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +# VALID_ARCHITECTURES = X64
> +#
> +
> +[Sources]
> + SystemFirmwareDxe.h
> + SystemFirmwareCommonDxe.c
> + SystemFirmwareUpdateDxe.c
> + ParseConfigProfile.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + VanGoghCommonPkg/AmdCommonPkg.dec
> + SignedCapsulePkg/SignedCapsulePkg.dec
> + ChachaniBoardPkg/Project.dec
> + AgesaPublic/AgesaPublic.dec
> +
> +[LibraryClasses]
> + BaseLib
> + UefiLib
> + BaseMemoryLib
> + DebugLib
> + PcdLib
> + MemoryAllocationLib
> + UefiBootServicesTableLib
> + HobLib
> + UefiRuntimeServicesTableLib
> + UefiDriverEntryPoint
> + DxeServicesLib
> + EdkiiSystemCapsuleLib
> + PlatformFlashAccessLib
> + IniParsingLib
> + PrintLib
> +
> +[Pcd]
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid
> ## CONSUMES
> + gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareFileGuid
> ## CONSUMES
> +
> gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescript
> or ## CONSUMES
> + gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress ##
> CONSUMES
> + gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize ##
> CONSUMES
> + gPlatformPkgTokenSpaceGuid.PcdFlashAbImageSlotDefaultPriority
> ## CONSUMES
> +
> +[Guids]
> + gOtaCapsuleUpdateGuid
> + gABSupportUpdateIshGuid
> +
> +[Protocols]
> + gEfiFirmwareManagementProtocolGuid ## PRODUCES
> +
> +[Depex]
> + gEfiVariableArchProtocolGuid
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> + SystemFirmwareUpdateDxeExtra.uni
> +
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal
> /SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
> new file mode 100644
> index 0000000000..e6bd18b249
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
> @@ -0,0 +1,15 @@
> +// /** @file
> +// SystemFirmware FMP update driver.
> +//
> +// Produce FMP instance to update system firmware.
> +//
> +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_MODULE_ABSTRACT #language en-US "SystemFirmware
> FMP update driver."
> +
> +#string STR_MODULE_DESCRIPTION #language en-US "Produce FMP
> instance to update system firmware."
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal
> /SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
> new file mode 100644
> index 0000000000..c549f017a4
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
> @@ -0,0 +1,15 @@
> +// /** @file
> +// SystemFirmwareUpdateDxeExtra Localized Strings and Content
> +//
> +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"SystemFirmwareUpdate DXE Driver"
> +
> +
> --
> 2.31.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114566): https://edk2.groups.io/g/devel/message/114566
Mute This Topic: https://groups.io/mt/103971411/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-01-26 9:29 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
2024-01-26 9:19 ` Chang, Abner via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 02/32] AMD/VanGoghBoard: Check in ACPI tables Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 03/32] AMD/VanGoghBoard: Check in Capsule update Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 04/32] AMD/VanGoghBoard: Check in AgesaPublic pkg Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 05/32]AMD/VanGoghBoard: Check in PlatformSecLib Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 06/32] AMD/VanGoghBoard: Check in AmdIdsExtLib Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 07/32] AMD/VanGoghBoard: Check in PciPlatform Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 08/32] AMD/VanGoghBoard: Check in UDKFlashUpdate Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 09/32] AMD/VanGoghBoard: Check in Flash_AB Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 10/32] AMD/VanGoghBoard: Check in FlashUpdate Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 11/32] AMD/VanGoghBoard: Check in FvbServices Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 12/32] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 14/32] AMD/VanGoghBoard: Check in SmbiosLib Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 15/32] AMD/VanGoghBoard: Check in SpiFlashDeviceLib Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 16/32] AMD/VanGoghBoard: Check in BaseTscTimerLib Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 17/32] AMD/VanGoghBoard: Check in Smm access module Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 18/32] AMD/VanGoghBoard: Check in PciHostBridge module Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 19/32] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 20/32] AMD/VanGoghBoard: Check in FTPM module Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule Zhai, MingXin (Duke) via groups.io
2024-01-26 9:28 ` Chang, Abner via groups.io [this message]
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 22/32] AMD/VanGoghBoard: Check in Vtf0 Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 23/32] AMD/VanGoghBoard: Check in AcpiPlatform Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 24/32] AMD/VanGoghBoard: Check in FchSpi module Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 25/32] AMD/VanGoghBoard: Check in PlatformInitPei module Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 26/32] AMD/VanGoghBoard: Check in Smbios platform dxe drivers Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg Zhai, MingXin (Duke) via groups.io
2024-01-26 9:34 ` Chang, Abner via groups.io
2024-01-26 9:36 ` Chang, Abner via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 29/32] AMD/VanGoghBoard: Check in SmramSaveState module Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 30/32] AMD/VanGoghBoard: Check in EDK2 override files Zhai, MingXin (Duke) via groups.io
2024-01-26 9:37 ` Chang, Abner via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script Zhai, MingXin (Duke) via groups.io
2024-01-26 9:48 ` [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Chang, Abner via groups.io
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=LV8PR12MB9452E17AC63DC9B0E7C810F3EA792@LV8PR12MB9452.namprd12.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox