reactos/boot/environ/lib/bootlib.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;
}