public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Chang, Abner via groups.io" <abner.chang=amd.com@groups.io>
To: "Zhai, MingXin (Duke)" <duke.zhai@amd.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Zhai, MingXin (Duke)" <duke.zhai@amd.com>,
	"Xing, Eric" <Eric.Xing@amd.com>,
	"Fu, Igniculus" <Igniculus.Fu@amd.com>
Subject: Re: [edk2-devel] [PATCH 03/33] AMD/VanGoghBoard: Check in Capsule update
Date: Tue, 23 Jan 2024 04:42:28 +0000	[thread overview]
Message-ID: <LV8PR12MB94527F685A7C9ACFF7C979BBEA742@LV8PR12MB9452.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20240118065046.961-4-duke.zhai@amd.com>

[AMD Official Use Only - General]

I have concern of keeping Intel's old tianocore licensing. I don't see any Intel's files those still have the old one. I think we have to remove it and have below line above or below AMD's copyright.
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>

Please also check if Intel updated the copyright year in the original file.

Thanks
Abner


> -----Original Message-----
> From: duke.zhai@amd.com <duke.zhai@amd.com>
> Sent: Thursday, January 18, 2024 2:50 PM
> To: devel@edk2.groups.io
> Cc: Zhai, MingXin (Duke) <duke.zhai@amd.com>; Xing, Eric
> <Eric.Xing@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>; Chang, Abner
> <Abner.Chang@amd.com>
> Subject: [PATCH 03/33] AMD/VanGoghBoard: Check in Capsule update
>
> From: Duke Zhai <Duke.Zhai@amd.com>
>
>
> BZ #:4640
>
> Chachani board supports "Capsule on Disk (CoD)" feature defined in UEFI
>
> Spec chapter 8.5.5 "Delivery of Capsules via file on Mass Storage Device".
>
> The BIOS capsule image is saved in hard disk as default setting.
>
>
>
> Signed-off-by: Ken Yao <ken.yao@amd.com>
>
> Cc: Duke Zhai <duke.zhai@amd.com>
>
> Cc: Eric Xing <eric.xing@amd.com>
>
> Cc: Igniculus Fu <igniculus.fu@amd.com>
>
> Cc: Abner Chang <abner.chang@amd.com>
>
> ---
>
>  .../SystemFirmwareDescriptor.aslc             |   99 ++
>
>  .../SystemFirmwareDescriptor.inf              |   53 +
>
>  .../SystemFirmwareDescriptorPei.c             |   78 ++
>
>  .../Include/Library/CapsuleHookLib.h          |   40 +
>
>  .../Capsule/CapsuleHookLib/CapsuleHookLib.c   | 1153
> +++++++++++++++++
>
>  .../Capsule/CapsuleHookLib/CapsuleHookLib.inf |   56 +
>
>  .../PlatformBootManager.c                     |  803 ++++++++++++
>
>  .../PlatformBootManager.h                     |  159 +++
>
>  .../PlatformBootManagerLib.inf                |   96 ++
>
>  .../PlatformBootManagerLib/PlatformConsole.c  |  504 +++++++
>
>  .../PlatformBootManagerLib/PlatformConsole.h  |   78 ++
>
>  .../PlatformBootManagerLib/PlatformData.c     |   48 +
>
>  .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf   |  122 ++
>
>  .../CapsuleRuntimeDxe/CapsuleService.c        |  470 +++++++
>
>  .../CapsuleRuntimeDxe/CapsuleService.h        |   82 ++
>
>  15 files changed, 3841 insertions(+)
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmware
> Descriptor/SystemFirmwareDescriptor.aslc
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmware
> Descriptor/SystemFirmwareDescriptor.inf
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmware
> Descriptor/SystemFirmwareDescriptorPei.c
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/CapsuleH
> ookLib.h
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleH
> ookLib/CapsuleHookLib.c
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleH
> ookLib/CapsuleHookLib.inf
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platform
> BootManagerLib/PlatformBootManager.c
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platform
> BootManagerLib/PlatformBootManager.h
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platform
> BootManagerLib/PlatformBootManagerLib.inf
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platform
> BootManagerLib/PlatformConsole.c
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platform
> BootManagerLib/PlatformConsole.h
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platform
> BootManagerLib/PlatformData.c
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/Ca
> psuleRuntimeDxe/CapsuleRuntimeDxe.inf
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/Ca
> psuleRuntimeDxe/CapsuleService.c
>
>  create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/Ca
> psuleRuntimeDxe/CapsuleService.h
>
>
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwa
> reDescriptor/SystemFirmwareDescriptor.aslc
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwa
> reDescriptor/SystemFirmwareDescriptor.aslc
>
> new file mode 100644
>
> index 0000000000..af73e846fc
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwa
> reDescriptor/SystemFirmwareDescriptor.aslc
>
> @@ -0,0 +1,99 @@
>
> +/** @file
>
> +  System firmware Descriptor file
>
> +
>
> +  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 descriptor.
>
> +
>
> +  Copyright (c) 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 <PiPei.h>
>
> +#include <Protocol/FirmwareManagement.h>
>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
>
> +
>
> +#define PACKAGE_VERSION                     0xFFFFFFFF
>
> +#define PACKAGE_VERSION_STRING              L"Unknown"
>
> +
>
> +#define CURRENT_FIRMWARE_VERSION            0x00003818
>
> +#define CURRENT_FIRMWARE_VERSION_STRING     L"00003818"
>
> +#define LOWEST_SUPPORTED_FIRMWARE_VERSION   0x00000001
>
> +
>
> +#define IMAGE_ID                            SIGNATURE_64('C', 'H', 'A', 'C', 'H', 'A','N','I')
>
> +#define IMAGE_ID_STRING                     L"ChachaniFD"
>
> +
>
> +// PcdSystemFmpCapsuleImageTypeIdGuid
>
> +#define IMAGE_TYPE_ID_GUID                  { 0x38663fe6, 0x934f, 0x42a1,
> { 0xbc, 0xb0, 0xf7, 0x9e, 0x62, 0xec, 0xbe, 0x80 } }
>
> +
>
> +typedef struct {
>
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  Descriptor;
>
> +  // real string data
>
> +  CHAR16
> ImageIdNameStr[sizeof(IMAGE_ID_STRING)/sizeof(CHAR16)];
>
> +  CHAR16
> VersionNameStr[sizeof(CURRENT_FIRMWARE_VERSION_STRING)/sizeof(CHA
> R16)];
>
> +  CHAR16
> PackageVersionNameStr[sizeof(PACKAGE_VERSION_STRING)/sizeof(CHAR16)
> ];
>
> +} IMAGE_DESCRIPTOR;
>
> +
>
> +IMAGE_DESCRIPTOR mImageDescriptor =
>
> +{
>
> +  {
>
> +    EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE,
>
> +    sizeof(EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR),
>
> +    sizeof(IMAGE_DESCRIPTOR),
>
> +    PACKAGE_VERSION,                                       // PackageVersion
>
> +    OFFSET_OF (IMAGE_DESCRIPTOR, PackageVersionNameStr),   //
> PackageVersionName
>
> +    1,                                                     // ImageIndex;
>
> +    {0x0},                                                 // Reserved
>
> +    IMAGE_TYPE_ID_GUID,                                    // ImageTypeId;
>
> +    IMAGE_ID,                                              // ImageId;
>
> +    OFFSET_OF (IMAGE_DESCRIPTOR, ImageIdNameStr),          //
> ImageIdName;
>
> +    CURRENT_FIRMWARE_VERSION,                              // Version;
>
> +    OFFSET_OF (IMAGE_DESCRIPTOR, VersionNameStr),          // VersionName;
>
> +    {0x0},                                                 // Reserved2
>
> +    FixedPcdGet32(PcdFlashAreaSize),                       // Size;
>
> +    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
>
> +      IMAGE_ATTRIBUTE_RESET_REQUIRED |
>
> +      IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
>
> +      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSupported;
>
> +    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
>
> +      IMAGE_ATTRIBUTE_RESET_REQUIRED |
>
> +      IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
>
> +      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSetting;
>
> +    0x0,                                                   // Compatibilities;
>
> +    LOWEST_SUPPORTED_FIRMWARE_VERSION,                     //
> LowestSupportedImageVersion;
>
> +    0x00000000,                                            // LastAttemptVersion;
>
> +    0,                                                     // LastAttemptStatus;
>
> +    {0x0},                                                 // Reserved3
>
> +    0,                                                     // HardwareInstance;
>
> +  },
>
> +  // real string data
>
> +  {IMAGE_ID_STRING},
>
> +  {CURRENT_FIRMWARE_VERSION_STRING},
>
> +  {PACKAGE_VERSION_STRING},
>
> +};
>
> +
>
> +
>
> +VOID*
>
> +ReferenceAcpiTable (
>
> +  VOID
>
> +  )
>
> +{
>
> +  //
>
> +  // Reference the table being generated to prevent the optimizer from
>
> +  // removing the data structure from the executable
>
> +  //
>
> +  return (VOID*)&mImageDescriptor;
>
> +}
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwa
> reDescriptor/SystemFirmwareDescriptor.inf
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwa
> reDescriptor/SystemFirmwareDescriptor.inf
>
> new file mode 100644
>
> index 0000000000..28d0b8f644
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwa
> reDescriptor/SystemFirmwareDescriptor.inf
>
> @@ -0,0 +1,53 @@
>
> +## @file
>
> +#  System firmware descriptor INF file
>
> +#
>
> +# 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 descriptor.
>
> +#
>
> +#  Copyright (c) 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.
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> +  INF_VERSION                    = 0x00010005
>
> +  BASE_NAME                      = SystemFirmwareDescriptor
>
> +  FILE_GUID                      = 90B2B846-CA6D-4D6E-A8D3-C140A8E110AC
>
> +  MODULE_TYPE                    = PEIM
>
> +  VERSION_STRING                 = 1.0
>
> +  ENTRY_POINT                    = SystemFirmwareDescriptorPeimEntry
>
> +
>
> +[Sources]
>
> +  SystemFirmwareDescriptorPei.c
>
> +  SystemFirmwareDescriptor.aslc
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +  SignedCapsulePkg/SignedCapsulePkg.dec
>
> +  ChachaniBoardPkg/Project.dec
>
> +
>
> +[LibraryClasses]
>
> +  PcdLib
>
> +  PeiServicesLib
>
> +  DebugLib
>
> +  PeimEntryPoint
>
> +
>
> +[Pcd]
>
> +
> gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescript
> or
>
> +  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
>
> +
>
> +[Depex]
>
> +  TRUE
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwa
> reDescriptor/SystemFirmwareDescriptorPei.c
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwa
> reDescriptor/SystemFirmwareDescriptorPei.c
>
> new file mode 100644
>
> index 0000000000..2413854577
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwa
> reDescriptor/SystemFirmwareDescriptorPei.c
>
> @@ -0,0 +1,78 @@
>
> +/** @file
>
> +  Implements SystemFirmwareDescriptorPei.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
>
> +  System Firmware descriptor producer.
>
> +
>
> +  Copyright (c) 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 <PiPei.h>
>
> +#include <Library/PcdLib.h>
>
> +#include <Library/PeiServicesLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Protocol/FirmwareManagement.h>
>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
>
> +
>
> +/**
>
> +  Entrypoint for SystemFirmwareDescriptor PEIM.
>
> +
>
> +  @param[in]  FileHandle  Handle of the file being invoked.
>
> +  @param[in]  PeiServices Describes the list of possible PEI Services.
>
> +
>
> +  @retval EFI_SUCCESS            PPI successfully installed.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SystemFirmwareDescriptorPeimEntry (
>
> +  IN EFI_PEI_FILE_HANDLE     FileHandle,
>
> +  IN CONST EFI_PEI_SERVICES  **PeiServices
>
> +  )
>
> +{
>
> +  EFI_STATUS                              Status;
>
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  *Descriptor;
>
> +  UINTN                                   Size;
>
> +  UINTN                                   Index;
>
> +  UINT32                                  AuthenticationStatus;
>
> +
>
> +  //
>
> +  // Search RAW section.
>
> +  //
>
> +  Index = 0;
>
> +  while (TRUE) {
>
> +    Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Index,
> FileHandle, (VOID **)&Descriptor, &AuthenticationStatus);
>
> +    if (EFI_ERROR (Status)) {
>
> +      // Should not happen, must something wrong in FDF.
>
> +      ASSERT (FALSE);
>
> +      return EFI_NOT_FOUND;
>
> +    }
>
> +
>
> +    if (Descriptor->Signature ==
> EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE) {
>
> +      break;
>
> +    }
>
> +
>
> +    Index++;
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR
> size - 0x%x\n", Descriptor->Length));
>
> +
>
> +  Size = Descriptor->Length;
>
> +  PcdSetPtrS (PcdEdkiiSystemFirmwareImageDescriptor, &Size, Descriptor);
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/Capsule
> HookLib.h
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/Capsule
> HookLib.h
>
> new file mode 100644
>
> index 0000000000..e573ac0f09
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/Capsule
> HookLib.h
>
> @@ -0,0 +1,40 @@
>
> +/** @file
>
> +  Implements CapsuleHookLib.h
>
> +
>
> +  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#ifndef _CAPSULE_HOOK_LIB_H_
>
> +#define _CAPSULE_HOOK_LIB_H_
>
> +
>
> +/**
>
> +  Detect Capsule file from ESP partition and update capsule.
>
> +
>
> +  @retval EFI_SUCCESS.              Opertion is successful.
>
> +  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate.
>
> +  @retval EFI_ERROR                 Internal error when update Capsule.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +CapsuleUpdateViaFileHook (
>
> +  VOID
>
> +  );
>
> +
>
> +/**
>
> +  Detect Capsule file from ESP partition and update capsule.
>
> +
>
> +  @retval EFI_SUCCESS.              Opertion is successful.
>
> +  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate.
>
> +  @retval EFI_ERROR                 Internal error when update Capsule.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +CapsuleUpdateViaFileLib (
>
> +  VOID
>
> +  );
>
> +
>
> +#endif
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Capsul
> eHookLib/CapsuleHookLib.c
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Capsul
> eHookLib/CapsuleHookLib.c
>
> new file mode 100644
>
> index 0000000000..b4513514b8
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Capsul
> eHookLib/CapsuleHookLib.c
>
> @@ -0,0 +1,1153 @@
>
> +/** @file
>
> +  Implements CapsuleHookLib.c
>
> +
>
> +  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Uefi.h>
>
> +#include <PiDxe.h>
>
> +#include <Guid/Gpt.h>
>
> +#include <Guid/FileSystemInfo.h>
>
> +#include <Protocol/SimpleFileSystem.h>
>
> +#include <Protocol/BlockIo.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/FileHandleLib.h>
>
> +#include <Library/DevicePathLib.h>
>
> +#include <Library/CapsuleLib.h>
>
> +#include <Library/CapsuleHookLib.h>
>
> +#include <OtaCapsuleUpdate.h>
>
> +
>
> +#define CAP_FILE_NAME  (CHAR16 *) FixedPcdGetPtr (PcdOtaCapsuleName)
>
> +#define CAP_PARTITION  (CHAR16 *) FixedPcdGetPtr
> (PcdOtaCapsulePartitionName)
>
> +CHAR16                    mPartitionName[36];
>
> +STATIC CONST CHAR16       *mSlotSuffixes[2] = { L"_a", L"_b" };
>
> +EFI_DEVICE_PATH_PROTOCOL  *mBootDevicePath;
>
> +
>
> +#define FLASH_DEVICE_PATH_SIZE(DevPath)  (GetDevicePathSize (DevPath) -
> sizeof (EFI_DEVICE_PATH_PROTOCOL))
>
> +
>
> +// Hidden (Not exported) function from DxeCapsuleReportLib.
>
> +extern
>
> +EFI_STATUS
>
> +// Not EFIAPI!
>
> +RecordCapsuleStatusVariable (
>
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
>
> +  IN EFI_STATUS          CapsuleStatus
>
> +  );
>
> +
>
> +/**
>
> +  Read GPT partition entries.
>
> +
>
> +  @param[in]  BlockIo             The BlockIo of device.
>
> +  @param[out] PartitionEntries    The output buffer of partition entry.
>
> +
>
> +  @retval EFI_SUCCESS             Operation completed successfully.
>
> +  @retval others                  Some error occurs when executing this routine.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ReadPartitionEntries (
>
> +  IN EFI_BLOCK_IO_PROTOCOL  *BlockIo,
>
> +  OUT EFI_PARTITION_ENTRY   **PartitionEntries
>
> +  )
>
> +{
>
> +  EFI_STATUS                  Status;
>
> +  UINTN                       EntrySize;
>
> +  UINTN                       NumEntries;
>
> +  UINTN                       BufferSize;
>
> +  UINT32                      MediaId;
>
> +  EFI_PARTITION_TABLE_HEADER  *GptHeader;
>
> +
>
> +  MediaId = BlockIo->Media->MediaId;
>
> +
>
> +  //
>
> +  // Read size of Partition entry and number of entries from GPT header
>
> +  //
>
> +  GptHeader = AllocatePool (BlockIo->Media->BlockSize);
>
> +  if (GptHeader == NULL) {
>
> +    return EFI_OUT_OF_RESOURCES;
>
> +  }
>
> +
>
> +  Status = BlockIo->ReadBlocks (
>
> +                      BlockIo,
>
> +                      MediaId,
>
> +                      PRIMARY_PART_HEADER_LBA,
>
> +                      BlockIo->Media->BlockSize,
>
> +                      (VOID *)GptHeader
>
> +                      );
>
> +  if (EFI_ERROR (Status)) {
>
> +    FreePool (GptHeader);
>
> +    return Status;
>
> +  }
>
> +
>
> +  //
>
> +  // Check there is a GPT on the media
>
> +  //
>
> +  if ((GptHeader->Header.Signature != EFI_PTAB_HEADER_ID) || (GptHeader-
> >MyLBA != PRIMARY_PART_HEADER_LBA)) {
>
> +    DEBUG ((DEBUG_ERROR, "No valid GPT found!\n"));
>
> +    FreePool (GptHeader);
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  EntrySize  = GptHeader->SizeOfPartitionEntry;
>
> +  NumEntries = GptHeader->NumberOfPartitionEntries;
>
> +  if ((EntrySize == 0) || (NumEntries == 0)) {
>
> +    DEBUG ((DEBUG_ERROR, "Invalid Entry size or number.\n"));
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  FreePool (GptHeader);
>
> +
>
> +  BufferSize        = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media-
> >BlockSize);
>
> +  *PartitionEntries = AllocatePool (BufferSize);
>
> +  if (PartitionEntries == NULL) {
>
> +    return EFI_OUT_OF_RESOURCES;
>
> +  }
>
> +
>
> +  Status = BlockIo->ReadBlocks (
>
> +                      BlockIo,
>
> +                      MediaId,
>
> +                      2,
>
> +                      BufferSize,
>
> +                      (VOID *)*PartitionEntries
>
> +                      );
>
> +  if (EFI_ERROR (Status)) {
>
> +    FreePool (*PartitionEntries);
>
> +    return Status;
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  Get capsule partition device path by partition name.
>
> +
>
> +  @param[in]  BootDevicePath      Pointer to the Device Path Protocol from
> variable.
>
> +  @param[in]  PartitionName       The given partition name.
>
> +  @param[out] PartitionDevicePath Pointer to the Device Path Protocol of
> capsule partition.
>
> +
>
> +  @retval EFI_SUCCESS             Operation completed successfully.
>
> +  @retval others                  Some error occurs when executing this routine.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetDevicePathByName (
>
> +  IN  EFI_DEVICE_PATH_PROTOCOL  *BootDevicePath,
>
> +  IN  CONST CHAR16              *PartitionName,
>
> +  OUT EFI_DEVICE_PATH_PROTOCOL  **PartitionDevicePath
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
>
> +  EFI_BLOCK_IO_PROTOCOL     *BlockIo;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *NextNode;
>
> +  HARDDRIVE_DEVICE_PATH     *PartitionNode;
>
> +  EFI_PARTITION_ENTRY       *PartitionEntries;
>
> +  UINTN                     NumHandles;
>
> +  UINTN                     LoopIndex;
>
> +  EFI_HANDLE                *AllHandles;
>
> +  EFI_HANDLE                Handle;
>
> +
>
> +  //
>
> +  // Get all BlockIo handles in system
>
> +  //
>
> +  Status = gBS->LocateHandleBuffer (
>
> +                  ByProtocol,
>
> +                  &gEfiBlockIoProtocolGuid,
>
> +                  NULL,
>
> +                  &NumHandles,
>
> +                  &AllHandles
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Couldn't locate BlockIo protocol: %r\n",
> Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
>
> +    Status = gBS->OpenProtocol (
>
> +                    AllHandles[LoopIndex],
>
> +                    &gEfiDevicePathProtocolGuid,
>
> +                    (VOID **)&DevicePath,
>
> +                    gImageHandle,
>
> +                    NULL,
>
> +                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> +                    );
>
> +    if (EFI_ERROR (Status)) {
>
> +      DEBUG ((DEBUG_ERROR, "Couldn't locate DevicePath protocol: %r\n",
> Status));
>
> +      return Status;
>
> +    }
>
> +
>
> +    if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE
> (BootDevicePath))) {
>
> +      BootDevicePath = DevicePath;
>
> +      break;
>
> +    }
>
> +  }
>
> +
>
> +  DevicePath = BootDevicePath;
>
> +  Status     = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePath,
> &Handle);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Couldn't locate device status: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->OpenProtocol (
>
> +                  Handle,
>
> +                  &gEfiBlockIoProtocolGuid,
>
> +                  (VOID **)&BlockIo,
>
> +                  gImageHandle,
>
> +                  NULL,
>
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Failed to get BlockIo: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = ReadPartitionEntries (BlockIo, &PartitionEntries);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Failed to read partitions from disk device: %r\n",
> Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
>
> +    Status = gBS->OpenProtocol (
>
> +                    AllHandles[LoopIndex],
>
> +                    &gEfiDevicePathProtocolGuid,
>
> +                    (VOID **)&DevicePath,
>
> +                    gImageHandle,
>
> +                    NULL,
>
> +                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> +                    );
>
> +    if (EFI_ERROR (Status)) {
>
> +      DEBUG ((DEBUG_ERROR, "Couldn't locate DevicePath protocol: %r\n",
> Status));
>
> +      return Status;
>
> +    }
>
> +
>
> +    if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE
> (BootDevicePath))) {
>
> +      NextNode = NextDevicePathNode (DevicePath);
>
> +
>
> +      while (!IsDevicePathEndType (NextNode)) {
>
> +        if ((NextNode->Type == MEDIA_DEVICE_PATH) &&
>
> +            (NextNode->SubType == MEDIA_HARDDRIVE_DP))
>
> +        {
>
> +          break;
>
> +        }
>
> +
>
> +        NextNode = NextDevicePathNode (NextNode);
>
> +      }
>
> +
>
> +      if (IsDevicePathEndType (NextNode)) {
>
> +        continue;
>
> +      }
>
> +
>
> +      PartitionNode = (HARDDRIVE_DEVICE_PATH *)NextNode;
>
> +
>
> +      if (PartitionNode->PartitionNumber == 0) {
>
> +        continue;
>
> +      }
>
> +
>
> +      if (0 == StrCmp (PartitionEntries[PartitionNode->PartitionNumber -
> 1].PartitionName, PartitionName)) {
>
> +        break;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  if (LoopIndex >= NumHandles) {
>
> +    return EFI_LOAD_ERROR;
>
> +  }
>
> +
>
> +  *PartitionDevicePath = DevicePath;
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Get capsule paritioin information.
>
> +
>
> +  @param[in]  VOID
>
> +
>
> +  @retval EFI_SUCCESS             Operation completed successfully.
>
> +  @retval others                  Some error occurs when executing this routine.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +CapsulePartitionInfo (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS          Status;
>
> +  UINTN               VarSize;
>
> +  OTA_CAPSULE_UPDATE  OtaCapsuleUpdateVal;
>
> +  CHAR16              BootPath[512];
>
> +
>
> +  //
>
> +  // Get Capsule A/B partition.
>
> +  //
>
> +  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, "CapsulePartitionInfo: GetVariable failed: %r\n",
> Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  ZeroMem (mPartitionName, sizeof (mPartitionName));
>
> +  StrCpyS (mPartitionName, sizeof (mPartitionName), CAP_PARTITION);
>
> +  StrCatS (mPartitionName, sizeof (mPartitionName),
> mSlotSuffixes[OtaCapsuleUpdateVal.UpdateSlot]);
>
> +  DEBUG ((DEBUG_INFO, "CapsulePartitionInfo from partition: %s\n",
> mPartitionName));
>
> +
>
> +  //
>
> +  // Get Boot device path
>
> +  //
>
> +  VarSize = 512;
>
> +  Status  = gRT->GetVariable (
>
> +                   L"AndroidBootDevice",
>
> +                   &gEfiGlobalVariableGuid,
>
> +                   NULL,
>
> +                   &VarSize,
>
> +                   BootPath
>
> +                   );
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "CapsulePartitionInfo: Get BootDevice variable
> failed: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  mBootDevicePath = ConvertTextToDevicePath (BootPath);
>
> +  if (mBootDevicePath == NULL) {
>
> +    DEBUG ((DEBUG_ERROR, "mBootDevicePath is NULL\n"));
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Read Capsule file information from FAT partiton.
>
> +
>
> +  @param[in]  FileName              File name of Capsule binary
>
> +  @param[out] Buffer                Return buffer pointer of Capsule binary
>
> +  @param[out] BufferSize            Capsule binary size
>
> +
>
> +  @retval EFI_SUCCESS               Read Capsule information successfully
>
> +  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate
>
> +  @retval EFI_NOT_FOUND             Fail to read Capsule information
>
> +  @retval Others                    Internal error when read Capsule information
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ReadCapsuleInfo (
>
> +  IN CHAR16  *FileName,
>
> +  OUT VOID   **Buffer,
>
> +  OUT UINTN  *BufferSize
>
> +  )
>
> +{
>
> +  EFI_STATUS                       Status;
>
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
>
> +  EFI_FILE                         *Root;
>
> +  EFI_FILE                         *FileHandle;
>
> +  UINT8                            *FileBuffer;
>
> +  UINTN                            FileSize;
>
> +  EFI_HANDLE                       Handle;
>
> +  EFI_BLOCK_IO_PROTOCOL            *BlockIo;
>
> +  EFI_DEVICE_PATH_PROTOCOL         *BootPartitionPath;
>
> +
>
> +  FileBuffer = NULL;
>
> +  FileSize   = 0;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "ReadCapsuleInfo()...\n"));
>
> +
>
> +  Status = GetDevicePathByName (mBootDevicePath, mPartitionName,
> &BootPartitionPath);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid,
> &BootPartitionPath, &Handle);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  //
>
> +  // Get Capsule file
>
> +  //
>
> +  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID
> **)&BlockIo);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  if (BlockIo->Media->RemovableMedia) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&Fs);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = Fs->OpenVolume (Fs, &Root);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ,
> 0);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  if (FileHandle == NULL) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  Status = FileHandleGetSize (FileHandle, (UINT64 *)&FileSize);
>
> +  if (EFI_ERROR (Status)) {
>
> +    FileHandleClose (FileHandle);
>
> +    return Status;
>
> +  }
>
> +
>
> +  FileBuffer = AllocateZeroPool (FileSize);
>
> +  if (FileBuffer == NULL) {
>
> +    FileHandleClose (FileHandle);
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = FileHandleRead (FileHandle, &FileSize, FileBuffer);
>
> +  if (EFI_ERROR (Status)) {
>
> +    FileHandleClose (FileHandle);
>
> +    FreePool (FileBuffer);
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = FileHandleClose (FileHandle);
>
> +  if (EFI_ERROR (Status)) {
>
> +    FreePool (FileBuffer);
>
> +    return Status;
>
> +  }
>
> +
>
> +  *Buffer     = FileBuffer;
>
> +  *BufferSize = FileSize;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "Capsule size: 0x%x\n", *BufferSize));
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Remove capsule file from FAT partitions.
>
> +
>
> +  @param[in]  FileName              File name of Capsule binary
>
> +
>
> +  @retval EFI_SUCCESS               Delete capsule succesfully
>
> +  @retval Others                    Internal error of delete capsule function
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RemoveCapsuleFile (
>
> +  IN CHAR16  *FileName
>
> +  )
>
> +{
>
> +  EFI_STATUS                       Status;
>
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
>
> +  EFI_FILE                         *Root;
>
> +  EFI_FILE                         *FileHandle;
>
> +  EFI_HANDLE                       Handle;
>
> +  EFI_BLOCK_IO_PROTOCOL            *BlockIo;
>
> +  EFI_DEVICE_PATH_PROTOCOL         *BootPartitionPath;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "RemoveCapsuleFile()...\n"));
>
> +
>
> +  Status = GetDevicePathByName (mBootDevicePath, mPartitionName,
> &BootPartitionPath);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid,
> &BootPartitionPath, &Handle);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  //
>
> +  // Remove Capsule file
>
> +  //
>
> +  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID
> **)&BlockIo);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  if (BlockIo->Media->RemovableMedia) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&Fs);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = Fs->OpenVolume (Fs, &Root);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ |
> EFI_FILE_MODE_WRITE, 0);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  if (FileHandle == NULL) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  Status = FileHandleDelete (FileHandle);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Passes and processes the capsule file.
>
> +
>
> +  @param  CapsuleHeaderArray    Virtual pointer to an array of virtual
> pointers to the capsules
>
> +                                being passed into update capsule.
>
> +  @param  CapsuleCount          Number of pointers to EFI_CAPSULE_HEADER
> in CaspuleHeaderArray.
>
> +
>
> +  @retval EFI_SUCCESS           Valid capsule was passed.
>
> +  @retval others                Some error occurs when executing this routine.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UpdateCapsule (
>
> +  IN EFI_CAPSULE_HEADER  **CapsuleHeaderArray,
>
> +  IN UINTN               CapsuleCount
>
> +  )
>
> +{
>
> +  UINTN               ArrayNumber;
>
> +  EFI_STATUS          Status;
>
> +  EFI_CAPSULE_HEADER  *CapsuleHeader;
>
> +
>
> +  //
>
> +  // Capsule Count can't be less than one.
>
> +  //
>
> +  if (CapsuleCount < 1) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  CapsuleHeader = NULL;
>
> +
>
> +  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
>
> +    //
>
> +    // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
> flag must have
>
> +    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
>
> +    //
>
> +    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
>
> +    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET |
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) ==
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
>
> +      return EFI_INVALID_PARAMETER;
>
> +    }
>
> +
>
> +    //
>
> +    // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must
> have
>
> +    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
>
> +    //
>
> +    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET |
> CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
>
> +      return EFI_INVALID_PARAMETER;
>
> +    }
>
> +
>
> +    // FIXME: The CoD Image CANNOT BE RELOADED as Memory capsule.
>
> +    //
>
> +    // Check FMP capsule flag
>
> +    //
>
> +    if (  CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)
>
> +       && ((CapsuleHeader->Flags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0))
>
> +    {
>
> +      return EFI_INVALID_PARAMETER;
>
> +    }
>
> +
>
> +    //
>
> +    // Check Capsule image without populate flag by firmware support capsule
> function
>
> +    //
>
> +    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)
> == 0) {
>
> +      Status = SupportCapsuleImage (CapsuleHeader);
>
> +      if (EFI_ERROR (Status)) {
>
> +        return Status;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  //
>
> +  // Walk through all capsules, record whether there is a capsule needs reset
>
> +  // or initiate reset. And then process capsules which has no reset flag
> directly.
>
> +  //
>
> +  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
>
> +    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
>
> +    //
>
> +    // Here should be in the boot-time for non-reset capsule image
>
> +    // Platform specific update for the non-reset capsule image.
>
> +    //
>
> +
>
> +    // FIXME: The CoD Image CANNOT BE RELOADED as Memory capsule.
>
> +    if (((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) ==
> 0) || TRUE) {
>
> +      Status = ProcessCapsuleImage (CapsuleHeader);
>
> +      if (EFI_ERROR (Status)) {
>
> +        return Status;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Detect Capsule file from ESP partition and update capsule.
>
> +
>
> +  @retval EFI_SUCCESS               Opertion is successful.
>
> +  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate.
>
> +  @retval EFI_ERROR                 Internal error when update Capsule.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +CapsuleUpdateViaFileHook (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS          Status;
>
> +  UINT8               *CapsuleBuffer;
>
> +  UINTN               CapsuleSize;
>
> +  EFI_CAPSULE_HEADER  *CapsuleHeader;
>
> +  UINTN               CapsuleNum;
>
> +
>
> +  CapsuleBuffer = NULL;
>
> +  CapsuleSize   = 0;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "CapsuleUpdateViaFileHook() Entry Point...\n"));
>
> +
>
> +  Status = CapsulePartitionInfo ();
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "CapsulePartitionInfo failed: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = ReadCapsuleInfo (CAP_FILE_NAME, (VOID **)&CapsuleBuffer,
> &CapsuleSize);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Read Capsule file failed. Status: %r\n", Status));
>
> +    if (CapsuleBuffer != NULL) {
>
> +      FreePool (CapsuleBuffer);
>
> +    }
>
> +
>
> +    return Status;
>
> +  }
>
> +
>
> +  CapsuleHeader = (EFI_CAPSULE_HEADER *)CapsuleBuffer;
>
> +  CapsuleNum    = 1;
>
> +
>
> +  Status = UpdateCapsule (&CapsuleHeader, CapsuleNum);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Failed to update capsule. Status: %r\n", Status));
>
> +  }
>
> +
>
> +  if (CapsuleBuffer != NULL) {
>
> +    FreePool (CapsuleBuffer);
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "Capsule update via file completed, reset
> system...\n"));
>
> +
>
> +  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Get capsule partition device path by partition name.
>
> +
>
> +  @param[in]  BootDevicePath      Pointer to the Device Path Protocol from
> variable.
>
> +  @param[in]  PartitionName       The given partition name.
>
> +  @param[out] PartitionDevicePath Pointer to the Device Path Protocol of
> capsule partition.
>
> +
>
> +  @retval EFI_SUCCESS             Operation completed successfully.
>
> +  @retval others                  Some error occurs when executing this routine.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetDevicePathByBoot (
>
> +  IN  EFI_DEVICE_PATH_PROTOCOL  *BootDevicePath,
>
> +  OUT EFI_DEVICE_PATH_PROTOCOL  **PartitionDevicePath
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
>
> +  EFI_BLOCK_IO_PROTOCOL     *BlockIo;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *NextNode;
>
> +  UINTN                     NumHandles;
>
> +  UINTN                     LoopIndex;
>
> +  EFI_HANDLE                *AllHandles;
>
> +  EFI_HANDLE                Handle;
>
> +
>
> +  //
>
> +  // Get all BlockIo handles in system
>
> +  //
>
> +  Status = gBS->LocateHandleBuffer (
>
> +                  ByProtocol,
>
> +                  &gEfiBlockIoProtocolGuid,
>
> +                  NULL,
>
> +                  &NumHandles,
>
> +                  &AllHandles
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Couldn't locate BlockIo protocol: %r\n",
> Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
>
> +    Status = gBS->OpenProtocol (
>
> +                    AllHandles[LoopIndex],
>
> +                    &gEfiDevicePathProtocolGuid,
>
> +                    (VOID **)&DevicePath,
>
> +                    gImageHandle,
>
> +                    NULL,
>
> +                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> +                    );
>
> +    if (EFI_ERROR (Status)) {
>
> +      DEBUG ((DEBUG_ERROR, "Couldn't locate DevicePath protocol: %r\n",
> Status));
>
> +      return Status;
>
> +    }
>
> +
>
> +    if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE
> (BootDevicePath))) {
>
> +      BootDevicePath = DevicePath;
>
> +      break;
>
> +    }
>
> +  }
>
> +
>
> +  DevicePath = BootDevicePath;
>
> +  Status     = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePath,
> &Handle);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Couldn't locate device status: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->OpenProtocol (
>
> +                  Handle,
>
> +                  &gEfiBlockIoProtocolGuid,
>
> +                  (VOID **)&BlockIo,
>
> +                  gImageHandle,
>
> +                  NULL,
>
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Failed to get BlockIo: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
>
> +    Status = gBS->OpenProtocol (
>
> +                    AllHandles[LoopIndex],
>
> +                    &gEfiDevicePathProtocolGuid,
>
> +                    (VOID **)&DevicePath,
>
> +                    gImageHandle,
>
> +                    NULL,
>
> +                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> +                    );
>
> +    if (EFI_ERROR (Status)) {
>
> +      DEBUG ((DEBUG_ERROR, "Couldn't locate DevicePath protocol: %r\n",
> Status));
>
> +      return Status;
>
> +    }
>
> +
>
> +    if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE
> (BootDevicePath))) {
>
> +      NextNode = NextDevicePathNode (DevicePath);
>
> +
>
> +      while (!IsDevicePathEndType (NextNode)) {
>
> +        if ((NextNode->Type == MEDIA_DEVICE_PATH) &&
>
> +            (NextNode->SubType == MEDIA_HARDDRIVE_DP))
>
> +        {
>
> +          break;
>
> +        }
>
> +
>
> +        NextNode = NextDevicePathNode (NextNode);
>
> +      }
>
> +
>
> +      if (IsDevicePathEndType (NextNode)) {
>
> +        continue;
>
> +      }
>
> +
>
> +      break;
>
> +    }
>
> +  }
>
> +
>
> +  if (LoopIndex >= NumHandles) {
>
> +    return EFI_LOAD_ERROR;
>
> +  }
>
> +
>
> +  *PartitionDevicePath = DevicePath;
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Get capsule paritioin information.
>
> +
>
> +  @param[in]  VOID
>
> +
>
> +  @retval EFI_SUCCESS             Operation completed successfully.
>
> +  @retval others                  Some error occurs when executing this routine.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +CapsulePathInfo (
>
> +  VOID
>
> +  )
>
> +{
>
> +  mBootDevicePath = ConvertTextToDevicePath ((CHAR16 *)PcdGetPtr
> (PcdNVMeDevicePath));
>
> +
>
> +  if (mBootDevicePath == NULL) {
>
> +    DEBUG ((DEBUG_ERROR, "mBootDevicePath is NULL\n"));
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Read Capsule file information from FAT partiton.
>
> +
>
> +  @param[in]  FileName              File name of Capsule binary
>
> +  @param[out] Buffer                Return buffer pointer of Capsule binary
>
> +  @param[out] BufferSize            Capsule binary size
>
> +
>
> +  @retval EFI_SUCCESS               Read Capsule information successfully
>
> +  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate
>
> +  @retval EFI_NOT_FOUND             Fail to read Capsule information
>
> +  @retval Others                    Internal error when read Capsule information
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +IterateAllCapsulesFromDisk (
>
> +  IN CHAR16    *FileBaseName,
>
> +  OUT VOID     **Buffer,
>
> +  OUT UINTN    *BufferSize,
>
> +  OUT BOOLEAN  *NoNextFile
>
> +  )
>
> +{
>
> +  EFI_STATUS                       Status;
>
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
>
> +  EFI_FILE                         *Root;
>
> +  EFI_FILE                         *DirHandle;
>
> +  EFI_FILE                         *FileHandle;
>
> +  EFI_FILE_INFO                    *FileInfo;
>
> +  UINT8                            *FileBuffer;
>
> +  EFI_HANDLE                       Handle;
>
> +  EFI_BLOCK_IO_PROTOCOL            *BlockIo;
>
> +  EFI_DEVICE_PATH_PROTOCOL         *BootPartitionPath;
>
> +  BOOLEAN                          Found = FALSE;
>
> +
>
> +  FileBuffer = NULL;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "ReadCapsuleInfo()...\n"));
>
> +
>
> +  Status = GetDevicePathByBoot (mBootDevicePath, &BootPartitionPath);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "IGpuDevicePath: %S\n", ConvertDevicePathToText
> (BootPartitionPath, FALSE, FALSE)));
>
> +
>
> +  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid,
> &BootPartitionPath, &Handle);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  //
>
> +  // Get Capsule file
>
> +  //
>
> +  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID
> **)&BlockIo);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 1Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  if (BlockIo->Media->RemovableMedia) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 2Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&Fs);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 3Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = Fs->OpenVolume (Fs, &Root);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 4Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = Root->Open (Root, &DirHandle, FileBaseName,
> EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Cannot open %s. Status = %r\n", FileBaseName,
> Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  //
>
> +  // Get file count first
>
> +  //
>
> +  Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
>
> +  while (!*NoNextFile && !Found) {
>
> +    // . & ..
>
> +    Status = FileHandleFindNextFile (DirHandle, FileInfo, NoNextFile);
>
> +    if (EFI_ERROR (Status)) {
>
> +      return Status;
>
> +    }
>
> +
>
> +    if (FileInfo->Attribute & EFI_FILE_DIRECTORY) {
>
> +      continue;
>
> +    }
>
> +
>
> +    Found = TRUE;
>
> +  }
>
> +
>
> +  if (!Found) {
>
> +    *NoNextFile = TRUE;
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "Processing Capsule %s\n", FileInfo->FileName));
>
> +  FileBuffer = AllocateZeroPool (FileInfo->FileSize);
>
> +  if (FileBuffer == NULL) {
>
> +    return EFI_BUFFER_TOO_SMALL;
>
> +  }
>
> +
>
> +  Status = DirHandle->Open (DirHandle, &FileHandle, FileInfo->FileName,
> EFI_FILE_MODE_READ, 0);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo Cannot open file %s: %r\n",
> FileInfo->FileName, Status));
>
> +    FreePool (FileBuffer);
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = FileHandleRead (FileHandle, &FileInfo->FileSize, FileBuffer);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 7Locate DevicePath failed:
> %r\n", Status));
>
> +    FileHandleClose (FileHandle);
>
> +    FreePool (FileBuffer);
>
> +    return Status;
>
> +  }
>
> +
>
> +  if (!*NoNextFile) {
>
> +    Status = FileHandleClose (DirHandle);
>
> +  }
>
> +
>
> +  Status = FileHandleClose (FileHandle);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 8Locate DevicePath failed:
> %r\n", Status));
>
> +    FreePool (FileBuffer);
>
> +    return Status;
>
> +  }
>
> +
>
> +  *Buffer     = FileBuffer;
>
> +  *BufferSize = FileInfo->FileSize;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "Capsule size: 0x%x\n", *BufferSize));
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Read Capsule file information from FAT partiton.
>
> +
>
> +  @param[in]  FileBaseName              File name of Capsule binary
>
> +
>
> +  @retval EFI_SUCCESS               Delete first capsule successfully
>
> +  @retval EFI_NOT_FOUND             Fail to found Capsule information
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DeleteFirstCapsule (
>
> +  CHAR16  *FileBaseName
>
> +  )
>
> +{
>
> +  EFI_DEVICE_PATH_PROTOCOL         *BootPartitionPath;
>
> +  EFI_HANDLE                       Handle;
>
> +  EFI_STATUS                       Status;
>
> +  EFI_BLOCK_IO_PROTOCOL            *BlockIo;
>
> +  EFI_FILE_PROTOCOL                *Root;
>
> +  EFI_FILE_HANDLE                  DirHandle;
>
> +  BOOLEAN                          NoNextFile = FALSE;
>
> +  EFI_FILE_INFO                    *FileInfo;
>
> +  BOOLEAN                          Found = FALSE;
>
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
>
> +  EFI_FILE_HANDLE                  FileHandle;
>
> +
>
> +  Status = GetDevicePathByBoot (mBootDevicePath, &BootPartitionPath);
>
> +
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "IGpuDevicePath: %S\n", ConvertDevicePathToText
> (BootPartitionPath, FALSE, FALSE)));
>
> +
>
> +  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid,
> &BootPartitionPath, &Handle);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  //
>
> +  // Get Capsule file
>
> +  //
>
> +  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID
> **)&BlockIo);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 1Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  if (BlockIo->Media->RemovableMedia) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 2Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&Fs);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 3Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = Fs->OpenVolume (Fs, &Root);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 4Locate DevicePath failed:
> %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = Root->Open (Root, &DirHandle, FileBaseName,
> EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "Cannot open %s. Status = %r\n", FileBaseName,
> Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
>
> +  while (!NoNextFile && !Found) {
>
> +    // . & ..
>
> +    FileHandleFindNextFile (DirHandle, FileInfo, &NoNextFile);
>
> +    if (FileInfo->Attribute & EFI_FILE_DIRECTORY) {
>
> +      continue;
>
> +    }
>
> +
>
> +    Found = TRUE;
>
> +  }
>
> +
>
> +  if (!Found) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "Deleting Capsule %s\n", FileInfo->FileName));
>
> +  Status = DirHandle->Open (DirHandle, &FileHandle, FileInfo->FileName,
> EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
>
> +  if (!EFI_ERROR (Status)) {
>
> +    Status = FileHandle->Delete (FileHandle);
>
> +    if (EFI_ERROR (Status)) {
>
> +      DEBUG ((DEBUG_INFO, "Cannot delete Capsule %s:%r\n", FileInfo-
> >FileName, Status));
>
> +    }
>
> +
>
> +    DirHandle->Close (DirHandle);
>
> +    Root->Close (Root);
>
> +    return EFI_SUCCESS;
>
> +  }
>
> +
>
> +  return EFI_NOT_FOUND;
>
> +}
>
> +
>
> +/**
>
> +  Detect Capsule file from ESP partition and update capsule.
>
> +
>
> +  @retval EFI_SUCCESS               Opertion is successful.
>
> +  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate.
>
> +  @retval EFI_ERROR                 Internal error when update Capsule.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +CapsuleUpdateViaFileLib (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS          Status;
>
> +  UINT8               *CapsuleBuffer;
>
> +  UINTN               CapsuleSize;
>
> +  EFI_CAPSULE_HEADER  *CapsuleHeader;
>
> +  UINTN               CapsuleNum;
>
> +  UINTN               CurrentCapsuleFileNo = 0;
>
> +  BOOLEAN             NoNextFile           = FALSE;
>
> +
>
> +  CapsuleBuffer = NULL;
>
> +  CapsuleSize   = 0;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "CapsuleUpdateViaFileHook() Entry Point...\n"));
>
> +
>
> +  Status = CapsulePathInfo ();
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((DEBUG_ERROR, "CapsulePathInfo failed: %r\n", Status));
>
> +    return Status;
>
> +  }
>
> +
>
> +  while (!NoNextFile) {
>
> +    Status = IterateAllCapsulesFromDisk (EFI_CAPSULE_FILE_DIRECTORY, (VOID
> **)&CapsuleBuffer, &CapsuleSize, &NoNextFile);
>
> +    if (EFI_ERROR (Status)) {
>
> +      DEBUG ((DEBUG_ERROR, "Failed to update capsule:%r\n", Status));
>
> +      break;
>
> +    }
>
> +
>
> +    CapsuleHeader = (EFI_CAPSULE_HEADER *)CapsuleBuffer;
>
> +    CapsuleNum    = 1;
>
> +    Status        = UpdateCapsule (&CapsuleHeader, CapsuleNum);
>
> +    RecordCapsuleStatusVariable (CapsuleHeader, Status);
>
> +    if (EFI_ERROR (Status)) {
>
> +      DEBUG ((DEBUG_ERROR, "Failed to update capsule.\n"));
>
> +      break;
>
> +    }
>
> +
>
> +    Status = DeleteFirstCapsule (EFI_CAPSULE_FILE_DIRECTORY);
>
> +    if (EFI_ERROR (Status)) {
>
> +      DEBUG ((DEBUG_ERROR, "Cannot delete Capsule.\n"));
>
> +      break;
>
> +    }
>
> +  }
>
> +
>
> +  if (CapsuleBuffer != NULL) {
>
> +    FreePool (CapsuleBuffer);
>
> +  }
>
> +
>
> +  if (!CurrentCapsuleFileNo && (Status == EFI_NOT_FOUND)) {
>
> +    Status = EFI_SUCCESS;
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "Capsule update via file completed, Status=%r\n",
> Status));
>
> +  // RecordFmpCapsuleStatus();
>
> +  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
>
> +
>
> +  // Unreachable.
>
> +  return EFI_SUCCESS;
>
> +}
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Capsul
> eHookLib/CapsuleHookLib.inf
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Capsul
> eHookLib/CapsuleHookLib.inf
>
> new file mode 100644
>
> index 0000000000..c3e910007a
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Capsul
> eHookLib/CapsuleHookLib.inf
>
> @@ -0,0 +1,56 @@
>
> +## @file
>
> +# Capsule Hook Lib Module
>
> +#
>
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> +  INF_VERSION                    = 0x00010005
>
> +  BASE_NAME                      = CapsuleHookLib
>
> +  FILE_GUID                      = 22BC4D9A-C78A-4038-8071-865765C4C019
>
> +  MODULE_TYPE                    = DXE_DRIVER
>
> +  VERSION_STRING                 = 1.0
>
> +  LIBRARY_CLASS                  = CapsuleHookLib
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the build
> tools.
>
> +#
>
> +#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
>
> +#
>
> +
>
> +[Sources]
>
> +  CapsuleHookLib.c
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +  VanGoghCommonPkg/AmdCommonPkg.dec
>
> +  ChachaniBoardPkg/Project.dec
>
> +
>
> +[LibraryClasses]
>
> +  BaseLib
>
> +  MemoryAllocationLib
>
> +  UefiBootServicesTableLib
>
> +  UefiRuntimeServicesTableLib
>
> +  BaseMemoryLib
>
> +  DebugLib
>
> +  UefiLib
>
> +  FileHandleLib
>
> +  DxeServicesLib
>
> +  CapsuleLib
>
> +
>
> +[Protocols]
>
> +  gEfiBlockIoProtocolGuid
>
> +  gEfiSimpleFileSystemProtocolGuid
>
> +
>
> +[Pcd]
>
> +  gAmdCommonPkgTokenSpaceGuid.PcdOtaCapsuleName
>
> +  gAmdCommonPkgTokenSpaceGuid.PcdOtaCapsulePartitionName
>
> +  gPlatformPkgTokenSpaceGuid.PcdNVMeDevicePath
>
> +
>
> +[Guids]
>
> +  gEfiFmpCapsuleGuid
>
> +  gEfiGlobalVariableGuid
>
> +  gOtaCapsuleUpdateGuid
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformBootManager.c
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformBootManager.c
>
> new file mode 100644
>
> index 0000000000..a647e92054
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformBootManager.c
>
> @@ -0,0 +1,803 @@
>
> +/** @file
>
> +  Implements PlatformBootManager.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
>
> +  This file include all platform action which can be customized
>
> +  by IBV/OEM.
>
> +
>
> +Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +//
>
> +// PCI Vendor ID and Device ID
>
> +//
>
> +#define VENDOR_ID   0x1002
>
> +#define DEVICE_ID   0x163F
>
> +#define DEVICE_ID2  0x1435
>
> +
>
> +#include "PlatformBootManager.h"
>
> +#include "PlatformConsole.h"
>
> +#include <Protocol/PlatformBootManagerOverride.h>
>
> +#include <Guid/BootManagerMenu.h>
>
> +#include <Library/HobLib.h>
>
> +#include <Library/DxeServicesTableLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/CapsuleHookLib.h>
>
> +#include <Library/CapsuleLib.h>
>
> +
>
> +//
>
> +// Predefined platform root bridge
>
> +//
>
> +PLATFORM_ROOT_BRIDGE_DEVICE_PATH  gPlatformRootBridge0 = {
>
> +  gPciRootBridge,
>
> +  gEndEntire
>
> +};
>
> +
>
> +EFI_DEVICE_PATH_PROTOCOL  *gPlatformRootBridges[] = {
>
> +  (EFI_DEVICE_PATH_PROTOCOL *)&gPlatformRootBridge0,
>
> +  NULL
>
> +};
>
> +
>
> +extern EFI_GUID                                            gEfiEventReadyToBootGuid;
>
> +UNIVERSAL_PAYLOAD_PLATFORM_BOOT_MANAGER_OVERRIDE_PROTOCO
> L  *mUniversalPayloadPlatformBootManagerOverrideInstance = NULL;
>
> +
>
> +EFI_STATUS
>
> +GetGopDevicePath (
>
> +  IN  EFI_DEVICE_PATH_PROTOCOL  *PciDevicePath,
>
> +  OUT EFI_DEVICE_PATH_PROTOCOL  **GopDevicePath
>
> +  );
>
> +
>
> +/**
>
> +  Signal EndOfDxe event and install SMM Ready to lock protocol.
>
> +
>
> +**/
>
> +VOID
>
> +InstallReadyToLock (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  EFI_HANDLE                Handle;
>
> +  EFI_SMM_ACCESS2_PROTOCOL  *SmmAccess;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "InstallReadyToLock  entering......\n"));
>
> +  //
>
> +  // Inform the SMM infrastructure that we're entering BDS and may run 3rd
> party code hereafter
>
> +  // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth
>
> +  //
>
> +  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
>
> +  DEBUG ((DEBUG_INFO, "All EndOfDxe callbacks have returned
> successfully\n"));
>
> +
>
> +  //
>
> +  // Install DxeSmmReadyToLock protocol in order to lock SMM
>
> +  //
>
> +  Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID
> **)&SmmAccess);
>
> +  if (!EFI_ERROR (Status)) {
>
> +    Handle = NULL;
>
> +    Status = gBS->InstallProtocolInterface (
>
> +                    &Handle,
>
> +                    &gEfiDxeSmmReadyToLockProtocolGuid,
>
> +                    EFI_NATIVE_INTERFACE,
>
> +                    NULL
>
> +                    );
>
> +    ASSERT_EFI_ERROR (Status);
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "InstallReadyToLock  end\n"));
>
> +  return;
>
> +}
>
> +
>
> +/**
>
> +  Return the index of the load option in the load option array.
>
> +
>
> +  The function consider two load options are equal when the
>
> +  OptionType, Attributes, Description, FilePath and OptionalData are equal.
>
> +
>
> +  @param Key    Pointer to the load option to be found.
>
> +  @param Array  Pointer to the array of load options to be found.
>
> +  @param Count  Number of entries in the Array.
>
> +
>
> +  @retval -1          Key wasn't found in the Array.
>
> +  @retval 0 ~ Count-1 The index of the Key in the Array.
>
> +**/
>
> +INTN
>
> +PlatformFindLoadOption (
>
> +  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION  *Key,
>
> +  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION  *Array,
>
> +  IN UINTN                               Count
>
> +  )
>
> +{
>
> +  UINTN  Index;
>
> +
>
> +  for (Index = 0; Index < Count; Index++) {
>
> +    if ((Key->OptionType == Array[Index].OptionType) &&
>
> +        (Key->Attributes == Array[Index].Attributes) &&
>
> +        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
>
> +        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize
> (Key->FilePath)) == 0) &&
>
> +        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
>
> +        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key-
> >OptionalDataSize) == 0))
>
> +    {
>
> +      return (INTN)Index;
>
> +    }
>
> +  }
>
> +
>
> +  return -1;
>
> +}
>
> +
>
> +/**
>
> +  Register a boot option using a file GUID in the FV.
>
> +
>
> +  @param FileGuid     The file GUID name in FV.
>
> +  @param Description  The boot option description.
>
> +  @param Attributes   The attributes used for the boot option loading.
>
> +**/
>
> +VOID
>
> +PlatformRegisterFvBootOption (
>
> +  EFI_GUID  *FileGuid,
>
> +  CHAR16    *Description,
>
> +  UINT32    Attributes
>
> +  )
>
> +{
>
> +  EFI_STATUS                         Status;
>
> +  UINTN                              OptionIndex;
>
> +  EFI_BOOT_MANAGER_LOAD_OPTION       NewOption;
>
> +  EFI_BOOT_MANAGER_LOAD_OPTION       *BootOptions;
>
> +  UINTN                              BootOptionCount;
>
> +  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;
>
> +  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
>
> +  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
>
> +
>
> +  Status = gBS->HandleProtocol (gImageHandle,
> &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +
>
> +  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
>
> +  DevicePath = AppendDevicePathNode (
>
> +                 DevicePathFromHandle (LoadedImage->DeviceHandle),
>
> +                 (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
>
> +                 );
>
> +
>
> +  Status = EfiBootManagerInitializeLoadOption (
>
> +             &NewOption,
>
> +             LoadOptionNumberUnassigned,
>
> +             LoadOptionTypeBoot,
>
> +             Attributes,
>
> +             Description,
>
> +             DevicePath,
>
> +             NULL,
>
> +             0
>
> +             );
>
> +  if (!EFI_ERROR (Status)) {
>
> +    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
> LoadOptionTypeBoot);
>
> +
>
> +    OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions,
> BootOptionCount);
>
> +
>
> +    if (OptionIndex == -1) {
>
> +      Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN)-
> 1);
>
> +      ASSERT_EFI_ERROR (Status);
>
> +    }
>
> +
>
> +    EfiBootManagerFreeLoadOption (&NewOption);
>
> +    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
>
> +  }
>
> +}
>
> +
>
> +/**
>
> +  Get device path of one IGPU and one DGPU.
>
> +
>
> +  @param IGpuDevicePath   Return the IGPU devide path, if no, return NULL.
>
> +  @param DGpuDevicePath   Return the DGPU devide path, if no, return
> NULL.
>
> +
>
> +  @retval EFI_SUCCSS      Get all platform active video device path.
>
> +  @retval EFI_STATUS      Return the status of gBS->LocateDevicePath (),
>
> +                          gBS->ConnectController (),
>
> +                          and gBS->LocateHandleBuffer ().
>
> +**/
>
> +EFI_STATUS
>
> +GetVgaDevicePath (
>
> +  IN OUT EFI_DEVICE_PATH_PROTOCOL  **IGpuDevicePath,
>
> +  IN OUT EFI_DEVICE_PATH_PROTOCOL  **DGpuDevicePath
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  EFI_HANDLE                RootHandle;
>
> +  UINTN                     HandleCount;
>
> +  EFI_HANDLE                *HandleBuffer;
>
> +  UINTN                     Index;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
>
> +  EFI_PCI_IO_PROTOCOL       *PciIo;
>
> +  PCI_TYPE00                Pci;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "GetVgaDevicePath enter\n"));
>
> +
>
> +  HandleCount     = 0;
>
> +  DevicePath      = NULL;
>
> +  HandleBuffer    = NULL;
>
> +  *IGpuDevicePath = NULL;
>
> +  *DGpuDevicePath = NULL;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "VENDOR_ID = 0x%x\n", VENDOR_ID));
>
> +  DEBUG ((DEBUG_INFO, "DEVICE_ID = 0x%x\n", DEVICE_ID));
>
> +
>
> +  //
>
> +  // Make all the PCI_IO protocols on PCI Seg 0 show up
>
> +  //
>
> +  EfiBootManagerConnectDevicePath (gPlatformRootBridges[0], NULL);
>
> +
>
> +  Status = gBS->LocateDevicePath (
>
> +                  &gEfiDevicePathProtocolGuid,
>
> +                  &gPlatformRootBridges[0],
>
> +                  &RootHandle
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->ConnectController (
>
> +                  RootHandle,
>
> +                  NULL,
>
> +                  NULL,
>
> +                  FALSE
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  //
>
> +  // Start to check all the pci io to find all possible VGA device
>
> +  //
>
> +  HandleCount  = 0;
>
> +  HandleBuffer = NULL;
>
> +  Status       = gBS->LocateHandleBuffer (
>
> +                        ByProtocol,
>
> +                        &gEfiPciIoProtocolGuid,
>
> +                        NULL,
>
> +                        &HandleCount,
>
> +                        &HandleBuffer
>
> +                        );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  for (Index = 0; Index < HandleCount; Index++) {
>
> +    Status = gBS->HandleProtocol (
>
> +                    HandleBuffer[Index],
>
> +                    &gEfiPciIoProtocolGuid,
>
> +                    (VOID **)&PciIo
>
> +                    );
>
> +    if (!EFI_ERROR (Status)) {
>
> +      //
>
> +      // Check for all VGA device
>
> +      //
>
> +      Status = PciIo->Pci.Read (
>
> +                            PciIo,
>
> +                            EfiPciIoWidthUint32,
>
> +                            0,
>
> +                            sizeof (Pci) / sizeof (UINT32),
>
> +                            &Pci
>
> +                            );
>
> +      if (EFI_ERROR (Status)) {
>
> +        continue;
>
> +      }
>
> +
>
> +      //
>
> +      // Here we decide which VGA device to enable in PCI bus
>
> +      //
>
> +      // The first plugin PCI VGA card device will be present as PCI VGA
>
> +      // The onchip AGP or AGP card will be present as AGP VGA
>
> +      //
>
> +      if (!IS_PCI_DISPLAY (&Pci)) {
>
> +        // if (!IS_PCI_VGA (&Pci)) {
>
> +        continue;
>
> +      }
>
> +
>
> +      //
>
> +      // Set the device as the possible console out device,
>
> +      //
>
> +      // Below code will make every VGA device to be one
>
> +      // of the possibe console out device
>
> +      //
>
> +      gBS->HandleProtocol (
>
> +             HandleBuffer[Index],
>
> +             &gEfiDevicePathProtocolGuid,
>
> +             (VOID **)&DevicePath
>
> +             );
>
> +      DEBUG ((DEBUG_INFO, "DevicePath: %S\n", ConvertDevicePathToText
> (DevicePath, FALSE, FALSE)));
>
> +
>
> +      if ((Pci.Hdr.VendorId == VENDOR_ID) && ((Pci.Hdr.DeviceId == DEVICE_ID)
> || (Pci.Hdr.DeviceId == DEVICE_ID2))) {
>
> +        // IGPU
>
> +        *IGpuDevicePath = DevicePath;
>
> +      } else {
>
> +        // DGPU
>
> +        *DGpuDevicePath = DevicePath;
>
> +      }
>
> +
>
> +      if ((*IGpuDevicePath != NULL) && (*DGpuDevicePath != NULL)) {
>
> +        DEBUG ((DEBUG_INFO, "IGpuDevicePath and DGpuDevicePath are not
> NULL\n"));
>
> +        break;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "IGpuDevicePath: %S\n", ConvertDevicePathToText
> (*IGpuDevicePath, FALSE, FALSE)));
>
> +  DEBUG ((DEBUG_INFO, "DGpuDevicePath: %S\n", ConvertDevicePathToText
> (*DGpuDevicePath, FALSE, FALSE)));
>
> +  FreePool (HandleBuffer);
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +
>
> +  Find the platform active vga, and base on the policy to enable the vga as
>
> +  the console out device. The policy is active dGPU, if no dGPU active iGPU.
>
> +
>
> +  None.
>
> +
>
> +  @param EFI_UNSUPPORTED         There is no active vga device
>
> +
>
> +  @retval EFI_STATUS             Return the status of BdsLibGetVariableAndSize ()
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +PlatformBdsForceActiveVga (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePathFirst;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePathSecond;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *IGpuDevicePath;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *DGpuDevicePath;
>
> +
>
> +  DEBUG ((EFI_D_INFO, "PlatformBdsForceActiveVga enter\n"));
>
> +
>
> +  Status           = EFI_SUCCESS;
>
> +  DevicePathFirst  = NULL;
>
> +  DevicePathSecond = NULL;
>
> +  GopDevicePath    = NULL;
>
> +  IGpuDevicePath   = NULL;
>
> +  DGpuDevicePath   = NULL;
>
> +
>
> +  //
>
> +  // Get device path of one IGPU and one DGPU
>
> +  //
>
> +  Status = GetVgaDevicePath (&IGpuDevicePath, &DGpuDevicePath);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +
>
> +  if ((IGpuDevicePath == NULL) && (DGpuDevicePath == NULL)) {
>
> +    DEBUG ((EFI_D_INFO, "No valid IGPU and DGPU\n"));
>
> +    return EFI_UNSUPPORTED;
>
> +  }
>
> +
>
> +  if ((IGpuDevicePath != NULL) && (DGpuDevicePath == NULL)) {
>
> +    DEBUG ((EFI_D_INFO, "Only IGPU is valid\n"));
>
> +    // DEBUG ((EFI_D_INFO,"Only IGPU is valid, Update IGPU ...\n"));
>
> +    DevicePathFirst  = IGpuDevicePath;
>
> +    DevicePathSecond = DGpuDevicePath;
>
> +    goto UpdateConOut;
>
> +  } else if ((IGpuDevicePath == NULL) && (DGpuDevicePath != NULL)) {
>
> +    DEBUG ((EFI_D_INFO, "Only DGPU is valid\n"));
>
> +    // DEBUG ((EFI_D_INFO,"Only DGPU is valid, Update DGPU ...\n"));
>
> +    DevicePathFirst  = DGpuDevicePath;
>
> +    DevicePathSecond = IGpuDevicePath;
>
> +    goto UpdateConOut;
>
> +  } else if ((IGpuDevicePath != NULL) && (DGpuDevicePath != NULL)) {
>
> +    DEBUG ((EFI_D_INFO, "DGPU and IGPU are valid, active DGPU\n"));
>
> +    // DEBUG ((EFI_D_INFO,"Only DGPU is valid, Update DGPU ...\n"));
>
> +    DevicePathFirst  = DGpuDevicePath;
>
> +    DevicePathSecond = IGpuDevicePath;
>
> +    goto UpdateConOut;
>
> +  }
>
> +
>
> +UpdateConOut:
>
> +  DEBUG ((DEBUG_INFO, "Before GetGopDevicePath: ConOutDevicePath is
> %S\n", ConvertDevicePathToText (DevicePathFirst, FALSE, FALSE)));
>
> +  GetGopDevicePath (DevicePathFirst, &GopDevicePath);
>
> +  DevicePathFirst = GopDevicePath;
>
> +  DEBUG ((DEBUG_INFO, "After GetGopDevicePath: ConOutDevicePath is
> %S\n", ConvertDevicePathToText (DevicePathFirst, FALSE, FALSE)));
>
> +  DEBUG ((DEBUG_INFO, "Exclusive device path is %S\n",
> ConvertDevicePathToText (DevicePathSecond, FALSE, FALSE)));
>
> +
>
> +  Status = EfiBootManagerUpdateConsoleVariable (
>
> +             ConOut,
>
> +             DevicePathFirst,
>
> +             DevicePathSecond
>
> +             );
>
> +  // TODO: Specify iGPU/dGPU.
>
> +  EfiBootManagerConnectVideoController (NULL);
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  Do the platform specific action before the console is connected.
>
> +
>
> +  Such as:
>
> +    Update console variable;
>
> +    Register new Driver#### or Boot####;
>
> +    Signal ReadyToLock event.
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +PlatformBootManagerBeforeConsole (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_INPUT_KEY                 Enter;
>
> +  EFI_INPUT_KEY                 CustomKey;
>
> +  EFI_INPUT_KEY                 Down;
>
> +  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
>
> +  EFI_STATUS                    Status;
>
> +  UINT64                        OsIndication;
>
> +  UINTN                         DataSize;
>
> +  UINT32                        Attributes;
>
> +  BOOLEAN                       CapsuleUpdateonDisk;
>
> +
>
> +  Status = gBS->LocateProtocol
> (&gUniversalPayloadPlatformBootManagerOverrideProtocolGuid, NULL,
> (VOID **)&mUniversalPayloadPlatformBootManagerOverrideInstance);
>
> +  if (EFI_ERROR (Status)) {
>
> +    mUniversalPayloadPlatformBootManagerOverrideInstance = NULL;
>
> +  }
>
> +
>
> +  Status = gRT->GetVariable (
>
> +                  L"OsIndications",
>
> +                  &gEfiGlobalVariableGuid,
>
> +                  &Attributes,
>
> +                  &DataSize,
>
> +                  &OsIndication
>
> +                  );
>
> +  if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {
>
> +    mUniversalPayloadPlatformBootManagerOverrideInstance-
> >BeforeConsole ();
>
> +    return;
>
> +  }
>
> +
>
> +  //
>
> +  // Register ENTER as CONTINUE key
>
> +  //
>
> +  Enter.ScanCode    = SCAN_NULL;
>
> +  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
>
> +  EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
>
> +
>
> +  if (FixedPcdGetBool (PcdBootManagerEscape)) {
>
> +    //
>
> +    // Map Esc to Boot Manager Menu
>
> +    //
>
> +    CustomKey.ScanCode    = SCAN_ESC;
>
> +    CustomKey.UnicodeChar = CHAR_NULL;
>
> +  } else {
>
> +    //
>
> +    // Map Esc to Boot Manager Menu
>
> +    //
>
> +    CustomKey.ScanCode    = SCAN_F2;
>
> +    CustomKey.UnicodeChar = CHAR_NULL;
>
> +  }
>
> +
>
> +  EfiBootManagerGetBootManagerMenu (&BootOption);
>
> +  EfiBootManagerAddKeyOptionVariable (NULL,
> (UINT16)BootOption.OptionNumber, 0, &CustomKey, NULL);
>
> +
>
> +  //
>
> +  // Also add Down key to Boot Manager Menu since some serial terminals
> don't support F2 key.
>
> +  //
>
> +  Down.ScanCode    = SCAN_DOWN;
>
> +  Down.UnicodeChar = CHAR_NULL;
>
> +  EfiBootManagerGetBootManagerMenu (&BootOption);
>
> +  EfiBootManagerAddKeyOptionVariable (NULL,
> (UINT16)BootOption.OptionNumber, 0, &Down, NULL);
>
> +  CapsuleUpdateonDisk = (BOOLEAN)((OsIndication &
> EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0);
>
> +  // Process Capsule in Memory first, before EndOfDxe.
>
> +  if ((GetBootModeHob () == BOOT_ON_FLASH_UPDATE) ||
> CapsuleUpdateonDisk) {
>
> +    PlatformBdsForceActiveVga (); // Force enable VGA on Capsule Update.
>
> +    ASSERT_EFI_ERROR (BootLogoEnableLogo ());
>
> +    Print (
>
> +      L"\n"
>
> +      L"    Updating system BIOS.....\n"
>
> +      L"\n"
>
> +      );
>
> +    if (CapsuleUpdateonDisk) {
>
> +      EfiBootManagerConnectAll (); // Get BlockIo
>
> +      CapsuleUpdateViaFileLib ();
>
> +    } else {
>
> +      ProcessCapsules ();
>
> +    }
>
> +  }
>
> +
>
> +  //
>
> +  // Install ready to lock.
>
> +  // This needs to be done before option rom dispatched.
>
> +  //
>
> +  InstallReadyToLock ();
>
> +
>
> +  //
>
> +  // Dispatch deferred images after EndOfDxe event and ReadyToLock
> installation.
>
> +  //
>
> +  EfiBootManagerDispatchDeferredImages ();
>
> +
>
> +  PlatformConsoleInit ();
>
> +}
>
> +
>
> +/**
>
> +  Do the platform specific action after the console is connected.
>
> +
>
> +  Such as:
>
> +    Dynamically switch output mode;
>
> +    Signal console ready platform customized event;
>
> +    Run diagnostics like memory testing;
>
> +    Connect certain devices;
>
> +    Dispatch additional option roms.
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +PlatformBootManagerAfterConsole (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Black;
>
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  White;
>
> +  EDKII_PLATFORM_LOGO_PROTOCOL   *PlatformLogo;
>
> +  EFI_STATUS                     Status;
>
> +  UINT64                         OsIndication;
>
> +  UINTN                          DataSize;
>
> +  UINT32                         Attributes;
>
> +
>
> +  if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {
>
> +    mUniversalPayloadPlatformBootManagerOverrideInstance->AfterConsole
> ();
>
> +    return;
>
> +  }
>
> +
>
> +  Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;
>
> +  White.Blue = White.Green = White.Red = White.Reserved = 0xFF;
>
> +
>
> +  Status = gBS->LocateProtocol (&gEdkiiPlatformLogoProtocolGuid, NULL,
> (VOID **)&PlatformLogo);
>
> +
>
> +  if (!EFI_ERROR (Status)) {
>
> +    gST->ConOut->ClearScreen (gST->ConOut);
>
> +    BootLogoEnableLogo ();
>
> +  }
>
> +
>
> +  EfiBootManagerConnectAll ();
>
> +  EfiBootManagerRefreshAllBootOption ();
>
> +
>
> +  // Process Capsule in Memory again, after EndOfDxe.
>
> +  if (GetBootModeHob () == BOOT_ON_FLASH_UPDATE) {
>
> +    ProcessCapsules ();
>
> +  }
>
> +
>
> +  OsIndication = 0;
>
> +  Attributes   = 0;
>
> +  DataSize     = sizeof (UINT64);
>
> +  Status       = gRT->GetVariable (
>
> +                        EFI_OS_INDICATIONS_VARIABLE_NAME,
>
> +                        &gEfiGlobalVariableGuid,
>
> +                        &Attributes,
>
> +                        &DataSize,
>
> +                        &OsIndication
>
> +                        );
>
> +  if (EFI_ERROR (Status)) {
>
> +    OsIndication = 0;
>
> +  }
>
> +
>
> +  //
>
> +  // Register UEFI Shell
>
> +  //
>
> +  PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell",
> LOAD_OPTION_ACTIVE);
>
> +
>
> +  {
>
> +    if (FixedPcdGetBool (PcdBootManagerEscape)) {
>
> +      Print (
>
> +        L"\n"
>
> +        L"    Esc or Down      to enter Boot Manager Menu.\n"
>
> +        L"    ENTER            to boot directly.\n"
>
> +        L"\n"
>
> +        );
>
> +    } else {
>
> +      Print (
>
> +        L"\n"
>
> +        L"    F2 or Down      to enter Boot Manager Menu.\n"
>
> +        L"    ENTER           to boot directly.\n"
>
> +        L"\n"
>
> +        );
>
> +    }
>
> +  }
>
> +}
>
> +
>
> +/**
>
> +  This function is called each second during the boot manager waits the
> timeout.
>
> +
>
> +  @param TimeoutRemain  The remaining timeout.
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +PlatformBootManagerWaitCallback (
>
> +  UINT16  TimeoutRemain
>
> +  )
>
> +{
>
> +  if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {
>
> +    mUniversalPayloadPlatformBootManagerOverrideInstance->WaitCallback
> (TimeoutRemain);
>
> +  }
>
> +
>
> +  return;
>
> +}
>
> +
>
> +/**
>
> +  The function is called when no boot option could be launched,
>
> +  including platform recovery options and options pointing to applications
>
> +  built into firmware volumes.
>
> +
>
> +  If this function returns, BDS attempts to enter an infinite loop.
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +PlatformBootManagerUnableToBoot (
>
> +  VOID
>
> +  )
>
> +{
>
> +  if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {
>
> +    mUniversalPayloadPlatformBootManagerOverrideInstance->UnableToBoot
> ();
>
> +  }
>
> +
>
> +  return;
>
> +}
>
> +
>
> +typedef struct {
>
> +  UINTN                   Signature;
>
> +  LIST_ENTRY              Link;
>
> +  EFI_PHYSICAL_ADDRESS    StartAddress;
>
> +  UINT64                  Length;
>
> +  UINT64                  Capabilities;
>
> +} NONTESTED_MEMORY_RANGE;
>
> +
>
> +//
>
> +// This structure records every nontested memory range parsed through GCD
>
> +// service.
>
> +//
>
> +#define EFI_NONTESTED_MEMORY_RANGE_SIGNATURE  SIGNATURE_32
> ('N', 'T', 'M', 'E')
>
> +
>
> +//
>
> +// attributes for reserved memory before it is promoted to system memory
>
> +//
>
> +#define EFI_MEMORY_PRESENT      0x0100000000000000ULL
>
> +#define EFI_MEMORY_INITIALIZED  0x0200000000000000ULL
>
> +#define EFI_MEMORY_TESTED       0x0400000000000000ULL
>
> +
>
> +/**
>
> +  Callback function for event group EFI_EVENT_GROUP_READY_TO_BOOT.
>
> +  This is used to expose the 4G above memory into system memory table.
>
> +
>
> +  @param[in]  Event      The Event that is being processed.
>
> +  @param[in]  Context    The Event Context.
>
> +
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +ExposeOver4GMemoryEventCallback (
>
> +  IN EFI_EVENT  Event,
>
> +  IN VOID       *Context
>
> +  )
>
> +{
>
> +  NONTESTED_MEMORY_RANGE           *Range;
>
> +  BOOLEAN                          NoFound;
>
> +  UINTN                            NumberOfDescriptors;
>
> +  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMap;
>
> +  UINTN                            Index;
>
> +  LIST_ENTRY                       *TmpLink;
>
> +  LIST_ENTRY                       NonTestedMemRanList;
>
> +
>
> +  DEBUG ((EFI_D_INFO, "ExposeOver4GMemoryEventCallback\n"));
>
> +
>
> +  TmpLink = NULL;
>
> +  NoFound = TRUE;
>
> +
>
> +  InitializeListHead (&NonTestedMemRanList);
>
> +
>
> +  gDS->GetMemorySpaceMap (&NumberOfDescriptors,
> &MemorySpaceMap);
>
> +  for (Index = 0; Index < NumberOfDescriptors; Index++) {
>
> +    if ((MemorySpaceMap[Index].GcdMemoryType ==
> EfiGcdMemoryTypeReserved) &&
>
> +        ((MemorySpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT |
> EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
>
> +         (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED))
>
> +        )
>
> +    {
>
> +      NoFound = FALSE;
>
> +
>
> +      gBS->AllocatePool (EfiBootServicesData, sizeof
> (NONTESTED_MEMORY_RANGE), (VOID **)&Range);
>
> +
>
> +      Range->Signature    = EFI_NONTESTED_MEMORY_RANGE_SIGNATURE;
>
> +      Range->StartAddress = MemorySpaceMap[Index].BaseAddress;
>
> +      Range->Length       = MemorySpaceMap[Index].Length;
>
> +      Range->Capabilities = MemorySpaceMap[Index].Capabilities;
>
> +
>
> +      InsertTailList (&NonTestedMemRanList, &Range->Link);
>
> +    }
>
> +  }
>
> +
>
> +  if (!NoFound) {
>
> +    TmpLink = NonTestedMemRanList.ForwardLink;
>
> +
>
> +    while (TmpLink != &NonTestedMemRanList) {
>
> +      Range = CR (TmpLink, NONTESTED_MEMORY_RANGE, Link,
> EFI_NONTESTED_MEMORY_RANGE_SIGNATURE);
>
> +      gDS->RemoveMemorySpace (Range->StartAddress, Range->Length);
>
> +      gDS->AddMemorySpace (
>
> +             EfiGcdMemoryTypeSystemMemory,
>
> +             Range->StartAddress,
>
> +             Range->Length,
>
> +             Range->Capabilities &~(EFI_MEMORY_PRESENT |
> EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED |
> EFI_MEMORY_RUNTIME)
>
> +             );
>
> +
>
> +      TmpLink = TmpLink->ForwardLink;
>
> +    }
>
> +  }
>
> +
>
> +  //
>
> +  // Make sure the hook ONLY called once.
>
> +  //
>
> +  if (Event != NULL) {
>
> +    gBS->CloseEvent (Event);
>
> +  }
>
> +}
>
> +
>
> +/**
>
> +  Get/update PcdBootManagerMenuFile from GUID HOB which will be
> assigned in bootloader.
>
> +
>
> +  @param  ImageHandle   The firmware allocated handle for the EFI image.
>
> +  @param  SystemTable   A pointer to the EFI System Table.
>
> +
>
> +  @retval EFI_SUCCESS       The entry point is executed successfully.
>
> +  @retval other             Some error occurs.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +PlatformBootManagerLibConstructor (
>
> +  IN EFI_HANDLE        ImageHandle,
>
> +  IN EFI_SYSTEM_TABLE  *SystemTable
>
> +  )
>
> +{
>
> +  EFI_STATUS                           Status;
>
> +  UINTN                                Size;
>
> +  VOID                                 *GuidHob;
>
> +  UNIVERSAL_PAYLOAD_GENERIC_HEADER     *GenericHeader;
>
> +  UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU  *BootManagerMenuFile;
>
> +
>
> +  EFI_EVENT  ExposeOver4GMemoryEvent;
>
> +
>
> +  Status = gBS->CreateEventEx (
>
> +                  EVT_NOTIFY_SIGNAL,
>
> +                  TPL_CALLBACK,
>
> +                  ExposeOver4GMemoryEventCallback,
>
> +                  NULL,
>
> +                  &gEfiEventReadyToBootGuid,
>
> +                  &ExposeOver4GMemoryEvent
>
> +                  );
>
> +  ASSERT_EFI_ERROR (Status);
>
> +
>
> +  GuidHob = GetFirstGuidHob (&gEdkiiBootManagerMenuFileGuid);
>
> +
>
> +  if (GuidHob == NULL) {
>
> +    //
>
> +    // If the HOB is not create, the default value of PcdBootManagerMenuFile
> will be used.
>
> +    //
>
> +    return EFI_SUCCESS;
>
> +  }
>
> +
>
> +  GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER
> *)GET_GUID_HOB_DATA (GuidHob);
>
> +  if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) >
> GET_GUID_HOB_DATA_SIZE (GuidHob)) || (GenericHeader->Length >
> GET_GUID_HOB_DATA_SIZE (GuidHob))) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  if (GenericHeader->Revision ==
> UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU_REVISION) {
>
> +    BootManagerMenuFile = (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU
> *)GET_GUID_HOB_DATA (GuidHob);
>
> +    if (BootManagerMenuFile->Header.Length <
> UNIVERSAL_PAYLOAD_SIZEOF_THROUGH_FIELD
> (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU, FileName)) {
>
> +      return EFI_NOT_FOUND;
>
> +    }
>
> +
>
> +    Size   = sizeof (BootManagerMenuFile->FileName);
>
> +    Status = PcdSetPtrS (PcdBootManagerMenuFile, &Size,
> &BootManagerMenuFile->FileName);
>
> +    ASSERT_EFI_ERROR (Status);
>
> +  } else {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformBootManager.h
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformBootManager.h
>
> new file mode 100644
>
> index 0000000000..0b4b85e7d2
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformBootManager.h
>
> @@ -0,0 +1,159 @@
>
> +/** @file
>
> +  Implements PlatformBootManager.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
>
> +   Head file for BDS Platform specific code
>
> +
>
> +Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#ifndef PLATFORM_BOOT_MANAGER_H_
>
> +#define PLATFORM_BOOT_MANAGER_H_
>
> +
>
> +#include <PiDxe.h>
>
> +#include <Protocol/LoadedImage.h>
>
> +
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>
> +#include <Library/UefiLib.h>
>
> +#include <Library/UefiBootManagerLib.h>
>
> +#include <Library/PcdLib.h>
>
> +#include <Library/DevicePathLib.h>
>
> +#include <Library/HiiLib.h>
>
> +#include <Library/PrintLib.h>
>
> +#include <Library/DxeServicesLib.h>
>
> +#include <Library/BootLogoLib.h>
>
> +#include <Protocol/SmmAccess2.h>
>
> +#include <Guid/GlobalVariable.h>
>
> +typedef struct {
>
> +  EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
>
> +  UINTN                       ConnectType;
>
> +} PLATFORM_CONSOLE_CONNECT_ENTRY;
>
> +
>
> +extern PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];
>
> +
>
> +#define gEndEntire \
>
> +  { \
>
> +    END_DEVICE_PATH_TYPE,\
>
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,\
>
> +    { END_DEVICE_PATH_LENGTH, 0 },\
>
> +  }
>
> +
>
> +#define CONSOLE_OUT  BIT0
>
> +#define CONSOLE_IN   BIT1
>
> +#define STD_ERROR    BIT2
>
> +
>
> +#define CLASS_HID          3
>
> +#define SUBCLASS_BOOT      1
>
> +#define PROTOCOL_KEYBOARD  1
>
> +
>
> +#define PNPID_DEVICE_PATH_NODE(PnpId) \
>
> +  { \
>
> +    { \
>
> +      ACPI_DEVICE_PATH, \
>
> +      ACPI_DP, \
>
> +      { \
>
> +        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
>
> +        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
>
> +      }, \
>
> +    }, \
>
> +    EISA_PNP_ID((PnpId)), \
>
> +    0 \
>
> +  }
>
> +
>
> +#define gPciRootBridge \
>
> +  PNPID_DEVICE_PATH_NODE(0x0A03)
>
> +
>
> +typedef struct {
>
> +  USB_CLASS_DEVICE_PATH       UsbClass;
>
> +  EFI_DEVICE_PATH_PROTOCOL    End;
>
> +} USB_CLASS_FORMAT_DEVICE_PATH;
>
> +
>
> +typedef struct {
>
> +  VENDOR_DEVICE_PATH    VendorDevicePath;
>
> +  UINT32                Instance;
>
> +} WIN_NT_VENDOR_DEVICE_PATH_NODE;
>
> +
>
> +//
>
> +// Below is the platform console device path
>
> +//
>
> +typedef struct {
>
> +  VENDOR_DEVICE_PATH                NtBus;
>
> +  WIN_NT_VENDOR_DEVICE_PATH_NODE    SerialDevice;
>
> +  UART_DEVICE_PATH                  Uart;
>
> +  VENDOR_DEVICE_PATH                TerminalType;
>
> +  EFI_DEVICE_PATH_PROTOCOL          End;
>
> +} NT_ISA_SERIAL_DEVICE_PATH;
>
> +
>
> +typedef struct {
>
> +  VENDOR_DEVICE_PATH                NtBus;
>
> +  WIN_NT_VENDOR_DEVICE_PATH_NODE    NtGopDevice;
>
> +  EFI_DEVICE_PATH_PROTOCOL          End;
>
> +} NT_PLATFORM_GOP_DEVICE_PATH;
>
> +
>
> +extern USB_CLASS_FORMAT_DEVICE_PATH  gUsbClassKeyboardDevicePath;
>
> +
>
> +/**
>
> +  Use SystemTable Conout to stop video based Simple Text Out consoles from
> going
>
> +  to the video device. Put up LogoFile on every video device that is a console.
>
> +
>
> +  @param[in]  LogoFile   File name of logo to display on the center of the
> screen.
>
> +
>
> +  @retval EFI_SUCCESS     ConsoleControl has been flipped to graphics and
> logo displayed.
>
> +  @retval EFI_UNSUPPORTED Logo not found
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +PlatformBootManagerEnableQuietBoot (
>
> +  IN  EFI_GUID  *LogoFile
>
> +  );
>
> +
>
> +/**
>
> +  Use SystemTable Conout to turn on video based Simple Text Out consoles.
> The
>
> +  Simple Text Out screens will now be synced up with all non video output
> devices
>
> +
>
> +  @retval EFI_SUCCESS     UGA devices are back in text mode and synced up.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +PlatformBootManagerDisableQuietBoot (
>
> +  VOID
>
> +  );
>
> +
>
> +/**
>
> +  Show progress bar with title above it. It only works in Graphics mode.
>
> +
>
> +  @param TitleForeground Foreground color for Title.
>
> +  @param TitleBackground Background color for Title.
>
> +  @param Title           Title above progress bar.
>
> +  @param ProgressColor   Progress bar color.
>
> +  @param Progress        Progress (0-100)
>
> +  @param PreviousValue   The previous value of the progress.
>
> +
>
> +  @retval  EFI_STATUS       Success update the progress bar
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +PlatformBootManagerShowProgress (
>
> +  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL  TitleForeground,
>
> +  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL  TitleBackground,
>
> +  IN CHAR16                         *Title,
>
> +  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL  ProgressColor,
>
> +  IN UINTN                          Progress,
>
> +  IN UINTN                          PreviousValue
>
> +  );
>
> +
>
> +#endif // _PLATFORM_BOOT_MANAGER_H
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformBootManagerLib.inf
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformBootManagerLib.inf
>
> new file mode 100644
>
> index 0000000000..db58d94301
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformBootManagerLib.inf
>
> @@ -0,0 +1,96 @@
>
> +## @file
>
> +# Platform Boot Manager Lib Module
>
> +#
>
> +# 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
>
> +#  Include all platform action which can be customized by IBV/OEM.
>
> +#
>
> +#  Copyright (c) 2012 - 2021, Intel Corporation. All rights reserved.<BR>
>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> +  INF_VERSION                    = 0x00010005
>
> +  BASE_NAME                      = PlatformBootManagerLib
>
> +  FILE_GUID                      = 9455F0BD-2037-488A-8899-56CB72A44A03
>
> +  MODULE_TYPE                    = DXE_DRIVER
>
> +  VERSION_STRING                 = 1.0
>
> +  LIBRARY_CLASS                  = PlatformBootManagerLib|DXE_DRIVER
>
> +  CONSTRUCTOR                    = PlatformBootManagerLibConstructor
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the build
> tools.
>
> +#
>
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
>
> +#
>
> +
>
> +[Sources]
>
> +  PlatformData.c
>
> +  PlatformConsole.c
>
> +  PlatformConsole.h
>
> +  PlatformBootManager.c
>
> +  PlatformBootManager.h
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +  UefiPayloadPkg/UefiPayloadPkg.dec
>
> +  AgesaPublic/AgesaPublic.dec
>
> +  VanGoghCommonPkg/AmdCommonPkg.dec
>
> +  ChachaniBoardPkg/Project.dec
>
> +
>
> +[LibraryClasses]
>
> +  BaseLib
>
> +  UefiBootServicesTableLib
>
> +  UefiRuntimeServicesTableLib
>
> +  UefiLib
>
> +  UefiBootManagerLib
>
> +  BootLogoLib
>
> +  PcdLib
>
> +  DxeServicesLib
>
> +  DxeServicesTableLib
>
> +  MemoryAllocationLib
>
> +  DevicePathLib
>
> +  HiiLib
>
> +  PrintLib
>
> +  PlatformHookLib
>
> +  HobLib
>
> +  DebugLib
>
> +  CapsuleLib
>
> +  CapsuleHookLib
>
> +
>
> +[Guids]
>
> +  gEfiEndOfDxeEventGroupGuid
>
> +  gEdkiiBootManagerMenuFileGuid
>
> +  gEfiEventReadyToBootGuid
>
> +
>
> +[Protocols]
>
> +  gEfiGenericMemTestProtocolGuid  ## CONSUMES
>
> +  gEfiGraphicsOutputProtocolGuid  ## CONSUMES
>
> +  gEfiUgaDrawProtocolGuid         ## CONSUMES
>
> +  gEfiBootLogoProtocolGuid        ## CONSUMES
>
> +  gEfiDxeSmmReadyToLockProtocolGuid
>
> +  gEfiSmmAccess2ProtocolGuid
>
> +  gUniversalPayloadPlatformBootManagerOverrideProtocolGuid
>
> +  gEfiSerialIoProtocolGuid
>
> +  gEfiPciRootBridgeIoProtocolGuid
>
> +  gAmdCpmAllPciIoProtocolsInstalledProtocolGuid
>
> +
>
> +[Pcd]
>
> +  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
>
> +  gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand
>
> +  gUefiPayloadPkgTokenSpaceGuid.PcdShellFile
>
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
>
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
>
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
>
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile
>
> +  gUefiPayloadPkgTokenSpaceGuid.PcdBootManagerEscape
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformConsole.c
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformConsole.c
>
> new file mode 100644
>
> index 0000000000..0715fcc86e
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformConsole.c
>
> @@ -0,0 +1,504 @@
>
> +/** @file
>
> +  Implements PlatformConsole.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
>
> +This file include all platform action which can be customized by IBV/OEM.
>
> +
>
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include "PlatformBootManager.h"
>
> +#include "PlatformConsole.h"
>
> +#include <Guid/SerialPortLibVendor.h>
>
> +
>
> +#define PCI_DEVICE_PATH_NODE(Func, Dev) \
>
> +  { \
>
> +    { \
>
> +      HARDWARE_DEVICE_PATH, \
>
> +      HW_PCI_DP, \
>
> +      { \
>
> +        (UINT8) (sizeof (PCI_DEVICE_PATH)), \
>
> +        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
>
> +      } \
>
> +    }, \
>
> +    (Func), \
>
> +    (Dev) \
>
> +  }
>
> +
>
> +#define PNPID_DEVICE_PATH_NODE(PnpId) \
>
> +  { \
>
> +    { \
>
> +      ACPI_DEVICE_PATH, \
>
> +      ACPI_DP, \
>
> +      { \
>
> +        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
>
> +        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
>
> +      }, \
>
> +    }, \
>
> +    EISA_PNP_ID((PnpId)), \
>
> +    0 \
>
> +  }
>
> +
>
> +#define gPnp16550ComPort \
>
> +  PNPID_DEVICE_PATH_NODE(0x0501)
>
> +
>
> +#define gPnpPs2Keyboard \
>
> +  PNPID_DEVICE_PATH_NODE(0x0303)
>
> +
>
> +#define gPcAnsiTerminal \
>
> +  { \
>
> +    { \
>
> +      MESSAGING_DEVICE_PATH, \
>
> +      MSG_VENDOR_DP, \
>
> +      { \
>
> +        (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
>
> +        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
>
> +      } \
>
> +    }, \
>
> +    DEVICE_PATH_MESSAGING_PC_ANSI \
>
> +  }
>
> +
>
> +ACPI_HID_DEVICE_PATH  gPnpPs2KeyboardDeviceNode  =
> gPnpPs2Keyboard;
>
> +ACPI_HID_DEVICE_PATH  gPnp16550ComPortDeviceNode =
> gPnp16550ComPort;
>
> +VENDOR_DEVICE_PATH    gTerminalTypeDeviceNode    = gPcAnsiTerminal;
>
> +
>
> +BOOLEAN  mDetectDisplayOnly;
>
> +
>
> +/**
>
> +  Add IsaKeyboard to ConIn.
>
> +
>
> +  @param[in] DeviceHandle  Handle of the LPC Bridge device.
>
> +
>
> +  @retval EFI_SUCCESS  IsaKeyboard on the LPC bridge have been added to
> ConIn.
>
> +  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
>
> +                       from DeviceHandle.
>
> +**/
>
> +EFI_STATUS
>
> +PrepareLpcBridgeDevicePath (
>
> +  IN EFI_HANDLE  DeviceHandle
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
>
> +
>
> +  DevicePath = NULL;
>
> +  Status     = gBS->HandleProtocol (
>
> +                      DeviceHandle,
>
> +                      &gEfiDevicePathProtocolGuid,
>
> +                      (VOID *)&DevicePath
>
> +                      );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  //
>
> +  // Register Keyboard
>
> +  //
>
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
>
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Return the GOP device path in the platform.
>
> +
>
> +  @param[in]   PciDevicePath - Device path for the PCI graphics device.
>
> +  @param[out]  GopDevicePath - Return the device path with GOP installed.
>
> +
>
> +  @retval EFI_SUCCESS  - PCI VGA is added to ConOut.
>
> +  @retval EFI_INVALID_PARAMETER   - The device path parameter is invalid.
>
> +  @retval EFI_STATUS   - No GOP device found.
>
> +**/
>
> +EFI_STATUS
>
> +GetGopDevicePath (
>
> +  IN  EFI_DEVICE_PATH_PROTOCOL  *PciDevicePath,
>
> +  OUT EFI_DEVICE_PATH_PROTOCOL  **GopDevicePath
>
> +  )
>
> +{
>
> +  UINTN                     Index;
>
> +  EFI_STATUS                Status;
>
> +  EFI_HANDLE                PciDeviceHandle;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *TempPciDevicePath;
>
> +  UINTN                     GopHandleCount;
>
> +  EFI_HANDLE                *GopHandleBuffer;
>
> +
>
> +  if ((PciDevicePath == NULL) || (GopDevicePath == NULL)) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  //
>
> +  // Initialize the GopDevicePath to be PciDevicePath
>
> +  //
>
> +  *GopDevicePath    = PciDevicePath;
>
> +  TempPciDevicePath = PciDevicePath;
>
> +
>
> +  Status = gBS->LocateDevicePath (
>
> +                  &gEfiDevicePathProtocolGuid,
>
> +                  &TempPciDevicePath,
>
> +                  &PciDeviceHandle
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
>
> +
>
> +  Status = gBS->LocateHandleBuffer (
>
> +                  ByProtocol,
>
> +                  &gEfiGraphicsOutputProtocolGuid,
>
> +                  NULL,
>
> +                  &GopHandleCount,
>
> +                  &GopHandleBuffer
>
> +                  );
>
> +  if (!EFI_ERROR (Status)) {
>
> +    //
>
> +    // Add all the child handles as possible Console Device
>
> +    //
>
> +    for (Index = 0; Index < GopHandleCount; Index++) {
>
> +      Status = gBS->HandleProtocol (GopHandleBuffer[Index],
> &gEfiDevicePathProtocolGuid, (VOID *)&TempDevicePath);
>
> +      if (EFI_ERROR (Status)) {
>
> +        continue;
>
> +      }
>
> +
>
> +      if (CompareMem (
>
> +            PciDevicePath,
>
> +            TempDevicePath,
>
> +            GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
>
> +            ) == 0)
>
> +      {
>
> +        //
>
> +        // In current implementation, we only enable one of the child handles
>
> +        // as console device, i.e. sotre one of the child handle's device
>
> +        // path to variable "ConOut"
>
> +        // In future, we could select all child handles to be console device
>
> +        //
>
> +        *GopDevicePath = TempDevicePath;
>
> +
>
> +        //
>
> +        // Delete the PCI device's path that added by
> GetPlugInPciVgaDevicePath()
>
> +        // Add the integrity GOP device path.
>
> +        //
>
> +        EfiBootManagerUpdateConsoleVariable (ConOut, NULL, PciDevicePath);
>
> +        EfiBootManagerUpdateConsoleVariable (ConOut, TempDevicePath,
> NULL);
>
> +      }
>
> +    }
>
> +
>
> +    gBS->FreePool (GopHandleBuffer);
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Add PCI VGA to ConOut, ConIn, ErrOut.
>
> +
>
> +  @param[in]  DeviceHandle - Handle of PciIo protocol.
>
> +
>
> +  @retval EFI_SUCCESS  - PCI VGA is added to ConOut.
>
> +  @retval EFI_STATUS   - No PCI VGA device is added.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +PreparePciVgaDevicePath (
>
> +  IN EFI_HANDLE  DeviceHandle
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
>
> +
>
> +  DevicePath = NULL;
>
> +  Status     = gBS->HandleProtocol (
>
> +                      DeviceHandle,
>
> +                      &gEfiDevicePathProtocolGuid,
>
> +                      (VOID *)&DevicePath
>
> +                      );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  GetGopDevicePath (DevicePath, &GopDevicePath);
>
> +  DevicePath = GopDevicePath;
>
> +
>
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  For every PCI instance execute a callback function.
>
> +
>
> +  @param[in]  Id                 - The protocol GUID for callback
>
> +  @param[in]  CallBackFunction   - The callback function
>
> +
>
> +  @retval EFI_STATUS - Callback function failed.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +VisitAllInstancesOfProtocol (
>
> +  IN EFI_GUID                           *Id,
>
> +  IN SIMPLE_PROTOCOL_INSTANCE_CALLBACK  CallBackFunction
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +  UINTN       HandleCount;
>
> +  EFI_HANDLE  *HandleBuffer;
>
> +  UINTN       Index;
>
> +  VOID        *Instance;
>
> +
>
> +  //
>
> +  // Start to check all the PciIo to find all possible device
>
> +  //
>
> +  HandleCount  = 0;
>
> +  HandleBuffer = NULL;
>
> +  Status       = gBS->LocateHandleBuffer (
>
> +                        ByProtocol,
>
> +                        Id,
>
> +                        NULL,
>
> +                        &HandleCount,
>
> +                        &HandleBuffer
>
> +                        );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  for (Index = 0; Index < HandleCount; Index++) {
>
> +    Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
>
> +    if (EFI_ERROR (Status)) {
>
> +      continue;
>
> +    }
>
> +
>
> +    Status = (*CallBackFunction)(
>
> +  HandleBuffer[Index],
>
> +  Instance
>
> +  );
>
> +  }
>
> +
>
> +  gBS->FreePool (HandleBuffer);
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Do platform specific PCI Device check and add them to
>
> +  ConOut, ConIn, ErrOut.
>
> +
>
> +  @param[in]  Handle    - Handle of PCI device instance
>
> +  @param[in]  Instance  - The instance of PCI device
>
> +
>
> +  @retval EFI_SUCCESS - PCI Device check and Console variable update
> successfully.
>
> +  @retval EFI_STATUS - PCI Device check or Console variable update fail.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DetectAndPreparePlatformPciDevicePath (
>
> +  IN EFI_HANDLE  Handle,
>
> +  IN VOID        *Instance
>
> +  )
>
> +{
>
> +  EFI_STATUS           Status;
>
> +  EFI_PCI_IO_PROTOCOL  *PciIo;
>
> +  PCI_TYPE00           Pci;
>
> +
>
> +  EFI_HANDLE  CPMHandle;
>
> +
>
> +  PciIo = (EFI_PCI_IO_PROTOCOL *)Instance;
>
> +
>
> +  //
>
> +  // Check for all PCI device
>
> +  //
>
> +  Status = PciIo->Pci.Read (
>
> +                        PciIo,
>
> +                        EfiPciIoWidthUint32,
>
> +                        0,
>
> +                        sizeof (Pci) / sizeof (UINT32),
>
> +                        &Pci
>
> +                        );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = PciIo->Attributes (
>
> +                    PciIo,
>
> +                    EfiPciIoAttributeOperationEnable,
>
> +                    EFI_PCI_DEVICE_ENABLE,
>
> +                    NULL
>
> +                    );
>
> +  ASSERT_EFI_ERROR (Status);
>
> +
>
> +  if (!mDetectDisplayOnly) {
>
> +    //
>
> +    // Here we decide whether it is LPC Bridge
>
> +    //
>
> +    if ((IS_PCI_LPC (&Pci)) ||
>
> +        ((IS_PCI_ISA_PDECODE (&Pci)) &&
>
> +         (Pci.Hdr.VendorId == 0x8086)
>
> +        )
>
> +        )
>
> +    {
>
> +      //
>
> +      // Add IsaKeyboard to ConIn,
>
> +      // add IsaSerial to ConOut, ConIn, ErrOut
>
> +      //
>
> +      DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
>
> +      PrepareLpcBridgeDevicePath (Handle);
>
> +      return EFI_SUCCESS;
>
> +    }
>
> +  }
>
> +
>
> +  //
>
> +  // Enable all display devices
>
> +  //
>
> +  if (IS_PCI_DISPLAY (&Pci)) {
>
> +    //
>
> +    // Add them to ConOut.
>
> +    //
>
> +    DEBUG ((DEBUG_INFO, "Found PCI Display device\n"));
>
> +    EfiBootManagerConnectVideoController (Handle);
>
> +    //
>
> +    // At this point, all the PCI_IO protocols are installed completely.
>
> +    // Install gAmdCpmAllPciIoProtocolsInstalledProtocolGuid protocol for
> AmdCpmDisplayFeature DXE driver.
>
> +    //
>
> +    CPMHandle = NULL;
>
> +    Status    = gBS->InstallProtocolInterface (
>
> +                       &CPMHandle,
>
> +                       &gAmdCpmAllPciIoProtocolsInstalledProtocolGuid,
>
> +                       EFI_NATIVE_INTERFACE,
>
> +                       NULL
>
> +                       );
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    DEBUG ((EFI_D_INFO, "InstallProtocolInterface
> gAmdCpmAllPciIoProtocolsInstalledProtocolGuid %r\n", Status));
>
> +    return EFI_SUCCESS;
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  For every Serial Io instance, add it to ConOut, ConIn, ErrOut.
>
> +
>
> +  @param[in]  Handle     - The Serial Io device handle
>
> +  @param[in]  Instance   - The instance of the SerialIo protocol
>
> +
>
> +  @retval EFI_STATUS - Callback function failed.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +AddDevicePathForOneSerialIoInstance (
>
> +  IN EFI_HANDLE  Handle,
>
> +  IN VOID        *Instance
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
>
> +
>
> +  DevicePath = NULL;
>
> +  Status     = gBS->HandleProtocol (
>
> +                      Handle,
>
> +                      &gEfiDevicePathProtocolGuid,
>
> +                      (VOID *)&DevicePath
>
> +                      );
>
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
>
> +
>
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
>
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
>
> +  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  Do platform specific PCI Device check and add them to ConOut, ConIn,
> ErrOut
>
> +
>
> +  @param[in]  DetectDisplayOnly - Only detect display device if it's TRUE.
>
> +
>
> +  @retval EFI_SUCCESS - PCI Device check and Console variable update
> successfully.
>
> +  @retval EFI_STATUS - PCI Device check or Console variable update fail.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +DetectAndPreparePlatformPciDevicePaths (
>
> +  BOOLEAN  DetectDisplayOnly
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +
>
> +  mDetectDisplayOnly = DetectDisplayOnly;
>
> +
>
> +  EfiBootManagerUpdateConsoleVariable (
>
> +    ConIn,
>
> +    (EFI_DEVICE_PATH_PROTOCOL *)&gUsbClassKeyboardDevicePath,
>
> +    NULL
>
> +    );
>
> +
>
> +  VisitAllInstancesOfProtocol (
>
> +    &gEfiSerialIoProtocolGuid,
>
> +    AddDevicePathForOneSerialIoInstance
>
> +    );
>
> +
>
> +  Status = VisitAllInstancesOfProtocol (
>
> +             &gEfiPciIoProtocolGuid,
>
> +             DetectAndPreparePlatformPciDevicePath
>
> +             );
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  The function will connect one root bridge
>
> +
>
> +  @param[in]  Handle     - The root bridge handle
>
> +  @param[in]  Instance   - The instance of the root bridge
>
> +
>
> +  @return EFI_SUCCESS      Connect RootBridge successfully.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ConnectOneRootBridge (
>
> +  IN EFI_HANDLE  Handle,
>
> +  IN VOID        *Instance
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +
>
> +  Status = gBS->ConnectController (Handle, NULL, NULL, FALSE);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Platform console init. Include the platform firmware vendor, revision
>
> +  and so crc check.
>
> +
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +PlatformConsoleInit (
>
> +  VOID
>
> +  )
>
> +{
>
> +  VisitAllInstancesOfProtocol (
>
> +    &gEfiPciRootBridgeIoProtocolGuid,
>
> +    ConnectOneRootBridge
>
> +    );
>
> +
>
> +  //
>
> +  // Do platform specific PCI Device check and add them to ConOut, ConIn,
> ErrOut
>
> +  //
>
> +  DetectAndPreparePlatformPciDevicePaths (FALSE);
>
> +}
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformConsole.h
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformConsole.h
>
> new file mode 100644
>
> index 0000000000..a43583fb17
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformConsole.h
>
> @@ -0,0 +1,78 @@
>
> +/** @file
>
> +  Implements PlatformConsole.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
>
> +Head file for BDS Platform specific code
>
> +
>
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#ifndef PLATFORM_CONSOLE_H_
>
> +#define PLATFORM_CONSOLE_H_
>
> +
>
> +#include <PiDxe.h>
>
> +#include <IndustryStandard/Pci.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/PcdLib.h>
>
> +#include <Library/UefiLib.h>
>
> +#include <Library/DevicePathLib.h>
>
> +#include <Protocol/PciIo.h>
>
> +
>
> +#define IS_PCI_ISA_PDECODE(_p)  IS_CLASS3 (_p, PCI_CLASS_BRIDGE,
> PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
>
> +
>
> +//
>
> +// Type definitions
>
> +//
>
> +
>
> +//
>
> +// Platform Root Bridge
>
> +//
>
> +typedef struct {
>
> +  ACPI_HID_DEVICE_PATH        PciRootBridge;
>
> +  EFI_DEVICE_PATH_PROTOCOL    End;
>
> +} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
>
> +
>
> +typedef
>
> +EFI_STATUS
>
> +(EFIAPI *SIMPLE_PROTOCOL_INSTANCE_CALLBACK)(
>
> +  IN EFI_HANDLE            Handle,
>
> +  IN VOID                 *Instance
>
> +  );
>
> +
>
> +/**
>
> +  @param[in]  Handle - Handle of PCI device instance
>
> +  @param[in]  PciIo - PCI IO protocol instance
>
> +  @param[in]  Pci - PCI Header register block
>
> +**/
>
> +typedef
>
> +EFI_STATUS
>
> +(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
>
> +  IN EFI_HANDLE           Handle,
>
> +  IN EFI_PCI_IO_PROTOCOL  *PciIo,
>
> +  IN PCI_TYPE00           *Pci
>
> +  );
>
> +
>
> +/**
>
> +  Platform console init. Include the platform firmware vendor, revision
>
> +  and so crc check.
>
> +
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +PlatformConsoleInit (
>
> +  VOID
>
> +  );
>
> +
>
> +#endif
>
> diff --git
> a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformData.c
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformData.c
>
> new file mode 100644
>
> index 0000000000..5f4cba87a7
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Platfor
> mBootManagerLib/PlatformData.c
>
> @@ -0,0 +1,48 @@
>
> +/** @file
>
> +  Implements PlatformData.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
>
> +  Defined the platform specific device path which will be filled to
>
> +  ConIn/ConOut variables.
>
> +
>
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#include "PlatformBootManager.h"
>
> +
>
> +///
>
> +/// Predefined platform default console device path
>
> +///
>
> +GLOBAL_REMOVE_IF_UNREFERENCED
> PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[] = {
>
> +  {
>
> +    NULL,
>
> +    0
>
> +  }
>
> +};
>
> +
>
> +GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH
> gUsbClassKeyboardDevicePath = {
>
> +  {
>
> +    {
>
> +      MESSAGING_DEVICE_PATH,
>
> +      MSG_USB_CLASS_DP,
>
> +      {
>
> +        (UINT8)(sizeof (USB_CLASS_DEVICE_PATH)),
>
> +        (UINT8)((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
>
> +      }
>
> +    },
>
> +    0xffff,           // VendorId
>
> +    0xffff,           // ProductId
>
> +    CLASS_HID,        // DeviceClass
>
> +    SUBCLASS_BOOT,    // DeviceSubClass
>
> +    PROTOCOL_KEYBOARD // DeviceProtocol
>
> +  },
>
> +  gEndEntire
>
> +};
>
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
>
> new file mode 100644
>
> index 0000000000..c99dd4cd47
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
>
> @@ -0,0 +1,122 @@
>
> +## @file
>
> +#  Capsule Runtime DXE Module INF file
>
> +#
>
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +## @file
>
> +#  Capsule Runtime Driver produces two UEFI capsule runtime services:
> (UpdateCapsule, QueryCapsuleCapabilities).
>
> +#
>
> +#  It installs the Capsule Architectural Protocol defined in PI1.0a to signify
>
> +#  the capsule runtime services are ready.
>
> +#
>
> +#  Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
>
> +#  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> reserved.<BR>
>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> +  INF_VERSION                    = 0x00010005
>
> +  BASE_NAME                      = CapsuleRuntimeDxe
>
> +  MODULE_UNI_FILE                = CapsuleRuntimeDxe.uni
>
> +  FILE_GUID                      = 42857F0A-13F2-4B21-8A23-53D3F714B840
>
> +  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
>
> +  VERSION_STRING                 = 1.0
>
> +  ENTRY_POINT                    = CapsuleServiceInitialize
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the build
> tools.
>
> +#
>
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC ARM AARCH64 RISCV64
>
> +#
>
> +
>
> +[Sources]
>
> +  CapsuleService.c
>
> +  CapsuleService.h
>
> +
>
> +[Sources.Ia32, Sources.EBC, Sources.ARM, Sources.AARCH64,
> Sources.RISCV64]
>
> +  SaveLongModeContext.c
>
> +
>
> +[Sources.Ia32, Sources.X64, Sources.ARM, Sources.AARCH64,
> Sources.RISCV64]
>
> +  CapsuleCache.c
>
> +
>
> +[Sources.Ia32, Sources.X64, Sources.EBC, Sources.RISCV64]
>
> +  CapsuleReset.c
>
> +
>
> +[Sources.ARM, Sources.AARCH64]
>
> +  Arm/CapsuleReset.c
>
> +
>
> +[Sources.EBC]
>
> +  CapsuleCacheNull.c
>
> +
>
> +[Sources.X64]
>
> +  X64/SaveLongModeContext.c
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +  VanGoghCommonPkg/AmdCommonPkg.dec
>
> +
>
> +[LibraryClasses]
>
> +  UefiBootServicesTableLib
>
> +  PcdLib
>
> +  DebugLib
>
> +  UefiRuntimeServicesTableLib
>
> +  UefiDriverEntryPoint
>
> +  CapsuleLib
>
> +  UefiRuntimeLib
>
> +  BaseLib
>
> +  PrintLib
>
> +  BaseMemoryLib
>
> +  CacheMaintenanceLib
>
> +  IoLib
>
> +
>
> +[LibraryClasses.X64]
>
> +  UefiLib
>
> +  BaseMemoryLib
>
> +
>
> +[Guids]
>
> +  ## SOMETIMES_PRODUCES   ## Variable:L"CapsuleUpdateData" # (Process
> across reset capsule image) for capsule updated data
>
> +  ## SOMETIMES_PRODUCES   ## Variable:L"CapsuleLongModeBuffer" # The
> long mode buffer used by IA32 Capsule PEIM to call X64 CapsuleCoalesce code
> to handle >4GB capsule blocks
>
> +  gEfiCapsuleVendorGuid
>
> +  gEfiFmpCapsuleGuid                            ## SOMETIMES_CONSUMES   ## GUID #
> FMP capsule GUID
>
> +  gAmdSetCapsuleS3FlagGuid                      ## SOMETIMES_CONSUMES
>
> +  gEfiEventVirtualAddressChangeGuid             ## CONSUMES
>
> +
>
> +[Protocols]
>
> +  gEfiCapsuleArchProtocolGuid                   ## PRODUCES
>
> +  gEfiMmCommunication2ProtocolGuid              ## CONSUMES
>
> +
>
> +[Protocols.X64]
>
> +  ## UNDEFINED ## NOTIFY
>
> +  ## SOMETIMES_CONSUMES
>
> +  gEdkiiVariableLockProtocolGuid
>
> +
>
> +[FeaturePcd]
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset        ##
> CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportProcessCapsuleAtRuntime
> ## CONSUMES
>
> +
>
> +[FeaturePcd.X64]
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ##
> CONSUMES
>
> +
>
> +[Pcd]
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule   ##
> SOMETIMES_CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule      ##
> SOMETIMES_CONSUMES # Populate Image requires reset support.
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport         ##
> CONSUMES
>
> +
>
> +[Pcd.X64]
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize   ##
> SOMETIMES_CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable                ##
> SOMETIMES_CONSUMES
>
> +
>
> +[Depex]
>
> +  gEfiVariableWriteArchProtocolGuid AND            # Depends on variable write
> functionality to produce capsule data variable
>
> +  gEfiMmCommunication2ProtocolGuid                 # Perform AMD Specific flags
> settings
>
> +
>
> +# [Hob.X64]
>
> +# UNDEFINED                 ## SOMETIMES_CONSUMES # CPU
>
> +
>
> +[UserExtensions.TianoCore."ExtraFiles"]
>
> +  CapsuleRuntimeDxeExtra.uni
>
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> CapsuleRuntimeDxe/CapsuleService.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> CapsuleRuntimeDxe/CapsuleService.c
>
> new file mode 100644
>
> index 0000000000..45e9e40e2f
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> CapsuleRuntimeDxe/CapsuleService.c
>
> @@ -0,0 +1,470 @@
>
> +/** @file
>
> +  Implements CapsuleService.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
>
> +  Capsule Runtime Driver produces two UEFI capsule runtime services.
>
> +  (UpdateCapsule, QueryCapsuleCapabilities)
>
> +  It installs the Capsule Architectural Protocol defined in PI1.0a to signify
>
> +  the capsule runtime services are ready.
>
> +
>
> +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include "CapsuleService.h"
>
> +
>
> +#include <Library/IoLib.h>
>
> +
>
> +//
>
> +// Handle for the installation of Capsule Architecture Protocol.
>
> +//
>
> +EFI_HANDLE  mNewHandle = NULL;
>
> +
>
> +//
>
> +// The times of calling UpdateCapsule ()
>
> +//
>
> +UINTN  mTimes = 0;
>
> +
>
> +UINT32  mMaxSizePopulateCapsule    = 0;
>
> +UINT32  mMaxSizeNonPopulateCapsule = 0;
>
> +
>
> +// Cached MM Communication protocol.
>
> +EFI_MM_COMMUNICATION2_PROTOCOL  *mMmCommunication2 = NULL;
>
> +
>
> +// For MM Communication purpose.
>
> +EFI_MM_COMMUNICATE_HEADER  *mCommunicationBuffer         = NULL;
>
> +EFI_MM_COMMUNICATE_HEADER  *mCommunicationBufferPhysical =
> NULL;
>
> +EFI_EVENT                  mVirtualAddressChangeEvent    = NULL;
>
> +extern EFI_GUID            gAmdSetCapsuleS3FlagGuid;
>
> +
>
> +/**
>
> +  Passes capsules to the firmware with both virtual and physical mapping.
> Depending on the intended
>
> +  consumption, the firmware may process the capsule immediately. If the
> payload should persist
>
> +  across a system reset, the reset value returned from
> EFI_QueryCapsuleCapabilities must
>
> +  be passed into ResetSystem() and will cause the capsule to be processed by
> the firmware as
>
> +  part of the reset process.
>
> +
>
> +  @param  CapsuleHeaderArray    Virtual pointer to an array of virtual
> pointers to the capsules
>
> +                                being passed into update capsule.
>
> +  @param  CapsuleCount          Number of pointers to EFI_CAPSULE_HEADER
> in
>
> +                                CaspuleHeaderArray.
>
> +  @param  ScatterGatherList     Physical pointer to a set of
>
> +                                EFI_CAPSULE_BLOCK_DESCRIPTOR that describes the
>
> +                                location in physical memory of a set of capsules.
>
> +
>
> +  @retval EFI_SUCCESS           Valid capsule was passed. If
>
> +                                CAPSULE_FLAGS_PERSIT_ACROSS_RESET is not set, the
>
> +                                capsule has been successfully processed by the firmware.
>
> +  @retval EFI_DEVICE_ERROR      The capsule update was started, but failed
> due to a device error.
>
> +  @retval EFI_INVALID_PARAMETER CapsuleSize is NULL, or an incompatible
> set of flags were
>
> +                                set in the capsule header.
>
> +  @retval EFI_INVALID_PARAMETER CapsuleCount is Zero.
>
> +  @retval EFI_INVALID_PARAMETER For across reset capsule image,
> ScatterGatherList is NULL.
>
> +  @retval EFI_UNSUPPORTED       CapsuleImage is not recognized by the
> firmware.
>
> +  @retval EFI_OUT_OF_RESOURCES  When ExitBootServices() has been
> previously called this error indicates the capsule
>
> +                                is compatible with this platform but is not capable of being
> submitted or processed
>
> +                                in runtime. The caller may resubmit the capsule prior to
> ExitBootServices().
>
> +  @retval EFI_OUT_OF_RESOURCES  When ExitBootServices() has not been
> previously called then this error indicates
>
> +                                the capsule is compatible with this platform but there are
> insufficient resources to process.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UpdateCapsule (
>
> +  IN EFI_CAPSULE_HEADER    **CapsuleHeaderArray,
>
> +  IN UINTN                 CapsuleCount,
>
> +  IN EFI_PHYSICAL_ADDRESS  ScatterGatherList OPTIONAL
>
> +  )
>
> +{
>
> +  UINTN               ArrayNumber;
>
> +  EFI_STATUS          Status;
>
> +  EFI_CAPSULE_HEADER  *CapsuleHeader;
>
> +  BOOLEAN             NeedReset;
>
> +  BOOLEAN             InitiateReset;
>
> +  CHAR16              CapsuleVarName[30];
>
> +  CHAR16              *TempVarName;
>
> +
>
> +  //
>
> +  // Check if platform support Capsule In RAM or not.
>
> +  // Platform could choose to drop CapsulePei/CapsuleX64 and do not
> support Capsule In RAM.
>
> +  //
>
> +  if (!PcdGetBool (PcdCapsuleInRamSupport)) {
>
> +    return EFI_UNSUPPORTED;
>
> +  }
>
> +
>
> +  //
>
> +  // Capsule Count can't be less than one.
>
> +  //
>
> +  if (CapsuleCount < 1) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  NeedReset         = FALSE;
>
> +  InitiateReset     = FALSE;
>
> +  CapsuleHeader     = NULL;
>
> +  CapsuleVarName[0] = 0;
>
> +
>
> +  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
>
> +    //
>
> +    // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
> flag must have
>
> +    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
>
> +    //
>
> +    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
>
> +    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET |
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) ==
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
>
> +      return EFI_INVALID_PARAMETER;
>
> +    }
>
> +
>
> +    //
>
> +    // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must
> have
>
> +    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
>
> +    //
>
> +    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET |
> CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
>
> +      return EFI_INVALID_PARAMETER;
>
> +    }
>
> +
>
> +    //
>
> +    // Check FMP capsule flag
>
> +    //
>
> +    if (  CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)
>
> +       && ((CapsuleHeader->Flags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0))
>
> +    {
>
> +      return EFI_INVALID_PARAMETER;
>
> +    }
>
> +
>
> +    //
>
> +    // Check Capsule image without populate flag by firmware support capsule
> function
>
> +    //
>
> +    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)
> == 0) {
>
> +      Status = SupportCapsuleImage (CapsuleHeader);
>
> +      if (EFI_ERROR (Status)) {
>
> +        return Status;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  //
>
> +  // Walk through all capsules, record whether there is a capsule needs reset
>
> +  // or initiate reset. And then process capsules which has no reset flag
> directly.
>
> +  //
>
> +  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
>
> +    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
>
> +    //
>
> +    // Here should be in the boot-time for non-reset capsule image
>
> +    // Platform specific update for the non-reset capsule image.
>
> +    //
>
> +    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) ==
> 0) {
>
> +      if (EfiAtRuntime () && !FeaturePcdGet
> (PcdSupportProcessCapsuleAtRuntime)) {
>
> +        Status = EFI_OUT_OF_RESOURCES;
>
> +      } else {
>
> +        Status = ProcessCapsuleImage (CapsuleHeader);
>
> +      }
>
> +
>
> +      if (EFI_ERROR (Status)) {
>
> +        return Status;
>
> +      }
>
> +    } else {
>
> +      NeedReset = TRUE;
>
> +      if ((CapsuleHeader->Flags & CAPSULE_FLAGS_INITIATE_RESET) != 0) {
>
> +        InitiateReset = TRUE;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  //
>
> +  // After launching all capsules who has no reset flag, if no more capsules
> claims
>
> +  // for a system reset just return.
>
> +  //
>
> +  if (!NeedReset) {
>
> +    return EFI_SUCCESS;
>
> +  }
>
> +
>
> +  //
>
> +  // ScatterGatherList is only referenced if the capsules are defined to persist
> across
>
> +  // system reset.
>
> +  //
>
> +  if (ScatterGatherList == (EFI_PHYSICAL_ADDRESS)(UINTN)NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  //
>
> +  // Check if the platform supports update capsule across a system reset
>
> +  //
>
> +  if (!IsPersistAcrossResetCapsuleSupported ()) {
>
> +    return EFI_UNSUPPORTED;
>
> +  }
>
> +
>
> +  CapsuleCacheWriteBack (ScatterGatherList);
>
> +
>
> +  //
>
> +  // Construct variable name CapsuleUpdateData, CapsuleUpdateData1,
> CapsuleUpdateData2...
>
> +  // if user calls UpdateCapsule multiple times.
>
> +  //
>
> +  StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CHAR16),
> EFI_CAPSULE_VARIABLE_NAME);
>
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
>
> +  if (mTimes > 0) {
>
> +    UnicodeValueToStringS (
>
> +      TempVarName,
>
> +      sizeof (CapsuleVarName) - ((UINTN)TempVarName -
> (UINTN)CapsuleVarName),
>
> +      0,
>
> +      mTimes,
>
> +      0
>
> +      );
>
> +  }
>
> +
>
> +  //
>
> +  // ScatterGatherList is only referenced if the capsules are defined to persist
> across
>
> +  // system reset. Set its value into NV storage to let pre-boot driver to pick it
> up
>
> +  // after coming through a system reset.
>
> +  //
>
> +  Status = EfiSetVariable (
>
> +             CapsuleVarName,
>
> +             &gEfiCapsuleVendorGuid,
>
> +             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
>
> +             sizeof (UINTN),
>
> +             (VOID *)&ScatterGatherList
>
> +             );
>
> +  if (!EFI_ERROR (Status)) {
>
> +    //
>
> +    // Variable has been set successfully, increase variable index.
>
> +    //
>
> +    mTimes++;
>
> +    if (InitiateReset) {
>
> +      //
>
> +      // Firmware that encounters a capsule which has the
> CAPSULE_FLAGS_INITIATE_RESET Flag set in its header
>
> +      // will initiate a reset of the platform which is compatible with the passed-
> in capsule request and will
>
> +      // not return back to the caller.
>
> +      //
>
> +      // EfiResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
>
> +      // Invoke AMD Specific S3.
>
> +      DEBUG ((DEBUG_INFO, "Setting AMD Specific S3 Flag.\n"));
>
> +      Status = mMmCommunication2->Communicate (
>
> +                                    mMmCommunication2,
>
> +                                    mCommunicationBufferPhysical,
>
> +                                    mCommunicationBuffer,
>
> +                                    NULL
>
> +                                    );
>
> +    }
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  Returns if the capsule can be supported via UpdateCapsule().
>
> +  Notice: When PcdCapsuleInRamSupport is unsupported, even this routine
> returns a valid answer,
>
> +  the capsule still is unsupported via UpdateCapsule().
>
> +
>
> +  @param  CapsuleHeaderArray    Virtual pointer to an array of virtual
> pointers to the capsules
>
> +                                being passed into update capsule.
>
> +  @param  CapsuleCount          Number of pointers to EFI_CAPSULE_HEADER
> in
>
> +                                CaspuleHeaderArray.
>
> +  @param  MaxiumCapsuleSize     On output the maximum size that
> UpdateCapsule() can
>
> +                                support as an argument to UpdateCapsule() via
>
> +                                CapsuleHeaderArray and ScatterGatherList.
>
> +  @param  ResetType             Returns the type of reset required for the capsule
> update.
>
> +
>
> +  @retval EFI_SUCCESS           Valid answer returned.
>
> +  @retval EFI_UNSUPPORTED       The capsule image is not supported on this
> platform, and
>
> +                                MaximumCapsuleSize and ResetType are undefined.
>
> +  @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL, or
> ResetTyep is NULL,
>
> +                                Or CapsuleCount is Zero, or CapsuleImage is not valid.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +QueryCapsuleCapabilities (
>
> +  IN  EFI_CAPSULE_HEADER  **CapsuleHeaderArray,
>
> +  IN  UINTN               CapsuleCount,
>
> +  OUT UINT64              *MaxiumCapsuleSize,
>
> +  OUT EFI_RESET_TYPE      *ResetType
>
> +  )
>
> +{
>
> +  EFI_STATUS          Status;
>
> +  UINTN               ArrayNumber;
>
> +  EFI_CAPSULE_HEADER  *CapsuleHeader;
>
> +  BOOLEAN             NeedReset;
>
> +
>
> +  //
>
> +  // Capsule Count can't be less than one.
>
> +  //
>
> +  if (CapsuleCount < 1) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  //
>
> +  // Check whether input parameter is valid
>
> +  //
>
> +  if ((MaxiumCapsuleSize == NULL) || (ResetType == NULL)) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  CapsuleHeader = NULL;
>
> +  NeedReset     = FALSE;
>
> +
>
> +  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
>
> +    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
>
> +    //
>
> +    // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
> flag must have
>
> +    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
>
> +    //
>
> +    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET |
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) ==
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
>
> +      return EFI_INVALID_PARAMETER;
>
> +    }
>
> +
>
> +    //
>
> +    // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must
> have
>
> +    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
>
> +    //
>
> +    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET |
> CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
>
> +      return EFI_INVALID_PARAMETER;
>
> +    }
>
> +
>
> +    //
>
> +    // Check FMP capsule flag
>
> +    //
>
> +    if (  CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)
>
> +       && ((CapsuleHeader->Flags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0))
>
> +    {
>
> +      return EFI_INVALID_PARAMETER;
>
> +    }
>
> +
>
> +    //
>
> +    // Check Capsule image without populate flag is supported by firmware
>
> +    //
>
> +    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)
> == 0) {
>
> +      Status = SupportCapsuleImage (CapsuleHeader);
>
> +      if (EFI_ERROR (Status)) {
>
> +        return Status;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  //
>
> +  // Find out whether there is any capsule defined to persist across system
> reset.
>
> +  //
>
> +  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
>
> +    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
>
> +    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) !=
> 0) {
>
> +      NeedReset = TRUE;
>
> +      break;
>
> +    }
>
> +  }
>
> +
>
> +  if (NeedReset) {
>
> +    //
>
> +    // Check if the platform supports update capsule across a system reset
>
> +    //
>
> +    if (!IsPersistAcrossResetCapsuleSupported ()) {
>
> +      return EFI_UNSUPPORTED;
>
> +    }
>
> +
>
> +    *ResetType         = EfiResetWarm;
>
> +    *MaxiumCapsuleSize = (UINT64)mMaxSizePopulateCapsule;
>
> +  } else {
>
> +    //
>
> +    // For non-reset capsule image.
>
> +    //
>
> +    *ResetType         = EfiResetCold;
>
> +    *MaxiumCapsuleSize = (UINT64)mMaxSizeNonPopulateCapsule;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
>
> +
>
> +  Here it converts the SMM Communicate buffer address into virtual.
>
> +
>
> +  @param[in]  Event        Event whose notification function is being invoked.
>
> +  @param[in]  Context      Pointer to the notification function's context.
>
> +
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +VariableAddressChangeEvent (
>
> +  IN EFI_EVENT  Event,
>
> +  IN VOID       *Context
>
> +  )
>
> +{
>
> +  EfiConvertPointer (0x0, (VOID **)&mCommunicationBuffer);
>
> +  EfiConvertPointer (0x0, (VOID **)&mMmCommunication2);
>
> +}
>
> +
>
> +/**
>
> +
>
> +  This code installs UEFI capsule runtime service.
>
> +
>
> +  @param  ImageHandle    The firmware allocated handle for the EFI image.
>
> +  @param  SystemTable    A pointer to the EFI System Table.
>
> +
>
> +  @retval EFI_SUCCESS    UEFI Capsule Runtime Services are installed
> successfully.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +CapsuleServiceInitialize (
>
> +  IN EFI_HANDLE        ImageHandle,
>
> +  IN EFI_SYSTEM_TABLE  *SystemTable
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +
>
> +  mMaxSizePopulateCapsule    = PcdGet32 (PcdMaxSizePopulateCapsule);
>
> +  mMaxSizeNonPopulateCapsule = PcdGet32
> (PcdMaxSizeNonPopulateCapsule);
>
> +
>
> +  //
>
> +  // When PEI phase is IA32, DXE phase is X64, it is possible that capsule data
> are
>
> +  // put above 4GB, so capsule PEI will transfer to long mode to get capsule
> data.
>
> +  // The page table and stack is used to transfer processor mode from IA32 to
> long mode.
>
> +  // Create the base address of page table and stack, and save them into
> variable.
>
> +  // This is not needed when capsule with reset type is not supported.
>
> +  //
>
> +  SaveLongModeContext ();
>
> +
>
> +  //
>
> +  // Install capsule runtime services into UEFI runtime service tables.
>
> +  //
>
> +  gRT->UpdateCapsule            = UpdateCapsule;
>
> +  gRT->QueryCapsuleCapabilities = QueryCapsuleCapabilities;
>
> +
>
> +  //
>
> +  // Install the Capsule Architectural Protocol on a new handle
>
> +  // to signify the capsule runtime services are ready.
>
> +  //
>
> +  Status = gBS->InstallMultipleProtocolInterfaces (
>
> +                  &mNewHandle,
>
> +                  &gEfiCapsuleArchProtocolGuid,
>
> +                  NULL,
>
> +                  NULL
>
> +                  );
>
> +  ASSERT_EFI_ERROR (Status);
>
> +
>
> +  Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid,
> NULL, (VOID **)&mMmCommunication2);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +  Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof
> (EFI_MM_COMMUNICATE_HEADER), (VOID
> **)&mCommunicationBufferPhysical);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +  CopyGuid (&(mCommunicationBufferPhysical->HeaderGuid),
> &gAmdSetCapsuleS3FlagGuid);
>
> +  mCommunicationBufferPhysical->MessageLength = 0;
>
> +  mCommunicationBuffer                        = mCommunicationBufferPhysical;
>
> +
>
> +  // Create an event to update SMM pointers.
>
> +  gBS->CreateEventEx (
>
> +         EVT_NOTIFY_SIGNAL,
>
> +         TPL_NOTIFY,
>
> +         VariableAddressChangeEvent,
>
> +         NULL,
>
> +         &gEfiEventVirtualAddressChangeGuid,
>
> +         &mVirtualAddressChangeEvent
>
> +         );
>
> +
>
> +  return Status;
>
> +}
>
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> CapsuleRuntimeDxe/CapsuleService.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> CapsuleRuntimeDxe/CapsuleService.h
>
> new file mode 100644
>
> index 0000000000..d5df075e46
>
> --- /dev/null
>
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> CapsuleRuntimeDxe/CapsuleService.h
>
> @@ -0,0 +1,82 @@
>
> +/** @file
>
> +  Implements CapsuleService.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
>
> +  Capsule Runtime Driver produces two UEFI capsule runtime services.
>
> +  (UpdateCapsule, QueryCapsuleCapabilities)
>
> +  It installs the Capsule Architectural Protocol defined in PI1.0a to signify
>
> +  the capsule runtime services are ready.
>
> +
>
> +  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
>
> +  Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
>
> +
>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#ifndef _CAPSULE_SERVICE_H_
>
> +#define _CAPSULE_SERVICE_H_
>
> +
>
> +#include <Uefi.h>
>
> +
>
> +#include <Protocol/Capsule.h>
>
> +#include <Protocol/MmCommunication2.h>
>
> +#include <Guid/CapsuleVendor.h>
>
> +#include <Guid/FmpCapsule.h>
>
> +#include <Guid/EventGroup.h>
>
> +
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/PcdLib.h>
>
> +#include <Library/CapsuleLib.h>
>
> +#include <Library/UefiDriverEntryPoint.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>
> +#include <Library/UefiRuntimeLib.h>
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/PrintLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +
>
> +/**
>
> +  Create the variable to save the base address of page table and stack
>
> +  for transferring into long mode in IA32 PEI.
>
> +**/
>
> +VOID
>
> +SaveLongModeContext (
>
> +  VOID
>
> +  );
>
> +
>
> +/**
>
> +  Whether the platform supports capsules that persist across reset. Note that
>
> +  some platforms only support such capsules at boot time.
>
> +
>
> +  @return TRUE  if a PersistAcrossReset capsule may be passed to
> UpdateCapsule()
>
> +                at this time
>
> +          FALSE otherwise
>
> +**/
>
> +BOOLEAN
>
> +IsPersistAcrossResetCapsuleSupported (
>
> +  VOID
>
> +  );
>
> +
>
> +/**
>
> +  Writes Back a range of data cache lines covering a set of capsules in memory.
>
> +
>
> +  Writes Back the data cache lines specified by ScatterGatherList.
>
> +
>
> +  @param  ScatterGatherList Physical address of the data structure that
>
> +                            describes a set of capsules in memory
>
> +
>
> +**/
>
> +VOID
>
> +CapsuleCacheWriteBack (
>
> +  IN  EFI_PHYSICAL_ADDRESS  ScatterGatherList
>
> +  );
>
> +
>
> +#endif
>
> --
>
> 2.31.1
>
>



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114169): https://edk2.groups.io/g/devel/message/114169
Mute This Topic: https://groups.io/mt/103831164/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  reply	other threads:[~2024-01-23  4:42 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-18  6:50 [edk2-devel] [PATCH 00/33] Introduce AMD Vangogh platform reference code duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 01/33] AMD/AmdPlatformPkg: Check in AMD S3 logo duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 02/33] AMD/VanGoghBoard: Check in ACPI tables duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 03/33] AMD/VanGoghBoard: Check in Capsule update duke.zhai via groups.io
2024-01-23  4:42   ` Chang, Abner via groups.io [this message]
2024-01-25  8:25     ` Zhai, MingXin (Duke) via groups.io
2024-01-25 11:45       ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 04/33] AMD/VanGoghBoard: Check in AgesaPublic pkg duke.zhai via groups.io
2024-01-23  4:44   ` Chang, Abner via groups.io
2024-01-25  8:17     ` Xing, Eric via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 05/33] AMD/VanGoghBoard: Check in PlatformSecLib duke.zhai via groups.io
2024-01-23  4:46   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 06/33] AMD/VanGoghBoard: Check in AmdIdsExtLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 07/33] AMD/VanGoghBoard: Check in PciPlatform duke.zhai via groups.io
2024-01-23  4:50   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 08/33] AMD/VanGoghBoard: Check in UDKFlashUpdate duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 09/33] AMD/VanGoghBoard: Check in Flash_AB duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 10/33] AMD/VanGoghBoard: Check in FlashUpdate duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 11/33] AMD/VanGoghBoard: Check in FvbServices duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 12/33] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 13/33] AMD/VanGoghBoard: Check in PlatformFlashAccessLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 14/33] AMD/VanGoghBoard: Check in SmbiosLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 15/33] AMD/VanGoghBoard: Check in SpiFlashDeviceLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 16/33] AMD/VanGoghBoard: Check in BaseTscTimerLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 17/33] AMD/VanGoghBoard: Check in Smm access module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 18/33] AMD/VanGoghBoard: Check in PciHostBridge module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 19/33] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 20/33] AMD/VanGoghBoard: Check in FTPM module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 21/33] AMD/VanGoghBoard: Check in SignedCapsule duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 22/33] AMD/VanGoghBoard: Check in Vtf0 duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 23/33] AMD/VanGoghBoard: Check in AcpiPlatform duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 24/33] AMD/VanGoghBoard: Check in FchSpi module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 25/33] AMD/VanGoghBoard: Check in PlatformInitPei module duke.zhai via groups.io
2024-01-23  6:35   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 26/33] AMD/VanGoghBoard: Check in Smbios platform dxe drivers duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 27/33] AMD/VanGoghBoard: Check in Fsp2WrapperPkg duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 28/33] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module duke.zhai via groups.io
2024-01-23  5:14   ` Chang, Abner via groups.io
2024-01-23 10:20     ` Xing, Eric via groups.io
2024-01-23 10:44       ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 29/33] AMD/VanGoghBoard: Check in SmramSaveState module duke.zhai via groups.io
2024-01-20 14:37   ` Abdul Lateef Attar via groups.io
2024-01-23  5:15     ` Chang, Abner via groups.io
2024-01-23 10:27       ` Xing, Eric via groups.io
2024-01-23 10:44         ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 30/33] AMD/VanGoghBoard: Check in EDK2 override files duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 31/33] AMD/VanGoghBoard: Check in AMD SmmControlPei module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 32/33] AMD/VanGoghBoard: Check in Chachani board project files and build script duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 33/33] AMD/VanGoghBoard: Improvement coding style duke.zhai via groups.io

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=LV8PR12MB94527F685A7C9ACFF7C979BBEA742@LV8PR12MB9452.namprd12.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox