summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/Kconfig14
-rw-r--r--boot/Makefile1
-rw-r--r--boot/cedit.c163
-rw-r--r--boot/expo_build.c3
-rw-r--r--boot/scene.c12
-rw-r--r--boot/scene_internal.h8
6 files changed, 200 insertions, 1 deletions
diff --git a/boot/Kconfig b/boot/Kconfig
index a643a3d1286..c8b8f36d835 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -1630,4 +1630,18 @@ config SAVE_PREV_BL_INITRAMFS_START_ADDR
If no initramfs was provided by previous bootloader, no env variables
will be created.
+menu "Configuration editor"
+
+config CEDIT
+ bool "Configuration editor"
+ depends on BOOTSTD
+ help
+ Provides a way to deal with board configuration and present it to
+ the user for adjustment.
+
+ This is intended to provide both graphical and text-based user
+ interfaces, but only graphical is support at present.
+
+endmenu # Configuration editor
+
endmenu # Booting
diff --git a/boot/Makefile b/boot/Makefile
index 28c4e55ca65..f828f870a37 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -33,6 +33,7 @@ ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL
obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o
obj-$(CONFIG_$(SPL_TPL_)EXPO) += bootflow_menu.o
obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow_menu.o
+obj-$(CONFIG_$(SPL_TPL_)CEDIT) += cedit.o
endif
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
diff --git a/boot/cedit.c b/boot/cedit.c
new file mode 100644
index 00000000000..ee24658917b
--- /dev/null
+++ b/boot/cedit.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Implementation of configuration editor
+ *
+ * Copyright 2023 Google LLC
+ * Written by Simon Glass <[email protected]>
+ */
+
+#include <common.h>
+#include <cli.h>
+#include <dm.h>
+#include <expo.h>
+#include <menu.h>
+#include <video.h>
+#include <linux/delay.h>
+#include "scene_internal.h"
+
+int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
+{
+ struct scene_obj_txt *txt;
+ struct scene_obj *obj;
+ struct scene *scn;
+ int y;
+
+ scn = expo_lookup_scene_id(exp, scene_id);
+ if (!scn)
+ return log_msg_ret("scn", -ENOENT);
+
+ txt = scene_obj_find_by_name(scn, "prompt");
+ if (txt)
+ scene_obj_set_pos(scn, txt->obj.id, 0, vpriv->ysize - 50);
+
+ txt = scene_obj_find_by_name(scn, "title");
+ if (txt)
+ scene_obj_set_pos(scn, txt->obj.id, 200, 10);
+
+ y = 100;
+ list_for_each_entry(obj, &scn->obj_head, sibling) {
+ if (obj->type == SCENEOBJT_MENU) {
+ scene_obj_set_pos(scn, obj->id, 50, y);
+ scene_menu_arrange(scn, (struct scene_obj_menu *)obj);
+ y += 50;
+ }
+ }
+
+ return 0;
+}
+
+int cedit_run(struct expo *exp)
+{
+ struct cli_ch_state s_cch, *cch = &s_cch;
+ struct video_priv *vid_priv;
+ uint scene_id;
+ struct udevice *dev;
+ struct scene *scn;
+ bool done;
+ int ret;
+
+ cli_ch_init(cch);
+
+ /* For now we only support a video console */
+ ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
+ if (ret)
+ return log_msg_ret("vid", ret);
+ ret = expo_set_display(exp, dev);
+ if (ret)
+ return log_msg_ret("dis", ret);
+
+ ret = expo_first_scene_id(exp);
+ if (ret < 0)
+ return log_msg_ret("scn", ret);
+ scene_id = ret;
+
+ ret = expo_set_scene_id(exp, scene_id);
+ if (ret)
+ return log_msg_ret("sid", ret);
+
+ exp->popup = true;
+
+ /* This is not supported for now */
+ if (0)
+ expo_set_text_mode(exp, true);
+
+ vid_priv = dev_get_uclass_priv(dev);
+
+ scn = expo_lookup_scene_id(exp, scene_id);
+ scene_highlight_first(scn);
+
+ cedit_arange(exp, vid_priv, scene_id);
+
+ ret = expo_calc_dims(exp);
+ if (ret)
+ return log_msg_ret("dim", ret);
+
+ done = false;
+ do {
+ struct expo_action act;
+ int ichar, key;
+
+ ret = expo_render(exp);
+ if (ret)
+ break;
+
+ ichar = cli_ch_process(cch, 0);
+ if (!ichar) {
+ while (!ichar && !tstc()) {
+ schedule();
+ mdelay(2);
+ ichar = cli_ch_process(cch, -ETIMEDOUT);
+ }
+ if (!ichar) {
+ ichar = getchar();
+ ichar = cli_ch_process(cch, ichar);
+ }
+ }
+
+ key = 0;
+ if (ichar) {
+ key = bootmenu_conv_key(ichar);
+ if (key == BKEY_NONE)
+ key = ichar;
+ }
+ if (!key)
+ continue;
+
+ ret = expo_send_key(exp, key);
+ if (ret)
+ break;
+
+ ret = expo_action_get(exp, &act);
+ if (!ret) {
+ switch (act.type) {
+ case EXPOACT_POINT_OBJ:
+ scene_set_highlight_id(scn, act.select.id);
+ cedit_arange(exp, vid_priv, scene_id);
+ break;
+ case EXPOACT_OPEN:
+ scene_set_open(scn, act.select.id, true);
+ cedit_arange(exp, vid_priv, scene_id);
+ break;
+ case EXPOACT_CLOSE:
+ scene_set_open(scn, act.select.id, false);
+ cedit_arange(exp, vid_priv, scene_id);
+ break;
+ case EXPOACT_SELECT:
+ scene_set_open(scn, scn->highlight_id, false);
+ cedit_arange(exp, vid_priv, scene_id);
+ break;
+ case EXPOACT_QUIT:
+ log_debug("quitting\n");
+ done = true;
+ break;
+ default:
+ break;
+ }
+ }
+ } while (!done);
+
+ if (ret)
+ return log_msg_ret("end", ret);
+
+ return 0;
+}
diff --git a/boot/expo_build.c b/boot/expo_build.c
index 7e61ab06a8d..22f62eb54bc 100644
--- a/boot/expo_build.c
+++ b/boot/expo_build.c
@@ -376,7 +376,8 @@ int expo_build(ofnode root, struct expo **expp)
ret = read_strings(&info, root);
if (ret)
return log_msg_ret("str", ret);
- list_strings(&info);
+ if (_DEBUG)
+ list_strings(&info);
ret = expo_new("name", NULL, &exp);
if (ret)
diff --git a/boot/scene.c b/boot/scene.c
index 6fbc1fc578c..e52333371f9 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -92,6 +92,18 @@ void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type)
return NULL;
}
+void *scene_obj_find_by_name(struct scene *scn, const char *name)
+{
+ struct scene_obj *obj;
+
+ list_for_each_entry(obj, &scn->obj_head, sibling) {
+ if (!strcmp(name, obj->name))
+ return obj;
+ }
+
+ return NULL;
+}
+
int scene_obj_add(struct scene *scn, const char *name, uint id,
enum scene_obj_t type, uint size, struct scene_obj **objp)
{
diff --git a/boot/scene_internal.h b/boot/scene_internal.h
index dc98ecd0214..fb1ea5533b9 100644
--- a/boot/scene_internal.h
+++ b/boot/scene_internal.h
@@ -41,6 +41,14 @@ uint resolve_id(struct expo *exp, uint id);
void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type);
/**
+ * scene_obj_find_by_name() - Find an object in a scene by name
+ *
+ * @scn: Scene to search
+ * @name: Name to search for
+ */
+void *scene_obj_find_by_name(struct scene *scn, const char *name);
+
+/**
* scene_obj_add() - Add a new object to a scene
*
* @scn: Scene to update