Taming Verbose Commands: Introducing the U-Boot Console Pager

Have you ever run the help or env print command and watched a torrent of text scroll past, faster than you could read it? We’ve all been there. Important information disappears off the top of the screen before we have a chance to digest it.

Well, those days are over! Thanks to a new patch series, U-Boot Concept now includes a console pager, a simple but highly effective feature that makes managing long command outputs a breeze.

What is the Pager?

At its core, the pager does one thing very well: it pauses output once your screen is full. When you run a command that generates a lot of text, the pager will stop after a certain number of lines and display a prompt:

: Press SPACE to continue

This gives you all the time you need to read the output. Once you’re ready, just press the SPACE bar, and U-Boot will display the next screenful of text. It’s an intuitive and familiar experience for anyone who has used tools like less or more in a Linux environment.

How to Use and Configure It

The pager is enabled with the CONFIG_CONSOLE_PAGER option. Once enabled, U-Boot uses a smart system to determine the page size (i.e., how many lines to show before pausing). Here’s the order of priority:

  1. The pager Environment Variable: You have full control. You can set the number of lines (in hexadecimal) yourself (‘setenv pager 1e’). Setting it to 0 disables the pager.
  2. Automatic Device Detection: If the pager variable isn’t set, U-Boot tries to be clever.

    • If you’re using a video console (vidconsole), it will automatically use the number of rows your display supports.
    • If you’re on a serial console, U-Boot can query the terminal to get its dimensions. This is enabled by CONFIG_SERIAL_TERM_PRESENT.

  3. Default Value: If all else fails, it falls back to a sensible default defined by CONFIG_CONSOLE_PAGER_LINES.

Under the Hood: A Foundation of Quality-of-Life Improvements

Introducing the pager wasn’t just a single patch. This feature was built on a solid foundation of refactoring and improvements throughout the console and serial subsystems.

One of the key preparatory steps was to generalize terminal size detection. Previously, the logic to query a terminal’s rows and columns was tucked away in the EFI loader. This code has now been moved into the generic serial uclass, making it available to any part of U-Boot. To improve performance, the terminal dimensions are cached, so U-Boot only has to ask once.

Additionally, new helper functions were introduced to determine if the console is actually connected to an interactive terminal (serial_is_tty()) or if a video display is visible. This is particularly important for environments like sandbox, where U-Boot’s output might be redirected to a file. In those cases, the pager intelligently disables itself to prevent scripts from hanging.

A Boon for Testers and Developers

Speaking of automated testing, the pager could potentially cause tests to hang while waiting for user input. To solve this, two new command-line flags have been added to the sandbox environment:

  • -P: Bypasses the pager completely.
  • -A: Assumes no terminal is present, which disables the terminal-size query.

Our Python test suite has already been updated to use these flags, ensuring that automated testing remains smooth and reliable.

Conclusion

The console pager is a nice quality-of-life improvement that makes the U-Boot command line more user-friendly. It’s a small change that will have a big impact on daily development and debugging workflows, particularly on devices without a serial console. This work, along with the thoughtful refactoring that supports it, is a great example of the continuous effort to polish and improve the U-Boot user experience.

So go ahead, enable CONFIG_CONSOLE_PAGER, and enjoy a more civilized console experience!




Streamlining Your Patch Workflow with Patman Series Management

Managing patch series can be one of the most time-consuming aspects of contributing to large open-source projects like U-Boot and Linux. While patman has long been a powerful tool for creating, checking, and sending patches, the relatively new patman series feature takes workflow management to the next level by providing lifecycle management for series, with Patchwork integration.

What is ‘patman series’?

The patman series feature (available via patman s or patman ser for brevity) is a database-backed, series-management system that tracks your patch series from initial creation through upstream acceptance. Unlike traditional patch workflows where you manually track versions, reviews, and status across multiple tools, patman series provides a unified interface that integrates directly with Patchwork to automate much of this tedious bookkeeping.

Key Benefits

Automated Series Tracking: Once you add a series to patman’s database, it automatically tracks versions, maintains links to Patchwork, and monitors upstream progress.

Seamless Version Management: Creating v2, v3, etc. of your series is as simple as patman series inc, which automatically creates new branches and updates the database.

Patchwork Integration: Patman automatically discovers your series on Patchwork after sending, tracks review comments, and can gather review tags back into your commits.

Branch Organization: The system encourages a clean branching strategy where each series version gets its own branch, making it easy to maintain multiple versions simultaneously.

Getting Started: A Complete Workflow

Let’s walk through a typical workflow using patman series. First, set up your project (this only needs to be done once):

patman patchwork set-project U-Boot

Now suppose you have a branch video2 with some patches ready to send. Add it to patman’s tracking:

git checkout video2
patman series add

Patman will scan your branch and add it to the database. You might see a warning about unmarked commits – you can either let patman add Change-Id values with -m or tell it not to worry with -M:

patman series add -M

Now send your series:

patman series send

Patman will use git send-email to send your patches and then wait to see if it can automatically find your series on Patchwork. Once linked, you can track its progress. In fact you can see the progress of all your series. Here is an example:

$ patman series progress
Name             Description                               Count  Status
---------------  ----------------------------------------  -----  ---------------
apa              lib: Split fdt_print() into separate libr     4  4:unknown
apb              efi: App and devicetree improvements         20 *20:unknown
app-us           efi_loader: Separate device path into its     3  3:accepted
appc             [00/27] x86: efi: Various app improvement    27  27:n/a
appd             doc: efi_loader: Tidy up the bootefi-comm     2  1:new 1:unknown
bgr2             ACPI fixes                                    4 *4:unknown
blob             [0/4] bloblist: fdt: Clean up the code        5  4:changes 1:unknown
bmg              buildman: Correct behaviour of --in-tree      2  2:new
ci-lab           CI multi-processing                           1  1:n/a
cia              CI improvements                               1  1:changes
efiq3            [v3,00/29] arm: Support building as an EF    36  32:changes 4:unknown
efit             efi: Rename the lib/efi directory             4  4:new
expa             expo: Allow the nominal display-size to b     6  6:n/a
fast             emulation: Improve support for booting fr    19  19:unknown

Series Management Commands

The series subcommand offers a comprehensive set of operations:

Core Operations

  • add: Add a new series to tracking
  • send: Send patches (like patman send but for any tracked series)
  • ls: List all tracked series
  • scan: Rescan a branch to update patch information

Version Management

  • inc: Create next version (v2, v3, etc.) by creating a new branch
  • dec: Delete current version and branch
  • rm-version: Remove specific versions
  • rm: Remove entire series

Patchwork Integration

  • autolink: Find Patchwork link for your series
  • progress: Show upstream status and review progress
  • gather: Collect review tags from Patchwork into commits
  • open: Open series in web browser

Advanced Features

  • mark/unmark: Add/remove Change-Id tags for better patch tracking
  • archive/unarchive: Archive completed series (creates dated tags, deletes branches)
  • patches: Show patches in a specific series/version

Advanced Workflow Example

Here’s how the series feature shines in a real-world scenario:

  1. Initial submission:
   git checkout my-feature
   patman series add -m  # Mark commits with Change-Ids
   patman series send

  1. Address review feedback:
   patman series inc  # Creates my-feature-v2 branch
   # Make your changes...
   patman series send

  1. Track progress:
   patman series progress  # Shows review status
   patman series gather -Cc   # Pulls in Reviewed-by tags, shows comments

  1. Final acceptance:
   patman series archive  # Clean up, create tags

Database-Driven Benefits

The series feature maintains a SQLite database (typically in ~/.config/patman/) that persistently tracks:

  • Series metadata and descriptions
  • Version relationships between branches
  • Patchwork links and IDs
  • Patch Change-Ids for reliable tracking
  • Review status and gathered tags

This database approach means you can switch between projects, reboot your machine, or work on multiple series simultaneously without losing context.

Integration with Existing Workflows

The beauty of patman series is that it builds on top of the existing patman functionality you already know. All the same commit tags (Series-to, Series-cc, etc.) work exactly as before. The series feature simply adds persistent tracking and automation on top.

You can still use regular patman send for quick one-off patches, while leveraging patman series for more complex, multi-version patch series that need ongoing management.

Migration from Manual Workflows

If you’re currently managing patch series manually with git branches and spreadsheets, migrating to patman series is straightforward:

  1. Use patman series add on your existing branches
  2. Let patman discover Patchwork links with patman series autolink-all
  3. Start using patman series send instead of manual git send-email

Conclusion

The patman series feature represents a significant evolution in patch management tooling. By providing database-backed series tracking with deep Patchwork integration, it eliminates much of the manual bookkeeping that makes contributing to large projects tedious.

Whether you’re a seasoned contributor juggling multiple patch series or a newcomer looking to streamline your workflow, patman series offers a compelling upgrade to the traditional patch-by-patch approach. The investment in learning these commands pays dividends in reduced errors, better organization, and more time spent on actual development rather than patch logistics.

Try incorporating patman series into your next contribution workflow – your future self will thank you when managing v4 of that complex patch series becomes as simple as patman series inc followed by patman series send.


The patman series feature is available in recent versions of U-Boot’s patman tool (pip install patch-manager). For complete documentation, see tools/patman/patman.rst in the U-Boot source tree, or here.




Concept mailing list and patch management

If you are interested in watching the development of U-Boot Concept, consider joining the mailing list. You can do this in your web browser here, or send an email with ‘subscribe’ in the subject to concept-join@u-boot.org. If you are able to review patches or contribute your own, please do!

Also the patchwork server is up and running so future patches will be visible there. This also helps to collect reviews, etc.

You may also find it interesting to look at the merge requests.

Development goals

With U-Boot Concept, the goal is to continue the transformation of the code base so that it remains relevant in future, even if only as fodder for new developments. Keys goals remaining for 2025 are:

  • Continue evolution of standard boot
  • Get the EFI app fully functional on x86 and ARM
  • Broaden the expo feature set a little, e.g. a text editor
  • Keep up with the development of the Flat Image Tree (FIT) specification
  • Create packages for QEMU and EFI (including versions more focussed on secure boot)
  • Take a look at what it would take to support Rust code
  • Build out the new filesystem and file uclasses (better Linux compatibility?)

Not all of these will get done, but we’ll see what happens!




EFI app on ARM hits a milestone

The EFI app on x86 has supported booting for a while. With a recent 19-part series, the EFI app can now also boot an OS on ARM. This uses standard boot and the standard extlinux boot flow.


The Core Fixes

To successfully hand off control from the EFI environment to a new operating system, a few key steps must happen in the right order.

  • Exit Boot Services: The most important change is ensuring that U-Boot calls ExitBootServices() before it jumps to the OS kernel. This is a fundamental requirement of the EFI specification. It tells the underlying firmware that its boot-time services (like memory allocation, device I/O, etc.) are no longer needed, effectively handing exclusive control of the hardware over to the operating system.
  • Pass the Memory Map: An operating system needs to know the physical layout of the memory. This series adds the logic to obtain the EFI memory map and write the physical memory information into the Flattened Device Tree (FDT). This allows the Linux kernel to understand the memory layout and manage it correctly.
  • Improved Keyboard Compatibility: On some real-world hardware, such as certain Qualcomm laptops with USB keyboards, simply waiting for a keypress isn’t enough. The underlying system needs time to process other events for the keyboard input to register. The EFI serial driver is updated to use a periodic timer, making the console much more reliable on these devices.
  • General Tidying Up: Alongside these major functional updates, the series includes a lot of valuable code maintenance, such as correcting typos, reorganizing Kconfig options, and standardizing the format of EFI GUID declarations.

Tested and Ready

To ensure this new capability remains robust, the patch series also introduces a new continuous integration (CI) test. We now automatically build the efi-arm_app64 target and use it to boot a full Ubuntu 25.04 image on a QEMU virtual machine in the sjg lab. This provides a strong safeguard against future regressions.


A Note for Testers on QEMU

If you’re planning to test this yourself using QEMU, there’s an important detail to be aware of. The changes do not work correctly with QEMU 8.2 when booting Ubuntu 24.04, as the kernel fails very early in the process with a regime_is_user error.

The good news is that this has been fixed in QEMU 9.2 and newer. So, make sure you’re using an up-to-date version of QEMU for your testing! You can read more about the QEMU issue in this bug report.


Next up?

Work on the app continues, with the goal of having it boot the OS using EFI as well.




Spring Cleaning: Refactoring the U-Boot Test Suite for a Brighter Future


A robust and efficient test suite is the backbone of a healthy open-source project. It gives developers the confidence to add new features and refactor code without causing regressions. Recently, we’ve merged a significant 19-patch series that begins a much-needed cleanup of our Python test infrastructure, paving the way for faster, more reliable, and more parallelizable tests.

The Old Way: A Monolithic Setup

For a long time, many of our tests, particularly those for the bootstd (boot standard) commands, have relied on a collection of disk images. These images simulate various boot scenarios, from Fedora and Ubuntu systems to ChromiumOS and Android partitions.

Our previous approach was to have a single, monolithic test called test_ut_dm_init_bootstd() that would run before all other unit tests. Its only job was to create every single disk image that any of the subsequent tests might need.

While this worked, it had several drawbacks:

  • Inefficiency: Every test run created all the images, even if you only wanted to run a single test that didn’t need any of them.
  • Hidden Dependencies: The relationship between a test and the image it required was not explicit. If an image failed to generate, a seemingly unrelated test would fail later, making debugging confusing.
  • No Parallelism: This setup made it impossible to run tests in parallel (make pcheck). Many tests implicitly depended on files created by other tests, a major barrier to parallel execution.
  • CI Gaps: Commands like make qcheck (quick check) and make pcheck were not being tested in our CI, which meant they could break and remain broken for long periods.

A New Direction: Embracing Test Fixtures

The long-term goal is to move away from this monolithic setup and towards using proper test fixtures. In frameworks like pytest (which we use), a fixture is a function that provides a well-defined baseline for tests. For us, this means a fixture would create a specific disk image and provide it directly to the tests that need it, and only those tests.

This 19-patch series is the first major step in that direction.


The Cleanup Process: A Three-Step Approach

The series can be broken down into three main phases of work.

1. Stabilization and Bug Squashing

Before making big changes, we had to fix the basics. The first few patches were dedicated to getting make qcheck to pass reliably. This involved:

  • Disabling Link-Time Optimization (LTO), which was interfering with our event tracing tools (Patch 1/19).
  • Fixing a memory leak in the VBE test code (Patch 2/19).
  • Standardizing how we compile device trees in tests to fix path-related issues (Patch 3/19).

2. Decoupling Dependent Tests

A key requirement for parallel testing is that each test must be self-contained. We found a great example of a dependency where test_fdt_add_pubkey() relied on cryptographic keys created by an entirely different test, test_vboot_base().

To fix this, we first moved the key-generation code into a shared helper function (Patch 6/19). Then, we updated test_fdt_add_pubkey() to call this helper itself, ensuring it creates all the files it needs to run (Patch 7/19). This makes the test independent and ready for parallel execution.

3. Preparing for Fixtures by Refactoring

The bulk of the work in this series was a large-scale refactoring of all our image-creation functions. Previously, functions like setup_fedora_image() took a ubman object as an argument. This ubman is a function-scoped fixture, meaning it’s set up and torn down for every single test. This is not suitable for creating images, which we’d prefer to do only once per test session.

The solution was to change the signature of all these setup functions. Instead of: def setup_fedora_image(ubman):

They now accept the specific dependencies they actually need: def setup_fedora_image(config, log, ...):

This was done for every image type: Fedora, Ubuntu, Android, ChromiumOS, EFI, and more. This change decouples the image creation logic from the lifecycle of an individual test run, making it possible for us to move this code into a session-scoped fixture in the future.

What’s Next?

This series has laid the groundwork. The immediate bugs are fixed, tests are more independent, and the code is structured correctly. The next step will be to complete the transition by creating a session-scoped pytest fixture that handles all this image setup work once at the start of a test run.

This investment in our test infrastructure will pay dividends in the form of faster CI runs, a more pleasant developer experience, and a more stable and reliable U-Boot. Happy testing! 🌱




Fixing a Devious Memory Corruption Bug in Sandbox

We’ve just merged a fix in Concept for a particularly tricky memory corruption bug in the U-Boot sandbox environment. This bug was difficult to track down, so we wanted to share the story of the investigation and the solution.

The Symptom: Mysterious Heap Corruption

The problem first appeared as random and hard-to-reproduce memory corruption in the malloc() heap. These are often the most frustrating bugs to solve, as the place where the program crashes is rarely the place where the error actually occurred. After many hours of debugging, the root cause was finally identified, and it was quite unexpected.


The Culprit: A Memory Map Collision đź’Ą

It turns out that the PCI Enhanced Allocation (EA) driver, a feature used for testing within sandbox, was mapping its simulated device memory at the 1MB physical address.

This might seem harmless, but there’s a problem. When using the vbe_abrec_os boot method in sandbox, the Linux kernel is also loaded and executed from that very same 1MB address.

The collision was triggered by a specific feature: measured boot. When enabled, the bootm_measure() command needs to read the kernel’s data to calculate its hash. To do this, it calls map_sysmem() on the kernel’s memory region at 1MB. However, because the PCI EA driver had claimed that address space, the call was “hijacked.” Instead of mapping and reading RAM where the kernel was supposed to be, U-Boot was unknowingly reading from the simulated PCI device!

This led to the measurement being performed on incorrect data and, through a complex chain of events, corrupted the heap, causing crashes later on.


The Fix: A Multi-Pronged Approach

The solution was implemented in a series of five patches that not only fix the bug but also add safeguards to prevent similar issues in the future.

1. Move the PCI Space

The core of the fix was to move the PCI EA test space out of the way. Patch 2/5 relocates it from 0x100000 (1MB) to a much safer address at 0x20000000, well clear of any system RAM used by sandbox. This resolves the memory collision entirely.

2. Make Partial Maps a Fatal Error

A key clue during debugging was this log message: map_physmem: Warning: partial map at 100000, wanted 4, got 2000

This warning indicated that a driver asked to map a certain number of bytes but the underlying device mapping had a different size. While this might sometimes be harmless, in this case, it was a giant red flag that something was wrong.

Patch 5/5 promotes this warning to a fatal error. It now prints a “Fatal: partial map…” message and calls os_abort(). This makes the system fail loudly and immediately, which is much better than silently continuing with a corrupted state. This change will make similar bugs far easier to spot in the future.

3. Clean up Mapping Sizes

With the new fatal error in place, we had to clean up a few drivers that were requesting inexact mapping sizes. Patches 3/5 and 4/5 update the ACPI PMC driver and the PCI EA tests to request the exact size of the memory they intend to map, silencing the new error and making the code more precise.

4. A Quick Logging Fix

Finally, patch 1/5 was a small but helpful cleanup, swapping the “wanted” and “got” values in the log message, which were reversed, to avoid any future confusion.

This was a great example of how a seemingly innocuous test configuration can have far-reaching and destructive consequences. By moving the test region and hardening our memory mapping code, the sandbox environment is now more robust. Happy hacking!




Seeing is Believing: Video Support Lands for the ARM EFI App! 🎨

For a while now, U-Boot’s EFI application (efi_app) has been a handy tool, but with one noticeable difference between architectures: x86 could show things on the screen, while ARM was stuck in the dark. If you wanted a splash screen or a graphical boot menu in your ARM EFI app, you were out of luck.

Well, not anymore! A new patch series in Concept closes this gap, bringing full video output capabilities to the ARM EFI application. Let’s dive into how it works.


The Challenge: Drawing Pixels on ARM

The main hurdle for ARM video support within an EFI environment, especially in virtualized setups, is how graphics are handled. Many ARM systems, like QEMU configured with virtio-gpu, don’t provide a simple, direct-access framebuffer to which you can just write the pixel data.

Instead, they rely on the EFI Graphics Output Protocol (GOP) and specifically its Bit Block Transfer function, more commonly known as blt. The blt function is a versatile tool that can copy rectangular blocks of pixels around—from memory to the screen, from the screen to memory, or even from one part of the screen to another.

Thes series uses the blt function to enable video support. U-Boot now draws the display into an in-memory buffer and then uses a blt call to “push” that entire buffer to the visible screen.


A Quick Tour of the Changes

This feature was delivered in a series of seven patches, each building on the last.

  1. Store the GOP (Patch 1/7): The first step was foundational. The existing driver could find the GOP, but it didn’t save the pointer for later use. This patch introduces a private struct (efi_video_priv) to store the GOP handle, making it accessible after the initial probe.
  2. Implement the Blit Method (Patches 2/7 & 3/7): This is the core of the new feature.
    • A new pixel format EFI_GOT_BITBLT is recognized. When detected, the driver knows it must use blt operations instead of writing to a direct framebuffer.A video_sync operation is added, which calls the GOP’s blt function to update the display from U-Boot’s internal framebuffer. An enum, efi_gop_blt_op, was also added to make the code clearer.
  3. Enable a Full Boot Experience (Patches 5/7 & 7/7): What good is a screen if you can’t boot an OS? This series also enables the necessary configs to make the ARM EFI app a fully functional bootloader.

    • CONFIG_BOOTSTD_FULL is now enabled, allowing the app to automatically find and boot an operating system.
    • CONFIG_BOARD_EARLY_INIT_R is turned on to ensure block devices are available.
    • The VBE-OS boot method is also enabled, providing another way to locate and boot an OS.

  4. Supporting Cast (Patches 4/7 & 6/7): A couple of smaller patches provide essential plumbing. The QEMU build scripts were adjusted to prevent conflicts when using multiple disk images, and a fix was added to oftree_dispose() to allow builds where CONFIG_OF_LIVE is disabled.

What This Means for Developers and Users

With these changes, the U-Boot EFI application on ARM is now on par with its x86 counterpart. You can now:

  • Display splash screens for a professional boot experience.
  • Utilize a full graphical console.
  • Use bootstd to automatically scan for and boot an OS from connected block devices.

This makes the ARM efi_app far more useful, particularly in virtualized environments where virtio-gpu is the standard. It provides a complete, visually-enabled pre-boot environment straight out of the box. Go ahead and give it a try with the efi-arm_app64_defconfig! 🚀




Making CI Work for You: New Controls for U-Boot’s GitLab Pipeline

Continuous Integration (CI) is the backbone of a large project like U-Boot, ensuring that every change is tested against a huge matrix of boards and configurations. While this comprehensive testing is vital for quality, it can also be time-consuming. When you’re focused on a specific feature, waiting for a full “world build” to complete can slow down your development cycle.

A little series of patches introduces several improvements to U-Boot’s GitLab CI, giving developers powerful new tools to get faster, more targeted feedback.


## A New Toolbox for CI Control

This series is all about empowering developers to tailor CI runs to their specific needs. Instead of a one-size-fits-all pipeline, you can now easily select which parts you want to run.

Stage-Level Control

You can now disable entire stages of the CI pipeline using simple variables. If your changes don’t affect the world build, you can just turn it off for your test push:

# Push to the 'ci' remote, disabling the world_build stage
$ git push ci -o ci.variable=WORLD_BUILD=0

Similar variables are available for the other main stages:

  • TEST_SUITES=0: Disables the collection of miscellaneous tests (pylint, docs, etc.).
  • TEST_PY=0: Disables all test.py jobs.

Granular test.py Selection

The test.py stage runs U-Boot on emulated hardware and is often the most critical part of the pipeline. The TEST_PY variable offers fine-grained control here. You can use it to run:

  • All tests for a single board: TEST_PY=sandbox
  • A single, specific test job: TEST_PY='sandbox with clang test.py'

This is incredibly useful when you’re working on a single board and want to avoid running tests for dozens of others.


Laser-Focused Testing with TEST_SPEC

For the ultimate level of precision, the new TEST_SPEC variable lets you pass a test specifier directly to pytest. This allows you to run a single test or a specific group of tests across all relevant jobs.

For example, if you’re working on the bootstd command, you can run only the bootstd tests in CI with:

# Run only tests with 'bootstd' in their name
$ git push ci -o ci.variable=TEST_SPEC=bootstd

This can reduce a test run from 30 minutes to just a few minutes, providing a rapid feedback loop for iterative development.


A Cleaner, More Consistent CI

Beyond adding new features, the series also includes cleanups that make the CI configuration more consistent and maintainable. Stage names like world build have been standardized to world_build, and redundant shell logic has been removed in favor of letting GitLab’s own rules: engine handle job execution.

These small changes improve the readability and reliability of the CI infrastructure, making life easier for both developers and maintainers. By giving developers more control over their CI runs, these updates promise to make the development process faster and more efficient.




Supercharging FITs: U-Boot’s New Two-Stage Boot Capability

The Flattened Image Tree (FIT) is at the heart of modern U-Boot booting, providing a flexible and verifiable way to package kernels, ramdisks, and devicetrees. A new series introduces a significant enhancement to how U-Boot processes FITs, enabling a powerful two-stage boot process. This allows a “load-only” FIT to configure the system (like setting up a devicetree) before a second FIT loads the operating system.

This capability unlocks more flexible and dynamic boot scenarios, especially for systems where the hardware configuration (devicetree) and the OS have different update cadences or sources.


The Concept: Load-Only and Restartable Booting

The core of this feature revolves around two new concepts:

  1. Load-Only Configurations: A FIT configuration can now be marked as “load-only.” When U-Boot’s bootm command processes such a configuration, it understands that there might not be a kernel to boot. Instead of failing, it will load any specified components—like a devicetree or other binaries—into memory and then gracefully exit with a special status code (-ENOPKG).
  2. Restartable bootm: The bootm command, which orchestrates the boot process, now has a new restart subcommand. Unlike start, which clears all previous state, restart continues the boot process while preserving the components that have already been loaded.

When combined, these features allow for a sequence like this:

  1. bootm start <fit1_addr>: U-Boot loads a load-only FIT. It finds no OS but successfully loads a devicetree into memory.
  2. bootm restart <fit2_addr>: U-Boot loads a second, standard FIT. It finds the OS kernel and ramdisk. Because this is a restart, it retains the devicetree from the first step.
  3. bootm go: The kernel is booted using the devicetree from the first FIT and the kernel/ramdisk from the second.

Key Changes in the Series

Bringing this feature to life required a fair amount of refactoring:

  • Core bootm Logic: The bootm state machine was updated to recognize “load-only” configurations and to handle the new restart state, ensuring that previously loaded images (like the devicetree) are not discarded.
  • FIT Image Loading: The function fit_image_load() was enhanced to correctly handle the “load-only” property and return the new -ENOPKG error code when an OS is not present in such a configuration.
  • Function Refactoring: Several key functions in the boot flow, like boot_get_ramdisk() and boot_get_fdt(), were refactored for better clarity and more consistent error handling, making the code easier to maintain.
  • Comprehensive Testing: The FIT test suite in Python was significantly refactored and expanded. New tests were added to validate the “load-only” case and the two-stage boot process with a second FIT, ensuring the new functionality is robust.
  • Documentation: The bootm command’s documentation has been fleshed out to describe the boot flow, the new restart subcommand, and all the other states, making this powerful command easier for developers to understand and use.

This series significantly enhances the flexibility of U-Boot’s FIT handling, paving the way for more sophisticated and modular boot architectures.




Taming Build Complexity: Introducing Config Fragments in Buildman

As U-Boot’s support for hardware grows, so does the complexity of managing build configurations. A single board might require several build variations—for example, one with network support and one without, or a standard build versus one tailored for Android booting. Historically, managing these variations often meant duplicating large defconfig files, a maintenance headache waiting to happen.

A recent patch series, with contributions from Heinrich Schuchardt and Simon Glass, introduces a powerful and elegant solution to this problem by formally integrating configuration fragments into buildman, U-Boot’s indispensable build-testing tool.


What are Config Fragments?

A config fragment is a small, targeted file containing just a few Kconfig options. For instance, an acpi.config fragment might contain only one line:

CONFIG_ACPIGEN=y

Instead of creating a whole new qemu-riscv64_smode_acpi_defconfig, you can now apply this small fragment on top of the existing qemu-riscv64_smode_defconfig to generate a new build variant on the fly. This approach is cleaner, reduces duplication, and makes configurations easier to manage.

While the underlying Kconfig system has supported this for a while, buildman was unaware of this mechanism—until now.


Official buildman Support: Two New Approaches

The new series enhances buildman by providing two ways to work with fragments.

The Manual Approach: --fragments

For quick tests or one-off builds, buildman now has a --fragments command-line option. You can pass a comma-separated list of fragment files to apply to your build.

For example, to build qemu-riscv64_smode with ACPI support, you can now run:

tools/buildman/buildman -k qemu-riscv64_smode --fragments acpi.config

buildman handles the rest, correctly merging the fragment with the board’s base defconfig.


The Automated Build Matrix: --extend and .buildman

The real impact of this series lies in its ability to automate the discovery and building of these variations. This is achieved through a new file format and a new command-line flag.

A new file, configs/extended.buildman, now defines the relationships between boards and their valid fragments, creating what are called “extended boards.”

The syntax is simple and powerful. You can define a build variant and specify which boards it applies to using wildcards or by checking for specific CONFIG options in the base defconfig.

Here’s an example from the series that creates ACPI-enabled variants for all RISC-V QEMU boards:

# Build RISC-V QEMU builds with ACPI
name: acpi
fragment: acpi
targets:
  qemu-riscv*

To tell buildman to parse this file and build all the resulting extended boards, you simply add the -X (or --extend) flag to your command. buildman will then discover that acpi,qemu-riscv64_smode is a valid new target and add it to its build queue.


Continuous Integration for All Variants

This isn’t just a tool for local development. The final piece of this series integrates the -X flag directly into U-Boot’s GitLab CI. This means that these “extended board” configurations are now built and tested automatically as part of the “world build,” guaranteeing that build variations are treated as first-class citizens and don’t suffer from bit-rot. This last patch is pending, due to some last-minute issues.

By formalizing the concept of config fragments, this series makes the U-Boot build system more robust, easier to maintain, and better equipped to handle the diverse configurations required by the embedded ecosystem.