diff options
25 files changed, 810 insertions, 366 deletions
diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template index cca699c..2108948 100755 --- a/BaseTools/Conf/tools_def.template +++ b/BaseTools/Conf/tools_def.template @@ -1932,11 +1932,11 @@ RELEASE_GCC_LOONGARCH64_CC_FLAGS = DEF(GCC5_LOONGARCH64_CC_FLAGS) -Wno-unu DEFINE CLANGPDB_IA32_PREFIX = ENV(CLANG_BIN)
DEFINE CLANGPDB_X64_PREFIX = ENV(CLANG_BIN)
-DEFINE CLANGPDB_IA32_TARGET = -target i686-unknown-windows-gnu
-DEFINE CLANGPDB_X64_TARGET = -target x86_64-unknown-windows-gnu
+DEFINE CLANGPDB_IA32_TARGET = -target i686-pc-windows-msvc
+DEFINE CLANGPDB_X64_TARGET = -target x86_64-pc-windows-msvc
DEFINE CLANGPDB_WARNING_OVERRIDES = -Wno-parentheses-equality -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-empty-body -Wno-unused-const-variable -Wno-varargs -Wno-unknown-warning-option -Wno-unused-but-set-variable -Wno-unused-const-variable -Wno-unaligned-access -Wno-microsoft-enum-forward-reference
-DEFINE CLANGPDB_ALL_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) DEF(CLANGPDB_WARNING_OVERRIDES) -fno-stack-protector -funsigned-char -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang -Wno-address -Wno-shift-negative-value -Wno-unknown-pragmas -Wno-incompatible-library-redeclaration -Wno-null-dereference -mno-implicit-float -mms-bitfields -mno-stack-arg-probe -nostdlib -nostdlibinc -fseh-exceptions
+DEFINE CLANGPDB_ALL_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) DEF(CLANGPDB_WARNING_OVERRIDES) -fno-stack-protector -funsigned-char -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang -Wno-address -Wno-shift-negative-value -Wno-unknown-pragmas -Wno-incompatible-library-redeclaration -Wno-null-dereference -mno-implicit-float -mms-bitfields -mno-stack-arg-probe -nostdlib -nostdlibinc -fno-omit-frame-pointer -U _MSC_VER -D __GNUC__
###########################
# CLANGPDB IA32 definitions
diff --git a/BaseTools/set_vsprefix_envs.bat b/BaseTools/set_vsprefix_envs.bat index df2c771..5565f61 100644 --- a/BaseTools/set_vsprefix_envs.bat +++ b/BaseTools/set_vsprefix_envs.bat @@ -242,7 +242,12 @@ if not defined WINDDK3790_PREFIX ( )
if not defined IASL_PREFIX (
- set IASL_PREFIX=C:\ASL\
+ if exist "C:\ASL\" (
+ set IASL_PREFIX=C:\ASL\
+ ) else (
+ @echo.
+ @echo !!! WARNING !!! IASL_PREFIX environment variable is not set
+ )
)
popd
diff --git a/BaseTools/toolsetup.bat b/BaseTools/toolsetup.bat index ac52f7a..92eb682 100755 --- a/BaseTools/toolsetup.bat +++ b/BaseTools/toolsetup.bat @@ -333,6 +333,17 @@ if defined VS2022 ( call %EDK_TOOLS_PATH%\set_vsprefix_envs.bat
call %EDK_TOOLS_PATH%\get_vsvars.bat
)
+if defined BASETOOLS_MINGW_BUILD (
+ if not defined IASL_PREFIX (
+ REM For VS builds this environment variable is set via set_vsprefix_envs.bat
+ if exist "C:\ASL\" (
+ set IASL_PREFIX=C:\ASL\
+ ) else (
+ @echo.
+ @echo !!! WARNING !!! IASL_PREFIX environment variable is not set
+ )
+ )
+)
if %SCRIPT_ERROR% NEQ 0 (
@echo.
@echo !!! ERROR !!! %VSTool% is not installed !!!
diff --git a/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldiv.asm b/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldiv.nasm index c9f07e3..88b0705 100644 --- a/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldiv.asm +++ b/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldiv.nasm @@ -1,19 +1,19 @@ ;***
-;ulldiv.asm - unsigned long divide routine
+;ulldiv.nasm - unsigned long divide routine
;
; Copyright (c) Microsoft Corporation. All rights reserved.
+; Copyright (c) 2025, Intel Corporation. All rights reserved.
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
;Purpose:
; defines the unsigned long divide routine
; __aulldiv
;
-;Original Implemenation: MSVC 14.29.30133
+;Original Implementation: MSVC 14.29.30133
;
;*******************************************************************************
- .686
- .model flat,C
- .code
+
+ SECTION .text
;***
;ulldiv - unsigned long divide
@@ -37,10 +37,11 @@ ;Exceptions:
;
;*******************************************************************************
-_aulldiv PROC NEAR
+global ASM_PFX(_aulldiv)
+ASM_PFX(_aulldiv):
-HIWORD EQU [4] ;
-LOWORD EQU [0]
+%define HIWORD_OFFSET 4
+%define LOWORD_OFFSET 0
push ebx
push esi
@@ -68,8 +69,10 @@ LOWORD EQU [0] ; -----------------
;
-DVND equ [esp + 12] ; stack address of dividend (a)
-DVSR equ [esp + 20] ; stack address of divisor (b)
+; stack offset of dividend (a)
+%define DVND_OFFSET 12
+; stack offset of divisor (b)
+%define DVSR_OFFSET 20
;
; Now do the divide. First look to see if the divisor is less than 4194304K.
@@ -77,15 +80,15 @@ DVSR equ [esp + 20] ; stack address of divisor (b) ; things get a little more complex.
;
- mov eax,HIWORD(DVSR) ; check to see if divisor < 4194304K
+ mov eax, dword [esp + DVSR_OFFSET + HIWORD_OFFSET] ; check to see if divisor < 4194304K
or eax,eax
jnz short L1 ; nope, gotta do this the hard way
- mov ecx,LOWORD(DVSR) ; load divisor
- mov eax,HIWORD(DVND) ; load high word of dividend
+ mov ecx, dword [esp + DVSR_OFFSET + LOWORD_OFFSET] ; load divisor
+ mov eax, dword [esp + DVND_OFFSET + HIWORD_OFFSET] ; load high word of dividend
xor edx,edx
div ecx ; get high order bits of quotient
mov ebx,eax ; save high bits of quotient
- mov eax,LOWORD(DVND) ; edx:eax <- remainder:lo word of dividend
+ mov eax, dword [esp + DVND_OFFSET + LOWORD_OFFSET] ; edx:eax <- remainder:lo word of dividend
div ecx ; get low order bits of quotient
mov edx,ebx ; edx:eax <- quotient hi:quotient lo
jmp short L2 ; restore stack and return
@@ -96,9 +99,9 @@ DVSR equ [esp + 20] ; stack address of divisor (b) L1:
mov ecx,eax ; ecx:ebx <- divisor
- mov ebx,LOWORD(DVSR)
- mov edx,HIWORD(DVND) ; edx:eax <- dividend
- mov eax,LOWORD(DVND)
+ mov ebx, dword [esp + DVSR_OFFSET + LOWORD_OFFSET]
+ mov edx, dword [esp + DVND_OFFSET + HIWORD_OFFSET] ; edx:eax <- dividend
+ mov eax, dword [esp + DVND_OFFSET + LOWORD_OFFSET]
L3:
shr ecx,1 ; shift divisor right one bit; hi bit <- 0
rcr ebx,1
@@ -116,9 +119,9 @@ L3: ; dividend is close to 2**64 and the quotient is off by 1.
;
- mul dword ptr HIWORD(DVSR) ; QUOT * HIWORD(DVSR)
+ mul dword [esp + DVSR_OFFSET + HIWORD_OFFSET] ; QUOT * HIWORD(DVSR)
mov ecx,eax
- mov eax,LOWORD(DVSR)
+ mov eax, dword [esp + DVSR_OFFSET + LOWORD_OFFSET]
mul esi ; QUOT * LOWORD(DVSR)
add edx,ecx ; EDX:EAX = QUOT * DVSR
jc short L4 ; carry means Quotient is off by 1
@@ -129,10 +132,10 @@ L3: ; subtract one (1) from the quotient.
;
- cmp edx,HIWORD(DVND) ; compare hi words of result and original
+ cmp edx, dword [esp + DVND_OFFSET + HIWORD_OFFSET] ; compare hi words of result and original
ja short L4 ; if result > original, do subtract
jb short L5 ; if result < original, we are ok
- cmp eax,LOWORD(DVND) ; hi words are equal, compare lo words
+ cmp eax, dword [esp + DVND_OFFSET + LOWORD_OFFSET] ; hi words are equal, compare lo words
jbe short L5 ; if less or equal we are ok, else subtract
L4:
dec esi ; subtract 1 from quotient
@@ -151,7 +154,3 @@ L2: pop ebx
ret 16
-
-_aulldiv ENDP
-
- end
diff --git a/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf b/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf index e5fa3a9..8c3951d 100644 --- a/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf +++ b/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf @@ -1,7 +1,7 @@ ## @file
# Intrinsic Routines Wrapper Library Instance.
#
-# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2025, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -33,7 +33,7 @@ Ia32/MathFtol.c | MSFT
Ia32/MathLlmul.asm | MSFT
Ia32/MathLlshr.asm | MSFT
- Ia32/MathUlldiv.asm | MSFT
+ Ia32/MathUlldiv.nasm | MSFT
Ia32/MathUlldvrm.asm | MSFT
Ia32/MathLldiv.asm | MSFT
Ia32/MathUllrem.asm | MSFT
@@ -48,6 +48,8 @@ Ia32/MathDivS64x64.c | GCC
Ia32/MathDivU64x64.c | GCC
Ia32/MathModU64x64.c | GCC
+
+ Ia32/MathUlldiv.nasm | CLANGPDB
[Sources.X64]
CopyMem.c
Math.c | GCC
diff --git a/Maintainers.txt b/Maintainers.txt index ee0142f..9391039 100644 --- a/Maintainers.txt +++ b/Maintainers.txt @@ -209,7 +209,6 @@ W: https://github.com/tianocore/tianocore.github.io/wiki/EmulatorPkg M: Oliver Smith-Denny <osde@microsoft.com> [os-d]
M: Andrew Fish <afish@apple.com> [ajfish]
M: Michael Kubacki <mikuback@linux.microsoft.com> [makubacki]
-M: Ray Ni <ray.ni@intel.com> [niruiyu]
S: Maintained
EmulatorPkg: Redfish-related modules
@@ -314,7 +313,7 @@ F: MdeModulePkg/Include/Ppi/StorageSecurityCommand.h F: MdeModulePkg/Include/Protocol/Ps2Policy.h
F: MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/
F: MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/
-R: Ray Ni <ray.ni@intel.com> [niruiyu]
+R: Jacek Kolakowski <jacek.kolakowski@intel.com> [jkolakow]
MdeModulePkg: Disk modules
F: MdeModulePkg/Universal/Disk/
@@ -648,6 +647,7 @@ M: Ray Ni <ray.ni@intel.com> [niruiyu] R: Jiaxin Wu <jiaxin.wu@intel.com> [jiaxinwu]
R: Dun Tan <dun.tan@intel.com> [td36]
R: Khor Swee Aun <swee.aun.khor@intel.com> [sweeaun]
+R: Eduardo Cuevas Farfan <eduardo.cuevas.farfan@intel.com> [ecuevasf]
UefiCpuPkg
F: UefiCpuPkg/
@@ -659,6 +659,7 @@ R: Dun Tan <dun.tan@intel.com> [td36] R: Rahul Kumar <rahul1.kumar@intel.com> [rahul1-kumar]
R: Gerd Hoffmann <kraxel@redhat.com> [kraxel]
R: Star Zeng <star.zeng@intel.com> [lzeng14]
+R: Eduardo Cuevas Farfan <eduardo.cuevas.farfan@intel.com> [ecuevasf]
UefiCpuPkg: AMD related files
F: UefiCpuPkg/Library/MmSaveStateLib/*Amd*.*
@@ -673,7 +674,6 @@ M: Guo Dong <guo.dong@intel.com> [gdong1] M: Sean Rhodes <sean@starlabs.systems> [Sean-StarLabs]
M: James Lu <james.lu@intel.com> [jameslu8]
M: Benjamin Doron <benjamin.doron@9elements.com> [benjamindoron]
-M: Linus Liu <linus.liu@intel.com> [LinusvPelt]
R: Gua Guo <gua.guo@intel.com> [gguo11837463]
M: Chasel Chiu <chasel.chiu@intel.com> [ChaselChiu]
R: Shuo Liu <shuo.liu@intel.com> [shuoliu0]
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c index b3a4063..713415d 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c @@ -900,12 +900,17 @@ UsbEnumeratePort ( Child = NULL;
HubApi = HubIf->HubApi;
+ // Zero out PortState in case GetPortStatus does not set
+ // it and we continue on the EFI_DEVICE_ERROR path
+ PortState.PortStatus = 0;
+ PortState.PortChangeStatus = 0;
+
//
// Host learns of the new device by polling the hub for port changes.
//
Status = HubApi->GetPortStatus (HubIf, Port, &PortState);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) && (Status != EFI_DEVICE_ERROR)) {
DEBUG ((DEBUG_ERROR, "UsbEnumeratePort: failed to get state of port %d\n", Port));
return Status;
}
@@ -987,7 +992,9 @@ UsbEnumeratePort ( // Now, new device connected, enumerate and configure the device
//
DEBUG ((DEBUG_INFO, "UsbEnumeratePort: new device connected at port %d\n", Port));
- if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET) &&
+ (Status != EFI_DEVICE_ERROR))
+ {
Status = UsbEnumerateNewDev (HubIf, Port, FALSE);
} else {
Status = UsbEnumerateNewDev (HubIf, Port, TRUE);
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index cd3940d..6f08554 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -45,6 +45,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include <Protocol/HiiPackageList.h>
#include <Protocol/SmmBase2.h>
#include <Protocol/PeCoffImageEmulator.h>
+#include <Protocol/MemoryAttribute.h>
#include <Guid/MemoryTypeInformation.h>
#include <Guid/FirmwareFileSystem2.h>
#include <Guid/FirmwareFileSystem3.h>
@@ -250,6 +251,7 @@ extern EFI_SECURITY_ARCH_PROTOCOL *gSecurity; extern EFI_SECURITY2_ARCH_PROTOCOL *gSecurity2;
extern EFI_BDS_ARCH_PROTOCOL *gBds;
extern EFI_SMM_BASE2_PROTOCOL *gSmmBase2;
+extern EFI_MEMORY_ATTRIBUTE_PROTOCOL *gMemoryAttributeProtocol;
extern EFI_TPL gEfiCurrentTpl;
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index cc315ac..40e7dc8 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -156,6 +156,7 @@ gEfiHiiPackageListProtocolGuid ## SOMETIMES_PRODUCES
gEfiSmmBase2ProtocolGuid ## SOMETIMES_CONSUMES
gEdkiiPeCoffImageEmulatorProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiMemoryAttributeProtocolGuid ## CONSUMES
# Arch Protocols
gEfiBdsArchProtocolGuid ## CONSUMES
diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index 9df64cc..27c2788 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -1746,6 +1746,38 @@ CoreFreePages ( {
EFI_STATUS Status;
EFI_MEMORY_TYPE MemoryType;
+ UINT64 Attributes;
+
+ // check if this memory is returned to the core as RW at a minimum. If the memory attribute protocol is not installed,
+ // then we assume that the memory is RW by default and continue to free it.
+ if (gMemoryAttributeProtocol != NULL) {
+ Status = gMemoryAttributeProtocol->GetMemoryAttributes (
+ gMemoryAttributeProtocol,
+ Memory,
+ EFI_PAGES_TO_SIZE (NumberOfPages),
+ &Attributes
+ );
+
+ // if we failed to get the attributes, or if the memory is read-only or read-protected,
+ // then we leak the memory and return success. This is done because the UEFI spec does not specify whether pages
+ // should be freed with any specific permission attributes. As such, there exist bootloaders in the wild that will
+ // free memory that is marked RO, which can crash the core if DebugClearMemory is enabled or can be passed out to a
+ // driver in the next AllocatePages() call, which can cause a crash later on. It is deemed lower risk to leak the
+ // memory than to attempt to fix up the attributes as that requires syncing the GCD and the page table.
+ if (EFI_ERROR (Status) || (Attributes & EFI_MEMORY_RO) || (Attributes & EFI_MEMORY_RP)) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: Memory %llx for %llx Pages failed to get attributes with status %r or it is read-only or read-protected. "
+ "Attributes: %llx. Leaking memory!\n",
+ __func__,
+ Memory,
+ NumberOfPages,
+ Status,
+ Attributes
+ ));
+ return EFI_SUCCESS;
+ }
+ }
Status = CoreInternalFreePages (Memory, NumberOfPages, &MemoryType);
if (!EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c index 33357eb..69d26cb 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c @@ -38,6 +38,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include <Guid/MemoryAttributesTable.h>
#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/MemoryAttribute.h>
#include <Protocol/SimpleFileSystem.h>
#include "DxeMain.h"
@@ -67,6 +68,8 @@ extern LIST_ENTRY mGcdMemorySpaceMap; STATIC LIST_ENTRY mProtectedImageRecordList;
+EFI_MEMORY_ATTRIBUTE_PROTOCOL *gMemoryAttributeProtocol;
+
/**
Get the image type.
@@ -1034,6 +1037,37 @@ DisableNullDetectionAtTheEndOfDxe ( }
/**
+ A notification for the Memory Attribute Protocol Installation.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+MemoryAttributeProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiMemoryAttributeProtocolGuid, NULL, (VOID **)&gMemoryAttributeProtocol);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a - Unable to locate the memory attribute protocol! Status = %r\n",
+ __func__,
+ Status
+ ));
+ }
+
+ CoreCloseEvent (Event);
+}
+
+/**
Initialize Memory Protection support.
**/
VOID
@@ -1084,6 +1118,35 @@ CoreInitializeMemoryProtection ( );
ASSERT_EFI_ERROR (Status);
+ // Register an event to populate the memory attribute protocol
+ Status = CoreCreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ MemoryAttributeProtocolNotify,
+ NULL,
+ &Event
+ );
+
+ // if we fail to create the event or the protocol notify, we should still continue, we won't be able to query the
+ // memory attributes on FreePages(), so we may encounter a driver or bootloader that has not set attributes back to
+ // RW, but this matches the state of the world before this protocol was introduced, so it is not a regression.
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a - Failed to create event for the Memory Attribute Protocol notification: %r\n", __func__, Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ // Register for protocol notification
+ Status = CoreRegisterProtocolNotify (
+ &gEfiMemoryAttributeProtocolGuid,
+ Event,
+ &Registration
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a - Failed to register for the Memory Attribute Protocol notification: %r\n", __func__, Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+
//
// Register a callback to disable NULL pointer detection at EndOfDxe
//
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 88b5a9d..6ccca34 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -1508,8 +1508,7 @@ # OEM Reserved 0x4000000000000000<BR>
# OS Reserved 0x8000000000000000<BR>
#
- # NOTE: User must NOT set NX protection for EfiLoaderCode / EfiBootServicesCode / EfiRuntimeServicesCode. <BR>
- # User MUST set the same NX protection for EfiBootServicesData and EfiConventionalMemory. <BR>
+ # NOTE: User MUST set the same NX protection for EfiBootServicesData and EfiConventionalMemory. <BR>
#
# e.g. 0x7FD5 can be used for all memory except Code. <BR>
# e.g. 0x7BD4 can be used for all memory except Code and ACPINVS/Reserved. <BR>
diff --git a/OvmfPkg/PlatformCI/PlatformBuildLib.py b/OvmfPkg/PlatformCI/PlatformBuildLib.py index 6e0b9e4..19f92ac 100644 --- a/OvmfPkg/PlatformCI/PlatformBuildLib.py +++ b/OvmfPkg/PlatformCI/PlatformBuildLib.py @@ -110,21 +110,8 @@ class SettingsManager(UpdateSettingsManager, SetupSettingsManager, PrEvalSetting The tuple should be (<workspace relative path to dsc file>, <input dictionary of dsc key value pairs>)
'''
- import re
- import sys
-
- cmd_line_input_vars = {}
- for arg in sys.argv:
- if "=" in arg:
- key, value = arg.split("=", 1)
- if key.startswith("-"):
- continue
- if re.match(r"BLD_.+_", key):
- key = re.sub(r"^BLD_.+?_", "", key, count=1)
- cmd_line_input_vars[key] = value
-
dsc = CommonPlatform.GetDscName(",".join(self.ActualArchitectures))
- return (f"OvmfPkg/{dsc}", cmd_line_input_vars)
+ return (f"OvmfPkg/{dsc}", {})
# ####################################################################################### #
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c index ba0b2ec..f5b1d2a 100644 --- a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c +++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c @@ -33,188 +33,7 @@ EFI_MM_COMMUNICATION_PROTOCOL mMmCommunication = { MM_COMM_BUFFER mMmCommonBuffer;
EFI_SMM_CONTROL2_PROTOCOL *mSmmControl2;
EFI_SMM_ACCESS2_PROTOCOL *mSmmAccess;
-BOOLEAN mSmmLocked = FALSE;
-BOOLEAN mEndOfDxe = FALSE;
-
-//
-// Table of Protocol notification and GUIDed Event notifications that the Standalone Mm requires
-//
-MM_EVENT_NOTIFICATION mMmEvents[] = {
- //
- // Declare protocol notification on DxeMmReadyToLock protocols. When this notification is established,
- // the associated event is immediately signalled, so the notification function will be executed and the
- // DXE Mm Ready To Lock Protocol will be found if it is already in the handle database.
- //
- { ProtocolNotify, TRUE, &gEfiDxeMmReadyToLockProtocolGuid, MmReadyToLockEventNotify, &gEfiDxeMmReadyToLockProtocolGuid, NULL },
- //
- // Declare event notification on Ready To Boot Event Group. This is an extra event notification that is
- // used to make sure SMRAM is locked before any boot options are processed.
- //
- { EventNotify, TRUE, &gEfiEventReadyToBootGuid, MmReadyToLockEventNotify, &gEfiEventReadyToBootGuid, NULL },
- //
- // Declare event notification on Ready To Boot Event Group. This is used to inform the MM Core
- // to notify MM driver that system enter ready to boot.
- //
- { EventNotify, FALSE, &gEfiEventReadyToBootGuid, MmGuidedEventNotify, &gEfiEventReadyToBootGuid, NULL },
- //
- // Declare event notification on EndOfDxe event. When this notification is established,
- // the associated event is immediately signalled, so the notification function will be executed and the
- // End Of Dxe Protocol will be found if it is already in the handle database.
- //
- { EventNotify, TRUE, &gEfiEndOfDxeEventGroupGuid, MmGuidedEventNotify, &gEfiEndOfDxeEventGroupGuid, NULL },
- //
- // Declare event notification on EndOfDxe event. This is used to set EndOfDxe event signaled flag.
- //
- { EventNotify, TRUE, &gEfiEndOfDxeEventGroupGuid, MmEndOfDxeEventNotify, &gEfiEndOfDxeEventGroupGuid, NULL },
- //
- // Declare event notification on Exit Boot Services Event Group. This is used to inform the MM Core
- // to notify MM driver that system enter exit boot services.
- //
- { EventNotify, FALSE, &gEfiEventExitBootServicesGuid, MmGuidedEventNotify, &gEfiEventExitBootServicesGuid, NULL },
- //
- // Declare event notification on SetVirtualAddressMap() Event Group. This is used to convert fixed MM communication buffer
- // and MM_COMM_BUFFER_STATUS in mMmCommonBuffer, mSmmControl2 from physical addresses to virtual addresses.
- //
- { EventNotify, FALSE, &gEfiEventVirtualAddressChangeGuid, MmVirtualAddressChangeEvent, NULL, NULL },
- //
- // Terminate the table of event notifications
- //
- { EndNotify, FALSE, NULL, NULL, NULL, NULL }
-};
-
-/**
- Event notification that is fired when GUIDed Event Group is signaled.
-
- @param Event The Event that is being processed, not used.
- @param Context Event Context, not used.
-
-**/
-VOID
-EFIAPI
-MmGuidedEventNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- UINTN Size;
- EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
-
- CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)mMmCommonBuffer.PhysicalStart;
-
- //
- // Use Guid to initialize EFI_MM_COMMUNICATE_HEADER structure
- //
- CopyGuid (&CommunicateHeader->HeaderGuid, (EFI_GUID *)Context);
- CommunicateHeader->MessageLength = 1;
- CommunicateHeader->Data[0] = 0;
-
- //
- // Generate the Software SMI and return the result
- //
- Size = sizeof (EFI_MM_COMMUNICATE_HEADER);
- MmCommunicate2 (&mMmCommunication2, CommunicateHeader, CommunicateHeader, &Size);
-}
-
-/**
- Event notification that is fired every time a DxeSmmReadyToLock protocol is added
- or if gEfiEventReadyToBootGuid is signaled.
-
- @param Event The Event that is being processed, not used.
- @param Context Event Context, not used.
-
-**/
-VOID
-EFIAPI
-MmReadyToLockEventNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- EFI_STATUS Status;
- VOID *Interface;
- UINTN Index;
-
- //
- // See if we are already locked
- //
- if (mSmmLocked) {
- return;
- }
-
- //
- // Make sure this notification is for this handler
- //
- if (CompareGuid ((EFI_GUID *)Context, &gEfiDxeMmReadyToLockProtocolGuid)) {
- Status = gBS->LocateProtocol (&gEfiDxeMmReadyToLockProtocolGuid, NULL, &Interface);
- if (EFI_ERROR (Status)) {
- return;
- }
- } else {
- //
- // If MM is not locked yet and we got here from gEfiEventReadyToBootGuid being
- // signaled, then gEfiDxeMmReadyToLockProtocolGuid was not installed as expected.
- // Print a warning on debug builds.
- //
- DEBUG ((DEBUG_WARN, "DXE Mm Ready To Lock Protocol not installed before Ready To Boot signal\n"));
- }
-
- if (!mEndOfDxe) {
- DEBUG ((DEBUG_ERROR, "EndOfDxe Event must be signaled before DxeSmmReadyToLock Protocol installation!\n"));
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED,
- (EFI_SOFTWARE_SMM_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)
- );
- ASSERT (FALSE);
- }
-
- //
- // Lock the SMRAM (Note: Locking SMRAM may not be supported on all platforms)
- //
- mSmmAccess->Lock (mSmmAccess);
-
- //
- // Close protocol and event notification events that do not apply after the
- // DXE MM Ready To Lock Protocol has been installed or the Ready To Boot
- // event has been signalled.
- //
- for (Index = 0; mMmEvents[Index].NotifyFunction != NULL; Index++) {
- if (mMmEvents[Index].CloseOnLock) {
- gBS->CloseEvent (mMmEvents[Index].Event);
- }
- }
-
- //
- // Inform MM Core that the DxeSmmReadyToLock protocol was installed
- //
- MmGuidedEventNotify (Event, (VOID *)&gEfiDxeMmReadyToLockProtocolGuid);
-
- //
- // Print debug message that the SMRAM window is now locked.
- //
- DEBUG ((DEBUG_INFO, "MmCommunicationDxe locked SMRAM window\n"));
-
- //
- // Set flag so this operation will not be performed again
- //
- mSmmLocked = TRUE;
-}
-
-/**
- Event notification that is fired when EndOfDxe Event Group is signaled.
-
- @param Event The Event that is being processed, not used.
- @param Context Event Context, not used.
-
-**/
-VOID
-EFIAPI
-MmEndOfDxeEventNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- mEndOfDxe = TRUE;
-}
+EFI_EVENT mVirtualAddressChangeEvent = NULL;
/**
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
@@ -458,8 +277,6 @@ MmCommunicationEntryPoint ( EFI_HANDLE Handle;
EFI_HOB_GUID_TYPE *GuidHob;
MM_COMM_BUFFER *MmCommonBuffer;
- UINTN Index;
- VOID *Registration;
//
// Locate gMmCommBufferHobGuid and cache the content
@@ -507,29 +324,16 @@ MmCommunicationEntryPoint ( ASSERT_EFI_ERROR (Status);
//
- // Create the set of protocol and event notifications that the Standalone Mm requires
+ // Register the event to convert the pointer for runtime.
//
- for (Index = 0; mMmEvents[Index].NotificationType != EndNotify; Index++) {
- if (mMmEvents[Index].NotificationType == ProtocolNotify) {
- mMmEvents[Index].Event = EfiCreateProtocolNotifyEvent (
- mMmEvents[Index].Guid,
- TPL_CALLBACK,
- mMmEvents[Index].NotifyFunction,
- mMmEvents[Index].NotifyContext,
- &Registration
- );
- } else {
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- mMmEvents[Index].NotifyFunction,
- mMmEvents[Index].NotifyContext,
- mMmEvents[Index].Guid,
- &mMmEvents[Index].Event
- );
- ASSERT_EFI_ERROR (Status);
- }
- }
+ gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ MmVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mVirtualAddressChangeEvent
+ );
return EFI_SUCCESS;
}
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h index 3b399da..80d2bfa 100644 --- a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h +++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h @@ -25,30 +25,9 @@ #include <Protocol/MmCommunication3.h>
#include <Protocol/MmCommunication2.h>
#include <Protocol/MmCommunication.h>
-#include <Protocol/DxeMmReadyToLock.h>
#include <Protocol/SmmAccess2.h>
#include <Guid/MmCommBuffer.h>
-#include <Guid/EventGroup.h>
-
-typedef enum {
- EventNotify,
- ProtocolNotify,
- EndNotify,
-} NOTIFICATION_TYPE;
-
-//
-// Data structure used to declare a table of protocol notifications and event
-// notifications required by the Standalone Mm environment
-//
-typedef struct {
- NOTIFICATION_TYPE NotificationType;
- BOOLEAN CloseOnLock;
- EFI_GUID *Guid;
- EFI_EVENT_NOTIFY NotifyFunction;
- VOID *NotifyContext;
- EFI_EVENT Event;
-} MM_EVENT_NOTIFICATION;
/**
Communicates with a registered handler.
@@ -144,49 +123,6 @@ MmCommunicate ( );
/**
- Event notification that is fired every time a DxeSmmReadyToLock protocol is added
- or if gEfiEventReadyToBootGuid is signaled.
-
- @param Event The Event that is being processed, not used.
- @param Context Event Context, not used.
-
-**/
-VOID
-EFIAPI
-MmReadyToLockEventNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- );
-
-/**
- Event notification that is fired when GUIDed Event Group is signaled.
-
- @param Event The Event that is being processed, not used.
- @param Context Event Context, not used.
-
-**/
-VOID
-EFIAPI
-MmGuidedEventNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- );
-
-/**
- Event notification that is fired when EndOfDxe Event Group is signaled.
-
- @param Event The Event that is being processed, not used.
- @param Context Event Context, not used.
-
-**/
-VOID
-EFIAPI
-MmEndOfDxeEventNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- );
-
-/**
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf index dd5a0b1..2f23007 100644 --- a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf +++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf @@ -42,8 +42,6 @@ [Guids]
gMmCommBufferHobGuid
gEfiEventVirtualAddressChangeGuid
- gEfiEndOfDxeEventGroupGuid
- gEfiEventExitBootServicesGuid
gEfiMmCommunicateHeaderV3Guid
[Protocols]
@@ -51,7 +49,6 @@ gEfiMmCommunication2ProtocolGuid
gEfiSmmControl2ProtocolGuid
gEfiMmCommunicationProtocolGuid
- gEfiDxeMmReadyToLockProtocolGuid
gEfiSmmAccess2ProtocolGuid
[Depex]
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.c b/StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.c new file mode 100644 index 0000000..8e49b53 --- /dev/null +++ b/StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.c @@ -0,0 +1,265 @@ +/** @file
+ MmCommunicationNotifyDxe driver creates the notifications of
+ some protocols and event.
+
+ Copyright (c) 2025, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MmCommunicationNotifyDxe.h"
+
+//
+// PI 1.7 MM Communication Protocol 2 instance
+//
+EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication2;
+MM_COMM_BUFFER mMmCommonBuffer;
+EFI_SMM_ACCESS2_PROTOCOL *mSmmAccess;
+BOOLEAN mSmmLocked = FALSE;
+BOOLEAN mEndOfDxe = FALSE;
+
+//
+// Table of Protocol notification and GUIDed Event notifications that the Standalone Mm requires
+//
+MM_EVENT_NOTIFICATION mMmEvents[] = {
+ //
+ // Declare protocol notification on DxeMmReadyToLock protocols. When this notification is established,
+ // the associated event is immediately signalled, so the notification function will be executed and the
+ // DXE Mm Ready To Lock Protocol will be found if it is already in the handle database.
+ //
+ { ProtocolNotify, TRUE, &gEfiDxeMmReadyToLockProtocolGuid, MmReadyToLockEventNotify, &gEfiDxeMmReadyToLockProtocolGuid, NULL },
+ //
+ // Declare event notification on Ready To Boot Event Group. This is an extra event notification that is
+ // used to make sure SMRAM is locked before any boot options are processed.
+ //
+ { EventNotify, TRUE, &gEfiEventReadyToBootGuid, MmReadyToLockEventNotify, &gEfiEventReadyToBootGuid, NULL },
+ //
+ // Declare event notification on Ready To Boot Event Group. This is used to inform the MM Core
+ // to notify MM driver that system enter ready to boot.
+ //
+ { EventNotify, FALSE, &gEfiEventReadyToBootGuid, MmGuidedEventNotify, &gEfiEventReadyToBootGuid, NULL },
+ //
+ // Declare event notification on EndOfDxe event. When this notification is established,
+ // the associated event is immediately signalled, so the notification function will be executed and the
+ // End Of Dxe Protocol will be found if it is already in the handle database.
+ //
+ { EventNotify, TRUE, &gEfiEndOfDxeEventGroupGuid, MmGuidedEventNotify, &gEfiEndOfDxeEventGroupGuid, NULL },
+ //
+ // Declare event notification on EndOfDxe event. This is used to set EndOfDxe event signaled flag.
+ //
+ { EventNotify, TRUE, &gEfiEndOfDxeEventGroupGuid, MmEndOfDxeEventNotify, &gEfiEndOfDxeEventGroupGuid, NULL },
+ //
+ // Declare event notification on Exit Boot Services Event Group. This is used to inform the MM Core
+ // to notify MM driver that system enter exit boot services.
+ //
+ { EventNotify, FALSE, &gEfiEventExitBootServicesGuid, MmGuidedEventNotify, &gEfiEventExitBootServicesGuid, NULL },
+ //
+ // Terminate the table of event notifications
+ //
+ { EndNotify, FALSE, NULL, NULL, NULL, NULL }
+};
+
+/**
+ Event notification that is fired when GUIDed Event Group is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmGuidedEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Size;
+ EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
+
+ CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)mMmCommonBuffer.PhysicalStart;
+
+ //
+ // Use Guid to initialize EFI_MM_COMMUNICATE_HEADER structure
+ //
+ CopyGuid (&CommunicateHeader->HeaderGuid, (EFI_GUID *)Context);
+ CommunicateHeader->MessageLength = 1;
+ CommunicateHeader->Data[0] = 0;
+
+ //
+ // Generate the Software SMI and return the result
+ //
+ Size = sizeof (EFI_MM_COMMUNICATE_HEADER);
+ mMmCommunication2->Communicate (mMmCommunication2, CommunicateHeader, CommunicateHeader, &Size);
+}
+
+/**
+ Event notification that is fired every time a DxeSmmReadyToLock protocol is added
+ or if gEfiEventReadyToBootGuid is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmReadyToLockEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *Interface;
+ UINTN Index;
+
+ //
+ // See if we are already locked
+ //
+ if (mSmmLocked) {
+ return;
+ }
+
+ //
+ // Make sure this notification is for this handler
+ //
+ if (CompareGuid ((EFI_GUID *)Context, &gEfiDxeMmReadyToLockProtocolGuid)) {
+ Status = gBS->LocateProtocol (&gEfiDxeMmReadyToLockProtocolGuid, NULL, &Interface);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ } else {
+ //
+ // If MM is not locked yet and we got here from gEfiEventReadyToBootGuid being
+ // signaled, then gEfiDxeMmReadyToLockProtocolGuid was not installed as expected.
+ // Print a warning on debug builds.
+ //
+ DEBUG ((DEBUG_WARN, "DXE Mm Ready To Lock Protocol not installed before Ready To Boot signal\n"));
+ }
+
+ if (!mEndOfDxe) {
+ DEBUG ((DEBUG_ERROR, "EndOfDxe Event must be signaled before DxeSmmReadyToLock Protocol installation!\n"));
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED,
+ (EFI_SOFTWARE_SMM_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)
+ );
+ ASSERT (FALSE);
+ }
+
+ //
+ // Lock the SMRAM (Note: Locking SMRAM may not be supported on all platforms)
+ //
+ mSmmAccess->Lock (mSmmAccess);
+
+ //
+ // Close protocol and event notification events that do not apply after the
+ // DXE MM Ready To Lock Protocol has been installed or the Ready To Boot
+ // event has been signalled.
+ //
+ for (Index = 0; mMmEvents[Index].NotifyFunction != NULL; Index++) {
+ if (mMmEvents[Index].CloseOnLock) {
+ gBS->CloseEvent (mMmEvents[Index].Event);
+ }
+ }
+
+ //
+ // Inform MM Core that the DxeSmmReadyToLock protocol was installed
+ //
+ MmGuidedEventNotify (Event, (VOID *)&gEfiDxeMmReadyToLockProtocolGuid);
+
+ //
+ // Print debug message that the SMRAM window is now locked.
+ //
+ DEBUG ((DEBUG_INFO, "MmCommunicationNotifyDxe locked SMRAM window\n"));
+
+ //
+ // Set flag so this operation will not be performed again
+ //
+ mSmmLocked = TRUE;
+}
+
+/**
+ Event notification that is fired when EndOfDxe Event Group is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmEndOfDxeEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ mEndOfDxe = TRUE;
+}
+
+/**
+ The Entry Point for MmCommunicateNotifyDxe driver.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurred when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicationNotifyEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ MM_COMM_BUFFER *MmCommonBuffer;
+ UINTN Index;
+ VOID *Registration;
+
+ //
+ // Locate gMmCommBufferHobGuid and cache the content
+ //
+ GuidHob = GetFirstGuidHob (&gMmCommBufferHobGuid);
+ ASSERT (GuidHob != NULL);
+ MmCommonBuffer = GET_GUID_HOB_DATA (GuidHob);
+ CopyMem (&mMmCommonBuffer, MmCommonBuffer, sizeof (MM_COMM_BUFFER));
+
+ //
+ // Get SMM Access Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&mSmmAccess);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get MM Communication Protocol 2 instance
+ //
+ Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL, (VOID **)&mMmCommunication2);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create the set of protocol and event notifications that the Standalone Mm requires
+ //
+ for (Index = 0; mMmEvents[Index].NotificationType != EndNotify; Index++) {
+ if (mMmEvents[Index].NotificationType == ProtocolNotify) {
+ mMmEvents[Index].Event = EfiCreateProtocolNotifyEvent (
+ mMmEvents[Index].Guid,
+ TPL_CALLBACK,
+ mMmEvents[Index].NotifyFunction,
+ mMmEvents[Index].NotifyContext,
+ &Registration
+ );
+ } else {
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ mMmEvents[Index].NotifyFunction,
+ mMmEvents[Index].NotifyContext,
+ mMmEvents[Index].Guid,
+ &mMmEvents[Index].Event
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.h b/StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.h new file mode 100644 index 0000000..83391dc --- /dev/null +++ b/StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.h @@ -0,0 +1,156 @@ +/** @file
+
+ Copyright (c) 2025, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MM_COMMUNICATION_NOTIFY_DXE_H_
+#define MM_COMMUNICATION_NOTIFY_DXE_H_
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+#include <Protocol/SmmControl2.h>
+#include <Protocol/MmCommunication2.h>
+#include <Protocol/MmCommunication.h>
+#include <Protocol/DxeMmReadyToLock.h>
+#include <Protocol/SmmAccess2.h>
+
+#include <Guid/MmCommBuffer.h>
+#include <Guid/EventGroup.h>
+
+typedef enum {
+ EventNotify,
+ ProtocolNotify,
+ EndNotify,
+} NOTIFICATION_TYPE;
+
+//
+// Data structure used to declare a table of protocol notifications and event
+// notifications required by the Standalone Mm environment
+//
+typedef struct {
+ NOTIFICATION_TYPE NotificationType;
+ BOOLEAN CloseOnLock;
+ EFI_GUID *Guid;
+ EFI_EVENT_NOTIFY NotifyFunction;
+ VOID *NotifyContext;
+ EFI_EVENT Event;
+} MM_EVENT_NOTIFICATION;
+
+/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_MM_COMMUNICATION_PROTOCOL instance.
+ @param[in, out] CommBufferPhysical Physical address of the MM communication buffer.
+ @param[in, out] CommBufferVirtual Virtual address of the MM communication buffer.
+ @param[in, out] CommSize The size of the data buffer being passed in. On exit, the size of data
+ being returned. Zero if the handler does not wish to reply with any data.
+ This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
+ @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
+ If this error is returned, the MessageLength field
+ in the CommBuffer header or the integer pointed by
+ CommSize, are updated to reflect the maximum payload
+ size the implementation can accommodate.
+ @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter,
+ if not omitted, are in address range that cannot be
+ accessed by the MM environment.
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicate2 (
+ IN CONST EFI_MM_COMMUNICATION2_PROTOCOL *This,
+ IN OUT VOID *CommBufferPhysical,
+ IN OUT VOID *CommBufferVirtual,
+ IN OUT UINTN *CommSize OPTIONAL
+ );
+
+/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_MM_COMMUNICATION_PROTOCOL instance.
+ @param[in, out] CommBufferPhysical Physical address of the MM communication buffer
+ @param[in, out] CommSize The size of the data buffer being passed in. On exit, the size of data
+ being returned. Zero if the handler does not wish to reply with any data.
+ This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
+ @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
+ If this error is returned, the MessageLength field
+ in the CommBuffer header or the integer pointed by
+ CommSize, are updated to reflect the maximum payload
+ size the implementation can accommodate.
+ @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter,
+ if not omitted, are in address range that cannot be
+ accessed by the MM environment.
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicate (
+ IN CONST EFI_MM_COMMUNICATION_PROTOCOL *This,
+ IN OUT VOID *CommBufferPhysical,
+ IN OUT UINTN *CommSize OPTIONAL
+ );
+
+/**
+ Event notification that is fired every time a DxeSmmReadyToLock protocol is added
+ or if gEfiEventReadyToBootGuid is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmReadyToLockEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Event notification that is fired when GUIDed Event Group is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmGuidedEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Event notification that is fired when EndOfDxe Event Group is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmEndOfDxeEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.inf b/StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.inf new file mode 100644 index 0000000..670ae22 --- /dev/null +++ b/StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.inf @@ -0,0 +1,51 @@ +## @file
+# MmCommunicationNotifyDxe driver create the notifications of
+# some protocols and event.
+#
+# Copyright (c) 2025, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = MmCommunicationNotifyDxe
+ FILE_GUID = DE05B887-A2EF-4D81-BFFE-FF9CDE458753
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ ENTRY_POINT = MmCommunicationNotifyEntryPoint
+
+[Sources]
+ MmCommunicationNotifyDxe.c
+ MmCommunicationNotifyDxe.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ BaseLib
+ DebugLib
+ HobLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ UefiLib
+ ReportStatusCodeLib
+
+[Guids]
+ gMmCommBufferHobGuid
+ gEfiEndOfDxeEventGroupGuid
+ gEfiEventExitBootServicesGuid
+
+[Protocols]
+ gEfiDxeMmReadyToLockProtocolGuid
+ gEfiSmmAccess2ProtocolGuid
+ gEfiMmCommunication2ProtocolGuid
+
+[Depex]
+ gEfiMmCommunication2ProtocolGuid
diff --git a/StandaloneMmPkg/StandaloneMmPkg.dsc b/StandaloneMmPkg/StandaloneMmPkg.dsc index d36081e..caf0b50 100644 --- a/StandaloneMmPkg/StandaloneMmPkg.dsc +++ b/StandaloneMmPkg/StandaloneMmPkg.dsc @@ -96,6 +96,8 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVER]
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
@@ -147,6 +149,7 @@ StandaloneMmPkg/Library/SmmLockBoxMmDependency/SmmLockBoxMmDependency.inf
StandaloneMmPkg/Library/MmPlatformHobProducerLibNull/MmPlatformHobProducerLibNull.inf
StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf
+ StandaloneMmPkg/Drivers/MmCommunicationNotifyDxe/MmCommunicationNotifyDxe.inf
StandaloneMmPkg/Library/StandaloneMmExtractGuidedSectionLib/StandaloneMmExtractGuidedSectionLib.inf
[Components.AARCH64, Components.ARM]
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 8c1428c..f5f6074 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -160,7 +160,7 @@ GetWakeupBuffer ( @retval 0 Cannot find free memory below 4GB.
**/
UINTN
-AllocateCodeBuffer (
+AllocateCodePage (
IN UINTN BufferSize
)
{
@@ -417,14 +417,46 @@ AllocateApLoopCodeBuffer ( /**
Remove Nx protection for the range specific by BaseAddress and Length.
- The PEI implementation uses CpuPageTableLib to change the attribute.
- The DXE implementation uses gDS to change the attribute.
+ @param[in] BaseAddress BaseAddress of the range.
+ @param[in] Length Length of the range.
+**/
+VOID
+RemoveNxProtection (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;
+
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &MemDesc);
+ if (!EFI_ERROR (Status)) {
+ if (((MemDesc.Capabilities & EFI_MEMORY_XP) == EFI_MEMORY_XP) && ((MemDesc.Attributes & EFI_MEMORY_XP) == EFI_MEMORY_XP)) {
+ Status = gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ MemDesc.Attributes & (~EFI_MEMORY_XP)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a - Setting Nx on 0x%p returned %r\n", __func__, BaseAddress, Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a - Memory Address was not found in Memory map! %lp %r\n", __func__, BaseAddress, Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+/**
+ Add ReadOnly protection to the range specified by BaseAddress and Length.
@param[in] BaseAddress BaseAddress of the range.
@param[in] Length Length of the range.
**/
VOID
-RemoveNxprotection (
+ApplyRoProtection (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINTN Length
)
@@ -432,17 +464,23 @@ RemoveNxprotection ( EFI_STATUS Status;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;
- //
- // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD
- // service.
- //
Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &MemDesc);
if (!EFI_ERROR (Status)) {
- gDS->SetMemorySpaceAttributes (
- BaseAddress,
- Length,
- MemDesc.Attributes & (~EFI_MEMORY_XP)
- );
+ if (((MemDesc.Capabilities & EFI_MEMORY_RO) == EFI_MEMORY_RO) && ((MemDesc.Attributes & EFI_MEMORY_RO) != EFI_MEMORY_RO)) {
+ Status = gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ MemDesc.Attributes | EFI_MEMORY_RO
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a - Setting Ro on 0x%p returned %r\n", __func__, BaseAddress, Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a - Memory Address was not found in Memory map! %lp %r\n", __func__, BaseAddress, Status));
+ ASSERT_EFI_ERROR (Status);
}
}
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index ffaff18..96c0980 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -2072,6 +2072,7 @@ MpInitLibInitialize ( UINTN ApResetVectorSizeAbove1Mb;
UINTN BackupBufferAddr;
UINTN ApIdtBase;
+ IA32_CR0 Cr0;
FirstMpHandOff = GetNextMpHandOffHob (NULL);
if (FirstMpHandOff != NULL) {
@@ -2248,7 +2249,13 @@ MpInitLibInitialize ( // Copy all 32-bit code and 64-bit code into memory with type of
// EfiBootServicesCode to avoid page fault if NX memory protection is enabled.
//
- CpuMpData->WakeupBufferHigh = AllocateCodeBuffer (ApResetVectorSizeAbove1Mb);
+ CpuMpData->WakeupBufferHigh = AllocateCodePage (ApResetVectorSizeAbove1Mb);
+
+ Cr0.UintN = AsmReadCr0 ();
+ if (Cr0.Bits.PG != 0) {
+ RemoveNxProtection ((EFI_PHYSICAL_ADDRESS)(UINTN)CpuMpData->WakeupBufferHigh, ALIGN_VALUE (ApResetVectorSizeAbove1Mb, EFI_PAGE_SIZE));
+ }
+
CopyMem (
(VOID *)CpuMpData->WakeupBufferHigh,
CpuMpData->AddressMap.RendezvousFunnelAddress +
@@ -2256,6 +2263,9 @@ MpInitLibInitialize ( ApResetVectorSizeAbove1Mb
);
DEBUG ((DEBUG_INFO, "AP Vector: non-16-bit = %p/%x\n", CpuMpData->WakeupBufferHigh, ApResetVectorSizeAbove1Mb));
+ if (Cr0.Bits.PG != 0) {
+ ApplyRoProtection ((EFI_PHYSICAL_ADDRESS)(UINTN)CpuMpData->WakeupBufferHigh, ALIGN_VALUE (ApResetVectorSizeAbove1Mb, EFI_PAGE_SIZE));
+ }
//
// Save APIC mode for AP to sync
@@ -3484,7 +3494,7 @@ PrepareApLoopCode ( // Make sure that the buffer memory is executable if NX protection is enabled
// for EfiReservedMemoryType.
//
- RemoveNxprotection (Address, EFI_PAGES_TO_SIZE (FuncPages));
+ RemoveNxProtection (Address, EFI_PAGES_TO_SIZE (FuncPages));
}
mReservedTopOfApStack = (UINTN)Address + EFI_PAGES_TO_SIZE (StackPages+FuncPages);
@@ -3492,6 +3502,10 @@ PrepareApLoopCode ( mReservedApLoop.Data = (VOID *)(UINTN)Address;
ASSERT (mReservedApLoop.Data != NULL);
CopyMem (mReservedApLoop.Data, ApLoopFunc, ApLoopFuncSize);
+ if (Cr0.Bits.PG != 0) {
+ ApplyRoProtection (Address, EFI_PAGES_TO_SIZE (FuncPages));
+ }
+
if (!CpuMpData->UseSevEsAPMethod) {
//
// processors without SEV-ES and paging is enabled
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index b30dcb3..60cae3b 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -533,7 +533,7 @@ GetNextMpHandOffHob ( @retval 0 Cannot find free memory below 4GB.
**/
UINTN
-AllocateCodeBuffer (
+AllocateCodePage (
IN UINTN BufferSize
);
@@ -991,14 +991,23 @@ AllocateApLoopCodeBuffer ( /**
Remove Nx protection for the range specific by BaseAddress and Length.
- The PEI implementation uses CpuPageTableLib to change the attribute.
- The DXE implementation uses gDS to change the attribute.
-
@param[in] BaseAddress BaseAddress of the range.
@param[in] Length Length of the range.
**/
VOID
-RemoveNxprotection (
+RemoveNxProtection (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ );
+
+/**
+Add ReadOnly protection to the range specified by BaseAddress and Length.
+
+@param[in] BaseAddress BaseAddress of the range.
+@param[in] Length Length of the range.
+**/
+VOID
+ApplyRoProtection (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINTN Length
);
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c index bb28794..443508f 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c @@ -290,7 +290,7 @@ GetWakeupBuffer ( @retval 0 Cannot find free memory below 4GB.
**/
UINTN
-AllocateCodeBuffer (
+AllocateCodePage (
IN UINTN BufferSize
)
{
@@ -819,31 +819,21 @@ AllocateApLoopCodeBuffer ( }
/**
- Remove Nx protection for the range specific by BaseAddress and Length.
-
- The PEI implementation uses CpuPageTableLib to change the attribute.
- The DXE implementation uses gDS to change the attribute.
+ Determine the Paging Mode that the system is currently
+ using.
- @param[in] BaseAddress BaseAddress of the range.
- @param[in] Length Length of the range.
-**/
-VOID
-RemoveNxprotection (
- IN EFI_PHYSICAL_ADDRESS BaseAddress,
- IN UINTN Length
+ @retval PAGING_MODE
+ **/
+PAGING_MODE
+DetermineCurrentPagingMode (
+ VOID
)
{
- EFI_STATUS Status;
- UINTN PageTable;
- EFI_PHYSICAL_ADDRESS Buffer;
- UINTN BufferSize;
- IA32_MAP_ATTRIBUTE MapAttribute;
- IA32_MAP_ATTRIBUTE MapMask;
PAGING_MODE PagingMode;
IA32_CR4 Cr4;
BOOLEAN Page5LevelSupport;
- UINT32 RegEax;
BOOLEAN Page1GSupport;
+ UINT32 RegEax;
CPUID_EXTENDED_CPU_SIG_EDX RegEdx;
if (sizeof (UINTN) == sizeof (UINT64)) {
@@ -877,12 +867,36 @@ RemoveNxprotection ( PagingMode = PagingPae;
}
+ return PagingMode;
+}
+
+/**
+ Remove Nx protection for the range specific by BaseAddress and Length.
+
+ @param[in] BaseAddress BaseAddress of the range.
+ @param[in] Length Length of the range.
+**/
+VOID
+RemoveNxProtection (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ UINTN PageTable;
+ EFI_PHYSICAL_ADDRESS Buffer;
+ UINTN BufferSize;
+ IA32_MAP_ATTRIBUTE MapAttribute;
+ IA32_MAP_ATTRIBUTE MapMask;
+ PAGING_MODE PagingMode;
+
MapAttribute.Uint64 = 0;
MapMask.Uint64 = 0;
MapMask.Bits.Nx = 1;
PageTable = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64;
BufferSize = 0;
+ PagingMode = DetermineCurrentPagingMode ();
//
// Get required buffer size for changing the pagetable.
//
@@ -903,3 +917,52 @@ RemoveNxprotection ( ASSERT_EFI_ERROR (Status);
AsmWriteCr3 (PageTable);
}
+
+/**
+ Add ReadOnly protection to the range specified by BaseAddress and Length.
+
+ @param[in] BaseAddress BaseAddress of the range.
+ @param[in] Length Length of the range.
+**/
+VOID
+ApplyRoProtection (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ UINTN PageTable;
+ EFI_PHYSICAL_ADDRESS Buffer;
+ UINTN BufferSize;
+ IA32_MAP_ATTRIBUTE MapAttribute;
+ IA32_MAP_ATTRIBUTE MapMask;
+ PAGING_MODE PagingMode;
+
+ MapAttribute.Uint64 = 0;
+ MapMask.Uint64 = 0;
+ MapMask.Bits.ReadWrite = 1;
+ PageTable = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64;
+ BufferSize = 0;
+
+ PagingMode = DetermineCurrentPagingMode ();
+ //
+ // Get required buffer size for changing the pagetable.
+ //
+ Status = PageTableMap (&PageTable, PagingMode, 0, &BufferSize, BaseAddress, Length, &MapAttribute, &MapMask, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Allocate required Buffer.
+ //
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (BufferSize),
+ &Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = PageTableMap (&PageTable, PagingMode, (VOID *)(UINTN)Buffer, &BufferSize, BaseAddress, Length, &MapAttribute, &MapMask, NULL);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ AsmWriteCr3 (PageTable);
+ return;
+}
diff --git a/pip-requirements.txt b/pip-requirements.txt index 93fadfe..d2365e7 100644 --- a/pip-requirements.txt +++ b/pip-requirements.txt @@ -12,8 +12,8 @@ # https://www.python.org/dev/peps/pep-0440/#version-specifiers
##
-edk2-pytool-library~=0.23.0
-edk2-pytool-extensions~=0.29.0
+edk2-pytool-library~=0.23.4
+edk2-pytool-extensions~=0.29.11
antlr4-python3-runtime==4.9
lcov-cobertura==2.1.1
regex==2024.11.6
|