# SPDX-FileCopyrightText: Copyright (C) 2025 Bruce Ashfield # # SPDX-License-Identifier: MIT # # vcontainer-initramfs-create.inc # =========================================================================== # Shared code for building QEMU boot blobs (vdkr/vpdmn) - Image-based approach # =========================================================================== # # This .inc file contains common code for building boot blobs using # a proper Yocto image-based initramfs instead of extracting files. # # Required variables from including recipe: # VCONTAINER_RUNTIME - "vdkr" or "vpdmn" # # Boot flow: # QEMU boots kernel + tiny initramfs (cpio.gz from image recipe) # -> preinit mounts rootfs.img from /dev/vda # -> switch_root into rootfs.img # -> ${VCONTAINER_RUNTIME}-init.sh runs # # =========================================================================== HOMEPAGE = "https://git.yoctoproject.org/meta-virtualization/" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" inherit deploy # Not built by default - user must explicitly request via bitbake or vcontainer-native EXCLUDE_FROM_WORLD = "1" # No extraction tools needed - we use pre-built images DEPENDS = "" # Force rebuild control: # Set VCONTAINER_FORCE_BUILD = "1" in local.conf to disable stamp caching # and force compile/deploy to always run. Useful when debugging dependency issues. # Default: use normal stamp caching for faster incremental builds VCONTAINER_FORCE_BUILD ?= "" python () { if d.getVar('VCONTAINER_FORCE_BUILD') == '1': d.setVar('SSTATE_SKIP_CREATION', '1') d.setVarFlag('do_compile', 'nostamp', '1') d.setVarFlag('do_deploy', 'nostamp', '1') # Conditionally set mcdepends when our multiconfig is configured # (avoids parse errors when BBMULTICONFIG is not set, e.g. yocto-check-layer) mc = d.getVar('VCONTAINER_MULTICONFIG') bbmulticonfig = (d.getVar('BBMULTICONFIG') or "").split() if mc in bbmulticonfig: d.setVarFlag('do_compile', 'mcdepends', 'mc:%s::virtual/kernel:do_deploy' % mc) } # Only populate native sysroot, skip target sysroot to avoid libgcc conflicts INHIBIT_DEFAULT_DEPS = "1" # Dependencies: # 1. The tiny initramfs image (produces cpio.gz) # 2. The multiconfig rootfs image (produces squashfs) # 3. The kernel from main build # # Both initramfs and rootfs images are in the same multiconfig do_compile[depends] = "${VCONTAINER_RUNTIME}-tiny-initramfs-image:do_image_complete" do_compile[depends] += "${VCONTAINER_RUNTIME}-rootfs-image:do_image_complete" # mcdepends set conditionally in anonymous python below S = "${UNPACKDIR}" B = "${WORKDIR}/build" def get_kernel_image_name(d): arch = d.getVar('TARGET_ARCH') if arch == 'aarch64': return 'Image' elif arch in ['x86_64', 'i686', 'i586']: return 'bzImage' elif arch == 'arm': return 'zImage' return 'Image' def get_multiconfig_name(d): arch = d.getVar('TARGET_ARCH') if arch == 'aarch64': return 'vruntime-aarch64' elif arch in ['x86_64', 'i686', 'i586']: return 'vruntime-x86-64' return 'vruntime-aarch64' def get_blob_arch(d): """Map TARGET_ARCH to vrunner blob architecture (aarch64 or x86_64)""" arch = d.getVar('TARGET_ARCH') if arch == 'aarch64': return 'aarch64' elif arch in ['x86_64', 'i686', 'i586']: return 'x86_64' return 'aarch64' KERNEL_IMAGETYPE_INITRAMFS = "${@get_kernel_image_name(d)}" VCONTAINER_MULTICONFIG = "${@get_multiconfig_name(d)}" BLOB_ARCH = "${@get_blob_arch(d)}" # Path to the multiconfig build output VCONTAINER_MC_DEPLOY = "${TOPDIR}/tmp-${VCONTAINER_MULTICONFIG}/deploy/images/${MACHINE}" do_compile() { mkdir -p ${B} MC_TMPDIR="${TOPDIR}/tmp-${VCONTAINER_MULTICONFIG}" MC_DEPLOY="${MC_TMPDIR}/deploy/images/${MACHINE}" # ========================================================================= # PART 1: COPY TINY INITRAMFS (cpio.gz from image recipe) # ========================================================================= bbnote "Copying tiny initramfs from image build..." INITRAMFS_SRC="${MC_DEPLOY}/${VCONTAINER_RUNTIME}-tiny-initramfs-image-${MACHINE}.cpio.gz" if [ ! -f "${INITRAMFS_SRC}" ]; then bbfatal "Initramfs not found at ${INITRAMFS_SRC}. Build it first with: bitbake mc:${VCONTAINER_MULTICONFIG}:${VCONTAINER_RUNTIME}-tiny-initramfs-image" fi cp "${INITRAMFS_SRC}" ${B}/initramfs.cpio.gz INITRAMFS_SIZE=$(stat -c%s ${B}/initramfs.cpio.gz) bbnote "Initramfs copied: ${INITRAMFS_SIZE} bytes ($(expr ${INITRAMFS_SIZE} / 1024)KB)" # ========================================================================= # PART 2: COPY ROOTFS (squashfs from image recipe) # ========================================================================= bbnote "Copying rootfs from image build..." ROOTFS_SRC="${MC_DEPLOY}/${VCONTAINER_RUNTIME}-rootfs-image-${MACHINE}.rootfs.squashfs" if [ ! -f "${ROOTFS_SRC}" ]; then bbfatal "Rootfs image not found at ${ROOTFS_SRC}. Build it first with: bitbake mc:${VCONTAINER_MULTICONFIG}:${VCONTAINER_RUNTIME}-rootfs-image" fi cp "${ROOTFS_SRC}" ${B}/rootfs.img ROOTFS_SIZE=$(stat -c%s ${B}/rootfs.img) bbnote "Rootfs image copied: ${ROOTFS_SIZE} bytes ($(expr ${ROOTFS_SIZE} / 1024 / 1024)MB)" # ========================================================================= # PART 3: COPY KERNEL # ========================================================================= bbnote "Copying kernel image..." KERNEL_FILE="${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE_INITRAMFS}" if [ -f "${KERNEL_FILE}" ]; then cp "${KERNEL_FILE}" ${B}/kernel KERNEL_SIZE=$(stat -c%s ${B}/kernel) bbnote "Kernel copied: ${KERNEL_SIZE} bytes ($(expr ${KERNEL_SIZE} / 1024 / 1024)MB)" else bbwarn "Kernel not found at ${KERNEL_FILE}" fi } do_install[noexec] = "1" do_package[noexec] = "1" do_packagedata[noexec] = "1" do_package_write_rpm[noexec] = "1" do_package_write_ipk[noexec] = "1" do_package_write_deb[noexec] = "1" do_populate_sysroot[noexec] = "1" do_deploy() { # Deploy to ${VCONTAINER_RUNTIME}/ subdirectory install -d ${DEPLOYDIR}/${VCONTAINER_RUNTIME}/${BLOB_ARCH} if [ -f ${B}/initramfs.cpio.gz ]; then install -m 0644 ${B}/initramfs.cpio.gz ${DEPLOYDIR}/${VCONTAINER_RUNTIME}/${BLOB_ARCH}/ bbnote "Deployed initramfs.cpio.gz to ${VCONTAINER_RUNTIME}/${BLOB_ARCH}/" fi if [ -f ${B}/rootfs.img ]; then install -m 0644 ${B}/rootfs.img ${DEPLOYDIR}/${VCONTAINER_RUNTIME}/${BLOB_ARCH}/ bbnote "Deployed rootfs.img to ${VCONTAINER_RUNTIME}/${BLOB_ARCH}/" fi if [ -f ${B}/kernel ]; then install -m 0644 ${B}/kernel ${DEPLOYDIR}/${VCONTAINER_RUNTIME}/${BLOB_ARCH}/${KERNEL_IMAGETYPE_INITRAMFS} bbnote "Deployed kernel as ${VCONTAINER_RUNTIME}/${BLOB_ARCH}/${KERNEL_IMAGETYPE_INITRAMFS}" fi cat > ${DEPLOYDIR}/${VCONTAINER_RUNTIME}/${BLOB_ARCH}/README << EOF ${VCONTAINER_RUNTIME} Boot Blobs ================== Built for: ${TARGET_ARCH} Machine: ${MACHINE} Multiconfig: ${VCONTAINER_MULTICONFIG} Date: $(date) Files: ${KERNEL_IMAGETYPE_INITRAMFS} - Kernel image for QEMU initramfs.cpio.gz - Tiny initramfs (busybox + preinit) rootfs.img - Root filesystem with container tools Boot flow: QEMU boots kernel + initramfs -> preinit mounts rootfs.img from /dev/vda -> switch_root into rootfs.img -> ${VCONTAINER_RUNTIME}-init.sh runs container commands EOF } addtask deploy after do_compile before do_build