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 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 *
_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(DevicePath1) && !IsDevicePathEndType(DevicePath2))
+ while (!(IsDevicePathEndType(CurrentPath1)) &&
+ !(IsDevicePathEndType(CurrentPath2)))
{
/* Check if the element has a different length */
- Length1 = DevicePathNodeLength(DevicePath1);
- Length2 = DevicePathNodeLength(DevicePath2);
+ Length1 = DevicePathNodeLength(CurrentPath1);
+ Length2 = DevicePathNodeLength(CurrentPath2);
if (Length1 != Length2)
{
/* Then they're not related */
}
/* Check if the rest of the element data matches */
- if (RtlCompareMemory(DevicePath1, DevicePath2, Length1) != Length1)
+ if (RtlCompareMemory(CurrentPath1, CurrentPath2, Length1) != Length1)
{
/* Nope, not related */
return NULL;
}
/* Move to the next element */
- DevicePath1 = NextDevicePathNode(DevicePath1);
- DevicePath2 = NextDevicePathNode(DevicePath2);
+ CurrentPath1 = NextDevicePathNode(CurrentPath1);
+ CurrentPath2 = NextDevicePathNode(CurrentPath2);
}
/* If the last element in path 1 is empty, then path 2 is the child (deeper) */
- if (!IsDevicePathEndType(DevicePath1))
+ if (!IsDevicePathEndType(CurrentPath1))
{
return DevicePath2;
}
/* If the last element in path 2 is empty, then path 1 is the child (deeper) */
- if (!IsDevicePathEndType(DevicePath2))
+ if (!IsDevicePathEndType(CurrentPath2))
{
return DevicePath1;
}
}
}
- /* This now contains the deepeest (leaf) node */
+ /* This now contains the deepest (leaf) node */
return DevicePath;
}
}
else
{
- /* FIXME: @TODO: Not yet supported */
+ /* 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 */
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 */
+ 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 */
+ 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 */
+ 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,
{
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)
{
- /* FIXME: Not yet implemented */
- return STATUS_NOT_IMPLEMENTED;
+ /* 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(BlProtectedMode);
}
/* Make the EFI call */
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 */
+ 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,
if ((ModeChanged) && (NT_SUCCESS(Status)))
{
/* FIXME @TODO: Should be BlStatusPrint */
- EfiPrintf(L"Console video mode set to 0x%x\r\r\n", Mode);
+ EfiPrintf(L"Console video mode set to 0x%x\r\n", Mode);
}
/* Convert the error to an NTSTATUS */
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 */
+ 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,
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
NTSTATUS Status;
ULONGLONG Pages, StartPage, EndPage;
UINTN EfiMemoryMapSize, MapKey, DescriptorSize, DescriptorVersion;
- EFI_PHYSICAL_ADDRESS EfiBuffer;
+ EFI_PHYSICAL_ADDRESS EfiBuffer = 0;
EFI_MEMORY_DESCRIPTOR* EfiMemoryMap;
EFI_STATUS EfiStatus;
BL_ARCH_MODE OldMode;
/* Loop the EFI memory map */
#if 0
- EfiPrintf(L"UEFI MEMORY MAP\n\r\n");
+ EfiPrintf(L"UEFI MEMORY MAP\r\n\r\n");
EfiPrintf(L"TYPE START END ATTRIBUTES\r\n");
EfiPrintf(L"===============================================================\r\n");
#endif
if (Descriptor->Type == BlConventionalMemory)
{
/* Set the reserved flag on the descriptor */
- Descriptor->Flags |= BlReservedMemory;
+ EfiPrintf(L"Adding magic flag\r\n");
+ Descriptor->Flags |= BlMemoryReserved;
}
/* Add this descriptor into the list */
if ((Descriptor->Type == BlConventionalMemory) && (EndPage <= 0x100))
{
/* Set the reserved flag on the descriptor */
- Descriptor->Flags |= BlReservedMemory;
+ EfiPrintf(L"Adding magic flag\r\n");
+ Descriptor->Flags |= BlMemoryReserved;
}
/* 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);
+ ((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);
NTSTATUS Status = STATUS_SUCCESS;
EFI_KEY_TOGGLE_STATE KeyToggleState;
- /* Check if we have vaild firmware data */
+ /* Check if we have valid firmware data */
if (!(FirmwareData) || !(FirmwareData->Version))
{
return STATUS_INVALID_PARAMETER;
/* FIXME: Not supported */
Status = STATUS_NOT_SUPPORTED;
}
- else if (FirmwareData->Version >= 2)
+ else if (FirmwareData->Version >= BL_FIRMWARE_DESCRIPTOR_VERSION)
{
/* Version 2 -- save the data */
EfiFirmwareData = *FirmwareData;
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