% Canoeboot 25.06 "Onerous Olive" released!
% Leah Rowe
% 30 June 2025

A corresponding [Libreboot 25.06](https://libreboot.org/news/libreboot2506.html)
release is also available.

Today's Canoeboot 25.06 revision is a *stable release*, whereas the previous
stable release was Canoeboot 20241207; the previous *testing* release was
Canoeboot 25.04, and this releases fixes a few bugs. The codename for this release
is *Onerous Olive*.

<img tabindex=1 class="r" src="https://av.canoeboot.org/t60logo.jpg" /><span class="f"><img src="https://av.canoeboot.org/t60logo.jpg" /></span>

This release was built on the latest Debian 12.10 Bookworm release, as of
this day. It was also build-tested successfully on the latest Arch Linux updates
as of 26 June 2025.

New schedule and version numbers
-------------------------------

This change in version release scheme was previously reported in the news
post announcing Canoeboot's new [formal release schedule](schedule.md). As per
that article, the next stable release will be Canoeboot 25.06, in June 2025.

Regarding the changelog
--------------------

The Canoeboot 25.04 releases were essentially RCs (release candidates) of
the Canoeboot 25.06 release, given the [revised release schedule](revisions.md).

The focus since Canoeboot 25.04 has been on fixing bugs, while making as few
breaking changes as possible, ideally none; this also means that fewer boards
were added, and fewer features were added. This is because major works are
done right up until RCs, about two months before official release, and then
bugs are fixed between then and the release; this changelog reflects that.

The [original schedule](schedule.md) created *four* annual releases: YY.04, YY.06,
YY.10 and YY.12. 04 and 10 being testing releases, leading up to 06 and 12. These
numbers refer to the month of the year, and YY represents the year.

The revised schedule changed this to *two* releases, with RCs that get deleted
after the stable release comes out; 25.04 shall be retained on rsync, but it
is retroactively (and informally) referred to as "Canoeboot 25.06 RC0". This
explanation has been provided, for context.

Open source BIOS/UEFI firmware
----------------------------

<img tabindex=1 class="r" src="https://av.vimuser.org/x200-uboot.jpg" /><span class="f"><img src="https://av.vimuser.org/x200-uboot.jpg" /></span>

Canoeboot is a free/open source BIOS/UEFI replacement on x86 and ARM, providing
boot firmware that initialises the hardware in your computer, to then load an
operating system (e.g. Linux/BSD). It is specifically
a *[coreboot distribution](../docs/maintain/)*,
in the same way that Debian is a Linux distribution. It provides an automated
build system to produce coreboot ROM images with a variety of payloads such as
GRUB or SeaBIOS, with regular well-tested releases to make coreboot as easy
to use as possible for non-technical users. From a project management perspective,
this works in *exactly* the same way as a Linux distro, providing a source-based
package manager (called lbmk) which patches sources and compiles coreboot images.
It makes use of [coreboot](https://www.coreboot.org/) for hardware initialisation,
and then a payload such as [SeaBIOS](https://www.seabios.org/SeaBIOS)
or GRUB to boot your operating
system; on ARM(chromebooks) and certain x86 mainboards, we provide *U-Boot* (as
a coreboot payload), which provides a lightweight UEFI implementation..

Summarised list of changes
-------------------------

### Board support

The following boards have been added since the Canoeboot 25.04 release:

* Dell OptiPlex 7010 SFF desktop
* Dell OptiPlex 9020 SFF desktop
* Dell OptiPlex 9020 MT desktop
* Dell Latitude E5420 laptop
* Dell Latitude E5520 laptop
* Dell Latitude E5530 laptop
* Dell Latitude E6220 laptop
* Dell Latitude E6230 laptop
* Dell Latitude E6320 laptop
* Dell Latitude E6330 laptop
* Dell Latitude E6420 laptop
* Dell Latitude E6430 laptop
* Dell Latitude E6520 laptop
* Dell Latitude E6530 laptop
* HP Elite 8200 SFF desktop
* HP Elite 8300 CMT desktop
* HP Elite 8300 USDT desktop
* Dell Precision T1650 desktop
* Lenovo ThinkPad T420 laptop
* Lenovo ThinkPad T420s laptop
* Lenovo ThinkPad T430 laptop
* Lenovo ThinkPad T440p laptop
* Lenovo ThinkPad T520 laptop
* Lenovo ThinkPad T530 laptop
* Lenovo ThinkPad W530 laptop
* Lenovo ThinkPad W541 laptop
* Lenovo ThinkPad X220 laptop
* Lenovo ThinkPad X230 laptop
* Lenovo ThinkPad X230T laptop

These boards use Intel ME, and they're inherited from Libreboot; in Canoeboot,
we tell the user to avoid re-flashing the original Intel ME, but still
disable the ME after early bringup, using a specially modified Intel 
Flash Descriptor that sets the altMeDisable (HAP) bit - additionally, we
use Soft Temporary ME Disable in coreboot.

This is functionally equivalent to running `me_cleaner`, in that only the
ROMP and BUP modules are executed; the ME initialises itself but then shuts
down, during early boot. Using `me_cleaner` itself cannot be done in Canoeboot,
because that would mean either distributing (directly or indirectly) or
otherwise handling `me.bin`, which would go against Canoeboot policy.

Therefore, when installing Canoeboot on these newer machines, you can flash
just the BIOS region of the flash, and the IFD/GbE regions. In this way,
Canoeboot still provides a fully free coreboot distro on these machines.

This differs greatly from the Libreboot implementation, which downloads an
Intel ME at build time, shrinks it using mecleaner, and shrinks the ME region,
enlarging the BIOS region; as a result, Libreboot can build full images, where
all of the flash can be reprogrammed without issue.

This is because of differences in Libreboot and Canoeboot policies, which you
can learn by reading their policies:

* [Libreboot Binary Blob Reduction Policy](https://libreboot.org/news/policy.html)
* [Canoeboot Binary Blob Extermination Policy](policy.md)

Canoeboot provides more information about this in the [following
guide](../docs/install/ivy_has_common.md), which is also referenced in
the new Canoeboot installation instructions for these machines.

This change has been made, so as to expand the hardware support by Canoeboot,
while still complying with its zero-blob policy. Canoeboot *remains* a
fully *free software* coreboot distribution.

The HP EliteBook laptops (from Libreboot) were not added yet, because they
use EC firmware in-flash, and a reliable method to re-use what's there at
the factory has not yet been implemented, but I have successfully determined
that HP EliteBooks are also feasible, so these will be added in a future
Canoeboot release, most likely the Canoeboot 25.12 release planned for
December 2025.

### Revision updates

In descending order from latest changes to earliest changes:

* GRUB: Update to revision 73d1c959e (14 March 2025)

The GRUB update brings in several changes from upstream:

```
* 73d1c959e cryptocheck: Add --quiet option
* dbc0eb5bd disk/cryptodisk: Wipe the passphrase from memory
* 301b4ef25 disk/cryptodisk: Add the "erase secrets" function
* 23ec4535f docs: Document available crypto disks checks
* 10d778c4b commands/search: Add the diskfilter support
* 7a584fbde disk/diskfilter: Introduce the "cryptocheck" command
* ed691c0e0 commands/search: Introduce the --cryptodisk-only argument
* c448f511e kern/rescue_reader: Block the rescue mode until the CLI authentication
* 4abac0ad5 fs/xfs: Fix large extent counters incompat feature support
```

### Licensing

* no changes (relative to Canoeboot 25.04)

### Security

These can be considered bug fixes, but these are special fixes that are of
massive concern to users.

* This GRUB change was merged, in the aforementioned revision
  update: `dbc0eb5bd disk/cryptodisk: Wipe the passphrase from memory` - this
  wipes the LUKS key from memory, after GRUB exits, where one was created
  by GRUB while unlocking a given volume.

### Feature changes

In descending order from latest changes to earliest changes:

* `init.sh`: looser `XBMK_THREADS` validation; correct it on child instances,
  if it's not set, or set incorrectly.
* `get.sh`: use subshells on `try_` functions, wrapped in an error handler
  so as to provide more verbose output under fault conditions. This makes it
  easier to debug when a download fails.
* `git.sh`: Re-implement redundant git downloads, more reliably than before; all
  repositories are now cached, reliably, including submodules, even when upstream
  repo links differ wildly. This reduces the amount of internet bandwidth used,
  when handling multiple builds.
* `release.sh`: build in tmp directory first, leaving old files behind under
  fault conditions, for further analysis
* `inject.sh`: re-add mac address confirmation, for user-friendliness, when
  running the inject commands.
* `init.sh`: Resolve `XBMK_CACHE` via readlink
* `init.sh`: Use `readlink` in `pybin()`, with realpath only as fallback. This
  makes the function more redundant, working on more systems by default.
* `lib.sh`: support any command on `find_exec()` (later renamed); this is a
  generic function, that implements a while loop for a given set of files,
  based on the output a command that generates those paths. This is operated
  on by a function, defined when calling find\_exec. This unifies all use of
  while loops on lists of files and directories, throughout xbmk, rather
  than re-implementing the for/while loops each time.
* `inject.sh`: simplify kconfig scanning by using the `fe_` with a new
  function, `scankconfig()`. This new function checks *all* coreboot configs
  for a given target, whereas the old behaviour only resulted in the *first*
  config being checked. In practise, this causes no real behaviour changes.
* `rom.sh`: Print the rom image path being generated
* `lib.sh`: Add warning if x_ is called without args

### Configuration changes

<img tabindex=1 class="r" src="https://av.libreboot.org/rpi_pico/soic16_x200.webp" /><span class="f"><img src="https://av.libreboot.org/rpi_pico/soic16_x200.webp" /></span>

In descending order from the latest changes to the earliest changes:

* ifd/hp8300usdt: set the HAP bit by default; it was previously not set, but
  the `me_cleaner` config was nonetheless used, and ME Soft Temporary Disable
  was also used. As a result, this change is basically redundant, but otherwise
  technically correct (more so than the previous behaviour).
* coreboot: Remove unused vboot tests (futility tests), to shrink the size of
  release tarballs.
* `dependencies/debian`: add `libx86`
* A GRUB configuration change was made, fixing auto-scanning of LVMs when
  doing cryptomount.

### Bug fixes

<img tabindex=1 class="r" src="https://av.libreboot.org/rpi/wson8/0003.jpg" /><span class="f"><img src="https://av.libreboot.org/rpi/wson8/0003.jpg" /></span>

Most of these are build system fixes, but for example there is also a fix
applied to the GRUB source code.

The following bug fixes have been merged (in descending order from the latest
changes to the earliest changes):

* `tree.sh`: add sha512 error for `check_project_hashes()`. Handle errors
  in `sha512sum` and `awk`; also check that `project.hash` exists and error
  out if it doesn't, when checking a given project hash. We know that the
  project hash file should always exist, and always be read; technically,
  find might not yield results, but then an empty file would be produced.
  the empty file edge-case scenario would already have resulted in an error
  exit inside `configure_project()`, so that's already covered.
* `tree.sh`: add error checking in `check_project_hashes()`, when reading
  the `old_pjhash` variable; we need to error out where a read error occurs.
  such an error is extremely unlikely, so this fix is largely theoretical and
  preventative.
* `tree.sh`: more reliable clean in `run_make_command()`; don't do a no-op if
  it fails, instead fall back to the `clean` method, and throw an error
  if *that* fails. The no-op existed because not all projects have distclean,
  but we always intend for them to be cleaned. This therefore prevents
  further unhandled error conditions, in such edge cases.
* put coreboot utils in `elf/coreboot/TREE`, to prevent old binaries from
  still being used when a code change is made.
* `release.sh`: use printf to create version files, instead of copying the
  version files, because they don't exist in some cases, so this prevents
  an error condition.
* `init.sh`: error out if .git/ is a symlink; this is a preventative bug fix,
  to prevent future unknown bugs in such a scenario.
* `get.sh`: Properly error out if `tmpclone()` fails, where it previously
  failed to throw an error under certain fault conditions.
* `tree.sh`: Don't auto-run make-oldconfig; it now must be applied permanently,
  via e.g. `./mk -u` commands. Otherwise, undesirable changes can sometimes
  be made during build time, especially on projects that don't use scons
  quite as reliably, as in the U-Boot build system.
* `get.sh`: re-generate remotes every time, on cached Git repositories, so
  that configuration changes in `config/git/` are automatically applied when
  dealing with multiple versions of a given upstream project.
* `release.sh`: copy version files to `rsrc` (release source directory),
  otherwise an `unknown` version number is erroneously created. This fixes
  a regression caused by previous optimisation to `init.sh`
* xbmk: add fake config makefile args to `flashprog`, and `pcsx-redux`, to
  prevent `./mk -u` (without additional arguments) from erroneously exiting
  with error status. otherwise, an error can occur in such conditions if
  a Makefile has not yet been created.
* `rom.sh`: skip running `copyps1bios()` on dry builds, otherwise
  running `./mk -d` without argument will cause an error.
* `tree.sh`: Don't run make-clean on dry runs (`./mk -d`), to prevent error
  conditions while building GRUB, if `./mk -d` is passed without additional
  argument, since the latter requiires running autoconf to get a Makefile in
  the GRUB build system.
* `get.sh`: add missing check in `fetch_project()`; we were checking the
  main URL on a download, but not the backup URL.
* `get.sh`: stricter URL check in `xbmkget()`; throw an error if a URL is
  empty, rather than skipping to the next. If a URL is set but fails, then
  falling back to the next is OK (or throw an error if the backup is set,
  and also failed).
* `get.sh`: Make `xbmkget` always throw an error upon exiting the loop check;
  it was previously throwing an error if the for loop returned with zero status.
  Depending on the sh implementation, or changes made in the future, this could
  cause unpredictable buggy behaviour. Therefore, the error exit is much
  stricter now, and less ambiguous, to prevent future bugs, because it is
  imperative that execution must never continue under fault conditions. If a
  file or repository is successfully handled, a return (zero) occurs, otherwise
  the loop exits and a non-zero exit occurs.
* `tree.sh`: fix up `copy_elf()`, or specifically fix a bad `for` loop,
  because shorthand conditionals are used and the way they were used can be
  buggy on some sh implementations, so they are terminated more explicitly.
* xbmk: stricter handling of files on while loops, to prevent instances where
  execution continues under fault conditions. This prevents other, less
  predictable bugs in the future.
* `init.sh`: Hardcode `XBMK_CACHE` for integrity; this is a bug fix, because
  there's too much that can be wrong with this being configurable, so now it
  is hardcoded at runtime. It was never intended to be configurable anyway.
* `init.sh`: check/validate version/versiondate once read, in child instances
  of xbmk, to further verify that they were previously set, and set correctly.
  This is theoretically a preventative bug fix.
* `init.sh`: force an error condition if the xbmk version was not read. This
  prevents further erroneous state within xbmk.
* `init.sh`: check the `lock` file BEFORE `git init`, to prevent erroneous
  initialisation while another xbmk parent instance is running.
* `init.sh`: return from xbmk child instances in `set_env()` instead. This is
  easier than the previous check, preventing the initialisation of a git repo
  and/or recreation of xbmktmp and xbmklocal by erroneoues parent executions
  of xbmk while another parent is running - the latter of which could have
  caused a massively unpredictable build failure, so this is also a
  preemptive bug fix, fixing and preventing all kinds of weird unknown bugs.
* `release.sh`: don't move `src/docs/` to `docs/` inside release archives,
  because otherwise `./mk -b` will fail, inside release archives.
* `get.sh` submodules: Don't delete files recursively. Use `rm -R` instead
  of `rm -Rf`, on files.
* `git.sh`: Only create destination repo on success; don't leave a broken cache
  laying around, which would otherwise break the build system under certain
  conditions.
* `release.sh`: removed an unnecessary `src_dirname` variable
* `release.sh`: delete tmp/cache from release tarballs
* `inject.sh`: Remove confusing path on tar creation; that is, don't print said
  path, because temporary paths are printed during this, when creating tarballs.
  In this file, the correct path is printed at the end of the process, when
  handling an images tarball.
* `tree.sh`: only create elfdir in `copy_elf()`, to prevent empty directories
  being created where a project provides `build.list`, but where no actual
  configs are being built on a given target name.
* `mk`: add missing error handli for `mk -f` (when doing releases)
* `git.sh`: hard fail if git am fails (regression fix)
* `git.sh`: Hard fail if reset fails; allowing re-try when cloning fails, but
  the reset-fail scenario didn't cause any exit at all. This is fixed now.
* `init.sh`: Only check `XBMK_CACHE` if it exists
* `grub.cfg`: fix trying to boot all logical volumes after unlocking an encrypted
  volume; this makes booting LVMs more reliable, on encrypted boot setups.
* `init.sh`: also allow `XBMK_RELEASE=Y` or `=N`, not just `n` and `y`,
  because some people use uppercase here. This is considered a bug fix, but
  could just as easily have been in the features section.
* `init.sh`: check `XBMK_CACHE` is a directory instead of a file.
* `init.sh`: run `set_version` *before* `set_env`, to prevent a future situation
  where the version is not set correctly. In general, the version should always
  be set as early as poessible when running xbmk.
* `lib.sh`: re-add missing break in fe/fx\_, that caused improper exits (or non
  exits) in some cases.
* `singletree/elfcheck`: use `fx_`, not `fe_`; this is a less strict test, to
  prevent certain errors under specific edge-case conditions.
* `rom.sh`: Safer `cprom()`; don't insert special files like GRUB keymaps AFTER
  copying the system ROM to the final destination; do it BEFORE, instead, to
  ensure that bad images aren't left in place under fault conditions.
* `rom.sh`: specifically check keymaps in `cprom()`; it previously checked
  whether a setup is *not* seauboot, which was valid, but future conditionals
  would break this check. the code has been changed in advance, to prevent bugs
  in a future revision of xbmk.
* `mk`: Fix bad error handling for `gnu_setver`; I accidentally mixed and/or in
  a shorthand conditional statement, which leads to buggy behaviour in various
  implementations of sh.
* GRUB: Mark E820 reserved on coreboot memory, to fix cbmem when running
  with strict `/dev/mem` access; otherwise, restrictions on access to memory
  below 1MB will cause an error when trying to access the cbmem console.
* `lib.sh`: set `-u -e` in `err()` in case they were set `+u +e` in other parts
  of xbmk.
* `init.sh`: Silence the output of git config --global
* `init.sh`: Run git name/email check before init; otherwise, it returns if
  init is already done, which could lead to an error later when building
  coreboot.
* `lib.sh`: stricter `xbmk_err` check in `err()`
* `lib.sh`: simplify err-not-set handling
* `lib.sh` err: add missing redirect to stderr
* xbmk: MUCH safer `err` function; make it an actual function, instead of
  a variable. Initially, this function was made to then check a variable,
  that refers to a function, and a fallback was provided for non-zero exit
  in case the pointed function didn't, but it was later made to be just a
  simple function that exits with a message. Code equals bugs, so fewer lines
  of code will yield fewer bugs.
* `lib.sh`: Make x_ err if first arg is empty; this is a preventative bug fix,
  to make the build system still exit under such conditions, but it would
  result in an empty error message.
* `lib.sh`: Make err_ always exit no matter what; this is a preventative bug
  fix, just making the exit stricter in all cases.
* `mk`: re-make gnupath/ after handling crossgcc, rather than deleting files
  within. This makes the creation of it more reliable.
* `mk`: re-make gnupath/ for each cross compiler, to ensure that no stagnant
  build artifacts are re-used
* `inject.sh`: Stricter TBFW handling; don't copy it until it has been
  properly padded to the correct size.
* `init.sh`: *Re-create* tmpdirs on parent instance, to ensure that they are
  not cluttered with old files that might cause weird bugs in the future; this
  is a preventative bug fix.
* `init.sh`: Always create xbmklocal, to prevent errors in the case when it
  isn't created automatically in certain child instances, like when running
  a *release* copy of the build system, during release builds.
* `lib.sh`: Fix bad touch command
* `inject.sh`: always re-build nvmutil, so that changes to it are automatically
  re-applied when running the build system again. (and only build it once,
  for a given instance of xbmk)
* `util/nvmutil`:  use `x`, not `?`, for random characters, while still
  supporting `?` for backwards compatibility. This is because ZSH errors out
  when providing the old characters, in some setups. Use of `x` is more
  reliable, across several implementations of sh, e.g. `xx:xx:xx:xx:xx:xx`
  would be a full random MAC address.
* `lib.sh` find\_ex: explicitly create the tmp file, to prevent errors, which
  were nonetheless unlikely to begin with.
* `init.sh`: Explicitly create the xbmktmp directory (make sure to do this
  when creating this which is a temporary directory).
* `lib.sh`: add fe_ which is fx_ but err on find
* xbmk: unified execution on `find` commands. Handle it with a new special
  function that is common across the build system.
* `mk`: Download vendorfiles before building release, to mitigate intermittent
  internet connectivity during release builds, otherwise a release build could
  fail. This way, all downloads are done simultaneously, since downloads are
  the fastest part, even on a crap internet connection.
* Revert AHCI reset patch for SeaBIOS, which caused AHCI not to work in SeaBIOS
  on the 25.04 release; the latter was also revised, to fix this. SeaBIOS has
  since added a new release, which includes a fix that delays AHCI reset, to
  mitigate in cases where the controller isn't ready sooner. However, this
  release simply reverts the AHCI reset patch for now. The AHCI reset plus delay
  will be present in Canoeboot's next release, after 25.06.
* lenovo/t420: Add missing text-mode configuration

### General code cleanup

<img tabindex=1 class="r" src="https://av.libreboot.org/rpi/wson8/0007.jpg" /><span class="f"><img src="https://av.libreboot.org/rpi/wson8/0007.jpg" /></span>

Another bug focus in this release was to clean up the logic of Canoeboot's
build system, and fix several bugs, especially those relating to error handling.

A lot of cleanup was done on the init functions used by the build system, to
initialise common variables, such as environmental variables, and temporary
files and/or directories; such logic was moved to a new script called `init.sh`.

In descending order from the latest changes to the earliest changes:

* `lib.sh`: simplify `setvars()`
* `lib.sh`: simplify `chkvars()`
* `mk`: simplify `main()`
* `get.sh`: simplify `fetch_project()`
* `get.sh`: simplify `try_copy()`
* `get.sh`: tidy up `bad_checksum()`
* `get.sh`: simplify `fetch_targets()`
* general cleanup in `get.sh` and `vendor.sh`
* xbmk: rename `xbmklocal`/`xbmktmp` variables (shorten them)
* `get.sh`: consolidate printf statements
* `get.sh`: remove redundant printf in `fetch_project()`
* `get.sh`: remove superfluous command in `try_git()`
* `rom.sh`: simplify `mkcoreboottar()`
* `rom.sh`: rename `mkvendorfiles()`, which actually handles general init
  tasks, including the processing of vendor files where appropriate.
* `rom.sh`: simplify ccache handling for coreboot; make-oldconfig wasn't
  needed at all, when cooking configs to enable ccache, so the *cook* function
  became much smaller and was then merged with `mkvendorfiles()`
* `rom.sh`: simplify u-boot payload handling, by using a single variable name
  that defines the type of U-Boot tree. This allows several other U-Boot-related
  checks to be greatly simplified, as they were.
* `vendor.sh`: add a colon at the end of a `for` loop
* `get.sh`: make `xbmkget()` easier to understand, by not using shorthand
  conditional statements in the for loop handling a repository or file
  download.
* `init.sh`: merge `xbmk_lock()` with `xbmk_set_env()`
* `init.sh`: set pyver from `set_env()` instead of the main function.
* `init.sh`: merge `xbmk_mkdirs()` with `set_env()`
* `init.sh`: only update version files on parent, to speed up xbmk
* `init.sh`: simplify unknown version creation, where none was created and
  no Git metadata exists.
* `init.sh`: only set xbmk version on parent instance; we only need to read
  what was set, on child instances. In other words, apply the principle of
  least privelege.
* `init.sh`: initialise variables AFTER path, to avoid unnecessary work inside
  child instances of xbmk.
* `init.sh`: merge `create_pathdirs()` with `set_pyver()`
* `init.sh`: Set python version only on parent instances of xbmk, to speed
  up operation of the xbmk build system.
* `init.sh`: `xbmk_create_tmpdir()` to `xbmk_mkdirs()`
* `init.sh`: move `gnupath` creation to `create_tmpdir()`
* `init.sh`: move PATH init to `set_env()`
* `inject.sh`: shorten the `nukemode` variable name
* `get.sh`: simplify `bad_checksum()`
* `release.sh`: use `x_()` on find command for `nuke()`, so as to remove the
  need for a more complicated while loop inside said function.
* `get.sh`: move `nuke()` to `release.sh` and only run it on releases; don't
  do it on normal xbmk Git. It's only needed in the former context, because
  that has to do with distribution by the project, and this makes
  development easier. Therefore, files are only purged within the release
  archives, but not during development.
* `release.sh`: simplify `prep_release_bin()`
* `get.sh`: simplify `tmpclone()`
* `get.sh`: simplify `nuke()` by using `fx_` for the file loop
* `get.sh`: simplify `try_copy()`
* `get.sh`: simplify `fetch_submodules()` config check
* `get.sh`: simplify `fetch_submodules()` by using `xbmkget()` for everything,
  instead of implementing redundant logic in the build system.
* `git.sh`: rename to `get.sh`
* `rom.sh`: reduce indendation in `check_coreboot_utils`; simplify the for
  loop by replacing it with a call to `fx_` instead.
* `release.sh`: simplify `release()`
* `release.sh`: clean up the `vdir` after release
* `release.sh`: removed an unnecessary `mkdir` command
* `release.sh`: split up `build_release()` into smaller functions
* `lib.sh`: remove `rmgit()`
* `lib.sh`: remove the unnecessary `mk()` function
* `lib.sh`: move `xbmkget()` to `git.sh`
* `lib.sh`: move `mksha512sum()` to `vendor.sh`
* `lib.sh`: split up `try_file()` into smaller functions
* `lib.sh`: move `_ua` to `try_file()`
* `inject.sh`: remove the `hashfiles` variable
* `inject.sh`: define `xchanged` here instead
* `lib.sh`: use `fx_` in `rmgit()`
* `lib.sh`: split up `xbmkget()` into smaller functions
* `inject.sh`: only compile nvmutil if needed
* `inject.sh`: simplified serprog check
* `inject.sh`: further cleanup for `vendor.sh`, such that all vendor-download
  functions are only defined in `vendor.sh`; this means that the Canoeboot
  version of the file can remain in much closer sync, with fewer differences.
* `tree.sh`: simplified srcdir check on make-clean
* `inject.sh`: split up the inject functions into smaller functions for
  each specific task. (for inserting MAC addresses)
* xbmk: use `x_` instead of `err`, where appropriate, because it handles
  globbing perfectly these days, and `x_` is cleaner in most cases.
* `mk`: remove unnecessary line break
* `mk`: re-split tree logic to new file, `include/tree.sh`
* `mk`: move release functions to `include/release.sh`
* `git.sh`: use `setvars()` for fail variables
* `init.sh`: remove useless export; variables that are y/n can just be reset
  to `n` if not set to `y`, for simplicity.
* `init.sh`: export `LOCALVERSION` in `set_env` instead of `set_version`.
* `inject.sh`: simplified MAC address handling
* `inject.sh`: Simplify `patch_release_roms()`
* `lib.sh`: Remove useless command in `err()`
* `lib.sh`: Simplified `fx_()` and removed `fe_()`; fe didn't prefix `x_` to
  a given command, but fx did. Now, it is prefix manually, for greater control,
  on commands that need stricter error handling, while it can be avoided on
  commands where strict error handling is unfeasible.
* `mk`: Create serprog tarballs here instead; `rom.sh` was simplified to use
  mkhelp when building actual images.
* build serprog images using `fx_` *defined inside mkhelper*, to tidy up xbmk
* `rom.sh`: build serprog images with `fx_`, rather than implementing a
  specific for loop.
* `git.sh`: Simplify git am handling by using the new `fe_` or `fx_` function,
  instead of making a specific while loop.
* `inject.sh`: remove an unused function
* `init.sh`: New function `dx_` to execute path files; this is used instead
  of for loops all around xbmk, to simplify operations where the output of
  a file search is used as argument to a function.
* `lib.sh` `find_ex`: Write sort errors to `/dev/null`
* `lib.sh` `x_()`: Remove warning of empty args; it's really not required,
  since it's obvious anyway in the resulting final error message.
* xbmk: Replace `err()` with much simpler implementation, for reliability
  and bug prevention.
* `rom.sh`: simplify `mkseagrub()`
* `mk`: simplify `elfcheck()`
* `lib.sh`: simplify `singletree()`
* `git.sh`: move `singletree()` to `lib.sh`
* `lib.sh`: simplify `err()`
* `init.sh`: single-quote xbmklock in `xbmk_lock()`
* `init.sh`: define lock file in a variable instead; this makes it more
  flexible, because the path can be checked and then re-used nicely.
* `init.sh`: tidy up `xbmk_child_exec()`; make the command style more consistent
* `lib.sh`: rename errx to xmsg
* `init.sh`: tidy up the python version check
* `init.sh`: move non-init functions to `lib.sh`
* `init.sh`: simplify dependencies handling
* `rom.sh`: tidy up `copyps1bios()`
* `mk`: tidy up xgccargs handling
* `mk`: generally removed dead code
* `init.sh`: tidy up pathdir creation
* `mk`: tidy up `check_cross_compiler()`
* `mk`: reduce indentation in `check_cross_compiler()`
* `mk`: Allow use of x_ on prefix functions
* `mk`: tidy up `check_project_hashes()` sha512sum check
* `mk`: simplify `check_gnu_path()`
* `inject.sh`: general code cleanup
* xbmk: Unified local ./tmp handling
* `lib.sh`: redirect find errors to `/dev/null` to prevent clutter on
  the user's terminal
* `init.sh`: unified handling of ./tmp
* `mk`: include rom.sh directly
* `lib.sh`: Simplify rmgit()
* `lib.sh`: support multiple arguments in remkdir()
* `lib.sh`: simplify remkdir()
* xbmk: move x_() to `lib.sh`
* `init.sh`: move setvars/err_ to lib.sh

Git log
-------

This log is relative to Canoeboot 25.04:

```
* 126dff455b tree.sh: add sha512 error for check_project_hashes 
* 08a9837216 tree.sh: add error check in check_project_hashes() 
* e1664be01e tree.sh: more reliable clean in run_make_command 
* 1843f71577 inject.sh: add missing semicolons 
* 3567d95860 put coreboot utils in elf/coreboot/TREE 
* 885016c0c2 release.sh: use printf to create version files 
* eeb9954179 lib.sh: simplify setvars() 
* bc0a2a9b75 lib.sh: simplify chkvars() 
* 3657ed8677 mk: simplify main() 
* ee92a228c3 get.sh: simplify fetch_project() 
* bbc35fe6e6 get.sh: simplify try_copy() 
* b9f78f2aff get.sh: tidy up bad_checksum() 
* ff77de4a9d get.sh: simplify fetch_targets() 
* 405215bc34 general cleanup in get.sh 
* 21352b990e xbmk: rename xbmklocal/xbmktmp variables 
* fcfc43aced get.sh: consolidate printf statements 
* 46c0eb5ff4 get.sh: remove redundant printf in fetch_project 
* 77b79d3581 get.sh: remove superfluous command in try_git() 
* 7b8185f460 init.sh: error out if .git/ is a symlink 
* 2b8ccfbe5b get.sh: Properly error out if tmpclone fails 
* ff06b30ca5 tree.sh: Don't auto-run make-oldconfig 
* 173f304fd7 rom.sh: simplify mkcoreboottar() 
* 0854e99cfe rom.sh: rename mkvendorfiles 
* 00ab60e762 rom.sh: simplify ccache handling for coreboot 
* 82bb342a63 rom.sh: simplify u-boot payload handling 
* 463cdd8128 coreboot: Remove unused vboot tests 
* a70d8afc30 get.sh: Always update git remotes 
* 77ad7a0ca3 get.sh: re-generate remotes every time 
* e209646018 release.sh: copy version files to rsrc 
* ada8a6dd7b xbmk: add fake config makefile args to flashprog 
* 069aa21567 rom.sh: skip copyps1bios on dry builds 
* bcdcfa045a tree.sh: Don't run make-clean on dry runs 
* 4c0ecf17e6 GRUB: Update to revision 73d1c959e (14 March 2025) 
* be598c497b get.sh: add missing check in fetch_project() 
* 378a73ce42 get.sh: stricter URL check in xbmkget() 
* b9886740ba get.sh: make xbmkget() easier to understand 
* c130682fdf get.sh: Make xbmkget err on exiting the loop check 
* 1342d74cc6 tree.sh: fix up copy_elf(), bad for loop 
* b4a547caac lib.sh: Use while, not for, to process arguments 
* 41ffbb640d xbmk: stricter handling of files on while loops 
* b516a29482 init.sh: looser XBMK_THREADS validation 
* fa59f9da76 init.sh: Hardcode XBMK_CACHE for integrity 
* d92dee6781 dependencies/debian: add libx86 
* 6577abc60a FSDG-compliant Sandy/Ivybridge/Haswell support 
* addbd95a24 init.sh: merge xbmk_lock() with xbmk_set_env() 
* 1c34d4567b init.sh: move xbmk_set_version 
* a4103517ea init.sh: set pyver from set_env 
* 6a3c771feb init.sh: merge xbmk_mkdirs with set_env 
* de62243cd2 init.sh: check version/versiondate once read 
* 6b8ee3d3b3 init.sh: error if version not read 
* 08610f4145 init.sh: only update version files on parent 
* 412b0a81d7 init.sh: simplify unknown version creation 
* 2a6a4d765d init.sh: only set xbmk version on parent instance 
* 416b1f66be init.sh: initialise variables AFTER path 
* 46f09075c2 init.sh: merge create_pathdirs with set_pyver 
* abf52b0394 init.sh: Set python version only on parent 
* 1e4e3f36f4 init.sh: remove useless command 
* ed83718cf2 init.sh: remove useless comment 
* 8617375799 init.sh: xbmk_create_tmpdir to xbmk_mkdirs 
* 83064459d9 init.sh: move gnupath creation to create_tmpdir 
* 0389d1eadb init.sh: move PATH init to set_env 
* 4aba9ef29e init.sh: check the lock file BEFORE git init 
* fa2c288939 init.sh: return from child in set_env instead 
* 9b1d4dfe82 inject.sh: shorten the nukemode variable name 
* e34651a98a release.sh: rename relsrc to rsrc 
* 1523a67729 release.sh: tidy up nuke() 
* c068efec88 get.sh: remove useless message 
* c660ecde62 get.sh: simplify bad_checksum() 
* 2d13b4c2e2 release.sh: simplify nuke() EVEN MORE, yet again 
* c20e29005f release.sh: use x_ on find command for nuke() 
* 97603a43cf release.sh: simplify nuke() EVEN MORE 
* 534a4d4870 get.sh: move nuke() to release.sh 
* 8b646abe9a release.sh: simplify prep_release_bin() 
* aeb1187a8a release.sh: don't move src/docs/ 
* 8cb0c224a5 get.sh: FURTHER simplify nuke() 
* 8cb23315d9 get.sh: simplify tmpclone() 
* 8d6244bb7f get.sh: fix bad mkdir command 
* 4582a21abf inject.sh: Stronger hash verification 
* fd98310f5b properly exit 1 when calling fx_ 
* e96dfae0b3 get.sh: simplify nuke() 
* 3bfb82cb82 get.sh: fix broken printf statement 
* 9c24b170c2 get.sh: use subshells on try_ functions 
* 4f926ee708 get.sh: simplify try_copy() 
* 36cf7892df get.sh submodules: Don't delete files recursively 
* 398f265359 get.sh: simplify fetch_submodules() config check 
* a3f48f3115 get.sh: simplify fetch_submodules() 
* 142b79b206 get.sh: fix caching of crossgcc tarballs 
* a658265a86 release.sh: Don't run prep_release with fx_ 
* aaa0a1ff93 git.sh: rename to get.sh 
* 2d691c7377 git.sh: Only create destination repo on success 
* 6199bc5b95 git.sh: cleanup 
* 1dd18a9a55 git.sh: Re-implement redundant git downloads 
* 176c0fa1c4 rom.sh: reduce indendation in check_coreboot_utils 
* 584de778f8 release.sh: simplify release() 
* ed8644177b release.sh: clean up the vdir after release 
* 2ca6337b0a release.sh: remove src_dirname variable 
* abfa2d1ec7 release.sh: build in tmp directory first 
* d3ec7e8635 release.sh: remove unnecessary mkdir command 
* b68447e75c release.sh: split up build_release() 
* 4b36ba9765 release.sh: delete tmp/cache from the tarball 
* 5861c25a7c lib.sh: remove rmgit() 
* 1f2c8e47d4 lib.sh: remove mk() 
* 19888e2cb8 lib.sh: move xbmkget() to git.sh 
* 9c5f59cc42 lib.sh: remove mksha512sum() 
* 279b7f20be lib.sh: split up try_file() 
* 3347e3d314 lib.sh: move _ua to try_file() 
* 57f68535a2 inject.sh: remove the hashfiles variable 
* d07bd53b07 inject.sh: define xchanged here instead 
* 47b9a261d7 lib.sh: use fx_ in rmgit() 
* ed9f6338af lib.sh: split up xbmkget() 
* 753af0a7a2 inject.sh: only compile nvmutil if needed 
* 387f4b785b inject.sh: simplified serprog check 
* 31bab5c10c remove another confusing message 
* 6c3ea129a4 inject.sh: Remove confusing path on tar creation 
* 3062f04c45 inject.sh: re-add mac address confirmation 
* cf8ca4cdd6 inject.sh: further cleanup 
* a82ca2da5f tree.sh: only create elfdir in copy_elf() 
* 33debfcf1c tree.sh: simplified srcdir check on make-clean 
* 2acdfefdf9 inject.sh: bring in sync with lbmk 0f931b508a8 
* a170ab4118 cbmk: use x_ instead of err, where appropriate 
* 5cdd377547 mk: use zero exit instead, to run trees 
* c022a14c9e remove useless comment 
* c9325f234e mk: remove unnecessary line break 
* e22593f037 mk: re-split tree logic to include/tree.sh 
* c463e8a52d mk: move release functions to idnclude/release.sh 
* 966a6377a0 mk: add missing error handli for mk -f 
* 718697c0e6 git.sh: re-write tmpclone without caching 
* a5c5089eda git.sh: use setvars for fail variables 
* 7b2671ea26 git.sh: hard fail if git am fails 
* 45b6d3b3ba git.sh: Hard fail if reset fails 
* e320ce60a7 init.sh: Only check XBMK_CACHE if it exists 
* d99bc55f4a also fix the other grub trees 
* c15ee8fc32 fix trying to boot all logical volumes after unlocking an encrypted volume 
* 63cef86bdb init.sh: remove useless export 
* 0a3793ad4e init.sh: also allow XBMK_RELEASE=Y or N 
* 433b5de916 init.sh: Resolve XBMK_CACHE via readlink 
* 5d2c94a8bd init.sh: check XBMK_CACHE is a directory instead 
* f0a0f678bf init.sh: export LOCALVERSION in set_env 
* 542d72192d init.sh: run set_version before set_env 
* 9ccfee43e7 init.sh: Use readlink in pybin() 
* 2f17c5be3b inject.sh: simplified MAC address handling 
* 3900122957 lib.sh: Remove useless command in err() 
* afcd0cfde6 lib.sh: Simplified fx_() and removed fe_() 
* 386f3c3346 mk: Create serprog tarballs here instead 
* 326f0459d9 build serprog using fe_ *defined inside mkhelper* 
* 418fcce9ba rom.sh: build serprog images with fe_ 
* add92cd405 lib.sh: support any command on find_exec() 
* bd5d85569f lib.sh: re-add missing break in fe/fx_ 
* eac3b96ddd git.sh: Simplify git am handling 
* 6e4172b1ba inject: remove unused function 
* 92374e6071 init.sh: New function dx_ to execute path files 
* 1bc8055e28 inject.sh: simplify kconfig scanning 
* ea8f9b59c6 lib.sh find_ex: Write sort errors to /dev/null 
* 0ba013a61d lib.sh x_(): Remove warning of empty args 
* e47324619d lbmk: Replace err with much simpler implementation 
* 2279a1f6f6 singletree/elfcheck: use fx_, not fe_ 
* 1e1e65cb43 rom.sh: Print the rom image path being generated 
* ffdf93bf90 rom.sh: Safer cprom() 
* 1c0c88c7cb rom.sh: specifically check keymaps in cprom() 
* 9342e5bb61 rom.sh: simplify mkseagrub() 
* 4a9376adc4 mk: simplify elfcheck() 
* e2f6e7a410 lib.sh: simplify singletree() 
* 9d91c3da60 git.sh: move singletree() to lib.sh 
* 877f00df1f mk: Fix bad error handling for gnu_setver 
* 0156cd91c8 lib.sh: set -u -e in err() 
* 7f150c3e4f GRUB: Mark E820 reserved on coreboot memory 
* 22d3266a53 lib.sh: Provide error message where none is given 
* 5b2d537123 init.sh: Silence the output of git config --global 
* edfa4a0ddd init.sh: Run git name/email check before init 
* 23755c1748 lib.sh: stricter xbmk_err check in err() 
* 5150bf64a4 lib.sh: simplify err-not-set handling 
* 90bd3e67c4 lib.sh: Add warning if x_ is called without args 
* 78aa78c82e lib.sh: simplify err() 
* 15afad4a2b init.sh: single-quote xbmklock in xbmk_lock() 
* 41bc473276 init.sh: define lock file in a variable instead 
* 4415865ccc init.sh: tidy up xbmk_child_exec() 
* ee686cc86b lib.sh err: add missing redirect to stderr 
* cd979e3b09 lbmk: MUCH safer err function 
* fda09e8923 lib.sh: rename errx to xmsg 
* 8eea01eceb lib.sh: Make x_ err if first arg is empty 
* af309d888b lib.sh: Make err_ always exit no matter what 
* 6e14ab7c09 init.sh: tidy up the python version check 
* 7944fd6297 init.sh: move non-init functions to lib.sh 
* 159ded1c4e init.sh: simplify dependencies handling 
* 7ab7bf19f2 rom.sh: tidy up copyps1bios() 
* a5519f13e1 mk: tidy up xgccargs handling 
* ed441a4ba0 mk: remove useless code 
* e05787d82f init.sh: tidy up pathdir creation 
* 2c3f9e4e7e mk: re-make gnupath/ after handling crossgcc 
* e6d3b5763d mk: tidy up check_cross_compiler 
* 45513d56be mk: re-make gnupath/ for each cross compiler 
* 7314903331 mk: reduce indentation in check_cross_compiler() 
* f6005f17b6 mk: Allow use of x_ on prefix functions 
* 4a32890198 mk: tidy up check_project_hashes() sha512sum check 
* 1d988606ca mk: simplify check_gnu_path() 
* f64b2affb1 inject.sh: minor code cleanup 
* bb5228dc32 init.sh: *Re-create* tmpdirs on parent instance 
* 0c05289152 init.sh: Always create xbmklocal 
* b2c14b6759 lbmk: Unified local ./tmp handling 
* 6a653729a3 lib.sh: redirect find errors to /dev/null 
* 67e06ce368 lib.sh: Fix bad touch command 
* 2c9f3065ee inject.sh: Only build nvmutil once 
* 4ca73f9434 inject.sh: always re-build nvmutil 
* e6c2fd9734 util/nvmutil:  use x, not ?, for random characters 
* 09f6a6b11d lib.sh find_ex: explicitly create the tmp file 
* 2d05cd260d init.sh: Explicitly create the xbmktmp directory 
* e32a6c96d5 init.sh: unified handling of ./tmp 
* 6c7da73782 lib.sh: add fe_ which is fx_ but err on find 
* afb5e7d3d5 lbmk: unified execution on find commands 
* 0b9c797f32 mk: include rom.sh directly 
* a13e53ba16 lib.sh: Simplify rmgit() 
* 61407551ca lib.sh: support multiple arguments in remkdir() 
* 4c2786daba lib.sh: simplify remkdir() 
* 6348e8a93e move x_() to lib.sh 
* a30fd38ae4 init.sh: move setvars/err_ to lib.sh 
* d51b995528 Restore SeaBIOS 9029a010 update, but with AHCI fix 
* 62f9c277f3 Revert "seabios: bump to rev 9029a010, 4 March 2025" 
```

Revision releases
-----------------

When certain bugs are found, releases may be re-built and re-uploaded. When
this happens, the original release is replaced with a *revision release*.

Revisions are numbered; for example, the first post-release revision
is *rev1*.

### 25.06 (30 June 2025)

No revisions, thus far. The original 25.06 release is the current revision, so
it could be considered *rev0* (revision zero).


