public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Zhai, MingXin (Duke) via groups.io" <duke.zhai=amd.com@groups.io>
To: <devel@edk2.groups.io>
Cc: Eric Xing <eric.xing@amd.com>, Duke Zhai <duke.zhai@amd.com>,
	Igniculus Fu <igniculus.fu@amd.com>,
	Abner Chang <abner.chang@amd.com>
Subject: [edk2-devel] [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule
Date: Fri, 26 Jan 2024 14:00:39 +0800	[thread overview]
Message-ID: <20240126060050.1725-22-duke.zhai@amd.com> (raw)
In-Reply-To: <20240126060050.1725-1-duke.zhai@amd.com>

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/GenFds/Capsule.py
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFds/Capsule.py b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFds/Capsule.py
new file mode 100644
index 0000000000..0ec0b3ca43
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFds/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/Universal/SystemFirmwareUpdate/ParseConfigProfile.c
new file mode 100644
index 0000000000..b57586a267
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/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
+
+**/
+
+/** @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/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
new file mode 100644
index 0000000000..05a36162d3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/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/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h
new file mode 100644
index 0000000000..b1aab4c41e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/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/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
new file mode 100644
index 0000000000..894d363de0
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/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/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
new file mode 100644
index 0000000000..aff752007d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/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.PcdEdkiiSystemFirmwareImageDescriptor    ## 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/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
new file mode 100644
index 0000000000..e6bd18b249
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/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/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
new file mode 100644
index 0000000000..c549f017a4
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/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 (#114514): https://edk2.groups.io/g/devel/message/114514
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]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2024-01-26  6:02 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 ` Zhai, MingXin (Duke) via groups.io [this message]
2024-01-26  9:28   ` [edk2-devel] [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule Chang, Abner via groups.io
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=20240126060050.1725-22-duke.zhai@amd.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