From 040b04685ea4c47a5148c2fcc2ff6dfdd83bc714 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Aug 2023 16:40:25 -0600 Subject: expo: Split out cedit into its own header Before adding more functions to this interface, create a new header for the configuration editor. Fix up the expo header guard while we are here. Signed-off-by: Simon Glass --- boot/cedit.c | 1 + 1 file changed, 1 insertion(+) (limited to 'boot/cedit.c') diff --git a/boot/cedit.c b/boot/cedit.c index ee24658917b..2d16086bad6 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include -- cgit v1.2.3 From 8d0f890a0b9b0f7bf0b529f18f81a45ec6f64eb1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Aug 2023 16:40:27 -0600 Subject: expo: Add a function to prepare a cedit Split out the code which prepares the cedit for use, so we can call it from a test. Add a log category while we are here. Signed-off-by: Simon Glass --- boot/cedit.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'boot/cedit.c') diff --git a/boot/cedit.c b/boot/cedit.c index 2d16086bad6..6c10b211454 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -6,6 +6,8 @@ * Written by Simon Glass */ +#define LOG_CATEGORY LOGC_EXPO + #include #include #include @@ -47,18 +49,15 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) return 0; } -int cedit_run(struct expo *exp) +int cedit_prepare(struct expo *exp, struct video_priv **vid_privp, + struct scene **scnp) { - struct cli_ch_state s_cch, *cch = &s_cch; struct video_priv *vid_priv; - uint scene_id; struct udevice *dev; struct scene *scn; - bool done; + uint scene_id; int ret; - cli_ch_init(cch); - /* For now we only support a video console */ ret = uclass_first_device_err(UCLASS_VIDEO, &dev); if (ret) @@ -93,6 +92,27 @@ int cedit_run(struct expo *exp) if (ret) return log_msg_ret("dim", ret); + *vid_privp = vid_priv; + *scnp = scn; + + return scene_id; +} + +int cedit_run(struct expo *exp) +{ + struct cli_ch_state s_cch, *cch = &s_cch; + struct video_priv *vid_priv; + uint scene_id; + struct scene *scn; + bool done; + int ret; + + cli_ch_init(cch); + ret = cedit_prepare(exp, &vid_priv, &scn); + if (ret < 0) + return log_msg_ret("prep", ret); + scene_id = ret; + done = false; do { struct expo_action act; -- cgit v1.2.3 From 2dee81fe5f4a6427ba48fe17ff017930ddf3b4e4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Aug 2023 16:40:33 -0600 Subject: 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 --- boot/cedit.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) (limited to 'boot/cedit.c') diff --git a/boot/cedit.c b/boot/cedit.c index 6c10b211454..4dd79a2263d 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -9,6 +9,7 @@ #define LOG_CATEGORY LOGC_EXPO #include +#include #include #include #include @@ -18,6 +19,15 @@ #include #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) { struct scene_obj_txt *txt; @@ -182,3 +192,129 @@ int cedit_run(struct expo *exp) 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; +} -- cgit v1.2.3 From 472317cb12e534f56b631365987934960dfb0a3f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Aug 2023 16:40:34 -0600 Subject: expo: cedit: Support reading settings from a file Add a command to read cedit settings from a devicetree file. Signed-off-by: Simon Glass --- boot/cedit.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'boot/cedit.c') diff --git a/boot/cedit.c b/boot/cedit.c index 4dd79a2263d..6a74a380989 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; +} -- cgit v1.2.3 From fc9c0e0771cad76b24f73bb64c105b6ea39721ca Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Aug 2023 16:40:35 -0600 Subject: 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 --- boot/cedit.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 14 deletions(-) (limited to 'boot/cedit.c') diff --git a/boot/cedit.c b/boot/cedit.c index 6a74a380989..9399c01cda9 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; +} -- cgit v1.2.3 From bcf2b7202e960e7fb3df8d5e8ed0d6fa00a5a9fa Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Aug 2023 16:40:36 -0600 Subject: expo: cedit: Support reading settings from environment vars Add a command to read cedit settings from environment variables so that they can be restored as part of the environment. Signed-off-by: Simon Glass --- boot/cedit.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'boot/cedit.c') diff --git a/boot/cedit.c b/boot/cedit.c index 9399c01cda9..e3f6dc00399 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -439,3 +439,48 @@ int cedit_write_settings_env(struct expo *exp, bool verbose) return 0; } + +static int h_read_settings_env(struct scene_obj *obj, void *vpriv) +{ + struct cedit_iter_priv *priv = vpriv; + struct scene_obj_menu *menu; + char var[60]; + 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); + + val = env_get_ulong(var, 10, 0); + if (priv->verbose) + printf("%s=%d\n", var, val); + if (!val) + return log_msg_ret("get", -ENOENT); + + /* + * note that no validation is done here, to make sure the ID is valid + * and actually points to a menu item + */ + menu->cur_item_id = val; + + return 0; +} + +int cedit_read_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_read_settings_env, &priv); + if (ret) { + log_debug("Failed to read settings from env (err=%d)\n", ret); + return log_msg_ret("set", ret); + } + + return 0; +} -- cgit v1.2.3 From eb6c71b56282d3054dbffb83793e7d2c6745578e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Aug 2023 16:40:37 -0600 Subject: expo: cedit: Support writing settings to CMOS RAM Add a command to write cedit settings to CMOS RAM so that it can be preserved across a reboot. This uses a simple bit-encoding, where each field has a 'bit position' and a 'bit length' in the schema. Signed-off-by: Simon Glass --- boot/cedit.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) (limited to 'boot/cedit.c') diff --git a/boot/cedit.c b/boot/cedit.c index e3f6dc00399..725745aba55 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -15,22 +15,37 @@ #include #include #include +#include #include +#include #include #include #include "scene_internal.h" +enum { + CMOS_MAX_BITS = 2048, + CMOS_MAX_BYTES = CMOS_MAX_BITS / 8, +}; + +#define CMOS_BYTE(bit) ((bit) / 8) +#define CMOS_BIT(bit) ((bit) % 8) + /** * 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 * @verbose: true to show writing to environment variables + * @mask: Mask bits for the CMOS RAM. If a bit is set the byte containing it + * will be written + * @value: Value bits for CMOS RAM. This is the actual value written */ struct cedit_iter_priv { struct abuf *buf; ofnode node; bool verbose; + u8 *mask; + u8 *value; }; int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) @@ -445,7 +460,7 @@ static int h_read_settings_env(struct scene_obj *obj, void *vpriv) struct cedit_iter_priv *priv = vpriv; struct scene_obj_menu *menu; char var[60]; - int val, ret; + int val; if (obj->type != SCENEOBJT_MENU) return 0; @@ -484,3 +499,123 @@ int cedit_read_settings_env(struct expo *exp, bool verbose) return 0; } + +/** + * get_cur_menuitem_seq() - Get the sequence number of a menu's current item + * + * Enumerates the items of a menu (0, 1, 2) and returns the sequence number of + * the currently selected item. If the first item is selected, this returns 0; + * if the second, 1; etc. + * + * @menu: Menu to check + * Return: Sequence number on success, else -ve error value + */ +static int get_cur_menuitem_seq(const struct scene_obj_menu *menu) +{ + const struct scene_menitem *mi; + int seq, found; + + seq = 0; + found = -1; + list_for_each_entry(mi, &menu->item_head, sibling) { + if (mi->id == menu->cur_item_id) { + found = seq; + break; + } + seq++; + } + + if (found == -1) + return log_msg_ret("nf", -ENOENT); + + return found; +} + +static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv) +{ + const struct scene_obj_menu *menu; + struct cedit_iter_priv *priv = vpriv; + int val, ret; + uint i, seq; + + if (obj->type != SCENEOBJT_MENU) + return 0; + + menu = (struct scene_obj_menu *)obj; + val = menu->cur_item_id; + + ret = get_cur_menuitem_seq(menu); + if (ret < 0) + return log_msg_ret("cur", ret); + seq = ret; + log_debug("%s: seq=%d\n", menu->obj.name, seq); + + /* figure out where to place this item */ + if (!obj->bit_length) + return log_msg_ret("len", -EINVAL); + if (obj->start_bit + obj->bit_length > CMOS_MAX_BITS) + return log_msg_ret("bit", -E2BIG); + + for (i = 0; i < obj->bit_length; i++, seq >>= 1) { + uint bitnum = obj->start_bit + i; + + priv->mask[CMOS_BYTE(bitnum)] |= 1 << CMOS_BIT(bitnum); + if (seq & 1) + priv->value[CMOS_BYTE(bitnum)] |= BIT(CMOS_BIT(bitnum)); + log_debug("bit %x %x %x\n", bitnum, + priv->mask[CMOS_BYTE(bitnum)], + priv->value[CMOS_BYTE(bitnum)]); + } + + return 0; +} + +int cedit_write_settings_cmos(struct expo *exp, struct udevice *dev, + bool verbose) +{ + struct cedit_iter_priv priv; + int ret, i, count, first, last; + + /* write out the items */ + priv.mask = calloc(1, CMOS_MAX_BYTES); + if (!priv.mask) + return log_msg_ret("mas", -ENOMEM); + priv.value = calloc(1, CMOS_MAX_BYTES); + if (!priv.value) { + free(priv.mask); + return log_msg_ret("val", -ENOMEM); + } + + ret = expo_iter_scene_objs(exp, h_write_settings_cmos, &priv); + if (ret) { + log_debug("Failed to write CMOS (err=%d)\n", ret); + ret = log_msg_ret("set", ret); + goto done; + } + + /* write the data to the RTC */ + first = CMOS_MAX_BYTES; + last = -1; + for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) { + if (priv.mask[i]) { + log_debug("Write byte %x: %x\n", i, priv.value[i]); + ret = rtc_write8(dev, i, priv.value[i]); + if (ret) { + ret = log_msg_ret("wri", ret); + goto done; + } + count++; + first = min(first, i); + last = max(last, i); + } + } + if (verbose) { + printf("Write %d bytes from offset %x to %x\n", count, first, + last); + } + +done: + free(priv.mask); + free(priv.value); + return ret; +} -- cgit v1.2.3 From cfc402db3954d7c852c322b232ad6d8842af6bf1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Aug 2023 16:40:38 -0600 Subject: expo: cedit: Support reading settings from CMOS RAM Add a command to read edit settings from CMOS RAM, using the cedit definition to indicate which registers and bits are used. Signed-off-by: Simon Glass --- boot/cedit.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) (limited to 'boot/cedit.c') diff --git a/boot/cedit.c b/boot/cedit.c index 725745aba55..73645f70b6c 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -39,6 +39,7 @@ enum { * @mask: Mask bits for the CMOS RAM. If a bit is set the byte containing it * will be written * @value: Value bits for CMOS RAM. This is the actual value written + * @dev: RTC device to write to */ struct cedit_iter_priv { struct abuf *buf; @@ -46,6 +47,7 @@ struct cedit_iter_priv { bool verbose; u8 *mask; u8 *value; + struct udevice *dev; }; int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) @@ -619,3 +621,100 @@ done: free(priv.value); return ret; } + +static int h_read_settings_cmos(struct scene_obj *obj, void *vpriv) +{ + struct cedit_iter_priv *priv = vpriv; + const struct scene_menitem *mi; + struct scene_obj_menu *menu; + int val, ret; + uint i; + + if (obj->type != SCENEOBJT_MENU) + return 0; + + menu = (struct scene_obj_menu *)obj; + + /* figure out where to place this item */ + if (!obj->bit_length) + return log_msg_ret("len", -EINVAL); + if (obj->start_bit + obj->bit_length > CMOS_MAX_BITS) + return log_msg_ret("bit", -E2BIG); + + val = 0; + for (i = 0; i < obj->bit_length; i++) { + uint bitnum = obj->start_bit + i; + uint offset = CMOS_BYTE(bitnum); + + /* read the byte if not already read */ + if (!priv->mask[offset]) { + ret = rtc_read8(priv->dev, offset); + if (ret < 0) + return log_msg_ret("rea", ret); + priv->value[offset] = ret; + + /* mark it as read */ + priv->mask[offset] = 0xff; + } + + if (priv->value[offset] & BIT(CMOS_BIT(bitnum))) + val |= BIT(i); + log_debug("bit %x %x\n", bitnum, val); + } + + /* update the current item */ + mi = scene_menuitem_find_seq(menu, val); + if (!mi) + return log_msg_ret("seq", -ENOENT); + + menu->cur_item_id = mi->id; + log_debug("Update menu %d cur_item_id %d\n", menu->obj.id, mi->id); + + return 0; +} + +int cedit_read_settings_cmos(struct expo *exp, struct udevice *dev, + bool verbose) +{ + struct cedit_iter_priv priv; + int ret, i, count, first, last; + + /* read in the items */ + priv.mask = calloc(1, CMOS_MAX_BYTES); + if (!priv.mask) + return log_msg_ret("mas", -ENOMEM); + priv.value = calloc(1, CMOS_MAX_BYTES); + if (!priv.value) { + free(priv.mask); + return log_msg_ret("val", -ENOMEM); + } + priv.dev = dev; + + ret = expo_iter_scene_objs(exp, h_read_settings_cmos, &priv); + if (ret) { + log_debug("Failed to read CMOS (err=%d)\n", ret); + ret = log_msg_ret("set", ret); + goto done; + } + + /* read the data to the RTC */ + first = CMOS_MAX_BYTES; + last = -1; + for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) { + if (priv.mask[i]) { + log_debug("Read byte %x: %x\n", i, priv.value[i]); + count++; + first = min(first, i); + last = max(last, i); + } + } + if (verbose) { + printf("Read %d bytes from offset %x to %x\n", count, first, + last); + } + +done: + free(priv.mask); + free(priv.value); + return ret; +} -- cgit v1.2.3