mirror of
https://github.com/acidanthera/audk.git
synced 2025-08-23 02:28:08 +02:00
260 lines
6.8 KiB
C
260 lines
6.8 KiB
C
/** @file
|
|
|
|
Copyright (c) 2024 - 2025, Mikhail Krichanov. All rights reserved.
|
|
SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
**/
|
|
|
|
#include "DxeMain.h"
|
|
|
|
VOID *gUserSpaceEntryPoint;
|
|
USER_SPACE_DATA *gUserSpaceData;
|
|
VOID *gUserSpaceInterfaces;
|
|
|
|
EXCEPTION_ADDRESSES *mExceptionAddresses;
|
|
extern UINTN SysCallBase;
|
|
extern UINTN SysCallEnd;
|
|
|
|
STATIC UEFI_IMAGE_RECORD *mDxeUserSpace;
|
|
STATIC EFI_PHYSICAL_ADDRESS mCoreStackBase;
|
|
STATIC UINT64 mCoreStackSize;
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MakeUserPageTableTemplate (
|
|
OUT UINTN *UserPageTableTemplate,
|
|
OUT UINTN *UserPageTableTemplateSize
|
|
);
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InitializePlatform (
|
|
IN OUT EFI_SYSTEM_TABLE *System
|
|
);
|
|
|
|
VOID
|
|
EFIAPI
|
|
MapPlatform (
|
|
IN OUT UINTN UserPageTable
|
|
);
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InitializeUserSpace (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN LOADED_IMAGE_PRIVATE_DATA *Image
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_PHYSICAL_ADDRESS Physical;
|
|
EFI_PEI_HOB_POINTERS PeiHob;
|
|
EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
|
|
|
|
//
|
|
// Set UserSpace EntryPoint and BootServices.
|
|
//
|
|
Status = CoreAllocatePages (
|
|
AllocateAnyPages,
|
|
EfiUserSpaceMemoryType,
|
|
EFI_SIZE_TO_PAGES (sizeof (USER_SPACE_DATA)),
|
|
&Physical
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
gUserSpaceData = (USER_SPACE_DATA *)(UINTN)Physical;
|
|
|
|
CopyMem ((VOID *)gUserSpaceData, (VOID *)Image->Info.SystemTable, sizeof (EFI_SYSTEM_TABLE));
|
|
|
|
SetUefiImageMemoryAttributes (
|
|
(UINTN)gUserSpaceData,
|
|
ALIGN_VALUE (sizeof (USER_SPACE_DATA), EFI_PAGE_SIZE),
|
|
EFI_MEMORY_XP | EFI_MEMORY_USER
|
|
);
|
|
|
|
Status = InitializePlatform (&gUserSpaceData->SystemTable);
|
|
if (EFI_ERROR (Status)) {
|
|
CoreFreePages (
|
|
(EFI_PHYSICAL_ADDRESS)(UINTN)gUserSpaceData,
|
|
EFI_SIZE_TO_PAGES (sizeof (USER_SPACE_DATA))
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Initialize DxeUserSpace with Supervisor privileges.
|
|
//
|
|
mDxeUserSpace = GetUefiImageRecord (Image);
|
|
ASSERT (mDxeUserSpace != NULL);
|
|
|
|
SetUefiImageProtectionAttributes (mDxeUserSpace, FALSE);
|
|
|
|
AllowSupervisorAccessToUserMemory ();
|
|
Status = Image->EntryPoint (ImageHandle, (EFI_SYSTEM_TABLE *)gUserSpaceData);
|
|
|
|
gUserSpaceEntryPoint = gUserSpaceData->EntryPoint;
|
|
|
|
gUserSpaceData->SystemTable.BootServices = gUserSpaceData->BootServices;
|
|
gUserSpaceData->SystemTable.RuntimeServices = gUserSpaceData->RuntimeServices;
|
|
ForbidSupervisorAccessToUserMemory ();
|
|
|
|
SetUefiImageProtectionAttributes (mDxeUserSpace, TRUE);
|
|
|
|
Status = CoreAllocatePages (
|
|
AllocateAnyPages,
|
|
EfiUserSpaceMemoryType,
|
|
USER_SPACE_INTERFACES_PAGES,
|
|
&Physical
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
CoreFreePages (
|
|
(EFI_PHYSICAL_ADDRESS)(UINTN)gUserSpaceData,
|
|
EFI_SIZE_TO_PAGES (sizeof (USER_SPACE_DATA))
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
gUserSpaceInterfaces = (VOID *)(UINTN)Physical;
|
|
|
|
SetUefiImageMemoryAttributes (
|
|
(UINTN)gUserSpaceInterfaces,
|
|
EFI_PAGES_TO_SIZE (USER_SPACE_INTERFACES_PAGES),
|
|
EFI_MEMORY_XP | EFI_MEMORY_USER
|
|
);
|
|
|
|
mExceptionAddresses = GetExceptionAddresses ();
|
|
|
|
PeiHob.Raw = GetHobList ();
|
|
while ((PeiHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, PeiHob.Raw)) != NULL) {
|
|
MemoryHob = PeiHob.MemoryAllocation;
|
|
if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) {
|
|
mCoreStackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress;
|
|
mCoreStackSize = MemoryHob->AllocDescriptor.MemoryLength;
|
|
break;
|
|
}
|
|
|
|
PeiHob.Raw = GET_NEXT_HOB (PeiHob);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
UINTN
|
|
EFIAPI
|
|
InitializeUserPageTable (
|
|
IN LOADED_IMAGE_PRIVATE_DATA *Image
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN UserPageTable;
|
|
UINTN UserPageTableSize;
|
|
UEFI_IMAGE_RECORD_SEGMENT *ImageRecordSegment;
|
|
UINTN SectionAddress;
|
|
UINT32 Index;
|
|
UEFI_IMAGE_RECORD *UserImageRecord;
|
|
|
|
Status = MakeUserPageTableTemplate (&UserPageTable, &UserPageTableSize);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "Core: Failed to initialize User page table - %r.\n", Status));
|
|
CpuDeadLoop ();
|
|
}
|
|
|
|
//
|
|
// Map gUserSpaceData, gUserSpaceInterfaces, DxeUserSpace
|
|
//
|
|
gCpu->SetUserMemoryAttributes (
|
|
gCpu,
|
|
UserPageTable,
|
|
(UINTN)gUserSpaceData,
|
|
ALIGN_VALUE (sizeof (USER_SPACE_DATA), EFI_PAGE_SIZE),
|
|
EFI_MEMORY_XP | EFI_MEMORY_USER
|
|
);
|
|
|
|
gCpu->SetUserMemoryAttributes (
|
|
gCpu,
|
|
UserPageTable,
|
|
(UINTN)gUserSpaceInterfaces,
|
|
EFI_PAGES_TO_SIZE (USER_SPACE_INTERFACES_PAGES),
|
|
EFI_MEMORY_XP | EFI_MEMORY_USER
|
|
);
|
|
|
|
SectionAddress = mDxeUserSpace->StartAddress;
|
|
for (Index = 0; Index < mDxeUserSpace->NumSegments; Index++) {
|
|
ImageRecordSegment = &mDxeUserSpace->Segments[Index];
|
|
|
|
gCpu->SetUserMemoryAttributes (
|
|
gCpu,
|
|
UserPageTable,
|
|
SectionAddress,
|
|
ImageRecordSegment->Size,
|
|
ImageRecordSegment->Attributes | EFI_MEMORY_USER
|
|
);
|
|
|
|
SectionAddress += ImageRecordSegment->Size;
|
|
}
|
|
|
|
//
|
|
// Map CoreBootServices, CoreStackBase
|
|
//
|
|
gCpu->SetUserMemoryAttributes (
|
|
gCpu,
|
|
UserPageTable,
|
|
(UINTN)&SysCallBase,
|
|
(UINTN)&SysCallEnd - (UINTN)&SysCallBase,
|
|
EFI_MEMORY_RO
|
|
);
|
|
|
|
gCpu->SetUserMemoryAttributes (
|
|
gCpu,
|
|
UserPageTable,
|
|
mCoreStackBase,
|
|
mCoreStackSize,
|
|
EFI_MEMORY_XP
|
|
);
|
|
|
|
//
|
|
// Map ExceptionHandlers
|
|
//
|
|
gCpu->SetUserMemoryAttributes (
|
|
gCpu,
|
|
UserPageTable,
|
|
mExceptionAddresses->ExceptionHandlerBase,
|
|
mExceptionAddresses->ExceptionHandlerSize,
|
|
EFI_MEMORY_RO
|
|
);
|
|
|
|
gCpu->SetUserMemoryAttributes (
|
|
gCpu,
|
|
UserPageTable,
|
|
mExceptionAddresses->ExceptionDataBase,
|
|
SIZE_4KB,
|
|
EFI_MEMORY_XP
|
|
);
|
|
|
|
MapPlatform (UserPageTable);
|
|
|
|
//
|
|
// Map User Image
|
|
//
|
|
UserImageRecord = GetUefiImageRecord (Image);
|
|
ASSERT (UserImageRecord != NULL);
|
|
|
|
SectionAddress = UserImageRecord->StartAddress;
|
|
for (Index = 0; Index < UserImageRecord->NumSegments; Index++) {
|
|
ImageRecordSegment = &UserImageRecord->Segments[Index];
|
|
|
|
gCpu->SetUserMemoryAttributes (
|
|
gCpu,
|
|
UserPageTable,
|
|
SectionAddress,
|
|
ImageRecordSegment->Size,
|
|
ImageRecordSegment->Attributes | EFI_MEMORY_USER
|
|
);
|
|
|
|
SectionAddress += ImageRecordSegment->Size;
|
|
}
|
|
|
|
return UserPageTable;
|
|
}
|