Split the starting piece of this function into bootflow_menu_start()
and the polling part into bootflow_menu_poll() so that it is possible
for the caller to be in control of the event loop.

Move the expo_destroy() call into the caller.

Signed-off-by: Simon Glass <s...@chromium.org>
---

(no changes since v1)

 boot/bootflow_menu.c | 86 ++++++++++++++++++++------------------------
 cmd/bootflow.c       | 34 +++++++++++-------
 include/bootflow.h   | 33 ++++++++++-------
 3 files changed, 81 insertions(+), 72 deletions(-)

diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index d20d0be4734..018910c65b8 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -175,20 +175,13 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode 
node)
        return 0;
 }
 
-int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
-                     struct bootflow **bflowp)
+int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
+                       struct expo **expp)
 {
-       struct bootflow *sel_bflow;
        struct udevice *dev;
-       struct scene *scn;
        struct expo *exp;
-       uint sel_id;
-       bool done;
        int ret;
 
-       sel_bflow = NULL;
-       *bflowp = NULL;
-
        ret = bootflow_menu_new(&exp);
        if (ret)
                return log_msg_ret("exp", ret);
@@ -210,56 +203,55 @@ int bootflow_menu_run(struct bootstd_priv *std, bool 
text_mode,
        ret = expo_set_scene_id(exp, MAIN);
        if (ret)
                return log_msg_ret("scn", ret);
-       scn = expo_lookup_scene_id(exp, MAIN);
-       if (!scn)
-               return log_msg_ret("scn", -ENOENT);
 
        if (text_mode)
                expo_set_text_mode(exp, text_mode);
 
-       done = false;
-       do {
-               struct expo_action act;
-
-               ret = expo_poll(exp, &act);
-               if (!ret) {
-                       switch (act.type) {
-                       case EXPOACT_SELECT:
-                               sel_id = act.select.id;
-                               done = true;
-                               break;
-                       case EXPOACT_POINT_ITEM:
-                               LOGR("bmp", scene_menu_select_item(scn,
-                                       OBJ_MENU, act.select.id));
-                               break;
-                       case EXPOACT_QUIT:
-                               return -EPIPE;
-                       default:
-                               break;
-                       }
-               } else if (ret != -EPIPE && ret != -EAGAIN) {
-                       LOGR("bmr", ret);
-               }
-       } while (!done);
+       *expp = exp;
+
+       return 0;
+}
 
-       if (sel_id) {
+int bootflow_menu_poll(struct expo *exp, struct bootflow **bflowp)
+{
+       struct bootflow *sel_bflow;
+       struct expo_action act;
+       int ret;
+
+       sel_bflow = NULL;
+       *bflowp = NULL;
+
+       LOGR("bmp", expo_poll(exp, &act));
+
+       switch (act.type) {
+       case EXPOACT_SELECT: {
                struct bootflow *bflow;
                int i;
 
                for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
                     ret = bootflow_next_glob(&bflow), i++) {
-                       if (i == sel_id - ITEM) {
-                               sel_bflow = bflow;
-                               break;
+                       if (i == act.select.id - ITEM) {
+                               *bflowp = bflow;
+                               // printf("found %p\n", bflow);
+                               return 0;
                        }
                }
+               break;
+       }
+       case EXPOACT_POINT_ITEM: {
+               struct scene *scn = expo_lookup_scene_id(exp, MAIN);
+
+               if (!scn)
+                       return log_msg_ret("bms", -ENOENT);
+               LOGR("bmp", scene_menu_select_item(scn, OBJ_MENU,
+                                                  act.select.id));
+               break;
+       }
+       case EXPOACT_QUIT:
+               return -EPIPE;
+       default:
+               break;
        }
 
-       expo_destroy(exp);
-
-       if (!sel_bflow)
-               return -EAGAIN;
-       *bflowp = sel_bflow;
-
-       return 0;
+       return -EAGAIN;
 }
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 6189ab7fa40..456f51760f1 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -13,6 +13,8 @@
 #include <command.h>
 #include <console.h>
 #include <dm.h>
+#include <expo.h>
+#include <log.h>
 #include <mapmem.h>
 
 /**
@@ -105,24 +107,30 @@ __maybe_unused static int bootflow_handle_menu(struct 
bootstd_priv *std,
                                               bool text_mode,
                                               struct bootflow **bflowp)
 {
+       struct expo *exp;
        struct bootflow *bflow;
        int ret;
 
-       ret = bootflow_menu_run(std, text_mode, &bflow);
-       if (ret) {
-               if (ret == -EPIPE) {
-                       printf("Nothing chosen\n");
-                       std->cur_bootflow = NULL;
-               } else {
-                       printf("Menu failed (err=%d)\n", ret);
-               }
+       LOGR("bhs", bootflow_menu_start(std, text_mode, &exp));
 
-               return ret;
-       }
+       do {
+               ret = bootflow_menu_poll(exp, &bflow);
+       } while (ret == -EAGAIN);
 
-       printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name);
-       std->cur_bootflow = bflow;
-       *bflowp = bflow;
+       if (ret == -EPIPE) {
+               printf("Nothing chosen\n");
+               std->cur_bootflow = NULL;
+       } else if (ret) {
+               printf("Menu failed (err=%d)\n", ret);
+       } else {
+               printf("Selected: %s\n", bflow->os_name ? bflow->os_name :
+                      bflow->name);
+               std->cur_bootflow = bflow;
+               *bflowp = bflow;
+       }
+       expo_destroy(exp);
+       if (ret)
+               return ret;
 
        return 0;
 }
diff --git a/include/bootflow.h b/include/bootflow.h
index ef1d1a75ded..72f09304cff 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -503,18 +503,6 @@ int bootflow_menu_new(struct expo **expp);
  */
 int bootflow_menu_apply_theme(struct expo *exp, ofnode node);
 
-/**
- * bootflow_menu_run() - Create and run a menu of available bootflows
- *
- * @std: Bootstd information
- * @text_mode: Uses a text-based menu suitable for a serial port
- * @bflowp: Returns chosen bootflow (set to NULL if nothing is chosen)
- * @return 0 if an option was chosen, -EPIPE if nothing was chosen, -ve on
- * error
- */
-int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
-                     struct bootflow **bflowp);
-
 #define BOOTFLOWCL_EMPTY       ((void *)1)
 
 /**
@@ -639,4 +627,25 @@ struct bootflow_img *bootflow_img_add(struct bootflow 
*bflow, const char *fname,
  */
 int bootflow_get_seq(const struct bootflow *bflow);
 
+/**
+ * bootflow_menu_start() - Start up a menu for bootflows
+ *
+ * @std: bootstd information
+ * @text_mode: true to show the menu in text mode, false to use video display
+ * @expp: Returns the expo created, on success
+ * Return: 0 if OK, -ve on error
+ */
+int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
+                       struct expo **expp);
+
+/**
+ * bootflow_menu_poll() - Poll a menu for user action
+ *
+ * @exp: Expo to poll
+ * @bflowp: Returns chosen bootflow (set to NULL if nothing is chosen)
+ * Return 0 if a bootflow was chosen, -EAGAIN if nothing is chosen yet, -EPIPE
+ *     if the user quit
+ */
+int bootflow_menu_poll(struct expo *exp, struct bootflow **bflowp);
+
 #endif
-- 
2.43.0

Reply via email to