diff mbox series

fdt: cmd: allow to add chosen properties

Message ID 20230527214925.2360646-1-lynxis@fe80.eu
State Changes Requested
Delegated to: Simon Glass
Headers show
Series fdt: cmd: allow to add chosen properties | expand

Commit Message

Alexander 'lynxis' Couzens May 27, 2023, 9:49 p.m. UTC
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(+)

Comments

Simon Glass July 12, 2023, 2 p.m. UTC | #1
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
diff mbox series

Patch

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.