Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
oniro-image.bbclass 6.28 KiB
# SPDX-FileCopyrightText: Huawei Inc.
#
# SPDX-License-Identifier: Apache-2.0

# Oniro Project functionality for images

# List of tty to mask getty for
SYSTEMD_MASK_GETTY ?= ""

systemd_mask_getty () {
    if [ -e ${IMAGE_ROOTFS}${root_prefix}/lib/systemd/systemd ]; then
        for i in ${SYSTEMD_MASK_GETTY}; do
            systemctl --root="${IMAGE_ROOTFS}" mask "getty@${i}.service"
        done
    fi
}

# read_only_rootfs_hook
revert_volatile_dropear_hostkeys () {
    sed -i '/DROPBEAR_RSAKEY_DIR/d' ${IMAGE_ROOTFS}/etc/default/dropbear
}

IMAGE_PREPROCESS_COMMAND_append = " ${@ 'systemd_mask_getty;' if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d) and not bb.utils.contains('IMAGE_FEATURES', 'stateless-rootfs', True, False, d) else ''} revert_volatile_dropear_hostkeys"

IMAGE_FEATURES_append = " read-only-rootfs"

# Convert all KERNEL_DEVICETREE enties to IMAGE_BOOT_FILES entries
def dtb_boot_files(d):
    k_dt = d.getVar('KERNEL_DEVICETREE')
    if not k_dt:
        return ''
    return ' '.join(['kernel/{dtb};{dtb}'.format(dtb=dt) for dt in k_dt.split()])

# Convert all extlinux files to IMAGE_BOOT_FILES entries
def extlinux_boot_files(d):
    import os
    deploy_dir_image = d.getVar('DEPLOY_DIR_IMAGE')
    deploy_extlinux_files = os.path.join(deploy_dir_image, 'bootloader/extlinux')
    boot_files = []
    for root, _, files in os.walk(deploy_extlinux_files):
        for file in files:
            src = os.path.relpath(os.path.join(root, file), deploy_dir_image)
            dst = os.path.relpath(os.path.join(root, file), deploy_extlinux_files)
            boot_files.append('{0};{1}'.format(src, dst))
    if not boot_files:
        return ''
    return ' '.join(boot_files)

#
# wic configuration with support for system update partition setup
#

IMAGE_FSTYPES_append = " squashfs"

WKS_FILE_raspberrypi4-64 ?= "x-raspberrypi.wks.in"

WKS_FILE_seco-intel-b68 ?= "x-efi-systemd-microcode.wks.in"
IMAGE_FSTYPES_append_seco-intel-b68 = " wic.bz2 wic.bmap"

WKS_FILE_stm32mp1-av96 ?= "x-avenger96.wks.in"
IMAGE_BOOT_FILES_stm32mp1-av96 ?= " \
    kernel/${KERNEL_IMAGETYPE};${KERNEL_IMAGETYPE} \
    ${@dtb_boot_files(d)} \
    ${@extlinux_boot_files(d)} \
    "
IMAGE_FSTYPES_append_stm32mp1-av96 = " wic.bz2 wic.bmap"
WKS_FILE_DEPENDS_stm32mp1-av96 ?= " \
    u-boot-stm32mp-extlinux \
    virtual/bootloader \
    virtual/trusted-firmware-a \
    virtual/kernel \
    "
# TODO: ST u-boot hardcodes this value. Configure wic as well so it matches the
# uboot configuration.
WIC_ROOTA_PARTITION_EXTRA_ARGS_stm32mp1-av96 ?= "--uuid e91c4e10-16e6-4c0e-bd0e-77becf4a3582"

# We avoid any other fstypes (for qemu) by default as the OS depends on a
# specific partition table provided through the wic configuration.
IMAGE_FSTYPES_qemux86 ?= "wic wic.bz2"
WKS_FILE_qemux86 ?= "x-qemux86-directdisk.wks.in"
IMAGE_FSTYPES_qemux86-64 ?= "wic wic.bz2"
WKS_FILE_qemux86-64 ?= "x-qemux86-directdisk.wks.in"

WKS_FILE_seco-imx8mm-c61 ?= "x-imx-uboot-bootpart.wks.in"

#
# Deploy boot partition artifacts to the root partition. This is part of the
# system update design where the update payload is defined as the root
# filesystem. In order to avoid multiple payloads, we include the boot assets
# in the root filesystem.
#

# The path relative to the root of the root filesystem where to deploy the boot
# artifacts.
ROOTFS_BOOT_ARTIFACTS_PATH ?= "usr/lib/sysota/boot-assets"

def run_cmd(cmd):
    """
    Run a cmd (string) and fail if exit code is non zero.
    """

    import subprocess
    try:
        subprocess.check_call(cmd.split())
    except subprocess.CalledProcessError as e:
        bb.fatal("Command \"%s\" failed with exit code %s." % (cmd , e.returncode))

python deploy_boot_artifacts_to_rootfs() {
    """
    This functionality follows the general logic in bootimg-partition but is
    adapted to work as a root filesystem post install function.
    """

    import re
    from glob import glob

    boot_files = d.getVar('IMAGE_BOOT_FILES')
    if not boot_files:
        # Nothing to do if IMAGE_BOOT_FILES is not defined. Custom wic plugins
        # are not supported.
        bb.warn('IMAGE_BOOT_FILES empty, so no boot files will be included in the rootfs')
        return
    deploy_dir = d.getVar('DEPLOY_DIR_IMAGE')
    rootfs_dir = d.getVar('IMAGE_ROOTFS')
    rootfs_boot_dir = d.getVar('ROOTFS_BOOT_ARTIFACTS_PATH')
    if rootfs_boot_dir:
        rootfs_dir = os.path.join(rootfs_dir, rootfs_boot_dir)

    deploy_files = []
    for src_entry in re.findall(r'[\w;\-\./\*]+', boot_files):
        if ';' in src_entry:
            dst_entry = tuple(src_entry.split(';'))
            if not dst_entry[0] or not dst_entry[1]:
                bb.fatal('Malformed IMAGE_BOOT_FILES entry: %s' % src_entry)
        else:
            dst_entry = (src_entry, src_entry)
        bb.debug(1, 'Destination entry: %r' % str(dst_entry))
        deploy_files.append(dst_entry)

    install_task = [];
    for deploy_entry in deploy_files:
        src, dst = deploy_entry
        if '*' in src:
            # by default install files under their basename
            entry_name_fn = os.path.basename
            if dst != src:
                # unless a target name was given, then treat name
                # as a directory and append a basename
                entry_name_fn = lambda name: \
                                os.path.join(dst,
                                             os.path.basename(name))

            srcs = glob(os.path.join(deploy_dir, src))

            bb.debug(1, 'Globbed sources: %s' % ', '.join(srcs))
            for entry in srcs:
                src = os.path.relpath(entry, deploy_dir)
                entry_dst_name = entry_name_fn(entry)
                install_task.append((src, entry_dst_name))
        else:
            install_task.append((src, dst))

    for task in set(install_task):
        src_path, dst_path = task
        bb.debug(1, 'Install %s as %s' % (src_path, dst_path))
        if os.path.exists(os.path.join(rootfs_dir, dst_path)):
            bb.fatal("%s already exists in the root filesystem. Fix to avoid overwriting files." % dst_path)
        install_cmd = "install -m 0644 -D %s %s" \
                      % (os.path.join(deploy_dir, src_path),
                         os.path.join(rootfs_dir, dst_path))
        run_cmd(install_cmd)
}

ROOTFS_POSTPROCESS_COMMAND += "deploy_boot_artifacts_to_rootfs;"