alcyone/BOOT/ENVIRON/LIB/EFI/efiinit.c

249 lines
6.7 KiB
C

/*++
Copyright (c) 2024, Quinn Stephens.
Provided under the BSD 3-Clause license.
Module Name:
efiinit.c
Abstract:
Provides EFI initialization utilities.
--*/
#include "bootmgr.h"
#include "efi.h"
UCHAR EfiInitScratch[2048];
const EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
const EFI_GUID EfiDevicePathProtocol = DEVICE_PATH_PROTOCOL;
VOID
EfiInitpCreateApplicationEntry (
IN EFI_SYSTEM_TABLE *SystemTable,
IN OUT PBOOT_APPLICATION_ENTRY Entry,
IN ULONG BufferSize,
IN EFI_DEVICE_PATH *DevicePath,
IN EFI_DEVICE_PATH *FilePath,
IN PWCHAR LoadOptions,
IN ULONG LoadOptionsSize,
OUT PULONG BufferUsed,
OUT PBOOT_DEVICE *Device
)
/*++
Routine Description:
Creates an application entry structure for the boot application.
Arguments:
SystemTable - Pointer to the EFI system table.
Entry - A buffer to put the entry in.
BufferSize - The amount of available space in the buffer.
DevicePath - The device path for the application.
FilePath - The file path for the application.
LoadOptions - Firmware load options string.
LoadOptionsSize - Length of the string pointed to by LoadOptions.
BufferUsed - Returns the amount of buffer space used by the routine.
Device - Returns a pointer to the device the application was loaded from.
Return Value:
None.
--*/
{
//
// Require enough space for the application entry.
//
if (BufferSize < sizeof(BOOT_APPLICATION_ENTRY)) {
*BufferUsed = 0;
return;
}
//
// Set up application entry structure.
//
RtlZeroMemory(Entry, sizeof(BOOT_APPLICATION_ENTRY));
Entry->Signature = BOOT_APPLICATION_ENTRY_SIGNATURE;
//
// TODO: This routine is not fully implemented.
//
(VOID)SystemTable;
(VOID)DevicePath;
(VOID)FilePath;
(VOID)LoadOptions;
(VOID)LoadOptionsSize;
(VOID)Device;
*BufferUsed = sizeof(BOOT_APPLICATION_ENTRY);
}
PBOOT_INPUT_PARAMETERS
EfiInitCreateInputParameters (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Creates the input parameter structure for the boot application.
Arguments:
ImageHandle - Handle for the boot manager image.
SystemTable - Pointer to the EFI system table.
Return Value:
Pointer to parameter structure on success or NULL on failure.
--*/
{
ULONG ScratchUsed = 0;
ULONG ApplicationEntrySize = 0;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS BadPageAddress;
EFI_LOADED_IMAGE *LoadedImage;
EFI_DEVICE_PATH *DevicePath;
PBOOT_INPUT_PARAMETERS InputParameters;
PBOOT_MEMORY_INFO MemoryInfo;
PBOOT_MEMORY_DESCRIPTOR MemoryDescriptor;
PBOOT_DEVICE BootDevice;
PBOOT_FIRMWARE_DATA FirmwareData;
PBOOT_RETURN_DATA ReturnData;
//
// Page 0x102 may be broken on some machines.
// It is mapped here so that it does not get used.
//
BadPageAddress = 0x102 << PAGE_SHIFT;
SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, 1, &BadPageAddress);
//
// Get boot manager image information.
//
Status = SystemTable->BootServices->HandleProtocol(
ImageHandle,
(EFI_GUID*)&EfiLoadedImageProtocol,
(VOID**)&LoadedImage
);
if (Status != EFI_SUCCESS) {
return NULL;
}
//
// Get boot manager image device path.
//
Status = SystemTable->BootServices->HandleProtocol(
LoadedImage->DeviceHandle,
(EFI_GUID*)&EfiDevicePathProtocol,
(VOID**)&DevicePath
);
if (Status != EFI_SUCCESS) {
return NULL;
}
//
// Create input parameters structure.
//
InputParameters = (PBOOT_INPUT_PARAMETERS)(&EfiInitScratch[ScratchUsed]);
ScratchUsed += sizeof(BOOT_INPUT_PARAMETERS);
InputParameters->Signature = BOOT_INPUT_PARAMETERS_SIGNATURE;
InputParameters->Version = BOOT_INPUT_PARAMETERS_VERSION;
InputParameters->MachineType = BOOT_MACHINE_TYPE;
InputParameters->TranslationType = BOOT_TRANSLATION_TYPE;
InputParameters->ImageBase = LoadedImage->ImageBase;
InputParameters->ImageSize = LoadedImage->ImageSize;
//
// Create memory info structure.
//
InputParameters->MemoryInfoOffset = ScratchUsed;
MemoryInfo = (PBOOT_MEMORY_INFO)(&EfiInitScratch[ScratchUsed]);
ScratchUsed += sizeof(BOOT_MEMORY_INFO);
MemoryInfo->Version = BOOT_MEMORY_INFO_VERSION;
MemoryInfo->MdlOffset = sizeof(BOOT_MEMORY_INFO);
MemoryInfo->DescriptorCount = 1;
MemoryInfo->DescriptorSize = sizeof(BOOT_MEMORY_DESCRIPTOR);
MemoryInfo->BasePageOffset = FIELD_OFFSET(BOOT_MEMORY_DESCRIPTOR, BasePage);
//
// Create a memory descriptor for the boot manager image.
//
MemoryDescriptor = (PBOOT_MEMORY_DESCRIPTOR)(&EfiInitScratch[ScratchUsed]);
ScratchUsed += sizeof(BOOT_MEMORY_DESCRIPTOR);
MemoryDescriptor->BasePage = (UINTN)InputParameters->ImageBase >> PAGE_SHIFT;
MemoryDescriptor->Pages = ALIGN_UP(InputParameters->ImageSize, PAGE_SIZE) >> PAGE_SHIFT;
MemoryDescriptor->Flags = MEMORY_FLAG_CACHE_WB;
MemoryDescriptor->Type = MEMORY_TYPE_BOOT_APPLICATION;
//
// Create an application entry for the boot application.
//
InputParameters->ApplicationEntryOffset = ScratchUsed;
EfiInitpCreateApplicationEntry(
SystemTable,
(PBOOT_APPLICATION_ENTRY)(&EfiInitScratch[ScratchUsed]),
sizeof(EfiInitScratch) - ScratchUsed,
DevicePath,
LoadedImage->FilePath,
LoadedImage->LoadOptions,
LoadedImage->LoadOptionsSize,
&ApplicationEntrySize,
&BootDevice
);
ScratchUsed += ApplicationEntrySize;
//
// Copy application device to scratch area.
//
InputParameters->BootDeviceOffset = ScratchUsed;
if (BootDevice != NULL) {
RtlCopyMemory(&EfiInitScratch[ScratchUsed], BootDevice, BootDevice->Size);
ScratchUsed += BootDevice->Size;
} else {
RtlZeroMemory(&EfiInitScratch[ScratchUsed], sizeof(BOOT_DEVICE));
ScratchUsed += sizeof(BOOT_DEVICE);
}
//
// Create firmware data structure.
//
InputParameters->FirmwareDataOffset = ScratchUsed;
FirmwareData = (PBOOT_FIRMWARE_DATA)(&EfiInitScratch[ScratchUsed]);
ScratchUsed += sizeof(BOOT_FIRMWARE_DATA);
FirmwareData->Version = BOOT_FIRMWARE_DATA_VERSION;
FirmwareData->Reserved = 0;
FirmwareData->ImageHandle = ImageHandle;
FirmwareData->SystemTable = SystemTable;
//
// Create return data structure.
//
InputParameters->ReturnDataOffset = ScratchUsed;
ReturnData = (PBOOT_RETURN_DATA)(&EfiInitScratch[ScratchUsed]);
ScratchUsed += sizeof(BOOT_RETURN_DATA);
ReturnData->Version = BOOT_RETURN_DATA_VERSION;
InputParameters->Size = ScratchUsed;
return InputParameters;
}