3. Build system
MICOFE is built with the Infrabase build system (bitbake based), aligned on
the SO3 release the framework is pinned to (currently the v6.3.0 tag).
The build tree follows the SO3 reference model: shared recipes and scripts are
kept identical to SO3, and only genuine MICOFE additions (the framebuffer/input
forwarding, the EMISO engine, the agency applications) diverge.
3.1. Source model
The components fall into two categories:
Fetched components:
so3(the capsule kernel),avz(the hypervisor),u-bootandqemuare fetched at build time from their upstream repositories. SO3 and AVZ are pinned to an SO3 release tag throughSRCREV/IB_SO3_TAGinbuild/meta-so3/recipes-so3/{so3,avz}. The fetched trees at the repository root (so3/,avz/,u-boot/,qemu/) are build products and are not committed.In-tree components: the Linux agency kernel patches live in
build/meta-linux— the SOO agency set follows the SO3soo-genericmodel (one generic patch directory shared by every agency kernel, plus a per-kernel directory whose same-named patches shadow the generic ones); the MICOFE vfbdev/vinput backends and their wiring are carried directly in MICOFE’s copy of the generic set — and the MICOFE user space applications are committed underlinux/usr(src/sooholds the capsule management applications, the framebuffer/input forwarders and the EMISO engine). They are built in place — no patch materialization.
3.2. Building
The entry point is scripts/build.sh with a positional recipe name:
./scripts/build.sh bsp-linux # full agency BSP (kernel, u-boot, rootfs, usr, ITBs)
./scripts/build.sh bsp-capsules # the SO3 capsule image (virt64_capsule.itb)
./scripts/build.sh so3 # a single component (also: avz, uboot, usr-linux, ...)
./scripts/build.sh -l # list the available recipes
./scripts/build.sh -c bsp-linux # clean, then rebuild
For a fast edit/build loop on the user-space applications,
scripts/makeusr.sh (run from linux/usr) does a direct cmake+make —
including the out-of-tree kernel modules — without driving bitbake;
deploy.sh usr-linux then pushes the result onto the media.
bitbake runs unprivileged; the few privileged operations (losetup, mkfs,
rootfs extraction) go through sudo -n. Run
scripts/common/setup_sudo.sh once so the sudo timestamp is shared with the
build (it installs a sudoers drop-in enabling global timestamps).
Building bsp-linux bakes the agency applications into
rootfs.cpio: the user space is compiled, then injected into the rootfs
archive as a build step. Deploying never rebuilds nor modifies that archive.
3.2.1. Containerized build (dbuild.sh)
The whole build environment (cross toolchains — including the bare-metal
aarch64-none-elf AVZ/SO3 toolchain that is so easy to miss on a
hand-provisioned host — host packages, Python) is available as a Docker
image, defined under docker/build-env and driven by
scripts/dbuild.sh:
./scripts/dbuild.sh --build # build the micofe-build:1.0 image (once)
./scripts/dbuild.sh build.sh bsp-linux # run any front-end script inside
./scripts/dbuild.sh # interactive shell, env.sh sourced
./scripts/dbuild.sh st.sh -d # graphical QEMU from the container
The image carries only the environment: the repository stays on the host and is bind-mounted at its own absolute path, so bitbake stamps, the buildroot host tree and the CMake caches remain valid and a tree can be built from inside or outside the container interchangeably. The container runs as the calling host user (UID/GID mapped at run time) and carries a blanket sudo rule, so the privileged storage steps never prompt.
3.2.2. Image assembly (ITS render)
The FIT image sources (.its) are templates committed in the layers
(build/meta-bsp/recipes-bsp/{linux,so3}/files/its/). At build time the
shared do_render_its task expands their ${IB_*_PATH} placeholders and
renders them into the git-ignored linux/images/ (or so3/images/),
where do_itb runs mkimage. The embedded ramfs is selected by
IB_RAMFS_SOURCE in build/conf/local.conf:
"initrd"(MICOFE default) — the small, git-trackedboard/<plat>/initrd.cpiobusybox ramdisk. Its/initmounts the ext4 rootfs on the second partition andswitch_root’s into it (two-stage boot)."rootfs"— the full buildrootrootfs.cpio, run from RAM.
3.3. Deploying
scripts/deploy.sh is a pure media write (nothing is rebuilt):
./scripts/deploy.sh bsp-linux # ITBs + uEnv.txt on p1, agency rootfs on p2
./scripts/deploy.sh bsp-capsules # capsule .itb into p2:/mnt/capsules/image/
The target is the filesystem/work/sdcard.img.<plat> image
(IB_STORAGE_MODE = "soft"), created once with
./scripts/build.sh filesystem.
3.4. Booting
scripts/st.sh boots the deployed image in QEMU (serial console on stdio).
The AVZ boot is a two-ITB chain: U-Boot loads virt64_avz.itb (the
hypervisor) and virt64_guest.itb (the Linux agency), then jumps to AVZ
through the guest-boot command (AVZ FIT in x0, guest ITB in x1).
st.sh detects the AVZ configuration from the selected ITS and enables EL2
(-M virt,virtualization=on) automatically.
The agency then performs the two-stage boot: the embedded busybox ramdisk
mounts the full rootfs on /dev/vda2 and switches into it, up to the MICOFE
login on the serial console.
3.5. Target platforms
The platform is selected by IB_PLATFORM in build/conf/local.conf.
When switching platforms, purge the per-recipe work directories and stamps
(build/tmp/work, build/tmp/stamps) together with the in-place source
trees (so3/, avz/, linux/usr/build) — the fetched/attached trees
are replaced by the new platform’s sources and a stale tree silently builds
the wrong target.
3.5.1. virt64 (QEMU)
The development and validation platform. The whole stack is runtime-validated
there: agency boot, capsule injection (s3c-* tools and the EMISO REST
API), the per-capsule VLOGS logs and the virtualized framebuffer chain. st.sh -d
opens the QEMU GTK window showing the SO3/PL111 screen; the agency real
framebuffer additionally requires modern virtio:
./scripts/st.sh "-global virtio-mmio.force-legacy=false -device virtio-gpu-device"
3.5.2. rpi4_64 (Raspberry Pi 4)
Set IB_PLATFORM ?= "rpi4_64" and build as usual — the full chain compiles
up to the two AVZ boot images (rpi4_64_avz.itb and
rpi4_64_linux_guest.itb under linux/images/): the SO3 capsule, AVZ
(rpi4_64_avz_soo_defconfig), the Raspberry Pi kernel with the SOO agency
patch set (including the vfbdev/vinput backends), the bcm2711-rpi-4-b.dtb
and the buildroot root file system. The AVZ guest ITS load addresses follow
the rpi4 memory map (kernel 0x10000000, FDT 0x15000000, initrd
0x15c00000; AVZ at 0x00080000).
Note
The rpi4_64 environment is build-validated only — it has not been booted on a board yet. Flashing, the U-Boot/guest-boot bring-up and the framebuffer test on the real scanout are the next step.
Note
The user-space test module for rpi4_64 is the generic modtry; the
Sense-HAT senseled module requires the VSENSELED/VSENSEJ
kernel backends, which have never been enabled in the rpi4 defconfig.
3.6. Capsule lifecycle
The capsule management applications shipped in the agency /root are the
SO3 s3c-* tools:
s3c-inject /mnt/capsules/image/virt64_capsule.itb # inject and start a capsule
s3c-list # list residing capsules and their state
s3c-save <file> # snapshot a capsule
s3c-restore <file> # restore a snapshot
s3c-shutdown <id> # shut a capsule down
They talk to the SOO core driver through /dev/soo/core (char device,
major 126), created at boot by the /etc/init.d/S30soo script (the agency
runs SysVinit). A living capsule exposes its console through the vuart
backend, multiplexed on the agency serial console.
The EMISO engine offers the same lifecycle through a Docker-compatible REST API.