mirror of
https://github.com/reactos/reactos.git
synced 2024-11-01 12:26:32 +00:00
9393fc320e
Excluded: 3rd-party code (incl. wine) and most of the win32ss.
2593 lines
72 KiB
C
2593 lines
72 KiB
C
/*
|
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
|
* PROJECT: ReactOS UEFI Boot Library
|
|
* FILE: boot/environ/lib/firmware/efi/firmware.c
|
|
* PURPOSE: Boot Library Firmware Initialization for EFI
|
|
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include "bl.h"
|
|
|
|
/* DATA VARIABLES ************************************************************/
|
|
|
|
PBL_FIRMWARE_DESCRIPTOR EfiFirmwareParameters;
|
|
BL_FIRMWARE_DESCRIPTOR EfiFirmwareData;
|
|
EFI_HANDLE EfiImageHandle;
|
|
EFI_SYSTEM_TABLE* EfiSystemTable;
|
|
|
|
EFI_SYSTEM_TABLE *EfiST;
|
|
EFI_BOOT_SERVICES *EfiBS;
|
|
EFI_RUNTIME_SERVICES *EfiRT;
|
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *EfiConOut;
|
|
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *EfiConIn;
|
|
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *EfiConInEx;
|
|
PHYSICAL_ADDRESS EfiRsdt;
|
|
|
|
EFI_GUID EfiGraphicsOutputProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
|
EFI_GUID EfiUgaDrawProtocol = EFI_UGA_DRAW_PROTOCOL_GUID;
|
|
EFI_GUID EfiLoadedImageProtocol = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
|
EFI_GUID EfiDevicePathProtocol = EFI_DEVICE_PATH_PROTOCOL_GUID;
|
|
EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
|
|
EFI_GUID EfiBlockIoProtocol = EFI_BLOCK_IO_PROTOCOL_GUID;
|
|
EFI_GUID EfiRootAcpiTableGuid = EFI_ACPI_20_TABLE_GUID;
|
|
EFI_GUID EfiRootAcpiTable10Guid = EFI_ACPI_TABLE_GUID;
|
|
EFI_GUID EfiGlobalVariable = EFI_GLOBAL_VARIABLE;
|
|
EFI_GUID BlpEfiSecureBootPrivateNamespace = { 0x77FA9ABD , 0x0359, 0x4D32, { 0xBD, 0x60, 0x28, 0xF4, 0xE7, 0x8F, 0x78, 0x4B } };
|
|
|
|
WCHAR BlScratchBuffer[8192];
|
|
|
|
BOOLEAN BlpFirmwareChecked;
|
|
BOOLEAN BlpFirmwareEnabled;
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
EFI_DEVICE_PATH *
|
|
EfiIsDevicePathParent (
|
|
_In_ EFI_DEVICE_PATH *DevicePath1,
|
|
_In_ EFI_DEVICE_PATH *DevicePath2
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH* CurrentPath1;
|
|
EFI_DEVICE_PATH* CurrentPath2;
|
|
USHORT Length1, Length2;
|
|
|
|
/* Start with the current nodes */
|
|
CurrentPath1 = DevicePath1;
|
|
CurrentPath2 = DevicePath2;
|
|
|
|
/* Loop each element of the device path */
|
|
while (!(IsDevicePathEndType(CurrentPath1)) &&
|
|
!(IsDevicePathEndType(CurrentPath2)))
|
|
{
|
|
/* Check if the element has a different length */
|
|
Length1 = DevicePathNodeLength(CurrentPath1);
|
|
Length2 = DevicePathNodeLength(CurrentPath2);
|
|
if (Length1 != Length2)
|
|
{
|
|
/* Then they're not related */
|
|
return NULL;
|
|
}
|
|
|
|
/* Check if the rest of the element data matches */
|
|
if (RtlCompareMemory(CurrentPath1, CurrentPath2, Length1) != Length1)
|
|
{
|
|
/* Nope, not related */
|
|
return NULL;
|
|
}
|
|
|
|
/* Move to the next element */
|
|
CurrentPath1 = NextDevicePathNode(CurrentPath1);
|
|
CurrentPath2 = NextDevicePathNode(CurrentPath2);
|
|
}
|
|
|
|
/* If the last element in path 1 is empty, then path 2 is the child (deeper) */
|
|
if (!IsDevicePathEndType(CurrentPath1))
|
|
{
|
|
return DevicePath2;
|
|
}
|
|
|
|
/* If the last element in path 2 is empty, then path 1 is the child (deeper) */
|
|
if (!IsDevicePathEndType(CurrentPath2))
|
|
{
|
|
return DevicePath1;
|
|
}
|
|
|
|
/* They're both the end, so they're identical, so there's no parent */
|
|
return NULL;
|
|
}
|
|
|
|
EFI_DEVICE_PATH*
|
|
EfiGetLeafNode (
|
|
_In_ EFI_DEVICE_PATH *DevicePath
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH *NextDevicePath;
|
|
|
|
/* Make sure we're not already at the end */
|
|
if (!IsDevicePathEndType(DevicePath))
|
|
{
|
|
/* Grab the next node element, and keep going until the end */
|
|
for (NextDevicePath = NextDevicePathNode(DevicePath);
|
|
!IsDevicePathEndType(NextDevicePath);
|
|
NextDevicePath = NextDevicePathNode(NextDevicePath))
|
|
{
|
|
/* Save the current node we're at */
|
|
DevicePath = NextDevicePath;
|
|
}
|
|
}
|
|
|
|
/* This now contains the deepest (leaf) node */
|
|
return DevicePath;
|
|
}
|
|
|
|
VOID
|
|
EfiPrintf (
|
|
_In_ PWCHAR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list args;
|
|
va_start(args, Format);
|
|
|
|
/* Capture the buffer in our scratch pad, and NULL-terminate */
|
|
vsnwprintf(BlScratchBuffer, RTL_NUMBER_OF(BlScratchBuffer) - 1, Format, args);
|
|
BlScratchBuffer[RTL_NUMBER_OF(BlScratchBuffer) - 1] = UNICODE_NULL;
|
|
|
|
/* Check which mode we're in */
|
|
if (CurrentExecutionContext->Mode == BlRealMode)
|
|
{
|
|
/* Call EFI directly */
|
|
EfiConOut->OutputString(EfiConOut, BlScratchBuffer);
|
|
}
|
|
else
|
|
{
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
|
|
/* Call EFI directly */
|
|
if (EfiConOut != NULL)
|
|
{
|
|
EfiConOut->OutputString(EfiConOut, BlScratchBuffer);
|
|
}
|
|
|
|
/* Switch back to protected mode */
|
|
BlpArchSwitchContext(BlProtectedMode);
|
|
}
|
|
|
|
/* All done */
|
|
va_end(args);
|
|
}
|
|
|
|
BOOLEAN EfiProtHashTableInitialized;
|
|
ULONG EfiProtHashTableId;
|
|
|
|
typedef struct _BL_EFI_PROTOCOL
|
|
{
|
|
LIST_ENTRY ListEntry;
|
|
EFI_GUID* Protocol;
|
|
PVOID Interface;
|
|
LONG ReferenceCount;
|
|
BOOLEAN AddressMapped;
|
|
} BL_EFI_PROTOCOL, *PBL_EFI_PROTOCOL;
|
|
|
|
NTSTATUS
|
|
EfiVmOpenProtocol (
|
|
_In_ EFI_HANDLE Handle,
|
|
_In_ EFI_GUID* Protocol,
|
|
_Outptr_ PVOID* Interface
|
|
)
|
|
{
|
|
BOOLEAN AddressMapped;
|
|
PLIST_ENTRY HashList, NextEntry;
|
|
PHYSICAL_ADDRESS InterfaceAddress, TranslatedAddress;
|
|
NTSTATUS Status;
|
|
BL_HASH_ENTRY HashEntry;
|
|
PBL_HASH_VALUE HashValue;
|
|
PBL_EFI_PROTOCOL EfiProtocol;
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
PVOID InterfaceVa;
|
|
|
|
/* Initialize failure paths */
|
|
AddressMapped = FALSE;
|
|
HashList = NULL;
|
|
InterfaceAddress.QuadPart = 0;
|
|
|
|
/* Have we initialized the protocol table yet? */
|
|
if (!EfiProtHashTableInitialized)
|
|
{
|
|
/* Nope -- create the hash table */
|
|
Status = BlHtCreate(0, NULL, NULL, &EfiProtHashTableId);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Remember for next time */
|
|
EfiProtHashTableInitialized = TRUE;
|
|
}
|
|
|
|
/* Check if we already have a list of protocols for this handle */
|
|
HashEntry.Flags = BL_HT_VALUE_IS_INLINE;
|
|
HashEntry.Size = sizeof(Handle);
|
|
HashEntry.Value = Handle;
|
|
Status = BlHtLookup(EfiProtHashTableId, &HashEntry, &HashValue);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* We do -- the hash value is the list itself */
|
|
HashList = (PLIST_ENTRY)HashValue->Data;
|
|
NextEntry = HashList->Flink;
|
|
|
|
/* Iterate over it */
|
|
while (NextEntry != HashList)
|
|
{
|
|
/* Get each protocol in the list, checking for a match */
|
|
EfiProtocol = CONTAINING_RECORD(NextEntry,
|
|
BL_EFI_PROTOCOL,
|
|
ListEntry);
|
|
if (EfiProtocol->Protocol == Protocol)
|
|
{
|
|
/* Match found -- add a reference and return it */
|
|
EfiProtocol->ReferenceCount++;
|
|
*Interface = EfiProtocol->Interface;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* Try the next entry */
|
|
NextEntry = NextEntry->Flink;
|
|
}
|
|
}
|
|
|
|
/* Switch to real mode for firmware call */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Check if this is EFI 1.02 */
|
|
if (EfiST->Hdr.Revision == EFI_1_02_SYSTEM_TABLE_REVISION)
|
|
{
|
|
/* Use the old call */
|
|
EfiStatus = EfiBS->HandleProtocol(Handle,
|
|
Protocol,
|
|
(PVOID*)&InterfaceAddress);
|
|
}
|
|
else
|
|
{
|
|
/* Use the EFI 2.00 API instead */
|
|
EfiStatus = EfiBS->OpenProtocol(Handle,
|
|
Protocol,
|
|
(PVOID*)&InterfaceAddress,
|
|
EfiImageHandle,
|
|
NULL,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
}
|
|
|
|
/* Switch back to protected mode if needed */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Check the result, and bail out on failure */
|
|
Status = EfiGetNtStatusCode(EfiStatus);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Check what address the interface lives at, and translate it */
|
|
InterfaceVa = PhysicalAddressToPtr(InterfaceAddress);
|
|
if (BlMmTranslateVirtualAddress(InterfaceVa, &TranslatedAddress))
|
|
{
|
|
/* We expect firmware to be 1:1 mapped, fail if not */
|
|
if (InterfaceAddress.QuadPart != TranslatedAddress.QuadPart)
|
|
{
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Create a virtual (1:1) mapping for the interface */
|
|
Status = BlMmMapPhysicalAddressEx(&InterfaceVa,
|
|
BlMemoryFixed,
|
|
PAGE_SIZE,
|
|
InterfaceAddress);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Remember for cleanup */
|
|
AddressMapped = TRUE;
|
|
}
|
|
|
|
/* The caller now has the interface */
|
|
*Interface = InterfaceVa;
|
|
|
|
/* Did we already have some protocols on this handle? */
|
|
if (!HashList)
|
|
{
|
|
/* Nope, this is the first time -- so allocate the list */
|
|
HashList = BlMmAllocateHeap(sizeof(*HashList));
|
|
if (!HashList)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Initialize it */
|
|
InitializeListHead(HashList);
|
|
|
|
/* And then store it in the hash table for this handle */
|
|
Status = BlHtStore(EfiProtHashTableId,
|
|
&HashEntry,
|
|
HashList,
|
|
sizeof(*HashList));
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
BlMmFreeHeap(HashList);
|
|
goto Quickie;
|
|
}
|
|
}
|
|
|
|
/* Finally, allocate a protocol tracker structure */
|
|
EfiProtocol = BlMmAllocateHeap(sizeof(*EfiProtocol));
|
|
if (!EfiProtocol)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* And store this information in case the protocol is needed again */
|
|
EfiProtocol->Protocol = Protocol;
|
|
EfiProtocol->Interface = *Interface;
|
|
EfiProtocol->ReferenceCount = 1;
|
|
EfiProtocol->AddressMapped = AddressMapped;
|
|
InsertTailList(HashList, &EfiProtocol->ListEntry);
|
|
|
|
/* Passthru to success case */
|
|
AddressMapped = FALSE;
|
|
|
|
Quickie:
|
|
/* Failure path -- did we map anything ?*/
|
|
if (AddressMapped)
|
|
{
|
|
/* Get rid of it */
|
|
BlMmUnmapVirtualAddressEx(InterfaceVa, PAGE_SIZE);
|
|
*Interface = NULL;
|
|
}
|
|
|
|
/* Return the failure */
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiOpenProtocol (
|
|
_In_ EFI_HANDLE Handle,
|
|
_In_ EFI_GUID *Protocol,
|
|
_Outptr_ PVOID* Interface
|
|
)
|
|
{
|
|
EFI_STATUS EfiStatus;
|
|
NTSTATUS Status;
|
|
BL_ARCH_MODE OldMode;
|
|
|
|
/* Are we using virtual memory/ */
|
|
if (MmTranslationType != BlNone)
|
|
{
|
|
/* We need complex tracking to make this work */
|
|
Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
|
|
}
|
|
else
|
|
{
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Are we on legacy 1.02? */
|
|
if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION)
|
|
{
|
|
/* Make the legacy call */
|
|
EfiStatus = EfiBS->HandleProtocol(Handle, Protocol, Interface);
|
|
}
|
|
else
|
|
{
|
|
/* Use the UEFI version */
|
|
EfiStatus = EfiBS->OpenProtocol(Handle,
|
|
Protocol,
|
|
Interface,
|
|
EfiImageHandle,
|
|
NULL,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
Status = EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
/* Clear the interface on failure, and return the status */
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
*Interface = NULL;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiVmpCloseProtocol (
|
|
_In_ EFI_HANDLE Handle,
|
|
_In_ EFI_GUID* Protocol
|
|
)
|
|
{
|
|
EFI_STATUS EfiStatus;
|
|
BL_ARCH_MODE OldMode;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Are we on legacy 1.02? */
|
|
if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION)
|
|
{
|
|
/* Nothing to close */
|
|
EfiStatus = EFI_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
/* Use the UEFI version */
|
|
EfiStatus = EfiBS->CloseProtocol(Handle,
|
|
Protocol,
|
|
EfiImageHandle,
|
|
NULL);
|
|
|
|
/* Normalize not found as success */
|
|
if (EfiStatus == EFI_NOT_FOUND)
|
|
{
|
|
EfiStatus = EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert to NT status */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiVmpFreeInterfaceEntry (
|
|
_In_ EFI_HANDLE Handle,
|
|
_In_ PBL_EFI_PROTOCOL EfiProtocol
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
BL_HASH_ENTRY HashEntry;
|
|
|
|
/* Assume success */
|
|
Status = STATUS_SUCCESS;
|
|
|
|
/* Is this the last protocol on this handle? */
|
|
if (IsListEmpty(&EfiProtocol->ListEntry))
|
|
{
|
|
/* Delete the hash table entry for this handle */
|
|
HashEntry.Value = Handle;
|
|
HashEntry.Size = sizeof(Handle);
|
|
HashEntry.Flags = BL_HT_VALUE_IS_INLINE;
|
|
Status = BlHtDelete(EfiProtHashTableId, &HashEntry);
|
|
|
|
/* This will free the list head itself */
|
|
BlMmFreeHeap(EfiProtocol->ListEntry.Flink);
|
|
}
|
|
else
|
|
{
|
|
/* Simply remove this entry */
|
|
RemoveEntryList(&EfiProtocol->ListEntry);
|
|
}
|
|
|
|
/* Had we virtually mapped this protocol? */
|
|
if (EfiProtocol->AddressMapped)
|
|
{
|
|
/* Unmap it */
|
|
BlMmUnmapVirtualAddressEx(EfiProtocol->Interface, PAGE_SIZE);
|
|
}
|
|
|
|
/* Free the protocol entry, and return */
|
|
BlMmFreeHeap(EfiProtocol);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiVmCloseProtocol (
|
|
_In_ EFI_HANDLE Handle,
|
|
_In_ EFI_GUID* Protocol
|
|
)
|
|
{
|
|
BL_HASH_ENTRY HashEntry;
|
|
PLIST_ENTRY ListHead, NextEntry;
|
|
NTSTATUS Status, CloseStatus;
|
|
PBL_HASH_VALUE HashValue;
|
|
PBL_EFI_PROTOCOL EfiProtocol;
|
|
|
|
/* Lookup the list entry for this handle */
|
|
HashEntry.Size = sizeof(Handle);
|
|
HashEntry.Flags = BL_HT_VALUE_IS_INLINE;
|
|
HashEntry.Value = Handle;
|
|
Status = BlHtLookup(EfiProtHashTableId, &HashEntry, &HashValue);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* This handle was never used for any protocols */
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Iterate through the list of opened protocols */
|
|
ListHead = (PLIST_ENTRY)HashValue->Data;
|
|
NextEntry = ListHead->Flink;
|
|
while (NextEntry != ListHead)
|
|
{
|
|
/* Get this protocol entry and check for a match */
|
|
EfiProtocol = CONTAINING_RECORD(NextEntry, BL_EFI_PROTOCOL, ListEntry);
|
|
if (EfiProtocol->Protocol == Protocol)
|
|
{
|
|
/* Drop a reference -- was it the last one? */
|
|
if (EfiProtocol->ReferenceCount-- == 1)
|
|
{
|
|
/* Yep -- free this entry */
|
|
Status = EfiVmpFreeInterfaceEntry(Handle, EfiProtocol);
|
|
|
|
/* Call firmware to close the protocol */
|
|
CloseStatus = EfiVmpCloseProtocol(Handle, Protocol);
|
|
if (!NT_SUCCESS(CloseStatus))
|
|
{
|
|
/* Override free status if close was a failure */
|
|
Status = CloseStatus;
|
|
}
|
|
|
|
/* Return final status */
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
/* Next entry */
|
|
NextEntry = NextEntry->Flink;
|
|
}
|
|
|
|
/* This protocol was never opened */
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiCloseProtocol (
|
|
_In_ EFI_HANDLE Handle,
|
|
_In_ EFI_GUID *Protocol
|
|
)
|
|
{
|
|
EFI_STATUS EfiStatus;
|
|
NTSTATUS Status;
|
|
BL_ARCH_MODE OldMode;
|
|
|
|
/* Are we using virtual memory/ */
|
|
if (MmTranslationType != BlNone)
|
|
{
|
|
/* We need complex tracking to make this work */
|
|
Status = EfiVmCloseProtocol(Handle, Protocol);
|
|
}
|
|
else
|
|
{
|
|
/* Are we on legacy 1.02? */
|
|
if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION)
|
|
{
|
|
/* Nothing to close */
|
|
EfiStatus = EFI_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Use the UEFI version */
|
|
EfiStatus = EfiBS->CloseProtocol(Handle, Protocol, EfiImageHandle, NULL);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Normalize not found as success */
|
|
if (EfiStatus == EFI_NOT_FOUND)
|
|
{
|
|
EfiStatus = EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
Status = EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
/* All done */
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiGetVariable (
|
|
_In_ PWCHAR VariableName,
|
|
_In_ EFI_GUID* VendorGuid,
|
|
_Out_opt_ PULONG Attributes,
|
|
_Inout_ PULONG DataSize,
|
|
_Out_ PVOID Data
|
|
)
|
|
{
|
|
EFI_STATUS EfiStatus;
|
|
NTSTATUS Status;
|
|
BL_ARCH_MODE OldMode;
|
|
ULONG LocalAttributes;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"getvar vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Call the runtime API */
|
|
EfiStatus = EfiRT->GetVariable(VariableName,
|
|
VendorGuid,
|
|
(UINT32*)&LocalAttributes,
|
|
(UINTN*)DataSize,
|
|
Data);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Return attributes back to the caller if asked to */
|
|
if (Attributes)
|
|
{
|
|
*Attributes = LocalAttributes;
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS and return it */
|
|
Status = EfiGetNtStatusCode(EfiStatus);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
BlpSecureBootEFIIsEnabled (
|
|
VOID
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
BOOLEAN SetupMode, SecureBoot;
|
|
ULONG DataSize;
|
|
|
|
/* Assume setup mode enabled, and no secure boot */
|
|
SecureBoot = FALSE;
|
|
SetupMode = TRUE;
|
|
|
|
/* Get the SetupMode variable */
|
|
DataSize = sizeof(SetupMode);
|
|
Status = EfiGetVariable(L"SetupMode",
|
|
&EfiGlobalVariable,
|
|
NULL,
|
|
&DataSize,
|
|
&SetupMode);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* If it worked, get the SecureBoot variable */
|
|
DataSize = sizeof(SecureBoot);
|
|
Status = EfiGetVariable(L"SecureBoot",
|
|
&EfiGlobalVariable,
|
|
NULL,
|
|
&DataSize,
|
|
&SecureBoot);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* In setup mode or without secureboot turned on, return failure */
|
|
if ((SecureBoot != TRUE) || (SetupMode))
|
|
{
|
|
Status = STATUS_INVALID_SIGNATURE;
|
|
}
|
|
|
|
// BlpSbdiStateFlags |= 8u;
|
|
}
|
|
}
|
|
|
|
/* Return secureboot status */
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
BlSecureBootIsEnabled (
|
|
_Out_ PBOOLEAN SecureBootEnabled
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
/* Have we checked before ? */
|
|
if (!BlpFirmwareChecked)
|
|
{
|
|
/* First time checking */
|
|
Status = BlpSecureBootEFIIsEnabled();
|
|
if NT_SUCCESS(Status)
|
|
{
|
|
/* Yep, it's on */
|
|
BlpFirmwareEnabled = TRUE;
|
|
}
|
|
|
|
/* Don't check again */
|
|
BlpFirmwareChecked = TRUE;
|
|
}
|
|
|
|
/* Return the firmware result */
|
|
*SecureBootEnabled = BlpFirmwareEnabled;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
BlSecureBootCheckForFactoryReset (
|
|
VOID
|
|
)
|
|
{
|
|
BOOLEAN SecureBootEnabled;
|
|
NTSTATUS Status;
|
|
ULONG DataSize;
|
|
|
|
/* Initialize locals */
|
|
DataSize = 0;
|
|
SecureBootEnabled = FALSE;
|
|
|
|
/* Check if secureboot is enabled */
|
|
Status = BlSecureBootIsEnabled(&SecureBootEnabled);
|
|
if (!(NT_SUCCESS(Status)) || !(SecureBootEnabled))
|
|
{
|
|
/* It's not. Check if there's a revocation list */
|
|
Status = EfiGetVariable(L"RevocationList",
|
|
&BlpEfiSecureBootPrivateNamespace,
|
|
NULL,
|
|
&DataSize,
|
|
NULL);
|
|
if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL))
|
|
{
|
|
/* We don't support this yet */
|
|
EfiPrintf(L"Not yet supported\r\n");
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
/* Return back to the caller */
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConInReset (
|
|
VOID
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"coninreset vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = EfiConIn->Reset(EfiConIn, FALSE);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConInExReset (
|
|
VOID
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"conreset vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = EfiConInEx->Reset(EfiConInEx, FALSE);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConInExSetState (
|
|
_In_ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *ConInEx,
|
|
_In_ EFI_KEY_TOGGLE_STATE* KeyToggleState
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
PHYSICAL_ADDRESS ConInExPhys, KeyTogglePhys;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Translate pointers from virtual to physical */
|
|
BlMmTranslateVirtualAddress(ConInEx, &ConInExPhys);
|
|
ConInEx = (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL*)PhysicalAddressToPtr(ConInExPhys);
|
|
BlMmTranslateVirtualAddress(KeyToggleState, &KeyTogglePhys);
|
|
KeyToggleState = (EFI_KEY_TOGGLE_STATE*)PhysicalAddressToPtr(KeyTogglePhys);
|
|
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = ConInEx->SetState(ConInEx, KeyToggleState);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiSetWatchdogTimer (
|
|
VOID
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = EfiBS->SetWatchdogTimer(0, 0, 0, NULL);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiGetMemoryMap (
|
|
_Out_ UINTN* MemoryMapSize,
|
|
_Inout_ EFI_MEMORY_DESCRIPTOR *MemoryMap,
|
|
_Out_ UINTN* MapKey,
|
|
_Out_ UINTN* DescriptorSize,
|
|
_Out_ UINTN* DescriptorVersion
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
PHYSICAL_ADDRESS MemoryMapSizePhysical, MemoryMapPhysical, MapKeyPhysical;
|
|
PHYSICAL_ADDRESS DescriptorSizePhysical, DescriptorVersionPhysical;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Convert all of the addresses to physical */
|
|
BlMmTranslateVirtualAddress(MemoryMapSize, &MemoryMapSizePhysical);
|
|
MemoryMapSize = (UINTN*)PhysicalAddressToPtr(MemoryMapSizePhysical);
|
|
BlMmTranslateVirtualAddress(MemoryMap, &MemoryMapPhysical);
|
|
MemoryMap = (EFI_MEMORY_DESCRIPTOR*)PhysicalAddressToPtr(MemoryMapPhysical);
|
|
BlMmTranslateVirtualAddress(MapKey, &MapKeyPhysical);
|
|
MapKey = (UINTN*)PhysicalAddressToPtr(MapKeyPhysical);
|
|
BlMmTranslateVirtualAddress(DescriptorSize, &DescriptorSizePhysical);
|
|
DescriptorSize = (UINTN*)PhysicalAddressToPtr(DescriptorSizePhysical);
|
|
BlMmTranslateVirtualAddress(DescriptorVersion, &DescriptorVersionPhysical);
|
|
DescriptorVersion = (UINTN*)PhysicalAddressToPtr(DescriptorVersionPhysical);
|
|
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = EfiBS->GetMemoryMap(MemoryMapSize,
|
|
MemoryMap,
|
|
MapKey,
|
|
DescriptorSize,
|
|
DescriptorVersion);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiFreePages (
|
|
_In_ ULONG Pages,
|
|
_In_ EFI_PHYSICAL_ADDRESS PhysicalAddress
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = EfiBS->FreePages(PhysicalAddress, Pages);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiStall (
|
|
_In_ ULONG StallTime
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = EfiBS->Stall(StallTime);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConOutQueryMode (
|
|
_In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
|
|
_In_ ULONG Mode,
|
|
_In_ UINTN* Columns,
|
|
_In_ UINTN* Rows
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"conqmode vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = TextInterface->QueryMode(TextInterface, Mode, Columns, Rows);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConOutSetMode (
|
|
_In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
|
|
_In_ ULONG Mode
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"setmode vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = TextInterface->SetMode(TextInterface, Mode);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConOutSetAttribute (
|
|
_In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
|
|
_In_ ULONG Attribute
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"sattr vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = TextInterface->SetAttribute(TextInterface, Attribute);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConOutSetCursorPosition (
|
|
_In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
|
|
_In_ ULONG Column,
|
|
_In_ ULONG Row
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"setcursor vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = TextInterface->SetCursorPosition(TextInterface, Column, Row);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConOutEnableCursor (
|
|
_In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
|
|
_In_ BOOLEAN Visible
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"enablecurso vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = TextInterface->EnableCursor(TextInterface, Visible);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConOutOutputString (
|
|
_In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
|
|
_In_ PWCHAR String
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"output string vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = TextInterface->OutputString(TextInterface, String);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
VOID
|
|
EfiConOutReadCurrentMode (
|
|
_In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
|
|
_Out_ EFI_SIMPLE_TEXT_OUTPUT_MODE* Mode
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"readmode vm path\r\n");
|
|
EfiStall(10000000);
|
|
return;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
RtlCopyMemory(Mode, TextInterface->Mode, sizeof(*Mode));
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
EfiGopGetFrameBuffer (
|
|
_In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface,
|
|
_Out_ PHYSICAL_ADDRESS* FrameBuffer,
|
|
_Out_ UINTN *FrameBufferSize
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
PHYSICAL_ADDRESS GopInterfacePhys, FrameBufferPhys, FrameBufferSizePhys;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Translate pointer to physical */
|
|
BlMmTranslateVirtualAddress(GopInterface, &GopInterfacePhys);
|
|
GopInterface = PhysicalAddressToPtr(GopInterfacePhys);
|
|
|
|
/* Translate pointer to physical */
|
|
BlMmTranslateVirtualAddress(FrameBuffer, &FrameBufferPhys);
|
|
FrameBuffer = PhysicalAddressToPtr(FrameBufferPhys);
|
|
|
|
/* Translate pointer to physical */
|
|
BlMmTranslateVirtualAddress(FrameBufferSize, &FrameBufferSizePhys);
|
|
FrameBufferSize = PhysicalAddressToPtr(FrameBufferSizePhys);
|
|
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
FrameBuffer->QuadPart = GopInterface->Mode->FrameBufferBase;
|
|
*FrameBufferSize = GopInterface->Mode->FrameBufferSize;
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiGopGetCurrentMode (
|
|
_In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface,
|
|
_Out_ UINTN* Mode,
|
|
_Out_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
PHYSICAL_ADDRESS GopInterfacePhys, ModePhys, InformationPhys;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Translate pointer to physical */
|
|
if (!BlMmTranslateVirtualAddress(GopInterface, &GopInterfacePhys))
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
GopInterface = PhysicalAddressToPtr(GopInterfacePhys);
|
|
|
|
/* Translate pointer to physical */
|
|
if (!BlMmTranslateVirtualAddress(Mode, &ModePhys))
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
Mode = PhysicalAddressToPtr(ModePhys);
|
|
|
|
/* Translate pointer to physical */
|
|
if (!BlMmTranslateVirtualAddress(Information, &InformationPhys))
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
Information = PhysicalAddressToPtr(InformationPhys);
|
|
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
*Mode = GopInterface->Mode->Mode;
|
|
RtlCopyMemory(Information, GopInterface->Mode->Info, sizeof(*Information));
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Return back */
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiGopSetMode (
|
|
_In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface,
|
|
_In_ ULONG Mode
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
BOOLEAN ModeChanged;
|
|
NTSTATUS Status;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"gopsmode vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
if (Mode == GopInterface->Mode->Mode)
|
|
{
|
|
EfiStatus = EFI_SUCCESS;
|
|
ModeChanged = FALSE;
|
|
}
|
|
{
|
|
EfiStatus = GopInterface->SetMode(GopInterface, Mode);
|
|
ModeChanged = TRUE;
|
|
}
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Print out to the debugger if the mode was changed */
|
|
Status = EfiGetNtStatusCode(EfiStatus);
|
|
if ((ModeChanged) && (NT_SUCCESS(Status)))
|
|
{
|
|
/* FIXME @TODO: Should be BlStatusPrint */
|
|
EfiPrintf(L"Console video mode set to 0x%x\r\n", Mode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiLocateHandleBuffer (
|
|
_In_ EFI_LOCATE_SEARCH_TYPE SearchType,
|
|
_In_ EFI_GUID *Protocol,
|
|
_Inout_ PULONG HandleCount,
|
|
_Inout_ EFI_HANDLE** Buffer
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
UINTN BufferSize;
|
|
PVOID InputBuffer;
|
|
BOOLEAN TranslateResult;
|
|
PHYSICAL_ADDRESS BufferPhys;
|
|
|
|
/* Bail out if we're missing parameters */
|
|
if (!(Buffer) || !(HandleCount))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Check if a buffer was passed in*/
|
|
InputBuffer = *Buffer;
|
|
if (InputBuffer)
|
|
{
|
|
/* Then we should already have a buffer size*/
|
|
BufferSize = sizeof(EFI_HANDLE) * *HandleCount;
|
|
}
|
|
else
|
|
{
|
|
/* Then no buffer size exists */
|
|
BufferSize = 0;
|
|
}
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Translate the input buffer from virtual to physical */
|
|
TranslateResult = BlMmTranslateVirtualAddress(InputBuffer, &BufferPhys);
|
|
InputBuffer = TranslateResult ? PhysicalAddressToPtr(BufferPhys) : NULL;
|
|
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Try the first time */
|
|
EfiStatus = EfiBS->LocateHandle(SearchType,
|
|
Protocol,
|
|
NULL,
|
|
&BufferSize,
|
|
InputBuffer);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Check result of first search */
|
|
if (EfiStatus == EFI_BUFFER_TOO_SMALL)
|
|
{
|
|
/* Did we have an existing buffer? */
|
|
if (*Buffer)
|
|
{
|
|
/* Free it */
|
|
BlMmFreeHeap(*Buffer);
|
|
}
|
|
|
|
/* Allocate a new one */
|
|
InputBuffer = BlMmAllocateHeap(BufferSize);
|
|
*Buffer = InputBuffer;
|
|
if (!InputBuffer)
|
|
{
|
|
/* No space, fail */
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Translate the input buffer from virtual to physical */
|
|
TranslateResult = BlMmTranslateVirtualAddress(InputBuffer,
|
|
&BufferPhys);
|
|
InputBuffer = TranslateResult ? PhysicalAddressToPtr(BufferPhys) : NULL;
|
|
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Try again */
|
|
EfiStatus = EfiBS->LocateHandle(SearchType,
|
|
Protocol,
|
|
NULL,
|
|
&BufferSize,
|
|
InputBuffer);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
}
|
|
|
|
/* Return the number of handles */
|
|
*HandleCount = BufferSize / sizeof(EFI_HANDLE);
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
VOID
|
|
EfiResetSystem (
|
|
_In_ EFI_RESET_TYPE ResetType
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"reset vm path\r\n");
|
|
EfiStall(10000000);
|
|
return;
|
|
}
|
|
|
|
/* Call the EFI runtime */
|
|
EfiRT->ResetSystem(ResetType, EFI_SUCCESS, 0, NULL);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiConnectController (
|
|
_In_ EFI_HANDLE ControllerHandle
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
|
|
/* Is this EFI 1.02? */
|
|
if (EfiST->Hdr.Revision == EFI_1_02_SYSTEM_TABLE_REVISION)
|
|
{
|
|
/* This function didn't exist back then */
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* FIXME: Not yet implemented */
|
|
EfiPrintf(L"connectctrl vm path\r\n");
|
|
EfiStall(10000000);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = EfiBS->ConnectController(ControllerHandle, NULL, NULL, TRUE);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfiAllocatePages (
|
|
_In_ ULONG Type,
|
|
_In_ ULONG Pages,
|
|
_Inout_ EFI_PHYSICAL_ADDRESS* Memory
|
|
)
|
|
{
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_STATUS EfiStatus;
|
|
PHYSICAL_ADDRESS MemoryPhysical;
|
|
|
|
/* Are we in protected mode? */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
/* Translate output address */
|
|
BlMmTranslateVirtualAddress(Memory, &MemoryPhysical);
|
|
Memory = (EFI_PHYSICAL_ADDRESS*)PhysicalAddressToPtr(MemoryPhysical);
|
|
|
|
/* Switch to real mode */
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Make the EFI call */
|
|
EfiStatus = EfiBS->AllocatePages(Type, EfiLoaderData, Pages, Memory);
|
|
|
|
/* Switch back to protected mode if we came from there */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the error to an NTSTATUS */
|
|
return EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
|
|
NTSTATUS
|
|
EfipGetSystemTable (
|
|
_In_ EFI_GUID *TableGuid,
|
|
_Out_ PPHYSICAL_ADDRESS TableAddress
|
|
)
|
|
{
|
|
ULONG i;
|
|
NTSTATUS Status;
|
|
|
|
/* Assume failure */
|
|
Status = STATUS_NOT_FOUND;
|
|
|
|
/* Loop through the configuration tables */
|
|
for (i = 0; i < EfiST->NumberOfTableEntries; i++)
|
|
{
|
|
/* Check if this one matches the one we want */
|
|
if (RtlEqualMemory(&EfiST->ConfigurationTable[i].VendorGuid,
|
|
TableGuid,
|
|
sizeof(*TableGuid)))
|
|
{
|
|
/* Return its address */
|
|
TableAddress->QuadPart = (ULONG_PTR)EfiST->ConfigurationTable[i].VendorTable;
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Return the search result */
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
EfipGetRsdt (
|
|
_Out_ PPHYSICAL_ADDRESS FoundRsdt
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG Length;
|
|
PHYSICAL_ADDRESS RsdpAddress, Rsdt;
|
|
PRSDP Rsdp;
|
|
|
|
/* Assume failure */
|
|
Length = 0;
|
|
Rsdp = NULL;
|
|
|
|
/* Check if we already know it */
|
|
if (EfiRsdt.QuadPart)
|
|
{
|
|
/* Return it */
|
|
*FoundRsdt = EfiRsdt;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* Otherwise, look for the ACPI 2.0 RSDP (XSDT really) */
|
|
Status = EfipGetSystemTable(&EfiRootAcpiTableGuid, &RsdpAddress);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Didn't fint it, look for the ACPI 1.0 RSDP (RSDT really) */
|
|
Status = EfipGetSystemTable(&EfiRootAcpiTable10Guid, &RsdpAddress);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
/* Map it */
|
|
Length = sizeof(*Rsdp);
|
|
Status = BlMmMapPhysicalAddressEx((PVOID*)&Rsdp,
|
|
0,
|
|
Length,
|
|
RsdpAddress);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Check the revision (anything >= 2.0 is XSDT) */
|
|
if (Rsdp->Revision)
|
|
{
|
|
/* Check if the table is bigger than just its header */
|
|
if (Rsdp->Length > Length)
|
|
{
|
|
/* Capture the real length */
|
|
Length = Rsdp->Length;
|
|
|
|
/* Unmap our header mapping */
|
|
BlMmUnmapVirtualAddressEx(Rsdp, sizeof(*Rsdp));
|
|
|
|
/* And map the whole thing now */
|
|
Status = BlMmMapPhysicalAddressEx((PVOID*)&Rsdp,
|
|
0,
|
|
Length,
|
|
RsdpAddress);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
/* Read the XSDT address from the table*/
|
|
Rsdt = Rsdp->XsdtAddress;
|
|
}
|
|
else
|
|
{
|
|
/* ACPI 1.0 so just read the RSDT */
|
|
Rsdt.QuadPart = Rsdp->RsdtAddress;
|
|
}
|
|
|
|
/* Save it for later */
|
|
EfiRsdt = Rsdt;
|
|
|
|
/* And return it back */
|
|
*FoundRsdt = Rsdt;
|
|
}
|
|
|
|
/* Check if we had mapped the RSDP */
|
|
if (Rsdp)
|
|
{
|
|
/* Unmap it */
|
|
BlMmUnmapVirtualAddressEx(Rsdp, Length);
|
|
}
|
|
|
|
/* Return search result back to caller */
|
|
return Status;
|
|
}
|
|
|
|
BL_MEMORY_ATTR
|
|
MmFwpGetOsAttributeType (
|
|
_In_ ULONGLONG Attribute
|
|
)
|
|
{
|
|
BL_MEMORY_ATTR OsAttribute = 0;
|
|
|
|
if (Attribute & EFI_MEMORY_UC)
|
|
{
|
|
OsAttribute = BlMemoryUncached;
|
|
}
|
|
|
|
if (Attribute & EFI_MEMORY_WC)
|
|
{
|
|
OsAttribute |= BlMemoryWriteCombined;
|
|
}
|
|
|
|
if (Attribute & EFI_MEMORY_WT)
|
|
{
|
|
OsAttribute |= BlMemoryWriteThrough;
|
|
}
|
|
|
|
if (Attribute & EFI_MEMORY_WB)
|
|
{
|
|
OsAttribute |= BlMemoryWriteBack;
|
|
}
|
|
|
|
if (Attribute & EFI_MEMORY_UCE)
|
|
{
|
|
OsAttribute |= BlMemoryUncachedExported;
|
|
}
|
|
|
|
if (Attribute & EFI_MEMORY_WP)
|
|
{
|
|
OsAttribute |= BlMemoryWriteProtected;
|
|
}
|
|
|
|
if (Attribute & EFI_MEMORY_RP)
|
|
{
|
|
OsAttribute |= BlMemoryReadProtected;
|
|
}
|
|
|
|
if (Attribute & EFI_MEMORY_XP)
|
|
{
|
|
OsAttribute |= BlMemoryExecuteProtected;
|
|
}
|
|
|
|
if (Attribute & EFI_MEMORY_RUNTIME)
|
|
{
|
|
OsAttribute |= BlMemoryRuntime;
|
|
}
|
|
|
|
return OsAttribute;
|
|
}
|
|
|
|
BL_MEMORY_TYPE
|
|
MmFwpGetOsMemoryType (
|
|
_In_ EFI_MEMORY_TYPE MemoryType
|
|
)
|
|
{
|
|
BL_MEMORY_TYPE OsType;
|
|
|
|
switch (MemoryType)
|
|
{
|
|
case EfiLoaderCode:
|
|
case EfiLoaderData:
|
|
OsType = BlLoaderMemory;
|
|
break;
|
|
|
|
case EfiBootServicesCode:
|
|
case EfiBootServicesData:
|
|
OsType = BlEfiBootMemory;
|
|
break;
|
|
|
|
case EfiRuntimeServicesCode:
|
|
OsType = BlEfiRuntimeCodeMemory;
|
|
break;
|
|
|
|
case EfiRuntimeServicesData:
|
|
OsType = BlEfiRuntimeDataMemory;
|
|
break;
|
|
|
|
case EfiConventionalMemory:
|
|
OsType = BlConventionalMemory;
|
|
break;
|
|
|
|
case EfiUnusableMemory:
|
|
OsType = BlUnusableMemory;
|
|
break;
|
|
|
|
case EfiACPIReclaimMemory:
|
|
OsType = BlAcpiReclaimMemory;
|
|
break;
|
|
|
|
case EfiACPIMemoryNVS:
|
|
OsType = BlAcpiNvsMemory;
|
|
break;
|
|
|
|
case EfiMemoryMappedIO:
|
|
OsType = BlDeviceIoMemory;
|
|
break;
|
|
|
|
case EfiMemoryMappedIOPortSpace:
|
|
OsType = BlDevicePortMemory;
|
|
break;
|
|
|
|
case EfiPalCode:
|
|
OsType = BlPalMemory;
|
|
break;
|
|
|
|
default:
|
|
OsType = BlReservedMemory;
|
|
break;
|
|
}
|
|
|
|
return OsType;
|
|
}
|
|
|
|
NTSTATUS
|
|
MmFwGetMemoryMap (
|
|
_Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap,
|
|
_In_ ULONG Flags
|
|
)
|
|
{
|
|
BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
|
|
BOOLEAN UseEfiBuffer, HaveRamDisk;
|
|
NTSTATUS Status;
|
|
ULONGLONG Pages, StartPage, EndPage, EfiBufferPage;
|
|
UINTN EfiMemoryMapSize, MapKey, DescriptorSize, DescriptorVersion;
|
|
EFI_PHYSICAL_ADDRESS EfiBuffer = 0;
|
|
EFI_MEMORY_DESCRIPTOR* EfiMemoryMap;
|
|
EFI_STATUS EfiStatus;
|
|
BL_ARCH_MODE OldMode;
|
|
EFI_MEMORY_DESCRIPTOR EfiDescriptor;
|
|
BL_MEMORY_TYPE MemoryType;
|
|
PBL_MEMORY_DESCRIPTOR Descriptor;
|
|
BL_MEMORY_ATTR Attribute;
|
|
PVOID LibraryBuffer;
|
|
|
|
/* Initialize EFI memory map attributes */
|
|
EfiMemoryMapSize = MapKey = DescriptorSize = DescriptorVersion = 0;
|
|
LibraryBuffer = NULL;
|
|
|
|
/* Increment the nesting depth */
|
|
MmDescriptorCallTreeCount++;
|
|
|
|
/* Determine if we should use EFI or our own allocator at this point */
|
|
UseEfiBuffer = Flags & BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS;
|
|
if (!(LibraryParameters.LibraryFlags & BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED))
|
|
{
|
|
UseEfiBuffer = TRUE;
|
|
}
|
|
|
|
/* Bail out if we don't have a list to use */
|
|
if (MemoryMap == NULL)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Free the current descriptor list */
|
|
MmMdFreeList(MemoryMap);
|
|
|
|
/* Call into EFI to get the size of the memory map */
|
|
Status = EfiGetMemoryMap(&EfiMemoryMapSize,
|
|
NULL,
|
|
&MapKey,
|
|
&DescriptorSize,
|
|
&DescriptorVersion);
|
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
{
|
|
/* This should've failed because our buffer was too small, nothing else */
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Add 4 more descriptors just in case things changed */
|
|
EfiMemoryMapSize += (4 * DescriptorSize);
|
|
Pages = BYTES_TO_PAGES(EfiMemoryMapSize);
|
|
|
|
/* Should we use EFI to grab memory? */
|
|
if (UseEfiBuffer)
|
|
{
|
|
/* Yes -- request one more page to align up correctly */
|
|
Pages++;
|
|
|
|
/* Grab the required pages */
|
|
Status = EfiAllocatePages(AllocateAnyPages,
|
|
Pages,
|
|
&EfiBuffer);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"EFI allocation failed: %lx\r\n", Status);
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Free the pages for now */
|
|
Status = EfiFreePages(Pages, EfiBuffer);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiBuffer = 0;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Now round to the actual buffer size, removing the extra page */
|
|
EfiBuffer = ROUND_TO_PAGES(EfiBuffer);
|
|
Pages--;
|
|
Status = EfiAllocatePages(AllocateAddress,
|
|
Pages,
|
|
&EfiBuffer);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiBuffer = 0;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Get the final aligned size and proper buffer */
|
|
EfiMemoryMapSize = EFI_PAGES_TO_SIZE(Pages);
|
|
EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR*)(ULONG_PTR)EfiBuffer;
|
|
|
|
/* Switch to real mode if not already in it */
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Call EFI to get the memory map */
|
|
EfiStatus = EfiBS->GetMemoryMap(&EfiMemoryMapSize,
|
|
EfiMemoryMap,
|
|
&MapKey,
|
|
&DescriptorSize,
|
|
&DescriptorVersion);
|
|
|
|
/* Switch back into the previous mode */
|
|
if (OldMode != BlRealMode)
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert the result code */
|
|
Status = EfiGetNtStatusCode(EfiStatus);
|
|
}
|
|
else
|
|
{
|
|
/* Round the map to pages */
|
|
Pages = BYTES_TO_PAGES(EfiMemoryMapSize);
|
|
|
|
/* Allocate a large enough buffer */
|
|
Status = MmPapAllocatePagesInRange(&LibraryBuffer,
|
|
BlLoaderData,
|
|
Pages,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"Failed to allocate mapped VM for EFI map: %lx\r\n", Status);
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Call EFI to get the memory map */
|
|
EfiMemoryMap = LibraryBuffer;
|
|
Status = EfiGetMemoryMap(&EfiMemoryMapSize,
|
|
LibraryBuffer,
|
|
&MapKey,
|
|
&DescriptorSize,
|
|
&DescriptorVersion);
|
|
}
|
|
|
|
/* So far so good? */
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"Failed to get EFI memory map: %lx\r\n", Status);
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Did we get correct data from firmware? */
|
|
if (((EfiMemoryMapSize % DescriptorSize)) ||
|
|
(DescriptorSize < sizeof(EFI_MEMORY_DESCRIPTOR)))
|
|
{
|
|
EfiPrintf(L"Incorrect descriptor size\r\n");
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Did we boot from a RAM disk? */
|
|
if ((BlpBootDevice->DeviceType == LocalDevice) &&
|
|
(BlpBootDevice->Local.Type == RamDiskDevice))
|
|
{
|
|
/* We don't handle this yet */
|
|
EfiPrintf(L"RAM boot not supported\r\n");
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
goto Quickie;
|
|
}
|
|
else
|
|
{
|
|
/* We didn't, so there won't be any need to find the memory descriptor */
|
|
HaveRamDisk = FALSE;
|
|
}
|
|
|
|
/* Loop the EFI memory map */
|
|
#if 0
|
|
EfiPrintf(L"UEFI MEMORY MAP\r\n\r\n");
|
|
EfiPrintf(L"TYPE START END ATTRIBUTES\r\n");
|
|
EfiPrintf(L"===============================================================\r\n");
|
|
#endif
|
|
while (EfiMemoryMapSize != 0)
|
|
{
|
|
/* Check if this is an EFI buffer, but we're not in real mode */
|
|
if ((UseEfiBuffer) && (OldMode != BlRealMode))
|
|
{
|
|
BlpArchSwitchContext(BlRealMode);
|
|
}
|
|
|
|
/* Capture it so we can go back to protected mode (if possible) */
|
|
EfiDescriptor = *EfiMemoryMap;
|
|
|
|
/* Go back to protected mode, if we had switched */
|
|
if ((UseEfiBuffer) && (OldMode != BlRealMode))
|
|
{
|
|
BlpArchSwitchContext(OldMode);
|
|
}
|
|
|
|
/* Convert to OS memory type */
|
|
MemoryType = MmFwpGetOsMemoryType(EfiDescriptor.Type);
|
|
|
|
/* Round up or round down depending on where the memory is coming from */
|
|
if (MemoryType == BlConventionalMemory)
|
|
{
|
|
StartPage = BYTES_TO_PAGES(EfiDescriptor.PhysicalStart);
|
|
}
|
|
else
|
|
{
|
|
StartPage = EfiDescriptor.PhysicalStart >> PAGE_SHIFT;
|
|
}
|
|
|
|
/* Calculate the ending page */
|
|
EndPage = StartPage + EfiDescriptor.NumberOfPages;
|
|
|
|
/* If after rounding, we ended up with 0 pages, skip this */
|
|
if (StartPage == EndPage)
|
|
{
|
|
goto LoopAgain;
|
|
}
|
|
#if 0
|
|
EfiPrintf(L"%08X 0x%016I64X-0x%016I64X 0x%I64X\r\n",
|
|
MemoryType,
|
|
StartPage << PAGE_SHIFT,
|
|
EndPage << PAGE_SHIFT,
|
|
EfiDescriptor.Attribute);
|
|
#endif
|
|
/* Check for any range of memory below 1MB */
|
|
if (StartPage < 0x100)
|
|
{
|
|
/* Does this range actually contain NULL? */
|
|
if (StartPage == 0)
|
|
{
|
|
/* Manually create a reserved descriptof for this page */
|
|
Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
|
|
Descriptor = MmMdInitByteGranularDescriptor(Attribute,
|
|
BlReservedMemory,
|
|
0,
|
|
0,
|
|
1);
|
|
if (!Descriptor)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
/* Add this descriptor into the list */
|
|
Status = MmMdAddDescriptorToList(MemoryMap,
|
|
Descriptor,
|
|
BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"Failed to add zero page descriptor: %lx\r\n", Status);
|
|
break;
|
|
}
|
|
|
|
/* Now handle the rest of the range, unless this was it */
|
|
StartPage = 1;
|
|
if (EndPage == 1)
|
|
{
|
|
goto LoopAgain;
|
|
}
|
|
}
|
|
|
|
/* Does the range go beyond 1MB? */
|
|
if (EndPage > 0x100)
|
|
{
|
|
/* Then create the descriptor for everything up until the megabyte */
|
|
Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
|
|
Descriptor = MmMdInitByteGranularDescriptor(Attribute,
|
|
MemoryType,
|
|
StartPage,
|
|
0,
|
|
0x100 - StartPage);
|
|
if (!Descriptor)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
/* Check if this region is currently free RAM */
|
|
if (Descriptor->Type == BlConventionalMemory)
|
|
{
|
|
/* Set the appropriate flag on the descriptor */
|
|
Descriptor->Flags |= BlMemoryBelow1MB;
|
|
}
|
|
|
|
/* Add this descriptor into the list */
|
|
Status = MmMdAddDescriptorToList(MemoryMap,
|
|
Descriptor,
|
|
BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"Failed to add 1MB descriptor: %lx\r\n", Status);
|
|
break;
|
|
}
|
|
|
|
/* Now handle the rest of the range above 1MB */
|
|
StartPage = 0x100;
|
|
}
|
|
}
|
|
|
|
/* Check if we loaded from a RAM disk */
|
|
if (HaveRamDisk)
|
|
{
|
|
/* We don't handle this yet */
|
|
EfiPrintf(L"RAM boot not supported\r\n");
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Create a descriptor for the current range */
|
|
Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
|
|
Descriptor = MmMdInitByteGranularDescriptor(Attribute,
|
|
MemoryType,
|
|
StartPage,
|
|
0,
|
|
EndPage - StartPage);
|
|
if (!Descriptor)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
/* Check if this region is currently free RAM below 1MB */
|
|
if ((Descriptor->Type == BlConventionalMemory) && (EndPage <= 0x100))
|
|
{
|
|
/* Set the appropriate flag on the descriptor */
|
|
Descriptor->Flags |= BlMemoryBelow1MB;
|
|
}
|
|
|
|
/* Add the descriptor to the list, requesting coalescing as asked */
|
|
Status = MmMdAddDescriptorToList(MemoryMap,
|
|
Descriptor,
|
|
BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG |
|
|
((Flags & BL_MM_FLAG_REQUEST_COALESCING) ?
|
|
BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG : 0));
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"Failed to add full descriptor: %lx\r\n", Status);
|
|
break;
|
|
}
|
|
|
|
LoopAgain:
|
|
/* Consume this descriptor, and move to the next one */
|
|
EfiMemoryMapSize -= DescriptorSize;
|
|
EfiMemoryMap = (PVOID)((ULONG_PTR)EfiMemoryMap + DescriptorSize);
|
|
}
|
|
|
|
/* Check if we are using the local UEFI buffer */
|
|
if (!UseEfiBuffer)
|
|
{
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Free the EFI buffer */
|
|
Status = EfiFreePages(Pages, EfiBuffer);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Keep the pages marked 'in use' and fake success */
|
|
Status = STATUS_SUCCESS;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Get the base page of the EFI buffer */
|
|
EfiBufferPage = EfiBuffer >> PAGE_SHIFT;
|
|
Pages = (EfiBufferPage + Pages) - EfiBufferPage;
|
|
|
|
/* Don't try freeing below */
|
|
EfiBuffer = 0;
|
|
|
|
/* Find the current descriptor for the allocation */
|
|
Descriptor = MmMdFindDescriptorFromMdl(MemoryMap,
|
|
BL_MM_REMOVE_PHYSICAL_REGION_FLAG,
|
|
EfiBufferPage);
|
|
if (!Descriptor)
|
|
{
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Convert it to a free descriptor */
|
|
Descriptor = MmMdInitByteGranularDescriptor(Descriptor->Flags,
|
|
BlConventionalMemory,
|
|
EfiBufferPage,
|
|
0,
|
|
Pages);
|
|
if (!Descriptor)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Remove the region from the memory map */
|
|
Status = MmMdRemoveRegionFromMdlEx(MemoryMap,
|
|
BL_MM_REMOVE_PHYSICAL_REGION_FLAG,
|
|
EfiBufferPage,
|
|
Pages,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
MmMdFreeDescriptor(Descriptor);
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Add it back as free memory */
|
|
Status = MmMdAddDescriptorToList(MemoryMap,
|
|
Descriptor,
|
|
BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG);
|
|
|
|
Quickie:
|
|
/* Free the EFI buffer, if we had one */
|
|
if (EfiBuffer != 0)
|
|
{
|
|
EfiFreePages(Pages, EfiBuffer);
|
|
}
|
|
|
|
/* Free the library-allocated buffer, if we had one */
|
|
if (LibraryBuffer != 0)
|
|
{
|
|
MmPapFreePages(LibraryBuffer, BL_MM_INCLUDE_MAPPED_ALLOCATED);
|
|
}
|
|
|
|
/* On failure, free the memory map if one was passed in */
|
|
if (!NT_SUCCESS(Status) && (MemoryMap != NULL))
|
|
{
|
|
MmMdFreeList(MemoryMap);
|
|
}
|
|
|
|
/* Decrement the nesting depth and return */
|
|
MmDescriptorCallTreeCount--;
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
BlpFwInitialize (
|
|
_In_ ULONG Phase,
|
|
_In_ PBL_FIRMWARE_DESCRIPTOR FirmwareData
|
|
)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
EFI_KEY_TOGGLE_STATE KeyToggleState;
|
|
|
|
/* Check if we have valid firmware data */
|
|
if (!(FirmwareData) || !(FirmwareData->Version))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Check which boot phase we're in */
|
|
if (Phase != 0)
|
|
{
|
|
/* Memory manager is ready, open the extended input protocol */
|
|
Status = EfiOpenProtocol(EfiST->ConsoleInHandle,
|
|
&EfiSimpleTextInputExProtocol,
|
|
(PVOID*)&EfiConInEx);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Set the initial key toggle state */
|
|
KeyToggleState = EFI_TOGGLE_STATE_VALID | 40;
|
|
EfiConInExSetState(EfiConInEx, &KeyToggleState);
|
|
}
|
|
|
|
/* Setup the watchdog timer */
|
|
EfiSetWatchdogTimer();
|
|
}
|
|
else
|
|
{
|
|
/* Make a copy of the parameters */
|
|
EfiFirmwareParameters = &EfiFirmwareData;
|
|
|
|
/* Check which version we received */
|
|
if (FirmwareData->Version == 1)
|
|
{
|
|
/* FIXME: Not supported */
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
}
|
|
else if (FirmwareData->Version >= BL_FIRMWARE_DESCRIPTOR_VERSION)
|
|
{
|
|
/* Version 2 -- save the data */
|
|
EfiFirmwareData = *FirmwareData;
|
|
EfiSystemTable = FirmwareData->SystemTable;
|
|
EfiImageHandle = FirmwareData->ImageHandle;
|
|
|
|
/* Set the EDK-II style variables as well */
|
|
EfiST = EfiSystemTable;
|
|
EfiBS = EfiSystemTable->BootServices;
|
|
EfiRT = EfiSystemTable->RuntimeServices;
|
|
EfiConOut = EfiSystemTable->ConOut;
|
|
EfiConIn = EfiSystemTable->ConIn;
|
|
EfiConInEx = NULL;
|
|
}
|
|
else
|
|
{
|
|
/* Unknown version */
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
/* Return the initialization state */
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
BlFwGetParameters (
|
|
_In_ PBL_FIRMWARE_DESCRIPTOR Parameters
|
|
)
|
|
{
|
|
/* Make sure we got an argument */
|
|
if (!Parameters)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Copy the static data */
|
|
*Parameters = *EfiFirmwareParameters;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
BlFwEnumerateDevice (
|
|
_In_ PBL_DEVICE_DESCRIPTOR Device
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG PathProtocols, BlockProtocols;
|
|
EFI_HANDLE* PathArray;
|
|
EFI_HANDLE* BlockArray;
|
|
|
|
/* Initialize locals */
|
|
BlockArray = NULL;
|
|
PathArray = NULL;
|
|
PathProtocols = 0;
|
|
BlockProtocols = 0;
|
|
|
|
/* Enumeration only makes sense on disks or partitions */
|
|
if ((Device->DeviceType != DiskDevice) &&
|
|
(Device->DeviceType != LegacyPartitionDevice) &&
|
|
(Device->DeviceType != PartitionDevice))
|
|
{
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
/* Enumerate the list of device paths */
|
|
Status = EfiLocateHandleBuffer(ByProtocol,
|
|
&EfiDevicePathProtocol,
|
|
&PathProtocols,
|
|
&PathArray);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Loop through each one */
|
|
Status = STATUS_NOT_FOUND;
|
|
while (PathProtocols)
|
|
{
|
|
/* Attempt to connect the driver for this device epath */
|
|
Status = EfiConnectController(PathArray[--PathProtocols]);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Now enumerate any block I/O devices the driver added */
|
|
Status = EfiLocateHandleBuffer(ByProtocol,
|
|
&EfiBlockIoProtocol,
|
|
&BlockProtocols,
|
|
&BlockArray);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
break;
|
|
}
|
|
|
|
/* Loop through each one */
|
|
while (BlockProtocols)
|
|
{
|
|
/* Check if one of the new devices is the one we want */
|
|
Status = BlockIoEfiCompareDevice(Device,
|
|
BlockArray[--BlockProtocols]);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Yep, all done */
|
|
goto Quickie;
|
|
}
|
|
}
|
|
|
|
/* Move on to the next device path */
|
|
BlMmFreeHeap(BlockArray);
|
|
BlockArray = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
Quickie:
|
|
/* We're done -- free the array of device path protocols, if any */
|
|
if (PathArray)
|
|
{
|
|
BlMmFreeHeap(PathArray);
|
|
}
|
|
|
|
/* We're done -- free the array of block I/O protocols, if any */
|
|
if (BlockArray)
|
|
{
|
|
BlMmFreeHeap(BlockArray);
|
|
}
|
|
|
|
/* Return if we found the device or not */
|
|
return Status;
|
|
}
|
|
|
|
/*++
|
|
* @name EfiGetEfiStatusCode
|
|
*
|
|
* The EfiGetEfiStatusCode routine converts an NT Status to an EFI status.
|
|
*
|
|
* @param Status
|
|
* NT Status code to be converted.
|
|
*
|
|
* @remark Only certain, specific NT status codes are converted to EFI codes.
|
|
*
|
|
* @return The corresponding EFI Status code, EFI_NO_MAPPING otherwise.
|
|
*
|
|
*--*/
|
|
EFI_STATUS
|
|
EfiGetEfiStatusCode(
|
|
_In_ NTSTATUS Status
|
|
)
|
|
{
|
|
switch (Status)
|
|
{
|
|
case STATUS_NOT_SUPPORTED:
|
|
return EFI_UNSUPPORTED;
|
|
case STATUS_DISK_FULL:
|
|
return EFI_VOLUME_FULL;
|
|
case STATUS_INSUFFICIENT_RESOURCES:
|
|
return EFI_OUT_OF_RESOURCES;
|
|
case STATUS_MEDIA_WRITE_PROTECTED:
|
|
return EFI_WRITE_PROTECTED;
|
|
case STATUS_DEVICE_NOT_READY:
|
|
return EFI_NOT_STARTED;
|
|
case STATUS_DEVICE_ALREADY_ATTACHED:
|
|
return EFI_ALREADY_STARTED;
|
|
case STATUS_MEDIA_CHANGED:
|
|
return EFI_MEDIA_CHANGED;
|
|
case STATUS_INVALID_PARAMETER:
|
|
return EFI_INVALID_PARAMETER;
|
|
case STATUS_ACCESS_DENIED:
|
|
return EFI_ACCESS_DENIED;
|
|
case STATUS_BUFFER_TOO_SMALL:
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
case STATUS_DISK_CORRUPT_ERROR:
|
|
return EFI_VOLUME_CORRUPTED;
|
|
case STATUS_REQUEST_ABORTED:
|
|
return EFI_ABORTED;
|
|
case STATUS_NO_MEDIA:
|
|
return EFI_NO_MEDIA;
|
|
case STATUS_IO_DEVICE_ERROR:
|
|
return EFI_DEVICE_ERROR;
|
|
case STATUS_INVALID_BUFFER_SIZE:
|
|
return EFI_BAD_BUFFER_SIZE;
|
|
case STATUS_NOT_FOUND:
|
|
return EFI_NOT_FOUND;
|
|
case STATUS_DRIVER_UNABLE_TO_LOAD:
|
|
return EFI_LOAD_ERROR;
|
|
case STATUS_NO_MATCH:
|
|
return EFI_NO_MAPPING;
|
|
case STATUS_SUCCESS:
|
|
return EFI_SUCCESS;
|
|
case STATUS_TIMEOUT:
|
|
return EFI_TIMEOUT;
|
|
default:
|
|
return EFI_NO_MAPPING;
|
|
}
|
|
}
|
|
|
|
/*++
|
|
* @name EfiGetNtStatusCode
|
|
*
|
|
* The EfiGetNtStatusCode routine converts an EFI Status to an NT status.
|
|
*
|
|
* @param EfiStatus
|
|
* EFI Status code to be converted.
|
|
*
|
|
* @remark Only certain, specific EFI status codes are converted to NT codes.
|
|
*
|
|
* @return The corresponding NT Status code, STATUS_UNSUCCESSFUL otherwise.
|
|
*
|
|
*--*/
|
|
NTSTATUS
|
|
EfiGetNtStatusCode (
|
|
_In_ EFI_STATUS EfiStatus
|
|
)
|
|
{
|
|
switch (EfiStatus)
|
|
{
|
|
case EFI_NOT_READY:
|
|
case EFI_NOT_FOUND:
|
|
return STATUS_NOT_FOUND;
|
|
case EFI_NO_MEDIA:
|
|
return STATUS_NO_MEDIA;
|
|
case EFI_MEDIA_CHANGED:
|
|
return STATUS_MEDIA_CHANGED;
|
|
case EFI_ACCESS_DENIED:
|
|
case EFI_SECURITY_VIOLATION:
|
|
return STATUS_ACCESS_DENIED;
|
|
case EFI_TIMEOUT:
|
|
case EFI_NO_RESPONSE:
|
|
return STATUS_TIMEOUT;
|
|
case EFI_NO_MAPPING:
|
|
return STATUS_NO_MATCH;
|
|
case EFI_NOT_STARTED:
|
|
return STATUS_DEVICE_NOT_READY;
|
|
case EFI_ALREADY_STARTED:
|
|
return STATUS_DEVICE_ALREADY_ATTACHED;
|
|
case EFI_ABORTED:
|
|
return STATUS_REQUEST_ABORTED;
|
|
case EFI_VOLUME_FULL:
|
|
return STATUS_DISK_FULL;
|
|
case EFI_DEVICE_ERROR:
|
|
return STATUS_IO_DEVICE_ERROR;
|
|
case EFI_WRITE_PROTECTED:
|
|
return STATUS_MEDIA_WRITE_PROTECTED;
|
|
/* @FIXME: ReactOS Headers don't yet have this */
|
|
//case EFI_OUT_OF_RESOURCES:
|
|
//return STATUS_INSUFFICIENT_NVRAM_RESOURCES;
|
|
case EFI_VOLUME_CORRUPTED:
|
|
return STATUS_DISK_CORRUPT_ERROR;
|
|
case EFI_BUFFER_TOO_SMALL:
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
case EFI_SUCCESS:
|
|
return STATUS_SUCCESS;
|
|
case EFI_LOAD_ERROR:
|
|
return STATUS_DRIVER_UNABLE_TO_LOAD;
|
|
case EFI_INVALID_PARAMETER:
|
|
return STATUS_INVALID_PARAMETER;
|
|
case EFI_UNSUPPORTED:
|
|
return STATUS_NOT_SUPPORTED;
|
|
case EFI_BAD_BUFFER_SIZE:
|
|
return STATUS_INVALID_BUFFER_SIZE;
|
|
default:
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|