public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
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]
-=-=-=-=-=-=-=-=-=-=-=-



  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