From c5440a6ae85d0b68e511c1b0b81dc97a3df719e5 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Sun, 19 Nov 2023 16:54:58 +0000 Subject: [PATCH 1/4] bootflow: bootmeth_efi: Set bootp_arch as hex bootmeth_efi sets up bootp_arch which is read later in bootp.c Currently bootp_arch is being set as integer string and being read in bootp.c as hex, this sends incorrect arch value to dhcp server which in return sends wrong file for network boot. For ARM64 UEFI Arch value is 0xb (11), here we set environment as 11 and later is read as 0x11 and 17 is sent to dhcp server. Setting it as hex string fixes the problem. Reviewed-by: Simon Glass Signed-off-by: Shantur Rathore --- boot/bootmeth_efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index 9ba7734911e..682cf5b23b7 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -339,7 +339,7 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) ret = env_set("bootp_vci", str); if (ret) return log_msg_ret("vcs", ret); - ret = env_set_ulong("bootp_arch", arch); + ret = env_set_hex("bootp_arch", arch); if (ret) return log_msg_ret("ars", ret); From e31317e161928aadb8941cb63ce49d6faa8002f4 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Sun, 19 Nov 2023 16:54:59 +0000 Subject: [PATCH 2/4] bootflow: bootmeth_efi: set bflow->fname from bootfile name We need to set boot->fname before calling efi_set_bootdev otherwise this crashes as bflow->fname is null. Reviewed-by: Simon Glass Signed-off-by: Shantur Rathore --- boot/bootmeth_efi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index 682cf5b23b7..fd224f7c91a 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -323,7 +323,7 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) char file_addr[17], fname[256]; char *tftp_argv[] = {"tftp", file_addr, fname, NULL}; struct cmd_tbl cmdtp = {}; /* dummy */ - const char *addr_str, *fdt_addr_str; + const char *addr_str, *fdt_addr_str, *bootfile_name; int ret, arch, size; ulong addr, fdt_addr; char str[36]; @@ -360,6 +360,12 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) return log_msg_ret("sz", -EINVAL); bflow->size = size; + /* bootfile should be setup by dhcp*/ + bootfile_name = env_get("bootfile"); + if (!bootfile_name) + return log_msg_ret("bootfile_name", ret); + bflow->fname = strdup(bootfile_name); + /* do the hideous EFI hack */ efi_set_bootdev("Net", "", bflow->fname, map_sysmem(addr, 0), bflow->size); From 184fc0379dd0d750d8d032fb5a147150c13547c2 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Sun, 19 Nov 2023 16:55:00 +0000 Subject: [PATCH 3/4] bootflow: bootmeth_efi: Handle fdt not available. While booting with efi, if fdt isn't available externally, just use the built-in one. Reviewed-by: Simon Glass Signed-off-by: Shantur Rathore --- boot/bootmeth_efi.c | 19 +++++++++++++------ include/bootflow.h | 2 ++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index fd224f7c91a..e884dc62937 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -313,6 +313,7 @@ static int distro_efi_try_bootflow_files(struct udevice *dev, */ } else { log_debug("No device tree available\n"); + bflow->flags |= BOOTFLOWF_USE_BUILTIN_FDT; } return 0; @@ -391,6 +392,7 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) bflow->fdt_addr = fdt_addr; } else { log_debug("No device tree available\n"); + bflow->flags |= BOOTFLOWF_USE_BUILTIN_FDT; } bflow->state = BOOTFLOWST_READY; @@ -429,13 +431,11 @@ static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow) return log_msg_ret("read", ret); /* - * use the provided device tree if available, else fall back to - * the control FDT + * use the provided device tree if not using the built-in fdt */ - if (bflow->fdt_fname) + if (bflow->flags & ~BOOTFLOWF_USE_BUILTIN_FDT) fdt = bflow->fdt_addr; - else - fdt = (ulong)map_to_sysmem(gd->fdt_blob); + } else { /* * This doesn't actually work for network devices: @@ -452,7 +452,14 @@ static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow) * At some point we can add a real interface to bootefi so we can call * this directly. For now, go through the CLI, like distro boot. */ - snprintf(cmd, sizeof(cmd), "bootefi %lx %lx", kernel, fdt); + if (bflow->flags & BOOTFLOWF_USE_BUILTIN_FDT) { + log_debug("Booting with built-in fdt\n"); + snprintf(cmd, sizeof(cmd), "bootefi %lx", kernel); + } else { + log_debug("Booting with external fdt\n"); + snprintf(cmd, sizeof(cmd), "bootefi %lx %lx", kernel, fdt); + } + if (run_command(cmd, 0)) return log_msg_ret("run", -EINVAL); diff --git a/include/bootflow.h b/include/bootflow.h index fede8f22a2b..42112874f64 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -45,10 +45,12 @@ enum bootflow_state_t { * CONFIG_OF_HAS_PRIOR_STAGE is enabled * @BOOTFLOWF_STATIC_BUF: Indicates that @bflow->buf is statically set, rather * than being allocated by malloc(). + * @BOOTFLOWF_USE_BUILTIN_FDT : Indicates that current bootflow uses built-in FDT */ enum bootflow_flags_t { BOOTFLOWF_USE_PRIOR_FDT = 1 << 0, BOOTFLOWF_STATIC_BUF = 1 << 1, + BOOTFLOWF_USE_BUILTIN_FDT = 1 << 2, }; /** From 37503b0c0c042b07eed377baf587fdbabdb46dd9 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Sun, 19 Nov 2023 16:55:01 +0000 Subject: [PATCH 4/4] bootflow: bootmeth_efi: don't free buffer bootmeth_efi doesn't allocate any buffer to load efi in any case. enable static buffer flag for all cases. Reviewed-by: Simon Glass Signed-off-by: Shantur Rathore --- boot/bootmeth_efi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index e884dc62937..446cb73140e 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -160,7 +160,6 @@ static int efiload_read_file(struct bootflow *bflow, ulong addr) if (ret) return log_msg_ret("read", ret); bflow->buf = map_sysmem(addr, bflow->size); - bflow->flags |= BOOTFLOWF_STATIC_BUF; set_efi_bootdev(desc, bflow); @@ -404,6 +403,12 @@ static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow) { int ret; + /* + * bootmeth_efi doesn't allocate any buffer neither for blk nor net device + * set flag to avoid freeing static buffer. + */ + bflow->flags |= BOOTFLOWF_STATIC_BUF; + if (bootmeth_uses_network(bflow)) { /* we only support reading from one device, so ignore 'dev' */ ret = distro_efi_read_bootflow_net(bflow);