]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
bootstd: Replicate the dtb-filename quirks of distroboot
authorSimon Glass <sjg@chromium.org>
Wed, 22 Feb 2023 19:17:04 +0000 (12:17 -0700)
committerSimon Glass <sjg@chromium.org>
Wed, 8 Mar 2023 19:40:49 +0000 (11:40 -0800)
For EFI, the distro boot scripts search in three different directories
for the .dtb file. The SOC-based filename fallback is supported only for
32-bit ARM.

Adjust the code to mirror this behaviour.

Also some boards can use a prior-stage FDT if one is not found in the
normal way. Support this and show a message in that case.

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: Mark Kettenis <kettenis@openbsd.org>
boot/bootflow.c
boot/bootmeth_efi.c
include/bootflow.h

index 70d5fc523871505293377a266162398f971573c9..8f2cb876bb49a57949aa2e9d1142167d3af39122 100644 (file)
@@ -467,6 +467,9 @@ int bootflow_run_boot(struct bootflow_iter *iter, struct bootflow *bflow)
 
        printf("** Booting bootflow '%s' with %s\n", bflow->name,
               bflow->method->name);
+       if (IS_ENABLED(CONFIG_OF_HAS_PRIOR_STAGE) &&
+           (bflow->flags & BOOTFLOWF_USE_PRIOR_FDT))
+               printf("Using prior-stage device tree\n");
        ret = bootflow_boot(bflow);
        if (!IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
                printf("Boot failed (err=%d)\n", ret);
index 67c972e3fe42e6a67007e7bd7d898d5c855dbcf9..6a97ac02ff5ccc1fb60bafca254388d3f322bf34 100644 (file)
@@ -147,25 +147,60 @@ static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
        return 0;
 }
 
-static void distro_efi_get_fdt_name(char *fname, int size)
+/**
+ * distro_efi_get_fdt_name() - Get the filename for reading the .dtb file
+ *
+ * @fname: Place to put filename
+ * @size: Max size of filename
+ * @seq: Sequence number, to cycle through options (0=first)
+ * Returns: 0 on success, -ENOENT if the "fdtfile" env var does not exist,
+ * -EINVAL if there are no more options, -EALREADY if the control FDT should be
+ * used
+ */
+static int distro_efi_get_fdt_name(char *fname, int size, int seq)
 {
        const char *fdt_fname;
+       const char *prefix;
+
+       /* select the prefix */
+       switch (seq) {
+       case 0:
+               /* this is the default */
+               prefix = "/dtb";
+               break;
+       case 1:
+               prefix = "";
+               break;
+       case 2:
+               prefix = "/dtb/current";
+               break;
+       default:
+               return log_msg_ret("pref", -EINVAL);
+       }
 
        fdt_fname = env_get("fdtfile");
        if (fdt_fname) {
-               snprintf(fname, size, "dtb/%s", fdt_fname);
+               snprintf(fname, size, "%s/%s", prefix, fdt_fname);
                log_debug("Using device tree: %s\n", fname);
-       } else {
+       } else if (IS_ENABLED(CONFIG_OF_HAS_PRIOR_STAGE)) {
+               strcpy(fname, "<prior>");
+               return log_msg_ret("pref", -EALREADY);
+       /* Use this fallback only for 32-bit ARM */
+       } else if (IS_ENABLED(CONFIG_ARM) && !IS_ENABLED(CONFIG_ARM64)) {
                const char *soc = env_get("soc");
                const char *board = env_get("board");
                const char *boardver = env_get("boardver");
 
                /* cf the code in label_boot() which seems very complex */
-               snprintf(fname, size, "dtb/%s%s%s%s.dtb",
+               snprintf(fname, size, "%s/%s%s%s%s.dtb", prefix,
                         soc ? soc : "", soc ? "-" : "", board ? board : "",
                         boardver ? boardver : "");
                log_debug("Using default device tree: %s\n", fname);
+       } else {
+               return log_msg_ret("env", -ENOENT);
        }
+
+       return 0;
 }
 
 static int distro_efi_read_bootflow_file(struct udevice *dev,
@@ -174,7 +209,7 @@ static int distro_efi_read_bootflow_file(struct udevice *dev,
        struct blk_desc *desc = NULL;
        ulong fdt_addr, size;
        char fname[256];
-       int ret;
+       int ret, seq;
 
        /* We require a partition table */
        if (!bflow->part)
@@ -196,13 +231,26 @@ static int distro_efi_read_bootflow_file(struct udevice *dev,
        if (ret)
                return log_msg_ret("read", -EINVAL);
 
-       distro_efi_get_fdt_name(fname, sizeof(fname));
+       fdt_addr = env_get_hex("fdt_addr_r", 0);
+
+       /* try the various available names */
+       ret = -ENOENT;
+       for (seq = 0; ret; seq++) {
+               ret = distro_efi_get_fdt_name(fname, sizeof(fname), seq);
+               if (ret == -EALREADY) {
+                       bflow->flags = BOOTFLOWF_USE_PRIOR_FDT;
+                       break;
+               }
+               if (ret)
+                       return log_msg_ret("nam", ret);
+               ret = bootmeth_common_read_file(dev, bflow, fname, fdt_addr,
+                                               &size);
+       }
+
        bflow->fdt_fname = strdup(fname);
        if (!bflow->fdt_fname)
                return log_msg_ret("fil", -ENOMEM);
 
-       fdt_addr = env_get_hex("fdt_addr_r", 0);
-       ret = bootmeth_common_read_file(dev, bflow, fname, fdt_addr, &size);
        if (!ret) {
                bflow->fdt_size = size;
                bflow->fdt_addr = fdt_addr;
@@ -277,7 +325,11 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow)
        fdt_addr = hextoul(fdt_addr_str, NULL);
        sprintf(file_addr, "%lx", fdt_addr);
 
-       distro_efi_get_fdt_name(fname, sizeof(fname));
+       /* We only allow the first prefix with PXE */
+       ret = distro_efi_get_fdt_name(fname, sizeof(fname), 0);
+       if (ret)
+               return log_msg_ret("nam", ret);
+
        bflow->fdt_fname = strdup(fname);
        if (!bflow->fdt_fname)
                return log_msg_ret("fil", -ENOMEM);
index e5fdf5f29d1b92b77d519c27e87c4fdaae0d7a30..f20f575030f13599b5c4a78e09c8b381d8907ce1 100644 (file)
@@ -36,6 +36,18 @@ enum bootflow_state_t {
        BOOTFLOWST_COUNT
 };
 
+/**
+ * enum bootflow_flags_t - flags for bootflows
+ *
+ * @BOOTFLOWF_USE_PRIOR_FDT: Indicates that an FDT was not found by the bootmeth
+ *     and it is using the prior-stage FDT, which is the U-Boot control FDT.
+ *     This is only possible with the EFI bootmeth (distro-efi) and only when
+ *     CONFIG_OF_HAS_PRIOR_STAGE is enabled
+ */
+enum bootflow_flags_t {
+       BOOTFLOWF_USE_PRIOR_FDT = 1 << 0,
+};
+
 /**
  * struct bootflow - information about a bootflow
  *
@@ -68,6 +80,7 @@ enum bootflow_state_t {
  * @fdt_fname: Filename of FDT file
  * @fdt_size: Size of FDT file
  * @fdt_addr: Address of loaded fdt
+ * @flags: Flags for the bootflow (see enum bootflow_flags_t)
  */
 struct bootflow {
        struct list_head bm_node;
@@ -90,6 +103,7 @@ struct bootflow {
        char *fdt_fname;
        int fdt_size;
        ulong fdt_addr;
+       int flags;
 };
 
 /**