[PATCH 14/19] expo: cedit: Support reading settings from a file

Simon Glass sjg at chromium.org
Tue Aug 15 00:40:34 CEST 2023


Add a command to read cedit settings from a devicetree file.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 boot/cedit.c            | 52 +++++++++++++++++++++++++++++++++++++++++
 cmd/cedit.c             | 39 +++++++++++++++++++++++++++++++
 doc/usage/cmd/cedit.rst |  8 +++++++
 include/cedit.h         | 13 +++++++++++
 test/boot/cedit.c       | 22 ++++++++++++++---
 5 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/boot/cedit.c b/boot/cedit.c
index 4dd79a2263d6..6a74a3809898 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -23,9 +23,11 @@
  * struct cedit_iter_priv - private data for cedit operations
  *
  * @buf: Buffer to use when writing settings to the devicetree
+ * @node: Node to read from when reading settings from devicetree
  */
 struct cedit_iter_priv {
 	struct abuf *buf;
+	ofnode node;
 };
 
 int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
@@ -318,3 +320,53 @@ int cedit_write_settings(struct expo *exp, struct abuf *buf)
 
 	return 0;
 }
+
+static int h_read_settings(struct scene_obj *obj, void *vpriv)
+{
+	struct cedit_iter_priv *priv = vpriv;
+	ofnode node = priv->node;
+
+	switch (obj->type) {
+	case SCENEOBJT_NONE:
+	case SCENEOBJT_IMAGE:
+	case SCENEOBJT_TEXT:
+		break;
+	case SCENEOBJT_MENU: {
+		struct scene_obj_menu *menu;
+		uint val;
+
+		if (ofnode_read_u32(node, obj->name, &val))
+			return log_msg_ret("rd", -ENOENT);
+		menu = (struct scene_obj_menu *)obj;
+		menu->cur_item_id = val;
+
+		break;
+	}
+	}
+
+	return 0;
+}
+
+int cedit_read_settings(struct expo *exp, oftree tree)
+{
+	struct cedit_iter_priv priv;
+	ofnode root, node;
+	int ret;
+
+	root = oftree_root(tree);
+	if (!ofnode_valid(root))
+		return log_msg_ret("roo", -ENOENT);
+	node = ofnode_find_subnode(root, CEDIT_NODE_NAME);
+	if (!ofnode_valid(node))
+		return log_msg_ret("pat", -ENOENT);
+
+	/* read in the items */
+	priv.node = node;
+	ret = expo_iter_scene_objs(exp, h_read_settings, &priv);
+	if (ret) {
+		log_debug("Failed to read settings (err=%d)\n", ret);
+		return log_msg_ret("set", ret);
+	}
+
+	return 0;
+}
diff --git a/cmd/cedit.c b/cmd/cedit.c
index 18cc8ba191bf..a155e080b1f2 100644
--- a/cmd/cedit.c
+++ b/cmd/cedit.c
@@ -99,6 +99,43 @@ static int do_cedit_write_fdt(struct cmd_tbl *cmdtp, int flag, int argc,
 	return 0;
 }
 
+static int do_cedit_read_fdt(struct cmd_tbl *cmdtp, int flag, int argc,
+			     char *const argv[])
+{
+	const char *fname;
+	void *buf;
+	oftree tree;
+	ulong size;
+	int ret;
+
+	if (argc < 4)
+		return CMD_RET_USAGE;
+	fname = argv[3];
+
+	ret = fs_load_alloc(argv[1], argv[2], argv[3], SZ_1M, 0, &buf, &size);
+	if (ret) {
+		printf("File not found\n");
+		return CMD_RET_FAILURE;
+	}
+
+	tree = oftree_from_fdt(buf);
+	if (!oftree_valid(tree)) {
+		free(buf);
+		printf("Cannot create oftree\n");
+		return CMD_RET_FAILURE;
+	}
+
+	ret = cedit_read_settings(cur_exp, tree);
+	oftree_dispose(tree);
+	free(buf);
+	if (ret) {
+		printf("Failed to read settings: %dE\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return 0;
+}
+
 static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc,
 			char *const argv[])
 {
@@ -128,12 +165,14 @@ static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc,
 #ifdef CONFIG_SYS_LONGHELP
 static char cedit_help_text[] =
 	"load <interface> <dev[:part]> <filename>   - load config editor\n"
+	"cedit read_fdt <i/f> <dev[:part]> <filename>     - read settings\n"
 	"cedit write_fdt <i/f> <dev[:part]> <filename>    - write settings\n"
 	"cedit run                                        - run config editor";
 #endif /* CONFIG_SYS_LONGHELP */
 
 U_BOOT_CMD_WITH_SUBCMDS(cedit, "Configuration editor", cedit_help_text,
 	U_BOOT_SUBCMD_MKENT(load, 5, 1, do_cedit_load),
+	U_BOOT_SUBCMD_MKENT(read_fdt, 5, 1, do_cedit_read_fdt),
 	U_BOOT_SUBCMD_MKENT(write_fdt, 5, 1, do_cedit_write_fdt),
 	U_BOOT_SUBCMD_MKENT(run, 1, 1, do_cedit_run),
 );
diff --git a/doc/usage/cmd/cedit.rst b/doc/usage/cmd/cedit.rst
index 0581594831fa..0a9f620b59b3 100644
--- a/doc/usage/cmd/cedit.rst
+++ b/doc/usage/cmd/cedit.rst
@@ -11,6 +11,7 @@ Synopis
     cedit load <interface> <dev[:part]> <filename>
     cedit run
     cedit write_fdt <dev[:part]> <filename>
+    cedit read_fdt <dev[:part]> <filename>
 
 Description
 -----------
@@ -45,6 +46,11 @@ cedit write_fdt
 Writes the current user settings to a devicetree file. For each menu item the
 selected ID and its text string are written.
 
+cedit read_fdt
+~~~~~~~~~~~~~~
+
+Reads the user settings from a devicetree file and updates the cedit with those
+settings.
 
 Example
 -------
@@ -65,3 +71,5 @@ That results in::
             power-loss-str = "Always Off";
         };
     }
+
+    => cedit read_fdt hostfs - settings.dtb
diff --git a/include/cedit.h b/include/cedit.h
index 6086e3020062..bb6e87d4af77 100644
--- a/include/cedit.h
+++ b/include/cedit.h
@@ -7,6 +7,8 @@
 #ifndef __CEDIT_H
 #define __CEDIT_H
 
+#include <dm/ofnode_decl.h>
+
 struct abuf;
 struct expo;
 struct scene;
@@ -67,4 +69,15 @@ int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
  */
 int cedit_write_settings(struct expo *exp, struct abuf *buf);
 
+/**
+ * cedit_read_settings() - Read settings in FDT format
+ *
+ * Read an FDT with the settings
+ *
+ * @exp: Expo to read settings into
+ * @tree: Tree to read from
+ * Return: 0 if OK, -ve on error
+ */
+int cedit_read_settings(struct expo *exp, oftree tree);
+
 #endif /* __CEDIT_H */
diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index 1dd78c64158d..659c47ed35fb 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -54,11 +54,12 @@ static int cedit_base(struct unit_test_state *uts)
 }
 BOOTSTD_TEST(cedit_base, 0);
 
-/* Check the cedit write_fdt commands */
+/* Check the cedit write_fdt and read_fdt commands */
 static int cedit_fdt(struct unit_test_state *uts)
 {
 	struct video_priv *vid_priv;
 	extern struct expo *cur_exp;
+	struct scene_obj_menu *menu;
 	ulong addr = 0x1000;
 	struct ofprop prop;
 	struct scene *scn;
@@ -72,6 +73,11 @@ static int cedit_fdt(struct unit_test_state *uts)
 
 	ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, &vid_priv, &scn));
 
+	/* get a menu to fiddle with */
+	menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_MENU);
+	ut_assertnonnull(menu);
+	menu->cur_item_id = ID_CPU_SPEED_2;
+
 	ut_assertok(run_command("cedit write_fdt hostfs - settings.dtb", 0));
 	ut_assertok(run_commandf("load hostfs - %lx settings.dtb", addr));
 	ut_assert_nextlinen("1024 bytes read");
@@ -80,9 +86,9 @@ static int cedit_fdt(struct unit_test_state *uts)
 	tree = oftree_from_fdt(fdt);
 	node = ofnode_find_subnode(oftree_root(tree), CEDIT_NODE_NAME);
 
-	ut_asserteq(ID_CPU_SPEED_1,
+	ut_asserteq(ID_CPU_SPEED_2,
 		    ofnode_read_u32_default(node, "cpu-speed", 0));
-	ut_asserteq_str("2 GHz", ofnode_read_string(node, "cpu-speed-str"));
+	ut_asserteq_str("2.5 GHz", ofnode_read_string(node, "cpu-speed-str"));
 	ut_assert(ofnode_valid(node));
 
 	/* There should only be 4 properties */
@@ -93,6 +99,16 @@ static int cedit_fdt(struct unit_test_state *uts)
 
 	ut_assert_console_end();
 
+	/* reset the expo */
+	menu->cur_item_id = ID_CPU_SPEED_1;
+
+	/* load in the settings and make sure they update */
+	ut_assertok(run_command("cedit read_fdt hostfs - settings.dtb", 0));
+	ut_asserteq(ID_CPU_SPEED_2, menu->cur_item_id);
+
+	ut_assertnonnull(menu);
+	ut_assert_console_end();
+
 	return 0;
 }
 BOOTSTD_TEST(cedit_fdt, 0);
-- 
2.41.0.694.ge786442a9b-goog



More information about the U-Boot mailing list