driveruefidynamic-loading

UEFI Application: UEFI NTFS driver is not loading properly


I'm working on an EFI application to load an NTFS driver (ntfs_x64.efi). When I load the driver from the EFI shell using "load ntfs_x64.efi" command, it works perfectly. However, when I try to load the driver programmatically from within my EFI application, it loads, but Type and #D are not getting assigned.

DRV | Version | Type | CFG | DIAG | #D | #C | DriverName | ImageName | Working (Shell) enter image description here Not Working (EFI APP) enter image description here

I would appreciate any insights or suggestions on how to troubleshoot this issue.

Program

EFI_STATUS
EFIAPI
LoadNtfsDriver(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
    EFI_STATUS Status;
    EFI_HANDLE LoadedImageHandle;
    EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
    EFI_DEVICE_PATH_PROTOCOL *DevicePath;
    UINTN ExitDataSize = 4*1024;
    CHAR16 *ExitData = NULL;

    // Allocate memory for ExitData
    ExitData = AllocatePool(ExitDataSize);
    if (ExitData == NULL) {
        Print(L"Failed to allocate memory for ExitData.\n");
        return EFI_OUT_OF_RESOURCES;
    }
    Print(L"Memory allocated\n");

    // Get the Loaded Image Protocol for the current image to access its device handle
    Status = gBS->OpenProtocol(
        ImageHandle,
        &gEfiLoadedImageProtocolGuid,
        (VOID **)&LoadedImage,
        ImageHandle,
        NULL,
        EFI_OPEN_PROTOCOL_GET_PROTOCOL);
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to get LoadedImageProtocol: %r\n", Status);
        return Status;
    }

    // Create a device path for the NTFS driver file
    DevicePath = FileDevicePath(LoadedImage->DeviceHandle, NTFS_DRIVER_PATH);
    if (DevicePath == NULL)
    {
        Print(L"Failed to create device path for %s\n", NTFS_DRIVER_PATH);
        return EFI_NOT_FOUND;
    }

    // Load the NTFS driver (ntfs_x64.efi)
    Status = gBS->LoadImage(
        FALSE,             // Not a Boot Image
        ImageHandle,       // Parent image handle
        DevicePath,        // Path to the NTFS driver
        NULL,              // Optional source buffer
        0,                 // Size of the source buffer
        &LoadedImageHandle // Image handle for the loaded driver
    );
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to load %s: %r\n", NTFS_DRIVER_PATH, Status);
        FreePool(DevicePath);
        return Status;
    }
    Print(L"%s loaded successfully.\n", NTFS_DRIVER_PATH);
    Print(L"Status: %r\n", Status);
    
    // Start the NTFS driver
    Status = gBS->StartImage(
        LoadedImageHandle,
        &ExitDataSize, // Optional exit data size
        &ExitData  // Optional exit data
    );
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to start %s: %r\n", NTFS_DRIVER_PATH, Status);
    }
    else
    {
        Print(L"%s started successfully.\n", NTFS_DRIVER_PATH);
        Print(L"Status: %r\n", Status);
        Print(L"Exit Data: %s\n", ExitData);
    }

    // Free allocated device path memory
    FreePool(DevicePath);

    return EFI_SUCCESS;
}

Solution

  • I connected the driver to all the handles of Disk IO protocols and the issue resolved.

    EFI_STATUS
    EFIAPI
    LoadNtfsDriver(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
    {
        EFI_STATUS Status;
        EFI_HANDLE LoadedImageHandle;
        EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
        EFI_DEVICE_PATH_PROTOCOL *DevicePath;
        UINTN ExitDataSize = 4*1024;
        CHAR16 *ExitData = NULL;
    
        Status = gBS->OpenProtocol(
            ImageHandle,
            &gEfiLoadedImageProtocolGuid,
            (VOID **)&LoadedImage,
            ImageHandle,
            NULL,
            EFI_OPEN_PROTOCOL_GET_PROTOCOL);
        if (EFI_ERROR(Status))
        {
            Print(L"Failed to get LoadedImageProtocol: %r\n", Status);
            return Status;
        }
    
        DevicePath = FileDevicePath(LoadedImage->DeviceHandle, NTFS_DRIVER_PATH);
        if (DevicePath == NULL)
        {
            Print(L"Failed to create device path for %s\n", NTFS_DRIVER_PATH);
            return EFI_NOT_FOUND;
        }
    
        Status = gBS->LoadImage(
            FALSE,             // Not a Boot Image
            ImageHandle,       // Parent image handle
            DevicePath,        // Path to the NTFS driver
            NULL,              // Optional source buffer
            0,                 // Size of the source buffer
            &LoadedImageHandle // Image handle for the loaded driver
        );
        if (EFI_ERROR(Status))
        {
            Print(L"Failed to load %s: %r\n", NTFS_DRIVER_PATH, Status);
            FreePool(DevicePath);
            return Status;
        }
        Print(L"%s loaded successfully.\n", NTFS_DRIVER_PATH);
        Print(L"Status: %r\n", Status);
        
        // Start the NTFS driver
        Status = gBS->StartImage(
            LoadedImageHandle,
            &ExitDataSize, // Optional exit data size
            &ExitData  // Optional exit data
        );
        if (EFI_ERROR(Status))
        {
            Print(L"Failed to start %s: %r\n", NTFS_DRIVER_PATH, Status);
        }
        else
        {
            Print(L"%s started successfully.\n", NTFS_DRIVER_PATH);
            Print(L"Status: %r\n", Status);
            Print(L"Exit Data: %s\n", ExitData);
        }
        
        EFI_HANDLE *HandleBuffer;
        UINTN HandleCount;
        UINTN Index;
    
        // Locate all handles supporting the Disk I/O protocol
        Status = gBS->LocateHandleBuffer(
            ByProtocol,
            &gEfiDiskIoProtocolGuid,
            NULL,
            &HandleCount,
            &HandleBuffer);
        if (EFI_ERROR(Status)) {
            Print(L"Failed to locate Disk IO handles: %r\n", Status);
            return Status;
        }
    
        for (Index = 0; Index < HandleCount; Index++) {
            // Attempt to connect the controller for each handle
            Status = gBS->ConnectController(
                HandleBuffer[Index],
                NULL,
                NULL,
                TRUE);
            if (EFI_ERROR(Status)) {
                Print(L"Failed to connect controller for handle %d: %r\n", Index, Status);
            } else {
                Print(L"Controller connected for handle %d.\n", Index);
            }
        }
    
        if (HandleBuffer) {
            FreePool(HandleBuffer);
        }
    
        // Free allocated device path memory
        FreePool(DevicePath);
    
        return EFI_SUCCESS;
    }