I build driver for UEFI subsystem using EDK-2 in which I implement one my custom protocol. To use this protocol functionality I load this driver into memory to find and use this protocol later. It works fine everywhere except one my test device(Lenovo ThinkPad) with UEFI v2.31. When I try to load my efi driver into memory system stucks. I tried to do it by code, later I tried to load this EFI image into memory from EFI shell, but got the same result.
I added some debug prints to my code to find out concrete step, when system stucks. So, it looks like it stucks on this call
BS->StartImage
Here is sample of code to load EFI driver image:
// try to generate path and load image from this path
// if absolute path was passed (start with "\EFI\")
// it (path) will not be changed
status = generate_path(loaded_image_info, image_path, &path_name);
PrintLineWithCLI("7");
if (status != EFI_SUCCESS)
return status;
PrintLineWithCLI("8");
devpath = FileDevicePath(loaded_image_info->DeviceHandle, path_name);
PrintLineWithCLI("9");
status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image_handle, devpath, NULL, 0, &image_to_execute);
PrintLineWithCLI("10");
if (status == EFI_SUCCESS)
{
PrintLineWithCLI("11");
// before start image we must add load options (if exist) to loaded image
if (load_options != NULL && load_options_size > 0)
{
PrintLineWithCLI("12");
// obtain information for image to execute (that we try to execute)
status = uefi_call_wrapper(BS->HandleProtocol, 3, image_to_execute, &gEfiLoadedImageProtocolGuid, (void **)&loaded_image_info);
PrintLineWithCLI("13");
if (status == EFI_SUCCESS)
{
PrintLineWithCLI("14");
// aas where and when we must free this memory?
loaded_image_info->LoadOptions = AllocateZeroPool(load_options_size);
loaded_image_info->LoadOptionsSize = load_options_size;
CopyMem(loaded_image_info->LoadOptions, load_options, load_options_size);
}
}
PrintLineWithCLI("15");
status = uefi_call_wrapper(BS->StartImage, 3, image_to_execute, NULL, NULL);
PrintLineWithCLI("16");
// do not unload image here - through this code we load drivers and drivers not have to be unloaded
//uefi_call_wrapper(BS->UnloadImage, 1, image_to_execute);
}
And on this line
status = uefi_call_wrapper(BS->StartImage, 3, image_to_execute, NULL, NULL);
system stucks.
I tried to add also some debug prints to entry point of my custom driver which I try to load in this way. Sample of driver entry point code here
EFI_STATUS
EFIAPI
DriverEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
ShellPrintEx(
-1,
-1,
L"1\n"
);
Status = EFI_SUCCESS;
//__debugbreak();
initilize_logging();
ShellPrintEx(
-1,
-1,
L"2\n"
);
ShellPrintEx(
-1,
-1,
L"3\n"
);
// Install UEFI Driver Model protocol(s).
//
Status = EfiLibInstallAllDriverProtocols2(
ImageHandle,
SystemTable,
NULL,
NULL, // pass NULL to always create new HANDLE for this driver - it's necessary for SECURE BOOT
&gComponentName,
&gComponentName2,
NULL,
NULL,
NULL,
NULL
);
ShellPrintEx(
-1,
-1,
L"4\n"
);
//ASSERT_EFI_ERROR(Status);
ShellPrintEx(
-1,
-1,
L"5\n"
);
if(EFI_SUCCESS == Status)
{
ShellPrintEx(
-1,
-1,
L"6\n"
);
Status = gBS->InstallProtocolInterface(
&ImageHandle,
&gEfiProtocolGuid,
EFI_NATIVE_INTERFACE,
&gProtocol
);
}
ShellPrintEx(
-1,
-1,
L"7\n"
);
return Status;
}
All of these prints were outed on a screen. But, after that it looks like systems stucks and execution doesn't return to the caller (who initiated driver loading) and next print after BS->StartImage is not outputed on a screen.
So, can somebody give me any ideas, why it happens and how to solve this problem?
I haven't implemented Driver Binding protocol at all to pass it as a parameter for the EfiLibInstallAllDriverProtocols2 method. As described @MiSimon: the DriverBinding parameter for the EfiLibInstallAllDriverProtocols2 method is not marked as optional, in the current EDK2 sources there is an ASSERT (DriverBinding != NULL) at the start of this function, passing NULL may result in undefined behaviour. So I had to create a dummy DriverBinding protocol (return EFI_UNSUPPORTED from Start, Stop, Supported) and pass it to EfiLibInstallAllDriverProtocols2. That resolved the problem. @MiSimon, thank you for your help!