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

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@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.

Hi Alexander,
On Sat, 27 May 2023 at 16:02, Alexander Couzens lynxis@fe80.eu wrote:
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.
only be visible
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@fe80.eu
cmd/fdt.c | 10 +++++++ common/fdt_support.c | 69 +++++++++++++++++++++++++++++++++++++++++++ include/fdt_support.h | 2 ++ 3 files changed, 81 insertions(+)
Sorry I missed this patch when it was sent.
Please can you add to doc/usage/cmd/fdt.rst and test/cmd/fdt.c ?
We need docs and tests for new commands.
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,
+};
please comment this struct:
+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);
check errors
list_add_tail(&entry->list, &chosen_entries);
blank line before final return
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);
check error
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);
Please add function comments
/**
- Add initrd information to the FDT before booting the OS.
-- 2.40.1
Regards, Simon
participants (2)
-
Alexander Couzens
-
Simon Glass