mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-01 04:13:35 +00:00
[BOOTMLIB]: Implement a few more BCD option functions. Minus a PE loader (BmpLaunchBootEntry) and some more BCD parsing (BmpGetSelectedBootEntry) with some glue in between, the UEFI Boot Manager is nearly done. Once it is, it will be time to implement the actual loader -- Winload.efi. The good news is that we'll have all of bootlib already good to go (with all its hacks). The bad news is that Winload will turn on paging, so all those unimplemented paths and UEFI mode switches will have to be made to work. svn path=/trunk/; revision=70556
454 lines
12 KiB
C
454 lines
12 KiB
C
/*
|
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
|
* PROJECT: ReactOS UEFI Boot Library
|
|
* FILE: boot/environ/lib/bootlib.c
|
|
* PURPOSE: Boot Library Initialization
|
|
* PROGRAMMER: Alex Ionescu ([email protected])
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include "bl.h"
|
|
|
|
/* DATA VARIABLES ************************************************************/
|
|
|
|
BL_LIBRARY_PARAMETERS BlpLibraryParameters;
|
|
PBL_DEVICE_DESCRIPTOR BlpBootDevice;
|
|
PWCHAR BlpApplicationBaseDirectory;
|
|
PBOOT_APPLICATION_PARAMETER_BLOCK BlpApplicationParameters;
|
|
BL_LOADED_APPLICATION_ENTRY BlpApplicationEntry;
|
|
BOOLEAN BlpLibraryParametersInitialized;
|
|
|
|
ULONG PdPersistAllocations;
|
|
LIST_ENTRY BlBadpListHead;
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/*++
|
|
* @name InitializeLibrary
|
|
*
|
|
* The InitializeLibrary function initializes the Boot Library.
|
|
*
|
|
* @param BootParameters
|
|
* Pointer to the Boot Application Parameter Block.
|
|
*
|
|
* @param LibraryParameters
|
|
* Pointer to the Boot Library Parameters.
|
|
*
|
|
* @return NT_SUCCESS if the boot library was loaded correctly, relevant error
|
|
* otherwise.
|
|
*
|
|
*--*/
|
|
NTSTATUS
|
|
InitializeLibrary (
|
|
_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootAppParameters,
|
|
_In_ PBL_LIBRARY_PARAMETERS LibraryParameters
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PBL_MEMORY_DATA MemoryData;
|
|
PBL_APPLICATION_ENTRY AppEntry;
|
|
PBL_FIRMWARE_DESCRIPTOR FirmwareDescriptor;
|
|
ULONG_PTR ParamPointer = (ULONG_PTR)BootAppParameters;
|
|
|
|
/* Validate correct Boot Application data */
|
|
if (!(BootAppParameters) ||
|
|
(BootAppParameters->Signature[0] != BOOT_APPLICATION_SIGNATURE_1) ||
|
|
(BootAppParameters->Signature[1] != BOOT_APPLICATION_SIGNATURE_2) ||
|
|
(BootAppParameters->Size < sizeof(*BootAppParameters)))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Get sub-structures */
|
|
MemoryData = (PBL_MEMORY_DATA)(ParamPointer + BootAppParameters->MemoryDataOffset);
|
|
FirmwareDescriptor = (PBL_FIRMWARE_DESCRIPTOR)(ParamPointer + BootAppParameters->FirmwareParametersOffset);
|
|
AppEntry = (PBL_APPLICATION_ENTRY)(ParamPointer + BootAppParameters->AppEntryOffset);
|
|
BlpBootDevice = (PBL_DEVICE_DESCRIPTOR)(ParamPointer + BootAppParameters->BootDeviceOffset);
|
|
BlpApplicationBaseDirectory = LibraryParameters->ApplicationBaseDirectory;
|
|
|
|
/* Initialize the firmware table */
|
|
Status = BlpFwInitialize(0, FirmwareDescriptor);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Find boot application entry */
|
|
if (strncmp(AppEntry->Signature, BL_APP_ENTRY_SIGNATURE, 7))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER_9;
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Read parameters */
|
|
BlpApplicationParameters = BootAppParameters;
|
|
BlpLibraryParameters = *LibraryParameters;
|
|
|
|
/* Check if the caller sent us their internal BCD options */
|
|
if (AppEntry->Flags & BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL)
|
|
{
|
|
/* These are external to us now, as far as we are concerned */
|
|
AppEntry->Flags &= ~BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL;
|
|
AppEntry->Flags |= BL_APPLICATION_ENTRY_BCD_OPTIONS_EXTERNAL;
|
|
}
|
|
|
|
/* Save the application entry flags */
|
|
BlpApplicationEntry.Flags = AppEntry->Flags;
|
|
|
|
/* Copy the GUID and point to the options */
|
|
BlpApplicationEntry.Guid = AppEntry->Guid;
|
|
BlpApplicationEntry.BcdData = &AppEntry->BcdData;
|
|
|
|
/* Everything has been captured */
|
|
BlpLibraryParametersInitialized = TRUE;
|
|
|
|
/* Initialize the architecture (PM or RM) switching */
|
|
Status = BlpArchInitialize(0);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Initialize the memory manager */
|
|
Status = BlpMmInitialize(MemoryData,
|
|
BootAppParameters->MemoryTranslationType,
|
|
LibraryParameters);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"MM init failed!\r\n");
|
|
goto Quickie;
|
|
}
|
|
|
|
/* Initialize firmware now that the heap, etc works */
|
|
Status = BlpFwInitialize(1, FirmwareDescriptor);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Destroy memory manager in phase 1 */
|
|
//BlpMmDestroy(1);
|
|
EfiPrintf(L"Firmware2 init failed!\r\n");
|
|
return Status;
|
|
}
|
|
|
|
#if 0
|
|
/* Modern systems have an undocumented BCD system for the boot frequency */
|
|
Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
|
|
0x15000075,
|
|
&BootFrequency);
|
|
if (NT_SUCCESS(Status) && (BootFrequency))
|
|
{
|
|
/* Use it if present */
|
|
BlpTimePerformanceFrequency = BootFrequency;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
/* Use the TSC for calibration */
|
|
Status = BlpTimeCalibratePerformanceCounter();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Destroy memory manager in phase 1 */
|
|
EfiPrintf(L"TSC calibration failed\r\n");
|
|
//BlpMmDestroy(1);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
/* Now setup the rest of the architecture (IDT, etc) */
|
|
Status = BlpArchInitialize(1);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Destroy memory manager in phase 1 */
|
|
EfiPrintf(L"Arch2 init failed\r\n");
|
|
//BlpMmDestroy(1);
|
|
return Status;
|
|
}
|
|
|
|
#ifdef BL_TPM_SUPPORT
|
|
/* Initialize support for Trusted Platform Module v1.2 */
|
|
BlpTpmInitialize();
|
|
#endif
|
|
|
|
#ifdef BL_TPM_SUPPORT
|
|
/* Initialize the event manager */
|
|
EnSubsystemInitialized = 1;
|
|
InitializeListHead(&EnEventNotificationList);
|
|
#endif
|
|
|
|
/* Initialize the I/O Manager */
|
|
Status = BlpIoInitialize();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Destroy memory manager in phase 1 and the event manager */
|
|
EfiPrintf(L"IO init failed\r\n");
|
|
#ifdef BL_TPM_SUPPORT
|
|
if (EnSubsystemInitialized)
|
|
{
|
|
BlpEnDestroy();
|
|
}
|
|
#endif
|
|
//BlpMmDestroy(1);
|
|
return Status;
|
|
}
|
|
|
|
#ifdef BL_NET_SUPPORT
|
|
/* Initialize the network stack */
|
|
Status = BlNetInitialize();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Destroy the I/O, event, and memory managers in phase 1 */
|
|
BlpIoDestroy();
|
|
#ifdef BL_TPM_SUPPORT
|
|
if (EnSubsystemInitialized)
|
|
{
|
|
BlpEnDestroy();
|
|
}
|
|
#endif
|
|
BlpMmDestroy(1);
|
|
return Status;
|
|
}
|
|
#endif
|
|
|
|
/* Initialize the utility library */
|
|
Status = BlUtlInitialize();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Destroy the network, I/O, event, and memory managers in phase 1 */
|
|
#ifdef BL_NET_SUPPORT
|
|
BlNetDestroy();
|
|
#endif
|
|
//BlpIoDestroy();
|
|
#ifdef BL_TPM_SUPPORT
|
|
if (EnSubsystemInitialized)
|
|
{
|
|
BlpEnDestroy();
|
|
}
|
|
#endif
|
|
//BlpMmDestroy(1);
|
|
EfiPrintf(L"Util init failed\r\n");
|
|
return Status;
|
|
}
|
|
|
|
#ifdef BL_KD_SUPPORT
|
|
/* Initialize PCI Platform Support */
|
|
PltInitializePciConfiguration();
|
|
#endif
|
|
|
|
#ifdef BL_SECURE_BOOT_SUPPORT
|
|
/* Read the current SecureBoot Policy*/
|
|
Status = BlSecureBootSetActivePolicyFromPersistedData();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Destroy everything that we've currently set up */
|
|
#ifdef BL_KD_SUPPORT
|
|
PltDestroyPciConfiguration();
|
|
#endif
|
|
#ifdef BL_NET_SUPPORT
|
|
BlNetDestroy();
|
|
#endif
|
|
BlpIoDestroy();
|
|
#ifdef BL_TPM_SUPPORT
|
|
if (EnSubsystemInitialized)
|
|
{
|
|
BlpEnDestroy();
|
|
}
|
|
#endif
|
|
BlpMmDestroy(1);
|
|
return Status;
|
|
}
|
|
#endif
|
|
|
|
#ifdef BL_TPM_SUPPORT
|
|
/* Initialize phase 0 of the security subsystem */
|
|
SipInitializePhase0();
|
|
#endif
|
|
|
|
#ifdef BL_KD_SUPPORT
|
|
/* Bring up the boot debugger, now that SecureBoot has been processed */
|
|
BlBdInitialize();
|
|
#endif
|
|
|
|
#ifdef BL_ETW_SUPPORT
|
|
/* Initialize internal logging */
|
|
BlpLogInitialize();
|
|
#endif
|
|
|
|
/* Are graphics enabled? */
|
|
if (!(LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_NO_DISPLAY))
|
|
{
|
|
/* Initialize the graphics library */
|
|
BlpDisplayInitialize(LibraryParameters->LibraryFlags);
|
|
}
|
|
|
|
/* Initialize the boot application persistent data */
|
|
PdPersistAllocations = 0;
|
|
InitializeListHead(&BlBadpListHead);
|
|
|
|
#ifdef BL_TPM_SUPPORT
|
|
/* Now setup the security subsystem in phase 1 */
|
|
BlpSiInitialize(1);
|
|
#endif
|
|
|
|
/* Setup the text, UI and font resources */
|
|
Status = BlpResourceInitialize();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Tear down everything if this failed */
|
|
if (!(LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_NO_DISPLAY))
|
|
{
|
|
// BlpDisplayDestroy();
|
|
}
|
|
#ifdef BL_KD_SUPPORT
|
|
BlpBdDestroy();
|
|
PltDestroyPciConfiguration();
|
|
#endif
|
|
#ifdef BL_NET_SUPPORT
|
|
BlNetDestroy();
|
|
#endif
|
|
//BlpIoDestroy();
|
|
#ifdef BL_TPM_SUPPORT
|
|
if (EnSubsystemInitialized)
|
|
{
|
|
BlpEnDestroy();
|
|
}
|
|
#endif
|
|
//BlpMmDestroy(1);
|
|
return Status;
|
|
}
|
|
|
|
#if BL_BITLOCKER_SUPPORT
|
|
/* Setup the boot cryptography library */
|
|
g_pEnvironmentData = &SymCryptEnvironmentWindowsBootLibrary;
|
|
if (SymCryptEnvWindowsBootLibInit)
|
|
{
|
|
SymCryptEnvWindowsBootLibInit();
|
|
}
|
|
#endif
|
|
|
|
/* We are fully initialized, remember this and exit with success */
|
|
BlpLibraryParameters.LibraryFlags |= BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED;
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Quickie:
|
|
return Status;
|
|
}
|
|
|
|
/*++
|
|
* @name BlInitializeLibrary
|
|
*
|
|
* The BlInitializeLibrary function initializes, or re-initializes, the
|
|
* Boot Library.
|
|
*
|
|
* @param BootParameters
|
|
* Pointer to the Boot Application Parameter Block.
|
|
*
|
|
* @param LibraryParameters
|
|
* Pointer to the Boot Library Parameters.
|
|
*
|
|
* @return NT_SUCCESS if the boot library was loaded correctly, relevant error
|
|
* otherwise.
|
|
*
|
|
*--*/
|
|
NTSTATUS
|
|
BlInitializeLibrary(
|
|
_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootAppParameters,
|
|
_In_ PBL_LIBRARY_PARAMETERS LibraryParameters
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
/* Are we re-initializing the library? */
|
|
if (LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE)
|
|
{
|
|
/* From scratch? */
|
|
BlpLibraryParameters = *LibraryParameters;
|
|
if (LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE_ALL)
|
|
{
|
|
#ifdef BL_TPM_SUPPORT
|
|
/* Reinitialize the TPM security enclave as BCD hash changed */
|
|
BlpSiInitialize(1);
|
|
#endif
|
|
#ifdef BL_KD_SUPPORT
|
|
/* Reinitialize the boot debugger as BCD debug options changed */
|
|
BlBdInitialize();
|
|
#endif
|
|
|
|
/* Reparse the bad page list now that the BCD has been reloaded */
|
|
BlMmRemoveBadMemory();
|
|
|
|
/* Reparse the low/high physical address limits as well */
|
|
BlpMmInitializeConstraints();
|
|
|
|
/* Redraw the graphics console as needed */
|
|
BlpDisplayInitialize(LibraryParameters->LibraryFlags);
|
|
|
|
/* Reinitialize resources (language may have changed) */
|
|
BlpResourceInitialize();
|
|
}
|
|
|
|
/* Nothing to do, we're done */
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
/* Nope, this is first time initialization */
|
|
Status = InitializeLibrary(BootAppParameters, LibraryParameters);
|
|
}
|
|
|
|
/* Return initialization status */
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
BlDestroyLibrary (
|
|
VOID
|
|
)
|
|
{
|
|
EfiPrintf(L"Destroy not yet implemented\r\n");
|
|
return;
|
|
}
|
|
|
|
PGUID
|
|
BlGetApplicationIdentifier (
|
|
VOID
|
|
)
|
|
{
|
|
/* Return the GUID, if one was present */
|
|
return (BlpApplicationEntry.Flags & BL_APPLICATION_ENTRY_FLAG_NO_GUID) ?
|
|
NULL : &BlpApplicationEntry.Guid;
|
|
}
|
|
|
|
NTSTATUS
|
|
BlGetApplicationBaseAndSize (
|
|
_Out_ PVOID* ImageBase,
|
|
_Out_ PULONG ImageSize
|
|
)
|
|
{
|
|
/* Fail if output parameters are missing */
|
|
if (!ImageBase || !ImageSize)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Return the requested data */
|
|
*ImageBase = (PVOID)(ULONG_PTR)BlpApplicationParameters->ImageBase;
|
|
*ImageSize = BlpApplicationParameters->ImageSize;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
BlDestroyBootEntry (
|
|
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry
|
|
)
|
|
{
|
|
/* Check if we had allocated BCD options */
|
|
if (AppEntry->Flags & BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL)
|
|
{
|
|
BlMmFreeHeap(AppEntry->BcdData);
|
|
}
|
|
|
|
/* Free the entry itself */
|
|
BlMmFreeHeap(AppEntry);
|
|
}
|