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> --- boot/bootflow_menu.c | 86 ++++++++++++++++++++------------------------ cmd/bootflow.c | 35 +++++++++++------- include/bootflow.h | 33 ++++++++++------- 3 files changed, 82 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 0163129deba..2871d91dd29 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,31 @@ __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 == -EAGAIN) { - 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("ret %d bflow %p\n", ret, bflow); - 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