blob: 32dd7f0903075f54fe72b2ee4603e3a2f766c986 [file] [log] [blame]
Simon Glassb5c8fea2023-01-06 08:52:43 -06001.. SPDX-License-Identifier: GPL-2.0+
2
3Expo menu
4=========
5
6U-Boot provides a menu implementation for use with selecting bootflows and
7changing U-Boot settings. This is in early stages of development.
8
9Motivation
10----------
11
12U-Boot already has a text-based menu system accessed via the
13:doc:`../usage/cmd/bootmenu`. This works using environment variables, or via
14some EFI-specific hacks.
15
16The command makes use of a lower-level `menu` implementation, which is quite
17flexible and can be used to make menu hierarchies.
18
19However this system is not flexible enough for use with standard boot. It does
20not support a graphical user interface and cannot currently support anything
21more than a very simple list of items. While it does support multiple menus in
22hierarchies, these are implemented by the caller. See for example `eficonfig.c`.
23
24Another challenge with the current menu implementation is that it controls
25the event loop, such that bootmenu_loop() does not return until a key is
26pressed. This makes it difficult to implement dynamic displays or to do other
27things while the menu is running, such as searching for more bootflows.
28
29For these reasons an attempt has been made to develop a more flexible system
30which can handle menus as well as other elements. This is called 'expo', short
31for exposition, in an attempt to avoid common words like display, screen, menu
32and the like. The primary goal is to support Verified Boot for Embedded (VBE),
33although it is available to any boot method, using the 'bootflow menu' command.
34
35Efforts have been made to use common code with the existing menu, including
36key processing in particular.
37
38Previous work looked at integrating Nuklear into U-Boot. This works fine and
39could provide a way to provide a more flexible UI, perhaps with expo dealing
40with the interface to Nuklear. But this is quite a big step and it may be years
41before this becomes desirable, if at all. For now, U-Boot only needs a fairly
42simple set of menus and options, so rendering them directly is fairly
43straightforward.
44
45Concepts
46--------
47
48The creator of the expo is here called a `controller` and it controls most
49aspects of the expo. This is the code that you must write to use expo.
50
51An `expo` is a set of scenes which can be presented to the user one at a time,
52to show information and obtain input from the user.
53
54A `scene` is a collection of objects which are displayed together on the screen.
55Only one scene is visible at a time and scenes do not share objects.
56
57A `scene object` is something that appears in the scene, such as some text, an
58image or a menu. Objects can be positioned and hidden.
59
60A `menu object` contains a title, a set of `menu items` and a pointer to the
61current item. Menu items consist of a keypress (indicating what to press to
62select the item), label and description. All three are shown in a single line
63within the menu. Items can also have a preview image, which is shown when the
64item is highlighted.
65
66All components have a name. This is purely for debugging, so it is easy to see
67what object is referred to. Of course the ID numbers can help as well, but they
68are less easy to distinguish.
69
70While the expo implementation provides support for handling keypresses and
71rendering on the display or serial port, it does not actually deal with reading
72input from the user, nor what should be done when a particular menu item is
73selected. This is deliberate since having the event loop outside the expo is
74more flexible, particularly in a single-threaded environment like U-Boot.
75
76Everything within an expo has a unique ID number. This is done so that it is
77easy to refer to things after the expo has been created. The expectation is that
78the controller declares an enum containing all of the elements in the expo,
79passing the ID of each object as it is created. When a menu item is selected,
80its ID is returned. When a object's font or position needs to change, the ID is
81passed to expo functions to indicate which object it is. It is possible for expo
82to auto-allocate IDs, but this is not recommended. The use of IDs is a
83convenience, removing the need for the controller to store pointers to objects,
84or even the IDs of objects. Programmatic creation of many items in a loop can be
85handled by allocating space in the enum for a maximum number of items, then
86adding the loop count to the enum values to obtain unique IDs.
87
88All text strings are stored in a structure attached to the expo, referenced by
89a text ID. This makes it easier at some point to implement multiple languages or
90to support Unicode strings.
91
92Menu objects do not have their own text and image objects. Instead they simply
93refer to objects which have been created. So a menu item is just a collection
94of IDs of text and image objects. When adding a menu item you must create these
95objects first, then create the menu item, passing in the relevant IDs.
96
97Creating an expo
98----------------
99
100To create an expo, use `expo_new()` followed by `scene_new()` to create a scene.
101Then add objects to the scene, using functions like `scene_txt_str()` and
102`scene_menu()`. For every menu item, add text and image objects, then create
103the menu item with `scene_menuitem()`, referring to those objects.
104
105Layout
106------
107
108Individual objects can be positioned using `scene_obj_set_pos()`. Menu items
109cannot be positioned manually: this is done by `scene_arrange()` which is called
110automatically when something changes. The menu itself determines the position of
111its items.
112
113Rendering
114---------
115
116Rendering is performed by calling `expo_render()`. This uses either the
117vidconsole, if present, or the serial console in `text mode`. Expo handles
118presentation automatically in either case, without any change in how the expo is
119created.
120
121For the vidconsole, Truetype fonts can be used if enabled, to enhance the
122quality of the display. For text mode, each menu item is shown in a single line,
123allowing easy selection using arrow keys.
124
125Input
126-----
127
128The controller is responsible for collecting keyboard input. A good way to do
129this is to use `cli_ch_process()`, since it handles conversion of escape
130sequences into keys. However, expo has some special menu-key codes for
131navigating the interface. These are defined in `enum bootmenu_key` and include
132`BKEY_UP` for moving up and `BKEY_SELECT` for selecting an item. You can use
133`bootmenu_conv_key()` to convert an ASCII key into one of these.
134
135Once a keypress is decoded, call `expo_send_key()` to send it to the expo. This
136may cause an update to the expo state and may produce an action.
137
138Actions
139-------
140
141Call `expo_action_get()` in the event loop to check for any actions that the
142expo wants to report. These can include selecting a particular menu item, or
143quitting the menu. Processing of these is the responsibility of your controller.
144
145Event loop
146----------
147
148Expo is intended to be used in an event loop. For an example loop, see
149`bootflow_menu_run()`. It is possible to perform other work in your event loop,
150such as scanning devices for more bootflows.
151
152Themes
153------
154
155Expo does not itself support themes. The bootflow_menu implement supposed a
156basic theme, applying font sizes to the various text objects in the expo.
157
158API documentation
159-----------------
160
161.. kernel-doc:: include/expo.h
162
163Future ideas
164------------
165
166Some ideas for future work:
167
168- Default menu item and a timeout
169- Higher-level / automatic / more flexible layout of objects
170- Image formats other than BMP
171- Use of ANSI sequences to control a serial terminal
172- Colour selection
173- Better support for handling lots of settings, e.g. with multiple menus and
174 radio/option widgets
175- Mouse support
176- Integrate Nuklear, NxWidgets or some other library for a richer UI
177- Optimise rendering by only updating the display with changes since last render
178- Use expo to replace the existing menu implementation
179- Add a Kconfig option to drop the names to save code / data space
180- Add a Kconfig option to disable vidconsole support to save code / data space
181- Support both graphical and text menus at the same time on different devices
182- Implement proper measurement of object bounding boxes, to permit more exact
183 layout. This would tidy up the layout when Truetype is not used
184- Support unicode
185- Support curses for proper serial-terminal menus
186
187.. Simon Glass <sjg@chromium.org>
188.. 7-Oct-22