From: Simon Glass Date: Mon, 14 Aug 2023 22:40:35 +0000 (-0600) Subject: expo: cedit: Support writing settings to environment vars X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=fc9c0e0771cad76b24f73bb64c105b6ea39721ca;p=u-boot.git expo: cedit: Support writing settings to environment vars Add a command to write cedit settings to environment variables so that they can be stored with 'saveenv'. Signed-off-by: Simon Glass --- diff --git a/boot/cedit.c b/boot/cedit.c index 6a74a38098..9399c01cda 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -24,10 +25,12 @@ * * @buf: Buffer to use when writing settings to the devicetree * @node: Node to read from when reading settings from devicetree + * @verbose: true to show writing to environment variables */ struct cedit_iter_priv { struct abuf *buf; ofnode node; + bool verbose; }; int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) @@ -209,6 +212,30 @@ static int check_space(int ret, struct abuf *buf) return 0; } +static int get_cur_menuitem_text(const struct scene_obj_menu *menu, + const char **strp) +{ + struct scene *scn = menu->obj.scene; + const struct scene_menitem *mi; + const struct scene_obj_txt *txt; + const char *str; + + mi = scene_menuitem_find(menu, menu->cur_item_id); + if (!mi) + return log_msg_ret("mi", -ENOENT); + + txt = scene_obj_find(scn, mi->label_id, SCENEOBJT_TEXT); + if (!txt) + return log_msg_ret("txt", -ENOENT); + + str = expo_get_str(scn->expo, txt->str_id); + if (!str) + return log_msg_ret("str", -ENOENT); + *strp = str; + + return 0; +} + static int h_write_settings(struct scene_obj *obj, void *vpriv) { struct cedit_iter_priv *priv = vpriv; @@ -221,9 +248,6 @@ static int h_write_settings(struct scene_obj *obj, void *vpriv) break; case SCENEOBJT_MENU: { const struct scene_obj_menu *menu; - const struct scene_obj_txt *txt; - struct scene *scn = obj->scene; - const struct scene_menitem *mi; const char *str; char name[80]; int ret, i; @@ -243,17 +267,9 @@ static int h_write_settings(struct scene_obj *obj, void *vpriv) if (ret) return log_msg_ret("wrt", -EFAULT); - mi = scene_menuitem_find(menu, menu->cur_item_id); - if (!mi) - return log_msg_ret("mi", -ENOENT); - - txt = scene_obj_find(scn, mi->label_id, SCENEOBJT_TEXT); - if (!txt) - return log_msg_ret("txt", -ENOENT); - - str = expo_get_str(scn->expo, txt->str_id); - if (!str) - return log_msg_ret("str", -ENOENT); + ret = get_cur_menuitem_text(menu, &str); + if (ret) + return log_msg_ret("mis", ret); snprintf(name, sizeof(name), "%s-str", obj->name); ret = -EAGAIN; @@ -370,3 +386,56 @@ int cedit_read_settings(struct expo *exp, oftree tree) return 0; } + +static int h_write_settings_env(struct scene_obj *obj, void *vpriv) +{ + const struct scene_obj_menu *menu; + struct cedit_iter_priv *priv = vpriv; + char name[80], var[60]; + const char *str; + int val, ret; + + if (obj->type != SCENEOBJT_MENU) + return 0; + + menu = (struct scene_obj_menu *)obj; + val = menu->cur_item_id; + snprintf(var, sizeof(var), "c.%s", obj->name); + + if (priv->verbose) + printf("%s=%d\n", var, val); + + ret = env_set_ulong(var, val); + if (ret) + return log_msg_ret("set", ret); + + ret = get_cur_menuitem_text(menu, &str); + if (ret) + return log_msg_ret("mis", ret); + + snprintf(name, sizeof(name), "c.%s-str", obj->name); + if (priv->verbose) + printf("%s=%s\n", name, str); + + ret = env_set(name, str); + if (ret) + return log_msg_ret("st2", ret); + + return 0; +} + +int cedit_write_settings_env(struct expo *exp, bool verbose) +{ + struct cedit_iter_priv priv; + int ret; + + /* write out the items */ + priv.verbose = verbose; + ret = expo_iter_scene_objs(exp, h_write_settings_env, &priv); + if (ret) { + log_debug("Failed to write settings to env (err=%d)\n", ret); + return log_msg_ret("set", ret); + } + + return 0; +} diff --git a/cmd/cedit.c b/cmd/cedit.c index a155e080b1..85629f7b83 100644 --- a/cmd/cedit.c +++ b/cmd/cedit.c @@ -136,6 +136,26 @@ static int do_cedit_read_fdt(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } +static int do_cedit_write_env(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + bool verbose; + int ret; + + if (check_cur_expo()) + return CMD_RET_FAILURE; + + verbose = argc > 1 && !strcmp(argv[1], "-v"); + + ret = cedit_write_settings_env(cur_exp, verbose); + if (ret) { + printf("Failed to write settings to environment: %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[]) { @@ -167,6 +187,7 @@ static char cedit_help_text[] = "load - load config editor\n" "cedit read_fdt - read settings\n" "cedit write_fdt - write settings\n" + "cedit write_env [-v] - write settings to env vars\n" "cedit run - run config editor"; #endif /* CONFIG_SYS_LONGHELP */ @@ -174,5 +195,6 @@ 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(write_env, 2, 1, do_cedit_write_env), 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 0a9f620b59..426470a82a 100644 --- a/doc/usage/cmd/cedit.rst +++ b/doc/usage/cmd/cedit.rst @@ -12,6 +12,7 @@ Synopis cedit run cedit write_fdt cedit read_fdt + cedit write_env [-v] Description ----------- @@ -52,6 +53,19 @@ cedit read_fdt Reads the user settings from a devicetree file and updates the cedit with those settings. +cedit write_env +~~~~~~~~~~~~~~~ + +Writes the settings to environment variables. For each menu item the selected +ID and its text string are written, similar to: + + setenv c. + setenv c.-str + +The `-v` flag enables verbose mode, where each variable is printed before it is +set. + + Example ------- @@ -73,3 +87,14 @@ That results in:: } => cedit read_fdt hostfs - settings.dtb + +This shows settings being stored in the environment:: + + => cedit write_env -v + => print + ... + c.cpu-speed=6 + c.cpu-speed-str=2 GHz + c.power-loss=10 + c.power-loss-str=Always Off + ... diff --git a/include/cedit.h b/include/cedit.h index bb6e87d4af..f261207e20 100644 --- a/include/cedit.h +++ b/include/cedit.h @@ -80,4 +80,13 @@ int cedit_write_settings(struct expo *exp, struct abuf *buf); */ int cedit_read_settings(struct expo *exp, oftree tree); +/** + * cedit_write_settings_env() - Write settings to envrionment variables + * + * @exp: Expo to write settings from + * @verbose: true to print each var as it is set + * Return: 0 if OK, -ve on error + */ +int cedit_write_settings_env(struct expo *exp, bool verbose); + #endif /* __CEDIT_H */ diff --git a/test/boot/cedit.c b/test/boot/cedit.c index 659c47ed35..26a69f0323 100644 --- a/test/boot/cedit.c +++ b/test/boot/cedit.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -112,3 +113,35 @@ static int cedit_fdt(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(cedit_fdt, 0); + +/* Check the cedit write_env command */ +static int cedit_env(struct unit_test_state *uts) +{ + struct video_priv *vid_priv; + extern struct expo *cur_exp; + struct scene_obj_menu *menu; + struct scene *scn; + + console_record_reset_enable(); + ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0)); + + 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_env -v", 0)); + ut_assert_nextlinen("c.cpu-speed=7"); + ut_assert_nextlinen("c.cpu-speed-str=2.5 GHz"); + ut_assert_nextlinen("c.power-loss=10"); + ut_assert_nextlinen("c.power-loss-str=Always Off"); + ut_assert_console_end(); + + ut_asserteq(7, env_get_ulong("c.cpu-speed", 10, 0)); + ut_asserteq_str("2.5 GHz", env_get("c.cpu-speed-str")); + + return 0; +} +BOOTSTD_TEST(cedit_env, 0);