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

1256 lines
31 KiB
C

/** @file
Copyright (c) 2024 - 2025, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "DxeMain.h"
#include "SupportedProtocols.h"
#define MAX_CALL 1
LIST_ENTRY gUserSpaceDriversHead = INITIALIZE_LIST_HEAD_VARIABLE (gUserSpaceDriversHead);
EFI_STATUS
EFIAPI
CallUserSpace (
IN USER_SPACE_CALL_DATA *Data,
IN UINTN UserStackTop
);
EFI_STATUS
EFIAPI
GoToUserSpace (
IN UINT8 Number,
IN VOID *EntryPoint,
IN USER_SPACE_DRIVER *UserDriver,
...
)
{
EFI_STATUS Status;
USER_SPACE_CALL_DATA *Input;
VA_LIST Marker;
UINTN Index;
UINTN UserStackTop;
UINTN UserStackBase;
if (UserDriver->NumberOfCalls > MAX_CALL) {
return EFI_OUT_OF_RESOURCES;
}
UserStackBase = (UINTN)AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));
if (UserStackBase == 0) {
return EFI_OUT_OF_RESOURCES;
}
UserStackTop = UserStackBase + STACK_SIZE - (sizeof (USER_SPACE_CALL_DATA) + Number * sizeof (UINTN));
Input = (USER_SPACE_CALL_DATA *)UserStackTop;
Input->NumberOfArguments = Number;
Input->EntryPoint = EntryPoint;
VA_START (Marker, UserDriver);
for (Index = 0; Index < Number; ++Index) {
Input->Arguments[Index] = VA_ARG (Marker, UINTN);
}
VA_END (Marker);
SetUefiImageMemoryAttributes (UserStackBase, STACK_SIZE, EFI_MEMORY_XP | EFI_MEMORY_USER);
gCpu->SetUserMemoryAttributes (
gCpu,
UserDriver->UserPageTable,
UserStackBase,
STACK_SIZE,
EFI_MEMORY_XP | EFI_MEMORY_USER
);
++UserDriver->NumberOfCalls;
//
// Reserve space on stack for 4 arguments (X64 NOOPT prerequisite).
//
UserStackTop = ALIGN_VALUE (UserStackTop - 8*4 - CPU_STACK_ALIGNMENT, CPU_STACK_ALIGNMENT);
Status = CallUserSpace (
Input,
UserStackTop
);
--UserDriver->NumberOfCalls;
CoreFreePages (UserStackBase, EFI_SIZE_TO_PAGES (STACK_SIZE));
return Status;
}
STATIC
USER_SPACE_DRIVER *
EFIAPI
FindUserSpaceDriver (
IN VOID *CoreWrapper,
OUT UINTN *OldPageTable
)
{
LIST_ENTRY *Link;
USER_SPACE_DRIVER *UserDriver;
ASSERT (OldPageTable != NULL);
for (Link = gUserSpaceDriversHead.ForwardLink; Link != &gUserSpaceDriversHead; Link = Link->ForwardLink) {
UserDriver = BASE_CR (Link, USER_SPACE_DRIVER, Link);
if (UserDriver->CoreWrapper == CoreWrapper) {
*OldPageTable = gUserPageTable;
gUserPageTable = UserDriver->UserPageTable;
return UserDriver;
}
}
return NULL;
}
EFI_STATUS
EFIAPI
CoreDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
AllowSupervisorAccessToUserMemory ();
EntryPoint = (VOID *)This->Supported;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
3,
EntryPoint,
UserDriver,
This,
ControllerHandle,
RemainingDevicePath
);
gUserPageTable = OldPageTable;
return Status;
}
EFI_STATUS
EFIAPI
CoreDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
AllowSupervisorAccessToUserMemory ();
EntryPoint = (VOID *)This->Start;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
3,
EntryPoint,
UserDriver,
This,
ControllerHandle,
RemainingDevicePath
);
gUserPageTable = OldPageTable;
return Status;
}
EFI_STATUS
EFIAPI
CoreDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
)
{
EFI_STATUS Status;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
AllowSupervisorAccessToUserMemory ();
EntryPoint = (VOID *)This->Stop;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
4,
EntryPoint,
UserDriver,
This,
ControllerHandle,
NumberOfChildren,
ChildHandleBuffer
);
gUserPageTable = OldPageTable;
return Status;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileClose (
IN EFI_FILE_PROTOCOL *This
)
{
EFI_STATUS Status;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
AllowSupervisorAccessToUserMemory ();
EntryPoint = (VOID *)This->Close;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
1,
EntryPoint,
UserDriver,
This
);
FreePool (UserDriver->CoreWrapper);
RemoveEntryList (&UserDriver->Link);
FreePool (UserDriver);
gUserPageTable = OldPageTable;
return Status;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileDelete (
IN EFI_FILE_PROTOCOL *This
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileRead (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
EFI_STATUS Status;
UINTN *UserSpaceBufferSize;
VOID *UserSpaceBuffer;
EFI_PHYSICAL_ADDRESS UserSpacePages;
UINT32 PagesNumber;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN OldPageTable;
if ((This == NULL) || (BufferSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// gUserPageTable must be set before alloctation of EfiUserSpaceMemoryType pages.
//
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
UserSpaceBuffer = NULL;
UserSpacePages = 0;
PagesNumber = (UINT32)EFI_SIZE_TO_PAGES (sizeof (UINTN *) + *BufferSize);
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
PagesNumber,
&UserSpacePages
);
if (EFI_ERROR (Status)) {
gUserPageTable = OldPageTable;
return Status;
}
UserSpaceBufferSize = (UINTN *)(UINTN)UserSpacePages;
AllowSupervisorAccessToUserMemory ();
*UserSpaceBufferSize = *BufferSize;
EntryPoint = (VOID *)This->Read;
ForbidSupervisorAccessToUserMemory ();
if (Buffer != NULL) {
UserSpaceBuffer = (VOID *)((UINTN *)(UINTN)UserSpacePages + 1);
}
Status = GoToUserSpace (
3,
EntryPoint,
UserDriver,
This,
UserSpaceBufferSize,
UserSpaceBuffer
);
AllowSupervisorAccessToUserMemory ();
if ((UserSpaceBuffer != NULL) && (Buffer != NULL) && (*BufferSize >= *UserSpaceBufferSize)) {
CopyMem (Buffer, UserSpaceBuffer, *UserSpaceBufferSize);
}
*BufferSize = *UserSpaceBufferSize;
ForbidSupervisorAccessToUserMemory ();
CoreFreePages (UserSpacePages, PagesNumber);
gUserPageTable = OldPageTable;
return Status;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileWrite (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileSetPosition (
IN EFI_FILE_PROTOCOL *This,
IN UINT64 Position
)
{
EFI_STATUS Status;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
AllowSupervisorAccessToUserMemory ();
EntryPoint = (VOID *)This->SetPosition;
ForbidSupervisorAccessToUserMemory ();
#if defined (MDE_CPU_X64) || defined (MDE_CPU_AARCH64)
Status = GoToUserSpace (
2,
EntryPoint,
UserDriver,
This,
Position
);
#elif defined (MDE_CPU_IA32)
//
// UINT64 Position is passed as 2 double words on stack.
//
Status = GoToUserSpace (
3,
EntryPoint,
UserDriver,
This,
Position
);
#elif defined (MDE_CPU_ARM)
//
// UINT64 Position is passed as 2 words in 2 registers and is aligned on 8 bytes.
// R0 == This, R1 == NULL, R2 == Position_Low, R3 == Position_High.
//
Status = GoToUserSpace (
4,
EntryPoint,
UserDriver,
This,
NULL,
(UINT32)Position,
(UINT32)(Position >> 32)
);
#endif
gUserPageTable = OldPageTable;
return Status;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileGetPosition (
IN EFI_FILE_PROTOCOL *This,
OUT UINT64 *Position
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS UserSpacePosition;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN OldPageTable;
if ((This == NULL) || (Position == NULL)) {
return EFI_INVALID_PARAMETER;
}
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
1,
&UserSpacePosition
);
if (EFI_ERROR (Status)) {
gUserPageTable = OldPageTable;
return Status;
}
AllowSupervisorAccessToUserMemory ();
*(UINT64 *)(UINTN)UserSpacePosition = *Position;
EntryPoint = (VOID *)This->GetPosition;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
2,
EntryPoint,
UserDriver,
This,
UserSpacePosition
);
AllowSupervisorAccessToUserMemory ();
*Position = *(UINT64 *)(UINTN)UserSpacePosition;
ForbidSupervisorAccessToUserMemory ();
CoreFreePages (UserSpacePosition, 1);
gUserPageTable = OldPageTable;
return Status;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileGetInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
EFI_STATUS Status;
EFI_GUID *UserSpaceInformationType;
UINTN *UserSpaceBufferSize;
VOID *UserSpaceBuffer;
EFI_PHYSICAL_ADDRESS UserSpacePages;
UINT32 PagesNumber;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN OldPageTable;
if ((This == NULL) || (BufferSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
UserSpaceBuffer = NULL;
UserSpaceInformationType = NULL;
UserSpacePages = 0;
PagesNumber = (UINT32)EFI_SIZE_TO_PAGES (sizeof (UINTN *) + *BufferSize + sizeof (EFI_GUID));
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
PagesNumber,
&UserSpacePages
);
if (EFI_ERROR (Status)) {
gUserPageTable = OldPageTable;
return Status;
}
UserSpaceBufferSize = (UINTN *)(UINTN)UserSpacePages;
AllowSupervisorAccessToUserMemory ();
*UserSpaceBufferSize = *BufferSize;
EntryPoint = (VOID *)This->GetInfo;
ForbidSupervisorAccessToUserMemory ();
if (Buffer != NULL) {
UserSpaceBuffer = (VOID *)((UINTN *)(UINTN)UserSpacePages + 1);
}
if (InformationType != NULL) {
UserSpaceInformationType = (EFI_GUID *)((UINTN)UserSpacePages + sizeof (UINTN *) + *BufferSize);
AllowSupervisorAccessToUserMemory ();
CopyGuid (UserSpaceInformationType, InformationType);
ForbidSupervisorAccessToUserMemory ();
}
Status = GoToUserSpace (
4,
EntryPoint,
UserDriver,
This,
UserSpaceInformationType,
UserSpaceBufferSize,
UserSpaceBuffer
);
AllowSupervisorAccessToUserMemory ();
if ((UserSpaceBuffer != NULL) && (Buffer != NULL) && (*BufferSize >= *UserSpaceBufferSize)) {
CopyMem (Buffer, UserSpaceBuffer, *UserSpaceBufferSize);
}
*BufferSize = *UserSpaceBufferSize;
ForbidSupervisorAccessToUserMemory ();
CoreFreePages (UserSpacePages, PagesNumber);
gUserPageTable = OldPageTable;
return Status;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileSetInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileFlush (
IN EFI_FILE_PROTOCOL *This
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileOpenEx (
IN EFI_FILE_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes,
IN OUT EFI_FILE_IO_TOKEN *Token
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileReadEx (
IN EFI_FILE_PROTOCOL *This,
IN OUT EFI_FILE_IO_TOKEN *Token
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileWriteEx (
IN EFI_FILE_PROTOCOL *This,
IN OUT EFI_FILE_IO_TOKEN *Token
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileFlushEx (
IN EFI_FILE_PROTOCOL *This,
IN OUT EFI_FILE_IO_TOKEN *Token
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
CoreFileOpen (
IN EFI_FILE_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
{
EFI_STATUS Status;
EFI_FILE_PROTOCOL *NewFile;
EFI_FILE_PROTOCOL **UserSpaceNewHandle;
CHAR16 *UserSpaceFileName;
EFI_PHYSICAL_ADDRESS UserSpacePages;
UINT32 PagesNumber;
USER_SPACE_DRIVER *UserDriver;
USER_SPACE_DRIVER *NewDriver;
VOID *EntryPoint;
UINTN OldPageTable;
if ((This == NULL) || (NewHandle == NULL) || (FileName == NULL)) {
return EFI_INVALID_PARAMETER;
}
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
UserSpaceNewHandle = NULL;
UserSpaceFileName = NULL;
UserSpacePages = 0;
PagesNumber = (UINT32)EFI_SIZE_TO_PAGES (sizeof (EFI_FILE_PROTOCOL *) + StrSize (FileName));
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
PagesNumber,
&UserSpacePages
);
if (EFI_ERROR (Status)) {
*NewHandle = NULL;
gUserPageTable = OldPageTable;
return Status;
}
UserSpaceNewHandle = (EFI_FILE_PROTOCOL **)(UINTN)UserSpacePages;
UserSpaceFileName = (CHAR16 *)((EFI_FILE_PROTOCOL **)(UINTN)UserSpacePages + 1);
AllowSupervisorAccessToUserMemory ();
Status = StrCpyS (UserSpaceFileName, StrLen (FileName) + 1, FileName);
EntryPoint = (VOID *)This->Open;
ForbidSupervisorAccessToUserMemory ();
if (EFI_ERROR (Status)) {
*NewHandle = NULL;
CoreFreePages (UserSpacePages, PagesNumber);
gUserPageTable = OldPageTable;
return Status;
}
#if defined (MDE_CPU_X64) || defined (MDE_CPU_AARCH64)
Status = GoToUserSpace (
5,
EntryPoint,
UserDriver,
This,
UserSpaceNewHandle,
UserSpaceFileName,
OpenMode,
Attributes
);
#elif defined (MDE_CPU_IA32)
//
// UINT64 OpenMode and Attributes are each passed as 2 double words on stack.
//
Status = GoToUserSpace (
7,
EntryPoint,
UserDriver,
This,
UserSpaceNewHandle,
UserSpaceFileName,
OpenMode,
Attributes
);
#elif defined (MDE_CPU_ARM)
//
// UINT64 OpenMode and Attributes are each passed as 2 words on stack.
// Each of them is aligned on 8 bytes.
// R0 == This, R1 == UserSpaceNewHandle, R2 == UserSpaceFileName, R3 == NULL,
// [SP] == OpenMode, [SP + 8] == Attributes.
//
Status = GoToUserSpace (
8,
EntryPoint,
UserDriver,
This,
UserSpaceNewHandle,
UserSpaceFileName,
NULL,
(UINT32)OpenMode,
(UINT32)(OpenMode >> 32),
(UINT32)Attributes,
(UINT32)(Attributes >> 32)
);
#endif
if (EFI_ERROR (Status)) {
*NewHandle = NULL;
CoreFreePages (UserSpacePages, PagesNumber);
gUserPageTable = OldPageTable;
return Status;
}
NewFile = AllocatePool (sizeof (EFI_FILE_PROTOCOL));
if (NewFile == NULL) {
*NewHandle = NULL;
CoreFreePages (UserSpacePages, PagesNumber);
gUserPageTable = OldPageTable;
return EFI_OUT_OF_RESOURCES;
}
NewDriver = AllocatePool (sizeof (USER_SPACE_DRIVER));
if (NewDriver == NULL) {
*NewHandle = NULL;
FreePool (NewFile);
CoreFreePages (UserSpacePages, PagesNumber);
gUserPageTable = OldPageTable;
return EFI_OUT_OF_RESOURCES;
}
NewDriver->CoreWrapper = NewFile;
NewDriver->UserPageTable = UserDriver->UserPageTable;
NewDriver->NumberOfCalls = 0;
AllowSupervisorAccessToUserMemory ();
NewDriver->UserSpaceDriver = *UserSpaceNewHandle;
NewFile->Revision = (*UserSpaceNewHandle)->Revision;
ForbidSupervisorAccessToUserMemory ();
InsertTailList (&gUserSpaceDriversHead, &NewDriver->Link);
NewFile->Open = CoreFileOpen;
NewFile->Close = CoreFileClose;
NewFile->Delete = CoreFileDelete;
NewFile->Read = CoreFileRead;
NewFile->Write = CoreFileWrite;
NewFile->GetPosition = CoreFileGetPosition;
NewFile->SetPosition = CoreFileSetPosition;
NewFile->GetInfo = CoreFileGetInfo;
NewFile->SetInfo = CoreFileSetInfo;
NewFile->Flush = CoreFileFlush;
NewFile->OpenEx = CoreFileOpenEx;
NewFile->ReadEx = CoreFileReadEx;
NewFile->WriteEx = CoreFileWriteEx;
NewFile->FlushEx = CoreFileFlushEx;
*NewHandle = (EFI_FILE_PROTOCOL *)NewFile;
CoreFreePages (UserSpacePages, PagesNumber);
gUserPageTable = OldPageTable;
return Status;
}
EFI_STATUS
EFIAPI
CoreSimpleFileSystemOpenVolume (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **Root
)
{
EFI_STATUS Status;
EFI_FILE_PROTOCOL **UserSpaceRoot;
EFI_FILE_PROTOCOL *File;
EFI_PHYSICAL_ADDRESS Physical;
USER_SPACE_DRIVER *UserDriver;
USER_SPACE_DRIVER *NewDriver;
VOID *EntryPoint;
UINTN OldPageTable;
if (Root == NULL) {
return EFI_INVALID_PARAMETER;
}
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
AllowSupervisorAccessToUserMemory ();
EntryPoint = (VOID *)This->OpenVolume;
ForbidSupervisorAccessToUserMemory ();
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
1,
&Physical
);
if (EFI_ERROR (Status)) {
*Root = NULL;
gUserPageTable = OldPageTable;
return Status;
}
UserSpaceRoot = (EFI_FILE_PROTOCOL **)(UINTN)Physical;
Status = GoToUserSpace (
2,
EntryPoint,
UserDriver,
This,
UserSpaceRoot
);
if (EFI_ERROR (Status)) {
*Root = NULL;
CoreFreePages (Physical, 1);
gUserPageTable = OldPageTable;
return Status;
}
File = AllocatePool (sizeof (EFI_FILE_PROTOCOL));
if (File == NULL) {
*Root = NULL;
CoreFreePages (Physical, 1);
gUserPageTable = OldPageTable;
return EFI_OUT_OF_RESOURCES;
}
NewDriver = AllocatePool (sizeof (USER_SPACE_DRIVER));
if (NewDriver == NULL) {
*Root = NULL;
FreePool (File);
CoreFreePages (Physical, 1);
gUserPageTable = OldPageTable;
return EFI_OUT_OF_RESOURCES;
}
NewDriver->CoreWrapper = File;
NewDriver->UserPageTable = UserDriver->UserPageTable;
NewDriver->NumberOfCalls = 0;
AllowSupervisorAccessToUserMemory ();
NewDriver->UserSpaceDriver = *UserSpaceRoot;
File->Revision = (*UserSpaceRoot)->Revision;
ForbidSupervisorAccessToUserMemory ();
InsertTailList (&gUserSpaceDriversHead, &NewDriver->Link);
File->Open = CoreFileOpen;
File->Close = CoreFileClose;
File->Delete = CoreFileDelete;
File->Read = CoreFileRead;
File->Write = CoreFileWrite;
File->GetPosition = CoreFileGetPosition;
File->SetPosition = CoreFileSetPosition;
File->GetInfo = CoreFileGetInfo;
File->SetInfo = CoreFileSetInfo;
File->Flush = CoreFileFlush;
File->OpenEx = CoreFileOpenEx;
File->ReadEx = CoreFileReadEx;
File->WriteEx = CoreFileWriteEx;
File->FlushEx = CoreFileFlushEx;
*Root = (EFI_FILE_PROTOCOL *)File;
CoreFreePages (Physical, 1);
gUserPageTable = OldPageTable;
return Status;
}
INTN
EFIAPI
CoreUnicodeCollationStriColl (
IN EFI_UNICODE_COLLATION_PROTOCOL *This,
IN CHAR16 *Str1,
IN CHAR16 *Str2
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS UserMem;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN Size1;
UINTN Size2;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
Size1 = StrSize (Str1);
Size2 = StrSize (Str2);
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
EFI_SIZE_TO_PAGES (Size1 + Size2),
&UserMem
);
if (EFI_ERROR (Status)) {
gUserPageTable = OldPageTable;
return 0;
}
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)(UINTN)UserMem, (VOID *)Str1, Size1);
CopyMem ((VOID *)((UINTN)UserMem + Size1), (VOID *)Str2, Size2);
EntryPoint = (VOID *)This->StriColl;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
3,
EntryPoint,
UserDriver,
This,
(UINTN)UserMem,
(UINTN)UserMem + Size1
);
CoreFreePages (UserMem, EFI_SIZE_TO_PAGES (Size1 + Size2));
gUserPageTable = OldPageTable;
return (INTN)Status;
}
BOOLEAN
EFIAPI
CoreUnicodeCollationMetaiMatch (
IN EFI_UNICODE_COLLATION_PROTOCOL *This,
IN CHAR16 *String,
IN CHAR16 *Pattern
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS UserMem;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN Size1;
UINTN Size2;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
Size1 = StrSize (String);
Size2 = StrSize (Pattern);
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
EFI_SIZE_TO_PAGES (Size1 + Size2),
&UserMem
);
if (EFI_ERROR (Status)) {
gUserPageTable = OldPageTable;
return FALSE;
}
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)(UINTN)UserMem, (VOID *)String, Size1);
CopyMem ((VOID *)((UINTN)UserMem + Size1), (VOID *)Pattern, Size2);
EntryPoint = (VOID *)This->MetaiMatch;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
3,
EntryPoint,
UserDriver,
This,
(UINTN)UserMem,
(UINTN)UserMem + Size1
);
CoreFreePages (UserMem, EFI_SIZE_TO_PAGES (Size1 + Size2));
gUserPageTable = OldPageTable;
return (BOOLEAN)Status;
}
VOID
EFIAPI
CoreUnicodeCollationStrLwr (
IN EFI_UNICODE_COLLATION_PROTOCOL *This,
IN OUT CHAR16 *Str
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS UserMem;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN Size1;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
Size1 = StrSize (Str);
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
EFI_SIZE_TO_PAGES (Size1),
&UserMem
);
if (EFI_ERROR (Status)) {
gUserPageTable = OldPageTable;
return;
}
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)(UINTN)UserMem, (VOID *)Str, Size1);
EntryPoint = (VOID *)This->StrLwr;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
2,
EntryPoint,
UserDriver,
This,
(UINTN)UserMem
);
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)Str, (VOID *)(UINTN)UserMem, Size1);
ForbidSupervisorAccessToUserMemory ();
CoreFreePages (UserMem, EFI_SIZE_TO_PAGES (Size1));
gUserPageTable = OldPageTable;
}
VOID
EFIAPI
CoreUnicodeCollationStrUpr (
IN EFI_UNICODE_COLLATION_PROTOCOL *This,
IN OUT CHAR16 *Str
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS UserMem;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN Size1;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
Size1 = StrSize (Str);
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
EFI_SIZE_TO_PAGES (Size1),
&UserMem
);
if (EFI_ERROR (Status)) {
gUserPageTable = OldPageTable;
return;
}
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)(UINTN)UserMem, (VOID *)Str, Size1);
EntryPoint = (VOID *)This->StrUpr;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
2,
EntryPoint,
UserDriver,
This,
(UINTN)UserMem
);
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)Str, (VOID *)(UINTN)UserMem, Size1);
ForbidSupervisorAccessToUserMemory ();
CoreFreePages (UserMem, EFI_SIZE_TO_PAGES (Size1));
gUserPageTable = OldPageTable;
}
VOID
EFIAPI
CoreUnicodeCollationFatToStr (
IN EFI_UNICODE_COLLATION_PROTOCOL *This,
IN UINTN FatSize,
IN CHAR8 *Fat,
OUT CHAR16 *String
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS UserMem;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
EFI_SIZE_TO_PAGES (FatSize * 3),
&UserMem
);
if (EFI_ERROR (Status)) {
gUserPageTable = OldPageTable;
return;
}
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)(UINTN)UserMem, (VOID *)Fat, FatSize);
EntryPoint = (VOID *)This->FatToStr;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
4,
EntryPoint,
UserDriver,
This,
FatSize,
(UINTN)UserMem,
(UINTN)UserMem + FatSize
);
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)String, (VOID *)((UINTN)UserMem + FatSize), FatSize * 2);
ForbidSupervisorAccessToUserMemory ();
CoreFreePages (UserMem, EFI_SIZE_TO_PAGES (FatSize * 3));
gUserPageTable = OldPageTable;
}
BOOLEAN
EFIAPI
CoreUnicodeCollationStrToFat (
IN EFI_UNICODE_COLLATION_PROTOCOL *This,
IN CHAR16 *String,
IN UINTN FatSize,
OUT CHAR8 *Fat
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS UserMem;
USER_SPACE_DRIVER *UserDriver;
VOID *EntryPoint;
UINTN Size1;
UINTN OldPageTable;
UserDriver = FindUserSpaceDriver (This, &OldPageTable);
ASSERT (UserDriver != NULL);
This = UserDriver->UserSpaceDriver;
Size1 = StrSize (String);
Status = CoreAllocatePages (
AllocateAnyPages,
EfiUserSpaceMemoryType,
EFI_SIZE_TO_PAGES (FatSize + Size1),
&UserMem
);
if (EFI_ERROR (Status)) {
gUserPageTable = OldPageTable;
return FALSE;
}
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)(UINTN)UserMem, (VOID *)String, Size1);
EntryPoint = (VOID *)This->StrToFat;
ForbidSupervisorAccessToUserMemory ();
Status = GoToUserSpace (
4,
EntryPoint,
UserDriver,
This,
(UINTN)UserMem,
FatSize,
(UINTN)UserMem + Size1
);
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)Fat, (VOID *)((UINTN)UserMem + Size1), FatSize);
ForbidSupervisorAccessToUserMemory ();
CoreFreePages (UserMem, EFI_SIZE_TO_PAGES (FatSize + Size1));
gUserPageTable = OldPageTable;
return (BOOLEAN)Status;
}