From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 342447803DE for ; Fri, 26 Jan 2024 06:02:17 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=lo2gKrcQ9X5PO08+gCYk/GPf4v0CRzb+KkRjaNBvV7k=; c=relaxed/simple; d=groups.io; h=ARC-Seal:ARC-Message-Signature:ARC-Authentication-Results:Received-SPF:From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding:Content-Type; s=20140610; t=1706248935; v=1; b=HVncDtVD/qyXlIUHqgT7q7znKuNybfFBR0ICjclgEKNnL+Rt1w/fcqDlG5gwyyNDeMfmQ253 Nfa3iP3fP5ZxAqW2RsxQNJXqpJu89y63+oxaqPajLS7Q6vFgcl1XLbPPOr3ZDSUIcutH1cBuWpt q5EH5y4YahW10ZUX0E9CcmoU= X-Received: by 127.0.0.2 with SMTP id uVrQYY7687511xAdRIxoQ3UU; Thu, 25 Jan 2024 22:02:15 -0800 X-Received: from NAM10-DM6-obe.outbound.protection.outlook.com (NAM10-DM6-obe.outbound.protection.outlook.com [40.107.93.56]) by mx.groups.io with SMTP id smtpd.web10.9818.1706248934132932204 for ; Thu, 25 Jan 2024 22:02:14 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=HixCeyxcNp434N5Zdw0yAxJ04Qutat1Y1o+2TQk2MmOWxqhbFpjptwK9ROrCndUrft0gKkjxocr4ttcmwHybjkK1sS5sDHYEitezdCPC8/hmsqHjUMAA8fu7aI/kGF4XI+QxLlw6nfNTUqjb3F1vgAELPDPKg9hBbuWynKAjxW33L/YwjMd9tnQnnJM4jgpj0ortwT508YJxmIY6YmcGxo2q1D9Fsa36P9i1axNI76aUjqlDYRAaCpWIgXT999XJRHNY+8P0SmmH/UQzTzQ+2QMWGLhnx+sR4iZeWp1DzIfpOiaAU0qW09GoBdAQPyegdy3JErZ/tBlqijN+5uYztA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=iS8vdD0mWdCzcoFVYH8WJqkaPQtyPQtVllF5EMdosRQ=; b=QOD/w7bjs1HCgkmtXPdC9feNEONs6jLhS3hzz6grRh/EtC431XbuZL0lglL3FzCrhzrie3p8xqW9qEf6IkB7RWCSvlPaTdk3bhD1agTqf6tloKmhgaWVta6zEAeyFAIq9p6H6F28tU4shYWDlf8fu0oQw12j4oOqRj+dbokp9/OoJLFTdN7faknyFv84UQRGktCNDu/ZWCh6pHGYSC4+3TqyuAf8e63Vb4lgg09RXDTaAZtuCqo3yfW955HqTHTLRO7Qb+PBwiwbfoXxg2jtfLDUFS5DDBZerp1wFuXc4BnoqvWl43PpSF5sPz7QK1ZWgVzWx/K4ozaTL60Ph4YloQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) X-Received: from SJ0PR05CA0070.namprd05.prod.outlook.com (2603:10b6:a03:332::15) by IA0PR12MB8424.namprd12.prod.outlook.com (2603:10b6:208:40c::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7228.26; Fri, 26 Jan 2024 06:02:08 +0000 X-Received: from DS2PEPF0000343B.namprd02.prod.outlook.com (2603:10b6:a03:332:cafe::7f) by SJ0PR05CA0070.outlook.office365.com (2603:10b6:a03:332::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7228.24 via Frontend Transport; Fri, 26 Jan 2024 06:02:08 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C X-Received: from SATLEXMB04.amd.com (165.204.84.17) by DS2PEPF0000343B.mail.protection.outlook.com (10.167.18.38) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7228.16 via Frontend Transport; Fri, 26 Jan 2024 06:02:08 +0000 X-Received: from SHA-LX-MINGXZHA.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Fri, 26 Jan 2024 00:01:35 -0600 From: "Zhai, MingXin (Duke) via groups.io" To: CC: Duke Zhai , Eric Xing , Igniculus Fu , Abner Chang Subject: [edk2-devel] [PATCH V2 03/32] AMD/VanGoghBoard: Check in Capsule update Date: Fri, 26 Jan 2024 14:00:21 +0800 Message-ID: <20240126060050.1725-4-duke.zhai@amd.com> In-Reply-To: <20240126060050.1725-1-duke.zhai@amd.com> References: <20240126060050.1725-1-duke.zhai@amd.com> MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DS2PEPF0000343B:EE_|IA0PR12MB8424:EE_ X-MS-Office365-Filtering-Correlation-Id: 841937c6-0c8c-45c4-1c34-08dc1e34544d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: G2MfWrbGP9zjJlHBpf4Hp+bnhW+BVrai4zsGlDbgX/D5a4isbfVaf6GOSnMUnpWAfpTGzwZlaHhK0i1ZBoYyOmBZmrquFLsvTPIMtuOwb87c4+f8SNETQHahzkxVf5Us6VbWYox3m/sHKh0wm/5IyFLLlHgkRJDWa7+AWUkHEntlrvFmiFmJw+02sWCqRZIgJ2uSZSxIrE1iulE18W1VQm/+VvTyeWt7X0YM1p0nuqHYAgd9KhVZTylc0unr1vts4fcyVeNNeWcWTTSZ/csjegu2l/K+RtoGwn0iEwgGytbGpeYvkJqZxuylwJhS/SI4jO4uZHoDikO1xOdsWrvAjpwZD6TktGG8kT27HtOa5s9HTlmk2plwlrU4ZiPS5CAUB7b/fBu4gswrh/c3m0r5OScQRgR357bD/ZZ3oKEJf5B4zyGls+tZP7tuN3dNc0/ka+FmY1grZp24jsjCnVXnWmOZmPUYKJfny0A6/Bf8B0qtX2ezF7ytqXIkxVrpJWNn0ucLYqUyqyJd79psTvVcJQxy91Z3nZibiDRnM+LSvOY3kgnz8tQb10ai1Zc7YPH0BRqqS7OWHizv8WbEpG/4V0bGFtmd8/AbCndy1t8QGXXJupXDdwkU3bn9UQxf0e6CSLOP2gP+KrbB+maOWkGLSSTnfc9wg6YkBbtuyK4PNFlM9bjCzzeUCP8OrzoEKOOoUui1Ty7Uoi5K5A8ZuNuDWf24A3zOaG7dpEPi1g1kNjJZ2FTgoYMxilI8qOUtwNvgnY87gPxENHxA0v/Sp+UTKIP87V/HFqLppoFEWewH0mk= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2024 06:02:08.0458 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 841937c6-0c8c-45c4-1c34-08dc1e34544d X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: DS2PEPF0000343B.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: IA0PR12MB8424 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,duke.zhai@amd.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: Di3ZbRFk2FXpyChkZFBmNXr3x7686176AA= Content-Transfer-Encoding: quoted-printable Content-Type: text/plain X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=HVncDtVD; arc=reject ("signature check failed: fail, {[1] = sig:microsoft.com:reject}"); dmarc=none; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io From: Duke Zhai BZ #:4640 In V2: Improve coding style. 1.Remove the leading underscore and use double underscore at trailing in = C header files. 2.Remove old tianocore licenses and redundant license description. 3.Improve coding style. For example: remove space between @param. In V1: 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 Cc: Duke Zhai Cc: Eric Xing Cc: Igniculus Fu Cc: Abner Chang --- .../SystemFirmwareDescriptor.aslc | 85 ++ .../SystemFirmwareDescriptor.inf | 39 + .../SystemFirmwareDescriptorPei.c | 64 + .../Include/Library/CapsuleHookLib.h | 40 + .../Capsule/CapsuleHookLib/CapsuleHookLib.c | 1153 +++++++++++++++++ .../Capsule/CapsuleHookLib/CapsuleHookLib.inf | 56 + .../PlatformBootManager.c | 794 ++++++++++++ .../PlatformBootManager.h | 150 +++ .../PlatformBootManagerLib.inf | 89 ++ .../PlatformBootManagerLib/PlatformConsole.c | 495 +++++++ .../PlatformBootManagerLib/PlatformConsole.h | 69 + .../PlatformBootManagerLib/PlatformData.c | 39 + .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf | 122 ++ .../CapsuleRuntimeDxe/CapsuleService.c | 461 +++++++ .../CapsuleRuntimeDxe/CapsuleService.h | 73 ++ 15 files changed, 3729 insertions(+) create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/Syst= emFirmwareDescriptor/SystemFirmwareDescriptor.aslc create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/Syst= emFirmwareDescriptor/SystemFirmwareDescriptor.inf create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/Syst= emFirmwareDescriptor/SystemFirmwareDescriptorPei.c create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Libr= ary/CapsuleHookLib.h create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Caps= ule/CapsuleHookLib/CapsuleHookLib.c create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Caps= ule/CapsuleHookLib/CapsuleHookLib.inf create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Caps= ule/PlatformBootManagerLib/PlatformBootManager.c create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Caps= ule/PlatformBootManagerLib/PlatformBootManager.h create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Caps= ule/PlatformBootManagerLib/PlatformBootManagerLib.inf create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Caps= ule/PlatformBootManagerLib/PlatformConsole.c create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Caps= ule/PlatformBootManagerLib/PlatformConsole.h create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Caps= ule/PlatformBootManagerLib/PlatformData.c create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Un= iversal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Un= iversal/CapsuleRuntimeDxe/CapsuleService.c create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Un= iversal/CapsuleRuntimeDxe/CapsuleService.h diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmw= areDescriptor/SystemFirmwareDescriptor.aslc b/Platform/AMD/VanGoghBoard/Cha= chaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.asl= c new file mode 100644 index 0000000000..2e05a523c7 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDesc= riptor/SystemFirmwareDescriptor.aslc @@ -0,0 +1,85 @@ +/** @file + System firmware Descriptor file + System Firmware descriptor. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#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_S= TRING)/sizeof(CHAR16)]; + CHAR16 VersionNameStr[sizeof(CURRENT_FI= RMWARE_VERSION_STRING)/sizeof(CHAR16)]; + CHAR16 PackageVersionNameStr[sizeof(PAC= KAGE_VERSION_STRING)/sizeof(CHAR16)]; +} IMAGE_DESCRIPTOR; + +IMAGE_DESCRIPTOR mImageDescriptor =3D +{ + { + EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE, + sizeof(EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR), + sizeof(IMAGE_DESCRIPTOR), + PACKAGE_VERSION, // PackageVersi= on + OFFSET_OF (IMAGE_DESCRIPTOR, PackageVersionNameStr), // PackageVersi= onName + 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, // AttributesSu= pported; + IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | + IMAGE_ATTRIBUTE_RESET_REQUIRED | + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED | + IMAGE_ATTRIBUTE_IN_USE, // AttributesSe= tting; + 0x0, // Compatibilit= ies; + LOWEST_SUPPORTED_FIRMWARE_VERSION, // LowestSuppor= tedImageVersion; + 0x00000000, // LastAttemptV= ersion; + 0, // LastAttemptS= tatus; + {0x0}, // Reserved3 + 0, // HardwareInst= ance; + }, + // 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/SystemFirmw= areDescriptor/SystemFirmwareDescriptor.inf b/Platform/AMD/VanGoghBoard/Chac= haniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.inf new file mode 100644 index 0000000000..50f2b8c1a2 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDesc= riptor/SystemFirmwareDescriptor.inf @@ -0,0 +1,39 @@ +## @file +# System Firmware descriptor. +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D SystemFirmwareDescriptor + FILE_GUID =3D 90B2B846-CA6D-4D6E-A8D3-C140A8E110AC + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D 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.PcdEdkiiSystemFirmwareImageDescriptor + gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize + +[Depex] + TRUE diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmw= areDescriptor/SystemFirmwareDescriptorPei.c b/Platform/AMD/VanGoghBoard/Cha= chaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptorPei.= c new file mode 100644 index 0000000000..7f0c4421e3 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDesc= riptor/SystemFirmwareDescriptorPei.c @@ -0,0 +1,64 @@ +/** @file + Implements SystemFirmwareDescriptorPei.c + System Firmware descriptor producer. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +/** + 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 =3D 0; + while (TRUE) { + Status =3D PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Index, Fil= eHandle, (VOID **)&Descriptor, &AuthenticationStatus); + if (EFI_ERROR (Status)) { + // Should not happen, must something wrong in FDF. + ASSERT (FALSE); + return EFI_NOT_FOUND; + } + + if (Descriptor->Signature =3D=3D EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTO= R_SIGNATURE) { + break; + } + + Index++; + } + + DEBUG ((DEBUG_INFO, "EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR size - 0x%x\= n", Descriptor->Length)); + + Size =3D Descriptor->Length; + PcdSetPtrS (PcdEdkiiSystemFirmwareImageDescriptor, &Size, Descriptor); + + return EFI_SUCCESS; +} diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/Cap= suleHookLib.h b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/= CapsuleHookLib.h new file mode 100644 index 0000000000..584adfaee9 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/CapsuleHoo= kLib.h @@ -0,0 +1,40 @@ +/** @file + Implements CapsuleHookLib.h + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ 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/Cap= suleHookLib/CapsuleHookLib.c b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/L= ibrary/Capsule/CapsuleHookLib/CapsuleHookLib.c new file mode 100644 index 0000000000..b4513514b8 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHoo= kLib/CapsuleHookLib.c @@ -0,0 +1,1153 @@ +/** @file + Implements CapsuleHookLib.c + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAP_FILE_NAME (CHAR16 *) FixedPcdGetPtr (PcdOtaCapsuleName) +#define CAP_PARTITION (CHAR16 *) FixedPcdGetPtr (PcdOtaCapsulePartitionNa= me) +CHAR16 mPartitionName[36]; +STATIC CONST CHAR16 *mSlotSuffixes[2] =3D { L"_a", L"_b" }; +EFI_DEVICE_PATH_PROTOCOL *mBootDevicePath; + +#define FLASH_DEVICE_PATH_SIZE(DevPath) (GetDevicePathSize (DevPath) - si= zeof (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 ro= utine. + +**/ +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 =3D BlockIo->Media->MediaId; + + // + // Read size of Partition entry and number of entries from GPT header + // + GptHeader =3D AllocatePool (BlockIo->Media->BlockSize); + if (GptHeader =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status =3D 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 !=3D EFI_PTAB_HEADER_ID) || (GptHeader-= >MyLBA !=3D PRIMARY_PART_HEADER_LBA)) { + DEBUG ((DEBUG_ERROR, "No valid GPT found!\n")); + FreePool (GptHeader); + return EFI_DEVICE_ERROR; + } + + EntrySize =3D GptHeader->SizeOfPartitionEntry; + NumEntries =3D GptHeader->NumberOfPartitionEntries; + if ((EntrySize =3D=3D 0) || (NumEntries =3D=3D 0)) { + DEBUG ((DEBUG_ERROR, "Invalid Entry size or number.\n")); + return EFI_DEVICE_ERROR; + } + + FreePool (GptHeader); + + BufferSize =3D ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Medi= a->BlockSize); + *PartitionEntries =3D AllocatePool (BufferSize); + if (PartitionEntries =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status =3D 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 c= apsule partition. + + @retval EFI_SUCCESS Operation completed successfully. + @retval others Some error occurs when executing this ro= utine. + +**/ +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 =3D 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 =3D 0; LoopIndex < NumHandles; LoopIndex++) { + Status =3D 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", St= atus)); + return Status; + } + + if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE (B= ootDevicePath))) { + BootDevicePath =3D DevicePath; + break; + } + } + + DevicePath =3D BootDevicePath; + Status =3D gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DeviceP= ath, &Handle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Couldn't locate device status: %r\n", Status)); + return Status; + } + + Status =3D 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 =3D ReadPartitionEntries (BlockIo, &PartitionEntries); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to read partitions from disk device: %r\n= ", Status)); + return Status; + } + + for (LoopIndex =3D 0; LoopIndex < NumHandles; LoopIndex++) { + Status =3D 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", St= atus)); + return Status; + } + + if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE (B= ootDevicePath))) { + NextNode =3D NextDevicePathNode (DevicePath); + + while (!IsDevicePathEndType (NextNode)) { + if ((NextNode->Type =3D=3D MEDIA_DEVICE_PATH) && + (NextNode->SubType =3D=3D MEDIA_HARDDRIVE_DP)) + { + break; + } + + NextNode =3D NextDevicePathNode (NextNode); + } + + if (IsDevicePathEndType (NextNode)) { + continue; + } + + PartitionNode =3D (HARDDRIVE_DEVICE_PATH *)NextNode; + + if (PartitionNode->PartitionNumber =3D=3D 0) { + continue; + } + + if (0 =3D=3D StrCmp (PartitionEntries[PartitionNode->PartitionNumber= - 1].PartitionName, PartitionName)) { + break; + } + } + } + + if (LoopIndex >=3D NumHandles) { + return EFI_LOAD_ERROR; + } + + *PartitionDevicePath =3D 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 ro= utine. + +**/ +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 =3D sizeof (OTA_CAPSULE_UPDATE); + Status =3D 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[OtaCapsu= leUpdateVal.UpdateSlot]); + DEBUG ((DEBUG_INFO, "CapsulePartitionInfo from partition: %s\n", mPartit= ionName)); + + // + // Get Boot device path + // + VarSize =3D 512; + Status =3D gRT->GetVariable ( + L"AndroidBootDevice", + &gEfiGlobalVariableGuid, + NULL, + &VarSize, + BootPath + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "CapsulePartitionInfo: Get BootDevice variable fa= iled: %r\n", Status)); + return Status; + } + + mBootDevicePath =3D ConvertTextToDevicePath (BootPath); + if (mBootDevicePath =3D=3D 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 binar= y + @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 infor= mation + +**/ +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 =3D NULL; + FileSize =3D 0; + + DEBUG ((DEBUG_INFO, "ReadCapsuleInfo()...\n")); + + Status =3D GetDevicePathByName (mBootDevicePath, mPartitionName, &BootPa= rtitionPath); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status)); + return Status; + } + + Status =3D gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BootPartiti= onPath, &Handle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed: %r\n"= , Status)); + return Status; + } + + // + // Get Capsule file + // + Status =3D gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID = **)&BlockIo); + if (EFI_ERROR (Status)) { + return Status; + } + + if (BlockIo->Media->RemovableMedia) { + return Status; + } + + Status =3D gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGui= d, (VOID **)&Fs); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D Fs->OpenVolume (Fs, &Root); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ, = 0); + if (EFI_ERROR (Status)) { + return Status; + } + + if (FileHandle =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + Status =3D FileHandleGetSize (FileHandle, (UINT64 *)&FileSize); + if (EFI_ERROR (Status)) { + FileHandleClose (FileHandle); + return Status; + } + + FileBuffer =3D AllocateZeroPool (FileSize); + if (FileBuffer =3D=3D NULL) { + FileHandleClose (FileHandle); + return Status; + } + + Status =3D FileHandleRead (FileHandle, &FileSize, FileBuffer); + if (EFI_ERROR (Status)) { + FileHandleClose (FileHandle); + FreePool (FileBuffer); + return Status; + } + + Status =3D FileHandleClose (FileHandle); + if (EFI_ERROR (Status)) { + FreePool (FileBuffer); + return Status; + } + + *Buffer =3D FileBuffer; + *BufferSize =3D 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 funct= ion + +**/ +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 =3D GetDevicePathByName (mBootDevicePath, mPartitionName, &BootPa= rtitionPath); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status)); + return Status; + } + + Status =3D gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BootPartiti= onPath, &Handle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed: %r\n"= , Status)); + return Status; + } + + // + // Remove Capsule file + // + Status =3D gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID = **)&BlockIo); + if (EFI_ERROR (Status)) { + return Status; + } + + if (BlockIo->Media->RemovableMedia) { + return Status; + } + + Status =3D gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGui= d, (VOID **)&Fs); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D Fs->OpenVolume (Fs, &Root); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ |= EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR (Status)) { + return Status; + } + + if (FileHandle =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + Status =3D 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 poi= nters to the capsules + being passed into update capsule. + @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER i= n CaspuleHeaderArray. + + @retval EFI_SUCCESS Valid capsule was passed. + @retval others Some error occurs when executing this rout= ine. + +**/ +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 =3D NULL; + + for (ArrayNumber =3D 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + // + // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag mu= st have + // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well. + // + CapsuleHeader =3D CapsuleHeaderArray[ArrayNumber]; + if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPS= ULE_FLAGS_POPULATE_SYSTEM_TABLE)) =3D=3D CAPSULE_FLAGS_POPULATE_SYSTEM_TABL= E) { + 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 | CAPS= ULE_FLAGS_INITIATE_RESET)) =3D=3D 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) != =3D 0)) + { + return EFI_INVALID_PARAMETER; + } + + // + // Check Capsule image without populate flag by firmware support capsu= le function + // + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) =3D= =3D 0) { + Status =3D SupportCapsuleImage (CapsuleHeader); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + // + // Walk through all capsules, record whether there is a capsule needs re= set + // or initiate reset. And then process capsules which has no reset flag = directly. + // + for (ArrayNumber =3D 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader =3D 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) =3D= =3D 0) || TRUE) { + Status =3D 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 =3D NULL; + CapsuleSize =3D 0; + + DEBUG ((DEBUG_INFO, "CapsuleUpdateViaFileHook() Entry Point...\n")); + + Status =3D CapsulePartitionInfo (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "CapsulePartitionInfo failed: %r\n", Status)); + return Status; + } + + Status =3D ReadCapsuleInfo (CAP_FILE_NAME, (VOID **)&CapsuleBuffer, &Cap= suleSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Read Capsule file failed. Status: %r\n", Status)= ); + if (CapsuleBuffer !=3D NULL) { + FreePool (CapsuleBuffer); + } + + return Status; + } + + CapsuleHeader =3D (EFI_CAPSULE_HEADER *)CapsuleBuffer; + CapsuleNum =3D 1; + + Status =3D UpdateCapsule (&CapsuleHeader, CapsuleNum); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to update capsule. Status: %r\n", Status)= ); + } + + if (CapsuleBuffer !=3D 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 c= apsule partition. + + @retval EFI_SUCCESS Operation completed successfully. + @retval others Some error occurs when executing this ro= utine. + +**/ +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 =3D 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 =3D 0; LoopIndex < NumHandles; LoopIndex++) { + Status =3D 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", St= atus)); + return Status; + } + + if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE (B= ootDevicePath))) { + BootDevicePath =3D DevicePath; + break; + } + } + + DevicePath =3D BootDevicePath; + Status =3D gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DeviceP= ath, &Handle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Couldn't locate device status: %r\n", Status)); + return Status; + } + + Status =3D 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 =3D 0; LoopIndex < NumHandles; LoopIndex++) { + Status =3D 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", St= atus)); + return Status; + } + + if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE (B= ootDevicePath))) { + NextNode =3D NextDevicePathNode (DevicePath); + + while (!IsDevicePathEndType (NextNode)) { + if ((NextNode->Type =3D=3D MEDIA_DEVICE_PATH) && + (NextNode->SubType =3D=3D MEDIA_HARDDRIVE_DP)) + { + break; + } + + NextNode =3D NextDevicePathNode (NextNode); + } + + if (IsDevicePathEndType (NextNode)) { + continue; + } + + break; + } + } + + if (LoopIndex >=3D NumHandles) { + return EFI_LOAD_ERROR; + } + + *PartitionDevicePath =3D 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 ro= utine. + +**/ +EFI_STATUS +EFIAPI +CapsulePathInfo ( + VOID + ) +{ + mBootDevicePath =3D ConvertTextToDevicePath ((CHAR16 *)PcdGetPtr (PcdNVM= eDevicePath)); + + if (mBootDevicePath =3D=3D 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 binar= y + @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 infor= mation + +**/ +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 =3D FALSE; + + FileBuffer =3D NULL; + + DEBUG ((DEBUG_INFO, "ReadCapsuleInfo()...\n")); + + Status =3D GetDevicePathByBoot (mBootDevicePath, &BootPartitionPath); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "IGpuDevicePath: %S\n", ConvertDevicePathToText (Boo= tPartitionPath, FALSE, FALSE))); + + Status =3D gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BootPartiti= onPath, &Handle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed: %r\n"= , Status)); + return Status; + } + + // + // Get Capsule file + // + Status =3D 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 =3D gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGui= d, (VOID **)&Fs); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 3Locate DevicePath failed: %r\n= ", Status)); + return Status; + } + + Status =3D Fs->OpenVolume (Fs, &Root); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 4Locate DevicePath failed: %r\n= ", Status)); + return Status; + } + + Status =3D Root->Open (Root, &DirHandle, FileBaseName, EFI_FILE_MODE_REA= D | EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot open %s. Status =3D %r\n", FileBaseName, = Status)); + return Status; + } + + // + // Get file count first + // + Status =3D FileHandleFindFirstFile (DirHandle, &FileInfo); + while (!*NoNextFile && !Found) { + // . & .. + Status =3D FileHandleFindNextFile (DirHandle, FileInfo, NoNextFile); + if (EFI_ERROR (Status)) { + return Status; + } + + if (FileInfo->Attribute & EFI_FILE_DIRECTORY) { + continue; + } + + Found =3D TRUE; + } + + if (!Found) { + *NoNextFile =3D TRUE; + return EFI_NOT_FOUND; + } + + DEBUG ((DEBUG_INFO, "Processing Capsule %s\n", FileInfo->FileName)); + FileBuffer =3D AllocateZeroPool (FileInfo->FileSize); + if (FileBuffer =3D=3D NULL) { + return EFI_BUFFER_TOO_SMALL; + } + + Status =3D 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", File= Info->FileName, Status)); + FreePool (FileBuffer); + return Status; + } + + Status =3D 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 =3D FileHandleClose (DirHandle); + } + + Status =3D FileHandleClose (FileHandle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 8Locate DevicePath failed: %r\n= ", Status)); + FreePool (FileBuffer); + return Status; + } + + *Buffer =3D FileBuffer; + *BufferSize =3D 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 =3D FALSE; + EFI_FILE_INFO *FileInfo; + BOOLEAN Found =3D FALSE; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + EFI_FILE_HANDLE FileHandle; + + Status =3D GetDevicePathByBoot (mBootDevicePath, &BootPartitionPath); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "IGpuDevicePath: %S\n", ConvertDevicePathToText (Boo= tPartitionPath, FALSE, FALSE))); + + Status =3D gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BootPartiti= onPath, &Handle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed: %r\n"= , Status)); + return Status; + } + + // + // Get Capsule file + // + Status =3D 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 =3D gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGui= d, (VOID **)&Fs); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 3Locate DevicePath failed: %r\n= ", Status)); + return Status; + } + + Status =3D Fs->OpenVolume (Fs, &Root); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 4Locate DevicePath failed: %r\n= ", Status)); + return Status; + } + + Status =3D Root->Open (Root, &DirHandle, FileBaseName, EFI_FILE_MODE_REA= D | EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot open %s. Status =3D %r\n", FileBaseName, = Status)); + return Status; + } + + Status =3D FileHandleFindFirstFile (DirHandle, &FileInfo); + while (!NoNextFile && !Found) { + // . & .. + FileHandleFindNextFile (DirHandle, FileInfo, &NoNextFile); + if (FileInfo->Attribute & EFI_FILE_DIRECTORY) { + continue; + } + + Found =3D TRUE; + } + + if (!Found) { + return EFI_NOT_FOUND; + } + + DEBUG ((DEBUG_INFO, "Deleting Capsule %s\n", FileInfo->FileName)); + Status =3D DirHandle->Open (DirHandle, &FileHandle, FileInfo->FileName, = EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); + if (!EFI_ERROR (Status)) { + Status =3D FileHandle->Delete (FileHandle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Cannot delete Capsule %s:%r\n", FileInfo->FileN= ame, 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 =3D 0; + BOOLEAN NoNextFile =3D FALSE; + + CapsuleBuffer =3D NULL; + CapsuleSize =3D 0; + + DEBUG ((DEBUG_INFO, "CapsuleUpdateViaFileHook() Entry Point...\n")); + + Status =3D CapsulePathInfo (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "CapsulePathInfo failed: %r\n", Status)); + return Status; + } + + while (!NoNextFile) { + Status =3D IterateAllCapsulesFromDisk (EFI_CAPSULE_FILE_DIRECTORY, (VO= ID **)&CapsuleBuffer, &CapsuleSize, &NoNextFile); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to update capsule:%r\n", Status)); + break; + } + + CapsuleHeader =3D (EFI_CAPSULE_HEADER *)CapsuleBuffer; + CapsuleNum =3D 1; + Status =3D UpdateCapsule (&CapsuleHeader, CapsuleNum); + RecordCapsuleStatusVariable (CapsuleHeader, Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to update capsule.\n")); + break; + } + + Status =3D DeleteFirstCapsule (EFI_CAPSULE_FILE_DIRECTORY); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot delete Capsule.\n")); + break; + } + } + + if (CapsuleBuffer !=3D NULL) { + FreePool (CapsuleBuffer); + } + + if (!CurrentCapsuleFileNo && (Status =3D=3D EFI_NOT_FOUND)) { + Status =3D EFI_SUCCESS; + } + + DEBUG ((DEBUG_INFO, "Capsule update via file completed, Status=3D%r\n", = Status)); + // RecordFmpCapsuleStatus(); + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + + // Unreachable. + return EFI_SUCCESS; +} diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Cap= suleHookLib/CapsuleHookLib.inf b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg= /Library/Capsule/CapsuleHookLib/CapsuleHookLib.inf new file mode 100644 index 0000000000..c3e910007a --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHoo= kLib/CapsuleHookLib.inf @@ -0,0 +1,56 @@ +## @file +# Capsule Hook Lib Module +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D CapsuleHookLib + FILE_GUID =3D 22BC4D9A-C78A-4038-8071-865765C4C019 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D CapsuleHookLib + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/Pla= tformBootManagerLib/PlatformBootManager.c b/Platform/AMD/VanGoghBoard/Chach= aniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.c new file mode 100644 index 0000000000..94f4f8207a --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBo= otManagerLib/PlatformBootManager.c @@ -0,0 +1,794 @@ +/** @file + This file include all platform action which can be customized + by IBV/OEM. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.
+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 +#include +#include +#include +#include +#include +#include + +// +// Predefined platform root bridge +// +PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 =3D { + gPciRootBridge, + gEndEntire +}; + +EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] =3D { + (EFI_DEVICE_PATH_PROTOCOL *)&gPlatformRootBridge0, + NULL +}; + +extern EFI_GUID gEfiEventReadyT= oBootGuid; +UNIVERSAL_PAYLOAD_PLATFORM_BOOT_MANAGER_OVERRIDE_PROTOCOL *mUniversalPayl= oadPlatformBootManagerOverrideInstance =3D 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 =3D gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID= **)&SmmAccess); + if (!EFI_ERROR (Status)) { + Handle =3D NULL; + Status =3D 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 =3D 0; Index < Count; Index++) { + if ((Key->OptionType =3D=3D Array[Index].OptionType) && + (Key->Attributes =3D=3D Array[Index].Attributes) && + (StrCmp (Key->Description, Array[Index].Description) =3D=3D 0) && + (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSi= ze (Key->FilePath)) =3D=3D 0) && + (Key->OptionalDataSize =3D=3D Array[Index].OptionalDataSize) && + (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->Op= tionalDataSize) =3D=3D 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 =3D gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageProtocolGu= id, (VOID **)&LoadedImage); + ASSERT_EFI_ERROR (Status); + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + DevicePath =3D AppendDevicePathNode ( + DevicePathFromHandle (LoadedImage->DeviceHandle), + (EFI_DEVICE_PATH_PROTOCOL *)&FileNode + ); + + Status =3D EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + if (!EFI_ERROR (Status)) { + BootOptions =3D EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOp= tionTypeBoot); + + OptionIndex =3D PlatformFindLoadOption (&NewOption, BootOptions, BootO= ptionCount); + + if (OptionIndex =3D=3D -1) { + Status =3D 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 =3D 0; + DevicePath =3D NULL; + HandleBuffer =3D NULL; + *IGpuDevicePath =3D NULL; + *DGpuDevicePath =3D NULL; + + DEBUG ((DEBUG_INFO, "VENDOR_ID =3D 0x%x\n", VENDOR_ID)); + DEBUG ((DEBUG_INFO, "DEVICE_ID =3D 0x%x\n", DEVICE_ID)); + + // + // Make all the PCI_IO protocols on PCI Seg 0 show up + // + EfiBootManagerConnectDevicePath (gPlatformRootBridges[0], NULL); + + Status =3D gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &gPlatformRootBridges[0], + &RootHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D 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 =3D 0; + HandleBuffer =3D NULL; + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + if (!EFI_ERROR (Status)) { + // + // Check for all VGA device + // + Status =3D 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 (Dev= icePath, FALSE, FALSE))); + + if ((Pci.Hdr.VendorId =3D=3D VENDOR_ID) && ((Pci.Hdr.DeviceId =3D=3D= DEVICE_ID) || (Pci.Hdr.DeviceId =3D=3D DEVICE_ID2))) { + // IGPU + *IGpuDevicePath =3D DevicePath; + } else { + // DGPU + *DGpuDevicePath =3D DevicePath; + } + + if ((*IGpuDevicePath !=3D NULL) && (*DGpuDevicePath !=3D NULL)) { + DEBUG ((DEBUG_INFO, "IGpuDevicePath and DGpuDevicePath are not NUL= L\n")); + break; + } + } + } + + DEBUG ((DEBUG_INFO, "IGpuDevicePath: %S\n", ConvertDevicePathToText (*IG= puDevicePath, FALSE, FALSE))); + DEBUG ((DEBUG_INFO, "DGpuDevicePath: %S\n", ConvertDevicePathToText (*DG= puDevicePath, FALSE, FALSE))); + FreePool (HandleBuffer); + + return EFI_SUCCESS; +} + +/** + + Find the platform active vga, and base on the policy to enable the vga a= s + the console out device. The policy is active dGPU, if no dGPU active iGP= U. + + None. + + @param EFI_UNSUPPORTED There is no active vga device + + @retval EFI_STATUS Return the status of BdsLibGetVariableAnd= Size () + +**/ +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 ((DEBUG_INFO, "PlatformBdsForceActiveVga enter\n")); + + Status =3D EFI_SUCCESS; + DevicePathFirst =3D NULL; + DevicePathSecond =3D NULL; + GopDevicePath =3D NULL; + IGpuDevicePath =3D NULL; + DGpuDevicePath =3D NULL; + + // + // Get device path of one IGPU and one DGPU + // + Status =3D GetVgaDevicePath (&IGpuDevicePath, &DGpuDevicePath); + ASSERT_EFI_ERROR (Status); + + if ((IGpuDevicePath =3D=3D NULL) && (DGpuDevicePath =3D=3D NULL)) { + DEBUG ((DEBUG_INFO, "No valid IGPU and DGPU\n")); + return EFI_UNSUPPORTED; + } + + if ((IGpuDevicePath !=3D NULL) && (DGpuDevicePath =3D=3D NULL)) { + DEBUG ((DEBUG_INFO, "Only IGPU is valid\n")); + // DEBUG ((DEBUG_INFO,"Only IGPU is valid, Update IGPU ...\n")); + DevicePathFirst =3D IGpuDevicePath; + DevicePathSecond =3D DGpuDevicePath; + goto UpdateConOut; + } else if ((IGpuDevicePath =3D=3D NULL) && (DGpuDevicePath !=3D NULL)) { + DEBUG ((DEBUG_INFO, "Only DGPU is valid\n")); + // DEBUG ((DEBUG_INFO,"Only DGPU is valid, Update DGPU ...\n")); + DevicePathFirst =3D DGpuDevicePath; + DevicePathSecond =3D IGpuDevicePath; + goto UpdateConOut; + } else if ((IGpuDevicePath !=3D NULL) && (DGpuDevicePath !=3D NULL)) { + DEBUG ((DEBUG_INFO, "DGPU and IGPU are valid, active DGPU\n")); + // DEBUG ((DEBUG_INFO,"Only DGPU is valid, Update DGPU ...\n")); + DevicePathFirst =3D DGpuDevicePath; + DevicePathSecond =3D IGpuDevicePath; + goto UpdateConOut; + } + +UpdateConOut: + DEBUG ((DEBUG_INFO, "Before GetGopDevicePath: ConOutDevicePath is %S\n",= ConvertDevicePathToText (DevicePathFirst, FALSE, FALSE))); + GetGopDevicePath (DevicePathFirst, &GopDevicePath); + DevicePathFirst =3D GopDevicePath; + DEBUG ((DEBUG_INFO, "After GetGopDevicePath: ConOutDevicePath is %S\n", = ConvertDevicePathToText (DevicePathFirst, FALSE, FALSE))); + DEBUG ((DEBUG_INFO, "Exclusive device path is %S\n", ConvertDevicePathTo= Text (DevicePathSecond, FALSE, FALSE))); + + Status =3D 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 =3D gBS->LocateProtocol (&gUniversalPayloadPlatformBootManagerOve= rrideProtocolGuid, NULL, (VOID **)&mUniversalPayloadPlatformBootManagerOver= rideInstance); + if (EFI_ERROR (Status)) { + mUniversalPayloadPlatformBootManagerOverrideInstance =3D NULL; + } + + Status =3D gRT->GetVariable ( + L"OsIndications", + &gEfiGlobalVariableGuid, + &Attributes, + &DataSize, + &OsIndication + ); + if (mUniversalPayloadPlatformBootManagerOverrideInstance !=3D NULL) { + mUniversalPayloadPlatformBootManagerOverrideInstance->BeforeConsole ()= ; + return; + } + + // + // Register ENTER as CONTINUE key + // + Enter.ScanCode =3D SCAN_NULL; + Enter.UnicodeChar =3D CHAR_CARRIAGE_RETURN; + EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + + if (FixedPcdGetBool (PcdBootManagerEscape)) { + // + // Map Esc to Boot Manager Menu + // + CustomKey.ScanCode =3D SCAN_ESC; + CustomKey.UnicodeChar =3D CHAR_NULL; + } else { + // + // Map Esc to Boot Manager Menu + // + CustomKey.ScanCode =3D SCAN_F2; + CustomKey.UnicodeChar =3D CHAR_NULL; + } + + EfiBootManagerGetBootManagerMenu (&BootOption); + EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumbe= r, 0, &CustomKey, NULL); + + // + // Also add Down key to Boot Manager Menu since some serial terminals do= n't support F2 key. + // + Down.ScanCode =3D SCAN_DOWN; + Down.UnicodeChar =3D CHAR_NULL; + EfiBootManagerGetBootManagerMenu (&BootOption); + EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumbe= r, 0, &Down, NULL); + CapsuleUpdateonDisk =3D (BOOLEAN)((OsIndication & EFI_OS_INDICATIONS_FIL= E_CAPSULE_DELIVERY_SUPPORTED) !=3D 0); + // Process Capsule in Memory first, before EndOfDxe. + if ((GetBootModeHob () =3D=3D BOOT_ON_FLASH_UPDATE) || CapsuleUpdateonDi= sk) { + 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 install= ation. + // + 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 !=3D NULL) { + mUniversalPayloadPlatformBootManagerOverrideInstance->AfterConsole (); + return; + } + + Black.Blue =3D Black.Green =3D Black.Red =3D Black.Reserved =3D 0; + White.Blue =3D White.Green =3D White.Red =3D White.Reserved =3D 0xFF; + + Status =3D 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 () =3D=3D BOOT_ON_FLASH_UPDATE) { + ProcessCapsules (); + } + + OsIndication =3D 0; + Attributes =3D 0; + DataSize =3D sizeof (UINT64); + Status =3D gRT->GetVariable ( + EFI_OS_INDICATIONS_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + &Attributes, + &DataSize, + &OsIndication + ); + if (EFI_ERROR (Status)) { + OsIndication =3D 0; + } + + // + // Register UEFI Shell + // + PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", L= OAD_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 ti= meout. + + @param TimeoutRemain The remaining timeout. +**/ +VOID +EFIAPI +PlatformBootManagerWaitCallback ( + UINT16 TimeoutRemain + ) +{ + if (mUniversalPayloadPlatformBootManagerOverrideInstance !=3D NULL) { + mUniversalPayloadPlatformBootManagerOverrideInstance->WaitCallback (Ti= meoutRemain); + } + + 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 !=3D 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 ((DEBUG_INFO, "ExposeOver4GMemoryEventCallback\n")); + + TmpLink =3D NULL; + NoFound =3D TRUE; + + InitializeListHead (&NonTestedMemRanList); + + gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); + for (Index =3D 0; Index < NumberOfDescriptors; Index++) { + if ((MemorySpaceMap[Index].GcdMemoryType =3D=3D EfiGcdMemoryTypeReserv= ed) && + ((MemorySpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_M= EMORY_INITIALIZED | EFI_MEMORY_TESTED)) =3D=3D + (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) + ) + { + NoFound =3D FALSE; + + gBS->AllocatePool (EfiBootServicesData, sizeof (NONTESTED_MEMORY_RAN= GE), (VOID **)&Range); + + Range->Signature =3D EFI_NONTESTED_MEMORY_RANGE_SIGNATURE; + Range->StartAddress =3D MemorySpaceMap[Index].BaseAddress; + Range->Length =3D MemorySpaceMap[Index].Length; + Range->Capabilities =3D MemorySpaceMap[Index].Capabilities; + + InsertTailList (&NonTestedMemRanList, &Range->Link); + } + } + + if (!NoFound) { + TmpLink =3D NonTestedMemRanList.ForwardLink; + + while (TmpLink !=3D &NonTestedMemRanList) { + Range =3D CR (TmpLink, NONTESTED_MEMORY_RANGE, Link, EFI_NONTESTED_M= EMORY_RANGE_SIGNATURE); + gDS->RemoveMemorySpace (Range->StartAddress, Range->Length); + gDS->AddMemorySpace ( + EfiGcdMemoryTypeSystemMemory, + Range->StartAddress, + Range->Length, + Range->Capabilities &~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIA= LIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME) + ); + + TmpLink =3D TmpLink->ForwardLink; + } + } + + // + // Make sure the hook ONLY called once. + // + if (Event !=3D NULL) { + gBS->CloseEvent (Event); + } +} + +/** + Get/update PcdBootManagerMenuFile from GUID HOB which will be assigned i= n 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 =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + ExposeOver4GMemoryEventCallback, + NULL, + &gEfiEventReadyToBootGuid, + &ExposeOver4GMemoryEvent + ); + ASSERT_EFI_ERROR (Status); + + GuidHob =3D GetFirstGuidHob (&gEdkiiBootManagerMenuFileGuid); + + if (GuidHob =3D=3D NULL) { + // + // If the HOB is not create, the default value of PcdBootManagerMenuFi= le will be used. + // + return EFI_SUCCESS; + } + + GenericHeader =3D (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 =3D=3D UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU_R= EVISION) { + BootManagerMenuFile =3D (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU *)GET_GUI= D_HOB_DATA (GuidHob); + if (BootManagerMenuFile->Header.Length < UNIVERSAL_PAYLOAD_SIZEOF_THRO= UGH_FIELD (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU, FileName)) { + return EFI_NOT_FOUND; + } + + Size =3D sizeof (BootManagerMenuFile->FileName); + Status =3D PcdSetPtrS (PcdBootManagerMenuFile, &Size, &BootManagerMenu= File->FileName); + ASSERT_EFI_ERROR (Status); + } else { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/Pla= tformBootManagerLib/PlatformBootManager.h b/Platform/AMD/VanGoghBoard/Chach= aniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.h new file mode 100644 index 0000000000..15891f9471 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBo= otManagerLib/PlatformBootManager.h @@ -0,0 +1,150 @@ +/** @file + Head file for BDS Platform specific code + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef PLATFORM_BOOT_MANAGER_H_ +#define PLATFORM_BOOT_MANAGER_H_ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +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 con= sole. + + @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/Pla= tformBootManagerLib/PlatformBootManagerLib.inf b/Platform/AMD/VanGoghBoard/= ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager= Lib.inf new file mode 100644 index 0000000000..fc9251d3fd --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBo= otManagerLib/PlatformBootManagerLib.inf @@ -0,0 +1,89 @@ +## @file +# Include all platform action which can be customized by IBV/OEM. +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. +# Copyright (c) 2012 - 2021, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PlatformBootManagerLib + FILE_GUID =3D 9455F0BD-2037-488A-8899-56CB72A44A03 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PlatformBootManagerLib|DXE_DRIVER + CONSTRUCTOR =3D PlatformBootManagerLibConstructor + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/Pla= tformBootManagerLib/PlatformConsole.c b/Platform/AMD/VanGoghBoard/ChachaniB= oardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.c new file mode 100644 index 0000000000..4849770ff6 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBo= otManagerLib/PlatformConsole.c @@ -0,0 +1,495 @@ +/** @file +This file include all platform action which can be customized by IBV/OEM. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PlatformBootManager.h" +#include "PlatformConsole.h" +#include + +#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 =3D gPnpPs2Keyboard; +ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode =3D gPnp16550ComPort; +VENDOR_DEVICE_PATH gTerminalTypeDeviceNode =3D 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 Co= nIn. + @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missin= g + from DeviceHandle. +**/ +EFI_STATUS +PrepareLpcBridgeDevicePath ( + IN EFI_HANDLE DeviceHandle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath =3D NULL; + Status =3D gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID *)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Register Keyboard + // + DevicePath =3D AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOC= OL *)&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 =3D=3D NULL) || (GopDevicePath =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the GopDevicePath to be PciDevicePath + // + *GopDevicePath =3D PciDevicePath; + TempPciDevicePath =3D PciDevicePath; + + Status =3D gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempPciDevicePath, + &PciDeviceHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE); + + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiGraphicsOutputProtocolGuid, + NULL, + &GopHandleCount, + &GopHandleBuffer + ); + if (!EFI_ERROR (Status)) { + // + // Add all the child handles as possible Console Device + // + for (Index =3D 0; Index < GopHandleCount; Index++) { + Status =3D gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDeviceP= athProtocolGuid, (VOID *)&TempDevicePath); + if (EFI_ERROR (Status)) { + continue; + } + + if (CompareMem ( + PciDevicePath, + TempDevicePath, + GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH + ) =3D=3D 0) + { + // + // In current implementation, we only enable one of the child hand= les + // 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 devi= ce + // + *GopDevicePath =3D TempDevicePath; + + // + // Delete the PCI device's path that added by GetPlugInPciVgaDevic= ePath() + // 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 =3D NULL; + Status =3D gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID *)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + GetGopDevicePath (DevicePath, &GopDevicePath); + DevicePath =3D 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 =3D 0; + HandleBuffer =3D NULL; + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + Id, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance); + if (EFI_ERROR (Status)) { + continue; + } + + Status =3D (*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 succe= ssfully. + @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 =3D (EFI_PCI_IO_PROTOCOL *)Instance; + + // + // Check for all PCI device + // + Status =3D PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D 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 =3D=3D 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 =3D NULL; + Status =3D gBS->InstallProtocolInterface ( + &CPMHandle, + &gAmdCpmAllPciIoProtocolsInstalledProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_INFO, "InstallProtocolInterface gAmdCpmAllPciIoProtocols= InstalledProtocolGuid %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 =3D NULL; + Status =3D gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID *)&DevicePath + ); + DevicePath =3D AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOC= OL *)&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, Err= Out + + @param[in] DetectDisplayOnly - Only detect display device if it's TRUE. + + @retval EFI_SUCCESS - PCI Device check and Console variable update succe= ssfully. + @retval EFI_STATUS - PCI Device check or Console variable update fail. + +**/ +EFI_STATUS +DetectAndPreparePlatformPciDevicePaths ( + BOOLEAN DetectDisplayOnly + ) +{ + EFI_STATUS Status; + + mDetectDisplayOnly =3D DetectDisplayOnly; + + EfiBootManagerUpdateConsoleVariable ( + ConIn, + (EFI_DEVICE_PATH_PROTOCOL *)&gUsbClassKeyboardDevicePath, + NULL + ); + + VisitAllInstancesOfProtocol ( + &gEfiSerialIoProtocolGuid, + AddDevicePathForOneSerialIoInstance + ); + + Status =3D 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 =3D 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/Pla= tformBootManagerLib/PlatformConsole.h b/Platform/AMD/VanGoghBoard/ChachaniB= oardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.h new file mode 100644 index 0000000000..dc66db7ced --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBo= otManagerLib/PlatformConsole.h @@ -0,0 +1,69 @@ +/** @file +Head file for BDS Platform specific code + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef PLATFORM_CONSOLE_H_ +#define PLATFORM_CONSOLE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/Pla= tformBootManagerLib/PlatformData.c b/Platform/AMD/VanGoghBoard/ChachaniBoar= dPkg/Library/Capsule/PlatformBootManagerLib/PlatformData.c new file mode 100644 index 0000000000..d8871a4bd5 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBo= otManagerLib/PlatformData.c @@ -0,0 +1,39 @@ +/** @file + Defined the platform specific device path which will be filled to + ConIn/ConOut variables. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PlatformBootManager.h" + +/// +/// Predefined platform default console device path +/// +GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformCon= sole[] =3D { + { + NULL, + 0 + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeybo= ardDevicePath =3D { + { + { + 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/Overri= de/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf new file mode 100644 index 0000000000..c99dd4cd47 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/Capsul= eRuntimeDxe/CapsuleRuntimeDxe.inf @@ -0,0 +1,122 @@ +## @file +# Capsule Runtime DXE Module INF file +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +## @file +# Capsule Runtime Driver produces two UEFI capsule runtime services: (Upd= ateCapsule, QueryCapsuleCapabilities). +# +# It installs the Capsule Architectural Protocol defined in PI1.0a to sig= nify +# the capsule runtime services are ready. +# +# Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
+# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All righ= ts reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D CapsuleRuntimeDxe + MODULE_UNI_FILE =3D CapsuleRuntimeDxe.uni + FILE_GUID =3D 42857F0A-13F2-4B21-8A23-53D3F714B840 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D CapsuleServiceInitialize + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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 acro= ss 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 h= andle >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 ## CO= NSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSupportProcessCapsuleAtRuntime ## CO= NSUMES + +[FeaturePcd.X64] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUME= S + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule ## SOMETIM= ES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule ## SOMETIM= ES_CONSUMES # Populate Image requires reset support. + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport ## CONSUME= S + +[Pcd.X64] + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize ## SOMET= IMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMET= IMES_CONSUMES + +[Depex] + gEfiVariableWriteArchProtocolGuid AND # Depends on variable w= rite 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/ed= k2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c new file mode 100644 index 0000000000..6915c054dd --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/Capsul= eRuntimeDxe/CapsuleService.c @@ -0,0 +1,461 @@ +/** @file + Capsule Runtime Driver produces two UEFI capsule runtime services. + (UpdateCapsule, QueryCapsuleCapabilities) + It installs the Capsule Architectural Protocol defined in PI1.0a to sign= ify + the capsule runtime services are ready. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "CapsuleService.h" + +#include + +// +// Handle for the installation of Capsule Architecture Protocol. +// +EFI_HANDLE mNewHandle =3D NULL; + +// +// The times of calling UpdateCapsule () +// +UINTN mTimes =3D 0; + +UINT32 mMaxSizePopulateCapsule =3D 0; +UINT32 mMaxSizeNonPopulateCapsule =3D 0; + +// Cached MM Communication protocol. +EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication2 =3D NULL; + +// For MM Communication purpose. +EFI_MM_COMMUNICATE_HEADER *mCommunicationBuffer =3D NULL; +EFI_MM_COMMUNICATE_HEADER *mCommunicationBufferPhysical =3D NULL; +EFI_EVENT mVirtualAddressChangeEvent =3D 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 pa= yload should persist + across a system reset, the reset value returned from EFI_QueryCapsuleCap= abilities 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 poi= nters to the capsules + being passed into update capsule. + @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER i= n + CaspuleHeaderArray. + @param ScatterGatherList Physical pointer to a set of + EFI_CAPSULE_BLOCK_DESCRIPTOR that describe= s the + location in physical memory of a set of ca= psules. + + @retval EFI_SUCCESS Valid capsule was passed. If + CAPSULE_FLAGS_PERSIT_ACROSS_RESET is not s= et, 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 se= t of flags were + set in the capsule header. + @retval EFI_INVALID_PARAMETER CapsuleCount is Zero. + @retval EFI_INVALID_PARAMETER For across reset capsule image, ScatterGat= herList is NULL. + @retval EFI_UNSUPPORTED CapsuleImage is not recognized by the firm= ware. + @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has been previousl= y called this error indicates the capsule + is compatible with this platform but is no= t capable of being submitted or processed + in runtime. The caller may resubmit the ca= psule prior to ExitBootServices(). + @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has not been previ= ously called then this error indicates + the capsule is compatible with this platfo= rm 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 suppor= t 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 =3D FALSE; + InitiateReset =3D FALSE; + CapsuleHeader =3D NULL; + CapsuleVarName[0] =3D 0; + + for (ArrayNumber =3D 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + // + // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag mu= st have + // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well. + // + CapsuleHeader =3D CapsuleHeaderArray[ArrayNumber]; + if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPS= ULE_FLAGS_POPULATE_SYSTEM_TABLE)) =3D=3D CAPSULE_FLAGS_POPULATE_SYSTEM_TABL= E) { + 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 | CAPS= ULE_FLAGS_INITIATE_RESET)) =3D=3D CAPSULE_FLAGS_INITIATE_RESET) { + return EFI_INVALID_PARAMETER; + } + + // + // Check FMP capsule flag + // + if ( CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid) + && ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != =3D 0)) + { + return EFI_INVALID_PARAMETER; + } + + // + // Check Capsule image without populate flag by firmware support capsu= le function + // + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) =3D= =3D 0) { + Status =3D SupportCapsuleImage (CapsuleHeader); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + // + // Walk through all capsules, record whether there is a capsule needs re= set + // or initiate reset. And then process capsules which has no reset flag = directly. + // + for (ArrayNumber =3D 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader =3D 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) =3D=3D= 0) { + if (EfiAtRuntime () && !FeaturePcdGet (PcdSupportProcessCapsuleAtRun= time)) { + Status =3D EFI_OUT_OF_RESOURCES; + } else { + Status =3D ProcessCapsuleImage (CapsuleHeader); + } + + if (EFI_ERROR (Status)) { + return Status; + } + } else { + NeedReset =3D TRUE; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_INITIATE_RESET) !=3D 0) { + InitiateReset =3D TRUE; + } + } + } + + // + // After launching all capsules who has no reset flag, if no more capsul= es claims + // for a system reset just return. + // + if (!NeedReset) { + return EFI_SUCCESS; + } + + // + // ScatterGatherList is only referenced if the capsules are defined to p= ersist across + // system reset. + // + if (ScatterGatherList =3D=3D (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, Capsul= eUpdateData2... + // if user calls UpdateCapsule multiple times. + // + StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CHAR16), EFI_CA= PSULE_VARIABLE_NAME); + TempVarName =3D CapsuleVarName + StrLen (CapsuleVarName); + if (mTimes > 0) { + UnicodeValueToStringS ( + TempVarName, + sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarNam= e), + 0, + mTimes, + 0 + ); + } + + // + // ScatterGatherList is only referenced if the capsules are defined to p= ersist 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 =3D 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_IN= ITIATE_RESET Flag set in its header + // will initiate a reset of the platform which is compatible with th= e 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 =3D 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 re= turns a valid answer, + the capsule still is unsupported via UpdateCapsule(). + + @param CapsuleHeaderArray Virtual pointer to an array of virtual poi= nters to the capsules + being passed into update capsule. + @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER i= n + CaspuleHeaderArray. + @param MaxiumCapsuleSize On output the maximum size that UpdateCaps= ule() 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 undef= ined. + @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL, or ResetTyep i= s NULL, + Or CapsuleCount is Zero, or CapsuleImage i= s 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 =3D=3D NULL) || (ResetType =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + CapsuleHeader =3D NULL; + NeedReset =3D FALSE; + + for (ArrayNumber =3D 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader =3D CapsuleHeaderArray[ArrayNumber]; + // + // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag mu= st have + // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well. + // + if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPS= ULE_FLAGS_POPULATE_SYSTEM_TABLE)) =3D=3D CAPSULE_FLAGS_POPULATE_SYSTEM_TABL= E) { + 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 | CAPS= ULE_FLAGS_INITIATE_RESET)) =3D=3D CAPSULE_FLAGS_INITIATE_RESET) { + return EFI_INVALID_PARAMETER; + } + + // + // Check FMP capsule flag + // + if ( CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid) + && ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != =3D 0)) + { + return EFI_INVALID_PARAMETER; + } + + // + // Check Capsule image without populate flag is supported by firmware + // + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) =3D= =3D 0) { + Status =3D SupportCapsuleImage (CapsuleHeader); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + // + // Find out whether there is any capsule defined to persist across syste= m reset. + // + for (ArrayNumber =3D 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader =3D CapsuleHeaderArray[ArrayNumber]; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) !=3D 0= ) { + NeedReset =3D TRUE; + break; + } + } + + if (NeedReset) { + // + // Check if the platform supports update capsule across a system reset + // + if (!IsPersistAcrossResetCapsuleSupported ()) { + return EFI_UNSUPPORTED; + } + + *ResetType =3D EfiResetWarm; + *MaxiumCapsuleSize =3D (UINT64)mMaxSizePopulateCapsule; + } else { + // + // For non-reset capsule image. + // + *ResetType =3D EfiResetCold; + *MaxiumCapsuleSize =3D (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 invo= ked. + @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 succe= ssfully. + +**/ +EFI_STATUS +EFIAPI +CapsuleServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + mMaxSizePopulateCapsule =3D PcdGet32 (PcdMaxSizePopulateCapsule); + mMaxSizeNonPopulateCapsule =3D 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 capsu= le 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 v= ariable. + // This is not needed when capsule with reset type is not supported. + // + SaveLongModeContext (); + + // + // Install capsule runtime services into UEFI runtime service tables. + // + gRT->UpdateCapsule =3D UpdateCapsule; + gRT->QueryCapsuleCapabilities =3D QueryCapsuleCapabilities; + + // + // Install the Capsule Architectural Protocol on a new handle + // to signify the capsule runtime services are ready. + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mNewHandle, + &gEfiCapsuleArchProtocolGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL,= (VOID **)&mMmCommunication2); + ASSERT_EFI_ERROR (Status); + Status =3D gBS->AllocatePool (EfiRuntimeServicesData, sizeof (EFI_MM_COM= MUNICATE_HEADER), (VOID **)&mCommunicationBufferPhysical); + ASSERT_EFI_ERROR (Status); + CopyGuid (&(mCommunicationBufferPhysical->HeaderGuid), &gAmdSetCapsuleS3= FlagGuid); + mCommunicationBufferPhysical->MessageLength =3D 0; + mCommunicationBuffer =3D mCommunicationBufferPhys= ical; + + // 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/ed= k2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h new file mode 100644 index 0000000000..fc6d831663 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/Capsul= eRuntimeDxe/CapsuleService.h @@ -0,0 +1,73 @@ +/** @file + Capsule Runtime Driver produces two UEFI capsule runtime services. + (UpdateCapsule, QueryCapsuleCapabilities) + It installs the Capsule Architectural Protocol defined in PI1.0a to sign= ify + the capsule runtime services are ready. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef CAPSULE_SERVICE_H__ +#define CAPSULE_SERVICE_H__ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + 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 t= hat + some platforms only support such capsules at boot time. + + @return TRUE if a PersistAcrossReset capsule may be passed to UpdateCap= sule() + at this time + FALSE otherwise +**/ +BOOLEAN +IsPersistAcrossResetCapsuleSupported ( + VOID + ); + +/** + Writes Back a range of data cache lines covering a set of capsules in me= mory. + + 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 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114497): https://edk2.groups.io/g/devel/message/114497 Mute This Topic: https://groups.io/mt/103971394/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-