audk/MdeModulePkg/Core/Dxe/SysCall/Initialization.c
2025-04-14 13:17:36 +03:00

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;
}