[PATCH v2 3/3] fdt: introduce fsapply command
Andre Przywara
andre.przywara at arm.com
Fri Feb 10 12:02:13 CET 2023
Explicitly specifying the exact filenames of devicetree overlays files
on a U-Boot command line can be quite tedious for users, especially
when it should be made persistent for every boot.
To simplify the task of applying (custom) DT overlays, introduce a
"fdt fsapply" subcommand, that iterates a given directory in any
supported filesystem, and tries to apply every .dtbo file found it
there.
This allows users to simply drop a DT overlay file into a magic
directory, and it will be applied on the next boot automatically,
by the virtue of just a generic U-Boot command call.
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
cmd/fdt.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
diff --git a/cmd/fdt.c b/cmd/fdt.c
index 1972490bdc2..00f92dbbb5d 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -12,12 +12,14 @@
#include <env.h>
#include <image.h>
#include <linux/ctype.h>
+#include <linux/sizes.h>
#include <linux/types.h>
#include <asm/global_data.h>
#include <linux/libfdt.h>
#include <fdt_support.h>
#include <mapmem.h>
#include <asm/io.h>
+#include <fs.h>
#define MAX_LEVEL 32 /* how deeply nested we will go */
#define SCRATCHPAD 1024 /* bytes of scratchpad memory */
@@ -127,6 +129,81 @@ static int fdt_get_header_value(int argc, char *const argv[])
return CMD_RET_FAILURE;
}
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+static int apply_all_overlays(const char *ifname, const char *dev_part_str,
+ const char *dirname)
+{
+ unsigned long addr;
+ struct fdt_header *dtbo;
+ const char *addr_str;
+ struct fs_dir_stream *dirs;
+ struct fs_dirent *dent;
+ char fname[256], *name_beg;
+ int ret;
+
+ addr_str = env_get("fdtoverlay_addr_r");
+ if (!addr_str) {
+ printf("Invalid fdtoverlay_addr_r for loading overlays\n");
+ return CMD_RET_FAILURE;
+ }
+ addr = hextoul(addr_str, NULL);
+
+ ret = fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY);
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ if (!dirname)
+ dirname = "/";
+ dirs = fs_opendir(dirname);
+ if (!dirs) {
+ printf("Cannot find directory \"%s\"\n", dirname);
+ return CMD_RET_FAILURE;
+ }
+
+ strcpy(fname, dirname);
+ name_beg = strchr(fname, 0);
+ if (name_beg[-1] != '/')
+ *name_beg++ = '/';
+
+ dtbo = map_sysmem(addr, 0);
+ while ((dent = fs_readdir(dirs))) {
+ loff_t size = 0;
+
+ if (dent->type == FS_DT_DIR)
+ continue;
+
+ if (strcmp(dent->name + strlen(dent->name) - 5, ".dtbo"))
+ continue;
+
+ printf("%s: ", dent->name);
+ strcpy(name_beg, dent->name);
+ fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY);
+ if (dent->size > SZ_2M)
+ size = SZ_2M;
+ else
+ size = dent->size;
+ ret = fs_read(fname, addr, 0, size, &size);
+ if (ret) {
+ printf(" errno: %d\n", ret);
+ continue;
+ }
+ if (!fdt_valid(&dtbo)) {
+ /* fdt_valid() clears the pointer upon failure */
+ dtbo = map_sysmem(addr, 0);
+ continue;
+ }
+
+ if (fdt_overlay_apply_verbose(working_fdt, dtbo) == 0)
+ printf("applied\n");
+ }
+ unmap_sysmem(dtbo);
+
+ fs_closedir(dirs);
+
+ return 0;
+}
+#endif
+
/*
* Flattened Device Tree command, see the help for parameter definitions.
*/
@@ -747,6 +824,15 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
ret = fdt_overlay_apply_verbose(working_fdt, blob);
if (ret)
return CMD_RET_FAILURE;
+ /* apply all .dtbo files from a directory */
+ } else if (strncmp(argv[1], "fsap", 4) == 0) {
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ if (!working_fdt)
+ return CMD_RET_FAILURE;
+
+ return apply_all_overlays(argv[2], argv[3], argv[4]);
}
#endif
/* resize the fdt */
@@ -1104,6 +1190,7 @@ static char fdt_help_text[] =
"addr [-c] [-q] <addr> [<size>] - Set the [control] fdt location to <addr>\n"
#ifdef CONFIG_OF_LIBFDT_OVERLAY
"fdt apply <addr> - Apply overlay to the DT\n"
+ "fdt fsapply <ifname> <dev:part> <dir> - Apply all overlays in directory\n"
#endif
#ifdef CONFIG_OF_BOARD_SETUP
"fdt boardsetup - Do board-specific set up\n"
--
2.25.1
More information about the U-Boot
mailing list