Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / boot / environ / lib / firmware / efi / firmware.c
diff --git a/boot/environ/lib/firmware/efi/firmware.c b/boot/environ/lib/firmware/efi/firmware.c
new file mode 100644 (file)
index 0000000..915de6d
--- /dev/null
@@ -0,0 +1,2592 @@
+/*
+ * 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 = (PVOID)InterfaceAddress.LowPart;
+    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*)ConInExPhys.LowPart;
+        BlMmTranslateVirtualAddress(KeyToggleState, &KeyTogglePhys);
+        KeyToggleState = (EFI_KEY_TOGGLE_STATE*)KeyTogglePhys.LowPart;
+
+        /* 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*)MemoryMapSizePhysical.LowPart;
+        BlMmTranslateVirtualAddress(MemoryMap, &MemoryMapPhysical);
+        MemoryMap = (EFI_MEMORY_DESCRIPTOR*)MemoryMapPhysical.LowPart;
+        BlMmTranslateVirtualAddress(MapKey, &MapKeyPhysical);
+        MapKey = (UINTN*)MapKeyPhysical.LowPart;
+        BlMmTranslateVirtualAddress(DescriptorSize, &DescriptorSizePhysical);
+        DescriptorSize = (UINTN*)DescriptorSizePhysical.LowPart;
+        BlMmTranslateVirtualAddress(DescriptorVersion, &DescriptorVersionPhysical);
+        DescriptorVersion = (UINTN*)DescriptorVersionPhysical.LowPart;
+
+        /* 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 = (PVOID)GopInterfacePhys.LowPart;
+
+        /* Translate pointer to physical */
+        BlMmTranslateVirtualAddress(FrameBuffer, &FrameBufferPhys);
+        FrameBuffer = (PVOID)FrameBufferPhys.LowPart;
+
+        /* Translate pointer to physical */
+        BlMmTranslateVirtualAddress(FrameBufferSize, &FrameBufferSizePhys);
+        FrameBufferSize = (PVOID)FrameBufferSizePhys.LowPart;
+
+        /* 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 = (PVOID)GopInterfacePhys.LowPart;
+
+        /* Translate pointer to physical */
+        if (!BlMmTranslateVirtualAddress(Mode, &ModePhys))
+        {
+            return STATUS_UNSUCCESSFUL;
+        }
+        Mode = (PVOID)ModePhys.LowPart;
+
+        /* Translate pointer to physical */
+        if (!BlMmTranslateVirtualAddress(Information, &InformationPhys))
+        {
+            return STATUS_UNSUCCESSFUL;
+        }
+        Information = (PVOID)InformationPhys.LowPart;
+
+        /* 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 ? (PVOID)BufferPhys.LowPart : 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 ? (PVOID)BufferPhys.LowPart : 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*)MemoryPhysical.LowPart;
+
+        /* 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;
+    }
+}