[BOOT:LIB] More initialization and cleanup

Started BlpMmDestroy(), MmMdDestroy(), MmPaDestroy(),
EfiSetWatchdogTimer(), EfiOpenProtocol(), EfiConInExSetState(), and
BlDestroyLibrary().
Completed BlpFwInitialize().
Improved InitializeLibrary().
This commit is contained in:
2024-10-06 13:50:21 -04:00
parent 620ede5862
commit 2472e39635
13 changed files with 777 additions and 225 deletions

View File

@@ -16,14 +16,17 @@ Abstract:
#include <ntrtl.h>
#include "bootlib.h"
#include "efi.h"
#include "efilib.h"
BOOT_FIRMWARE_DATA EfiFirmwareData;
PBOOT_FIRMWARE_DATA EfiFirmwareParameters;
EFI_HANDLE EfiImageHandle;
EFI_SYSTEM_TABLE *EfiST;
EFI_BOOT_SERVICES *EfiBS;
EFI_RUNTIME_SERVICES *EfiRT;
SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut;
SIMPLE_INPUT_INTERFACE *EfiConIn;
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *EfiConInEx;
NTSTATUS
BlpFwInitialize (
@@ -54,6 +57,9 @@ Return Value:
--*/
{
NTSTATUS Status;
EFI_KEY_TOGGLE_STATE KeyToggleState;
if (FirmwareData == NULL || FirmwareData->Version == 0) {
return STATUS_INVALID_PARAMETER;
}
@@ -62,16 +68,33 @@ Return Value:
RtlCopyMemory(&EfiFirmwareData, FirmwareData, sizeof(BOOT_FIRMWARE_DATA));
EfiFirmwareParameters = &EfiFirmwareData;
EfiImageHandle = FirmwareData->ImageHandle;
EfiST = FirmwareData->SystemTable;
EfiBS = EfiST->BootServices;
EfiRT = EfiST->RuntimeServices;
EfiConOut = EfiST->ConOut;
EfiConIn = EfiST->ConIn;
}
EfiConInEx = NULL;
} else if (Stage == 1) {
//
// Open the extended console input protocol.
// If successful, tell it to capture partial key events.
//
Status = EfiOpenProtocol(
EfiST->ConsoleInHandle,
&EfiSimpleTextInputExProtocol,
(VOID**)&EfiConInEx
);
if (NT_SUCCESS(Status)) {
KeyToggleState = EFI_KEY_STATE_EXPOSED | EFI_TOGGLE_STATE_VALID;
EfiConInExSetState(EfiConInEx, &KeyToggleState);
}
//
// TODO: Implement stage 1 initialization.
//
//
// Disable the watchdog timer.
//
EfiSetWatchdogTimer(0, 0, 0, NULL);
}
return STATUS_SUCCESS;
}

View File

@@ -14,6 +14,9 @@ Abstract:
--*/
#include "efilib.h"
#include "mm.h"
EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
EFI_STATUS
EfiGetEfiStatusCode (
@@ -84,7 +87,6 @@ Return Value:
}
}
NTSTATUS
EfiGetNtStatusCode (
IN EFI_STATUS Status
@@ -154,4 +156,381 @@ Return Value:
default:
return STATUS_UNSUCCESSFUL;
}
}
}
NTSTATUS
EfiGetMemoryMap (
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
IN OUT UINTN *MapKey,
IN OUT UINTN *DescriptorSize,
IN OUT UINT32 *DescriptorVersion
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.GetMemoryMap(). Gets the firmware memory map
and places it into a buffer.
Arguments:
MemoryMapSize - pointer to the size of the buffer.
MemoryMap - pointer to the buffer to store the memory map in.
MapKey - ponter to the memory map key.
DescriptorSize - pointer to the size of each memory map descriptor.
DescriptorVersion - pointer to the version of memory map descriptors.
Return Value:
STATUS_SUCCESS if successful.
STATUS_INVALID_PARAMETER if MemoryMapSize and/or MemoryMap are invalid.
STATUS_BUFFER_TOO_SMALL if MemoryMapSize is too small.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
//
// TODO: Translate addresses here.
// Need MmArchTranslateVirtualAddress().
//
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->GetMemoryMap(
MemoryMapSize,
MemoryMap,
MapKey,
DescriptorSize,
DescriptorVersion
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *Memory
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.AllocatePages(). Allocates contiguous pages
of physical memory.
Arguments:
Type - the type of allocation.
MemoryType - the type of memory to allocate.
Pages - the number of pages to allocate.
Memory - pointer to a physical address of the allocation.
Return Value:
STATUS_SUCCESS if successful.
STATUS_INVALID_PARAMETER if Type, MemoryType, and/or Memory are invalid.
STATUS_INSUFFICIENT_NVRAM_RESOURCES if the pages could not be allocated.
STATUS_NOT_FOUND if the pages could not be found.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->AllocatePages(
Type,
MemoryType,
Pages,
Memory
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN Pages
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.FreePages(). Frees contiguous pages
of physical memory.
Arguments:
Memory - physical address of the pages to be freed.
Pages - the number of pages to free.
Return Value:
STATUS_SUCCESS if successful.
STATUS_NOT_FOUND if the allocation was not found.
STATUS_INVALID_PARAMETER Memory and/or Pages are invalid.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->FreePages(
Memory,
Pages
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiSetWatchdogTimer (
IN UINTN Timeout,
IN UINT64 WatchdogCode,
IN UINTN DataSize,
IN CHAR16 *WatchdogData
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.SetWatchdogTimer().
Sets the watchdog timer.
Arguments:
Timeout - The number of seconds to set the timer to.
Setting this to 0 disables the timer.
WatchdogCode - The code to set when an event occurs.
DataSize - The size in bytes of WatchdogData.
WatchdogData - Optional pointer to a string containing
a description of the timer, possibly accompanied
by binary data.
Return Value:
STATUS_SUCCESS if successful.
STATUS_INVALID_PARAMETER if WatchdogCode is invalid.
STATUS_NOT_SUPPORTED if there is no Watchdog timer.
STATUS_IO_DEVICE_ERROR if the timer could not be set.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
if (Timeout != 0 && WatchdogCode <= 0xffff) {
return STATUS_INVALID_PARAMETER;
}
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
//
// TODO: Translate addresses here.
// Need MmArchTranslateVirtualAddress().
//
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->SetWatchdogTimer(
Timeout,
WatchdogCode,
DataSize,
WatchdogData
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiOpenProtocol (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN OUT VOID **Interface
)
/*++
Routine Description:
Wrapper that uses either EFI_BOOT_SERVICES.OpenProtocol() or HandleProtocol().
Opens a handle to a protocol and finds its interface.
Arguments:
Handle - The handle to the protocol to open.
Protocol - The GUID of the protocol.
Intercce - Pointer that recieves the address of the interface.
Return Value:
STATUS_SUCCESS if successful.
Error code on failure.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
NTSTATUS Status;
if (MmTranslationType != TRANSLATION_TYPE_NONE) {
//
// TODO: Translate addresses.
// Need EfiVmOpenProtocol().
//
DebugPrint(L"EfiOpenProtocol(): Virtual address translation not supported\r\n");
return STATUS_NOT_IMPLEMENTED;
}
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ExecutionContextFirmware);
}
//
// If supported, use OpenProtocol() (EFI 1.10+).
// It helps ensure the protocol is not uninstalled
// when still in use.
//
if (EfiST->Hdr.Revision >= EFI_MAKE_REVISION(1, 10)) {
EfiStatus = EfiBS->OpenProtocol(
Handle,
Protocol,
Interface,
EfiImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
} else {
EfiStatus = EfiBS->HandleProtocol(
Handle,
Protocol,
Interface
);
}
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
//
// Convert EFI status to NT status.
//
Status = EfiGetNtStatusCode(EfiStatus);
if (!NT_SUCCESS(Status)) {
*Interface = NULL;
}
return Status;
}
NTSTATUS
EfiConInExSetState (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *Protocol,
IN EFI_KEY_TOGGLE_STATE *KeyToggleState
)
/*++
Routine Description:
Wrapper around EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.SetState().
Sets an input protocol's state.
Arguments:
Protocol - The protocol to set the state of.
KeyToggle State - The state to set.
Return Value:
STATUS_SUCCESS if successful.
STATUS_IO_DEVICE_ERROR if the state could not be set.
STATUS_UNSUPPORTED if State is not supported by the device.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
//
// TODO: Translate addresses here.
// Need MmArchTranslateVirtualAddress().
//
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = Protocol->SetState(
Protocol,
KeyToggleState
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}

View File

@@ -23,172 +23,6 @@ Abstract:
#define EFI_PAGE(NtPage) (((NtPage) << PAGE_SHIFT) >> EFI_PAGE_SHIFT)
#define NT_PAGE(EfiPage) (((EfiPage) << EFI_PAGE_SHIFT) >> PAGE_SHIFT)
NTSTATUS
EfiGetMemoryMap (
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
IN OUT UINTN *MapKey,
IN OUT UINTN *DescriptorSize,
IN OUT UINT32 *DescriptorVersion
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.GetMemoryMap(). Gets the firmware memory map
and places it into a buffer.
Arguments:
MemoryMapSize - pointer to the size of the buffer.
MemoryMap - pointer to the buffer to store the memory map in.
MapKey - ponter to the memory map key.
DescriptorSize - pointer to the size of each memory map descriptor.
DescriptorVersion - pointer to the version of memory map descriptors.
Return Value:
STATUS_SUCCESS if successful,
Other NTSTATUS value if an error occurs.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
//
// TODO: Translate addresses here.
// Need MmArchTranslateVirtualAddress().
//
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->GetMemoryMap(
MemoryMapSize,
MemoryMap,
MapKey,
DescriptorSize,
DescriptorVersion
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *Memory
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.AllocatePages(). Allocates contiguous pages
of physical memory.
Arguments:
Type - the type of allocation.
MemoryType - the type of memory to allocate.
Pages - the number of pages to allocate.
Memory - pointer to a physical address of the allocation.
Return Value:
STATUS_SUCCESS if successful,
Other NTSTATUS value if an error occurs.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->AllocatePages(
Type,
MemoryType,
Pages,
Memory
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN Pages
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.FreePages(). Frees contiguous pages
of physical memory.
Arguments:
Memory - physical address of the pages to be freed.
Pages - the number of pages to free.
Return Value:
STATUS_SUCCESS if successful,
Other NTSTATUS value if an error occurs.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->FreePages(
Memory,
Pages
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
MEMORY_TYPE
BlMmTranslateEfiMemoryType (
IN EFI_MEMORY_TYPE EfiMemoryType

View File

@@ -17,6 +17,56 @@ Abstract:
#include "bootlib.h"
#include "mm.h"
ULONG MmTranslationType;
NTSTATUS
BlpMmDestroy (
IN ULONG Stage
)
/*++
Routine Description:
Cleans up after any actions performed by the memory manager.
After calling this, the memory manager can no longer be used.
Arguments:
Stage - Which stage of cleanup to perform.
Stage 0: Unknown.
Stage 1: Destroy all MM modules.
Return Value:
STATUS_SUCCESS if successful.
--*/
{
NTSTATUS Status, ExitStatus;
ExitStatus = STATUS_SUCCESS;
if (Stage == 1) {
Status = MmMdDestroy();
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
Status = MmPaDestroy(0);
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
Status = MmPaDestroy(1);
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
}
return ExitStatus;
}
NTSTATUS
BlpMmInitializeConstraints (
VOID
@@ -34,8 +84,7 @@ Arguments:
Return Value:
STATUS_SUCCESS if successful,
STATUS_SUCCESS if successful.
--*/
@@ -83,8 +132,8 @@ Return Value:
// Check TranslationType.
//
if (
TranslationType > TRANSLATION_TYPE_MAX ||
LibraryParameters->TranslationType > TRANSLATION_TYPE_MAX
TranslationType > TRANSLATION_TYPE_MAX
|| LibraryParameters->TranslationType > TRANSLATION_TYPE_MAX
) {
DebugPrint(L"BlpMmInitialize(): TranslationType is invalid\r\n");
return STATUS_INVALID_PARAMETER;
@@ -103,6 +152,8 @@ Return Value:
return Status;
}
MmTranslationType = LibraryParameters->TranslationType;
//
// TODO: Finish this routine.
//

View File

@@ -885,6 +885,35 @@ Return Value:
return Descriptor;
}
NTSTATUS
MmMdDestroy (
)
/*++
Routine Description:
Cleans up after any actions performed by the memory descriptor manager.
After calling this, the memory descriptor manager can no longer be used.
Arguments:
None.
Return Value:
STATUS_SUCCESS.
--*/
{
//
// TODO: Implement this routine.
//
return STATUS_SUCCESS;
}
VOID
MmMdInitialize (
IN ULONG Stage,

View File

@@ -58,6 +58,40 @@ Return Value:
Mdl->Type = MDL_TYPE_PHYSICAL;
}
NTSTATUS
MmPaDestroy (
IN ULONG Stage
)
/*++
Routine Description:
Cleans up after any actions performed by the page allocator.
After calling this, the page allocator can no longer be used.
Arguments:
Stage - Which stage of cleanup to perform.
Stage 0: Unknown.
Stage 1: Unknown.
Return Value:
STATUS_SUCCESS.
--*/
{
(VOID)Stage;
//
// TODO: Implement this routine.
//
return STATUS_SUCCESS;
}
NTSTATUS
MmPaInitialize (
IN PBOOT_MEMORY_INFO MemoryInfo,

View File

@@ -78,7 +78,7 @@ Return Value:
//
Status = BlpFwInitialize(0, FirmwareData);
if (!NT_SUCCESS(Status)) {
return Status;
goto Stage0Failed;
}
ConsolePrint(L"> Alcyone EFI Boot Manager\r\n");
@@ -86,7 +86,8 @@ Return Value:
if (ApplicationEntry->Signature != BOOT_INIT_APPLICATION_ENTRY_SIGNATURE) {
DebugPrint(L"InitializeLibrary(): ApplicationEntry Signature is invalid\r\n");
return STATUS_INVALID_PARAMETER_9;
Status = STATUS_INVALID_PARAMETER_9;
goto Stage0Failed;
}
//
@@ -104,14 +105,27 @@ Return Value:
Status = BlpArchInitialize(0);
if (!NT_SUCCESS(Status)) {
return Status;
goto Stage0Failed;
}
Status = BlpMmInitialize(MemoryInfo, ApplicationParameters->TranslationType, LibraryParameters);
if (!NT_SUCCESS(Status)) {
return Status;
goto Stage0Failed;
}
Status = BlpFwInitialize(1, FirmwareData);
if (!NT_SUCCESS(Status)) {
goto Stage1Failed;
}
Status = BlpArchInitialize(1);
if (!NT_SUCCESS(Status)) {
goto Stage1Failed;
}
Stage1Failed:
BlpMmDestroy(1);
Stage0Failed:
return STATUS_SUCCESS;
}
@@ -160,10 +174,25 @@ Arguments:
Return Value:
STATUS_SUCCESS.
STATUS_SUCCESS if successful.
Error code on failure.
--*/
{
return STATUS_SUCCESS;
NTSTATUS Status, ExitStatus;
ExitStatus = STATUS_SUCCESS;
Status = BlpMmDestroy(0);
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
Status = BlpMmDestroy(1);
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
return ExitStatus;
}