diff options
Diffstat (limited to 'doc/develop')
-rw-r--r-- | doc/develop/bootstd.rst | 50 | ||||
-rw-r--r-- | doc/develop/codingstyle.rst | 8 | ||||
-rw-r--r-- | doc/develop/cyclic.rst | 26 | ||||
-rw-r--r-- | doc/develop/gdb.rst | 171 | ||||
-rw-r--r-- | doc/develop/index.rst | 1 | ||||
-rw-r--r-- | doc/develop/tests_writing.rst | 1 | ||||
-rw-r--r-- | doc/develop/uefi/fwu_updates.rst | 20 | ||||
-rw-r--r-- | doc/develop/uefi/uefi.rst | 12 |
8 files changed, 242 insertions, 47 deletions
diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst index a07a72581e7..34631089ae0 100644 --- a/doc/develop/bootstd.rst +++ b/doc/develop/bootstd.rst @@ -39,7 +39,7 @@ Bootflow A bootflow is a file that describes how to boot a distro. Conceptually there can be different formats for that file but at present U-Boot only supports the -BootLoaderSpec_ format. which looks something like this:: +BootLoaderSpec_ format which looks something like this:: menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options. menu title Fedora-Workstation-armhfp-31-1.9 Boot Options. @@ -52,7 +52,7 @@ BootLoaderSpec_ format. which looks something like this:: initrd /initramfs-5.3.7-301.fc31.armv7hl.img As you can see it specifies a kernel, a ramdisk (initrd) and a directory from -which to load devicetree files. The details are described in distro_bootcmd_. +which to load Device Tree files. The details are described in distro_bootcmd_. The bootflow is provided by the distro. It is not part of U-Boot. U-Boot's job is simply to interpret the file and carry out the instructions. This allows @@ -85,7 +85,7 @@ Bootmeth -------- Once the list of filesystems is provided, how does U-Boot find the bootflow -files in these filesystems. That is the job of bootmeth. Each boot method has +files in these filesystems? That is the job of bootmeth. Each boot method has its own way of doing this. For example, the distro bootmeth simply looks through the provided filesystem @@ -106,7 +106,7 @@ they scan a lot of devices. Boot process ------------ -U-Boot tries to use the 'lazy init' approach whereever possible and distro boot +U-Boot tries to use the 'lazy init' approach wherever possible and distro boot is no exception. The algorithm is:: while (get next bootdev) @@ -174,13 +174,13 @@ the same way as setting this variable. Bootdev uclass -------------- -The bootdev uclass provides an simple API call to obtain a bootflows from a +The bootdev uclass provides a simple API call to obtain a bootflow from a device:: int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, struct bootflow *bflow); -This takes a iterator which indicates the bootdev, partition and bootmeth to +This takes an iterator which indicates the bootdev, partition and bootmeth to use. It returns a bootflow. This is the core of the bootdev implementation. The bootdev drivers that implement this differ depending on the media they are reading from, but each is responsible for returning a valid bootflow if @@ -188,7 +188,7 @@ available. A helper called `bootdev_find_in_blk()` makes it fairly easy to implement this function for each media device uclass, in a few lines of code. For many types -ot bootdevs, the `get_bootflow` member can be NULL, indicating that the default +of bootdevs, the `get_bootflow` member can be NULL, indicating that the default handler is used. This is called `default_get_bootflow()` and it only works with block devices. @@ -196,7 +196,7 @@ block devices. Bootdev drivers --------------- -A bootdev driver is typically fairly simple. Here is one for mmc:: +A bootdev driver is typically fairly simple. Here is one for MMC:: static int mmc_bootdev_bind(struct udevice *dev) { @@ -328,7 +328,7 @@ or:: Here, `eth_bootdev` is the name of the Ethernet bootdev driver and `dev` -is the ethernet device. This function is safe to call even if standard boot is +is the Ethernet device. This function is safe to call even if standard boot is not enabled, since it does nothing in that case. It can be added to all uclasses which implement suitable media. @@ -340,7 +340,7 @@ Standard boot requires a single instance of the bootstd device to make things work. This includes global information about the state of standard boot. See `struct bootstd_priv` for this structure, accessed with `bootstd_get_priv()`. -Within the devicetree, if you add bootmeth devices, they should be children of +Within the Device Tree, if you add bootmeth devices, they should be children of the bootstd device. See `arch/sandbox/dts/test.dts` for an example of this. @@ -349,12 +349,12 @@ the bootstd device. See `arch/sandbox/dts/test.dts` for an example of this. Automatic devices ----------------- -It is possible to define all the required devices in the devicetree manually, +It is possible to define all the required devices in the Device Tree manually, but it is not necessary. The bootstd uclass includes a `dm_scan_other()` function which creates the bootstd device if not found. If no bootmeth devices are found at all, it creates one for each available bootmeth driver. -If your devicetree has any bootmeth device it must have all of them that you +If your Device Tree has any bootmeth device it must have all of them that you want to use, since no bootmeth devices will be created automatically in that case. @@ -363,8 +363,8 @@ Using devicetree ---------------- If a bootdev is complicated or needs configuration information, it can be -added to the devicetree as a child of the media device. For example, imagine a -bootdev which reads a bootflow from SPI flash. The devicetree fragment might +added to the Device Tree as a child of the media device. For example, imagine a +bootdev which reads a bootflow from SPI flash. The Device Tree fragment might look like this:: spi@0 { @@ -398,7 +398,7 @@ Standard boot is enabled with `CONFIG_BOOTSTD`. Each bootmeth has its own CONFIG option also. For example, `CONFIG_BOOTMETH_EXTLINUX` enables support for booting from a disk using an `extlinux.conf` file. -To enable all feature sof standard boot, use `CONFIG_BOOTSTD_FULL`. This +To enable all features of standard boot, use `CONFIG_BOOTSTD_FULL`. This includes the full set of commands, more error messages when things go wrong and bootmeth ordering with the bootmeths environment variable. @@ -492,9 +492,9 @@ Theory of operation This describes how standard boot progresses through to booting an operating system. -To start. all the necessary devices must be bound, including bootstd, which +To start, all the necessary devices must be bound, including bootstd, which provides the top-level `struct bootstd_priv` containing optional configuration -information. The bootstd device is also holds the various lists used while +information. The bootstd device also holds the various lists used while scanning. This step is normally handled automatically by driver model, as described in `Automatic Devices`_. @@ -504,7 +504,7 @@ those bootdevs. So, all up, we need a single bootstd device, one or more bootdev devices and one or more bootmeth devices. Once these are ready, typically a `bootflow scan` command is issued. This kicks -of the iteration process, which involves hunting for bootdevs and looking +off the iteration process, which involves hunting for bootdevs and looking through the bootdevs and their partitions one by one to find bootflows. Iteration is kicked off using `bootflow_scan_first()`. @@ -526,7 +526,7 @@ Then the iterator is set up to according to the parameters given: - If `label` indicates a numeric bootdev number (e.g. "2") then `BOOTFLOW_METHF_SINGLE_DEV` is set. In this case, moving to the next bootdev - simple stops, since there is only one. No hunters are used. + simply stops, since there is only one. No hunters are used. - If `label` indicates a particular media device (e.g. "mmc1") then `BOOTFLOWIF_SINGLE_MEDIA` is set. In this case, moving to the next bootdev processes just the children of the media device. Hunters are used, in this @@ -554,7 +554,7 @@ bootdev and disturb the original ordering. Next, the ordering of bootmeths is determined, by `bootmeth_setup_iter_order()`. By default the ordering is again by sequence number, i.e. the `/aliases` node, -or failing that the order in the devicetree. But the `bootmeth order` command +or failing that the order in the Device Tree. But the `bootmeth order` command or `bootmeths` environment variable can be used to set up an ordering. If that has been done, the ordering is in `struct bootstd_priv`, so that ordering is simply copied into the iterator. Either way, the `method_order` array it set up, @@ -652,12 +652,12 @@ valid bootflow is found early on. With `bootflow scan -b`, that causes the bootflow to be immediately booted. Assuming it is successful, the iteration never completes. -Also note that the iterator hold the **current** combination being considered. +Also note that the iterator holds the **current** combination being considered. So when `iter_incr()` is called, it increments to the next one and returns it, the new **current** combination. Note also the `err` field in `struct bootflow_iter`. This is normally 0 and has -thus has no effect on `iter_inc()`. But if it is non-zero, signalling an error, +thus no effect on `iter_inc()`. But if it is non-zero, signalling an error, it indicates to the iterator what it should do when called. It can force moving to the next partition, or bootdev, for example. The special values `BF_NO_MORE_PARTS` and `BF_NO_MORE_DEVICES` handle this. When `iter_incr` sees @@ -675,7 +675,7 @@ So what happens inside of `bootflow_check()`? It simply calls the uclass method `bootdev_get_bootflow()` to ask the bootdev to return a bootflow. It passes the iterator to the bootdev method, so that function knows what we are talking about. At first, the bootflow is set up in the state `BOOTFLOWST_BASE`, -with just the `method` and `dev` intiialised. But the bootdev may fill in more, +with just the `method` and `dev` initialised. But the bootdev may fill in more, e.g. updating the state, depending on what it finds. For global bootmeths the `bootmeth_get_bootflow()` function is called instead of `bootdev_get_bootflow()`. @@ -733,12 +733,12 @@ bootflow is handled by the bootmeth driver for that bootflow. In the case of extlinux boot, this parses and processes the `extlinux.conf` file that was read. See `extlinux_boot()` for how that works. The processing may involve reading additional files, which is handled by the `read_file()` method, which is -`extlinux_read_file()` in this case. All bootmethds should support reading +`extlinux_read_file()` in this case. All bootmeths should support reading files, since the bootflow is typically only the basic instructions and does not include the operating system itself, ramdisk, device tree, etc. The vast majority of the bootstd code is concerned with iterating through -partitions on bootdevs and using bootmethds to find bootflows. +partitions on bootdevs and using bootmeths to find bootflows. How about bootdevs which are not block devices? They are handled by the same methods as above, but with a different implementation. For example, the bootmeth diff --git a/doc/develop/codingstyle.rst b/doc/develop/codingstyle.rst index f6248cdcb1e..fa3cd6aec82 100644 --- a/doc/develop/codingstyle.rst +++ b/doc/develop/codingstyle.rst @@ -110,9 +110,8 @@ Include files You should follow this ordering in U-Boot. In all cases, they should be listed in alphabetical order. First comes headers which are located directly in our -top-level include diretory. This excludes the common.h header file which is to -be removed. Second are headers within subdirectories, Finally directory-local -includes should be listed. See this example: +top-level include diretory. Second are headers within subdirectories, Finally +directory-local includes should be listed. See this example: .. code-block:: C @@ -129,9 +128,6 @@ For files that need to be compiled for the host (e.g. tools), you need to use ``#ifndef USE_HOSTCC`` to avoid including U-Boot specific include files. See common/image.c for an example. -If you encounter code which still uses <common.h> a patch to remove that and -replace it with any required include files directly is much appreciated. - If your file uses driver model, include <dm.h> in the C file. Do not include dm.h in a header file. Try to use forward declarations (e.g. ``struct udevice``) instead. diff --git a/doc/develop/cyclic.rst b/doc/develop/cyclic.rst index 67831496a70..893c269099a 100644 --- a/doc/develop/cyclic.rst +++ b/doc/develop/cyclic.rst @@ -19,20 +19,26 @@ Registering a cyclic function To register a cyclic function, use something like this:: - static void cyclic_demo(void *ctx) + struct donkey { + struct cyclic_info cyclic; + void (*say)(const char *s); + }; + + static void cyclic_demo(struct cyclic_info *c) { - /* Just a small dummy delay here */ - udelay(10); + struct donkey *donkey = container_of(c, struct donkey, cyclic); + + donkey->say("Are we there yet?"); } - - int board_init(void) + + int donkey_init(void) { - struct cyclic_info *cyclic; - + struct donkey *donkey; + + /* Initialize donkey ... */ + /* Register demo cyclic function */ - cyclic = cyclic_register(cyclic_demo, 10 * 1000, "cyclic_demo", NULL); - if (!cyclic) - printf("Registering of cyclic_demo failed\n"); + cyclic_register(&donkey->cyclic, cyclic_demo, 10 * 1000, "cyclic_demo"); return 0; } diff --git a/doc/develop/gdb.rst b/doc/develop/gdb.rst new file mode 100644 index 00000000000..4e359c7f226 --- /dev/null +++ b/doc/develop/gdb.rst @@ -0,0 +1,171 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (c) 2024 Alexander Dahl + +Debugging U-Boot with GDB +========================= + +Using a JTAG adapter it is possible to debug a running U-Boot with GDB. +A common way is to connect a debug adapter to the JTAG connector of your +board, run a GDB server, connect GDB to the GDB server, and use GDB as usual. + +Similarly QEMU can provide a GDB server. + +Preparing build +--------------- + +Building U-Boot with with reduced optimization (-Og) and without link time +optimization is recommended for easier debugging:: + + CONFIG_CC_OPTIMIZE_FOR_DEBUG=y + CONFIG_LTO=n + +Otherwise build, install, and run U-Boot as usual. + +Using OpenOCD as GDB server +--------------------------- + +`OpenOCD <https://openocd.org/>`_ is an open source tool supporting hardware +debug probes, and providing a GDB server. It is readily available in major Linux +distributions or you can build it from source. + +Here is example of starting OpenOCD on Debian using a J-Link adapter and a +board with an AT91 SAMA5D2 SoC: + +.. code-block:: console + + $ openocd -f interface/jlink.cfg -f target/at91sama5d2.cfg -c 'adapter speed 4000' + Open On-Chip Debugger 0.12.0 + Licensed under GNU GPL v2 + For bug reports, read + http://openocd.org/doc/doxygen/bugs.html + Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'. + adapter speed: 4000 kHz + + Info : Listening on port 6666 for tcl connections + Info : Listening on port 4444 for telnet connections + Info : J-Link V10 compiled Jan 30 2023 11:28:07 + Info : Hardware version: 10.10 + Info : VTarget = 3.244 V + Info : clock speed 4000 kHz + Info : JTAG tap: at91sama5d2.cpu tap/device found: 0x5ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x5) + Info : at91sama5d2.cpu_a5.0: hardware has 3 breakpoints, 2 watchpoints + Info : at91sama5d2.cpu_a5.0: MPIDR level2 0, cluster 0, core 0, mono core, no SMT + Info : starting gdb server for at91sama5d2.cpu_a5.0 on 3333 + Info : Listening on port 3333 for gdb connections + +Notice that OpenOCD is listening on port 3333 for GDB connections. + +Using QEMU as GDB server +------------------------ + +When running U-Boot on QEMU you can used the '-gdb' parameter to provide a +GDB server: + + qemu-system-riscv64 -M virt -nographic -gdb tcp::3333 -kernel u-boot + +Running a GDB session +---------------------- + +You need a GDB suited for your target. This can be the GDB coming with your +toolchain or *gdb-multiarch* available in your Linux distribution. + +.. prompt:: bash $ + + gdb-multiarch u-boot + +In the above command-line *u-boot* is the U-boot binary in your build +directory. You may need to adjust the path when calling GDB. + +Connect to the GDB server like this: + +.. code-block:: console + + (gdb) target extended-remote :3333 + Remote debugging using :3333 + 0x27fa9ac6 in ?? () + (gdb) + +This is fine for debugging before U-Boot relocates itself. + +For debugging U-Boot after relocation you need to indicate the relocation +address to GDB. You can retrieve the relocation address from the U-Boot shell +with the command *bdinfo*: + +.. code-block:: console + + U-Boot> bdinfo + boot_params = 0x20000100 + DRAM bank = 0x00000000 + -> start = 0x20000000 + -> size = 0x08000000 + flashstart = 0x00000000 + flashsize = 0x00000000 + flashoffset = 0x00000000 + baudrate = 115200 bps + relocaddr = 0x27f7a000 + reloc off = 0x0607a000 + Build = 32-bit + current eth = ethernet@f8008000 + ethaddr = 00:50:c2:31:58:d4 + IP addr = <NULL> + fdt_blob = 0x27b36060 + new_fdt = 0x27b36060 + fdt_size = 0x00003e40 + lmb_dump_all: + memory.cnt = 0x1 / max = 0x10 + memory[0] [0x20000000-0x27ffffff], 0x08000000 bytes flags: 0 + reserved.cnt = 0x1 / max = 0x10 + reserved[0] [0x27b31d00-0x27ffffff], 0x004ce300 bytes flags: 0 + devicetree = separate + arch_number = 0x00000000 + TLB addr = 0x27ff0000 + irq_sp = 0x27b36050 + sp start = 0x27b36040 + Early malloc usage: cd8 / 2000 + +Look out for the line starting with *relocaddr* which has the address +you need, ``0x27f7a000`` in this case. + +On most architectures (not sandbox, x86, Xtensa) the global data pointer is +stored in a fixed register: + +============ ======== +Architecture Register +============ ======== +arc r25 +arm r9 +arm64 x18 +m68k d7 +microblaze r31 +mips k0 +nios2 gp +powerpc r2 +riscv gp +sh r13 +============ ======== + +On these architecture the relocation address cat be determined by +dereferencing the global data pointer stored in register, *r9* in the example: + +.. code-block:: console + + (gdb) p/x (*(struct global_data*)$r9)->relocaddr + $1 = 0x27f7a000 + +In the GDB shell discard the previously loaded symbol file and add it once +again with the relocation address like this: + +.. code-block:: console + + (gdb) symbol-file + Discard symbol table from `/home/adahl/build/u-boot/v2024.04.x/u-boot'? (y or n) y + No symbol file now. + (gdb) add-symbol-file u-boot 0x27f7a000 + add symbol table from file "u-boot" at + .text_addr = 0x27f7a000 + (y or n) y + Reading symbols from u-boot... + (gdb) + +You can now use GDB as usual, setting breakpoints, printing backtraces, +inspecting variables, stepping through the code, etc. diff --git a/doc/develop/index.rst b/doc/develop/index.rst index f82e148b101..f9c4bf839ee 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -60,6 +60,7 @@ Debugging :maxdepth: 1 crash_dumps + gdb trace Packaging diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst index bb1145da268..44b544fa78b 100644 --- a/doc/develop/tests_writing.rst +++ b/doc/develop/tests_writing.rst @@ -281,7 +281,6 @@ new one of those, you should add a new suite. Create a new file in test/ or a subdirectory and define a macro to register the suite. For example:: - #include <common.h> #include <console.h> #include <mapmem.h> #include <dm/test.h> diff --git a/doc/develop/uefi/fwu_updates.rst b/doc/develop/uefi/fwu_updates.rst index e4709d82b41..51e8a28efe1 100644 --- a/doc/develop/uefi/fwu_updates.rst +++ b/doc/develop/uefi/fwu_updates.rst @@ -46,6 +46,8 @@ The feature can be enabled by specifying the following configs:: CONFIG_FWU_NUM_BANKS=<val> CONFIG_FWU_NUM_IMAGES_PER_BANK=<val> + CONFIG_FWU_MDATA_V1=y or CONFIG_FWU_MDATA_V2=y + in the .config file By enabling the CONFIG_CMD_FWU_METADATA config option, the @@ -58,6 +60,14 @@ enable the FWU Multi Bank Update functionality. Please refer to the section :ref:`uefi_capsule_update_ref` for more details on generation of the UEFI capsule. +FWU Metadata +------------ + +U-Boot supports both versions(1 and 2) of the FWU metadata defined in +the two revisions of the specification. Support can be enabled for +either of the two versions through a config flag. The mkfwumdata tool +can generate metadata for both the supported versions. + Setting up the device for GPT partitioned storage ------------------------------------------------- @@ -94,12 +104,12 @@ of. Each GPT partition entry in the GPT header has two GUIDs:: * UniquePartitionGUID The PartitionTypeGUID value should correspond to the -``image_type_uuid`` field of the FWU metadata. This field is used to +``image_type_guid`` field of the FWU metadata. This field is used to identify a given type of updatable firmware image, e.g. U-Boot, OP-TEE, FIP etc. This GUID should also be used for specifying the `--guid` parameter when generating the capsule. -The UniquePartitionGUID value should correspond to the ``image_uuid`` +The UniquePartitionGUID value should correspond to the ``image_guid`` field in the FWU metadata. This GUID is used to identify images of a given image type in different banks. @@ -108,8 +118,8 @@ metadata partitions. This would be the PartitionTypeGUID for the metadata partitions. Similarly, the UEFI specification defines the ESP GUID to be be used. -When generating the metadata, the ``image_type_uuid`` and the -``image_uuid`` values should match the *PartitionTypeGUID* and the +When generating the metadata, the ``image_type_guid`` and the +``image_guid`` values should match the *PartitionTypeGUID* and the *UniquePartitionGUID* values respectively. Performing the Update @@ -181,5 +191,5 @@ empty capsule would be:: Links ----- -* [1] https://developer.arm.com/documentation/den0118/a/ - FWU Specification +* [1] https://developer.arm.com/documentation/den0118/ - FWU Specification * [2] https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf - Dependable Boot Specification diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst index ea70dcbda86..88596f312c0 100644 --- a/doc/develop/uefi/uefi.rst +++ b/doc/develop/uefi/uefi.rst @@ -631,6 +631,18 @@ where version.dtso looks like:: The properties of image-type-id and image-index must match the value defined in the efi_fw_image array as image_type_id and image_index. +Porting Capsule Updates to new boards +************************************* + +It is important, when using a reference board as a starting point for a custom +board, that certain steps are taken to properly support Capsule Updates. + +Capsule GUIDs need to be unique for each firmware and board. That is, if two +firmwares are built from the same source but result in different binaries +because they are built for different boards, they should have different GUIDs. +Therefore it is important when creating support for a new board, new GUIDs are +defined in the board's header file. *DO NOT* reuse capsule GUIDs. + Executing the boot manager ~~~~~~~~~~~~~~~~~~~~~~~~~~ |