[edk2-devel] [PATCH 21/33] AMD/VanGoghBoard: Check in SignedCapsule.

duke.zhai via groups.io posted 33 patches 7 months, 3 weeks ago
There is a newer version of this series
[edk2-devel] [PATCH 21/33] AMD/VanGoghBoard: Check in SignedCapsule.
Posted by duke.zhai via groups.io 7 months, 3 weeks ago
From: Duke Zhai <Duke.Zhai@amd.com>


BZ #:4640

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 |  261 +++

 .../SystemFirmwareUpdate/ParseConfigProfile.c |  231 +++

 .../SystemFirmwareCommonDxe.c                 |  386 +++++

 .../SystemFirmwareUpdate/SystemFirmwareDxe.h  |  435 +++++

 .../SystemFirmwareUpdateDxe.c                 | 1448 +++++++++++++++++

 .../SystemFirmwareUpdateDxe.inf               |   91 ++

 .../SystemFirmwareUpdateDxe.uni               |   31 +

 .../SystemFirmwareUpdateDxeExtra.uni          |   30 +

 .../Include/OtaCapsuleUpdate.h                |   38 +

 9 files changed, 2951 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

 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/OtaCapsuleUpdate.h



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..248eb25889

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFds/Capsule.py

@@ -0,0 +1,261 @@

+#/*****************************************************************************

+#*

+#* Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+#* SPDX-License-Identifier: BSD-2-Clause-Patent

+#******************************************************************************

+#

+

+# This file includes code originally published under the following license.

+

+## @file

+# generate capsule

+#

+#  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..d3640cb3d9

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c

@@ -0,0 +1,386 @@

+/** @file

+  Implements SystemFirmwareCommonDxe.C

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  Produce FMP instance for system firmware.

+

+  Copyright (c) 2016 - 2018, 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"

+

+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..8164f66958

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h

@@ -0,0 +1,435 @@

+/** @file

+    Implementation of SystemFirmwareDxe.h

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  System Firmware update header file.

+

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

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#ifndef _SYSTEM_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..61e23b4564

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c

@@ -0,0 +1,1448 @@

+/** @file

+  Implements SystemFirmwareUpdateDxe.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  SetImage instance to update system firmware.

+

+  Caution: This module requires additional review when modified.

+  This module will have external input - capsule image.

+  This external input must be validated carefully to avoid security issue like

+  buffer overflow, integer overflow.

+

+  FmpSetImage() will receive untrusted input and do basic validation.

+

+  Copyright (c) 2016 - 2018, 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"

+

+//

+// 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..3b96e42e14

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni

@@ -0,0 +1,31 @@

+// /** @file

+// SystemFirmwareUpdateDxe Localized Strings and Content

+//

+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+//

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+// This file includes code originally published under the following license.

+

+// /** @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.

+//

+// **/

+

+

+#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..68206af750

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni

@@ -0,0 +1,30 @@

+// /** @file

+// SystemFirmwareUpdateDxeExtra Localized Strings and Content

+//

+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+//

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+// This file includes code originally published under the following license.

+

+// /** @file

+// SystemFirmwareUpdateDxe Localized Strings and Content

+//

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

+//

+// This program and the accompanying materials

+// are licensed and made available under the terms and conditions of the BSD License

+// which accompanies this distribution.  The full text of the license may be found at

+// http://opensource.org/licenses/bsd-license.php

+//

+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+//

+// **/

+

+#string STR_PROPERTIES_MODULE_NAME

+#language en-US

+"SystemFirmwareUpdate DXE Driver"

+

+

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/OtaCapsuleUpdate.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/OtaCapsuleUpdate.h

new file mode 100644

index 0000000000..6f10bc9c82

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/OtaCapsuleUpdate.h

@@ -0,0 +1,38 @@

+/** @file

+    Implements OtaCapsuleUpdate.h

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef _OTA_CAPSULE_UPDATE_H_

+#define _OTA_CAPSULE_UPDATE_H_

+

+#pragma pack (1)

+//

+// OTA for BIOS Capsule update

+//

+typedef struct {

+  UINT8    UpdateFlag;      // 0: No update required; 1: update required

+  UINT8    UpdateSlot;      // 0: Slot A; 1: Slot B

+} OTA_CAPSULE_UPDATE;

+

+#pragma pack ()

+

+//

+// Variable Name for OTA BIOS Update

+//

+#define OTA_CAPSULE_VAR_NAME  L"OtaCapsuleVar"

+

+//

+// Variable Name for ISH update. (The variable name is ignored in ISH update function)

+//

+#define ISH_VAR_NAME  L"IshVar"

+

+#define MAX_SLOT_NUM  2

+#define SLOT_A        0

+#define SLOT_B        1

+

+#define EFS_LOCATION  0x20000

+

+#endif

--

2.31.1





-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114071): https://edk2.groups.io/g/devel/message/114071
Mute This Topic: https://groups.io/mt/103831194/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-