How to load an EFI Binary stored in Windows FAT32 Partition

I am writing an UEFI application (A) which will load another UEFI application (B). This another UEFI application (B) is stored on one of the Windows Partition (FAT32). I am trying to load (B) from (A). Two things I need to perform from (A)

  1. First of all locate the Windows Partition (Volume) where (B) is stored.
  2. Load and Start Image (B).

So far I have been able to write following code.

EFI_STATUS
UefiMain(
    EFI_HANDLE          image_handle,
    EFI_SYSTEM_TABLE    *st
) {
    EFI_BOOT_SERVICES * bs = st->BootServices;
    
    // set the gloabl service table before we do anything else
    g_st = st;
    
    EFI_HANDLE*         handle;
    UINTN               n_handle ;
    EFI_STATUS          status;

    status = bs->LocateHandleBuffer(ByProtocol,
                                &gEfiSimpleFileSystemProtocolGuid,
                                NULL,
                                &n_handle,
                                &handle);

    if (EFI_ERROR (status)) 
    {
        print((CHAR16 *) L"LocateHandle Failed : ");
        print_hex_dword(status);
        print((CHAR16 *) L"\n");
        return EFI_SUCCESS;
    }

    print((CHAR16 *) L" n_handle : ");
    print_hex_dword(n_handle);
    print((CHAR16 *) L"\n");
    
    for (UINTN i=0; i<n_handle; i++) 
    {
            
        EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *protocol;
        status = bs->OpenProtocol(handle[i],
                                        &gEfiSimpleFileSystemProtocolGuid,
                                        (void**)&protocol,
                                        image_handle,
                                        NULL,
                                        EFI_OPEN_PROTOCOL_GET_PROTOCOL);

        if (EFI_ERROR (status)) 
        {
            print((CHAR16 *) L"OpenProtocol Failed : ");
            print_hex_dword(status);
            print((CHAR16 *) L"\n");
            return EFI_SUCCESS;
        }

        EFI_FILE_PROTOCOL *volume_root;
            
        status = protocol->OpenVolume(protocol, &volume_root);
        if (EFI_ERROR (status)) 
        {
            print((CHAR16 *) L"OpenVolume Failed : ");
            print_hex_dword(status);
            print((CHAR16 *) L"\n");
            return EFI_SUCCESS;
        }
        
        EFI_FILE_PROTOCOL* root;
        status = volume_root->Open(volume_root,
                                                &root,
                                                (CHAR16 *)L"MY_FOLDER\\myB.efi",
                                                EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
        
        if (EFI_ERROR (status)) 
        {
            print((CHAR16 *) L"Open Failed :");
            print_hex_dword(status);
            print((CHAR16 *) L"\n");
            continue;
        }
        else
        {
            print((CHAR16 *) L"Open is Success\n");
        }

        //get file info, two try process
        EFI_FILE_INFO* file_info = 0;
        UINTN file_info_size = 0;
        status = root->GetInfo(root, &FileInfoGuid, &file_info_size, 0 );

        if (status != EFI_BUFFER_TOO_SMALL )
        {
            //ErrorPrint(L"Failed to stat file '%s'. (Error %d)\r\n", filename, res);
            print((CHAR16 *) L"GetInfo Failed :");
            print_hex_dword(status);
            print((CHAR16 *) L"\n");
            return EFI_NOT_FOUND ;
        }

        status = bs->AllocatePool(EfiLoaderData, file_info_size, (void**) &file_info);
        if (status)
        {
            //ErrorPrint(L"Failed to allocate file info memory. (Error %d)\r\n", res);
            print((CHAR16 *) L"AllocatePool Failed :");
            print_hex_dword(status);
            print((CHAR16 *) L"\n");
            return EFI_OUT_OF_RESOURCES ;
        }

        status = root->GetInfo(root, &FileInfoGuid, &file_info_size,(void*) file_info);

        print((CHAR16 *) L"FileSize :");
        print_hex_dword(file_info->FileSize);
        print((CHAR16 *) L"\n");
    
    }
    
    return EFI_SUCCESS;
}

I am not able to proceed further. I believe that I will need to get DevicePath for the (B) application but I am not sure how to do that. Any pointer will be helpful.

Thanks.


Once you've successfully opened the file, you can use FileDevicePath(handle[i], L"MY_FOLDER\\myB.efi") (which you should have if using EDK2 or GNU-EFI) to get an EFI_DEVICE_PATH which points to the file. Then you can load the image with something like as follows

// Set this from within the loop or break with an appropriate i.
EFI_DEVICE_PATH *path = FileDevicePath(handle[i], L"MY_FOLDER\\myB.efi");

EFI_HANDLE *img;
status = bs->LoadImage(false, image_handle, path, NULL, 0, &img)

if (EFI_ERROR(status)) {
     print((CHAR16*) L"Failed to load image!");
     return status;
}

status = bs->StartImage(img, NULL, NULL);

// We'll get here if the child image exits or if it fails to load
if (EFI_ERROR(status)) {
    print((CHAR16*) L"Failed to start image!");
}