mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 14:18:41 +00:00
481 lines
13 KiB
C
481 lines
13 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 (alex.ionescu@reactos.org)
|
|
*/
|
|
|
|
/* 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 BlpApplicationFlags;
|
|
|
|
ULONG PdPersistAllocations;
|
|
LIST_ENTRY BlpPdListHead;
|
|
|
|
/* 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;
|
|
LARGE_INTEGER BootFrequency;
|
|
ULONG_PTR ParamPointer;
|
|
|
|
/* Validate correct Boot Application data */
|
|
ParamPointer = (ULONG_PTR)BootAppParameters;
|
|
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;
|
|
}
|
|
|
|
/* Modern systems have an undocumented BCD system for the boot frequency */
|
|
Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
|
|
0x15000075,
|
|
(PULONGLONG)&BootFrequency.QuadPart);
|
|
if (NT_SUCCESS(Status) && (BootFrequency.QuadPart))
|
|
{
|
|
/* Use it if present */
|
|
BlpTimePerformanceFrequency = BootFrequency.QuadPart;
|
|
}
|
|
else
|
|
{
|
|
/* 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(&BlpPdListHead);
|
|
|
|
#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);
|
|
}
|
|
|
|
NTSTATUS
|
|
BlPdQueryData (
|
|
_In_ const GUID* DataGuid,
|
|
_In_ PVOID Unknown,
|
|
_Inout_ PBL_PD_DATA_BLOB DataBlob
|
|
)
|
|
{
|
|
/* Check for invalid or missing parameters */
|
|
if (!(DataBlob) ||
|
|
!(DataGuid) ||
|
|
((DataBlob->BlobSize) && !(DataBlob->Data)))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Check if there's no persistent data blobs */
|
|
if (IsListEmpty(&BlpPdListHead))
|
|
{
|
|
return STATUS_NOT_FOUND;
|
|
}
|
|
|
|
/* Not yet handled, TODO */
|
|
EfiPrintf(L"Boot persistent data not yet implemented\r\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|