diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c index c6ee74cfdd..7a58d7b23b 100644 --- a/MdeModulePkg/Core/Dxe/Image/Image.c +++ b/MdeModulePkg/Core/Dxe/Image/Image.c @@ -1595,6 +1595,7 @@ CoreStartImage ( UINT64 HandleDatabaseKey; UINTN SetJumpFlag; EFI_HANDLE Handle; + UINT64 Attributes; Handle = ImageHandle; @@ -1686,7 +1687,15 @@ CoreStartImage ( // Call the image's entry point // Image->Started = TRUE; - Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable); + + if (!Image->IsUserImage) { + Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable); + } else { + gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)Image->EntryPoint, &Attributes); + ASSERT ((Attributes & EFI_MEMORY_USER) != 0); + + Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable); + } // // Add some debug information if the image returned with error. diff --git a/MdePkg/Include/Protocol/Cpu.h b/MdePkg/Include/Protocol/Cpu.h index 3d25ad08f8..ccaec43cb4 100644 --- a/MdePkg/Include/Protocol/Cpu.h +++ b/MdePkg/Include/Protocol/Cpu.h @@ -244,12 +244,20 @@ EFI_STATUS typedef EFI_STATUS (EFIAPI *EFI_CPU_SET_MEMORY_ATTRIBUTES)( - IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes ); +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_GET_MEMORY_ATTRIBUTES)( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Address, + OUT UINT64 *Attributes + ); + /// /// The EFI_CPU_ARCH_PROTOCOL is used to abstract processor-specific functions from the DXE /// Foundation. This includes flushing caches, enabling and disabling interrupts, hooking interrupt @@ -279,6 +287,7 @@ struct _EFI_CPU_ARCH_PROTOCOL { /// a read-only field. /// UINT32 DmaBufferAlignment; + EFI_CPU_GET_MEMORY_ATTRIBUTES GetMemoryAttributes; }; extern EFI_GUID gEfiCpuArchProtocolGuid; diff --git a/UefiCpuPkg/Library/CpuArchLib/CpuDxe.c b/UefiCpuPkg/Library/CpuArchLib/CpuDxe.c index 9a26bb5af7..f9fbe05c8d 100644 --- a/UefiCpuPkg/Library/CpuArchLib/CpuDxe.c +++ b/UefiCpuPkg/Library/CpuArchLib/CpuDxe.c @@ -31,7 +31,8 @@ EFI_CPU_ARCH_PROTOCOL gCpuImpl = { CpuGetTimerValue, CpuSetMemoryAttributes, 1, // NumberOfTimers - 4 // DmaBufferAlignment + 4, // DmaBufferAlignment + CpuGetMemoryAttributes }; EFI_HOB_PLATFORM_INFO *mPlatformInfoHob2 = NULL; diff --git a/UefiCpuPkg/Library/CpuArchLib/CpuDxe.h b/UefiCpuPkg/Library/CpuArchLib/CpuDxe.h index 34a865d1dd..731dbd6d13 100644 --- a/UefiCpuPkg/Library/CpuArchLib/CpuDxe.h +++ b/UefiCpuPkg/Library/CpuArchLib/CpuDxe.h @@ -221,6 +221,14 @@ CpuSetMemoryAttributes ( IN UINT64 Attributes ); +EFI_STATUS +EFIAPI +CpuGetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Address, + OUT UINT64 *Attributes + ); + /** Initialize Global Descriptor Table. diff --git a/UefiCpuPkg/Library/CpuArchLib/CpuPageTable.c b/UefiCpuPkg/Library/CpuArchLib/CpuPageTable.c index 35ff6d9dbf..f889efe3d0 100644 --- a/UefiCpuPkg/Library/CpuArchLib/CpuPageTable.c +++ b/UefiCpuPkg/Library/CpuArchLib/CpuPageTable.c @@ -405,6 +405,30 @@ GetAttributesFromPageEntry ( return Attributes; } +EFI_STATUS +EFIAPI +CpuGetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Address, + OUT UINT64 *Attributes + ) +{ + PAGE_TABLE_LIB_PAGING_CONTEXT PagingContext; + PAGE_ATTRIBUTE PageAttribute; + UINT64 *PageEntry; + + GetCurrentPagingContext (&PagingContext); + + PageEntry = GetPageTableEntry (&PagingContext, Address, &PageAttribute); + if (PageEntry == NULL) { + return EFI_NOT_FOUND; + } + + *Attributes = GetAttributesFromPageEntry (PageEntry); + + return EFI_SUCCESS; +} + /** Modify memory attributes of page entry.