[PATCH] efi: fix semihosting EFI payload booting

Heinrich Schuchardt xypron.glpk at gmx.de
Thu May 11 17:23:13 CEST 2023

On 5/11/23 10:59, Andre Przywara wrote:
> On Thu, 11 May 2023 08:22:30 +0200
> Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
>> On 5/11/23 02:00, Andre Przywara wrote:
>>> On Wed, 10 May 2023 23:19:33 +0200
>>> Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
>>> Hi,
>>>> On 5/10/23 19:26, Andre Przywara wrote:
>>>>> On Wed, 10 May 2023 17:58:06 +0200
>>>>> Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
>>>>> Hi,
>>>>>> On 5/10/23 16:13, Andre Przywara wrote:
>>>>>>> At the moment any naive attempt to boot an EFI payload that has just
>>>>>>> been loaded via "hostfs" (sandbox or semihosting) is met by a rather
>>>>>>> confusing error message:
>>>>>>> ===========
>>>>>>> VExpress64# load hostfs - $kernel_addr_r Image
>>>>>>> 52752896 bytes read in 8 ms (6.1 GiB/s)
>>>>>>> VExpress64# bootefi $kernel_addr_r
>>>>>>> No UEFI binary known at 0x80080000
>>>>>>> ===========
>>>>>>> Actually explicitly providing the filesize:
>>>>>>> VExpress64# bootefi $kernel_addr_r:$filesize
>>>>>>> works around that problem, but the issue lies deeper: the call to
>>>>>>> efi_set_bootdev() (as done by the generic load code) bails out at some
>>>>>>> point, leaving the image_addr and image_size variables unset, which
>>>>>>> triggers this message. The problem seems to be that "-" is not
>>>>>>> understood by the code creating an UEFI device path. We could try to fix
>>>>>>> just that, but actually semihosting seems to have some explicit support
>>>>>>> in UEFI (at least it does in EDK II): there is a separate GUID for it,
>>>>>>> and hostfs is significantly different in some aspects to justify special
>>>>>>> handling.
>>>>>>> Check for the device name being "hostfs" and create a specific UEFI device
>>>>>>> path for semihosting in this case. This uses the GUID used by EDK II for
>>>>>>> almost 15 years.
>>>>>>> This fixes the above load/bootefi sequence without requiring an explicit
>>>>>>> file size argument.
>>>>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>>>> Could you, please, indicate how to invoke QEMU with semihosting enabled.
>>>>>> This information needs to be added to doc/usage/semihosting.rst.
>>>>> It's already there:
>>>>> https://u-boot.readthedocs.io/en/latest/usage/semihosting.html#qemu
>>>> This does not tell me which arguments I should pass to qemu-system-aarch64.
>>> I would say that's out of scope for this document, and is explained in
>>> doc/boards/emulation/qemu-arm.rst. A minimum working example is:
>>> $ qemu-system-aarch64 -M virt -cpu cortex-a57 -nographic -bios u-boot.bin
>>>>> It's mostly just "-semihosting" on the QEMU side, but it's not
>>>>> enabled by default in the QEMU defconfig, because it *was* needed
>>>>> to be provided in sync with the QEMU option. It's a debug feature,
>>>>> so there is no good discovery mechanism, really. I think Sean made
>>>>> this work, with this autodetect via trap feature, so we might want
>>>>> to enable this option now, at least for the filesystem part.
>>>> If it is missing in Ubuntu's QEMU, please, indicate how I can build a
>>>> QEMU that allows testing. This information needs to go into
>>>> semihosting.rst.
>>> It's all there and it works on my 20.04 QEMU build out of the box. What
>>> I meant is that -semihosting is a QEMU command line *option*, and a very
>>> optional one, so to speak, as it's more an ARM low level debugger
>>> technology than anything else, and it was just adopted by QEMU. And
>>> until recently you had to make sure that you give that option to QEMU
>>> if you enable semihosting support in U-Boot, otherwise it would crash.
>>> For more details see Sean's FOSDEM talk:
>>> https://fosdem.org/2023/schedule/event/semihosting_uboot/
>>>>> Regardless I was doing those experiments with the FVP fastmodel, which is
>>>> It seems FVP's are not open source
>>>> (https://developer.arm.com/Tools%20and%20Software/Fixed%20Virtual%20Platforms).
>>>> We need some open source solution for testing the suggested changes.
>>> Sure, I just mentioned this because the models are just the reference
>>> implementation and natural habitat for semihosting: because it's
>>> enabled by default there, and it's an ancient ARM technology.
>>> If you want to test it, just use your favourite QEMU command line (or
>>> the one I mention above) and add "-semihosting". Then load your EFI app:
>>> => load hostfs - $kernel_addr_r app.efi
>>> => bootefi $kernel_addr_r
>>> Cheers,
>>> Andre
>> I have compiled qemu_arm64_defconfig with CONFIG_SERIAL_PROBE_ALL=y and
> Ah, sorry, I see that the semihosting QEMU doc section fails to
> mention that you need to enable CONFIG_SEMIHOSTING. That is just listed
> in the FVP section. I will send a patch later.
>> invoked qemu-system-aarch64 (1:7.2+dfsg-5ubuntu2) on Ubuntu 23.10 with
>> -semihosting.
>> qemu-system-aarch64 -semihosting \
>> -machine virt,gic-version=max -accel tcg,thread=multi \
>> -m 1G -smp cores=2 \
>> -bios denx/u-boot.bin -cpu cortex-a72 -nographic -gdb tcp::1234 \
>> -netdev user,id=eth0,tftp=tftp -device e1000,netdev=eth0,romfile= \
>> -drive if=none,file=arm64.img,format=raw,id=mydisk \
>> -drive if=pflash,format=raw,index=1,file=envstore.img \
>> -device virtio-rng-pci \
>> -device ich9-ahci,id=ahci -device ide-hd,drive=mydisk,bus=ahci.0
>> With and without your patch I get:
>> => load hostfs - $kernel_addr_r foo
> This should work then, if foo is a file in your local directory.
> Hope that helps!
> Cheers,
> Andre

Now I am able to debug the code.

I wonder if the file system should be exposed as EFI simple file system
so that EFI applications can access it, e.g. for GRUB to load initrd and
the kernel.

If we don't want to expose it, this change will be enough:

diff --git a/lib/efi_loader/efi_device_path.c
index e2e98a39be..058bdc1ee5 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -1203,7 +1203,7 @@ efi_status_t efi_dp_from_name(const char *dev,
const char *devnr,
         } else if (!strcmp(dev, "Uart")) {
                 if (device)
                         *device = efi_dp_from_uart();
-       } else if (!strcmp(dev, "Mem")) {
+       } else if (!strcmp(dev, "Mem") || !strcmp(dev, "hostfs") ) {
                 efi_get_image_parameters(&image_addr, &image_size);

                 if (device)

Best regards


More information about the U-Boot mailing list