[PATCH] bootstd: efi: Handle prior-stage FDT in network path

Kory Maincent kory.maincent at bootlin.com
Wed Mar 25 10:59:41 CET 2026


On Sun, 22 Mar 2026 14:08:50 -0600
Simon Glass <sjg at chromium.org> wrote:

> When CONFIG_OF_HAS_PRIOR_STAGE is enabled and fdtfile is not set,
> efi_get_distro_fdt_name() returns -EALREADY to indicate the prior-stage
> FDT should be used. The block-device EFI path handles this by setting
> BOOTFLOWF_USE_PRIOR_FDT, but the network path treats it as an error,
> causing the bootflow to stay in 'base' state with a -EALREADY error.
> 
> This also means fdt_addr_r is required even when no FDT download is
> needed, giving a spurious  -EINVAL error.
> 
> Fix this by calling efi_get_distro_fdt_name() before checking
> fdt_addr_r, and handling -EALREADY by setting BOOTFLOWF_USE_PRIOR_FDT
> to skip the FDT download, matching the block-device behaviour.
> 
> THere is no test for this at present, since sandbox does not enable
> CONFIG_OF_HAS_PRIOR_STAGE and lacks infra for network-based EFI boot.
> 
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
> 
>  boot/bootmeth_efi.c | 36 +++++++++++++++++++-----------------
>  1 file changed, 19 insertions(+), 17 deletions(-)
> 
> diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
> index f592fec07f6..cbb392e1636 100644
> --- a/boot/bootmeth_efi.c
> +++ b/boot/bootmeth_efi.c
> @@ -269,27 +269,29 @@ static int distro_efi_read_bootflow_net(struct bootflow
> *bflow) return log_msg_ret("fi0", -ENOMEM);
>  
>  	/* read the DT file also */
> -	fdt_addr_str = env_get("fdt_addr_r");
> -	if (!fdt_addr_str)
> -		return log_msg_ret("fdt", -EINVAL);
> -	fdt_addr = hextoul(fdt_addr_str, NULL);
> -	sprintf(file_addr, "%lx", fdt_addr);
> -
> -	/* We only allow the first prefix with PXE */
>  	ret = efi_get_distro_fdt_name(fname, sizeof(fname), 0);
> -	if (ret)
> +	if (ret == -EALREADY) {
> +		bflow->flags |= BOOTFLOWF_USE_PRIOR_FDT;
> +	} else if (ret) {
>  		return log_msg_ret("nam", ret);
> +	} else {

Instead of this big else maybe you can return directly in the EALREADY case
alongside with a comment, like this:

if (ret == -EALREADY) {
	/* Prior stage fdt is used */
	bflow->flags |= BOOTFLOWF_USE_PRIOR_FDT;
	bflow->state = BOOTFLOWST_READY;
	return 0;
} else if (ret) {
	return log_msg_ret("nam", ret);
}

> +		fdt_addr_str = env_get("fdt_addr_r");
> +		if (!fdt_addr_str)
> +			return log_msg_ret("fdt", -EINVAL);
> +		fdt_addr = hextoul(fdt_addr_str, NULL);
> +		sprintf(file_addr, "%lx", fdt_addr);
>  
> -	bflow->fdt_fname = strdup(fname);
> -	if (!bflow->fdt_fname)
> -		return log_msg_ret("fil", -ENOMEM);
> +		bflow->fdt_fname = strdup(fname);
> +		if (!bflow->fdt_fname)
> +			return log_msg_ret("fil", -ENOMEM);
>  
> -	if (!do_tftpb(&cmdtp, 0, 3, tftp_argv)) {
> -		bflow->fdt_size = env_get_hex("filesize", 0);
> -		bflow->fdt_addr = fdt_addr;
> -	} else {
> -		log_debug("No device tree available\n");
> -		bflow->flags |= BOOTFLOWF_USE_BUILTIN_FDT;
> +		if (!do_tftpb(&cmdtp, 0, 3, tftp_argv)) {
> +			bflow->fdt_size = env_get_hex("filesize", 0);
> +			bflow->fdt_addr = fdt_addr;
> +		} else {
> +			log_debug("No device tree available\n");
> +			bflow->flags |= BOOTFLOWF_USE_BUILTIN_FDT;
> +		}
>  	}
>  
>  	bflow->state = BOOTFLOWST_READY;



-- 
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


More information about the U-Boot mailing list