Wolf Team FC
Wolf Team FC

Reputation: 21

System stucks on attempt to load EFI driver image

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?

Upvotes: 2

Views: 595

Answers (2)

Wolf Team FC
Wolf Team FC

Reputation: 21

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!

Upvotes: 0

lior
lior

Reputation: 26

The shell probably gets stuck from code running in an infinite loop. The UEFI system relies on cooperative multitasking, so if your code gets stuck, no one (except higher IRQ) will stop it.

In addition, uefi_call_wrapper is part of gnu-uefi, are you sure that you are using EDK2?

Upvotes: 0

Related Questions