/*++ Copyright (c) 2024, Quinn Stephens. Provided under the BSD 3-Clause license. Module Name: bootlib.c Abstract: Provides boot library utilities. --*/ #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) \ ) ULONG BlGetBootOptionListSize ( IN PBOOT_APPLICATION_OPTION Options ); ULONG BlGetBootOptionSize ( IN PBOOT_APPLICATION_OPTION Option ) /*++ Routine Description: Gets the size of a boot option. Arguments: Option - the boot option to get the size of. Return Value: The size of the option. --*/ { ULONG TotalSize; if (Option->DataOffset != 0) { TotalSize = Option->DataOffset + Option->DataSize; } else { TotalSize = sizeof(BOOT_APPLICATION_OPTION); } if (Option->OtherOptionsOffset != 0) { TotalSize += BlGetBootOptionListSize((PBOOT_APPLICATION_OPTION)((PUCHAR)Option + Option->OtherOptionsOffset)); } return TotalSize; } ULONG BlGetBootOptionListSize ( IN PBOOT_APPLICATION_OPTION Options ) /*++ Routine Description: Gets the total size of a list boot options. Arguments: Options - the boot option list to get the size of. Return Value: The size of the options. --*/ { ULONG TotalSize, NextOffset; PBOOT_APPLICATION_OPTION Option; TotalSize = 0; NextOffset = 0; do { Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)Options + NextOffset); NextOffset = Option->NextOptionOffset; TotalSize += BlGetBootOptionSize(Option); } while (NextOffset != 0); return TotalSize; } 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_INPUT_APPLICATION_ENTRY ApplicationEntry; PBOOT_DEVICE BootDevice; 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. // ApplicationEntry = (PBOOT_INPUT_APPLICATION_ENTRY)((PUCHAR)InputParameters + InputParameters->ApplicationEntryOffset); BootDevice = (PBOOT_DEVICE)((PUCHAR)InputParameters + InputParameters->BootDeviceOffset); FirmwareData = (PBOOT_FIRMWARE_DATA)((PUCHAR)InputParameters + InputParameters->FirmwareDataOffset); // // Initialize firmware library. // Status = BlpFwInitialize(0, FirmwareData); if (!NT_SUCCESS(Status)) { return Status; } // // Print debug 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); ConsolePrint(L"Boot device type: "); switch (BootDevice->Type) { case BOOT_DEVICE_TYPE_PARTITION: ConsolePrint(L"partition\r\n"); BlockDevice = &BootDevice->Partition.Parent; break; case BOOT_DEVICE_TYPE_PARTITION_EX: ConsolePrint(L"partition\r\n"); BlockDevice = &BootDevice->PartitionEx.Parent; break; default: ConsolePrint(L"generic block device\r\n"); BlockDevice = &BootDevice->Block; break; } ConsolePrint(L"Boot device parent type: "); switch (BlockDevice->Type) { case BOOT_BLOCK_DEVICE_TYPE_HARDDRIVE: ConsolePrint(L"hard drive\r\n"); break; case BOOT_BLOCK_DEVICE_TYPE_CDROM: ConsolePrint(L"CD-ROM\r\n"); break; case BOOT_BLOCK_DEVICE_TYPE_RAMDISK: ConsolePrint(L"RAM disk\r\n"); break; default: ConsolePrint(L"generic block device\r\n"); break; } Option = &ApplicationEntry->Options; for (ULONG Index = 0; !Option->IsInvalid; Index++) { ConsolePrintf(L"Boot entry option %x: ", Index); if (Option->Type == BCDE_DATA_TYPE_APPLICATION_PATH) { ConsolePrint(L"application path \""); ConsolePrint((PWSTR)((PUCHAR)Option + Option->DataOffset)); ConsolePrint(L"\"\r\n"); } else { ConsolePrintf(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); } 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; }