[PATCH] fdt: cmd: allow to add chosen properties

Alexander Couzens lynxis at fe80.eu
Sat May 27 23:49:25 CEST 2023


Add command fdt chosenu32/chosenstr to allow setting runtime properties.
This is useful to pass information to the OS.
E.g. which slot is currently booted in a A/B/recovery scheme.
Or the reset reason which may only visitable to the u-boot.

Scripts can use:
> fdt chosenstr u-boot,abboot b
To inform the OS which slot was booted.

or pass u32
> fdt chosenu32 u-boot,try 3

Signed-off-by: Alexander Couzens <lynxis at fe80.eu>
---
 cmd/fdt.c             | 10 +++++++
 common/fdt_support.c  | 69 +++++++++++++++++++++++++++++++++++++++++++
 include/fdt_support.h |  2 ++
 3 files changed, 81 insertions(+)

diff --git a/cmd/fdt.c b/cmd/fdt.c
index aae3278526c4..050014cccd0e 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -278,6 +278,14 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 		return CMD_RET_SUCCESS;
 	}
 
+	else if (strncmp(argv[1], "chosenstr", 3) == 0) {
+		if (argc != 4)
+			return CMD_RET_USAGE;
+
+		fdt_chosen_set_str(argv[2], argv[3]);
+		return 0;
+	}
+
 	if (!working_fdt) {
 		puts("No FDT memory address configured. Please configure\n"
 		     "the FDT address via \"fdt addr <address>\" command.\n"
@@ -1147,6 +1155,8 @@ static char fdt_help_text[] =
 	"fdt rsvmem delete <index>           - Delete a mem reserves\n"
 	"fdt chosen [<start> <size>]         - Add/update the /chosen branch in the tree\n"
 	"                                        <start>/<size> - initrd start addr/size\n"
+	"fdt chosenu32 key value             - Add key to /chosen with u32 value\n"
+	"fdt chosenstr key value             - Add key to /chosen with string value\n"
 #if defined(CONFIG_FIT_SIGNATURE)
 	"fdt checksign [<addr>]              - check FIT signature\n"
 	"                                      <addr> - address of key blob\n"
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 2053fe3bad83..33b22ebc94ad 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -10,10 +10,12 @@
 #include <abuf.h>
 #include <env.h>
 #include <log.h>
+#include <malloc.h>
 #include <mapmem.h>
 #include <net.h>
 #include <stdio_dev.h>
 #include <linux/ctype.h>
+#include <linux/list.h>
 #include <linux/types.h>
 #include <asm/global_data.h>
 #include <linux/libfdt.h>
@@ -22,6 +24,21 @@
 #include <fdtdec.h>
 #include <version.h>
 
+static LIST_HEAD(chosen_entries);
+
+enum fdt_chosen_type {
+	FDT_CHOSEN_TYPE_U32,
+	FDT_CHOSEN_TYPE_STR,
+};
+
+struct fdt_chosen_entry {
+	struct list_head list;
+	enum fdt_chosen_type type;
+	char *key;
+	char *str;
+	u32 u32;
+};
+
 /**
  * fdt_getprop_u32_default_node - Return a node's property or a default
  *
@@ -269,6 +286,34 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
 	return 0;
 }
 
+int fdt_chosen_set_str(char *key, char *value)
+{
+	struct fdt_chosen_entry *entry = calloc(1, sizeof(*entry));
+
+	if (!entry)
+		return 1;
+
+	entry->type = FDT_CHOSEN_TYPE_STR;
+	entry->key = strdup(key);
+	entry->str = strdup(value);
+	list_add_tail(&entry->list, &chosen_entries);
+	return 0;
+}
+
+int fdt_chosen_set_int(char *key, u32 value)
+{
+	struct fdt_chosen_entry *entry = calloc(1, sizeof(*entry));
+
+	if (!entry)
+		return 1;
+
+	entry->type = FDT_CHOSEN_TYPE_U32;
+	entry->key = strdup(key);
+	entry->u32 = value;
+	list_add_tail(&entry->list, &chosen_entries);
+	return 0;
+}
+
 /**
  * board_fdt_chosen_bootargs - boards may override this function to use
  *                             alternative kernel command line arguments
@@ -284,6 +329,7 @@ int fdt_chosen(void *fdt)
 	int   nodeoffset;
 	int   err;
 	char  *str;		/* used to set string properties */
+	struct list_head *entry;
 
 	err = fdt_check_header(fdt);
 	if (err < 0) {
@@ -319,6 +365,29 @@ int fdt_chosen(void *fdt)
 		}
 	}
 
+	list_for_each(entry, &chosen_entries) {
+		struct fdt_chosen_entry *chosen = list_entry(entry, struct fdt_chosen_entry, list);
+
+		switch (chosen->type) {
+		case FDT_CHOSEN_TYPE_STR:
+			err = fdt_setprop_string(fdt, nodeoffset, chosen->key, chosen->str);
+			if (err < 0) {
+				printf("WARNING: could not set fdt %s to %s. Error: %s.\n",
+				       chosen->key, chosen->str, fdt_strerror(err));
+				continue;
+			}
+			break;
+		case FDT_CHOSEN_TYPE_U32:
+			err = fdt_setprop_u32(fdt, nodeoffset, chosen->key, chosen->u32);
+			if (err < 0) {
+				printf("WARNING: could not set fdt %s to %d. Error: %s.\n",
+				       chosen->key, chosen->u32, fdt_strerror(err));
+				continue;
+			}
+			break;
+		}
+	}
+
 	/* add u-boot version */
 	err = fdt_setprop(fdt, nodeoffset, "u-boot,version", PLAIN_VERSION,
 			  strlen(PLAIN_VERSION) + 1);
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 5638bd4f1655..b1c331f05370 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -51,6 +51,8 @@ int fdt_root(void *fdt);
  * Return: 0 if ok, or -FDT_ERR_... on error
  */
 int fdt_chosen(void *fdt);
+int fdt_chosen_set_str(char *key, char *value);
+int fdt_chosen_set_int(char *key, u32 value);
 
 /**
  * Add initrd information to the FDT before booting the OS.
-- 
2.40.1



More information about the U-Boot mailing list