]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - boot/bootflow_menu.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * Provide a menu of available bootflows and related options
5 * Copyright 2022 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
9 #define LOG_CATEGORY UCLASS_BOOTSTD
19 #include <video_console.h>
21 #include <linux/delay.h>
22 #include "bootflow_internal.h"
25 * struct menu_priv - information about the menu
27 * @num_bootflows: Number of bootflows in the menu
33 int bootflow_menu_new(struct expo
**expp
)
35 struct udevice
*last_bootdev
;
36 struct scene_obj_menu
*menu
;
37 struct menu_priv
*priv
;
38 struct bootflow
*bflow
;
44 priv
= calloc(1, sizeof(*priv
));
46 return log_msg_ret("prv", -ENOMEM
);
48 ret
= expo_new("bootflows", priv
, &exp
);
50 return log_msg_ret("exp", ret
);
52 ret
= scene_new(exp
, "main", MAIN
, &scn
);
54 return log_msg_ret("scn", ret
);
56 ret
|= scene_txt_str(scn
, "prompt", OBJ_PROMPT
, STR_PROMPT
,
57 "UP and DOWN to choose, ENTER to select", NULL
);
59 ret
= scene_menu(scn
, "main", OBJ_MENU
, &menu
);
60 ret
|= scene_obj_set_pos(scn
, OBJ_MENU
, MARGIN_LEFT
, 100);
61 ret
|= scene_txt_str(scn
, "title", OBJ_MENU_TITLE
, STR_MENU_TITLE
,
62 "U-Boot - Boot Menu", NULL
);
63 ret
|= scene_menu_set_title(scn
, OBJ_MENU
, OBJ_PROMPT
);
65 logo
= video_get_u_boot_logo();
67 ret
|= scene_img(scn
, "ulogo", OBJ_U_BOOT_LOGO
, logo
, NULL
);
68 ret
|= scene_obj_set_pos(scn
, OBJ_U_BOOT_LOGO
, -4, 4);
71 ret
|= scene_txt_str(scn
, "cur_item", OBJ_POINTER
, STR_POINTER
, ">",
73 ret
|= scene_menu_set_pointer(scn
, OBJ_MENU
, OBJ_POINTER
);
75 return log_msg_ret("new", -EINVAL
);
78 for (ret
= bootflow_first_glob(&bflow
), i
= 0; !ret
&& i
< 36;
79 ret
= bootflow_next_glob(&bflow
), i
++) {
80 char str
[2], *label
, *key
;
84 if (bflow
->state
!= BOOTFLOWST_READY
)
87 *str
= i
< 10 ? '0' + i
: 'A' + i
- 10;
91 return log_msg_ret("key", -ENOMEM
);
92 label
= strdup(dev_get_parent(bflow
->dev
)->name
);
95 return log_msg_ret("nam", -ENOMEM
);
98 add_gap
= last_bootdev
!= bflow
->dev
;
99 last_bootdev
= bflow
->dev
;
101 ret
= expo_str(exp
, "prompt", STR_POINTER
, ">");
102 ret
|= scene_txt_str(scn
, "label", ITEM_LABEL
+ i
,
103 STR_LABEL
+ i
, label
, NULL
);
104 ret
|= scene_txt_str(scn
, "desc", ITEM_DESC
+ i
, STR_DESC
+ i
,
105 bflow
->os_name
? bflow
->os_name
:
107 ret
|= scene_txt_str(scn
, "key", ITEM_KEY
+ i
, STR_KEY
+ i
, key
,
111 preview_id
= ITEM_PREVIEW
+ i
;
112 ret
|= scene_img(scn
, "preview", preview_id
,
115 ret
|= scene_menuitem(scn
, OBJ_MENU
, "item", ITEM
+ i
,
116 ITEM_KEY
+ i
, ITEM_LABEL
+ i
,
117 ITEM_DESC
+ i
, preview_id
,
118 add_gap
? SCENEMIF_GAP_BEFORE
: 0,
122 return log_msg_ret("itm", -EINVAL
);
124 priv
->num_bootflows
++;
127 ret
= scene_arrange(scn
);
129 return log_msg_ret("arr", ret
);
136 int bootflow_menu_apply_theme(struct expo
*exp
, ofnode node
)
138 struct menu_priv
*priv
= exp
->priv
;
143 log_debug("Applying theme %s\n", ofnode_get_name(node
));
144 scn
= expo_lookup_scene_id(exp
, MAIN
);
146 return log_msg_ret("scn", -ENOENT
);
148 /* Avoid error-checking optional items */
149 if (!ofnode_read_u32(node
, "font-size", &font_size
)) {
152 log_debug("font size %d\n", font_size
);
153 scene_txt_set_font(scn
, OBJ_PROMPT
, NULL
, font_size
);
154 scene_txt_set_font(scn
, OBJ_POINTER
, NULL
, font_size
);
155 for (i
= 0; i
< priv
->num_bootflows
; i
++) {
156 ret
= scene_txt_set_font(scn
, ITEM_DESC
+ i
, NULL
,
159 return log_msg_ret("des", ret
);
160 scene_txt_set_font(scn
, ITEM_KEY
+ i
, NULL
, font_size
);
161 scene_txt_set_font(scn
, ITEM_LABEL
+ i
, NULL
,
166 ret
= scene_arrange(scn
);
168 return log_msg_ret("arr", ret
);
173 int bootflow_menu_run(struct bootstd_priv
*std
, bool text_mode
,
174 struct bootflow
**bflowp
)
176 struct cli_ch_state s_cch
, *cch
= &s_cch
;
177 struct bootflow
*sel_bflow
;
189 ret
= bootflow_menu_new(&exp
);
191 return log_msg_ret("exp", ret
);
193 if (ofnode_valid(std
->theme
)) {
194 ret
= bootflow_menu_apply_theme(exp
, std
->theme
);
196 return log_msg_ret("thm", ret
);
199 /* For now we only support a video console */
200 ret
= uclass_first_device_err(UCLASS_VIDEO
, &dev
);
202 return log_msg_ret("vid", ret
);
203 ret
= expo_set_display(exp
, dev
);
205 return log_msg_ret("dis", ret
);
207 ret
= expo_set_scene_id(exp
, MAIN
);
209 return log_msg_ret("scn", ret
);
212 expo_set_text_mode(exp
, text_mode
);
216 struct expo_action act
;
219 ret
= expo_render(exp
);
223 ichar
= cli_ch_process(cch
, 0);
225 while (!ichar
&& !tstc()) {
228 ichar
= cli_ch_process(cch
, -ETIMEDOUT
);
232 ichar
= cli_ch_process(cch
, ichar
);
238 key
= bootmenu_conv_key(ichar
);
239 if (key
== BKEY_NONE
)
245 ret
= expo_send_key(exp
, key
);
249 ret
= expo_action_get(exp
, &act
);
253 sel_id
= act
.select
.id
;
266 return log_msg_ret("end", ret
);
269 struct bootflow
*bflow
;
272 for (ret
= bootflow_first_glob(&bflow
), i
= 0; !ret
&& i
< 36;
273 ret
= bootflow_next_glob(&bflow
), i
++) {
274 if (i
== sel_id
- ITEM
) {