From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail05.groups.io (mail05.groups.io [45.79.224.7]) by spool.mail.gandi.net (Postfix) with ESMTPS id 4AC13740038 for ; Fri, 17 May 2024 03:49:59 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=lOFBG6RUPAwY1EI7KAjCbu8pUysOHDWrOcC6dAj/2Fs=; c=relaxed/simple; d=groups.io; h=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:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding:Content-Type; s=20240206; t=1715917797; v=1; b=lWuMuPJUezd9Nz9pY+kB/AKO69rcQRYt9VOnOkxNr1Zls4x1Sc+qrA9ntwlqbei6ly8+hzpm GiLCaYwEfAIFFO1T0vAw7aFddfql+xobmfNItsZnqQI5p7VkEOdjlPtA/+ebrVGSlFnmjp7dWwk oYQWur4L6/j4qys5qiNwe+nabyNL5D56EApN2RbLDf3NV56+I1bZyjhtdc3p3ute0juJfnaxgYh LqQ586bk5ORHGcqxkAX0bIQRf9LPngjnukZl289VFHsfDGmbvjlaH24zdrFMnlirWIvrsDF0SLF /9SQjUYnRqwoojajNdk/S5unI2ecTe6xgRSjcuPW3Ig6Q== X-Received: by 127.0.0.2 with SMTP id ikUcYY7687511x2ZvCnhdhkw; Thu, 16 May 2024 20:49:57 -0700 X-Received: from NAM02-DM3-obe.outbound.protection.outlook.com (NAM02-DM3-obe.outbound.protection.outlook.com [40.107.95.50]) by mx.groups.io with SMTP id smtpd.web11.32600.1715917791838276245 for ; Thu, 16 May 2024 20:49:52 -0700 X-Received: from MN2PR19CA0046.namprd19.prod.outlook.com (2603:10b6:208:19b::23) by IA1PR12MB7592.namprd12.prod.outlook.com (2603:10b6:208:428::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7587.26; Fri, 17 May 2024 03:49:45 +0000 X-Received: from BN2PEPF00004FBC.namprd04.prod.outlook.com (2603:10b6:208:19b:cafe::54) by MN2PR19CA0046.outlook.office365.com (2603:10b6:208:19b::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7544.55 via Frontend Transport; Fri, 17 May 2024 03:49:45 +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 BN2PEPF00004FBC.mail.protection.outlook.com (10.167.243.182) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7587.21 via Frontend Transport; Fri, 17 May 2024 03:49:45 +0000 X-Received: from SATLEXMB06.amd.com (10.181.40.147) 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.35; Thu, 16 May 2024 22:49:44 -0500 X-Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB06.amd.com (10.181.40.147) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Thu, 16 May 2024 22:49:43 -0500 X-Received: from BLR-LAB-SFW01.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.35 via Frontend Transport; Thu, 16 May 2024 22:49:42 -0500 From: "Abdul Lateef Attar via groups.io" To: CC: Abdul Lateef Attar , Abner Chang , Paul Grimes Subject: [edk2-devel] [PATCH 5/5] AmdMinBoardPkg: Implements BoardBdsHookLib library Date: Fri, 17 May 2024 09:19:13 +0530 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN2PEPF00004FBC:EE_|IA1PR12MB7592:EE_ X-MS-Office365-Filtering-Correlation-Id: ad9ddbe2-c246-4807-6084-08dc7624647b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?X/uV8NX64UHBcY/NOCbUDmFsnIsgH4SItJuIbEo1ylOUPGx9Gxy5cXf9P0OR?= =?us-ascii?Q?2EVqkEj/A1JCBxhLtIKOqRxy6Hl0lXz+lMSF7z8Vr3XItuFphjj4najWfdr1?= =?us-ascii?Q?beZScUY09Rah3g2OSYtPYJeqHCIxzvO7E1bhbBjleCcM2/DaFmcgPqqVz3Y6?= =?us-ascii?Q?McJMXAzv/2tpSXEmnpKKpfptyY2lx5ISEXOlQMrPCy5Mgc/e4oL5SChezEw1?= =?us-ascii?Q?Zo8H2GPIqwcIgsuWN5r7M3zHHqeqprdP8Xe1f8j3DlALg1HnsUR3Q7hFUssN?= =?us-ascii?Q?CPJng33shGYi8OffElDxZqNXsZDmdDzxj2RIe/ZkLiQpVG0wwe1cx0ZaZKqR?= =?us-ascii?Q?67cQvCEpyXIC7wq/BHU8vguc8Sdmg2LeSmm5+wTAMc02ebR40hj3aLAmnuM7?= =?us-ascii?Q?Sls3zJvX3jvGCbgwNW48wpFOhKNyY1vbhrlwWR4tzJYKDIWpw9anrWY9FMck?= =?us-ascii?Q?5RG/W4lEKwwCxWjJ3lZviLsJu2Ktl5qWORE03BFd6AG9+LAuhsxKsyUlodQZ?= =?us-ascii?Q?RnUfxblClQ9txzlvzw2JsRtObCRtJlTMiDPSKNeosWYhG7Dxw0b1+8d9l62Q?= =?us-ascii?Q?2Rll8Cl9Xqqrx9m1sePHCvjIryxZ5+U3bdnwBq56l+gyrhl1NOWHibp6+3GO?= =?us-ascii?Q?e1KM3z1MaaBv9+O/U333ACoqq4xBiS6iR1cSVvPe8uLL9IHBD+CB0NY5o9E2?= =?us-ascii?Q?j+oxVzKimrJZTRDNZ7pGnpSL3VY0iJtyxLUB2RltO4IGX/eU+eiGM+Sp3AV8?= =?us-ascii?Q?+OxmINF1Q5Se2tSBumxGiJ97egnTs8u1LceXiPkH+EDrFsxiPNEg9EAf8rI4?= =?us-ascii?Q?+jZjuDRgIuSEPlpIrfJFKAnxYaaZEq997gST6qHKzVShHWJGfeBi+WwtFZeZ?= =?us-ascii?Q?AE1BdfuzdkiW+8pePKJSErXhJoPHHsExHqAz6HXKwdixWOSArzc1tFhneEN3?= =?us-ascii?Q?FYw5zdpbBo8s1KnFCoSxXviFOs/27n7fxnytZy6+VyU1RqsBCJjtktECBVbZ?= =?us-ascii?Q?Dpfh5jTS3PP1UG0mpcVhu/VZ0XPYmskrAYoSYMiCQU6XydqYRaWNHcZ0qaUB?= =?us-ascii?Q?7uV7e/3Y1t+GOwAUd75ugEP5vazirTJq/X2Zi05ICKfaWlPeQCiIN9ENLynf?= =?us-ascii?Q?sET8h8sJ3ONdJQFOdjos7Q9Q+LvY4bjGkqoGq6YRegwjEhvMYLdKaesykfet?= =?us-ascii?Q?H1rAAG/IiyC70Frua6VsZi0JZTMEn55ZJ8XWyP480IST6iLgF9ofAOha4ZO0?= =?us-ascii?Q?mXqFctCPuTpxcnftEEIq2r6MBO1wzFfxqGkH1jZvtcCixaVVINPAFwOUdC5I?= =?us-ascii?Q?5NhCU55RygBfNH/2UIwt96Ay4oZBBZAXw2erVtjUvf8lDSkRG7rMVyMu4zxT?= =?us-ascii?Q?K7lf7QCy6Q/3KONLvXV1wzAEHhaP?= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 May 2024 03:49:45.6006 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: ad9ddbe2-c246-4807-6084-08dc7624647b 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: BN2PEPF00004FBC.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: IA1PR12MB7592 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 Resent-Date: Thu, 16 May 2024 20:49:52 -0700 Resent-From: AbdulLateef.Attar@amd.com Reply-To: devel@edk2.groups.io,AbdulLateef.Attar@amd.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: myQQa4146wIiGbtf7KFHSr4kx7686176AA= 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=20240206 header.b=lWuMuPJU; dmarc=pass (policy=none) header.from=groups.io; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 45.79.224.7 as permitted sender) smtp.mailfrom=bounce@groups.io Implements BoardBdsHookLib library class for AMD platforms. Cc: Abner Chang Cc: Paul Grimes Signed-off-by: Abdul Lateef Attar --- .../AMD/AmdMinBoardPkg/AmdMinBoardPkg.dec | 10 + .../AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc | 2 + .../Include/Library/AmdBoardBdsHookLib.h | 130 ++ .../Library/BoardBdsHookLib/BoardBdsHook.h | 242 +++ .../Library/BoardBdsHookLib/BoardBdsHookLib.c | 1712 +++++++++++++++++ .../BoardBdsHookLib/BoardBdsHookLib.inf | 105 + .../Library/BoardBdsHookLib/BoardBootOption.c | 754 ++++++++ .../Library/BoardBdsHookLib/BoardMemoryTest.c | 83 + 8 files changed, 3038 insertions(+) create mode 100644 Platform/AMD/AmdMinBoardPkg/Include/Library/AmdBoardBds= HookLib.h create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/Boa= rdBdsHook.h create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/Boa= rdBdsHookLib.c create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/Boa= rdBdsHookLib.inf create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/Boa= rdBootOption.c create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/Boa= rdMemoryTest.c diff --git a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dec b/Platform/AMD/= AmdMinBoardPkg/AmdMinBoardPkg.dec index 03d1d77c34..47ec5b4b56 100644 --- a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dec +++ b/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dec @@ -17,9 +17,19 @@ PACKAGE_GUID =3D 44F9D761-9ECB-43DD-A5AC-177E5048701B PACKAGE_VERSION =3D 0.1 =20 +[Includes] + Include + [Guids] gAmdMinBoardPkgTokenSpaceGuid =3D {0xd4d23d79, 0x73bf, 0x460a, {0xa1, 0= xc7, 0x85, 0xa3, 0xca, 0x71, 0xb9, 0x4c}} =20 +[LibraryClasses] + ## @libraryclass Provide services to platform BDS hook. + BoardBdsHookLib|Include/Library/AmdBoardBdsHookLib.h + +[Protocols] + gAmdBoardBdsBootOptionPriorityProtocolGuid =3D { 0x5806db97, 0x5303, 0x4= 09f, { 0x8f, 0x09, 0xab, 0x29, 0xd8, 0x07, 0xa3, 0xf1}} + [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] # # PCI HotPlug Resource Padding diff --git a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc b/Platform/AMD/= AmdMinBoardPkg/AmdMinBoardPkg.dsc index e0afe1e755..e002e78f21 100644 --- a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc +++ b/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc @@ -41,6 +41,7 @@ BoardInitLib|AmdMinBoardPkg/Library/PeiBoardInitPreMemLib/PeiBoardInitPr= eMemLib.inf =20 [LibraryClasses.common.DXE_DRIVER] + BoardBdsHookLib|AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.i= nf BoardInitLib|AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf =20 [Components] @@ -53,4 +54,5 @@ =20 [Components.X64] AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf + AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf AmdMinBoardPkg/PciHotPlug/PciHotPlugInit.inf \ No newline at end of file diff --git a/Platform/AMD/AmdMinBoardPkg/Include/Library/AmdBoardBdsHookLib= .h b/Platform/AMD/AmdMinBoardPkg/Include/Library/AmdBoardBdsHookLib.h new file mode 100644 index 0000000000..6bfa4747e0 --- /dev/null +++ b/Platform/AMD/AmdMinBoardPkg/Include/Library/AmdBoardBdsHookLib.h @@ -0,0 +1,130 @@ +/** @file + Header file for BDS Hook Library + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef AMD_BOARD_BDS_HOOK_LIB_H_ +#define AMD_BOARD_BDS_HOOK_LIB_H_ + +#include +#include +#include +#include + +#define AMD_BOARD_BDS_BOOT_OPTION_PRIORITY_PROTOCOL_GUID \ + { 0x5806db97, 0x5303, 0x409f, \ + { 0x8f, 0x09, 0xab, 0x29, 0xd8, 0x07, 0xa3, 0xf1 }} + +/* + This protocol is introduced so the platform can give certain boot option= s + a custom priority value. Useful in boot overrides, or when IPMI doesn't = inherently + support a specific boot override needed by the platform. +*/ +struct _AMD_BOARD_BDS_BOOT_OPTION_PRIORITY_PROTOCOL { + UINT8 IpmiBootDeviceSelectorType; + SORT_COMPARE Compare; +}; + +typedef struct _AMD_BOARD_BDS_BOOT_OPTION_PRIORITY_PROTOCOL AMD_BOARD_BDS_= BOOT_OPTION_PRIORITY_PROTOCOL; + +extern EFI_GUID gAmdBoardBdsBootOptionPriorityProtocolGuid; + +/** + Returns the boot option type of a device + + @param[in] DevicePath The path of device whose boot option type + should be returned + @retval -1 Device type not found + @retval > -1 Device type found +**/ +UINT8 +BootOptionType ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + This is the callback function for Bds Ready To Boot event. + + @param[in] Event Pointer to this event + @param[in] Context Event handler private data + + @retval None. +**/ +VOID +EFIAPI +BdsReadyToBootCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + This is the callback function for Smm Ready To Lock event. + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsSmmReadyToLockCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + This is the callback function for PCI ENUMERATION COMPLETE. + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsPciEnumCompleteCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Before console after trusted console event callback + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsBeforeConsoleAfterTrustedConsoleCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Before console before end of DXE event callback + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsBeforeConsoleBeforeEndOfDxeGuidCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + After console ready before boot option event callback + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsAfterConsoleReadyBeforeBootOptionCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +#endif diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHo= ok.h b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h new file mode 100644 index 0000000000..5c950c4866 --- /dev/null +++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h @@ -0,0 +1,242 @@ +/** @file + Header file for BDS Hook Library + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef BOARD_BDS_HOOK_H_ +#define BOARD_BDS_HOOK_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/// +/// For boot order override. +/// +#define IPMI_BOOT_OVERRIDE_VAR_NAME L"IpmiBootOverride" +#define IS_FIRST_BOOT_VAR_NAME L"IsFirstBoot" +#define UEFI_HARD_DRIVE_NAME L"UEFI Hard Drive" + +/// +/// ConnectType +/// +#define CONSOLE_OUT 0x00000001 +#define STD_ERROR 0x00000002 +#define CONSOLE_IN 0x00000004 +#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR) +#define END_ENTIRE_DEVICE_PATH \ + { \ + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PAT= H_LENGTH, 0 } \ + } + +extern EFI_GUID gUefiShellFileGuid; +extern EFI_BOOT_MODE gBootMode; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN ConnectType; +} BDS_CONSOLE_CONNECT_ENTRY; + +// +// Platform Root Bridge +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_ROOT_BRIDGE_DEVICE_PATH; + +// +// Below is the platform console device path +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH IsaBridge; + ACPI_HID_DEVICE_PATH Keyboard; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_KEYBOARD_DEVICE_PATH; + +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH PciDevice; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_ONBOARD_CONTROLLER_DEVICE_PATH; + +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH Pci0Device; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_PEG_ROOT_CONTROLLER_DEVICE_PATH; + +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH PciBridge; + PCI_DEVICE_PATH PciDevice; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_PCI_CONTROLLER_DEVICE_PATH; + +// +// Below is the boot option device path +// + +#define CLASS_HID 3 +#define SUBCLASS_BOOT 1 +#define PROTOCOL_KEYBOARD 1 + +typedef struct { + USB_CLASS_DEVICE_PATH UsbClass; + EFI_DEVICE_PATH_PROTOCOL End; +} USB_CLASS_FORMAT_DEVICE_PATH; + +extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath; + +// +// Platform BDS Functions +// + +/** + Perform the memory test base on the memory test intensive level, + and update the memory resource. + + @param[in] Level The memory test intensive level. + + @retval EFI_STATUS Success test all the system memory and update + the memory resource + +**/ +EFI_STATUS +MemoryTest ( + IN EXTENDMEM_COVERAGE_LEVEL Level + ); + +/** + Connect with predeined platform connect sequence, + the OEM/IBV can customize with their own connect sequence. + + @param[in] BootMode Boot mode of this boot. +**/ +VOID +ConnectSequence ( + IN EFI_BOOT_MODE BootMode + ); + +/** + Compares boot priorities of two boot options + + @param[in] Left The left boot option + @param[in] Right The right boot option + + @return The difference between the Left and Right + boot options + **/ +INTN +EFIAPI +CompareBootOption ( + IN CONST VOID *Left, + IN CONST VOID *Right + ); + +/** + Compares boot priorities of two boot options, while giving PXE the high= est priority + + @param[in] Left The left boot option + @param[in] Right The right boot option + + @return The difference between the Left and Right + boot options +**/ +INTN +EFIAPI +CompareBootOptionPxePriority ( + IN CONST VOID *Left, + IN CONST VOID *Right + ); + +/** + Compares boot priorities of two boot options, while giving HDD the high= est priority + + @param[in] Left The left boot option + @param[in] Right The right boot option + + @return The difference between the Left and Right + boot options +**/ +INTN +EFIAPI +CompareBootOptionHddPriority ( + IN CONST VOID *Left, + IN CONST VOID *Right + ); + +/** + This function is called after all the boot options are enumerated and or= dered properly. +**/ +VOID +RegisterStaticHotkey ( + VOID + ); + +/** + Registers/Unregisters boot option hotkey +**/ +VOID +RegisterDefaultBootOption ( + VOID + ); + +/** + Add console variable device paths + + @param[in] ConsoleType ConIn or ConOut + @param[in] ConsoleDevicePath Device path to be added +**/ +VOID +AddConsoleVariable ( + IN CONSOLE_TYPE ConsoleType, + IN EFI_DEVICE_PATH *ConsoleDevicePath + ); + +#endif //BOARD_BDS_HOOK_H_ diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHo= okLib.c b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookL= ib.c new file mode 100644 index 0000000000..3d7c0c2bf7 --- /dev/null +++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c @@ -0,0 +1,1712 @@ +/** @file + This library registers Bds callbacks. It is a default library + implementation instance of the BDS hook library + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserv= ed.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "BoardBdsHook.h" + +#ifdef INTERNAL_IDS + #include +#endif + +CHAR16 *mConsoleVar[] =3D { L"ConIn"= , L"ConOut" }; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_BOOT_MODE gBootMode; +BOOLEAN gPPRequireUIConfirm; +extern UINTN mBootMenuOptionNumber; + +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 + }, + END_ENTIRE_DEVICE_PATH +}; + +#ifdef INTERNAL_IDS +EFI_STATUS +PrintSocOpnInfo ( + IN VOID + ); + +#endif + +// +// BDS Platform Functions +// + +/** + Checks if Mor bit is set. + @retval TRUE The MOR bit is set + @retval FALSE The MOR bit is not set +**/ +BOOLEAN +IsMorBitSet ( + VOID + ) +{ + UINTN MorControl; + EFI_STATUS Status; + UINTN DataSize; + + // + // Check if the MOR bit is set. + // + DataSize =3D sizeof (MorControl); + Status =3D gRT->GetVariable ( + MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, + &gEfiMemoryOverwriteControlDataGuid, + NULL, + &DataSize, + &MorControl + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, " gEfiMemoryOverwriteControlDataGuid doesn't exist= !!***\n")); + MorControl =3D 0; + } else { + DEBUG ((DEBUG_INFO, " Get the gEfiMemoryOverwriteControlDataGuid =3D %= x!!***\n", MorControl)); + } + + return (BOOLEAN)(MorControl & 0x01); +} + +/** + Prints device paths. + @param[in] Name The device name. + @param[in] DevicePath The device path to be printed +**/ +VOID +EFIAPI +DumpDevicePath ( + IN CHAR16 *Name, + IN EFI_DEVICE_PATH *DevicePath + ) +{ + CHAR16 *Str; + + Str =3D ConvertDevicePathToText (DevicePath, TRUE, TRUE); + DEBUG ((DEBUG_INFO, "%s: %s\n", Name, Str)); + if (Str !=3D NULL) { + FreePool (Str); + } +} + +/** + Return whether the device is trusted console. + + @param[in] ConsoleType The console type. + @param[in] Device The device path to be tested. + + @retval TRUE The device can be trusted. + @retval FALSE The device cannot be trusted. +**/ +BOOLEAN +IsTrustedConsole ( + IN CONSOLE_TYPE ConsoleType, + IN EFI_DEVICE_PATH_PROTOCOL *Device + ) +{ + VOID *TrustedConsoleDevicepath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Instance; + UINTN Size; + EFI_DEVICE_PATH_PROTOCOL *ConsoleDevice; + + if (Device =3D=3D NULL) { + return FALSE; + } + + ConsoleDevice =3D DuplicateDevicePath (Device); + + TrustedConsoleDevicepath =3D NULL; + + switch (ConsoleType) { + case ConIn: + TrustedConsoleDevicepath =3D DuplicateDevicePath (PcdGetPtr (PcdTrus= tedConsoleInputDevicePath)); + break; + case ConOut: + // + // Check GOP and remove last node + // + TempDevicePath =3D ConsoleDevice; + while (!IsDevicePathEndType (TempDevicePath)) { + if ((DevicePathType (TempDevicePath) =3D=3D ACPI_DEVICE_PATH) && + (DevicePathSubType (TempDevicePath) =3D=3D ACPI_ADR_DP)) + { + SetDevicePathEndNode (TempDevicePath); + break; + } + + TempDevicePath =3D NextDevicePathNode (TempDevicePath); + } + + TrustedConsoleDevicepath =3D DuplicateDevicePath (PcdGetPtr (PcdTrus= tedConsoleOutputDevicePath)); + break; + default: + ASSERT (FALSE); + break; + } + + TempDevicePath =3D TrustedConsoleDevicepath; + do { + Instance =3D GetNextDevicePathInstance (&TempDevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + + if (CompareMem (ConsoleDevice, Instance, Size - END_DEVICE_PATH_LENGTH= ) =3D=3D 0) { + FreePool (Instance); + FreePool (ConsoleDevice); + if (TempDevicePath !=3D NULL) { + FreePool (TempDevicePath); + } + + return TRUE; + } + + FreePool (Instance); + } while (TempDevicePath !=3D NULL); + + FreePool (ConsoleDevice); + if (TempDevicePath !=3D NULL) { + FreePool (TempDevicePath); + } + + return FALSE; +} + +/** + Return whether the USB device path is in a short form. + + @param[in] DevicePath The device path to be tested. + + @retval TRUE The device path is in short form. + @retval FALSE The device path is not in short form. +**/ +BOOLEAN +IsUsbShortForm ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + if ((DevicePathType (DevicePath) =3D=3D MESSAGING_DEVICE_PATH) && + ((DevicePathSubType (DevicePath) =3D=3D MSG_USB_CLASS_DP) || + (DevicePathSubType (DevicePath) =3D=3D MSG_USB_WWID_DP))) + { + return TRUE; + } + + return FALSE; +} + +/** + Connect the USB short form device path. + + @param[in] DevicePath USB short form device path + + @retval EFI_SUCCESS Successfully connected the USB device + @retval EFI_NOT_FOUND Cannot connect the USB device + @retval EFI_INVALID_PARAMETER The device path is invalid. +**/ +EFI_STATUS +ConnectUsbShortFormDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles; + UINTN HandleCount; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Class[3]; + BOOLEAN AtLeastOneConnected; + + // + // Check the passed in parameters + // + if (DevicePath =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!IsUsbShortForm (DevicePath)) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the usb host controller firstly, then connect with the remaining= device path + // + AtLeastOneConnected =3D FALSE; + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + Handles[Index], + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + if (!EFI_ERROR (Status)) { + // + // Check whether the Pci device is the wanted usb host controller + // + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Cla= ss); + if (!EFI_ERROR (Status) && + ((PCI_CLASS_SERIAL =3D=3D Class[2]) && (PCI_CLASS_SERIAL_USB =3D= =3D Class[1]))) + { + Status =3D gBS->ConnectController ( + Handles[Index], + NULL, + DevicePath, + FALSE + ); + if (!EFI_ERROR (Status)) { + AtLeastOneConnected =3D TRUE; + } + } + } + } + + return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND; +} + +/** + Return whether the Handle is a vga handle. + + @param[in] Handle The handle to be tested. + + @retval TRUE The handle is a vga handle. + @retval FALSE The handle is not a vga handle.. +**/ +BOOLEAN +IsVgaHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + EFI_STATUS Status; + + Status =3D gBS->HandleProtocol ( + Handle, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + if (!EFI_ERROR (Status)) { + Status =3D PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (!EFI_ERROR (Status)) { + if (IS_PCI_VGA (&Pci) || IS_PCI_OLD_VGA (&Pci)) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + Return whether the device path points to a video controller. + + @param[in] DevicePath The device path to be tested. + + @retval TRUE The device path points to a video controller. + @retval FALSE The device path does not point to a video controller. +**/ +EFI_HANDLE +IsVideoController ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DupDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_STATUS Status; + EFI_HANDLE DeviceHandle; + + DupDevicePath =3D DuplicateDevicePath (DevicePath); + ASSERT (DupDevicePath !=3D NULL); + if (DupDevicePath =3D=3D NULL) { + return NULL; + } + + TempDevicePath =3D DupDevicePath; + Status =3D gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempDevicePath, + &DeviceHandle + ); + FreePool (DupDevicePath); + if (EFI_ERROR (Status)) { + return NULL; + } + + if (IsVgaHandle (DeviceHandle)) { + return DeviceHandle; + } else { + return NULL; + } +} + +/** + Return whether the device path is a GOP device path. + + @param[in] DevicePath The device path to be tested. + + @retval TRUE The device path is a GOP device path. + @retval FALSE The device on the device path is not a GOP device path. +**/ +BOOLEAN +IsGopDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + while (!IsDevicePathEndType (DevicePath)) { + if ((DevicePathType (DevicePath) =3D=3D ACPI_DEVICE_PATH) && + (DevicePathSubType (DevicePath) =3D=3D ACPI_ADR_DP)) + { + return TRUE; + } + + DevicePath =3D NextDevicePathNode (DevicePath); + } + + return FALSE; +} + +/** + Remove all GOP device path instance from DevicePath and add the Gop to t= he DevicePath. + + @param[in] DevicePath The device path to be removed + @param[in] Gop The device path to be added. + + @retval Return The updated device path. +**/ +EFI_DEVICE_PATH_PROTOCOL * +UpdateGopDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *Gop + ) +{ + UINTN Size; + UINTN GopSize; + EFI_DEVICE_PATH_PROTOCOL *Temp; + EFI_DEVICE_PATH_PROTOCOL *Return; + EFI_DEVICE_PATH_PROTOCOL *Instance; + BOOLEAN Exist; + + Exist =3D FALSE; + Return =3D NULL; + GopSize =3D GetDevicePathSize (Gop); + do { + Instance =3D GetNextDevicePathInstance (&DevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + + if (!IsGopDevicePath (Instance) || + ((Size =3D=3D GopSize) && (CompareMem (Instance, Gop, GopSize) =3D= =3D 0)) + ) + { + if ((Size =3D=3D GopSize) && (CompareMem (Instance, Gop, GopSize) = =3D=3D 0)) { + Exist =3D TRUE; + } + + Temp =3D Return; + Return =3D AppendDevicePathInstance (Return, Instance); + if (Temp !=3D NULL) { + FreePool (Temp); + } + } + + FreePool (Instance); + } while (DevicePath !=3D NULL); + + if (!Exist) { + Temp =3D Return; + Return =3D AppendDevicePathInstance (Return, Gop); + if (Temp !=3D NULL) { + FreePool (Temp); + } + } + + return Return; +} + +/** + Get Graphics Controller Handle. VgaDevices needs to be freed by caller. + + @param[in] NeedTrustedConsole The flag to determine if trusted conso= le + or non trusted console should be retur= ned + @param[out] VgaDevices Array of handles corresponding to + valid VGA devices + @param[out] VgaDevicesCount Number of VGA devices found and placed= in + VgaDevices + + @retval EFI ERROR No VGA capable devices found + @retval EFI_SUCCESS At least one VGA device found +**/ +EFI_STATUS +EFIAPI +GetGraphicsController ( + IN BOOLEAN NeedTrustedConsole, + OUT EFI_HANDLE **VgaDevices, + OUT UINTN *VgaDevicesCount + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE *PciHandles; + UINTN PciHandlesSize; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINT32 NumDevices; + + if ((VgaDevicesCount =3D=3D NULL) || (VgaDevices =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + NumDevices =3D 0; + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &PciHandlesSize, + &PciHandles + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *VgaDevices =3D AllocateZeroPool (sizeof (EFI_HANDLE) * PciHandlesSize); + if (VgaDevices =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Index =3D 0; Index < PciHandlesSize; Index++) { + Status =3D gBS->HandleProtocol ( + PciHandles[Index], + &gEfiDevicePathProtocolGuid, + (VOID **)&DevicePath + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (!IsVgaHandle (PciHandles[Index])) { + continue; + } + + if ((NeedTrustedConsole && IsTrustedConsole (ConOut, DevicePath)) || + ((!NeedTrustedConsole) && (!IsTrustedConsole (ConOut, DevicePath))= )) + { + VgaDevices[0][NumDevices] =3D PciHandles[Index]; + NumDevices++; + } + } + + *VgaDevicesCount =3D NumDevices; + if (NumDevices > 0) { + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } +} + +/** + Updates Graphic ConOut variable. This function searches for all VGA capa= ble output devices and + adds them to the ConOut variable. + + @param[in] NeedTrustedConsole The flag that determines if trusted con= sole + or non trusted console should be returned +**/ +VOID +UpdateGraphicConOut ( + IN BOOLEAN NeedTrustedConsole + ) +{ + EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ConOutDevicePath; + EFI_DEVICE_PATH_PROTOCOL *UpdatedConOutDevicePath; + EFI_HANDLE *VgaDevices; + UINTN VgaDevicesCount; + UINTN Count; + EFI_STATUS Status; + + Count =3D 0; + VgaDevicesCount =3D 0; + + // + // Update ConOut variable + // + Status =3D GetGraphicsController (NeedTrustedConsole, &VgaDevices, &VgaD= evicesCount); + if (Status =3D=3D EFI_SUCCESS) { + GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL); + if (ConOutDevicePath !=3D NULL) { + DumpDevicePath (L"Original ConOut variable", ConOutDevicePath); + FreePool (ConOutDevicePath); + } + + // Add VGA devices to ConOut + for (Count =3D 0; Count < VgaDevicesCount; Count++) { + // + // Connect the GOP driver + // + gBS->ConnectController (VgaDevices[Count], NULL, NULL, TRUE); + // + // Get the GOP device path + // NOTE: We may get a device path that contains Controller node in i= t. + // + GopDevicePath =3D EfiBootManagerGetGopDevicePath (VgaDevices[Count])= ; + if (GopDevicePath !=3D NULL) { + GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL= ); + if (ConOutDevicePath !=3D NULL) { + UpdatedConOutDevicePath =3D UpdateGopDevicePath (ConOutDevicePat= h, GopDevicePath); + if (UpdatedConOutDevicePath !=3D NULL) { + gRT->SetVariable ( + L"ConOut", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS= | EFI_VARIABLE_BOOTSERVICE_ACCESS, + GetDevicePathSize (UpdatedConOutDevicePath), + UpdatedConOutDevicePath + ); + FreePool (UpdatedConOutDevicePath); + } + + FreePool (ConOutDevicePath); + } + + FreePool (GopDevicePath); + } + } + + FreePool (VgaDevices); + } + + GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL); + if (ConOutDevicePath !=3D NULL) { + DumpDevicePath (L"Final ConOut variable", ConOutDevicePath); + FreePool (ConOutDevicePath); + } +} + +/** + The function connects the trusted consoles. +**/ +VOID +ConnectTrustedConsole ( + VOID + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Consoles; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *Next; + UINTN Size; + UINTN Index; + EFI_HANDLE Handle; + EFI_STATUS Status; + VOID *TrustedConsoleDevicepath; + + TrustedConsoleDevicepath =3D PcdGetPtr (PcdTrustedConsoleInputDevicePath= ); + DumpDevicePath (L"TrustedConsoleIn", TrustedConsoleDevicepath); + TrustedConsoleDevicepath =3D PcdGetPtr (PcdTrustedConsoleOutputDevicePat= h); + DumpDevicePath (L"TrustedConsoleOut", TrustedConsoleDevicepath); + + for (Index =3D 0; Index < sizeof (mConsoleVar) / sizeof (mConsoleVar[0])= ; Index++) { + GetEfiGlobalVariable2 (mConsoleVar[Index], (VOID **)&Consoles, NULL); + + TempDevicePath =3D Consoles; + do { + Instance =3D GetNextDevicePathInstance (&TempDevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + + if (IsTrustedConsole (Index, Instance)) { + if (IsUsbShortForm (Instance)) { + ConnectUsbShortFormDevicePath (Instance); + } else { + for (Next =3D Instance; !IsDevicePathEnd (Next); Next =3D NextDe= vicePathNode (Next)) { + if ((DevicePathType (Next) =3D=3D ACPI_DEVICE_PATH) && (Device= PathSubType (Next) =3D=3D ACPI_ADR_DP)) { + break; + } else if ((DevicePathType (Next) =3D=3D HARDWARE_DEVICE_PATH)= && + (DevicePathSubType (Next) =3D=3D HW_CONTROLLER_DP) = && + (DevicePathType (NextDevicePathNode (Next)) =3D=3D = ACPI_DEVICE_PATH) && + (DevicePathSubType (NextDevicePathNode (Next)) =3D= =3D ACPI_ADR_DP) + ) + { + break; + } + } + + if (!IsDevicePathEnd (Next)) { + SetDevicePathEndNode (Next); + Status =3D EfiBootManagerConnectDevicePath (Instance, &Handle)= ; + if (!EFI_ERROR (Status)) { + gBS->ConnectController (Handle, NULL, NULL, TRUE); + } + } else { + EfiBootManagerConnectDevicePath (Instance, NULL); + } + } + } + + FreePool (Instance); + } while (TempDevicePath !=3D NULL); + + if (Consoles !=3D NULL) { + FreePool (Consoles); + } + } +} + +/** + The function connects the trusted Storages. +**/ +VOID +ConnectTrustedStorage ( + VOID + ) +{ + VOID *TrustedStorageDevicepath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Instance; + UINTN Size; + EFI_DEVICE_PATH_PROTOCOL *TempStorageDevicePath; + EFI_STATUS Status; + EFI_HANDLE DeviceHandle; + + TrustedStorageDevicepath =3D DuplicateDevicePath (PcdGetPtr (PcdTrustedS= torageDevicePath)); + DumpDevicePath (L"TrustedStorage", TrustedStorageDevicepath); + + TempDevicePath =3D TrustedStorageDevicepath; + do { + Instance =3D GetNextDevicePathInstance (&TempDevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + + EfiBootManagerConnectDevicePath (Instance, NULL); + + TempStorageDevicePath =3D Instance; + + Status =3D gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempStorageDevicePath, + &DeviceHandle + ); + if (!EFI_ERROR (Status)) { + gBS->ConnectController (DeviceHandle, NULL, NULL, FALSE); + } + + FreePool (Instance); + } while (TempDevicePath !=3D NULL); + + if (TempDevicePath !=3D NULL) { + FreePool (TempDevicePath); + } +} + +/** + Check if current BootCurrent variable is internal shell boot option. + + @retval TRUE BootCurrent is internal shell. + @retval FALSE BootCurrent is not internal shell. +**/ +BOOLEAN +BootCurrentIsInternalShell ( + VOID + ) +{ + UINTN VarSize; + UINT16 BootCurrent; + CHAR16 BootOptionName[16]; + UINT8 *BootOption; + UINT8 *Ptr; + BOOLEAN Result; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode; + EFI_GUID *GuidPoint; + + BootOption =3D NULL; + Result =3D FALSE; + + // + // Get BootCurrent variable + // + VarSize =3D sizeof (UINT16); + Status =3D gRT->GetVariable ( + L"BootCurrent", + &gEfiGlobalVariableGuid, + NULL, + &VarSize, + &BootCurrent + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Create boot option Bootxxxx from BootCurrent + // + UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04X", Boo= tCurrent); + + GetEfiGlobalVariable2 (BootOptionName, (VOID **)&BootOption, &VarSize); + if ((BootOption =3D=3D NULL) || (VarSize =3D=3D 0)) { + return FALSE; + } + + Ptr =3D BootOption; + Ptr +=3D sizeof (UINT32); + Ptr +=3D sizeof (UINT16); + Ptr +=3D StrSize ((CHAR16 *)Ptr); + TempDevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *)Ptr; + LastDeviceNode =3D TempDevicePath; + while (!IsDevicePathEnd (TempDevicePath)) { + LastDeviceNode =3D TempDevicePath; + TempDevicePath =3D NextDevicePathNode (TempDevicePath); + } + + GuidPoint =3D EfiGetNameGuidFromFwVolDevicePathNode ( + (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LastDeviceNode + ); + if ((GuidPoint !=3D NULL) && + ((CompareGuid (GuidPoint, &gUefiShellFileGuid)))) + { + // + // if this option is internal shell, return TRUE + // + Result =3D TRUE; + } + + if (BootOption !=3D NULL) { + FreePool (BootOption); + BootOption =3D NULL; + } + + return Result; +} + +/** + This function will change video resolution and text mode + for internal shell when internal shell is launched. + + @param None. + + @retval EFI_SUCCESS Mode is changed successfully. + @retval Others Mode failed to changed. +**/ +EFI_STATUS +EFIAPI +ChangeModeForInternalShell ( + VOID + ) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINT32 MaxGopMode; + UINT32 MaxTextMode; + UINT32 ModeNumber; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_STATUS Status; + UINTN Index; + UINTN CurrentColumn; + UINTN CurrentRow; + + // + // Internal shell mode + // + UINT32 mShellModeColumn; + UINT32 mShellModeRow; + UINT32 mShellHorizontalResolution; + UINT32 mShellVerticalResolution; + + // + // Get user defined text mode for internal shell only once. + // + mShellHorizontalResolution =3D PcdGet32 (PcdSetupVideoHorizontalResoluti= on); + mShellVerticalResolution =3D PcdGet32 (PcdSetupVideoVerticalResolution= ); + mShellModeColumn =3D PcdGet32 (PcdSetupConOutColumn); + mShellModeRow =3D PcdGet32 (PcdSetupConOutRow); + + Status =3D gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **)&GraphicsOutput + ); + if (EFI_ERROR (Status)) { + GraphicsOutput =3D NULL; + } + + Status =3D gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **)&SimpleTextOut + ); + if (EFI_ERROR (Status)) { + SimpleTextOut =3D NULL; + } + + if ((GraphicsOutput =3D=3D NULL) || (SimpleTextOut =3D=3D NULL)) { + return EFI_UNSUPPORTED; + } + + MaxGopMode =3D GraphicsOutput->Mode->MaxMode; + MaxTextMode =3D SimpleTextOut->Mode->MaxMode; + + // + // 1. If current video resolution is same with new video resolution, + // video resolution need not be changed. + // 1.1. If current text mode is same with new text mode, text mode ne= ed not be change. + // 1.2. If current text mode is different with new text mode, text mo= de need be change to new text mode. + // 2. If current video resolution is different with new video resolution= , we need restart whole console drivers. + // + for (ModeNumber =3D 0; ModeNumber < MaxGopMode; ModeNumber++) { + Status =3D GraphicsOutput->QueryMode ( + GraphicsOutput, + ModeNumber, + &SizeOfInfo, + &Info + ); + if (!EFI_ERROR (Status)) { + if ((Info->HorizontalResolution =3D=3D mShellHorizontalResolution) &= & + (Info->VerticalResolution =3D=3D mShellVerticalResolution)) + { + if ((GraphicsOutput->Mode->Info->HorizontalResolution =3D=3D mShel= lHorizontalResolution) && + (GraphicsOutput->Mode->Info->VerticalResolution =3D=3D mShellV= erticalResolution)) + { + // + // If current video resolution is same with new resolution, + // then check if current text mode is same with new text mode. + // + Status =3D SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOu= t->Mode->Mode, &CurrentColumn, &CurrentRow); + ASSERT_EFI_ERROR (Status); + if ((CurrentColumn =3D=3D mShellModeColumn) && (CurrentRow =3D= =3D mShellModeRow)) { + // + // Current text mode is same with new text mode, text mode nee= d not be change. + // + FreePool (Info); + return EFI_SUCCESS; + } else { + // + // Current text mode is different with new text mode, text mod= e need be change to new text mode. + // + for (Index =3D 0; Index < MaxTextMode; Index++) { + Status =3D SimpleTextOut->QueryMode (SimpleTextOut, Index, &= CurrentColumn, &CurrentRow); + if (!EFI_ERROR (Status)) { + if ((CurrentColumn =3D=3D mShellModeColumn) && (CurrentRow= =3D=3D mShellModeRow)) { + // + // New text mode is supported, set it. + // + Status =3D SimpleTextOut->SetMode (SimpleTextOut, Index)= ; + ASSERT_EFI_ERROR (Status); + // + // Update text mode PCD. + // + Status =3D PcdSet32S (PcdConOutColumn, mShellModeColumn)= ; + ASSERT_EFI_ERROR (Status); + + Status =3D PcdSet32S (PcdConOutRow, mShellModeRow); + ASSERT_EFI_ERROR (Status); + + FreePool (Info); + return EFI_SUCCESS; + } + } + } + + if (Index =3D=3D MaxTextMode) { + // + // If new text mode is not supported, return error. + // + FreePool (Info); + return EFI_UNSUPPORTED; + } + } + } else { + FreePool (Info); + // + // If current video resolution is not same with the new one, set= new video resolution. + // In this case, the driver which produces simple text out need = be restarted. + // + Status =3D GraphicsOutput->SetMode (GraphicsOutput, ModeNumber); + if (!EFI_ERROR (Status)) { + // + // Set PCD to restart GraphicsConsole and Consplitter to chang= e video resolution + // and produce new text mode based on new resolution. + // + Status =3D PcdSet32S (PcdVideoHorizontalResolution, mShellHori= zontalResolution); + ASSERT_EFI_ERROR (Status); + + Status =3D PcdSet32S (PcdVideoVerticalResolution, mShellVertic= alResolution); + ASSERT_EFI_ERROR (Status); + + Status =3D PcdSet32S (PcdConOutColumn, mShellModeColumn); + ASSERT_EFI_ERROR (Status); + + Status =3D PcdSet32S (PcdConOutRow, mShellModeRow); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextOutProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + for (Index =3D 0; Index < HandleCount; Index++) { + gBS->DisconnectController (HandleBuffer[Index], NULL, NULL= ); + } + + for (Index =3D 0; Index < HandleCount; Index++) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, T= RUE); + } + + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + + break; + } + } + } + } + + FreePool (Info); + } + } + + if (ModeNumber =3D=3D MaxGopMode) { + // + // If the new resolution is not supported, return error. + // + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + The function connects the trusted consoles and then call the PP processi= ng library interface. +**/ +VOID +ProcessTcgPp ( + VOID + ) +{ + gPPRequireUIConfirm |=3D Tcg2PhysicalPresenceLibNeedUserConfirm (); + + if (gPPRequireUIConfirm) { + ConnectTrustedConsole (); + } + + Tcg2PhysicalPresenceLibProcessRequest (NULL); +} + +/** + The function connects the trusted storage to perform TPerReset. +**/ +VOID +ProcessTcgMor ( + VOID + ) +{ + if (IsMorBitSet ()) { + ConnectTrustedConsole (); + ConnectTrustedStorage (); + } +} + +/** + Update the ConIn variable with USB Keyboard device path,if its not alrea= dy exists in ConIn. +**/ +VOID +EnumUsbKeyboard ( + VOID + ) +{ + DEBUG ((DEBUG_INFO, "[EnumUsbKeyboard]\n")); + EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *)= &gUsbClassKeyboardDevicePath, NULL); + // + // Append Usb Keyboard short form DevicePath into "ConInDev" + // + EfiBootManagerUpdateConsoleVariable (ConInDev, (EFI_DEVICE_PATH_PROTOCOL= *)&gUsbClassKeyboardDevicePath, NULL); +} + +/** + Connect with predeined platform connect sequence, + the OEM/IBV can customize with their own connect sequence. + + @param[in] BootMode Boot mode of this boot. +**/ +VOID +ConnectSequence ( + IN EFI_BOOT_MODE BootMode + ) +{ + EfiBootManagerConnectAll (); +} + +/** + Connects Root Bridge. + + @param[in] Recursive Recursively connect controllers if TRUE + **/ +VOID +ConnectRootBridge ( + IN BOOLEAN Recursive + ) +{ + UINTN RootBridgeHandleCount; + EFI_HANDLE *RootBridgeHandleBuffer; + UINTN RootBridgeIndex; + + RootBridgeHandleCount =3D 0; + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &RootBridgeHandleCount, + &RootBridgeHandleBuffer + ); + for (RootBridgeIndex =3D 0; RootBridgeIndex < RootBridgeHandleCount; Roo= tBridgeIndex++) { + gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL,= NULL, Recursive); + } +} + +/** + Add console variable device paths. + + @param[in] ConsoleType ConIn or ConOut + @param[in] ConsoleDevicePath Device path to be added +**/ +VOID +AddConsoleVariable ( + IN CONSOLE_TYPE ConsoleType, + IN EFI_DEVICE_PATH *ConsoleDevicePath + ) +{ + EFI_DEVICE_PATH *TempDevicePath; + EFI_DEVICE_PATH *Instance; + UINTN Size; + EFI_HANDLE GraphicsControllerHandle; + EFI_DEVICE_PATH *GopDevicePath; + + TempDevicePath =3D DuplicateDevicePath (ConsoleDevicePath); + do { + Instance =3D GetNextDevicePathInstance (&TempDevicePath, &Size); + if (Instance =3D=3D NULL) { + break; + } + + switch (ConsoleType) { + case ConIn: + if (IsUsbShortForm (Instance)) { + // + // Append Usb Keyboard short form DevicePath into "ConInDev" + // + EfiBootManagerUpdateConsoleVariable (ConInDev, Instance, NULL); + } + + EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL); + break; + case ConOut: + GraphicsControllerHandle =3D IsVideoController (Instance); + if (GraphicsControllerHandle =3D=3D NULL) { + EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL= ); + } else { + // + // Connect the GOP driver + // + gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TR= UE); + // + // Get the GOP device path + // NOTE: We may get a device path that contains Controller node = in it. + // + GopDevicePath =3D EfiBootManagerGetGopDevicePath (GraphicsContro= llerHandle); + if (GopDevicePath !=3D NULL) { + EfiBootManagerUpdateConsoleVariable (ConsoleType, GopDevicePat= h, NULL); + } + } + + break; + default: + ASSERT (FALSE); + break; + } + + FreePool (Instance); + } while (TempDevicePath !=3D NULL); + + if (TempDevicePath !=3D NULL) { + FreePool (TempDevicePath); + } +} + +/** + This is the callback function for PCI ENUMERATION COMPLETE. + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsPciEnumCompleteCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + VOID *ProtocolPointer; + EFI_DEVICE_PATH_PROTOCOL *VarConOut; + EFI_DEVICE_PATH_PROTOCOL *VarConIn; + + Status =3D EFI_SUCCESS; + + // + // Check if this is first time called by EfiCreateProtocolNotifyEvent() = or not, + // if it is, we will skip it until real event is triggered + // + Status =3D gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid,= NULL, (VOID **)&ProtocolPointer); + if (EFI_SUCCESS !=3D Status) { + return; + } + + // gBS->CloseEvent (Event); + + DEBUG ((DEBUG_INFO, "Event BdsPciEnumCompleteCallback callback starts\n"= )); + + gBootMode =3D GetBootModeHob (); + + // + // Fill ConIn/ConOut in Full Configuration boot mode + // + DEBUG ((DEBUG_INFO, "PlatformBootManagerInit - %x\n", gBootMode)); + + if ((gBootMode =3D=3D BOOT_WITH_FULL_CONFIGURATION) || + (gBootMode =3D=3D BOOT_WITH_DEFAULT_SETTINGS) || + (gBootMode =3D=3D BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS) || + (gBootMode =3D=3D BOOT_IN_RECOVERY_MODE)) + { + GetEfiGlobalVariable2 (L"ConOut", (VOID **)&VarConOut, NULL); + if (VarConOut !=3D NULL) { + FreePool (VarConOut); + } + + GetEfiGlobalVariable2 (L"ConIn", (VOID **)&VarConIn, NULL); + if (VarConIn !=3D NULL) { + FreePool (VarConIn); + } + + // + // Only fill ConIn/ConOut when ConIn/ConOut is empty because we may dr= op to Full Configuration boot mode in non-first boot + // + if ((VarConOut =3D=3D NULL) || (VarConIn =3D=3D NULL)) { + if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >=3D sizeof (EFI_= DEVICE_PATH_PROTOCOL)) { + AddConsoleVariable (ConOut, PcdGetPtr (PcdTrustedConsoleOutputDevi= cePath)); + } + + if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >=3D sizeof (EFI_D= EVICE_PATH_PROTOCOL)) { + AddConsoleVariable (ConIn, PcdGetPtr (PcdTrustedConsoleInputDevice= Path)); + } + } + } + + // + // Enumerate USB keyboard + // + EnumUsbKeyboard (); + + // + // For trusted console it must be handled here. + // + UpdateGraphicConOut (TRUE); + + // + // Register Boot Options + // + RegisterDefaultBootOption (); + + // + // Register Static Hot keys + // + RegisterStaticHotkey (); + + // + // Process Physical Preo + // + PERF_START_EX (NULL, "EventRec", NULL, AsmReadTsc (), 0x7010); + if (PcdGetBool (PcdTpm2Enable)) { + ProcessTcgPp (); + ProcessTcgMor (); + } + + PERF_END_EX (NULL, "EventRec", NULL, AsmReadTsc (), 0x7011); + + // + // Perform memory test + // We should make all UEFI memory and GCD information populated before E= xitPmAuth. + // SMM may consume these information. + // + MemoryTest ((EXTENDMEM_COVERAGE_LEVEL)PcdGet32 (PcdPlatformMemoryCheckLe= vel)); +} + +/** + This is the callback function for Smm Ready To Lock. + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsSmmReadyToLockCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + VOID *ProtocolPointer; + EFI_STATUS Status; + + // + // Check if this is first time called by EfiCreateProtocolNotifyEvent() = or not, + // if it is, we will skip it until real event is triggered + // + Status =3D gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL= , (VOID **)&ProtocolPointer); + if (EFI_SUCCESS !=3D Status) { + return; + } + + DEBUG ((DEBUG_INFO, "Event gEfiDxeSmmReadyToLockProtocolGuid callback st= arts\n")); + + // + // Dispatch the deferred 3rd party images. + // + EfiBootManagerDispatchDeferredImages (); + + // + // For non-trusted console it must be handled here. + // + UpdateGraphicConOut (FALSE); +} + +/** + ReadyToBoot callback to set video and text mode for internal shell boot. + That will not connect USB controller while CSM and FastBoot are disabled= , we need to connect them + before booting to Shell for showing USB devices in Shell. + + When FastBoot is enabled and Windows Console is the chosen Console behav= ior, input devices will not be connected + by default. Hence, when booting to EFI shell, connecting input consoles = are required. + + @param[in] Event Pointer to this event + @param[in] Context Event handler private data +**/ +VOID +EFIAPI +BdsReadyToBootCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DEBUG ((DEBUG_INFO, "BdsReadyToBootCallback\n")); + + if (BootCurrentIsInternalShell ()) { + ChangeModeForInternalShell (); + EfiBootManagerConnectAllDefaultConsoles (); + gDS->Dispatch (); + } +} + +/** + Before console after trusted console event callback + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsBeforeConsoleAfterTrustedConsoleCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DEBUG ((DEBUG_INFO, "Event gBdsEventBeforeConsoleBeforeEndOfDxeGuid call= back starts\n")); + + // + // Connect Root Bridge to make PCI BAR resource allocated and all PciIo = created + // + ConnectRootBridge (FALSE); +} + +/** + Before console before end of DXE event callback + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsBeforeConsoleBeforeEndOfDxeGuidCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DEBUG ((DEBUG_INFO, "Event gBdsBeforeConsoleBeforeEndOfDxeGuid callback = starts\n")); +} + +/** + Handles possible IPMI boot overrides by modifying the LoadOptions variab= le. + Uses sorting function installed in BootOptionPriorityProtocol if the pro= tocol + is installed and a valid IPMI override is detected. + + @retval EFI_SUCCESS Boot override successful, or not necessary. + @retval EFI_NOT_FOUND Attempted to override boot to an unsupported boo= t option. +**/ +EFI_STATUS +HandleIpmiBootOverride ( + VOID + ) +{ + UINT8 NvIpmiBootOverride; + UINT8 Index; + UINT8 CurrentIpmiBootOverride; + UINT8 *GetBootOptionsBuffer; + UINT8 *SetBootOptionsBuffer; + UINTN BootOptionCount; + UINTN DataSize; + IPMI_GET_BOOT_OPTIONS_REQUEST BootOptionsRequest; + IPMI_GET_BOOT_OPTIONS_RESPONSE *BootOptionsResponse; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5 *BootOptionsParameterData; + IPMI_SET_BOOT_OPTIONS_REQUEST *SetBootOptionsRequest; + IPMI_SET_BOOT_OPTIONS_RESPONSE SetBootOptionsResponse; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5 *SetBootOptionsParameterDat= a; + EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptionToManipulate; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + EFI_STATUS Status; + AMD_BOARD_BDS_BOOT_OPTION_PRIORITY_PROTOCOL *BootOptionPriorityProtocol= ; + EFI_HANDLE *BootPriorityHandles; + UINTN BootPriorityCount; + UINTN BootPriorityIndex; + BOOLEAN ValidBootPriorityOverride; + + ZeroMem (&BootOptionsRequest, sizeof (IPMI_GET_BOOT_OPTIONS_REQUEST)); + ZeroMem (&SetBootOptionsResponse, sizeof (IPMI_SET_BOOT_OPTIONS_RESPONSE= )); + + LoadOptionToManipulate =3D NULL; + Status =3D EFI_SUCCESS; + ValidBootPriorityOverride =3D FALSE; + // setup buffers + GetBootOptionsBuffer =3D (UINT8 *)AllocateZeroPool (sizeof (BootOptionsR= esponse) + sizeof (IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5)); + SetBootOptionsBuffer =3D (UINT8 *)AllocateZeroPool (sizeof (SetBootOptio= nsRequest) + sizeof (IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5)); + + // setup parameter data + BootOptionsRequest.ParameterSelector.Bits.ParameterSelector =3D IPMI_BOO= T_OPTIONS_PARAMETER_BOOT_FLAGS; + BootOptionsResponse =3D (IPMI_GE= T_BOOT_OPTIONS_RESPONSE *)&GetBootOptionsBuffer[0]; + Status =3D IpmiGetS= ystemBootOptions (&BootOptionsRequest, BootOptionsResponse); + BootOptionsParameterData =3D (IPMI_BO= OT_OPTIONS_RESPONSE_PARAMETER_5 *)BootOptionsResponse->ParameterData; + + if (EFI_ERROR (Status)) { + Status =3D EFI_UNSUPPORTED; + goto end; + } + + // setup SetBootOptions parameter data + SetBootOptionsRequest =3D (IPMI_SET_BOOT_OPTIONS_REQUEST *)&SetBoo= tOptionsBuffer[0]; + SetBootOptionsParameterData =3D (IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5 = *)SetBootOptionsRequest->ParameterData; + + BootOptions =3D EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOpti= onTypeBoot); + + // if received valid IPMI data, then override boot option + if (!BootOptionsResponse->ParameterValid.Bits.ParameterValid && BootOpti= onsParameterData->Data1.Bits.BootFlagValid) { + // get non volatile IpmiBootOverride variable + DataSize =3D sizeof (UINT8); + Status =3D gRT->GetVariable ( + IPMI_BOOT_OVERRIDE_VAR_NAME, + &gEfiCallerIdGuid, + NULL, + &DataSize, + &NvIpmiBootOverride + ); + if (EFI_ERROR (Status)) { + NvIpmiBootOverride =3D IPMI_BOOT_DEVICE_SELECTOR_NO_OVERRIDE; + } + + CurrentIpmiBootOverride =3D BootOptionsParameterData->Data2.Bits.BootD= eviceSelector; + + // Handle platform specific boot priority override + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gAmdBoardBdsBootOptionPriorityProtocolGuid, + NULL, + &BootPriorityCount, + &BootPriorityHandles + ); + + if (!EFI_ERROR (Status)) { + for (BootPriorityIndex =3D 0; BootPriorityIndex < BootPriorityCount;= BootPriorityIndex++) { + Status =3D gBS->HandleProtocol ( + BootPriorityHandles[BootPriorityIndex], + &gAmdBoardBdsBootOptionPriorityProtocolGuid, + (VOID **)&BootOptionPriorityProtocol + ); + if (!EFI_ERROR (Status) && + (BootOptionPriorityProtocol->IpmiBootDeviceSelectorType =3D=3D= CurrentIpmiBootOverride)) + { + DEBUG ((DEBUG_INFO, "Valid BootOptionPriority Override detected\= n")); + ValidBootPriorityOverride =3D TRUE; + break; + } + } + } + + if (CurrentIpmiBootOverride =3D=3D IPMI_BOOT_DEVICE_SELECTOR_BIOS_SETU= P) { + DEBUG ((DEBUG_INFO, "[Bds]BiosSetup option override detected via IPM= I\n")); + // need to find boot option corresponding to BiosSetup + for (Index =3D 0; Index < BootOptionCount; Index++) { + if ((StrCmp (BootOptions[Index].Description, L"Enter Setup") =3D= =3D 0) && (BootOptions[Index].Attributes =3D=3D (LOAD_OPTION_CATEGORY_APP |= LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN))) { + LoadOptionToManipulate =3D &BootOptions[Index]; + } else if (StrCmp (BootOptions[Index].Description, L"Enter Setup")= =3D=3D 0) { + // delete duplicate BiosSetup Menu option + EfiBootManagerDeleteLoadOptionVariable (BootOptions[Index].Optio= nNumber, LoadOptionTypeBoot); + } + } + + if (LoadOptionToManipulate =3D=3D NULL) { + Status =3D EFI_UNSUPPORTED; + goto end; + } + + // have Load option for bios setup, now update loadoptions + Status =3D EfiBootManagerDeleteLoadOpti= onVariable (LoadOptionToManipulate->OptionNumber, LoadOptionTypeBoot); + LoadOptionToManipulate->Attributes &=3D LOAD_OPTION_CATEGORY_BOOT; + LoadOptionToManipulate->Attributes |=3D (LOAD_OPTION_ACTIVE | LOAD_O= PTION_HIDDEN); + Status =3D EfiBootManagerAddLoadOptionV= ariable (LoadOptionToManipulate, 0); // add back in loadoptions in 0th inde= x (first option) + } else if (CurrentIpmiBootOverride =3D=3D IPMI_BOOT_DEVICE_SELECTOR_PX= E) { + DEBUG ((DEBUG_INFO, "[Bds]PXE option override detected via IPMI\n"))= ; + + if (ValidBootPriorityOverride) { + EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, BootOpti= onPriorityProtocol->Compare); + } else { + EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareB= ootOptionPxePriority); + } + } else if (CurrentIpmiBootOverride =3D=3D IPMI_BOOT_DEVICE_SELECTOR_HA= RDDRIVE) { + DEBUG ((DEBUG_INFO, "[Bds]HDD option override detected via IPMI\n"))= ; + if (ValidBootPriorityOverride) { + EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, BootOpti= onPriorityProtocol->Compare); + } else { + EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareB= ootOptionHddPriority); + } + } else if ((CurrentIpmiBootOverride =3D=3D IPMI_BOOT_DEVICE_SELECTOR_N= O_OVERRIDE) && (CurrentIpmiBootOverride !=3D NvIpmiBootOverride)) { + // delete BiosSetup option corresponding to the override + Status =3D EfiBootManagerDeleteLoadOptionVariable (BootOptions[0].Op= tionNumber, LoadOptionTypeBoot); + // re sort boot options + EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBoo= tOption); + } + + // if Ipmi override not persistent, reset boot option to None and pers= istent to true + if (!BootOptionsParameterData->Data1.Bits.PersistentOptions) { + SetBootOptionsRequest->ParameterValid.Bits.ParameterSelector =3D IPM= I_BOOT_OPTIONS_PARAMETER_BOOT_FLAGS; + CopyMem (SetBootOptionsParameterData, BootOptionsParameterData, size= of (IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5)); + SetBootOptionsParameterData->Data1.Bits.PersistentOptions =3D 1; = // persistent + SetBootOptionsParameterData->Data2.Bits.BootDeviceSelector =3D IPMI_= BOOT_DEVICE_SELECTOR_NO_OVERRIDE; // revert to no override + Status =3D IpmiS= etSystemBootOptions (SetBootOptionsRequest, &SetBootOptionsResponse); + } + + Status =3D gRT->SetVariable ( + IPMI_BOOT_OVERRIDE_VAR_NAME, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_A= CCESS, + sizeof (UINT8), + &CurrentIpmiBootOverride + ); + } + +end: + // Free buffers + FreePool (GetBootOptionsBuffer); + FreePool (SetBootOptionsBuffer); + return Status; +} + +/** + After console ready before boot option event callback. + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Even= t. +**/ +VOID +EFIAPI +BdsAfterConsoleReadyBeforeBootOptionCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_BOOT_MODE LocalBootMode; + EFI_STATUS Status; + BOOLEAN IsFirstBoot; + UINTN DataSize; + + DEBUG ((DEBUG_INFO, "Event gBdsAfterConsoleReadyBeforeBootOptionEvent ca= llback starts\n")); + // + // Get current Boot Mode + // + LocalBootMode =3D gBootMode; + DEBUG ((DEBUG_INFO, "Current local bootmode - %x\n", LocalBootMode)); + + // + // Go the different platform policy with different boot mode + // Notes: this part code can be change with the table policy + // + switch (LocalBootMode) { + case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES: + case BOOT_WITH_MINIMAL_CONFIGURATION: + case BOOT_ON_S4_RESUME: + // + // Perform some platform specific connect sequence + // + PERF_START_EX (NULL, "EventRec", NULL, AsmReadTsc (), 0x7050); + ConnectSequence (LocalBootMode); + PERF_END_EX (NULL, "EventRec", NULL, AsmReadTsc (), 0x7051); + + break; + + case BOOT_WITH_FULL_CONFIGURATION: + case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS: + case BOOT_WITH_DEFAULT_SETTINGS: + default: + // + // Perform some platform specific connect sequence + // + ConnectSequence (LocalBootMode); + + // + // Only in Full Configuration boot mode we do the enumeration of boo= t device + // + // + // Dispatch all but Storage Oprom explicitly, because we assume Int1= 3Thunk driver is there. + // + + // + // PXE boot option may appear after boot option enumeration + // + + EfiBootManagerRefreshAllBootOption (); + DataSize =3D sizeof (BOOLEAN); + Status =3D gRT->GetVariable ( + IS_FIRST_BOOT_VAR_NAME, + &gEfiCallerIdGuid, + NULL, + &DataSize, + &IsFirstBoot + ); + if (EFI_ERROR (Status)) { + // + // If can't find the variable, see it as the first boot + // + IsFirstBoot =3D TRUE; + } + + if (IsFirstBoot) { + // + // In the first boot, sort the boot option + // + EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareB= ootOption); + IsFirstBoot =3D FALSE; + Status =3D gRT->SetVariable ( + IS_FIRST_BOOT_VAR_NAME, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOT= SERVICE_ACCESS, + sizeof (BOOLEAN), + &IsFirstBoot + ); + } + + break; + } + + HandleIpmiBootOverride (); + + Print (L"Press F2 for Setup, or F7 for BootMenu!\n"); + + #ifdef INTERNAL_IDS + PrintSocOpnInfo (); + #endif +} + +#ifdef INTERNAL_IDS + +/** + Display CPU OPN on Splash screen After console ready. + @retval EFI_SUCCESS +**/ +EFI_STATUS +PrintSocOpnInfo ( + IN VOID + ) +{ + CHAR16 OpnChar[(sizeof (UINT64) / sizeof (UINT8)) * (MSR_CPUID_NAME_STR= ING5 - MSR_CPUID_NAME_STRING0 + 1) + 1]; + UINT32 Msr; + UINT64 Value; + UINTN CharIndex; + UINTN ByteIndex; + + CharIndex =3D 0; + for (Msr =3D MSR_CPUID_NAME_STRING0; Msr <=3D MSR_CPUID_NAME_STRING5; Ms= r++) { + Value =3D AsmReadMsr64 (Msr); + for (ByteIndex =3D 0; ByteIndex < (sizeof (UINT64) / sizeof (UINT8)); = ByteIndex++) { + OpnChar[CharIndex] =3D (Value & 0xFF); + CharIndex++; + Value =3D RShiftU64 (Value, 8); + } + } + + OpnChar[CharIndex] =3D L'\0'; + + DEBUG ((DEBUG_INFO, "\nProcessor OPN: ")); + DEBUG ((DEBUG_INFO, "%s\n", OpnChar)); + + Print (L"Processor OPN: "); + Print (OpnChar); + Print (L"\n\r"); + + return EFI_SUCCESS; +} + +#endif diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHo= okLib.inf b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHoo= kLib.inf new file mode 100644 index 0000000000..23e834e332 --- /dev/null +++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.i= nf @@ -0,0 +1,105 @@ +### @file +# Module Information file for the Bds Hook Library. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# Copyright (C) 2023- 2024 Advanced Micro Devices, Inc. All rights reserve= d.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + +[Defines] + INF_VERSION =3D 0x00010017 + BASE_NAME =3D BoardBdsHookLib + FILE_GUID =3D A500CFFB-26DA-4CB1-B214-EC16524C9733 + VERSION_STRING =3D 1.0 + MODULE_TYPE =3D DXE_DRIVER + LIBRARY_CLASS =3D BoardBdsHookLib|DXE_DRIVER + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + DxeServicesLib + DxeServicesTableLib + HiiLib + HobLib + IpmiCommandLib + IpmiLib + MemoryAllocationLib + PcdLib + PerformanceLib + PrintLib + SortLib + Tcg2PhysicalPresenceLib + TimerLib + UefiBootManagerLib + UefiBootServicesTableLib + UefiLib + UefiRuntimeServicesTableLib + +[Packages] + AmdMinBoardPkg/AmdMinBoardPkg.dec + BoardModulePkg/BoardModulePkg.dec + IpmiFeaturePkg/IpmiFeaturePkg.dec + ManageabilityPkg/ManageabilityPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + MinPlatformPkg/MinPlatformPkg.dec + SecurityPkg/SecurityPkg.dec + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand ## PRO= DUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn ## PRO= DUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow ## PRO= DUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution ## PRO= DUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution ## PRO= DUCES + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut ## PRO= DUCES + gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly ## CON= SUMES + gMinPlatformPkgTokenSpaceGuid.PcdPlatformMemoryCheckLevel ## CON= SUMES + gMinPlatformPkgTokenSpaceGuid.PcdShellFile ## CON= SUMES + gMinPlatformPkgTokenSpaceGuid.PcdShellFileDesc ## CON= SUMES + gMinPlatformPkgTokenSpaceGuid.PcdTpm2Enable ## CON= SUMES + gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleInputDevicePath ## CON= SUMES + gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleOutputDevicePath ## CON= SUMES + gMinPlatformPkgTokenSpaceGuid.PcdTrustedStorageDevicePath ## CON= SUMES + +[Sources] + BoardBdsHook.h + BoardBdsHookLib.c + BoardBootOption.c + BoardMemoryTest.c + +[Protocols] + gAmdBoardBdsBootOptionPriorityProtocolGuid ## CONSUMES + gEfiCpuIo2ProtocolGuid ## CONSUMES + gEfiDevicePathToTextProtocolGuid ## CONSUMES + gEfiDiskInfoProtocolGuid ## CONSUMES + gEfiDxeSmmReadyToLockProtocolGuid + gEfiDxeSmmReadyToLockProtocolGuid ## PRODUCES + gEfiFirmwareVolume2ProtocolGuid ## CONSUMES + gEfiFormBrowser2ProtocolGuid ## CONSUMES + gEfiGenericMemTestProtocolGuid ## CONSUMES + gEfiGenericMemTestProtocolGuid ## CONSUMES + gEfiPciIoProtocolGuid ## CONSUMES + gEfiPciRootBridgeIoProtocolGuid ## CONSUMES + gEfiSimpleTextInputExProtocolGuid ## CONSUMES + +[Guids] + gBdsEventAfterConsoleReadyBeforeBootOptionGuid + gBdsEventBeforeConsoleAfterTrustedConsoleGuid + gBdsEventBeforeConsoleBeforeEndOfDxeGuid + gEfiEndOfDxeEventGroupGuid ## CONSUMES + gEfiGlobalVariableGuid ## PRODUCES + gEfiMemoryOverwriteControlDataGuid ## PRODUCES + +[Depex.common.DXE_DRIVER] + gEfiVariableArchProtocolGuid + +[Depex] + TRUE diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBootO= ption.c b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBootOpti= on.c new file mode 100644 index 0000000000..16a47c2f82 --- /dev/null +++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardBootOption.c @@ -0,0 +1,754 @@ +/** @file + Driver for Platform Boot Options support. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserv= ed.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BoardBdsHook.h" + +EFI_GUID gUefiShellFileGuid =3D { 0 }; +EFI_GUID mUiFile =3D { + 0x462CAA21, 0x7614, 0x4503, { 0x83, 0x6E, 0x8A, 0xB6, 0xF4, 0x66, 0x23, = 0x31 } +}; +EFI_GUID mBootMenuFile =3D { + 0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, = 0x1D } +}; + +BOOLEAN mContinueBoot =3D FALSE; +BOOLEAN mBootMenuBoot =3D FALSE; +BOOLEAN mPxeBoot =3D FALSE; +BOOLEAN mHotKeypressed =3D FALSE; +EFI_EVENT HotKeyEvent =3D NULL; + +UINTN mBootMenuOptionNumber; +UINTN mSetupOptionNumber; + +/** + This function will create a SHELL BootOption to boot. + + @return Shell Device path for booting. +**/ +EFI_DEVICE_PATH_PROTOCOL * +BdsCreateShellDevicePath ( + VOID + ) +{ + UINTN FvHandleCount; + EFI_HANDLE *FvHandleBuffer; + UINTN Index; + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINTN Size; + UINT32 AuthenticationStatus; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + VOID *Buffer; + + DevicePath =3D NULL; + Status =3D EFI_SUCCESS; + + DEBUG ((DEBUG_INFO, "BdsCreateShellDevicePath\n")); + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvHandleCount, + &FvHandleBuffer + ); + + for (Index =3D 0; Index < FvHandleCount; Index++) { + gBS->HandleProtocol ( + FvHandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **)&Fv + ); + + Buffer =3D NULL; + Size =3D 0; + Status =3D Fv->ReadSection ( + Fv, + &gUefiShellFileGuid, + EFI_SECTION_PE32, + 0, + &Buffer, + &Size, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Skip if no shell file in the FV + // + continue; + } else { + // + // Found the shell + // + break; + } + } + + if (EFI_ERROR (Status)) { + // + // No shell present + // + if (FvHandleCount) { + FreePool (FvHandleBuffer); + } + + return NULL; + } + + // + // Build the shell boot option + // + DevicePath =3D DevicePathFromHandle (FvHandleBuffer[Index]); + + if (FvHandleCount) { + FreePool (FvHandleBuffer); + } + + return DevicePath; +} + +/** + Create Boot option for passed Firmware Volume. + + @param[in] FileGuid FV file name to use in FvDevicePathNode + @param[in] Description Description of the load option. + @param[in, out] BootOption Pointer to the load option to be initialized= . + @param[in] Attributes Attributes of the load option. + @param[in] OptionalData Optional data of the load option. + @param[in] OptionalDataSize Size of the optional data of the load option= . + + @retval EFI_SUCCESS The load option was initialized successful= ly. + @retval EFI_INVALID_PARAMETER BootOption, Description or FileGuid is NUL= L. +**/ +EFI_STATUS +CreateFvBootOption ( + IN EFI_GUID *FileGuid, + IN CHAR16 *Description, + IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, + IN UINT32 Attributes, + IN UINT8 *OptionalData, OPTIONAL IN UINT32 OptionalDataSize + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINT32 AuthenticationStatus; + VOID *Buffer; + UINTN Size; + + if ((BootOption =3D=3D NULL) || (FileGuid =3D=3D NULL) || (Description = =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + + if (!CompareGuid (&gUefiShellFileGuid, FileGuid)) { + Status =3D gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + if (!EFI_ERROR (Status)) { + Status =3D gBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **)&Fv + ); + if (!EFI_ERROR (Status)) { + Buffer =3D NULL; + Size =3D 0; + Status =3D Fv->ReadSection ( + Fv, + FileGuid, + EFI_SECTION_PE32, + 0, + &Buffer, + &Size, + &AuthenticationStatus + ); + if (Buffer !=3D NULL) { + FreePool (Buffer); + } + } + } + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + DevicePath =3D AppendDevicePathNode ( + DevicePathFromHandle (LoadedImage->DeviceHandle), + (EFI_DEVICE_PATH_PROTOCOL *)&FileNode + ); + } else { + DevicePath =3D AppendDevicePathNode ( + BdsCreateShellDevicePath (), + (EFI_DEVICE_PATH_PROTOCOL *)&FileNode + ); + } + + Status =3D EfiBootManagerInitializeLoadOption ( + BootOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + OptionalData, + OptionalDataSize + ); + FreePool (DevicePath); + return Status; +} + +/** + 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[in] Key Pointer to the load option to be found. + @param[in] Array Pointer to the array of load options to be found. + @param[in] 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; +} + +/** + Registers a boot option. + + @param[in] FileGuid Boot file GUID + @param[in] Description Boot option description + @param[in] Position Position of the new load option to put= in the ****Order variable. + @param[in] Attributes Boot option attributes + @param[in] OptionalData Optional data of the boot option. + @param[in] OptionalDataSize Size of the optional data of the boot = option + + @return boot option number +**/ +UINTN +RegisterFvBootOption ( + IN EFI_GUID *FileGuid, + IN CHAR16 *Description, + IN UINTN Position, + IN UINT32 Attributes, + IN UINT8 *OptionalData, OPTIONAL IN UINT32 OptionalDataSize + ) +{ + EFI_STATUS Status; + UINTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + + NewOption.OptionNumber =3D LoadOptionNumberUnassigned; + Status =3D CreateFvBootOption (FileGuid, Description, &N= ewOption, Attributes, OptionalData, OptionalDataSize); + 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, Position= ); + ASSERT_EFI_ERROR (Status); + } else { + NewOption.OptionNumber =3D BootOptions[OptionIndex].OptionNumber; + } + + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + } + + return NewOption.OptionNumber; +} + +/** + Boot manager wait callback. + + @param[in] TimeoutRemain The remaining timeout period +**/ +VOID +EFIAPI +PlatformBootManagerWaitCallback ( + IN UINT16 TimeoutRemain + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx; + EFI_KEY_DATA KeyData; + BOOLEAN PausePressed; + + // + // Pause on PAUSE key + // + Status =3D gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInp= utExProtocolGuid, (VOID **)&TxtInEx); + ASSERT_EFI_ERROR (Status); + + PausePressed =3D FALSE; + + while (TRUE) { + Status =3D TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData); + if (EFI_ERROR (Status)) { + break; + } + + if (KeyData.Key.ScanCode =3D=3D SCAN_PAUSE) { + PausePressed =3D TRUE; + break; + } + } + + // + // Loop until non-PAUSE key pressed + // + while (PausePressed) { + Status =3D TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData); + if (!EFI_ERROR (Status)) { + DEBUG (( + DEBUG_INFO, + "[PauseCallback] %x/%x %x/%x\n", + KeyData.Key.ScanCode, + KeyData.Key.UnicodeChar, + KeyData.KeyState.KeyShiftState, + KeyData.KeyState.KeyToggleState + )); + PausePressed =3D (BOOLEAN)(KeyData.Key.ScanCode =3D=3D SCAN_PAUSE); + } + } +} + +/** + Registers default boot option. +**/ +VOID +RegisterDefaultBootOption ( + VOID + ) +{ + UINT16 *ShellData; + UINT32 ShellDataSize; + + ShellData =3D NULL; + ShellDataSize =3D 0; + CopyMem (&gUefiShellFileGuid, PcdGetPtr (PcdShellFile), sizeof (GUID)); + RegisterFvBootOption (&gUefiShellFileGuid, (CHAR16 *)PcdGetPtr (PcdShell= FileDesc), (UINTN)-1, LOAD_OPTION_ACTIVE, (UINT8 *)ShellData, ShellDataSize= ); + + // + // Boot Menu + // + mBootMenuOptionNumber =3D RegisterFvBootOption (&mBootMenuFile, L"Boot D= evice List", (UINTN)-1, LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOA= D_OPTION_HIDDEN, NULL, 0); + + if (mBootMenuOptionNumber =3D=3D LoadOptionNumberUnassigned) { + DEBUG ((DEBUG_INFO, "BootMenuOptionNumber (%d) should not be same to L= oadOptionNumberUnassigned(%d).\n", mBootMenuOptionNumber, LoadOptionNumberU= nassigned)); + } + + // + // Boot Manager Menu + // + mSetupOptionNumber =3D RegisterFvBootOption (&mUiFile, L"Enter Setup", (= UINTN)-1, LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDE= N, NULL, 0); +} + +/** + Registers/Unregisters boot option hotkey. + + @param[in] OptionNumber The boot option number for the key option. + @param[in] Key The key input + @param[in] Add Flag to indicate to add or remove a key +**/ +VOID +RegisterBootOptionHotkey ( + IN UINT16 OptionNumber, + IN EFI_INPUT_KEY *Key, + IN BOOLEAN Add + ) +{ + EFI_STATUS Status; + + if (!Add) { + // + // No enter hotkey when force to setup or there is no boot option + // + Status =3D EfiBootManagerDeleteKeyOptionVariable (NULL, 0, Key, NULL); + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_NOT_FOUND); + } else { + // + // Register enter hotkey for the first boot option + // + Status =3D EfiBootManagerAddKeyOptionVariable (NULL, OptionNumber, 0, = Key, NULL); + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_ALREADY_STARTED= ); + } +} + +/** + Detect key press callback. + + @param[in] KeyData The key data + + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +DetectKeypressCallback ( + IN EFI_KEY_DATA *KeyData + ) +{ + mHotKeypressed =3D TRUE; + + if (HotKeyEvent !=3D NULL) { + gBS->SignalEvent (HotKeyEvent); + } + + return EFI_SUCCESS; +} + +/** + This function is called after all the boot options are enumerated and or= dered properly. +**/ +VOID +RegisterStaticHotkey ( + VOID + ) +{ + EFI_INPUT_KEY Enter; + EFI_KEY_DATA F2; + EFI_KEY_DATA F7; + BOOLEAN EnterSetup; + + EnterSetup =3D FALSE; + + // + // [Enter] + // + mContinueBoot =3D !EnterSetup; + if (mContinueBoot) { + Enter.ScanCode =3D SCAN_NULL; + Enter.UnicodeChar =3D CHAR_CARRIAGE_RETURN; + EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + } + + // + // [F2] + // + if (mSetupOptionNumber !=3D LoadOptionNumberUnassigned) { + F2.Key.ScanCode =3D SCAN_F2; + F2.Key.UnicodeChar =3D CHAR_NULL; + F2.KeyState.KeyShiftState =3D EFI_SHIFT_STATE_VALID; + F2.KeyState.KeyToggleState =3D 0; + RegisterBootOptionHotkey ((UINT16)mSetupOptionNumber, &F2.Key, TRUE); + } + + // + // Register [F7] only when the mBootMenuOptionNumber is valid + // + if (mBootMenuOptionNumber !=3D LoadOptionNumberUnassigned) { + F7.Key.ScanCode =3D SCAN_F7; + F7.Key.UnicodeChar =3D CHAR_NULL; + F7.KeyState.KeyShiftState =3D EFI_SHIFT_STATE_VALID; + F7.KeyState.KeyToggleState =3D 0; + mBootMenuBoot =3D !EnterSetup; + RegisterBootOptionHotkey ((UINT16)mBootMenuOptionNumber, &F7.Key, mBoo= tMenuBoot); + } +} + +/** + Returns the boot option type of a device. + + @param[in] DevicePath The DevicePath whose boot option type is + to be returned + @retval -1 Device type not found + @retval > -1 Device type found +**/ +UINT8 +BootOptionType ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *NextNode; + + for (Node =3D DevicePath; !IsDevicePathEndType (Node); Node =3D NextDevi= cePathNode (Node)) { + if (DevicePathType (Node) =3D=3D MESSAGING_DEVICE_PATH) { + // + // Make sure the device path points to the driver device. + // + NextNode =3D NextDevicePathNode (Node); + if (DevicePathSubType (NextNode) =3D=3D MSG_DEVICE_LOGICAL_UNIT_DP) = { + // + // if the next node type is Device Logical Unit, which specify the= Logical Unit Number (LUN), + // skip it + // + NextNode =3D NextDevicePathNode (NextNode); + } + + if (IsDevicePathEndType (NextNode)) { + if ((DevicePathType (Node) =3D=3D MESSAGING_DEVICE_PATH)) { + return DevicePathSubType (Node); + } else { + return MSG_SATA_DP; + } + } + } + } + + return (UINT8)-1; +} + +/** + Returns the priority number. + + @param[in] BootOption Load option to get the priority value for + @retval + OptionType EFI + ------------------------------------ + PXE 2 + DVD 4 + USB 6 + NVME 7 + HDD 8 + EFI Shell 9 + Others 100 + +**/ +UINTN +BootOptionPriority ( + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption + ) +{ + // + // EFI boot options + // + switch (BootOptionType (BootOption->FilePath)) { + case MSG_MAC_ADDR_DP: + case MSG_VLAN_DP: + case MSG_IPv4_DP: + case MSG_IPv6_DP: + return 2; + + case MSG_SATA_DP: + case MSG_ATAPI_DP: + case MSG_UFS_DP: + case MSG_NVME_NAMESPACE_DP: + return 4; + + case MSG_USB_DP: + return 6; + } + + if (StrCmp (BootOption->Description, (CHAR16 *)PcdGetPtr (PcdShellFileDe= sc)) =3D=3D 0) { + if (PcdGetBool (PcdBootToShellOnly)) { + return 0; + } + + return 9; + } + + if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) =3D=3D 0) { + return 8; + } + + return 100; +} + +/** + Returns the priority number while giving PXE highest + priority. + + @param[in] BootOption Load option to get the priority value for + @retval + OptionType EFI + ------------------------------------ + PXE 2 + DVD 4 + USB 6 + NVME 7 + HDD 8 + EFI Shell 9 + Others 100 +**/ +UINTN +PxeBootOptionPriority ( + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption + ) +{ + // + // EFI boot options + // + switch (BootOptionType (BootOption->FilePath)) { + case MSG_MAC_ADDR_DP: + case MSG_VLAN_DP: + case MSG_IPv4_DP: + case MSG_IPv6_DP: + return 2; + + case MSG_SATA_DP: + case MSG_ATAPI_DP: + case MSG_UFS_DP: + case MSG_NVME_NAMESPACE_DP: + return 4; + + case MSG_USB_DP: + return 6; + } + + if (StrCmp (BootOption->Description, (CHAR16 *)PcdGetPtr (PcdShellFileDe= sc)) =3D=3D 0) { + if (PcdGetBool (PcdBootToShellOnly)) { + return 0; + } + + return 9; + } + + if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) =3D=3D 0) { + return 8; + } + + return 100; +} + +/** + Returns the priority number while giving HDD, DVD, and NVME highest prio= rity. + + @param[in] BootOption Load option to get the priority value for + @retval + OptionType EFI + ------------------------------------ + NVME, DVD, HDD 2 + PXE 4 + USB 6 + HDD 8 + EFI Shell 9 + Others 100 +**/ +UINTN +HddBootOptionPriority ( + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption + ) +{ + // + // EFI boot options + // + switch (BootOptionType (BootOption->FilePath)) { + case MSG_SATA_DP: + case MSG_UFS_DP: + case MSG_NVME_NAMESPACE_DP: + return 2; + + case MSG_ATAPI_DP: + return 3; + + case MSG_MAC_ADDR_DP: + case MSG_VLAN_DP: + case MSG_IPv4_DP: + case MSG_IPv6_DP: + return 4; + + case MSG_USB_DP: + return 6; + } + + if (StrCmp (BootOption->Description, (CHAR16 *)PcdGetPtr (PcdShellFileDe= sc)) =3D=3D 0) { + if (PcdGetBool (PcdBootToShellOnly)) { + return 0; + } + + return 9; + } + + if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) =3D=3D 0) { + return 2; + } + + return 100; +} + +/** + Compares boot priorities of two boot options. + + @param[in] Left The left boot option + @param[in] Right The right boot option + + @retval The difference between the Left and Right + boot options + **/ +INTN +EFIAPI +CompareBootOption ( + IN CONST VOID *Left, + IN CONST VOID *Right + ) +{ + return BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Left) - + BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Right); +} + +/** + Compares boot priorities of two boot options, while giving PXE the high= est priority. + + @param[in] Left The left boot option + @param[in] Right The right boot option + + @retval The difference between the Left and Right + boot options + **/ +INTN +EFIAPI +CompareBootOptionPxePriority ( + IN CONST VOID *Left, + IN CONST VOID *Right + ) +{ + return PxeBootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Left) - + PxeBootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Right); +} + +/** + Compares boot priorities of two boot options, while giving HDD the high= est priority. + + @param[in] Left The left boot option + @param[in] Right The right boot option + + @retval The difference between the Left and Right + boot options + **/ +INTN +EFIAPI +CompareBootOptionHddPriority ( + IN CONST VOID *Left, + IN CONST VOID *Right + ) +{ + return HddBootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Left) - + HddBootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *)Right); +} diff --git a/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardMemor= yTest.c b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardMemoryTe= st.c new file mode 100644 index 0000000000..fff0ef2993 --- /dev/null +++ b/Platform/AMD/AmdMinBoardPkg/Library/BoardBdsHookLib/BoardMemoryTest.c @@ -0,0 +1,83 @@ +/** @file + Perform the platform memory test + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "BoardBdsHook.h" +#include + +/** + Perform the memory test base on the memory test intensive level, + and update the memory resource. + + @param[in] Level The memory test intensive level. + + @retval EFI_STATUS Success test all the system memory and update + the memory resource + +**/ +EFI_STATUS +MemoryTest ( + IN EXTENDMEM_COVERAGE_LEVEL Level + ) +{ + EFI_STATUS Status; + BOOLEAN RequireSoftECCInit; + EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; + UINT64 TestedMemorySize; + UINT64 TotalMemorySize; + BOOLEAN ErrorOut; + BOOLEAN TestAbort; + + TestedMemorySize =3D 0; + TotalMemorySize =3D 0; + ErrorOut =3D FALSE; + TestAbort =3D FALSE; + + RequireSoftECCInit =3D FALSE; + + Status =3D gBS->LocateProtocol ( + &gEfiGenericMemTestProtocolGuid, + NULL, + (VOID **)&GenMemoryTest + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + Status =3D GenMemoryTest->MemoryTestInit ( + GenMemoryTest, + Level, + &RequireSoftECCInit + ); + if (Status =3D=3D EFI_NO_MEDIA) { + // + // The PEI codes also have the relevant memory test code to check the = memory, + // it can select to test some range of the memory or all of them. If P= EI code + // checks all the memory, this BDS memory test will has no not-test me= mory to + // do the test, and then the status of EFI_NO_MEDIA will be returned b= y + // "MemoryTestInit". So it does not need to test memory again, just re= turn. + // + return EFI_SUCCESS; + } + + do { + Status =3D GenMemoryTest->PerformMemoryTest ( + GenMemoryTest, + &TestedMemorySize, + &TotalMemorySize, + &ErrorOut, + TestAbort + ); + if (ErrorOut && (Status =3D=3D EFI_DEVICE_ERROR)) { + ASSERT (0); + } + } while (Status !=3D EFI_NOT_FOUND); + + Status =3D GenMemoryTest->Finished (GenMemoryTest); + + return EFI_SUCCESS; +} --=20 2.34.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 (#118979): https://edk2.groups.io/g/devel/message/118979 Mute This Topic: https://groups.io/mt/106148095/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-