diff options
| author | Tom Rini <[email protected]> | 2023-08-25 17:52:59 -0400 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2023-08-25 17:52:59 -0400 |
| commit | 05763b71d2fcfe9729bf5ef0b14bd00c3af0c985 (patch) | |
| tree | 8a62bb1cda41f5fb2ff2cb0211e927e45645e18a /doc | |
| parent | 7c6b18fb5494a1da2421b16c42d31fc466c38362 (diff) | |
| parent | 84b08afcbb8f8b4402b940d87bf5822984eedb3d (diff) | |
Merge branch '2023-08-25-add-persistent-config-editor-via-expo' into next
To quote the author:
So far cedit does not support reading and writing the configuration.
This series add several features related to this:
First, it adds support for using a file on a filesystem. This is in
FDT format and provides enough information to reset the cedit back to
the saved settings.
Second, it adds support for using the U-Boot environment. Since the
environment is generally saved across reboots, this feature provides an
easy way of storing the state on most boards. The variables all have a
'c.' prefix to avoid confusion with other variables.
Finally it adds support for using CMOS RAM. This is commonly used on x86
devices to store BIOS settings. The expo schema provides information on
the register layout.
Some other minor tweaks and improvements are included along the way.
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/develop/cedit.rst | 169 | ||||
| -rw-r--r-- | doc/develop/expo.rst | 48 | ||||
| -rw-r--r-- | doc/develop/index.rst | 1 | ||||
| -rw-r--r-- | doc/usage/cmd/cedit.rst | 117 |
4 files changed, 321 insertions, 14 deletions
diff --git a/doc/develop/cedit.rst b/doc/develop/cedit.rst new file mode 100644 index 00000000000..63dff9d3f14 --- /dev/null +++ b/doc/develop/cedit.rst @@ -0,0 +1,169 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Configuration Editor +==================== + +Introduction +------------ + +U-Boot provides a configuration editor which allows settings to be changed in +a GUI or text environment. + + +This feature is still in development and has a number of limitations. For +example, cedit only supports menu items (there is no numeric or text entry), +provides no support for colour text and does not support scrolling. Still it is +possible to use it for simple applications. + + +Overview +-------- + +The configuration editor makes use of :doc:`expo` to build a description of the +configuration screens and allow user to interact with it. + +To create a single-scene cedit for your application: + +#. Design the scene, i.e. the objects that need to be present and what their + possible values are + +#. Enter this in .dts format + +#. Create a header file containing the IDs + +#. Run the 'expo.py' tool to generate a .dtb file containing the layout, which + can be used by U-Boot + +#. Use the :doc:`../usage/cmd/cedit` to create the cedit, read the settings, + present the cedit to the user and save the settings afterwards. + +Each of these is described in a separate section. See :ref:`expo_example` for +an example file. + + +Design a scene +-------------- + +Using a piece of paper or a drawing tool, lay out the objects you want in your +scene. Typically you will use the default layout engine, which simply puts items +one after the other from top to bottom. So use a single column and show the +prompt and value for each object. + +For menu items, show one of the values, but keep in mind what else you need. + + +Create an expo-format file +-------------------------- + +The description is in the form of a devicetree file, as documented at +:ref:`expo_format`. Since everything in an expo has an ID number (an integer +greater than 1) the description is written terms of these IDs. They each have +an enum value. which is typically taken care of by the `expo.py` tool. + +The expo should have a `scenes` node with a named scene as a subnode. Within the +scene, add properties for the scene, then a subnode for each object in the +scene. + +All object nodes require an `id` value and a `type` property. Other properties +depend on the type. For example, a menu has a `title` and an `item-label` list +proving the text for the menu items, as well as an `item-id` list providing the +ID of each menu item, so it can be selected. + +Text properties may have two variants. For example `title` specifies the title +of a menu, but you can instead use `title-id` to specify the string ID to use as +the title. String are defined in a separate area, common to the whole expo, +which contains a subnode for each string. Within that subnode are the ID and the +`value` (i.e. the text). For now only English is supported, but in future it may +be possible to append a language identifier to provide other values (e.g. +'value-es' for Spanish). + + +Create an ID header-file +------------------------ + +Expo needs to know the integer value to use for every ID referenced in your +expo-format file. For example, if you have defined a `cpu-speed` node with an +id of `ID_CPU_SPEED`, then Expo needs to know the value of `ID_CPU_SPEED`. + +When you write C code to use the expo, you may need to know the IDs. For +example, to find which value the user selected in `cpu-speed` menu, you must +use the `ID_CPU_SPEED` ID. The ID is the only way to refer to anything in Expo. + +Since we need a shared set of IDs, it is best to have a header file containing +them. Expo supports doing this with an enum, where every ID is listed in the +enum:: + + enum { + ZERO, + + ID_PROMPT, + + ID_SCENE1, + ID_SCENE1_TITLE, + ... + }; + +The C compiler can parse this directly. The `expo.py` tool parses it for expo. + +Create a header file containing every ID mentioned in your expo. Try to group +related things together. + + +Build the expo layout +--------------------- + +Use the `expo.py` tool to build a .dtb for your expo:: + + ./tools/expo.py -e expo_ids.h -l expo_layout.dts -o expo.dtb + +This uses the enum in the provided header file to get the ID numbers, grabs +the `.dts` file, inserts the ID numbers and then uses the devicetree compiler to +build a `.dtb` file. + +If you get an error:: + + Devicetree compiler error: + Error: <stdin>:9.19-20 syntax error + FATAL ERROR: Unable to parse input tree + +that means that something is wrong with your syntax, or perhaps you have an ID +in the `.dts` file that is not mentioned in your enum. Check both files and try +again. + + +Use the command interface +------------------------- + +See the :doc:`../usage/cmd/cedit` command for information on available commands. +Typically you will use `cedit load` to load the `.dtb` file and `cedit run` to +let the user interact with it. + + +Multiple scenes +--------------- + +Expo supports multiple scenes but has no pre-determined way of moving between +them. You could use selection of a menu item as a signal to change the scene, +but this is not currently implemented in the cedit code (see `cedit_run()`). + + +Themes +------ + +The configuration editor uses simple expo themes. The theme is read from +`/bootstd/cedit-theme` in the devicetree. + + +Reading and writing settings +---------------------------- + +Cedit provides several options for persistent settings: + +- Writing an FDT file to a filesystem +- Writing to U-Boot's environment variables, which are then typically stored in + a persistent manner +- Writing to CMOS RAM registers (common on x86 machines) + +For now, reading and writing settings is not automatic. See the +:doc:`../usage/cmd/cedit` for how to do this on the command line or in a +script. diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index 2ac4af232da..f13761995d3 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -317,6 +317,18 @@ id Specifies the ID of the object. This is used when referring to the object. +Where CMOS RAM is used for reading and writing settings, the following +additional properties are required: + +start-bit + Specifies the first bit in the CMOS RAM to use for this setting. For a RAM + with 0x100 bytes, there are 0x800 bit locations. For example, register 0x80 + holds bits 0x400 to 0x407. + +bit-length + Specifies the number of CMOS RAM bits to use for this setting. The bits + extend from `start-bit` to `start-bit + bit-length - 1`. Note that the bits + must be contiguous. Menu nodes have the following additional properties: @@ -358,6 +370,9 @@ The `expo_arrange()` function can be called to arrange the expo objects in a suitable manner. For each scene it puts the title at the top, the prompt at the bottom and the objects in order from top to bottom. + +.. _expo_example: + Expo format example ~~~~~~~~~~~~~~~~~~~ @@ -367,22 +382,27 @@ strings are provided inline in the nodes where they are used. :: - #define ID_PROMPT 1 - #define ID_SCENE1 2 - #define ID_SCENE1_TITLE 3 + /* this comment is parsed by the expo.py tool to insert the values below + + enum { + ZERO, + ID_PROMPT, + ID_SCENE1, + ID_SCENE1_TITLE, - #define ID_CPU_SPEED 4 - #define ID_CPU_SPEED_TITLE 5 - #define ID_CPU_SPEED_1 6 - #define ID_CPU_SPEED_2 7 - #define ID_CPU_SPEED_3 8 + ID_CPU_SPEED, + ID_CPU_SPEED_TITLE, + ID_CPU_SPEED_1, + ID_CPU_SPEED_2, + ID_CPU_SPEED_3, - #define ID_POWER_LOSS 9 - #define ID_AC_OFF 10 - #define ID_AC_ON 11 - #define ID_AC_MEMORY 12 + ID_POWER_LOSS, + ID_AC_OFF, + ID_AC_ON, + ID_AC_MEMORY, - #define ID_DYNAMIC_START 13 + ID_DYNAMIC_START, + */ &cedit { dynamic-start = <ID_DYNAMIC_START>; @@ -465,7 +485,7 @@ Some ideas for future work: - Support unicode - Support curses for proper serial-terminal menus - Add support for large menus which need to scroll -- Add support for reading and writing configuration settings with cedit +- Update expo.py tool to check for overlapping names and CMOS locations .. Simon Glass <[email protected]> .. 7-Oct-22 diff --git a/doc/develop/index.rst b/doc/develop/index.rst index 5b230d0321f..0d12484ace8 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -38,6 +38,7 @@ Implementation driver-model/index environment expo + cedit event global_data logging diff --git a/doc/usage/cmd/cedit.rst b/doc/usage/cmd/cedit.rst index 8e1110c7c77..f415b48699e 100644 --- a/doc/usage/cmd/cedit.rst +++ b/doc/usage/cmd/cedit.rst @@ -10,6 +10,11 @@ Synopis cedit load <interface> <dev[:part]> <filename> cedit run + cedit write_fdt <dev[:part]> <filename> + cedit read_fdt <dev[:part]> <filename> + cedit write_env [-v] + cedit read_env [-v] + cedit write_cmos [-v] [dev] Description ----------- @@ -22,6 +27,69 @@ It makes use of the expo subsystem. The description is in the form of a devicetree file, as documented at :ref:`expo_format`. +See :doc:`../../develop/cedit` for information about the configuration editor. + +cedit load +~~~~~~~~~~ + +Loads a configuration-editor description from a file. It creates a new cedit +structure ready for use. Initially no settings are read, so default values are +used for each object. + +cedit run +~~~~~~~~~ + +Runs the default configuration-editor event loop. This is very simple, just +accepting character input and moving through the objects under user control. +The implementation is at `cedit_run()`. + +cedit write_fdt +~~~~~~~~~~~~~~~ + +Writes the current user settings to a devicetree file. For each menu item the +selected ID and its text string are written. + +cedit read_fdt +~~~~~~~~~~~~~~ + +Reads the user settings from a devicetree file and updates the cedit with those +settings. + +cedit read_env +~~~~~~~~~~~~~~ + +Reads the settings from the environment variables. For each menu item `<name>`, +cedit looks for a variable called `c.<name>` with the ID of the selected menu +item. + +The `-v` flag enables verbose mode, where each variable is printed after it is +read. + +cedit write_env +~~~~~~~~~~~~~~~ + +Writes the settings to environment variables. For each menu item the selected +ID and its text string are written, similar to: + + setenv c.<name> <selected_id> + setenv c.<name>-str <selected_id's text string> + +The `-v` flag enables verbose mode, where each variable is printed before it is +set. + +cedit write_cmos +~~~~~~~~~~~~~~~~ + +Writes the settings to locations in the CMOS RAM. The locations used are +specified by the schema. See `expo_format_`. + +The `-v` flag enables verbose mode, which shows which CMOS locations were +updated. + +Normally the first RTC device is used to hold the data. You can specify a +different device by name using the `dev` parameter. + + Example ------- @@ -29,3 +97,52 @@ Example => cedit load hostfs - fred.dtb => cedit run + => cedit write_fdt hostfs - settings.dtb + +That results in:: + + / { + cedit-values { + cpu-speed = <0x00000006>; + cpu-speed-str = "2 GHz"; + power-loss = <0x0000000a>; + power-loss-str = "Always Off"; + }; + } + + => cedit read_fdt hostfs - settings.dtb + +This shows settings being stored in the environment:: + + => cedit write_env -v + c.cpu-speed=7 + c.cpu-speed-str=2.5 GHz + c.power-loss=12 + c.power-loss-str=Memory + => print + ... + c.cpu-speed=6 + c.cpu-speed-str=2 GHz + c.power-loss=10 + c.power-loss-str=Always Off + ... + + => cedit read_env -v + c.cpu-speed=7 + c.power-loss=12 + +This shows writing to CMOS RAM. Notice that the bytes at 80 and 84 change:: + + => rtc read 80 8 + 00000080: 00 00 00 00 00 2f 2a 08 ...../*. + => cedit write_cmos -v + Write 2 bytes from offset 80 to 84 + => rtc read 80 8 + 00000080: 01 00 00 00 08 2f 2a 08 ...../*. + => cedit read_cmos -v + Read 2 bytes from offset 80 to 84 + +Here is an example with the device specified:: + + => cedit write_cmos rtc@43 + => |
