2
votes

I have a UEFI application that needs to download (TFTP) the file "bootmgfw.efi" which is the Windows EFI boot loader. I can successfully call Mtftp(), LoadImage(), and StartImage() to download and execute the image. However, the Microsoft boot loader determines it is executing locally instead of over the network and looks for required files locally instead of downloading them via TFTP. How do I spawn an application such that it knows it is from a network?

I have two ideas, but so far I have been unable to make either work.

  1. After calling LoadImage() but before calling StartImage() I need to obtain the EFI_LOADED_IMAGE for the new image and modify it. I think I need to modify the DevicePath to indicate it is network loaded, but I do not know how to do this.

  2. Skip Mtftp() and call LoadImage() with TRUE for BootPolicy. I believe this will download and load the file, but I do not know how to tell it what file to load. My guess is the DevicePath passed into LoadImage() would contain this, but I do not know how to construct the DevicePath.

We had a UEFI developer who wrote this application, but he left the company before completing the work. So I am forced to pick up this code base and learn UEFI to try and complete this. Thanks for any help!

1
Are you sure the bootmgfw.efi is 'smart' enough to handle TFTP ? Does it have the code to do the TFPT download of the required files ? - s_b

1 Answers

0
votes

The behaviour of bootmgfw.efi is that it always looks for files it needs to load on the same path that it itself was loaded from it. So to make it download its files via TFTP you need to do this:

  1. In your boot application a new LoadFile protocol which gets files using TFTP behind the scenes by calling Mtftp()
  2. Create a "virtual" device path and associate it with this LoadFile protocol
  3. Load bootmgfw.efi using the virtual path instead of calling Mtftp() directly

If you do this bootmgfw.efi, when it tries to load its own files, will do so using the virtual device path and therefore end up downloading them via TFTP.

You can create the virtual path with the DevicePathUtilitiesProtocol. You can use your own application's device path as the base path and then append some subpath to it with devicePathUtilities::AppendDevicePath().

You can get your own application's device path by opening LoadedImage protocol on it followed by opening DevicePathProtocol on the loadedImage's DeviceHandle like this:

EFI_LOADED_IMAGE_PROTOCOL* loadedImage;
EFI_DEVICE_PATH_PROTOCOL *thisImageFilePath;
EFI_DEVICE_PATH_UTILITIES_PROTOCOL *devPathUtilities;

bootServices->OpenProtocol(imageHandle, &gEfiLoadedImageProtocolGuid, &loadedImage, imageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
bootServices->OpenProtocol(loadedImage->DeviceHandle, &gEfiDevicePathProtocolGuid, &thisImageFilePath, imageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);

At this point thisImageFilePath will be the path of your own application's image. You'll now have to call AppendDevicePath() on it and append another path of your choosing to it to get your virtual device path.

To create the new LoadFile protocol, refer to the UEFI spec.