Page 1 of 1

Using UEFI LoadImage

Posted: Tue Sep 15, 2020 2:25 pm
by nexos
Hello,
I am making an EFI bootloader, and ran into a problem. I am calling LoadImage to test chainloading, but it doesn't work. Here is how I call it:

Code: Select all

BS->LoadImage(FALSE, ImageHandle, loader->FilePath, buffer, size, &handle);
BS->StartImage(handle, 0, 0)
The Image starts fine, but then it runs the following code:

Code: Select all

EFI_GUID imageGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
status = BS->HandleProtocol(ImageHandle, &imageGuid, (VOID**)&loader);
EFI_GUID fsProt = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
status = BS->HandleProtocol(loader->DeviceHandle, &fsProt, (VOID**)&fileSys);
And the second call fails with EFI_ERROR_INVALID_PARAMETER.
Also, I am using the file handle obtained from the images structure.
Any suggestions?
Thanks,
nexos

Re: Using UEFI LoadImage

Posted: Tue Sep 15, 2020 4:52 pm
by zaval

Code: Select all

BS->LoadImage(FALSE, ImageHandle, loader->FilePath, buffer, size, &handle);
uhm, do you start the image recursively? because loader->FilePath points to the file part of the of the device path of the image, whose Loaded Image Protocol instance is pointed to by the "loader" variable.

Also, use OpenProtocol() instead of HandleProtocol() for obtaining a protocol instance from the handle, the latter is deprecated. I do like this and it works:

Code: Select all

	Status = pbs->OpenProtocol(
			gpLoadedImageProtocol->DeviceHandle,
			&gEfiSimpleFileSystemGuid,
			&gpSfspHomeDrive,
			ImageHandle,
			NULL,
			EFI_OPEN_PROTOCOL_GET_PROTOCOL
		);

Re: Using UEFI LoadImage

Posted: Tue Sep 15, 2020 6:58 pm
by nexos
I changed it to use OpenProtocol, and I also changed the LoadImage call to look like

Code: Select all

EFI_MEMORY_MAPPED_DEVICE* memDev = (EFI_MEMORY_MAPPED_DEVICE*)AllocMem(sizeof(EFI_MEMORY_MAPPED_DEVICE) * 2);
    memDev[0].Type = 1;
    memDev[0].subType = 3;
    memDev[0].len = 24;
    memDev[0].type = EfiLoaderData;
    memDev[0].startAddr = (UINT64)buffer;
    memDev[0].endAddr = (UINT64)buffer + size;
    memDev[1].Type = 0x7F;
    memDev[1].subType = 0xFF;
    memDev[1].len = 4;
    EFI_STATUS status = BS->LoadImage(FALSE, ImageHandle, (EFI_DEVICE_PATH_PROTOCOL*)memDev, buffer, size, &handle);
It does the same thing still.

Re: Using UEFI LoadImage

Posted: Tue Sep 15, 2020 7:14 pm
by nexos
It appears I found something interesting. When I chainload the app, the DeviceHandle of that app is 0 for some reason. Will have to look into.

Re: Using UEFI LoadImage

Posted: Wed Sep 16, 2020 2:21 pm
by zaval
when you LoadImage() something, it means, you have 2 images - one, that is started by the FW (let it be Img0) and the other (Img1), you start through LoadImage()/StartImage(). you should provide Device Path to Img1, when doing LoadImage() for it. So the Device Path would be something like [storage-device-part]\efi\nexos\Img1.efi. If Img1 resides on the same volume as Img0, [storage-device-part] is the same as for Img0. The idea is you should know the Device Path of this image (generally speaking, your chainloading system should have it written somewhere in its configuration). what do you try to accomplish with feeding LoadImage() with memory mapped device path? it won't let you grab Img1 from its storage. and btw, why do you start UEFI with such an unnecessary and useless thing like "chainloading"?