/*++ Copyright (c) 2024, Quinn Stephens. Provided under the BSD 3-Clause license. Module Name: bootlib.c Abstract: Provides boot library utilities. --*/ #include #include "bootlib.h" // // Total size of required structures. // #define MIN_INPUT_PARAMETERS_SIZE ( \ sizeof(BOOT_INPUT_PARAMETERS) + \ sizeof(BOOT_MEMORY_INFO) + \ sizeof(BOOT_FIRMWARE_DATA) + \ sizeof(BOOT_RETURN_DATA) \ ) PBOOT_INPUT_PARAMETERS BlpApplicationParameters; BOOT_APPLICATION_ENTRY BlpApplicationEntry; PBOOT_DEVICE BlpBootDevice; NTSTATUS InitializeLibrary ( IN PBOOT_INPUT_PARAMETERS InputParameters, IN PBOOT_LIBRARY_PARAMETERS LibraryParameters ) /*++ Routine Description: Internal routine to initialize the boot library. Arguments: InputParameters - pointer to the input parameters structure. LibraryParameters - pointer to the library parameters structure. Return Value: STATUS_SUCCESS if successful. --*/ { NTSTATUS Status; PBOOT_MEMORY_INFO MemoryInfo; PBOOT_INPUT_APPLICATION_ENTRY ApplicationEntry; PBOOT_FIRMWARE_DATA FirmwareData; PBOOT_BLOCK_IDENTIFIER BlockDevice; PBOOT_APPLICATION_OPTION Option; (VOID)LibraryParameters; // // Verify input parameters structure. // if (InputParameters == NULL || InputParameters->Signature != BOOT_INPUT_PARAMETERS_SIGNATURE || InputParameters->Size < MIN_INPUT_PARAMETERS_SIZE) { return STATUS_INVALID_PARAMETER; } // // Calculate structure addresses from offsets. // MemoryInfo = (PBOOT_MEMORY_INFO)((PUCHAR)InputParameters + InputParameters->MemoryInfoOffset); ApplicationEntry = (PBOOT_INPUT_APPLICATION_ENTRY)((PUCHAR)InputParameters + InputParameters->ApplicationEntryOffset); BlpBootDevice = (PBOOT_DEVICE)((PUCHAR)InputParameters + InputParameters->BootDeviceOffset); FirmwareData = (PBOOT_FIRMWARE_DATA)((PUCHAR)InputParameters + InputParameters->FirmwareDataOffset); // // Initialize firmware library. // It is important to do this early so that // ConsolePrint() and DebugPrint() can be used. // Status = BlpFwInitialize(0, FirmwareData); if (!NT_SUCCESS(Status)) { return Status; } // // Print image information. // ConsolePrintf(L"Image base: %x %x\r\n", (ULONG)((ULONG_PTR)InputParameters->ImageBase >> 32), (ULONG)((ULONG_PTR)InputParameters->ImageBase)); ConsolePrintf(L"Image size: %x\r\n", InputParameters->ImageSize); // // Check application entry signature. // if (ApplicationEntry->Signature != BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE) { DebugPrint(L"InitializeLibrary(): ApplicationEntry Signature is invalid\r\n"); return STATUS_INVALID_PARAMETER_9; } // // Save input parameters and application entry data. // BlpApplicationParameters = InputParameters; BlpApplicationEntry.Attributes = ApplicationEntry->Attributes; RtlCopyMemory(&BlpApplicationEntry.BcdIdentifier, &ApplicationEntry->BcdIdentifier, sizeof(GUID)); BlpApplicationEntry.Options = &ApplicationEntry->Options; // // Initialize memory manager. // Status = BlpMmInitialize(MemoryInfo, InputParameters->TranslationType, LibraryParameters); if (!NT_SUCCESS(Status)) { return Status; } // // Print debug information. // TODO: Remove this once the project is more stable? // #ifdef _DEBUG DebugPrint(L"Boot device type: "); switch (BlpBootDevice->Type) { case BOOT_DEVICE_TYPE_PARTITION: DebugPrint(L"partition\r\n"); BlockDevice = &BlpBootDevice->Partition.Parent; break; case BOOT_DEVICE_TYPE_PARTITION_EX: DebugPrint(L"partition\r\n"); BlockDevice = &BlpBootDevice->PartitionEx.Parent; break; default: DebugPrint(L"generic block device\r\n"); BlockDevice = &BlpBootDevice->Block; break; } DebugPrint(L"Boot device parent type: "); switch (BlockDevice->Type) { case BOOT_BLOCK_DEVICE_TYPE_HARDDRIVE: DebugPrint(L"hard drive\r\n"); break; case BOOT_BLOCK_DEVICE_TYPE_CDROM: DebugPrint(L"CD-ROM\r\n"); break; case BOOT_BLOCK_DEVICE_TYPE_RAMDISK: DebugPrint(L"RAM disk\r\n"); break; default: DebugPrint(L"generic block device\r\n"); break; } Option = &ApplicationEntry->Options; for (ULONG Index = 0; !Option->IsInvalid; Index++) { DebugPrintf(L"Boot entry option %x: ", Index); if (Option->Type == BCDE_DATA_TYPE_APPLICATION_PATH) { DebugPrint(L"application path \""); DebugPrint((PWSTR)((PUCHAR)Option + Option->DataOffset)); DebugPrint(L"\"\r\n"); } else { DebugPrintf(L"type %x, data size %x\r\n", Option->Type, Option->DataSize); } if (Option->NextOptionOffset == 0) { break; } Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)Option + Option->NextOptionOffset); } #endif return STATUS_SUCCESS; } NTSTATUS BlInitializeLibrary ( IN PBOOT_INPUT_PARAMETERS InputParameters, IN PBOOT_LIBRARY_PARAMETERS LibraryParameters ) /*++ Routine Description: Initializes the boot library. Arguments: InputParameters - pointer to the input parameters structure. LibraryParameters - pointer to the library parameters structure. Return Value: Any value returned by InitializeLibrary(). --*/ { return InitializeLibrary(InputParameters, LibraryParameters); } NTSTATUS BlDestroyLibrary ( VOID ) /*++ Routine Description: Cleans up after the boot library. Arguments: None. Return Value: STATUS_SUCCESS if successful. Error status if an error is encountered. --*/ { return STATUS_SUCCESS; }