[PATCH] efi: fix semihosting EFI payload booting
Heinrich Schuchardt
xypron.glpk at gmx.de
Wed May 10 17:58:06 CEST 2023
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.
Can there be multiple semihosting block devices?
> ---
> lib/efi_loader/efi_device_path.c | 34 ++++++++++++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
> index e2e98a39be1..b6d2074dd70 100644
> --- a/lib/efi_loader/efi_device_path.c
> +++ b/lib/efi_loader/efi_device_path.c
> @@ -1079,6 +1079,35 @@ struct efi_device_path *efi_dp_from_uart(void)
> return buf;
> }
>
> +#define SEMIHOSTING_GUID \
> + EFI_GUID(0xc5b9c74a, 0x6d72, 0x4719, \
> + 0x99, 0xab, 0xc5, 0x9f, 0x19, 0x90, 0x91, 0xeb)
Can semihosting be moved to the driver model?
Then we could create a generic catch all for device path nodes for all
uclasses.
Best regards
Heinrich
> +
> +struct efi_device_path *efi_dp_from_semihosting(void)
> +{
> + const struct efi_device_path_vendor smh_vendor = {
> + .dp = {
> + .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
> + .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
> + .length = sizeof(smh_vendor),
> + },
> + .guid = SEMIHOSTING_GUID,
> + };
> + void *buf, *pos;
> + size_t dpsize = sizeof(smh_vendor) + sizeof(END);
> +
> + buf = efi_alloc(dpsize);
> + if (!buf)
> + return NULL;
> + pos = buf;
> + memcpy(pos, &smh_vendor, sizeof(smh_vendor));
> + pos += sizeof(smh_vendor);
> +
> + memcpy(pos, &END, sizeof(END));
> +
> + return buf;
> +}
> +
> #ifdef CONFIG_NETDEVICES
> struct efi_device_path *efi_dp_from_eth(void)
> {
> @@ -1210,6 +1239,11 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
> *device = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
> (uintptr_t)image_addr,
> image_size);
> + } else if (!strcmp(dev, "hostfs")) {
> + efi_get_image_parameters(&image_addr, &image_size);
> +
> + if (device)
> + *device = efi_dp_from_semihosting();
> } else {
> part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
> 1);
More information about the U-Boot
mailing list