mirror of
https://xff.cz/git/u-boot/
synced 2026-01-07 03:29:19 +01:00
@@ -464,6 +464,28 @@ ready File was loaded and is ready for use. In this state the bootflow is
|
||||
======= =======================================================================
|
||||
|
||||
|
||||
Migrating from distro_boot
|
||||
--------------------------
|
||||
|
||||
To migrate from distro_boot:
|
||||
|
||||
#. Update your board header files to remove the BOOTENV and BOOT_TARGET_xxx
|
||||
defines. Standard boot finds available boot devices automatically.
|
||||
|
||||
#. Remove the "boot_targets" variable unless you need it. Standard boot uses a
|
||||
default order from fastest to slowest, which generally matches the order used
|
||||
by boards.
|
||||
|
||||
#. Make sure that CONFIG_BOOTSTD_DEFAULTS is enabled by your board, so it can
|
||||
boot common Linux distributions.
|
||||
|
||||
An example patch is at migrate_patch_.
|
||||
|
||||
If you are using custom boot scripts for your board, consider creating your
|
||||
own bootmeth to hold the logic. There are various examples at
|
||||
`boot/bootmeth_...`.
|
||||
|
||||
|
||||
Theory of operation
|
||||
-------------------
|
||||
|
||||
@@ -683,11 +705,12 @@ Assuming the bootmeth is happy, or at least indicates that it is willing to try
|
||||
partition. If that works it tries to detect a file system. If that works then it
|
||||
calls the bootmeth device once more, this time to read the bootflow.
|
||||
|
||||
Note: At present a filesystem is needed for the bootmeth to be called on block
|
||||
devices, simply because we don't have any examples where this is not the case.
|
||||
This feature can be added as needed. Note that sandbox is a special case, since
|
||||
in that case the host filesystem can be accessed even though the block device
|
||||
is NULL.
|
||||
Note: Normally a filesystem is needed for the bootmeth to be called on block
|
||||
devices, but bootmeths which don't need that can set the BOOTMETHF_ANY_PART
|
||||
flag to indicate that they can scan any partition. An example is the ChromiumOS
|
||||
bootmeth which can store a kernel in a raw partition. Note also that sandbox is
|
||||
a special case, since in that case the host filesystem can be accessed even
|
||||
though the block device is NULL.
|
||||
|
||||
If we take the example of the `bootmeth_extlinux` driver, this call ends up at
|
||||
`extlinux_read_bootflow()`. It has the filesystem ready, so tries various
|
||||
@@ -774,3 +797,4 @@ Other ideas:
|
||||
.. _BootLoaderSpec: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
|
||||
.. _distro_boot: https://github.com/u-boot/u-boot/blob/master/boot/distro.c
|
||||
.. _bootflow_h: https://github.com/u-boot/u-boot/blob/master/include/bootflow.h
|
||||
.. _migrate_patch: https://patchwork.ozlabs.org/project/uboot/patch/20230727215433.578830-2-sjg@chromium.org/
|
||||
|
||||
169
doc/develop/cedit.rst
Normal file
169
doc/develop/cedit.rst
Normal file
@@ -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.
|
||||
@@ -21,16 +21,31 @@ Declaring a spy
|
||||
|
||||
To declare a spy, use something like this::
|
||||
|
||||
static int snow_setup_cpus(void *ctx, struct event *event)
|
||||
static int snow_check_temperature(void)
|
||||
{
|
||||
/* do something */
|
||||
return 0;
|
||||
}
|
||||
EVENT_SPY(EVT_DM_POST_INIT_F, snow_setup_cpus);
|
||||
EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, snow_check_temperature);
|
||||
|
||||
This function is called when EVT_DM_POST_INIT_F is emitted, i.e. after the
|
||||
driver model is initialized (in U-Boot proper before and after relocation).
|
||||
|
||||
If you need access to the event data, use `EVENT_SPY_FULL`, like this::
|
||||
|
||||
static int snow_setup_cpus(void *ctx, struct event *event)
|
||||
{
|
||||
/* do something that uses event->data*/
|
||||
return 0;
|
||||
}
|
||||
EVENT_SPY_FULL(EVT_DM_POST_INIT_F, snow_setup_cpus);
|
||||
|
||||
Note that the context is always NULL for a static spy. See below for information
|
||||
about how to use a dynamic spy.
|
||||
|
||||
The return value is handled by the event emitter. If non-zero, then the error
|
||||
is returned to the function which emitted the event, i.e. the one that called
|
||||
`event_notify()`.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
@@ -80,6 +95,10 @@ to be notified when a particular device is probed or removed.
|
||||
This can be handled by enabling `CONFIG_EVENT_DYNAMIC`. It is then possible to
|
||||
call `event_register()` to register a new handler for a particular event.
|
||||
|
||||
If some context is need for the spy, you can pass a pointer to
|
||||
`event_register()` to provide that. Note that the context is only passed to
|
||||
a spy registered with `EVENT_SPY_FULL`.
|
||||
|
||||
Dynamic event handlers are called after all the static event spy handlers have
|
||||
been processed. Of course, since dynamic event handlers are created at runtime
|
||||
it is not possible to use the `event_dump.py` to see them.
|
||||
|
||||
@@ -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
|
||||
|
||||
#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
|
||||
enum {
|
||||
ZERO,
|
||||
ID_PROMPT,
|
||||
ID_SCENE1,
|
||||
ID_SCENE1_TITLE,
|
||||
|
||||
#define ID_POWER_LOSS 9
|
||||
#define ID_AC_OFF 10
|
||||
#define ID_AC_ON 11
|
||||
#define ID_AC_MEMORY 12
|
||||
ID_CPU_SPEED,
|
||||
ID_CPU_SPEED_TITLE,
|
||||
ID_CPU_SPEED_1,
|
||||
ID_CPU_SPEED_2,
|
||||
ID_CPU_SPEED_3,
|
||||
|
||||
#define ID_DYNAMIC_START 13
|
||||
ID_POWER_LOSS,
|
||||
ID_AC_OFF,
|
||||
ID_AC_ON,
|
||||
ID_AC_MEMORY,
|
||||
|
||||
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 <sjg@chromium.org>
|
||||
.. 7-Oct-22
|
||||
|
||||
@@ -38,6 +38,7 @@ Implementation
|
||||
driver-model/index
|
||||
environment
|
||||
expo
|
||||
cedit
|
||||
event
|
||||
global_data
|
||||
logging
|
||||
|
||||
@@ -318,6 +318,9 @@ Run the following command
|
||||
--guid <image GUID> \
|
||||
<capsule_file_name>
|
||||
|
||||
Capsule with firmware version
|
||||
*****************************
|
||||
|
||||
The UEFI specification does not define the firmware versioning mechanism.
|
||||
EDK II reference implementation inserts the FMP Payload Header right before
|
||||
the payload. It coutains the fw_version and lowest supported version,
|
||||
@@ -345,6 +348,43 @@ add --fw-version option in mkeficapsule tool.
|
||||
If the --fw-version option is not set, FMP Payload Header is not inserted
|
||||
and fw_version is set as 0.
|
||||
|
||||
Capsule Generation through binman
|
||||
*********************************
|
||||
|
||||
Support has also been added to generate capsules during U-Boot build
|
||||
through binman. This requires the platform's DTB to be populated with
|
||||
the capsule entry nodes for binman. The capsules then can be generated
|
||||
by specifying the capsule parameters as properties in the capsule
|
||||
entry node.
|
||||
|
||||
Check the test/py/tests/test_efi_capsule/capsule_gen_binman.dts file
|
||||
as reference for how a typical binman node for capsule generation
|
||||
looks like. For generating capsules as part of the platform's build, a
|
||||
capsule node would then have to be included into the platform's
|
||||
devicetree.
|
||||
|
||||
A typical binman node for generating a capsule would look like::
|
||||
|
||||
capsule {
|
||||
filename = "u-boot.capsule";
|
||||
efi-capsule {
|
||||
image-index = <0x1>;
|
||||
image-guid = "09d7cf52-0720-4710-91d1-08469b7fe9c8";
|
||||
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
In the above example, a capsule file named u-boot.capsule will be
|
||||
generated with u-boot.bin as it's input payload. The capsule
|
||||
generation parameters like image-index and image-guid are being
|
||||
specified as properties. Similarly, other properties like the private
|
||||
and public key certificate can be specified for generating signed
|
||||
capsules. Refer :ref:`etype_efi_capsule` for documentation about the
|
||||
efi-capsule binman entry type, which describes all the properties that
|
||||
can be specified.
|
||||
|
||||
Performing the update
|
||||
*********************
|
||||
|
||||
@@ -522,20 +562,11 @@ and used by the steps highlighted below.
|
||||
...
|
||||
}
|
||||
|
||||
You can do step-4 manually with
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ dtc -@ -I dts -O dtb -o signature.dtbo signature.dts
|
||||
$ fdtoverlay -i orig.dtb -o new.dtb -v signature.dtbo
|
||||
|
||||
where signature.dts looks like::
|
||||
|
||||
&{/} {
|
||||
signature {
|
||||
capsule-key = /incbin/("CRT.esl");
|
||||
};
|
||||
};
|
||||
You can perform step-4 through the Kconfig symbol
|
||||
CONFIG_EFI_CAPSULE_ESL_FILE. This symbol points to the esl file
|
||||
generated in step-2. Once the symbol has been populated with the path
|
||||
to the esl file, it will automatically get embedded into the
|
||||
platform's dtb as part of U-Boot build.
|
||||
|
||||
Anti-rollback Protection
|
||||
************************
|
||||
|
||||
Reference in New Issue
Block a user