diff --git a/.gitignore b/.gitignore index e7f5574be..1f293f94d 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,23 @@ build/cache # below keeps untracked — a rule there would never leave this machine. /filesystem/boot.conf +# What a build and a deploy produce, anchored so that nothing tracked beside +# them is hidden: the storage image and the boot-chain artefacts deploy.sh +# writes into filesystem/, the buildroot output and the links to it under +# linux/rootfs/, and the user-space sources the :lvgl patch set materialises +# in linux/usr/src/ (the patch set is the source; these are regenerated and +# would make do_patch refuse to re-create them once committed). +/filesystem/sdcard.img.* +/filesystem/work +/filesystem/*.bin +/filesystem/flash0.img +/linux/rootfs/Makefile +/linux/rootfs/board +/linux/rootfs/fs +/linux/rootfs/staging +/linux/usr/src/graphic/ +/linux/usr/src/lvgl/ + # TEZI HTTP feed published by deploy.sh, plus the feed server's pid/log, and # the makeusr.sh local deploy. Deliberately outside build/tmp so a clean does # not wipe a feed a board may be installing from. diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 000000000..0a6d93538 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,37 @@ + +v1.0.0 (26 sep 2026) + +First release of Infrabase, and the first line with a release branch +(release/v1.0). It is the build system the SO3, EDGE-M1, MICOFE and course +trees are aligned on, as it stood once that alignment was done. + + • A minimal Linux system built with BitBake: U-Boot, the kernel, a + buildroot root filesystem and the user-space applications, for QEMU + virt64 and virt32, the Raspberry Pi 4 (64 and 32-bit), the Toradex + Verdin iMX8M Plus and x86 QEMU. Components are fetched from upstream + and patched from tracked patch sets; the attach guard refuses to + overwrite local edits, and updiff folds them back into the set. + + • The boot chain is one ordered value, IB_BOOT_CHAIN, over the stages + atf, optee, uboot, avz and mcuboot: Linux on a bare U-Boot, with ATF, + with an OP-TEE secure world, or as a guest of the AVZ hypervisor at + EL2. The order is checked, everything else (IB_HYPERVISOR, the stage + flags, the ITS) is derived from it, and each platform declares the + stages it can run, so an impossible combination is refused at parse + time. + + • Deployment to an SD-card image, a real device or a Toradex Easy + Installer network feed served from the tree. The deploy writes + filesystem/boot.conf, and st.sh starts QEMU from it. On virt64 U-Boot + can be read off the card by the QEMU boot ROM + (IB_FIRST_STAGE_FROM_CARD). The user space goes where the running + root is: into the ramfs, or onto the rootfs partition. + + • A containerised build environment (dbuild.sh): the cross toolchains and + every host package in one image, the tree bind-mounted, the build run + as the calling user. + + • Every script prints the release it belongs to when it starts, + "[infrabase v1.0.0] build.sh bsp-linux", from the git tag + (scripts/ibversion.sh); the documentation derives its version from the + same helper. diff --git a/README.md b/README.md index fee6ca9c5..3ae0bffa3 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,8 @@ filesystem and user-space applications — for real boards and for QEMU-emulated ones, and deploys it to an SD-card image or to a real device. It builds four components — **ATF**, **OP-TEE**, **AVZ** and **Linux** — and -lets you combine them freely: Linux standalone or as a guest of the AVZ -hypervisor, on a firmware chain with or without ATF and with or without a -secure world. See [What gets built](#what-gets-built) below. +lets you combine them: Linux standalone or as a guest of the AVZ hypervisor, +on a firmware chain with or without ATF and with or without a secure world. See [What gets built](#what-gets-built) below. It is driven by [BitBake](https://docs.yoctoproject.org/bitbake), the task orchestrator behind Yocto, but stays deliberately small: components are fetched @@ -65,31 +64,29 @@ The platform is selected with `IB_PLATFORM` in `build/conf/local.conf`: ## What gets built -Two independent variables in `build/conf/local.conf` decide which of the four -components end up in an image: +One variable in `build/conf/local.conf`, **`IB_BOOT_CHAIN`**, decides which of +the four components end up in an image: the stages that run before Linux, in the +order they run, joined by `+` — `atf`, `optee`, `uboot`, `avz`, `mcuboot`. So +`uboot` is Linux on a bare U-Boot, `atf+optee+uboot` adds a secure world, +`uboot+avz` runs Linux as a guest of the AVZ hypervisor, and +`atf+optee+uboot+avz` has both. Everything else (`IB_HYPERVISOR`, the ITS, which +recipes are built) is derived from it, and the order is checked. -- **`IB_BOOT_CHAIN`** — the firmware underneath the OS: `uboot`, `atf+uboot`, - or `atf+optee+uboot` (a secure world). -- **`IB_HYPERVISOR`** — what the firmware hands control to: `none` (Linux runs - directly) or `avz` (AVZ at EL2, Linux as its guest). +What each platform can run is a set of stages (`IB_BOOT_STAGES_SUPPORTED`): -They are orthogonal: AVZ boots on a bare U-Boot chain just as well as on a full -secure one. Every combination a platform supports is buildable: - -| Platform | `uboot` | `atf+uboot` | `atf+optee+uboot` | -|---|---|---|---| -| `virt64` | none / avz | none / avz | none / avz | -| `verdin-imx8mp` | — | none / avz | none / avz | -| `rpi4_64` | none / avz | none / avz | — | -| `rpi4` | none | — | — | -| `virt32` | none | — | — | +| Platform | Supported stages | +|---|---| +| `virt64` | `atf optee uboot avz mcuboot` | +| `verdin-imx8mp` | `atf optee uboot avz` (`atf` required) | +| `rpi4_64` | `atf uboot avz` | +| `rpi4`, `virt32`, `x86-qemu` | `uboot` | -An absent cell is a hardware or upstream limit, not an omission — the i.MX8MP +A missing stage is a hardware or upstream limit, not an omission — the i.MX8MP boot ROM always installs BL31, TF-A's `rpi4` port is AArch64-only, OP-TEE has no `plat-rpi4` upstream (and the BCM2711 has no secure memory controller, so a TEE there could never be real), and AVZ ships aarch64 defconfigs only. Each is -explained next to `IB_BOOT_CHAINS_SUPPORTED` in `build/conf/local.conf`, and -asking for an unsupported combination is refused at parse time rather than +explained next to `IB_BOOT_STAGES_SUPPORTED` in `build/conf/local.conf`, and +asking for a stage a platform cannot run is refused at parse time rather than producing a board that boots nothing. ## Layout @@ -107,6 +104,33 @@ filesystem/ storage images and the mounted partitions (p1, p2) doc/ this documentation (Sphinx) ``` +## Releases + +Infrabase uses a branch-per-release model, the same as SO3: development happens +on `main`, and every minor version gets a long-lived `release/vX.Y` maintenance +branch on which patch releases are tagged (`vX.Y.Z`, or `vX.Y.Z-rc` for +candidates). Each tag has a matching +[GitHub Release](https://github.com/smartobjectoriented/infrabase/releases). +Every script prints the release it belongs to when it starts +(`[infrabase v1.0.0] build.sh bsp-linux`); `scripts/ibversion.sh` prints it on +its own. + +The full procedure — cutting patch and minor releases, tagging and publishing — +is documented in +[Release process](https://smartobjectoriented.github.io/infrabase/release_process.html). + +### Maintenance branches + +Each minor line has its own long-lived branch. Bug fixes for a published version +land there and are tagged as patch releases. + +| Line | Branch | Latest release | Status | +|------|--------|----------------|--------| +| 1.0 | [`release/v1.0`](https://github.com/smartobjectoriented/infrabase/tree/release/v1.0) | [v1.0.0](https://github.com/smartobjectoriented/infrabase/releases/tag/v1.0.0) | Current stable | + +See all versions on the +[Releases page](https://github.com/smartobjectoriented/infrabase/releases). + ## Contributing Work on a branch, one topic per branch, and open a pull request; see the diff --git a/build/conf/local.conf b/build/conf/local.conf index 840a65fc0..d770a5e98 100644 --- a/build/conf/local.conf +++ b/build/conf/local.conf @@ -198,7 +198,7 @@ IB_OPTEE_PLAT:virt64 = "vexpress-qemu_armv8a" IB_OPTEE_PLAT:verdin-imx8mp = "imx-mx8mpevk" # No IB_OPTEE_PLAT for rpi4_64 on purpose: OP-TEE has no plat-rpi4 upstream # and the BCM2711 has no secure memory controller. See -# IB_BOOT_CHAINS_SUPPORTED above. +# IB_BOOT_STAGES_SUPPORTED above. # virt64: SPD=opteed only on a chain that carries OP-TEE (BL2 then loads # BL32 = OP-TEE from the FIP). Without it the FIP carries BL31+U-Boot only — diff --git a/build/meta-usr/recipes-usr/lvgl/files/0001-usr-linux-1.0-r0/0002-CMakeLists.txt.patch b/build/meta-usr/recipes-usr/lvgl/files/0001-usr-linux-1.0-r0/0002-CMakeLists.txt.patch index c34543d6c..220952146 100644 --- a/build/meta-usr/recipes-usr/lvgl/files/0001-usr-linux-1.0-r0/0002-CMakeLists.txt.patch +++ b/build/meta-usr/recipes-usr/lvgl/files/0001-usr-linux-1.0-r0/0002-CMakeLists.txt.patch @@ -1,9 +1,30 @@ --- /home/rossierd/soo/infrabase/build/tmp/work/usr-linux-1.0-r0/usr-linux-1.0/src/graphic/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 +++ ./src/graphic/CMakeLists.txt 2025-08-28 13:15:04.926201072 +0200 -@@ -0,0 +1,6 @@ +@@ -0,0 +1,27 @@ + -+add_subdirectory(drm_tool) -+add_subdirectory(drm-utils) -+add_subdirectory(kmscube) -+add_subdirectory(gbmtest) -+add_subdirectory(fb_benchmark) ++# DRM/KMS and GL demos. Every one of them needs libdrm, fb_benchmark gbm too, ++# and kmscube and gbmtest EGL and GLESv2 on top — none of which the minimal ++# buildroot configuration ships (it keeps fbdev + evdev for LVGL). Build each ++# one only when the rootfs provides what it links against, instead of failing ++# the whole user-space configure on a fresh tree. ++ ++find_package(PkgConfig REQUIRED) ++pkg_check_modules(IB_GRAPHIC_DRM QUIET libdrm) ++pkg_check_modules(IB_GRAPHIC_GBM QUIET gbm) ++pkg_check_modules(IB_GRAPHIC_GL QUIET egl glesv2) ++ ++if(IB_GRAPHIC_DRM_FOUND) ++ add_subdirectory(drm_tool) ++ add_subdirectory(drm-utils) ++else() ++ message(STATUS "graphic: no libdrm in the rootfs, skipping the DRM demos") ++endif() ++ ++if(IB_GRAPHIC_DRM_FOUND AND IB_GRAPHIC_GBM_FOUND) ++ add_subdirectory(fb_benchmark) ++ ++ if(IB_GRAPHIC_GL_FOUND) ++ add_subdirectory(kmscube) ++ add_subdirectory(gbmtest) ++ endif() ++endif() diff --git a/doc/source/build_system/build_system.rst b/doc/source/build_system/build_system.rst index c09efb271..8eee65c1e 100644 --- a/doc/source/build_system/build_system.rst +++ b/doc/source/build_system/build_system.rst @@ -122,7 +122,8 @@ invocation, so adding a layer is a one-line change there rather than a hand edit ``avz`` recipe, not the SO3 kernel. Which of ``atf``, ``optee`` and ``avz`` a given build actually compiles is decided -by ``IB_BOOT_CHAIN`` / ``IB_HYPERVISOR`` at the dependency level (``bsp.bbclass``), +by ``IB_BOOT_CHAIN`` at the dependency level (``bsp.bbclass``, through the +``IB_CHAIN_HAS_`` flags derived from it), not by adding and removing layers — the layer set is the same for every build. Let's focus on the **meta-linux** layer as an example. diff --git a/doc/source/conf.py b/doc/source/conf.py index e84bf34d3..728b0e34b 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -12,6 +12,7 @@ # serve to show the default. import os +import subprocess import sys import sphinx sys.path.insert(0, os.path.abspath('.')) @@ -69,11 +70,28 @@ # |version| and |release|, also used in various other places throughout the # built documents. # -# The short X.Y version. -version = u'0.5' +# It is derived from the git release tag by the very same helper the scripts' +# release banner uses (scripts/ibversion.sh), so the documentation never has +# to be bumped by hand at release time. The helper falls back to its +# IB_VERSION_FALLBACK constant when the tree carries no git tag — which is the +# case for the shallow CI checkout that publishes these pages. + +def _ib_version(): + helper = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts', 'ibversion.sh')) + + try: + out = subprocess.check_output(['sh', helper], universal_newlines=True) + except (OSError, subprocess.CalledProcessError): + return 'unknown' + + return out.strip() or 'unknown' + # The full version, including alpha/beta/rc tags. -release = u'0.5.0' +release = _ib_version() + +# The short X.Y version. +version = '.'.join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/source/index.rst b/doc/source/index.rst index eaca59288..6b342a214 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -18,6 +18,7 @@ dev_flow base_extension/base_extension Coding conventions + Release process glossary | @@ -43,6 +44,7 @@ Coding conventions and development flow - :ref:`Our coding conventions ` - :ref:`Our development flow ` +- :ref:`Release process ` To edit the documentation and to use the correct underlying policy, you can read `this documentation style guide `_. diff --git a/doc/source/release_process.rst b/doc/source/release_process.rst new file mode 100644 index 000000000..47738c35d --- /dev/null +++ b/doc/source/release_process.rst @@ -0,0 +1,207 @@ +.. _release_process: + +Release process +############### + +Infrabase follows a branch-per-release model, the same as SO3: development +happens on ``main``, and every minor version gets a long-lived maintenance +branch on which patch releases are tagged. This keeps stable lines alive for +backports — the product trees built on Infrabase pin a line, not a commit — +while ``main`` moves on. + +Overview +******** + +Three git objects work together, and GitHub surfaces them in different places: + +.. list-table:: + :header-rows: 1 + :widths: 22 20 58 + + * - Object + - Example + - Role + * - ``main`` branch + - ``main`` + - Continuous development (the next, unreleased version). + * - ``release/vX.Y`` branch + - ``release/v1.0`` + - Long-lived maintenance line for a minor version. Patch fixes land here + and are tagged. + * - Tag ``vX.Y.Z`` + - ``v1.0.0`` + - Immutable point marking a delivered version. Release candidates use the + ``-rc`` suffix (``v1.0.1-rc``). + * - GitHub Release + - "Infrabase v1.0.0" + - The release page (notes + assets), attached to a tag. Exactly one is + flagged *Latest*; ``-rc`` tags are published as *pre-release*. + +Versioning +********** + +Versions follow semantic versioning ``vMAJOR.MINOR.PATCH``. What a product tree +relies on is the build interface — the ``IB_*`` configuration variables, the +command line of the scripts, the layer layout and the classes recipes inherit — +so that is what the numbers are about: + +* **MAJOR** — breaking changes to that interface: a variable renamed or with a + new meaning, a script option removed, a class or layer reorganised so that a + product layer no longer applies. +* **MINOR** — new features, backward compatible (a new platform, boot stage, + script option). Opens a new ``release/vX.Y`` branch. +* **PATCH** — bug fixes only, cut *on* an existing ``release/vX.Y`` branch. + +Release candidates append ``-rc`` (optionally ``-rcN`` for successive +candidates), e.g. ``v1.1.0-rc``. + +Which release is running? +************************* + +Every script under ``scripts/`` prints the release it belongs to when it +starts, on stderr, once per invocation — also when it runs another one +(``build.sh`` runs bitbake through the ``scripts/bitbake`` wrapper, +``dbuild.sh`` runs a script in the container):: + + [infrabase v1.0.0] deploy.sh bsp-linux + +The version comes from ``scripts/ibversion.sh``, which reads the git release +tag (``git describe``) and keeps only the base version: a tagged commit and +development on top of ``v1.0.0`` both report ``1.0.0``, while ``-rc`` is kept. +A tree without git metadata falls back to the ``IB_VERSION_FALLBACK`` constant +of that script. ``ibversion.sh`` can also be run on its own. + +Branch layout +************* + +:: + + main ──●──●──●──●──●──●───────► development (next version) + \ + release/v1.0 ●──●──● maintenance line for 1.0.x + │ │ └─ v1.0.1 (tags live on the branch) + │ └──── v1.0.1-rc + └─────── v1.0.0 + +While a minor line has not diverged from ``main`` yet (no work started on the +next minor), its ``release/vX.Y`` branch and ``main`` may point at the same +commit — that is expected. + +Which fixes go on a release branch? +*********************************** + +Being a bug fix is *not* what sends a change to a release branch. ``main`` is +the continuous development line and carries both features **and** fixes as they +land; anything committed there simply ships in the next version. There are two +kinds of fix: + +* **A fix for unreleased code, or one that can wait for the next version.** + Nothing special — it is an ordinary commit on ``main`` and ships in the next + ``vX.Y.0``. Do *not* touch any release branch. +* **A fix for an already-published version** (e.g. a bug in ``v1.0.0``) that + must ship *before* the next version. Only this case uses the patch-release + procedure below: the fix lands on ``release/v1.0`` (tagged ``v1.0.1``) and is + also carried to ``main`` so it is not lost at the next minor. + +In other words, what sends a change to ``release/vX.Y`` is the need to patch a +*live, already-released* version — never the mere fact that it is a fix rather +than a feature. A documentation-only change does not justify a patch release +either: it rides the next version. + +Cutting a patch release (``vX.Y.Z``) +************************************ + +Patch fixes are committed **on the release branch**, then tagged. If a fix was +first merged into ``main``, cherry-pick it onto the branch rather than +fast-forwarding. Do it as a pull request whose base is the release branch, so +the workflows run on the exact tree the tag will point at. + +.. code-block:: sh + + git checkout release/v1.0 + git cherry-pick # or commit the fix directly + # bump IB_VERSION_FALLBACK in scripts/ibversion.sh to 1.0.1 + + # optional: publish a candidate first + git tag -a v1.0.1-rc -m "infrabase v1.0.1-rc" + git push origin release/v1.0 v1.0.1-rc + gh release create v1.0.1-rc --title "Infrabase v1.0.1-rc" \ + --target release/v1.0 --prerelease --generate-notes + + # final release + git tag -a v1.0.1 -m "infrabase v1.0.1" + git push origin release/v1.0 v1.0.1 + gh release create v1.0.1 --title "Infrabase v1.0.1" \ + --target release/v1.0 --latest --notes-file + +Cutting a new minor release (``vX.Y.0``) +**************************************** + +When ``main`` is ready for a new minor version, prepare it on ``main`` first (a +pull request carrying the ``CHANGELOG`` entry, the *Maintained versions* table +and ``IB_VERSION_FALLBACK`` set to the version being cut), then branch off and +tag: + +.. code-block:: sh + + git checkout main + git checkout -b release/v1.1 + git push -u origin release/v1.1 + + git tag -a v1.1.0 -m "infrabase v1.1.0" + git push origin v1.1.0 + gh release create v1.1.0 --title "Infrabase v1.1.0" \ + --target release/v1.1 --latest --notes-file + +The release notes are the version's ``CHANGELOG`` entry. + +After tagging: propagate the release to ``main`` +************************************************ + +A release is not finished when the tag is pushed. The references to the current +version that live on ``main`` must be bumped right after every release (they +drift silently otherwise): + +* the *Maintained versions* table in ``README.md`` (the *Latest release* + column of the line, and the *Status* column when a new minor line starts); +* a ``CHANGELOG`` entry summarizing the release (same content as the GitHub + Release notes, kept in the repository for offline reference); +* ``IB_VERSION_FALLBACK`` in ``scripts/ibversion.sh``, used only when the tree + carries no git metadata (a tarball export, a copy without ``.git``). + +Two version strings need **no** action: the scripts' release banner and the +documentation version both derive from the release tag +(``scripts/ibversion.sh``, reused by ``doc/source/conf.py``). + +Before tagging: check the tree +****************************** + +The ``Docs`` workflow runs on every branch, ``release/**`` included, and must be +green on the commit the tag will point at:: + + gh run list --workflow Docs --branch release/v1.0 + +Infrabase has no build workflow of its own — a full build needs a kernel, a +rootfs and a privileged container for the deploy — so the build itself is +checked by hand, in the build container, on the commit being tagged: at least +``virt64`` with ``build.sh bsp-linux``, ``deploy.sh bsp-linux`` and a boot to the +login prompt with ``st.sh``. The product trees that consume a release (SO3, +the course trees, EDGE-M1, MICOFE) build it again in their own CI. + +Check ``IB_VERSION_FALLBACK`` too: it must already read the version being +tagged, since the tagged tree is what a gitless copy reports. It appears twice +in this page on purpose — bump it **in the release commit set** so the tag is +right, and again when propagating to ``main`` so the next release does not start +a version behind. + +Rules of thumb +************** + +* One ``release/vX.Y`` branch **per minor**, not per patch — patches are tags + *on* the branch. +* Tags are immutable: never move or delete a published ``vX.Y.Z`` tag. To + correct a release, cut the next patch. +* Exactly one GitHub Release carries the *Latest* flag; every ``-rc`` Release is + a *pre-release* so it never shadows the latest stable version. +* Once a ``release/vX.Y`` branch has diverged from ``main``, backport fixes with + ``git cherry-pick`` — do not fast-forward the branch onto ``main``. diff --git a/doc/source/user_guide.rst b/doc/source/user_guide.rst index 64089de4c..731f34b21 100644 --- a/doc/source/user_guide.rst +++ b/doc/source/user_guide.rst @@ -166,90 +166,96 @@ Platforms .. _boot_axes: -What gets built: the two axes -============================= +What gets built: the boot chain +=============================== Infrabase builds four components — **ATF**, **OP-TEE**, **AVZ** and **Linux**. -Which of them end up in an image is decided by two *independent* variables in -``build/conf/local.conf``: +Which of them end up in an image is decided by one variable in +``build/conf/local.conf``, ``IB_BOOT_CHAIN``: the stages that run before the +payload, **in the order they run**, joined by ``+``: .. list-table:: :header-rows: 1 - :widths: 24 76 - - * - Variable - - Values - * - ``IB_BOOT_CHAIN`` - - the firmware underneath the OS — - ``uboot`` (U-Boot alone), - ``atf+uboot`` (ATF BL1/BL2/BL31 + U-Boot), - ``atf+optee+uboot`` (… + OP-TEE as BL32, a secure world) - * - ``IB_HYPERVISOR`` - - what the firmware hands control to — - ``none`` (Linux runs directly on the firmware) or - ``avz`` (AVZ runs at EL2, Linux is its guest) - -They are orthogonal on purpose: AVZ boots fine on a bare U-Boot chain (QEMU's -``virtualization=on`` gives EL2 with no secure world at all), and a secure -world is equally useful under a plain Linux. Every combination a platform -supports is buildable: + :widths: 16 84 + + * - Stage + - Role + * - ``atf`` + - ARM Trusted Firmware (BL1/BL2/BL31). + * - ``optee`` + - OP-TEE as BL32, a secure world. Needs ``atf``. + * - ``uboot`` + - U-Boot. + * - ``avz`` + - The AVZ hypervisor at EL2, entered by U-Boot, with Linux as its guest. + Needs ``uboot``, after it. + * - ``mcuboot`` + - MCUboot, which picks an image out of a flash slot and runs it. + +So ``uboot`` is Linux on a bare U-Boot, ``atf+optee+uboot`` adds a secure world, +``uboot+avz`` runs Linux as an AVZ guest with no secure world (QEMU's +``virtualization=on`` gives EL2 without one), and ``atf+optee+uboot+avz`` has +both. The order is checked, not just the spelling — ``atf+avz+uboot`` is +refused — and a chain must contain ``uboot`` or ``mcuboot``, or nothing can +enter the payload. + +Everything else about the boot shape is **derived** from that one value by +``ib_normalize_boot_axes`` (``meta/classes/base.bbclass``): ``IB_HYPERVISOR`` +(``avz`` when the chain carries the stage, ``none`` otherwise), the +``IB_CHAIN_HAS_`` flags the recipes gate on, and which ITS is assembled. +Nothing else has to be set, and nothing can disagree with it. + +What each platform can run is declared as a set of stages, +``IB_BOOT_STAGES_SUPPORTED:`` (plus ``IB_BOOT_STAGES_REQUIRED`` where a +stage is mandatory): .. list-table:: :header-rows: 1 - :widths: 22 26 26 26 + :widths: 24 38 38 * - Platform - - ``uboot`` - - ``atf+uboot`` - - ``atf+optee+uboot`` + - Supported stages + - Required * - *virt64* - - none / avz - - none / avz - - none / avz - * - *verdin-imx8mp* + - ``atf optee uboot avz mcuboot`` - — - - none / avz - - none / avz + * - *verdin-imx8mp* + - ``atf optee uboot avz`` + - ``atf`` * - *rpi4_64* - - none / avz - - none / avz - - — - * - *rpi4* - - none - - — - - — - * - *virt32* - - none + - ``atf uboot avz`` - — + * - *rpi4*, *virt32*, *x86-qemu* + - ``uboot`` - — -An absent cell is a hardware or upstream limit, not an omission, and each one -is explained next to ``IB_BOOT_CHAINS_SUPPORTED`` in ``build/conf/local.conf``. -In short: the i.MX8MP boot ROM -always installs BL31, so there is no bare-U-Boot chain on the Verdin; TF-A's -``rpi4`` port is AArch64-only, so the 32-bit Pi has no ATF; OP-TEE has no -``plat-rpi4`` upstream and the BCM2711 has no secure memory controller, so a -secure world on either Pi could never be a real TEE; and AVZ ships aarch64 -defconfigs only, so the 32-bit platforms are standalone-Linux only. +A missing stage is a hardware or upstream limit, not an omission, and each one +is explained next to ``IB_BOOT_STAGES_SUPPORTED`` in ``build/conf/local.conf``. +In short: the i.MX8MP boot ROM always installs BL31, so there is no chain +without ``atf`` on the Verdin; TF-A's ``rpi4`` port is AArch64-only, so the +32-bit Pi has no ATF; OP-TEE has no ``plat-rpi4`` upstream and the BCM2711 has +no secure memory controller, so a secure world on either Pi could never be a +real TEE; and AVZ ships aarch64 defconfigs only, so the 32-bit platforms are +standalone-Linux only. -Asking for an unsupported combination is refused at parse time, naming what -the platform does support:: +Asking for a stage the platform cannot run is refused at parse time, naming +what it does support:: - ERROR: Platform "rpi4_64" cannot boot IB_BOOT_CHAIN="atf+optee+uboot". - Supported on this platform: uboot atf+uboot. - See IB_BOOT_CHAINS_SUPPORTED in build/conf/local.conf for why. + ERROR: Platform "rpi4_64" cannot run boot stage "optee" (IB_BOOT_CHAIN="atf+optee+uboot"). + Supported on this platform: atf uboot avz. + See IB_BOOT_STAGES_SUPPORTED in build/conf/local.conf for why. .. note:: - ``IB_TARGET_ITS`` is *derived* from ``IB_HYPERVISOR`` — ```` when it is - ``none``, ``_avz`` when it is ``avz`` — so the boot image always matches - the requested shape. Set it explicitly only for a hand-written ITS. + ``IB_TARGET_ITS`` is *derived* from the chain — ```` without ``avz``, + ``_avz`` with it — so the boot image always matches the requested + shape. Set it explicitly only for a hand-written ITS. .. note:: ``IB_BOOT_CHAIN = "full"`` is still accepted as a legacy alias for - ``atf+optee+uboot`` **plus** ``IB_HYPERVISOR = "avz"`` (the edge-m1 capsule - chain), so a tree aligning onto this one keeps building unchanged. + ``atf+optee+uboot+avz`` (the edge-m1 capsule chain), so a tree aligning onto + this one keeps building unchanged. Key variables ============= @@ -266,12 +272,12 @@ Key variables - Kernel defconfig, e.g. ``virt64_defconfig``. * - ``IB_TARGET_ITS:linux:`` - ITS basename used to build the FIT image (``.itb``). Derived from - ``IB_HYPERVISOR``; override only for a hand-written ITS. + the boot chain; override only for a hand-written ITS. * - ``IB_BOOT_CHAIN`` - - Firmware chain: ``uboot`` (default), ``atf+uboot`` or + - The ordered boot stages, e.g. ``uboot`` (default), ``uboot+avz``, ``atf+optee+uboot``. See :ref:`boot_axes`. * - ``IB_HYPERVISOR`` - - ``none`` (default) or ``avz``. See :ref:`boot_axes`. + - **Derived** from ``IB_BOOT_CHAIN`` (``avz`` or ``none``); do not set it. * - ``IB_CONFIG:avz:`` - AVZ defconfig, e.g. ``virt64_avz_defconfig``. * - ``IB_RAMFS_SOURCE`` diff --git a/scripts/bitbake b/scripts/bitbake index 7a5bf6c18..ad9312305 100755 --- a/scripts/bitbake +++ b/scripts/bitbake @@ -6,6 +6,9 @@ # Helps catch the case where the wrong env.sh is loaded for the # project being worked on. +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + if test -z "$IB_ROOT_DIR" || test -z "$BUILDDIR"; then echo "bitbake wrapper: IB_ROOT_DIR/BUILDDIR not set; source env.sh first." >&2 exit 1 diff --git a/scripts/build.sh b/scripts/build.sh index 9dc8af6bc..0ad971bac 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -12,6 +12,9 @@ # Copyright (c) 2014-2026 REDS Institute, HEIG-VD # Copyright (c) 2023-2026 EDGEMTech +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + progname=$(basename $0) # Resolve the project root from this script's own location, cd there, diff --git a/scripts/common/banner.sh b/scripts/common/banner.sh new file mode 100644 index 000000000..dfbff1606 --- /dev/null +++ b/scripts/common/banner.sh @@ -0,0 +1,28 @@ +# Copyright (c) 2026 EDGEMTech SA + +# Source me first thing from every user-facing script under scripts/. +# +# Prints which Infrabase release is running, on stderr so it never mixes +# with what a script writes on stdout: +# +# [infrabase v1.0.0] deploy.sh bsp-linux +# +# Once per invocation, not once per script: scripts call each other +# (build.sh runs the scripts/bitbake wrapper, deploy.sh runs +# tezi-feed-serve.sh), so the first one to print exports IB_BANNER_SHOWN and +# the nested ones stay quiet. dbuild.sh forwards it into the container for the +# same reason. +# +# The version comes from scripts/ibversion.sh (the git release tag). + +if [ -z "${IB_BANNER_SHOWN:-}" ]; then + _ib_banner_dir="$(cd "$(dirname "$(command -v -- "$0")")" && pwd)" + + printf '[infrabase v%s] %s%s\n' \ + "$(sh "$_ib_banner_dir/ibversion.sh")" \ + "$(basename "$0")" "${*:+ $*}" >&2 + + IB_BANNER_SHOWN=1 + export IB_BANNER_SHOWN + unset _ib_banner_dir +fi diff --git a/scripts/dbuild.sh b/scripts/dbuild.sh index 29f58cc30..c1c3f62a0 100755 --- a/scripts/dbuild.sh +++ b/scripts/dbuild.sh @@ -26,6 +26,9 @@ # # Copyright (c) 2026 REDS Institute - HEIG-VD +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + set -e progname=$(basename "$0") @@ -123,8 +126,10 @@ set -- -e IB_TREE="$IB_ROOT" -e IB_CWD="$cwd" "$@" # (BB_ENV_PASSTHROUGH_ADDITIONS) when they are set on the host. Without it # `IB_FORCE_ATTACH=1 dbuild.sh build.sh ` — what the attach guard # itself advises — never reached the container, and the guard kept refusing. +# IB_BANNER_SHOWN too: this script already printed the release banner, so the +# command it runs in the container must not print it a second time. -for _v in IB_FORCE_ATTACH IB_PARTITION_LAYOUT; do +for _v in IB_FORCE_ATTACH IB_PARTITION_LAYOUT IB_BANNER_SHOWN; do eval "_val=\${$_v:-}" [ -n "$_val" ] && set -- -e "$_v=$_val" "$@" done diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 9118f8ebc..42405ebdb 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -10,6 +10,9 @@ # Copyright (c) 2014-2026 REDS Institute, HEIG-VD # Copyright (c) 2023-2026 EDGEMTech +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + progname=$(basename $0) # Resolve project root from this script's own location, cd there, and diff --git a/scripts/diffdir.sh b/scripts/diffdir.sh index e8ccfa684..54aa8ba7c 100755 --- a/scripts/diffdir.sh +++ b/scripts/diffdir.sh @@ -2,6 +2,9 @@ # Copyright (c) 2025-2026 EDGEMTech SA +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + source_dir=$1 target_dir=$2 output_dir=$3 diff --git a/scripts/ibversion.sh b/scripts/ibversion.sh new file mode 100755 index 000000000..051fc6ef6 --- /dev/null +++ b/scripts/ibversion.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +# Copyright (c) 2026 EDGEMTech SA + +# Print the Infrabase release version, e.g. "1.0.0". +# +# The version is derived from the git release tag (vX.Y.Z) of the tree this +# script belongs to, so it never has to be bumped by hand. Only the base +# version is kept: the "--g" and "-dirty" suffixes git-describe +# adds on a commit past the tag are stripped, so both the tagged commit and +# development on top of v1.0.0 report "1.0.0". An "-rc" suffix is kept. +# +# When the tree carries no git metadata (a tarball export, a copy without +# .git), the IB_VERSION_FALLBACK constant below is printed instead. It is +# bumped with every release — see doc/source/release_process.rst. +# +# Used by the banner every script prints (scripts/common/banner.sh) and by the +# documentation (doc/source/conf.py). +# +# Usage: ibversion.sh + +IB_VERSION_FALLBACK="1.0.0" + +_tree=$(cd "$(dirname "$(command -v -- "$0")")/.." && pwd) + +if _v=$(git -C "$_tree" describe --tags --match 'v[0-9]*' 2>/dev/null) && [ -n "$_v" ]; then + _v=$(printf '%s' "$_v" | sed -e 's/-[0-9][0-9]*-g[0-9a-f]*$//' -e 's/-dirty$//') + printf '%s\n' "${_v#v}" + exit 0 +fi + +printf '%s\n' "$IB_VERSION_FALLBACK" diff --git a/scripts/init_storage.sh b/scripts/init_storage.sh index 19f1c36b3..7d6c0b60f 100755 --- a/scripts/init_storage.sh +++ b/scripts/init_storage.sh @@ -6,6 +6,9 @@ # — the recipe internally invokes losetup/fdisk/parted/mkfs via # `sudo -n` against the timestamp opened here. +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + progname=$(basename "$0") pr_usage() diff --git a/scripts/makeusr.sh b/scripts/makeusr.sh index fef3ede14..73e11a44a 100755 --- a/scripts/makeusr.sh +++ b/scripts/makeusr.sh @@ -11,6 +11,9 @@ # Copyright (c) 2026 Daniel Rossier, REDS Institute - HEIG-VD # +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + set -euo pipefail # The script operates on the *current directory* (so it can live in ~/scripts), diff --git a/scripts/mount.sh b/scripts/mount.sh index af9096a92..e52ae4a06 100755 --- a/scripts/mount.sh +++ b/scripts/mount.sh @@ -6,6 +6,9 @@ # recipe internally invokes mount/losetup via `sudo -n` against the # timestamp opened here. +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + progname=$(basename "$0") pr_usage() diff --git a/scripts/recovery-edgem.sh b/scripts/recovery-edgem.sh index 6137c2b0d..c805f6d8b 100755 --- a/scripts/recovery-edgem.sh +++ b/scripts/recovery-edgem.sh @@ -5,6 +5,9 @@ # Launch the EDGE-M1 customized Toradex Easy Installer (auto feed-add). # Build the FIT first with: scripts/tezi-custom/build.sh +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + set -e DIR=$(cd "$(dirname "$0")/tezi-custom" && pwd) if [ ! -f "$DIR/tezi.itb" ]; then diff --git a/scripts/st.sh b/scripts/st.sh index 7041a6b06..97023494d 100755 --- a/scripts/st.sh +++ b/scripts/st.sh @@ -2,6 +2,9 @@ # Copyright (c) 2025-2026 EDGEMTech SA +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + # Resolve project root from this script's own location, cd there, and # source env.sh — prompting the user first if the parent shell points # at a different tree. Every relative path below (filesystem/..., diff --git a/scripts/tezi-feed-serve.sh b/scripts/tezi-feed-serve.sh index eba496b75..1acaf0b40 100755 --- a/scripts/tezi-feed-serve.sh +++ b/scripts/tezi-feed-serve.sh @@ -26,6 +26,9 @@ # leaves a working feed behind with no manual step. It is idempotent and # silent when the server is already up. +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + progname=$(basename "$0") IB_ROOT=$(cd "$(dirname "$(command -v -- "$0")")/.." && pwd -P) diff --git a/scripts/umount.sh b/scripts/umount.sh index e7cf23864..ed29cf3e8 100755 --- a/scripts/umount.sh +++ b/scripts/umount.sh @@ -6,6 +6,9 @@ # recipe internally invokes umount/losetup via `sudo -n` against the # timestamp opened here. +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + progname=$(basename "$0") pr_usage() diff --git a/scripts/updiff.sh b/scripts/updiff.sh index 1b653dc22..8873ab7df 100755 --- a/scripts/updiff.sh +++ b/scripts/updiff.sh @@ -2,5 +2,8 @@ # Copyright (c) 2025-2026 EDGEMTech SA +# Release banner, once per invocation (see scripts/common/banner.sh). +. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/banner.sh" + bitbake $1 -c updiff