mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-11-29 22:51:49 +01:00
expo: cedit: Support writing settings to a file
Support writing settings from an expo into a file in FDT format. It consists of a single node with a two properties for each sceneitem, one with tag ID chosen by the user and another for its text value. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
6e648fa781
commit
2dee81fe5f
136
boot/cedit.c
136
boot/cedit.c
@ -9,6 +9,7 @@
|
|||||||
#define LOG_CATEGORY LOGC_EXPO
|
#define LOG_CATEGORY LOGC_EXPO
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <abuf.h>
|
||||||
#include <cedit.h>
|
#include <cedit.h>
|
||||||
#include <cli.h>
|
#include <cli.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
@ -18,6 +19,15 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include "scene_internal.h"
|
#include "scene_internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cedit_iter_priv - private data for cedit operations
|
||||||
|
*
|
||||||
|
* @buf: Buffer to use when writing settings to the devicetree
|
||||||
|
*/
|
||||||
|
struct cedit_iter_priv {
|
||||||
|
struct abuf *buf;
|
||||||
|
};
|
||||||
|
|
||||||
int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
|
int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
|
||||||
{
|
{
|
||||||
struct scene_obj_txt *txt;
|
struct scene_obj_txt *txt;
|
||||||
@ -182,3 +192,129 @@ int cedit_run(struct expo *exp)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_space(int ret, struct abuf *buf)
|
||||||
|
{
|
||||||
|
if (ret == -FDT_ERR_NOSPACE) {
|
||||||
|
if (!abuf_realloc_inc(buf, CEDIT_SIZE_INC))
|
||||||
|
return log_msg_ret("spc", -ENOMEM);
|
||||||
|
ret = fdt_resize(abuf_data(buf), abuf_data(buf),
|
||||||
|
abuf_size(buf));
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("res", -EFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int h_write_settings(struct scene_obj *obj, void *vpriv)
|
||||||
|
{
|
||||||
|
struct cedit_iter_priv *priv = vpriv;
|
||||||
|
struct abuf *buf = priv->buf;
|
||||||
|
|
||||||
|
switch (obj->type) {
|
||||||
|
case SCENEOBJT_NONE:
|
||||||
|
case SCENEOBJT_IMAGE:
|
||||||
|
case SCENEOBJT_TEXT:
|
||||||
|
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;
|
||||||
|
|
||||||
|
menu = (struct scene_obj_menu *)obj;
|
||||||
|
ret = -EAGAIN;
|
||||||
|
for (i = 0; ret && i < 2; i++) {
|
||||||
|
ret = fdt_property_u32(abuf_data(buf), obj->name,
|
||||||
|
menu->cur_item_id);
|
||||||
|
if (!i) {
|
||||||
|
ret = check_space(ret, buf);
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("res", -ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* this should not happen */
|
||||||
|
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);
|
||||||
|
|
||||||
|
snprintf(name, sizeof(name), "%s-str", obj->name);
|
||||||
|
ret = -EAGAIN;
|
||||||
|
for (i = 0; ret && i < 2; i++) {
|
||||||
|
ret = fdt_property_string(abuf_data(buf), name, str);
|
||||||
|
if (!i) {
|
||||||
|
ret = check_space(ret, buf);
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("rs2", -ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this should not happen */
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("wr2", -EFAULT);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cedit_write_settings(struct expo *exp, struct abuf *buf)
|
||||||
|
{
|
||||||
|
struct cedit_iter_priv priv;
|
||||||
|
void *fdt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
abuf_init(buf);
|
||||||
|
if (!abuf_realloc(buf, CEDIT_SIZE_INC))
|
||||||
|
return log_msg_ret("buf", -ENOMEM);
|
||||||
|
|
||||||
|
fdt = abuf_data(buf);
|
||||||
|
ret = fdt_create(fdt, abuf_size(buf));
|
||||||
|
if (!ret)
|
||||||
|
ret = fdt_finish_reservemap(fdt);
|
||||||
|
if (!ret)
|
||||||
|
ret = fdt_begin_node(fdt, "");
|
||||||
|
if (!ret)
|
||||||
|
ret = fdt_begin_node(fdt, CEDIT_NODE_NAME);
|
||||||
|
if (ret) {
|
||||||
|
log_debug("Failed to start FDT (err=%d)\n", ret);
|
||||||
|
return log_msg_ret("sta", -EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out the items */
|
||||||
|
priv.buf = buf;
|
||||||
|
ret = expo_iter_scene_objs(exp, h_write_settings, &priv);
|
||||||
|
if (ret) {
|
||||||
|
log_debug("Failed to write settings (err=%d)\n", ret);
|
||||||
|
return log_msg_ret("set", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fdt_end_node(fdt);
|
||||||
|
if (!ret)
|
||||||
|
ret = fdt_end_node(fdt);
|
||||||
|
if (!ret)
|
||||||
|
ret = fdt_finish(fdt);
|
||||||
|
if (ret) {
|
||||||
|
log_debug("Failed to finish FDT (err=%d)\n", ret);
|
||||||
|
return log_msg_ret("fin", -EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
51
cmd/cedit.c
51
cmd/cedit.c
@ -7,15 +7,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <abuf.h>
|
||||||
#include <cedit.h>
|
#include <cedit.h>
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <expo.h>
|
#include <expo.h>
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <mapmem.h>
|
||||||
#include <dm/ofnode.h>
|
#include <dm/ofnode.h>
|
||||||
#include <linux/sizes.h>
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
struct expo *cur_exp;
|
struct expo *cur_exp;
|
||||||
|
|
||||||
|
static int check_cur_expo(void)
|
||||||
|
{
|
||||||
|
if (!cur_exp) {
|
||||||
|
printf("No expo loaded\n");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_cedit_load(struct cmd_tbl *cmdtp, int flag, int argc,
|
static int do_cedit_load(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
char *const argv[])
|
char *const argv[])
|
||||||
{
|
{
|
||||||
@ -54,16 +67,46 @@ static int do_cedit_load(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_cedit_write_fdt(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
char *const argv[])
|
||||||
|
{
|
||||||
|
const char *fname;
|
||||||
|
struct abuf buf;
|
||||||
|
loff_t bytes;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (argc < 4)
|
||||||
|
return CMD_RET_USAGE;
|
||||||
|
fname = argv[3];
|
||||||
|
|
||||||
|
if (check_cur_expo())
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
|
||||||
|
ret = cedit_write_settings(cur_exp, &buf);
|
||||||
|
if (ret) {
|
||||||
|
printf("Failed to write settings: %dE\n", ret);
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_ANY))
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
|
||||||
|
ret = fs_write(fname, map_to_sysmem(abuf_data(&buf)), 0,
|
||||||
|
abuf_size(&buf), &bytes);
|
||||||
|
if (ret)
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc,
|
static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
char *const argv[])
|
char *const argv[])
|
||||||
{
|
{
|
||||||
ofnode node;
|
ofnode node;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!cur_exp) {
|
if (check_cur_expo())
|
||||||
printf("No expo loaded\n");
|
|
||||||
return CMD_RET_FAILURE;
|
return CMD_RET_FAILURE;
|
||||||
}
|
|
||||||
|
|
||||||
node = ofnode_path("/bootstd/cedit-theme");
|
node = ofnode_path("/bootstd/cedit-theme");
|
||||||
if (ofnode_valid(node)) {
|
if (ofnode_valid(node)) {
|
||||||
@ -85,10 +128,12 @@ static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||||||
#ifdef CONFIG_SYS_LONGHELP
|
#ifdef CONFIG_SYS_LONGHELP
|
||||||
static char cedit_help_text[] =
|
static char cedit_help_text[] =
|
||||||
"load <interface> <dev[:part]> <filename> - load config editor\n"
|
"load <interface> <dev[:part]> <filename> - load config editor\n"
|
||||||
|
"cedit write_fdt <i/f> <dev[:part]> <filename> - write settings\n"
|
||||||
"cedit run - run config editor";
|
"cedit run - run config editor";
|
||||||
#endif /* CONFIG_SYS_LONGHELP */
|
#endif /* CONFIG_SYS_LONGHELP */
|
||||||
|
|
||||||
U_BOOT_CMD_WITH_SUBCMDS(cedit, "Configuration editor", cedit_help_text,
|
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(load, 5, 1, do_cedit_load),
|
||||||
|
U_BOOT_SUBCMD_MKENT(write_fdt, 5, 1, do_cedit_write_fdt),
|
||||||
U_BOOT_SUBCMD_MKENT(run, 1, 1, do_cedit_run),
|
U_BOOT_SUBCMD_MKENT(run, 1, 1, do_cedit_run),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -10,6 +10,7 @@ Synopis
|
|||||||
|
|
||||||
cedit load <interface> <dev[:part]> <filename>
|
cedit load <interface> <dev[:part]> <filename>
|
||||||
cedit run
|
cedit run
|
||||||
|
cedit write_fdt <dev[:part]> <filename>
|
||||||
|
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
@ -38,6 +39,12 @@ Runs the default configuration-editor event loop. This is very simple, just
|
|||||||
accepting character input and moving through the objects under user control.
|
accepting character input and moving through the objects under user control.
|
||||||
The implementation is at `cedit_run()`.
|
The implementation is at `cedit_run()`.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
@ -46,3 +53,15 @@ Example
|
|||||||
|
|
||||||
=> cedit load hostfs - fred.dtb
|
=> cedit load hostfs - fred.dtb
|
||||||
=> cedit run
|
=> cedit run
|
||||||
|
=> cedit write_fdt hostfs - settings.dtb
|
||||||
|
|
||||||
|
That results in::
|
||||||
|
|
||||||
|
/ {
|
||||||
|
cedit-values {
|
||||||
|
cpu-speed = <0x00000006>;
|
||||||
|
cpu-speed-str = "2 GHz";
|
||||||
|
power-loss = <0x0000000a>;
|
||||||
|
power-loss-str = "Always Off";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@ -7,10 +7,21 @@
|
|||||||
#ifndef __CEDIT_H
|
#ifndef __CEDIT_H
|
||||||
#define __CEDIT_H
|
#define __CEDIT_H
|
||||||
|
|
||||||
|
struct abuf;
|
||||||
struct expo;
|
struct expo;
|
||||||
struct scene;
|
struct scene;
|
||||||
struct video_priv;
|
struct video_priv;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/* size increment for writing FDT */
|
||||||
|
CEDIT_SIZE_INC = 1024,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Name of the cedit node in the devicetree */
|
||||||
|
#define CEDIT_NODE_NAME "cedit-values"
|
||||||
|
|
||||||
|
extern struct expo *cur_exp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cedit_arange() - Arrange objects in a configuration-editor scene
|
* cedit_arange() - Arrange objects in a configuration-editor scene
|
||||||
*
|
*
|
||||||
@ -45,4 +56,15 @@ int cedit_run(struct expo *exp);
|
|||||||
int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
|
int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
|
||||||
struct scene **scnp);
|
struct scene **scnp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cedit_write_settings() - Write settings in FDT format
|
||||||
|
*
|
||||||
|
* Sets up an FDT with the settings
|
||||||
|
*
|
||||||
|
* @exp: Expo to write settings from
|
||||||
|
* @buf: Returns abuf containing the settings FDT (inited by this function)
|
||||||
|
* Return: 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int cedit_write_settings(struct expo *exp, struct abuf *buf);
|
||||||
|
|
||||||
#endif /* __CEDIT_H */
|
#endif /* __CEDIT_H */
|
||||||
|
|||||||
@ -7,6 +7,8 @@
|
|||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <cedit.h>
|
#include <cedit.h>
|
||||||
#include <expo.h>
|
#include <expo.h>
|
||||||
|
#include <mapmem.h>
|
||||||
|
#include <dm/ofnode.h>
|
||||||
#include <test/ut.h>
|
#include <test/ut.h>
|
||||||
#include "bootstd_common.h"
|
#include "bootstd_common.h"
|
||||||
#include <test/cedit-test.h>
|
#include <test/cedit-test.h>
|
||||||
@ -51,3 +53,46 @@ static int cedit_base(struct unit_test_state *uts)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
BOOTSTD_TEST(cedit_base, 0);
|
BOOTSTD_TEST(cedit_base, 0);
|
||||||
|
|
||||||
|
/* Check the cedit write_fdt commands */
|
||||||
|
static int cedit_fdt(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct video_priv *vid_priv;
|
||||||
|
extern struct expo *cur_exp;
|
||||||
|
ulong addr = 0x1000;
|
||||||
|
struct ofprop prop;
|
||||||
|
struct scene *scn;
|
||||||
|
oftree tree;
|
||||||
|
ofnode node;
|
||||||
|
void *fdt;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
fdt = map_sysmem(addr, 1024);
|
||||||
|
tree = oftree_from_fdt(fdt);
|
||||||
|
node = ofnode_find_subnode(oftree_root(tree), CEDIT_NODE_NAME);
|
||||||
|
|
||||||
|
ut_asserteq(ID_CPU_SPEED_1,
|
||||||
|
ofnode_read_u32_default(node, "cpu-speed", 0));
|
||||||
|
ut_asserteq_str("2 GHz", ofnode_read_string(node, "cpu-speed-str"));
|
||||||
|
ut_assert(ofnode_valid(node));
|
||||||
|
|
||||||
|
/* There should only be 4 properties */
|
||||||
|
for (i = 0, ofnode_first_property(node, &prop); ofprop_valid(&prop);
|
||||||
|
i++, ofnode_next_property(&prop))
|
||||||
|
;
|
||||||
|
ut_asserteq(4, i);
|
||||||
|
|
||||||
|
ut_assert_console_end();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
BOOTSTD_TEST(cedit_fdt, 0);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user