Merge https://source.denx.de/u-boot/custodians/u-boot-riscv
[platform/kernel/u-boot.git] / boot / cedit.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Implementation of configuration editor
4  *
5  * Copyright 2023 Google LLC
6  * Written by Simon Glass <sjg@chromium.org>
7  */
8
9 #include <common.h>
10 #include <cli.h>
11 #include <dm.h>
12 #include <expo.h>
13 #include <menu.h>
14 #include <video.h>
15 #include <linux/delay.h>
16 #include "scene_internal.h"
17
18 int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
19 {
20         struct scene_obj_txt *txt;
21         struct scene_obj *obj;
22         struct scene *scn;
23         int y;
24
25         scn = expo_lookup_scene_id(exp, scene_id);
26         if (!scn)
27                 return log_msg_ret("scn", -ENOENT);
28
29         txt = scene_obj_find_by_name(scn, "prompt");
30         if (txt)
31                 scene_obj_set_pos(scn, txt->obj.id, 0, vpriv->ysize - 50);
32
33         txt = scene_obj_find_by_name(scn, "title");
34         if (txt)
35                 scene_obj_set_pos(scn, txt->obj.id, 200, 10);
36
37         y = 100;
38         list_for_each_entry(obj, &scn->obj_head, sibling) {
39                 if (obj->type == SCENEOBJT_MENU) {
40                         scene_obj_set_pos(scn, obj->id, 50, y);
41                         scene_menu_arrange(scn, (struct scene_obj_menu *)obj);
42                         y += 50;
43                 }
44         }
45
46         return 0;
47 }
48
49 int cedit_run(struct expo *exp)
50 {
51         struct cli_ch_state s_cch, *cch = &s_cch;
52         struct video_priv *vid_priv;
53         uint scene_id;
54         struct udevice *dev;
55         struct scene *scn;
56         bool done;
57         int ret;
58
59         cli_ch_init(cch);
60
61         /* For now we only support a video console */
62         ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
63         if (ret)
64                 return log_msg_ret("vid", ret);
65         ret = expo_set_display(exp, dev);
66         if (ret)
67                 return log_msg_ret("dis", ret);
68
69         ret = expo_first_scene_id(exp);
70         if (ret < 0)
71                 return log_msg_ret("scn", ret);
72         scene_id = ret;
73
74         ret = expo_set_scene_id(exp, scene_id);
75         if (ret)
76                 return log_msg_ret("sid", ret);
77
78         exp->popup = true;
79
80         /* This is not supported for now */
81         if (0)
82                 expo_set_text_mode(exp, true);
83
84         vid_priv = dev_get_uclass_priv(dev);
85
86         scn = expo_lookup_scene_id(exp, scene_id);
87         scene_highlight_first(scn);
88
89         cedit_arange(exp, vid_priv, scene_id);
90
91         ret = expo_calc_dims(exp);
92         if (ret)
93                 return log_msg_ret("dim", ret);
94
95         done = false;
96         do {
97                 struct expo_action act;
98                 int ichar, key;
99
100                 ret = expo_render(exp);
101                 if (ret)
102                         break;
103
104                 ichar = cli_ch_process(cch, 0);
105                 if (!ichar) {
106                         while (!ichar && !tstc()) {
107                                 schedule();
108                                 mdelay(2);
109                                 ichar = cli_ch_process(cch, -ETIMEDOUT);
110                         }
111                         if (!ichar) {
112                                 ichar = getchar();
113                                 ichar = cli_ch_process(cch, ichar);
114                         }
115                 }
116
117                 key = 0;
118                 if (ichar) {
119                         key = bootmenu_conv_key(ichar);
120                         if (key == BKEY_NONE)
121                                 key = ichar;
122                 }
123                 if (!key)
124                         continue;
125
126                 ret = expo_send_key(exp, key);
127                 if (ret)
128                         break;
129
130                 ret = expo_action_get(exp, &act);
131                 if (!ret) {
132                         switch (act.type) {
133                         case EXPOACT_POINT_OBJ:
134                                 scene_set_highlight_id(scn, act.select.id);
135                                 cedit_arange(exp, vid_priv, scene_id);
136                                 break;
137                         case EXPOACT_OPEN:
138                                 scene_set_open(scn, act.select.id, true);
139                                 cedit_arange(exp, vid_priv, scene_id);
140                                 break;
141                         case EXPOACT_CLOSE:
142                                 scene_set_open(scn, act.select.id, false);
143                                 cedit_arange(exp, vid_priv, scene_id);
144                                 break;
145                         case EXPOACT_SELECT:
146                                 scene_set_open(scn, scn->highlight_id, false);
147                                 cedit_arange(exp, vid_priv, scene_id);
148                                 break;
149                         case EXPOACT_QUIT:
150                                 log_debug("quitting\n");
151                                 done = true;
152                                 break;
153                         default:
154                                 break;
155                         }
156                 }
157         } while (!done);
158
159         if (ret)
160                 return log_msg_ret("end", ret);
161
162         return 0;
163 }