]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
expo: Support menu-item values in cedit
authorSimon Glass <sjg@chromium.org>
Mon, 14 Oct 2024 22:32:00 +0000 (16:32 -0600)
committerSimon Glass <sjg@chromium.org>
Fri, 18 Oct 2024 20:10:22 +0000 (14:10 -0600)
Update the cedit read/write functions to support menu items with
values.

Signed-off-by: Simon Glass <sjg@chromium.org>
boot/cedit.c
boot/scene_menu.c
doc/usage/cmd/cedit.rst
test/boot/cedit.c
test/boot/files/expo_layout.dts

index 9d48d3ed50b98aba846351de83e8b5cd3edd9be3..d12892fbc4a1f04330c5bd5c04b96be821775057 100644 (file)
@@ -293,11 +293,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);
@@ -315,6 +353,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;
@@ -339,23 +409,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)
@@ -521,6 +589,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;
@@ -624,43 +700,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;
@@ -668,11 +713,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)
@@ -680,11 +724,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)],
@@ -787,7 +831,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);
 
index 04ff1590bc1bced9cad8cdec86b35dcdbc0048d6..17150af145dcd4ea2dbcbf7e0e63c4c2f7af64de 100644 (file)
@@ -69,7 +69,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++;
        }
index 5670805a00e17b884c34ba9d182700e615edb215..f29f1b3f38899d90bfb0a388fdedfca5b05c3ce3 100644 (file)
@@ -107,8 +107,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";
         };
     }
@@ -118,16 +120,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
index 0f2c2e73dd336590524a33ca2cfb6d59ece3a54d..4d1b99bc2eaaabfdee756b11a61f4f0bce348825 100644 (file)
@@ -96,14 +96,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();
 
@@ -151,8 +153,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();
 
index ebe5adb27bbea5d8e5c2d61312108b1059a6fd74..9bc1e4950b96606e4780c9cce8033a9f34c8655d 100644 (file)
                                        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 {