diff options
author | Simon Glass <sjg@chromium.org> | 2023-01-06 08:52:36 -0600 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-01-16 18:26:50 -0500 |
commit | 87c6f8a4880d849fc4b782d0c43880ef7eb1fe8e (patch) | |
tree | 708deae4b26ad9ee3da1993e5c256bc6daee3177 /boot | |
parent | 9e7ac0b0be5cb663e539716554d66f8f0890ca83 (diff) | |
download | u-boot-87c6f8a4880d849fc4b782d0c43880ef7eb1fe8e.tar.gz u-boot-87c6f8a4880d849fc4b782d0c43880ef7eb1fe8e.tar.bz2 u-boot-87c6f8a4880d849fc4b782d0c43880ef7eb1fe8e.zip |
expo: Add basic implementation
An expo is a way of presenting and collecting information from the
user. It consists of a collection of 'scenes' of which only one is
presented at a time. An expo is typically used to show a boot menu
and allow settings to be changed.
One created, the same expo can be automatically presented in graphical
form using a vidconsole, or in text form on a serial console.
Add an initial implementation of the expo itself. Supports for scenes
and objects is provided later.
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'boot')
-rw-r--r-- | boot/Kconfig | 12 | ||||
-rw-r--r-- | boot/expo.c | 170 |
2 files changed, 182 insertions, 0 deletions
diff --git a/boot/Kconfig b/boot/Kconfig index 30bc182fcd..36ccbf6b54 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -557,6 +557,18 @@ config VPL_BOOTMETH_VBE_SIMPLE_FW endif # BOOTMETH_VBE +config EXPO + bool "Support for expos - groups of scenes displaying a UI" + default y if BOOTMETH_VBE + help + An expo is a way of presenting and collecting information from the + user. It consists of a collection of 'scenes' of which only one is + presented at a time. An expo is typically used to show a boot menu + and allow settings to be changed. + + The expo can be presented in graphics form using a vidconsole, or in + text form on a serial console. + config BOOTMETH_SANDBOX def_bool y depends on SANDBOX diff --git a/boot/expo.c b/boot/expo.c new file mode 100644 index 0000000000..05950a1760 --- /dev/null +++ b/boot/expo.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Implementation of a expo, a collection of scenes providing menu options + * + * Copyright 2022 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <dm.h> +#include <expo.h> +#include <malloc.h> +#include <video.h> +#include "scene_internal.h" + +int expo_new(const char *name, void *priv, struct expo **expp) +{ + struct expo *exp; + + exp = calloc(1, sizeof(struct expo)); + if (!exp) + return log_msg_ret("expo", -ENOMEM); + exp->name = strdup(name); + if (!exp->name) { + free(exp); + return log_msg_ret("name", -ENOMEM); + } + exp->priv = priv; + INIT_LIST_HEAD(&exp->scene_head); + INIT_LIST_HEAD(&exp->str_head); + + *expp = exp; + + return 0; +} + +static void estr_destroy(struct expo_string *estr) +{ + free(estr); +} + +void expo_destroy(struct expo *exp) +{ + struct scene *scn, *next; + struct expo_string *estr, *enext; + + list_for_each_entry_safe(scn, next, &exp->scene_head, sibling) + scene_destroy(scn); + + list_for_each_entry_safe(estr, enext, &exp->str_head, sibling) + estr_destroy(estr); + + free(exp->name); + free(exp); +} + +int expo_str(struct expo *exp, const char *name, uint id, const char *str) +{ + struct expo_string *estr; + + estr = calloc(1, sizeof(struct expo_string)); + if (!estr) + return log_msg_ret("obj", -ENOMEM); + + estr->id = resolve_id(exp, id); + estr->str = str; + list_add_tail(&estr->sibling, &exp->str_head); + + return estr->id; +} + +const char *expo_get_str(struct expo *exp, uint id) +{ + struct expo_string *estr; + + list_for_each_entry(estr, &exp->str_head, sibling) { + if (estr->id == id) + return estr->str; + } + + return NULL; +} + +int expo_set_display(struct expo *exp, struct udevice *dev) +{ + exp->display = dev; + + return 0; +} + +void exp_set_text_mode(struct expo *exp, bool text_mode) +{ + exp->text_mode = text_mode; +} + +struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id) +{ + struct scene *scn; + + list_for_each_entry(scn, &exp->scene_head, sibling) { + if (scn->id == scene_id) + return scn; + } + + return NULL; +} + +int expo_set_scene_id(struct expo *exp, uint scene_id) +{ + if (!expo_lookup_scene_id(exp, scene_id)) + return log_msg_ret("id", -ENOENT); + exp->scene_id = scene_id; + + return 0; +} + +int expo_render(struct expo *exp) +{ + struct udevice *dev = exp->display; + struct video_priv *vid_priv = dev_get_uclass_priv(dev); + struct scene *scn = NULL; + u32 colour; + int ret; + + colour = video_index_to_colour(vid_priv, VID_WHITE); + ret = video_fill(dev, colour); + if (ret) + return log_msg_ret("fill", ret); + + if (exp->scene_id) { + scn = expo_lookup_scene_id(exp, exp->scene_id); + if (!scn) + return log_msg_ret("scn", -ENOENT); + + ret = scene_render(scn); + if (ret) + return log_msg_ret("ren", ret); + } + + video_sync(dev, true); + + return scn ? 0 : -ECHILD; +} + +int expo_send_key(struct expo *exp, int key) +{ + struct scene *scn = NULL; + + if (exp->scene_id) { + int ret; + + scn = expo_lookup_scene_id(exp, exp->scene_id); + if (!scn) + return log_msg_ret("scn", -ENOENT); + + ret = scene_send_key(scn, key, &exp->action); + if (ret) + return log_msg_ret("key", ret); + } + + return scn ? 0 : -ECHILD; +} + +int expo_action_get(struct expo *exp, struct expo_action *act) +{ + *act = exp->action; + exp->action.type = EXPOACT_NONE; + + return act->type == EXPOACT_NONE ? -EAGAIN : 0; +} |