diff options
author | Mario Bălănică <mariobalanica02@gmail.com> | 2024-06-30 15:59:32 +0300 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-07-16 12:54:07 +0300 |
commit | f9c373c8388f819166e57365197bc423d56209a6 (patch) | |
tree | 101d1d4f25f78d73b162b851f8508d94bb9789ef | |
parent | 1bb9f47739ae7993191a36bea76c5a2157fdd10f (diff) | |
download | edk2-f9c373c8388f819166e57365197bc423d56209a6.tar.xz |
EmbeddedPkg: Add option to disable EFI Memory Attribute Protocol
Introduce a driver that allows users to disable the EFI Memory Attribute
protocol through an HII setup option, in order to work around a broken
version of rhboot's shim used in some distros (e.g. CentOS Stream 9)
which incorrectly invokes the protocol and results in a Synchronous
Exception.
Default is enabled, which can also be overridden at build time by
changing `gEmbeddedTokenSpaceGuid.PcdMemoryAttributeEnabledDefault`.
It is only applicable to ARM64 and there isn't any other technical
reason for disabling this security feature.
See:
- https://github.com/microsoft/mu_silicon_arm_tiano/issues/124
- https://edk2.groups.io/g/devel/topic/99631663
- https://github.com/tianocore/edk2/pull/5840
Signed-off-by: Mario Bălănică <mariobalanica02@gmail.com>
8 files changed, 360 insertions, 0 deletions
diff --git a/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.c b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.c new file mode 100644 index 0000000000..7a0156ddbf --- /dev/null +++ b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.c @@ -0,0 +1,197 @@ +/** @file
+
+ Copyright (c) 2023-2024, Mario Bălănică <mariobalanica02@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include "MemoryAttributeManagerDxe.h"
+
+extern UINT8 MemoryAttributeManagerDxeHiiBin[];
+extern UINT8 MemoryAttributeManagerDxeStrings[];
+
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+STATIC HII_VENDOR_DEVICE_PATH mVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ MEMORY_ATTRIBUTE_MANAGER_FORMSET_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8)(END_DEVICE_PATH_LENGTH),
+ (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+/**
+ Installs HII page for user configuration.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+InstallHiiPages (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+
+ DriverHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mVendorDevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ HiiHandle = HiiAddPackages (
+ &gMemoryAttributeManagerFormSetGuid,
+ DriverHandle,
+ MemoryAttributeManagerDxeStrings,
+ MemoryAttributeManagerDxeHiiBin,
+ NULL
+ );
+
+ if (HiiHandle == NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mVendorDevicePath,
+ NULL
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function uninstalls the EFI_MEMORY_ATTRIBUTE_PROTOCOL
+ from CpuDxe's handle.
+**/
+STATIC
+VOID
+UninstallEfiMemoryAttributeProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ UINTN Size;
+ VOID *MemoryAttributeProtocol;
+
+ Size = sizeof (Handle);
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiMemoryAttributeProtocolGuid,
+ NULL,
+ &Size,
+ &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (Status == EFI_NOT_FOUND);
+ return;
+ }
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiMemoryAttributeProtocolGuid,
+ &MemoryAttributeProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = gBS->UninstallProtocolInterface (
+ Handle,
+ &gEfiMemoryAttributeProtocolGuid,
+ MemoryAttributeProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "EFI Memory Attribute Protocol disabled due to user/platform preference!\n"
+ ));
+}
+
+/**
+ The entry point for MemoryAttributeManagerDxe driver.
+
+ @param[in] ImageHandle The image handle of the driver.
+ @param[in] SystemTable The system table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+MemoryAttributeManagerInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ MEMORY_ATTRIBUTE_MANAGER_VARSTORE_DATA Config;
+
+ Config.Enabled = PROTOCOL_ENABLED_DEFAULT;
+
+ Size = sizeof (MEMORY_ATTRIBUTE_MANAGER_VARSTORE_DATA);
+ Status = gRT->GetVariable (
+ MEMORY_ATTRIBUTE_MANAGER_DATA_VAR_NAME,
+ &gMemoryAttributeManagerFormSetGuid,
+ NULL,
+ &Size,
+ &Config
+ );
+ if (EFI_ERROR (Status)) {
+ Status = gRT->SetVariable (
+ MEMORY_ATTRIBUTE_MANAGER_DATA_VAR_NAME,
+ &gMemoryAttributeManagerFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ Size,
+ &Config
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (!Config.Enabled) {
+ UninstallEfiMemoryAttributeProtocol ();
+ }
+
+ return InstallHiiPages ();
+}
diff --git a/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.h b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.h new file mode 100644 index 0000000000..a027f3e4b6 --- /dev/null +++ b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.h @@ -0,0 +1,22 @@ +/** @file
+
+ Copyright (c) 2023-2024, Mario Bălănică <mariobalanica02@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MEMORY_ATTRIBUTE_MANAGER_DXE_H_
+#define MEMORY_ATTRIBUTE_MANAGER_DXE_H_
+
+#include <Guid/MemoryAttributeManagerFormSet.h>
+
+#define PROTOCOL_ENABLED_DEFAULT FixedPcdGetBool(PcdMemoryAttributeEnabledDefault)
+
+#define MEMORY_ATTRIBUTE_MANAGER_DATA_VAR_NAME L"MemoryAttributeManagerData"
+
+typedef struct {
+ BOOLEAN Enabled;
+} MEMORY_ATTRIBUTE_MANAGER_VARSTORE_DATA;
+
+#endif // __MEMORY_ATTRIBUTE_MANAGER_DXE_H__
diff --git a/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.inf b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.inf new file mode 100644 index 0000000000..b55639cd71 --- /dev/null +++ b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.inf @@ -0,0 +1,62 @@ +## @file
+# EFI Memory Attribute Protocol state manager
+#
+# This driver allows users to disable the EFI Memory Attribute protocol
+# through an HII setup option, in order to work around a broken version
+# of rhboot's shim used in some distros (e.g. CentOS Stream 9) which
+# incorrectly invokes the protocol and results in a Synchronous Exception.
+#
+# It is only applicable to ARM64 and there isn't any other technical
+# reason for disabling this security feature.
+#
+# See:
+# - https://github.com/microsoft/mu_silicon_arm_tiano/issues/124
+# - https://edk2.groups.io/g/devel/topic/99631663
+# - https://github.com/tianocore/edk2/pull/5840
+#
+# Copyright (c) 2023-2024, Mario Bălănică <mariobalanica02@gmail.com>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = MemoryAttributeManagerDxe
+ FILE_GUID = 5319346b-66ad-433a-9a91-f7fc286bc9a1
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MemoryAttributeManagerInitialize
+
+[Sources]
+ MemoryAttributeManagerDxe.c
+ MemoryAttributeManagerDxe.h
+ MemoryAttributeManagerDxeHii.uni
+ MemoryAttributeManagerDxeHii.vfr
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ DevicePathLib
+ HiiLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiDriverEntryPoint
+
+[Guids]
+ gMemoryAttributeManagerFormSetGuid
+
+[Protocols]
+ gEfiMemoryAttributeProtocolGuid
+
+[Pcd]
+ gEmbeddedTokenSpaceGuid.PcdMemoryAttributeEnabledDefault
+
+[Depex]
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiMemoryAttributeProtocolGuid
diff --git a/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxeHii.uni b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxeHii.uni new file mode 100644 index 0000000000..8537824b1f --- /dev/null +++ b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxeHii.uni @@ -0,0 +1,17 @@ +/** @file
+
+ Copyright (c) 2023-2024, Mario Bălănică <mariobalanica02@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#langdef en-US "English"
+
+#string STR_NULL_STRING #language en-US ""
+
+#string STR_FORM_SET_TITLE #language en-US "EFI Memory Attribute Protocol"
+#string STR_FORM_SET_TITLE_HELP #language en-US "Configure the state of the EFI Memory Attribute Protocol.\n\n"
+ "Some old OS loader versions (e.g. as found in CentOS Stream 9) do not properly support the protocol and may cause a Synchronous Exception. This security feature can be disabled to work around the issue; otherwise it should be kept enabled."
+
+#string STR_ENABLE_PROTOCOL_PROMPT #language en-US "Enable Protocol"
diff --git a/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxeHii.vfr b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxeHii.vfr new file mode 100644 index 0000000000..a303426e3c --- /dev/null +++ b/EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxeHii.vfr @@ -0,0 +1,35 @@ +/** @file
+
+ Copyright (c) 2023-2024, Mario Bălănică <mariobalanica02@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiMultiPhase.h>
+#include <Guid/HiiPlatformSetupFormset.h>
+
+#include "MemoryAttributeManagerDxe.h"
+
+formset
+ guid = MEMORY_ATTRIBUTE_MANAGER_FORMSET_GUID,
+ title = STRING_TOKEN(STR_FORM_SET_TITLE),
+ help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP),
+ classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
+
+ efivarstore MEMORY_ATTRIBUTE_MANAGER_VARSTORE_DATA,
+ attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ name = MemoryAttributeManagerData,
+ guid = MEMORY_ATTRIBUTE_MANAGER_FORMSET_GUID;
+
+ form formid = 1,
+ title = STRING_TOKEN(STR_FORM_SET_TITLE);
+
+ checkbox varid = MemoryAttributeManagerData.Enabled,
+ prompt = STRING_TOKEN(STR_ENABLE_PROTOCOL_PROMPT),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ flags = CHECKBOX_DEFAULT | CHECKBOX_DEFAULT_MFG | RESET_REQUIRED,
+ default = PROTOCOL_ENABLED_DEFAULT,
+ endcheckbox;
+ endform;
+endformset;
diff --git a/EmbeddedPkg/EmbeddedPkg.dec b/EmbeddedPkg/EmbeddedPkg.dec index 5dfbbc2933..3497fa1df7 100644 --- a/EmbeddedPkg/EmbeddedPkg.dec +++ b/EmbeddedPkg/EmbeddedPkg.dec @@ -73,6 +73,9 @@ ## Include/Guid/NvVarStoreFormatted.h
gEdkiiNvVarStoreFormattedGuid = { 0xd1a86e3f, 0x0707, 0x4c35, { 0x83, 0xcd, 0xdc, 0x2c, 0x29, 0xc8, 0x91, 0xa3 } }
+ # Include/Guid/MemoryAttributeManagerFormSet.h
+ gMemoryAttributeManagerFormSetGuid = { 0xefab3427, 0x4793, 0x4e9e, { 0xaa, 0x29, 0x88, 0x0c, 0x9a, 0x77, 0x5b, 0x5f } }
+
[Protocols.common]
gHardwareInterruptProtocolGuid = { 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } }
gHardwareInterrupt2ProtocolGuid = { 0x32898322, 0x2da1, 0x474a, { 0xba, 0xaa, 0xf3, 0xf7, 0xcf, 0x56, 0x94, 0x70 } }
@@ -192,3 +195,8 @@ # Expected Overflow Android Kernel Command Line Characters
#
gEmbeddedTokenSpaceGuid.PcdAndroidKernelCommandLineOverflow|0|UINT32|0x000005C
+
+ #
+ # EFI Memory Attribute Protocol default enable state
+ #
+ gEmbeddedTokenSpaceGuid.PcdMemoryAttributeEnabledDefault|TRUE|BOOLEAN|0x00000060
diff --git a/EmbeddedPkg/EmbeddedPkg.dsc b/EmbeddedPkg/EmbeddedPkg.dsc index e9062cacbb..ef66aea29d 100644 --- a/EmbeddedPkg/EmbeddedPkg.dsc +++ b/EmbeddedPkg/EmbeddedPkg.dsc @@ -239,6 +239,8 @@ EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.inf
EmbeddedPkg/Drivers/FdtClientDxe/FdtClientDxe.inf
+ EmbeddedPkg/Drivers/MemoryAttributeManagerDxe/MemoryAttributeManagerDxe.inf
+
EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf {
<LibraryClasses>
DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf
diff --git a/EmbeddedPkg/Include/Guid/MemoryAttributeManagerFormSet.h b/EmbeddedPkg/Include/Guid/MemoryAttributeManagerFormSet.h new file mode 100644 index 0000000000..2efdf03216 --- /dev/null +++ b/EmbeddedPkg/Include/Guid/MemoryAttributeManagerFormSet.h @@ -0,0 +1,17 @@ +/** @file
+
+ Copyright (c) 2023-2024, Mario Bălănică <mariobalanica02@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MEMORY_ATTRIBUTE_MANAGER_FORMSET_H_
+#define MEMORY_ATTRIBUTE_MANAGER_FORMSET_H_
+
+#define MEMORY_ATTRIBUTE_MANAGER_FORMSET_GUID \
+ { 0xefab3427, 0x4793, 0x4e9e, { 0xaa, 0x29, 0x88, 0x0c, 0x9a, 0x77, 0x5b, 0x5f } }
+
+extern EFI_GUID gMemoryAttributeManagerFormSetGuid;
+
+#endif // __MEMORY_ATTRIBUTE_MANAGER_FORMSET_H__
|