diff options
Diffstat (limited to 'boot/cedit.c')
-rw-r--r-- | boot/cedit.c | 163 |
1 files changed, 163 insertions, 0 deletions
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 <sjg@chromium.org> + */ + +#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; +} |