
Update the cedit read/write functions to support menu items with values.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
boot/cedit.c | 148 +++++++++++++++++++++----------- boot/scene_menu.c | 2 +- doc/usage/cmd/cedit.rst | 15 +++- test/boot/cedit.c | 8 +- test/boot/files/expo_layout.dts | 4 +- 5 files changed, 117 insertions(+), 60 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c index cc1d5b76357..7fc800940fb 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -294,11 +294,49 @@ static int get_cur_menuitem_text(const struct scene_obj_menu *menu, return 0; }
+/** + * get_cur_menuitem_val() - Get the value of a menu's current item + * + * Obtains the value of the current item in the menu. If no value, then + * 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 + * @valp: Returns current-item value / sequence number + * Return: 0 on success, else -ve error value + */ +static int get_cur_menuitem_val(const struct scene_obj_menu *menu, int *valp) +{ + const struct scene_menitem *mi; + int seq; + + seq = 0; + list_for_each_entry(mi, &menu->item_head, sibling) { + if (mi->id == menu->cur_item_id) { + *valp = mi->value == INT_MAX ? seq : mi->value; + return 0; + } + seq++; + } + + return log_msg_ret("nf", -ENOENT); +} + +/** + * write_dt_string() - Write a string to the devicetree, expanding if needed + * + * If this fails, it tries again after expanding the devicetree a little + * + * @buf: Buffer containing the devicetree + * @name: Property name to use + * @str: String value + * Return: 0 if OK, -EFAULT if something went horribly wrong + */ static int write_dt_string(struct abuf *buf, const char *name, const char *str) { int ret, i;
- /* write the text of the current item */ ret = -EAGAIN; for (i = 0; ret && i < 2; i++) { ret = fdt_property_string(abuf_data(buf), name, str); @@ -316,6 +354,38 @@ static int write_dt_string(struct abuf *buf, const char *name, const char *str) return 0; }
+/** + * write_dt_u32() - Write an int to the devicetree, expanding if needed + * + * If this fails, it tries again after expanding the devicetree a little + * + * @buf: Buffer containing the devicetree + * @name: Property name to use + * @lva: Integer value + * Return: 0 if OK, -EFAULT if something went horribly wrong + */ +static int write_dt_u32(struct abuf *buf, const char *name, uint val) +{ + int ret, i; + + /* write the text of the current item */ + ret = -EAGAIN; + for (i = 0; ret && i < 2; i++) { + ret = fdt_property_u32(abuf_data(buf), name, val); + 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("str", -EFAULT); + + return 0; +} + static int h_write_settings(struct scene_obj *obj, void *vpriv) { struct cedit_iter_priv *priv = vpriv; @@ -340,23 +410,21 @@ static int h_write_settings(struct scene_obj *obj, void *vpriv) const struct scene_obj_menu *menu; const char *str; char name[80]; - int i; + int val;
/* write the ID of the current item */ 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 */ + ret = write_dt_u32(buf, obj->name, menu->cur_item_id); if (ret) - return log_msg_ret("wrt", -EFAULT); + return log_msg_ret("wrt", ret); + + snprintf(name, sizeof(name), "%s-value", obj->name); + ret = get_cur_menuitem_val(menu, &val); + if (ret < 0) + return log_msg_ret("cur", ret); + ret = write_dt_u32(buf, name, val); + if (ret) + return log_msg_ret("wr2", ret);
ret = get_cur_menuitem_text(menu, &str); if (ret) @@ -522,6 +590,14 @@ static int h_write_settings_env(struct scene_obj *obj, void *vpriv) ret = env_set(name, str); if (ret) return log_msg_ret("st2", ret); + + ret = get_cur_menuitem_val(menu, &val); + if (ret < 0) + return log_msg_ret("cur", ret); + snprintf(name, sizeof(name), "c.%s-value", obj->name); + if (priv->verbose) + printf("%s=%d\n", name, val); + break; case SCENEOBJT_TEXTLINE: { const struct scene_obj_textline *tline; @@ -625,43 +701,12 @@ 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; + uint i;
if (obj->type != SCENEOBJT_MENU || obj->id < EXPOID_BASE_ID) return 0; @@ -669,11 +714,10 @@ static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv) menu = (struct scene_obj_menu *)obj; val = menu->cur_item_id;
- ret = get_cur_menuitem_seq(menu); + ret = get_cur_menuitem_val(menu, &val); if (ret < 0) return log_msg_ret("cur", ret); - seq = ret; - log_debug("%s: seq=%d\n", menu->obj.name, seq); + log_debug("%s: val=%d\n", menu->obj.name, val);
/* figure out where to place this item */ if (!obj->bit_length) @@ -681,11 +725,11 @@ static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv) 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) { + for (i = 0; i < obj->bit_length; i++, val >>= 1) { uint bitnum = obj->start_bit + i;
priv->mask[CMOS_BYTE(bitnum)] |= 1 << CMOS_BIT(bitnum); - if (seq & 1) + if (val & 1) priv->value[CMOS_BYTE(bitnum)] |= BIT(CMOS_BIT(bitnum)); log_debug("bit %x %x %x\n", bitnum, priv->mask[CMOS_BYTE(bitnum)], @@ -788,7 +832,7 @@ static int h_read_settings_cmos(struct scene_obj *obj, void *vpriv)
/* update the current item */ log_debug("look for menuitem value %d in menu %d\n", val, menu->obj.id); - mi = scene_menuitem_find_seq(menu, val); + mi = scene_menuitem_find_val(menu, val); if (!mi) return log_msg_ret("seq", -ENOENT);
diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 002821ec1f5..86f5fd88804 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -70,7 +70,7 @@ struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
i = 0; list_for_each_entry(item, &menu->item_head, sibling) { - if (item->value == val) + if (item->value == INT_MAX ? val == i : item->value == val) return item; i++; } diff --git a/doc/usage/cmd/cedit.rst b/doc/usage/cmd/cedit.rst index f415b48699e..0f0cc26e74b 100644 --- a/doc/usage/cmd/cedit.rst +++ b/doc/usage/cmd/cedit.rst @@ -104,8 +104,10 @@ That results in:: / { cedit-values { cpu-speed = <0x00000006>; + cpu-speed-value = <0x00000003>; cpu-speed-str = "2 GHz"; power-loss = <0x0000000a>; + power-loss-value = <0x00000000>; power-loss-str = "Always Off"; }; } @@ -115,16 +117,23 @@ That results in:: This shows settings being stored in the environment::
=> cedit write_env -v - c.cpu-speed=7 + c.cpu-speed=11 c.cpu-speed-str=2.5 GHz - c.power-loss=12 - c.power-loss-str=Memory + c.cpu-speed-value=3 + c.power-loss=14 + c.power-loss-str=Always Off + c.power-loss-value=0 + c.machine-name=my-machine + c.cpu-speed=11 + c.power-loss=14 + c.machine-name=my-machine => print ... c.cpu-speed=6 c.cpu-speed-str=2 GHz c.power-loss=10 c.power-loss-str=Always Off + c.machine-name=my-machine ...
=> cedit read_env -v diff --git a/test/boot/cedit.c b/test/boot/cedit.c index 37807f9a981..876503befe0 100644 --- a/test/boot/cedit.c +++ b/test/boot/cedit.c @@ -100,14 +100,16 @@ static int cedit_fdt(struct unit_test_state *uts)
ut_asserteq(ID_CPU_SPEED_2, ofnode_read_u32_default(node, "cpu-speed", 0)); + ut_asserteq(3, + ofnode_read_u32_default(node, "cpu-speed-value", 0)); ut_asserteq_str("2.5 GHz", ofnode_read_string(node, "cpu-speed-str")); ut_asserteq_str("my-machine", ofnode_read_string(node, "machine-name"));
- /* There should only be 5 properties */ + /* There should only be 7 properties */ for (i = 0, ofnode_first_property(node, &prop); ofprop_valid(&prop); i++, ofnode_next_property(&prop)) ; - ut_asserteq(5, i); + ut_asserteq(7, i);
ut_assert_console_end();
@@ -156,8 +158,10 @@ static int cedit_env(struct unit_test_state *uts) ut_assertok(run_command("cedit write_env -v", 0)); ut_assert_nextlinen("c.cpu-speed=11"); ut_assert_nextlinen("c.cpu-speed-str=2.5 GHz"); + ut_assert_nextlinen("c.cpu-speed-value=3"); ut_assert_nextlinen("c.power-loss=14"); ut_assert_nextlinen("c.power-loss-str=Always Off"); + ut_assert_nextlinen("c.power-loss-value=0"); ut_assert_nextlinen("c.machine-name=my-machine"); ut_assert_console_end();
diff --git a/test/boot/files/expo_layout.dts b/test/boot/files/expo_layout.dts index ebe5adb27bb..9bc1e4950b9 100644 --- a/test/boot/files/expo_layout.dts +++ b/test/boot/files/expo_layout.dts @@ -40,10 +40,10 @@ ID_CPU_SPEED_3>;
/* values for the menu items */ - item-value = <(-1) 3 6>; + item-value = <0 3 6>;
start-bit = <0x400>; - bit-length = <2>; + bit-length = <3>; };
power-loss {