From: "Zhai, MingXin (Duke) via groups.io" <duke.zhai=amd.com@groups.io>
To: "Chang, Abner" <Abner.Chang@amd.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Xing, Eric" <Eric.Xing@amd.com>, "Fu, Igniculus" <Igniculus.Fu@amd.com>
Subject: Re: [edk2-devel] [PATCH 03/33] AMD/VanGoghBoard: Check in Capsule update
Date: Thu, 25 Jan 2024 08:25:59 +0000 [thread overview]
Message-ID: <DS0PR12MB94453E0A1E8E60F045C0D027F67A2@DS0PR12MB9445.namprd12.prod.outlook.com> (raw)
In-Reply-To: <LV8PR12MB94527F685A7C9ACFF7C979BBEA742@LV8PR12MB9452.namprd12.prod.outlook.com>
[AMD Official Use Only - General]
Hi Abner,
Thanks for your review, we have V2 patch improved it: Remove the old tianocore licensing style and redundant license description..
[PATCH V2 33/33] AMD/VanGoghBoard: Improvement coding style
Thanks!
-----Original Message-----
From: Chang, Abner <Abner.Chang@amd.com>
Sent: Tuesday, January 23, 2024 12:42 PM
To: Zhai, MingXin (Duke) <duke.zhai@amd.com>; 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: [PATCH 03/33] AMD/VanGoghBoard: Check in Capsule update
[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 (#114395): https://edk2.groups.io/g/devel/message/114395
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]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-01-25 12:10 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
2024-01-25 8:25 ` Zhai, MingXin (Duke) via groups.io [this message]
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=DS0PR12MB94453E0A1E8E60F045C0D027F67A2@DS0PR12MB9445.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