A Three-Phase PXE: Cleaning Up the Boot Process

The PXE/extlinux boot mechanism is a cornerstone of U-Boot’s standard boot flow. It parses a configuration file (like extlinux.conf), presents a menu, and loads the kernel, initrd, and device tree for the chosen option. A typical configuration file looks like this:

menu title Boot Menu
timeout 50
default linux

label linux
    menu label Ubuntu Linux
    kernel /vmlinuz
    initrd /initrd.img
    fdt /dtb/board.dtb
    fdtoverlays /dtb/overlay1.dtbo /dtb/overlay2.dtbo
    append root=/dev/sda1 quiet

While functional, the traditional implementation relied heavily on callbacks: as the parser encountered a file path (like /vmlinuz above), it would immediately call a function to load it.

We have submitted a series of 26 patches that introduces a new, cleaner API for this process.

The Problem with Callbacks

The callback-based approach mixes parsing logic with file loading logic. This makes it difficult for a caller to know what files need to be loaded without actually loading them. It also complicates environments where file access requires special handling or where the caller wants precise control over memory layout.

Furthermore, analysing the existing parser revealed several memory leaks where token strings and menu structures were not being freed properly.

The New Three-Phase API

The new API separates the boot process into three distinct phases:

  1. Parse (pxe_parse): The configuration file is parsed into a menu structure. Instead of loading files immediately, the parser populates a list of required files (kernel, initrd, FDT, overlays) for each label.
  2. Load (pxe_load): The caller iterates over the file list and loads the files manually to their desired addresses. The pxe_load() helper is then called to record the size and location of each loaded file.
  3. Boot (pxe_boot): Once everything is loaded, this function performs the final boot sequence using the pre-loaded file information.

This structure gives callers complete visibility and control. For example, a caller can now inspect the menu to see which files are required for a specific boot option before deciding where to load them.

Dealing with Includes

Configuration files often use the include directive to pull in other configs. In the new model, includes are not processed automatically. Instead, parsing populates an includes list. The caller is responsible for loading these included files and calling pxe_parse_include() to merge them into the menu. This explicit handling mirrors the control provided for boot files.

Improvements and Testing

Beyond the new API, this series includes several other improvements:

  • Memory Leaks: Fixed leaks in token parsing, menu labels, and FDT overlay paths. These were trivial to find with the recent malloc additions.
  • Explicit Sizing: The parser now accepts a file size parameter, removing the requirement for configuration files to be null-terminated strings.
  • Documentation: Comprehensive documentation for the new API has been added to doc/develop/bootstd/pxe_api.rst.

Some recently added tests, such as pxe_test_sysboot_norun(), continue to verify the traditional end-to-end functionality via the sysboot command. We added a new test, pxe_test_files_api_norun(), to verify the new callback-free workflow. It parses a configuration file, manually loads the kernel, initrd, and device tree overlays, records their positions via pxe_load(), and then simulates a boot. This new test also explicitly checks for memory leaks, ensuring that pxe_cleanup() properly frees all allocated memory, including the new file lists.

While these changes increase code size slightly (around 300 bytes on Thumb2 mostly fixing memory leaks and avoid access outside the file bounds), the result is a more robust, flexible, and leak-free PXE subsystem.




Taming the Beast: Refactoring Buildman for Maintainability

Buildman is the Swiss Army knife of U-Boot development. It handles the heavy lifting of building hundreds of boards in parallel, fetching the correct toolchains, and—perhaps most importantly—analysing the impact of your patches across git history. Whether you are checking for code bloat or verifying that a refactor doesn’t break a board you don’t own, buildman is the tool that makes it possible.

However, if you have ever peered into the internals of buildman, you might have noticed that the Builder class had become… well, enormous. Over the years, it accumulated responsibilities ranging from managing threads and file I/O to formatting console output and tracking build statistics.

A recent series of 18 patches to address this technical debt. The goal: split the monolithic Builder class into smaller, more focused components.

The Problem: A Class That Did Too Much

The Builder class in tools/buildman/builder.py had grown to over 2200 lines of code. It was handling two distinct responsibilities:

  1. Orchestrating the Build: Managing threads, checking out commits, running make, and saving artifacts.
  2. Reporting Results: Processing build outcomes, calculating size deltas, tracking error lines, and formatting the summary for the user.

These two concerns were tightly coupled, making the code hard to read, test, and maintain.

The Solution: Introduce ResultHandler

This refactor extracts the result-processing logic (~900 lines) into a new class called ResultHandler. The separation is clean:

  • Builder focuses on the act of building (I/O, git operations, process management).
  • ResultHandler focuses on the presentation of the build (summaries, error reporting, bloat analysis).

How We Got There

Refactoring a core tool like buildman is risky—regressions here can break workflows for developers everywhere. We took a stepwise approach:

  1. Extract Data Structures: We moved configuration handling (Config) and build outcomes (Outcome, BoardStatus, ErrLine) into their own modules (cfgutil.py, outcome.py). This broke the circular dependencies that often plague monolithic classes.
  2. Formalise Options: Instead of passing a dozen boolean flags (like show_errors, show_bloat) around individually, we grouped them into a DisplayOptions named tuple.
  3. Create the Handler: We introduced ResultHandler and progressively moved display methods into it—starting with simple size summaries and moving up to complex error delta calculations.
  4. Clean Up: Finally, we enforced Python naming conventions by adding underscore prefixes to private members (self.col became self._col), clarifying the public API.

The Result

The Builder class is now down to ~1200 lines—a much more manageable size. The display logic lives in tools/buildman/resulthandler.py, where it can be evolved independently.

While this doesn’t change the user-facing behaviour of buildman today, it makes the codebase significantly healthier and ready for future improvements. Sometimes the most important feature is code you can actually understand!




Weighing the Cost: An Update on Ext4l Code Size

A recent series in Concept enables ext4l for an ARM board, finally allowing us to make a concrete comparison between the code size of this new Linux-ported driver and the existing U-Boot implementation.

Here is a short note on what we found.

The “Linux is Large” Reality

The first observation is that the Linux kernel no longer operates under strict code-size constraints. In the early days of embedded Linux, there was immense pressure to keep footprints tiny—projects like uClinux aimed to run in very limited RAM. Today, even embedded CPUs often have gigabytes of RAM, and they run the full kernel without blinking.

This shift shows through in the code. One striking example: ext4l contains about 20KB just in error messages and warnings. To put that in perspective, those strings alone take up roughly the same amount of space as the entire code size of the existing, legacy ext4 implementation in U-Boot!

Shoehorning a modern Linux filesystem driver into a bootloader was always going to involve trade-offs. Now, we have the numbers to quantify them.

The Weigh-in: Early Results

So, how heavy is ext4l? We ran comparisons on Thumb2 (specifically the firefly-rk3288).

  • Legacy Ext4: ~7KB (Read-Only) / ~21KB (Read-Write)
  • New Ext4l: ~98KB (Read-Only) / ~137KB (Read-Write)

There is no getting around it: ext4l is significantly heavier.

Is the Size Worth It?

The short answer is: Yes, because the legacy driver is becoming obsolete.

U-Boot’s existing ext4 implementation is losing utility in the modern world. Most modern Linux distributions enable metadata checksums (metadata_csum) by default, rendering their filesystems unmountable by the current U-Boot driver. While the legacy driver has basic journaling, it lacks support for fast-commits and other features required to interact safely with real-world partitions.

Despite the size increase, ext4l provides feature-parity with Linux, allowing U-Boot to reliably interact with modern filesystems.

The Path Forward: Top-Down or Bottom-Up?

We are currently taking a “Top-Down” approach: porting the full-featured Linux driver (ext4l) and then looking for size reductions. There are likely areas we can trim, but we must be careful not to spoil one of ext4l‘s major benefits: a small code delta compared to Linux, which makes maintenance easier.

However, there is a potential “Bottom-Up” path: we could enhance the legacy ext4 driver just enough to support required features like checksums, without importing the full Linux architecture. The end result would likely land somewhere in the middle—smaller than ext4l, but larger than the current legacy driver.

The downside? It creates a distinct codebase that requires its own maintenance, separate from the kernel.

For now, ext4l gives us compatibility today, but the hunt for optimization continues.




Modernizing Buildman: A Case Study in AI-Assisted Refactoring


U-Boot’s suite of Python tools—including buildman, patman, and binman—are critical parts of our development workflow. However, like any long-lived software project, technical debt accumulates. Buildman in particular was written a while ago, without much use of pylint and has grown significantly over the years. The accumulated pylint warnings, inconsistent naming conventions, and a monolithic structure make maintenance somewhat difficult.

On the other hand, cleaning up Python code is error-prone and not a lot of fun! A few recent series (board, general, builderthead and test.py) has shown a different path: extensive use of AI as a co-developer to accelerate the cleanup.

The Problem: Entropy

The buildman code has several issues typical of older Python codebases:

  • Monolithic Class: The TestBuild class had become a dumping ground for all tests, making it hard to navigate.
  • Legacy Formatting: Reliance on % string formatting instead of modern f-strings.
  • PEP 8 Violations: A mix of CamelCase and snake_case method names, missing docstrings, and indentation inconsistencies.
  • Pylint Noise: A high volume of warnings that obscured actual logic errors.

The AI Advantage

Refactoring code to fix style issues is often tedious and error-prone. For this series, we used Claude Opus 4.5 to handle the heavy lifting. The AI was particularly effective at:

  1. Mechanical Translations: Converting hundreds of lines from % formatting to f-strings and renaming variables from CamelCase to snake_case to match PEP 8 standards.
  2. Logic Extraction: Helping to identify seams in the code where the massive TestBuild class could be split into logical components.
  3. Docstring Generation: Analyzing test methods and generating accurate, compliant docstrings where they were missing.

By offloading these tasks, we can focus on the architectural decisions while the AI handled the syntax updates. Each commit in the series carries a Co-developed-by tag, acknowledging the AI’s contribution to the code generation.

Most importantly, this clean-up can be largely a background task. In between other work, switch back to the clean-up terminal every now and then and spend a few minutes looking at what was done and deciding what to do next.

Key Architectural Improvements

The most significant change in the latest series is the decomposition of the TestBuild class.

Previously, TestBuild handled everything from output parsing to toolchain management. Now it is split into focused classes:

  • TestBuildBase: Common setup and teardown logic.
  • TestBuildOutput: Tests specific to summary display and error formatting.
  • TestBuildBoards: Tests regarding board selection logic.
  • TestBuildConfig: Tests for Kconfig manipulation.
  • TestBuildMisc: Process limits and other edge cases.

This separation of concerns makes the tests easier to read and understand.

The other series linked have adopted a similar approach – splitting code into separate functions to make it easier to read and maintain.

AI coding tools have a clear advantage in refactoring. They can fairly reliably extract code into functions and make other adjustments that are beyond a mere ‘refactor’ tool in VS Code or Eclipse, for example. It is also easy to go back to an earlier commit in the series to bring in a change, then continue the rebase and have the AI deal with merge conflicts.

Conclusion

This cleanup so far brings most of the buildman code into full pylint compliance (with some pragmatic disable-directives where necessary). It serves as a good example of how AI tools can be leveraged to modernize legacy infrastructure code in the U-Boot project, turning a multi-day refactoring slog into a manageable, efficient process.




Faster Tests and Better Debugging: Improvements to Malloc and test/py


Developing for U-Boot often involves chasing down elusive memory leaks and waiting for long test suites to finish. A recent series of 29 patches is aimed squarely at improving the developer experience in these areas.

This series introduces powerful new malloc debugging tools, optimises the video subsystem, and significantly improves the performance of the test/py infrastructure.

Deep Dive into Malloc Debugging

Finding memory leaks in a bootloader can be painful. This series adds several features to the malloc subsystem, particularly for sandbox, to make this process more transparent.

Malloc Traffic Log

A new logging feature records every malloc, free, and realloc call into a circular buffer. This includes the pointer address, allocation size, and the caller’s backtrace.

You can control this via the new malloc log command:

=> malloc log start
Malloc logging started
=> ... run commands that might leak ...
=> malloc log stop
Malloc logging stopped
=> malloc log
Malloc log: 29 entries (max 524288, total 29)
 Seq  Type              Ptr       Size  Caller
----  --------  ----------------  --------  ------
   0  free              16a016e0         0  free_pipe_list:2001  -parse_stream_outer:3208 -parse_file_outer:3300
   1  alloc             16a01b90        20  hush_file_init:3277  -parse_file_outer:3295 -run_pipe_real:1986
...

Each entry shows the operation type, the address and size and the caller trace, so you can figure out where it happened.

File Output for Heap Dumps

To make comparing heap states easier, new functions malloc_dump_to_file() and malloc_log_to_file() allow you to write the heap state directly to a file on the host system (when running U-Boot sandbox). This enables a simple workflow for finding leaks:

  1. Dump heap to before.txt
  2. Run your test case
  3. Dump heap to after.txt
  4. Use diff or comm on the host to identify pointers that persist.

Performance Improvements

Video and Truetype Optimization

Rendering text on the video console was identified as a performance bottleneck during testing.

  • Truetype Scratch Buffer: The stb_truetype library previously performed around 5 allocations per character. We added a pre-allocated scratch buffer, drastically reducing malloc pressure.
  • Full-line Copy: The video_flush_copy() function is now optimised to detect full-line damage, allowing for single memcpy calls instead of looping pixel-by-pixel or small chunks.

Accelerating test/py

Running the full test suite can be CPU intensive. This series addresses inefficiencies in how test/py handles console output.

  • VT100 Filtering: The logic to filter escape sequences was previously O(N^2). It has been optimised to filter only new data, significantly reducing overhead on verbose tests.
  • CPU Usage: A tiny delay has been added before polling the console pipe to allow data to accumulate (up to 4KB). This simple change reduced CPU usage by approximately 30% during intensive output operations.

Additional Features

  • Gprof Support: You can now build sandbox with GPROF=1 to generate profiling data (gmon.out) for analysis with standard GNU tools.
  • Runtime Mcheck Disable: A new -M flag allows you to disable mcheck heap protection at runtime, useful when the overhead interferes with specific timing-sensitive tests.

These changes make the U-Boot sandbox a faster, more observable environment for development!




Ext4l: Bringing Full Write Support to the Linux-Ported Filesystem

The effort to modernise U-Boot’s filesystem support continues with a major update to ext4l—the new ext4 driver ported directly from Linux. A recent series series of 30 patches that brings full write capabilities to the driver.

So far ext4l has only supported reading. With this series, the driver now supports the full lifecycle of file management, including file creation, modification, and deletion, all while using the journal for crash-safety.

What’s New?

The new series adds support for the following operations:

  • File Write: You can now write files using the journal for data integrity.
  • Deletion: Support for unlink to remove files.
  • Directories: Implementation of mkdir to create new directories.
  • Symbolic Links: Support for ln to create symlinks.
  • Renaming: Full support for renaming and moving files and directories.

Additionally, unlike the legacy ext4 driver, ext4l supports metadata_csum checksums, allowing U-Boot to interact with modern ext4 partitions without disabling features.

Adapting Linux Code for a Bootloader

Porting filesystem code from Linux to U-Boot presents unique challenges regarding resource management.

In the Linux kernel, the filesystem driver doesn’t need to meticulously free every single resource the moment a filesystem is unmounted; it can rely on the kernel’s broader memory management to clean up caches or reuse structures later.

U-Boot, however, operates differently. The bootloader might mount and unmount filesystems multiple times during a single session—for example, when running an extensive test suite or loading kernels and device trees from different partitions. If resources aren’t freed explicitly, memory leaks accumulate, eventually causing allocation failures.

To address this, this series includes significant infrastructure improvements that go beyond the Linux upstream code:

  • Aggressive Cleanup: We implemented thorough cleanup of journal references and buffer heads upon unmount to prevent memory leaks.
  • Safety Guards: Added safeguards to handle probe calls without explicit close calls from previous sessions.
  • Use-After-Free Prevention: Logic was added to prevent freeing buffer heads that still have active journal heads attached.

Testing and Next Steps

This series enables ext4l for sandbox testing, allowing us to validate these features rapidly without hardware. It also includes tweaks to the video console (a new --quiet_vidconsole flag) to speed up verbose test outputs.

While ext4l is now functional and usable for read/write operations, there is still work to be done before it could perhaps replace the existing ‘ext4’ driver: enabling the driver for ARM and x86 targets, fine-tuning Kconfig options to optimise code size, and expanding the documentation.

But for now, this is a significant step toward having a robust, modern, and maintainable ext4 implementation in U-Boot!

Note: This work was brought to you with the assistance of Claude and the city of Wuhan, China.




uman: A New Developer Companion for U-Boot

Developing for U-Boot often involves juggling a variety of tools: buildman for compilation, patman for patch submission, test.py for integration testing, and git for version control. While these tools are powerful individually, orchestrating them—especially when dealing with complex CI pipelines and dependencies—can be tedious.

To bridge these gaps, we are introducing uman (U-Boot Manager), a new command-line tool headed for Concept, designed to streamline the daily workflow of U-Boot developers.

uman unifies build, test, and CI interaction into a single interface, handling the “glue” logic that developers usually script themselves.

1. Taming the CI Pipeline

One of the biggest friction points in development is pushing to GitLab CI. Often, you only need to run a specific set of tests, but the default pipeline runs everything. uman ci gives you fine-grained control over what runs via git push options, without needing to manually edit YAML files.

# Push to CI, but ONLY run the pytest suite (skip world build)
uman ci -p

# Push to CI, but only run tests for the 'sandbox' board
uman ci -p sandbox

# Push and automatically create (or update) a Merge Request
uman ci -m

2. Simplified Local Testing

Running U-Boot’s pytest framework locally requires setting up environment variables, finding the correct build directory, and passing specific flags. uman py automates this. It detects your source tree, sets up paths for hooks, and handles board configuration.

# Run pytests for sandbox (automatically builds u-boot first)
uman py -b sandbox

# Run a specific test, keeping artifacts for inspection
uman py -b sandbox test_vbe -P

For developers working on C-based unit tests, uman introduces a C-Test Direct Runner (-C). If you have already set up the test environment (using -S -P), you can iterate rapidly on the C code without reloading the Python test harness every time:

# Fast iteration on a C test
uman py -C fs_test_ext4l_probe

3. Dependency Management

Testing often requires external firmware blobs (OpenSBI, TF-A, QEMU). Previously, developers had to manually hunt these down. uman setup automates fetching and building these dependencies.

# Download and install QEMU, OpenSBI, and toolchains needed for testing
$ uman setup
Setting up qemu...
All QEMU packages are installed
Setting up opensbi...
Downloading OpenSBI v1.3.1...
OpenSBI rv64: /home/sglass/dev/blobs/opensbi/fw_dynamic.bin
OpenSBI rv32: /home/sglass/dev/blobs/opensbi/fw_dynamic_rv32.bin
Setting up tfa...
Cloning TF-A...
Cloning into '/home/sglass/dev/blobs/tfa/src'...
remote: Counting objects: 6639, done
remote: Finding sources: 100% (6639/6639)
remote: Total 6639 (delta 686), reused 4523 (delta 686)
Receiving objects: 100% (6639/6639), 12.94 MiB | 10.11 MiB/s, done.
Resolving deltas: 100% (686/686), done.
Building TF-A for QEMU SBSA...
TF-A bl1: /home/sglass/dev/blobs/tfa/bl1.bin
TF-A fip: /home/sglass/dev/blobs/tfa/fip.bin
Setting up xtensa...
Downloading Xtensa dc233c toolchain...
Xtensa already configured in ~/.buildman
Xtensa toolchain: /home/sglass/dev/blobs/xtensa/2020.07/xtensa-dc233c-elf
Setup complete

4. Build Management

While buildman is excellent, uman build provides a quick wrapper for common development tasks, such as forcing a fresh build, enabling Link Time Optimization (LTO), or inspecting binary sizes immediately after a build.

# Build sandbox and show the size of the resulting binaries
uman build sandbox --size

# Build with disassembly output for debugging
uman build sandbox -O

Configuration

uman is designed to work out of the box, but it is also configurable via ~/.uman, allowing you to define persistent paths for builds, firmware blobs, and test hooks.

This tool aims to reduce the “context switching” overhead in U-Boot development, letting you focus more on the code and less on the tooling parameters.

Future

uman takes advantage of some of the newer features in Concept but it is compatible with the main tree also.

uman development is in its early stages and will expand over time. For now it is in a separate github repo. If you try it out, please send some feedback on the mailing list. For now, PRs are welcome!




Levelling Up U-Boot’s Test Infrastructure

Testing is the backbone of U-Boot development, but as the test suite grows, so does the friction involved in running it. Whether it is the time it takes to regenerate disk images or the difficulty of parsing test output in CI, there is always room for improvement.

A recent series of 9 patches in Concept smooths out several rough edges in the unit-test (ut) infrastructure. These changes focus on speed, directory cleanliness, and better automation support.

Faster Iteration with Persistence

One of the biggest time-sinks when iterating on C-based filesystem / boot tests is the Python-fixture setup. Every time you ran a test, the system generates fresh disk images, which is slow and repetitive if the images haven’t actually changed.

A new --persist (or -P) flag is now available in the Python-test runner. This tells the system to keep test artefacts—like disk images—after the run completes. Combined with updates to the test drivers, you can now re-run specific C tests immediately without waiting for the Python layer to regenerate the world.

A Cleaner Source Tree

Historically, tests tended to dump their temporary disk images (mmc1.img, spi.bin, etc.) directly into the source tree. This cluttered the workspace and requires a git-ignore rule to avoid making git status noisy.

This series moves all test-generated disk images to the persistent-data directory, i.e. inside the build directory. This keeps your source tree clean and groups all transient test-data in one predictable location.

Parallel Execution Support

Running the full unit test suite on a single core takes a while. Just the driver model tests alone (ut dm) take 13 seconds even on a fast machine. As a step towards improving this, we added support for parallel execution to the ut command.

You can now use the -P <n>:<w> flag to shard tests across multiple sandbox instances. For example, if you want to split the work across 4 workers, you can launch 4 separate sandbox processes:

./u-boot -T -c "ut -P4:0 dm"  # Worker 0
./u-boot -T -c "ut -P4:1 dm"  # Worker 1
...

The tests are distributed by index, ensuring a disjoint subset for each worker.

Automation and CLI Improvements

Several changes are included to make the ut command friendlier for both humans and machines:

  • Machine-Readable Output: A new -E flag emits explicit Result: PASS: ... or Result: FAIL: ... lines after each test. This eliminates the need for fragile regex parsing in CI scripts to determine exactly which test failed.
  • Combined Flags: You can finally combine single-character flags. Instead of typing ut -f -m -E, you can now simply run ut -fmE.
  • Manual Test Alias: The -m flag was added as an alias for -f (force), making it more intuitive to run “manual” tests.

These improvements should make the testing experience faster and less intrusive for everyday development.

What’s next?

A new tool is in the works to help productivity when running tests. Watch this space!




Safety at Scale: Introducing check and Per-Commit Validation in pickman

Automating cherry-picks with AI (as seen in our introduction to pickman) was a huge step forward for U-Boot Concept maintenance. However, as any maintainer knows, theory and practice often collide when you try to apply 260+ commits in a single session.

After several weeks of real-world use, we’ve identified three “stress points” in large-scale cherry-picking:

  1. The Detail Gap: It’s hard to see if a cherry-pick subtly mangled the code just by looking at a GitLab GUI.
  2. Ghost Commits: Effort is often wasted cherry-picking commits that were already merged via a different path.
  3. Delayed Failure: Building only at the end of a 200-commit series means catching a mistake at commit #5 requires a massive amount of backtracking.

A recent series introduces a suite of safety features to address these challenges.

1. The check Command: Catching “Mangled” Commits

The star of this update is the new check command. It provides a simple, high-level audit of the “delta” between an original commit and its cherry-picked version.

If a cherry-pick results in a significantly different file structure or line count compared to the original, pickman flags it for review:

 Cherry-pick Delta% Original   Subject
 ----------- ------ ---------- -------
 aaea489b2a     100 9bab7d2a7c net: wget: let wget_with_dns work with...
 e005799d8f      33 15e0c5e390 lmb: Remove lmb_alloc_addr_flags()
 c347fb4b1a      41 99145eec2d x86: select CONFIG_64BIT for X86_64
 12 problem commit(s) found

By adding the -d (diff) option, you can see a direct patch-to-patch comparison, making it easy to spot exactly where a conflict resolution went off the rails.

2. Move Fast, Check Often: Per-Commit Validation

We have updated the AI agent prompt to be much more proactive. Instead of blindly applying a series and hoping for the best, the agent now:

  • Checks Deltas Immediately: After every successful cherry-pick, it compares the new commit stat against the original.
  • Builds Every Commit: It runs buildman after every single commit. This ensures the tree remains in a “good” state throughout the entire process.
  • Self-Correction: If a delta is too large (>20%), the agent will now attempt to reset and manually apply the changes using git apply --3way before moving forward.

3. Smarter “Already-Applied” Detection

Duplicate commits are a constant headache. pickman now includes a robust detection system that looks for matching subjects in the target branch (ci/master) before it starts work.

It doesn’t just match text; the agent now compares actual patch content. It will only skip a commit if it can be verified as the same with good confidence, drastically reducing false positives.

Key Commands in this Series

Command Description
pickman check Identifies suspect cherry-picks based on delta ratio.
pickman check -d Shows a source code diff of the patch differences.
pickman check -v Shows detailed stats for all commits on the current branch.

Quality and Compliance

Beyond features, this series brings the pickman codebase up to production standards. We’ve enforced 80-column compliance, cleared numerous pylint warnings, and transitioned to using Named Tuples (like AgentCommit) to ensure the code is as readable as the commits it manages.

These refinements mark a step along the path to turn pickman from an experimental AI helper into a robust repository maintenance tool.




Silencing the Sphinx: Cleaner Documentation Builds

If you have ever run make htmldocs in U-Boot, you are likely familiar with the “wall of text” it produces. Between the standard Sphinx output, sub-make messages, and custom progress indicators, the build process has traditionally been very noisy.

While verbose output can be useful for debugging the toolchain itself, it is a hindrance when you are just trying to write documentation. The sheer volume of text makes it difficult to spot legitimate warnings and errors, which often get buried in the scroll.

A recent 5-part series in Concept addresses this. The goal is simple: if the build prints something, it should be something that requires your attention.

What changed?

The series cleans up the output in three specific ways:

  1. Enabling Quiet Mode: We now pass the -q flag to SPHINXOPTS and -s to the sub-make invocations. This suppresses the standard “reading sources” and “picking up dependencies” log lines.
  2. Removing Informational Clutter: We dropped the explicit print statement regarding CJK (Chinese/Japanese/Korean) font support in conf.py. The functionality remains, but we don’t need to be told about it on every run.
  3. Dropping Custom Progress Bars: The SPHINX and PARSE progress messages defined in the Makefiles have been removed.

The Result

The documentation build is now silent by default. This aligns the htmldocs target with the philosophy of the rest of the Kbuild system: silence is golden.

Now, when you run the docs build, you can be confident that any output appearing in your terminal is a warning or an error that needs to be fixed. This should make it significantly easier to maintain clean documentation and spot regressions in CI.