| Message ID | 20260223215008.2062721-3-twoerner@gmail.com |
|---|---|
| State | New |
| Headers | show |
| Series | standalone wic | expand |
On Mon, 2026-02-23 at 16:50 -0500, Trevor Woerner via lists.openembedded.org wrote: > Add an image class and wks file that demonstrates generating a wic image > with a 4096-byte sector size. > > Signed-off-by: Mark Hatle <mark.hatle@kernel.crashing.org> > Signed-off-by: Trevor Woerner <twoerner@gmail.com> > --- > changes in v5: > - none > > changes in v4: > - update the partition table format from mbr (msdos) to gpt > > changes in v3: > - tested more scenarios and make sure to fix the warning from v1 in > every case > > changes in v2: > - add Mark as a co-creator (sorry for missing this the first time!) > - provide a fix for the following warning: > WARNING: core-image-minimal-1.0-r0 do_image_wic_ufs: Function do_image_wic_ufs doesn't exist > --- > meta/classes-recipe/image.bbclass | 2 +- > meta/classes-recipe/image_types_ufs.bbclass | 221 ++++++++++++++++++++ > scripts/lib/wic/canned-wks/mkdisk-ufs.wks | 5 + > 3 files changed, 227 insertions(+), 1 deletion(-) > create mode 100644 meta/classes-recipe/image_types_ufs.bbclass > create mode 100644 scripts/lib/wic/canned-wks/mkdisk-ufs.wks > > diff --git a/meta/classes-recipe/image.bbclass b/meta/classes-recipe/image.bbclass > index 53f1a9dc45b0..97465836c14a 100644 > --- a/meta/classes-recipe/image.bbclass > +++ b/meta/classes-recipe/image.bbclass > @@ -18,7 +18,7 @@ inherit populate_sdk_base > IMGCLASSES += "${@['', 'populate_sdk_ext']['linux' in d.getVar("SDK_OS")]}" > IMGCLASSES += "${@bb.utils.contains_any('IMAGE_FSTYPES', 'live iso hddimg', 'image-live', '', d)}" > IMGCLASSES += "${@bb.utils.contains('IMAGE_FSTYPES', 'container', 'image-container', '', d)}" > -IMGCLASSES += "image_types_wic" > +IMGCLASSES += "image_types_wic image_types_ufs" > IMGCLASSES += "rootfs-postcommands" > IMGCLASSES += "image-postinst-intercepts" > IMGCLASSES += "overlayfs-etc" > diff --git a/meta/classes-recipe/image_types_ufs.bbclass b/meta/classes-recipe/image_types_ufs.bbclass > new file mode 100644 > index 000000000000..9a984f084289 > --- /dev/null > +++ b/meta/classes-recipe/image_types_ufs.bbclass > @@ -0,0 +1,221 @@ > +# > +# Copyright OpenEmbedded Contributors > +# > +# SPDX-License-Identifier: MIT > +# > + > +# The WICUFSVARS variable is used to define the base list of bitbake variables used in wic code > +# variables from this list are written to <image>.env file > +WICUFSVARS ?= "\ > + APPEND \ > + ASSUME_PROVIDED \ > + BBLAYERS \ > + DEPLOY_DIR_IMAGE \ > + FAKEROOTCMD \ > + HOSTTOOLS_DIR \ > + IMAGE_BASENAME \ > + IMAGE_BOOT_FILES \ > + IMAGE_CLASSES \ > + IMAGE_EFI_BOOT_FILES \ > + IMAGE_EXTRA_PARTITION_FILES \ > + IMAGE_LINK_NAME \ > + IMAGE_ROOTFS \ > + IMGDEPLOYDIR \ > + INITRAMFS_FSTYPES \ > + INITRAMFS_IMAGE \ > + INITRAMFS_IMAGE_BUNDLE \ > + INITRAMFS_LINK_NAME \ > + INITRD \ > + INITRD_LIVE \ > + ISODIR \ > + KERNEL_CONSOLE \ > + KERNEL_IMAGETYPE \ > + MACHINE \ > + PSEUDO_INCLUDE_PATHS \ > + RECIPE_SYSROOT_NATIVE \ > + ROOTFS_SIZE \ > + STAGING_DATADIR \ > + STAGING_DIR \ > + STAGING_DIR_HOST \ > + STAGING_LIBDIR \ > + TARGET_SYS \ > +" > + > +inherit_defer ${@bb.utils.contains('INITRAMFS_IMAGE_BUNDLE', '1', 'kernel-artifact-names', '', d)} > + > +WKSUFS_FILE ??= "${WKS_FILE}" > +WKSUFS_FILES ?= "${WKSUFS_FILE} ${IMAGE_BASENAME}.wks" > +WKSUFS_SEARCH_PATH ?= "${THISDIR}:${@':'.join('%s/wic' % p for p in '${BBPATH}'.split(':'))}:${@':'.join('%s/scripts/lib/wic/canned-wks' % l for l in '${BBPATH}:${COREBASE}'.split(':'))}" > +WKSUFS_FULL_PATH = "${@wks_search(d.getVar('WKSUFS_FILES').split(), d.getVar('WKSUFS_SEARCH_PATH')) or ''}" > + > +def wks_search(files, search_path): > + for f in files: > + if os.path.isabs(f): > + if os.path.exists(f): > + return f > + else: > + searched = bb.utils.which(search_path, f) > + if searched: > + return searched > + > +def wks_checksums(files, search_path): > + ret = "" > + for f in files: > + found, hist = bb.utils.which(search_path, f, history=True) > + ret = ret + " " + " ".join(h + ":False" for h in hist[:-1]) > + if found: > + ret = ret + " " + found + ":True" > + return ret > + > + > +WICUFS_CREATE_EXTRA_ARGS ?= "${WIC_CREATE_EXTRA_ARGS}" > + > +IMAGE_CMD:wic.ufs () { > + out="${IMGDEPLOYDIR}/${IMAGE_NAME}" > + build_wic_ufs="${WORKDIR}/build-wic-ufs" > + tmp_wic_ufs="${WORKDIR}/tmp-wic-ufs" > + wks="${WKSUFS_FULL_PATH}" > + if [ -e "$tmp_wic_ufs" ]; then > + # Ensure we don't have any junk leftover from a previously interrupted > + # do_image_wic_ufs execution > + rm -rf "$tmp_wic_ufs" > + fi > + if [ -z "$wks" ]; then > + bbfatal "No kickstart files from WKSUFS_FILES were found: ${WKSUFS_FILES}. Please set WKSUFS_FILE or WKSUFS_FILES appropriately." > + fi > + BUILDDIR="${TOPDIR}" PSEUDO_UNLOAD=1 wic create --debug "$wks" --sector-size 4096 --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}-ufs" -o "$build_wic_ufs/" -w "$tmp_wic_ufs" ${WICUFS_CREATE_EXTRA_ARGS} > + > + # look to see if the user specifies a custom imager > + IMAGER=direct > + eval set -- "${WICUFS_CREATE_EXTRA_ARGS} --" > + while [ 1 ]; do > + case "$1" in > + --imager|-i) > + shift > + IMAGER=$1 > + ;; > + --) > + shift > + break > + ;; > + esac > + shift > + done > + mv "$build_wic_ufs/$(basename "${wks%.wks}")"*.${IMAGER} "$out.wic.ufs" > +} > +IMAGE_CMD:wic.ufs[vardepsexclude] = "WKSUFS_FULL_PATH WKSUFS_FILES TOPDIR" > +SPDX_IMAGE_PURPOSE:wic.ufs = "diskImage" > +do_image_wic_ufs[cleandirs] = "${WORKDIR}/build-wic-ufs" > + > +# Rebuild when the wks file or vars in WICUFSVARS change > +USING_WIC_UFS = "${@bb.utils.contains_any('IMAGE_FSTYPES', 'wic.ufs ' + ' '.join('wic.ufs.%s' % c for c in '${CONVERSIONTYPES}'.split()), '1', '', d)}" > +WKSUFS_FILE_CHECKSUM = "${@wks_checksums(d.getVar('WKSUFS_FILES').split(), d.getVar('WKSUFS_SEARCH_PATH')) if '${USING_WIC_UFS}' else ''}" > +do_image_wic_ufs[file-checksums] += "${WKSUFS_FILE_CHECKSUM}" > +do_image_wic_ufs[depends] += "${@' '.join('%s-native:do_populate_sysroot' % r for r in ('parted', 'gptfdisk', 'dosfstools', 'mtools'))}" > + > +# We ensure all artfacts are deployed (e.g virtual/bootloader) > +do_image_wic_ufs[recrdeptask] += "do_deploy" > +do_image_wic_ufs[deptask] += "do_image_complete" > + > +WKSUFS_FILE_DEPENDS_DEFAULT = '${@bb.utils.contains_any("BUILD_ARCH", [ 'x86_64', 'i686' ], "syslinux-native", "",d)}' > +WKSUFS_FILE_DEPENDS_DEFAULT += "bmaptool-native cdrtools-native btrfs-tools-native squashfs-tools-native e2fsprogs-native erofs-utils-native" > +# Unified kernel images need objcopy > +WKSUFS_FILE_DEPENDS_DEFAULT += "virtual/cross-binutils" > +WKSUFS_FILE_DEPENDS_BOOTLOADERS = "" > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:aarch64 = "grub-efi systemd-boot" > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:arm = "systemd-boot" > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86 = "syslinux grub-efi systemd-boot" > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86-64 = "syslinux grub-efi systemd-boot" > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86-x32 = "syslinux grub-efi" > + > +WKSUFS_FILE_DEPENDS ??= "${WKSUFS_FILE_DEPENDS_DEFAULT} ${WKSUFS_FILE_DEPENDS_BOOTLOADERS}" > + > +DEPENDS += "${@ '${WKSUFS_FILE_DEPENDS}' if d.getVar('USING_WIC_UFS') else '' }" > + > +python do_write_wksufs_template () { > + """Write out expanded template contents to WKSUFS_FULL_PATH.""" > + import re > + > + template_body = d.getVar('_WKSUFS_TEMPLATE') > + > + # Remove any remnant variable references left behind by the expansion > + # due to undefined variables > + expand_var_regexp = re.compile(r"\${[^{}@\n\t :]+}") > + while True: > + new_body = re.sub(expand_var_regexp, '', template_body) > + if new_body == template_body: > + break > + else: > + template_body = new_body > + > + wks_file = d.getVar('WKSUFS_FULL_PATH') > + with open(wks_file, 'w') as f: > + f.write(template_body) > + f.close() > + # Copy the finalized wks file to the deploy directory for later use > + depdir = d.getVar('IMGDEPLOYDIR') > + basename = d.getVar('IMAGE_BASENAME') + '-ufs' > + bb.utils.copyfile(wks_file, "%s/%s" % (depdir, basename + '-' + os.path.basename(wks_file))) > +} > + > +do_flush_pseudodb() { > + ${FAKEROOTENV} ${FAKEROOTCMD} -S > +} > + > +python () { > + if d.getVar('USING_WIC_UFS'): > + wksufs_file_u = d.getVar('WKSUFS_FULL_PATH', False) > + wksufs_file = d.expand(wksufs_file_u) > + base, ext = os.path.splitext(wksufs_file) > + if ext == '.in' and os.path.exists(wksufs_file): > + wksufs_out_file = os.path.join(d.getVar('WORKDIR'), os.path.basename(base)) > + d.setVar('WKSUFS_FULL_PATH', wksufs_out_file) > + d.setVar('WKSUFS_TEMPLATE_PATH', wksufs_file_u) > + d.setVar('WKSUFS_FILE_CHECKSUM', '${WKSUFS_TEMPLATE_PATH}:True') > + > + # We need to re-parse each time the file changes, and bitbake > + # needs to be told about that explicitly. > + bb.parse.mark_dependency(d, wksufs_file) > + > + try: > + with open(wksufs_file, 'r') as f: > + body = f.read() > + except (IOError, OSError) as exc: > + pass > + else: > + # Previously, I used expandWithRefs to get the dependency list > + # and add it to WICUFSVARS, but there's no point re-parsing the > + # file in process_wks_template as well, so just put it in > + # a variable and let the metadata deal with the deps. > + d.setVar('_WKSUFS_TEMPLATE', body) > + bb.build.addtask('do_write_wksufs_template', 'do_image_wic_ufs', 'do_image', d) > + bb.build.addtask('do_image_wic_ufs', 'do_image_complete', 'do_image_wic', d) > +} > + > +# > +# Write environment variables used by wic > +# to tmp/sysroots/<machine>/imgdata/<image>-ufs.env > +# > +python do_rootfs_wicufsenv () { > + wicufsvars = d.getVar('WICUFSVARS') > + if not wicufsvars: > + return > + > + stdir = d.getVar('STAGING_DIR') > + outdir = os.path.join(stdir, d.getVar('MACHINE'), 'imgdata') > + bb.utils.mkdirhier(outdir) > + basename = d.getVar('IMAGE_BASENAME') + '-ufs' > + with open(os.path.join(outdir, basename) + '.env', 'w') as envf: > + for var in wicufsvars.split(): > + value = d.getVar(var) > + if value: > + envf.write('%s="%s"\n' % (var, value.strip())) > + envf.close() > + # Copy .env file to deploy directory for later use with stand alone wic > + depdir = d.getVar('IMGDEPLOYDIR') > + bb.utils.copyfile(os.path.join(outdir, basename) + '.env', os.path.join(depdir, basename) + '.env') > +} > +addtask do_flush_pseudodb after do_rootfs before do_image do_image_qa > +addtask do_rootfs_wicufsenv after do_image before do_image_wic_ufs > +do_rootfs_wicufsenv[vardeps] += "${WICUFSVARS}" > +do_rootfs_wicufsenv[prefuncs] = 'set_image_size' This is mostly duplication of code from image_types_wic.bbclass with different variable names, which makes it difficult to review the meaningful differences. Why do we need a separate class here? If we do need one, can we reduce duplication? Best regards,
On Tue, 2026-02-24 at 10:02 +0000, Paul Barker wrote: > On Mon, 2026-02-23 at 16:50 -0500, Trevor Woerner via > lists.openembedded.org wrote: > > Add an image class and wks file that demonstrates generating a wic image > > with a 4096-byte sector size. > > > > Signed-off-by: Mark Hatle <mark.hatle@kernel.crashing.org> > > Signed-off-by: Trevor Woerner <twoerner@gmail.com> > > --- > > changes in v5: > > - none > > > > changes in v4: > > - update the partition table format from mbr (msdos) to gpt > > > > changes in v3: > > - tested more scenarios and make sure to fix the warning from v1 in > > every case > > > > changes in v2: > > - add Mark as a co-creator (sorry for missing this the first time!) > > - provide a fix for the following warning: > > WARNING: core-image-minimal-1.0-r0 do_image_wic_ufs: Function do_image_wic_ufs doesn't exist > > --- > > meta/classes-recipe/image.bbclass | 2 +- > > meta/classes-recipe/image_types_ufs.bbclass | 221 ++++++++++++++++++++ > > scripts/lib/wic/canned-wks/mkdisk-ufs.wks | 5 + > > 3 files changed, 227 insertions(+), 1 deletion(-) > > create mode 100644 meta/classes-recipe/image_types_ufs.bbclass > > create mode 100644 scripts/lib/wic/canned-wks/mkdisk-ufs.wks > > > > diff --git a/meta/classes-recipe/image.bbclass b/meta/classes-recipe/image.bbclass > > index 53f1a9dc45b0..97465836c14a 100644 > > --- a/meta/classes-recipe/image.bbclass > > +++ b/meta/classes-recipe/image.bbclass > > @@ -18,7 +18,7 @@ inherit populate_sdk_base > > IMGCLASSES += "${@['', 'populate_sdk_ext']['linux' in d.getVar("SDK_OS")]}" > > IMGCLASSES += "${@bb.utils.contains_any('IMAGE_FSTYPES', 'live iso hddimg', 'image-live', '', d)}" > > IMGCLASSES += "${@bb.utils.contains('IMAGE_FSTYPES', 'container', 'image-container', '', d)}" > > -IMGCLASSES += "image_types_wic" > > +IMGCLASSES += "image_types_wic image_types_ufs" > > IMGCLASSES += "rootfs-postcommands" > > IMGCLASSES += "image-postinst-intercepts" > > IMGCLASSES += "overlayfs-etc" > > diff --git a/meta/classes-recipe/image_types_ufs.bbclass b/meta/classes-recipe/image_types_ufs.bbclass > > new file mode 100644 > > index 000000000000..9a984f084289 > > --- /dev/null > > +++ b/meta/classes-recipe/image_types_ufs.bbclass > > @@ -0,0 +1,221 @@ > > +# > > +# Copyright OpenEmbedded Contributors > > +# > > +# SPDX-License-Identifier: MIT > > +# > > + > > +# The WICUFSVARS variable is used to define the base list of bitbake variables used in wic code > > +# variables from this list are written to <image>.env file > > +WICUFSVARS ?= "\ > > + APPEND \ > > + ASSUME_PROVIDED \ > > + BBLAYERS \ > > + DEPLOY_DIR_IMAGE \ > > + FAKEROOTCMD \ > > + HOSTTOOLS_DIR \ > > + IMAGE_BASENAME \ > > + IMAGE_BOOT_FILES \ > > + IMAGE_CLASSES \ > > + IMAGE_EFI_BOOT_FILES \ > > + IMAGE_EXTRA_PARTITION_FILES \ > > + IMAGE_LINK_NAME \ > > + IMAGE_ROOTFS \ > > + IMGDEPLOYDIR \ > > + INITRAMFS_FSTYPES \ > > + INITRAMFS_IMAGE \ > > + INITRAMFS_IMAGE_BUNDLE \ > > + INITRAMFS_LINK_NAME \ > > + INITRD \ > > + INITRD_LIVE \ > > + ISODIR \ > > + KERNEL_CONSOLE \ > > + KERNEL_IMAGETYPE \ > > + MACHINE \ > > + PSEUDO_INCLUDE_PATHS \ > > + RECIPE_SYSROOT_NATIVE \ > > + ROOTFS_SIZE \ > > + STAGING_DATADIR \ > > + STAGING_DIR \ > > + STAGING_DIR_HOST \ > > + STAGING_LIBDIR \ > > + TARGET_SYS \ > > +" > > + > > +inherit_defer ${@bb.utils.contains('INITRAMFS_IMAGE_BUNDLE', '1', 'kernel-artifact-names', '', d)} > > + > > +WKSUFS_FILE ??= "${WKS_FILE}" > > +WKSUFS_FILES ?= "${WKSUFS_FILE} ${IMAGE_BASENAME}.wks" > > +WKSUFS_SEARCH_PATH ?= "${THISDIR}:${@':'.join('%s/wic' % p for p in '${BBPATH}'.split(':'))}:${@':'.join('%s/scripts/lib/wic/canned-wks' % l for l in '${BBPATH}:${COREBASE}'.split(':'))}" > > +WKSUFS_FULL_PATH = "${@wks_search(d.getVar('WKSUFS_FILES').split(), d.getVar('WKSUFS_SEARCH_PATH')) or ''}" > > + > > +def wks_search(files, search_path): > > + for f in files: > > + if os.path.isabs(f): > > + if os.path.exists(f): > > + return f > > + else: > > + searched = bb.utils.which(search_path, f) > > + if searched: > > + return searched > > + > > +def wks_checksums(files, search_path): > > + ret = "" > > + for f in files: > > + found, hist = bb.utils.which(search_path, f, history=True) > > + ret = ret + " " + " ".join(h + ":False" for h in hist[:-1]) > > + if found: > > + ret = ret + " " + found + ":True" > > + return ret > > + > > + > > +WICUFS_CREATE_EXTRA_ARGS ?= "${WIC_CREATE_EXTRA_ARGS}" > > + > > +IMAGE_CMD:wic.ufs () { > > + out="${IMGDEPLOYDIR}/${IMAGE_NAME}" > > + build_wic_ufs="${WORKDIR}/build-wic-ufs" > > + tmp_wic_ufs="${WORKDIR}/tmp-wic-ufs" > > + wks="${WKSUFS_FULL_PATH}" > > + if [ -e "$tmp_wic_ufs" ]; then > > + # Ensure we don't have any junk leftover from a previously interrupted > > + # do_image_wic_ufs execution > > + rm -rf "$tmp_wic_ufs" > > + fi > > + if [ -z "$wks" ]; then > > + bbfatal "No kickstart files from WKSUFS_FILES were found: ${WKSUFS_FILES}. Please set WKSUFS_FILE or WKSUFS_FILES appropriately." > > + fi > > + BUILDDIR="${TOPDIR}" PSEUDO_UNLOAD=1 wic create --debug "$wks" --sector-size 4096 --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}-ufs" -o "$build_wic_ufs/" -w "$tmp_wic_ufs" ${WICUFS_CREATE_EXTRA_ARGS} > > + > > + # look to see if the user specifies a custom imager > > + IMAGER=direct > > + eval set -- "${WICUFS_CREATE_EXTRA_ARGS} --" > > + while [ 1 ]; do > > + case "$1" in > > + --imager|-i) > > + shift > > + IMAGER=$1 > > + ;; > > + --) > > + shift > > + break > > + ;; > > + esac > > + shift > > + done > > + mv "$build_wic_ufs/$(basename "${wks%.wks}")"*.${IMAGER} "$out.wic.ufs" > > +} > > +IMAGE_CMD:wic.ufs[vardepsexclude] = "WKSUFS_FULL_PATH WKSUFS_FILES TOPDIR" > > +SPDX_IMAGE_PURPOSE:wic.ufs = "diskImage" > > +do_image_wic_ufs[cleandirs] = "${WORKDIR}/build-wic-ufs" > > + > > +# Rebuild when the wks file or vars in WICUFSVARS change > > +USING_WIC_UFS = "${@bb.utils.contains_any('IMAGE_FSTYPES', 'wic.ufs ' + ' '.join('wic.ufs.%s' % c for c in '${CONVERSIONTYPES}'.split()), '1', '', d)}" > > +WKSUFS_FILE_CHECKSUM = "${@wks_checksums(d.getVar('WKSUFS_FILES').split(), d.getVar('WKSUFS_SEARCH_PATH')) if '${USING_WIC_UFS}' else ''}" > > +do_image_wic_ufs[file-checksums] += "${WKSUFS_FILE_CHECKSUM}" > > +do_image_wic_ufs[depends] += "${@' '.join('%s-native:do_populate_sysroot' % r for r in ('parted', 'gptfdisk', 'dosfstools', 'mtools'))}" > > + > > +# We ensure all artfacts are deployed (e.g virtual/bootloader) > > +do_image_wic_ufs[recrdeptask] += "do_deploy" > > +do_image_wic_ufs[deptask] += "do_image_complete" > > + > > +WKSUFS_FILE_DEPENDS_DEFAULT = '${@bb.utils.contains_any("BUILD_ARCH", [ 'x86_64', 'i686' ], "syslinux-native", "",d)}' > > +WKSUFS_FILE_DEPENDS_DEFAULT += "bmaptool-native cdrtools-native btrfs-tools-native squashfs-tools-native e2fsprogs-native erofs-utils-native" > > +# Unified kernel images need objcopy > > +WKSUFS_FILE_DEPENDS_DEFAULT += "virtual/cross-binutils" > > +WKSUFS_FILE_DEPENDS_BOOTLOADERS = "" > > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:aarch64 = "grub-efi systemd-boot" > > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:arm = "systemd-boot" > > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86 = "syslinux grub-efi systemd-boot" > > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86-64 = "syslinux grub-efi systemd-boot" > > +WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86-x32 = "syslinux grub-efi" > > + > > +WKSUFS_FILE_DEPENDS ??= "${WKSUFS_FILE_DEPENDS_DEFAULT} ${WKSUFS_FILE_DEPENDS_BOOTLOADERS}" > > + > > +DEPENDS += "${@ '${WKSUFS_FILE_DEPENDS}' if d.getVar('USING_WIC_UFS') else '' }" > > + > > +python do_write_wksufs_template () { > > + """Write out expanded template contents to WKSUFS_FULL_PATH.""" > > + import re > > + > > + template_body = d.getVar('_WKSUFS_TEMPLATE') > > + > > + # Remove any remnant variable references left behind by the expansion > > + # due to undefined variables > > + expand_var_regexp = re.compile(r"\${[^{}@\n\t :]+}") > > + while True: > > + new_body = re.sub(expand_var_regexp, '', template_body) > > + if new_body == template_body: > > + break > > + else: > > + template_body = new_body > > + > > + wks_file = d.getVar('WKSUFS_FULL_PATH') > > + with open(wks_file, 'w') as f: > > + f.write(template_body) > > + f.close() > > + # Copy the finalized wks file to the deploy directory for later use > > + depdir = d.getVar('IMGDEPLOYDIR') > > + basename = d.getVar('IMAGE_BASENAME') + '-ufs' > > + bb.utils.copyfile(wks_file, "%s/%s" % (depdir, basename + '-' + os.path.basename(wks_file))) > > +} > > + > > +do_flush_pseudodb() { > > + ${FAKEROOTENV} ${FAKEROOTCMD} -S > > +} > > + > > +python () { > > + if d.getVar('USING_WIC_UFS'): > > + wksufs_file_u = d.getVar('WKSUFS_FULL_PATH', False) > > + wksufs_file = d.expand(wksufs_file_u) > > + base, ext = os.path.splitext(wksufs_file) > > + if ext == '.in' and os.path.exists(wksufs_file): > > + wksufs_out_file = os.path.join(d.getVar('WORKDIR'), os.path.basename(base)) > > + d.setVar('WKSUFS_FULL_PATH', wksufs_out_file) > > + d.setVar('WKSUFS_TEMPLATE_PATH', wksufs_file_u) > > + d.setVar('WKSUFS_FILE_CHECKSUM', '${WKSUFS_TEMPLATE_PATH}:True') > > + > > + # We need to re-parse each time the file changes, and bitbake > > + # needs to be told about that explicitly. > > + bb.parse.mark_dependency(d, wksufs_file) > > + > > + try: > > + with open(wksufs_file, 'r') as f: > > + body = f.read() > > + except (IOError, OSError) as exc: > > + pass > > + else: > > + # Previously, I used expandWithRefs to get the dependency list > > + # and add it to WICUFSVARS, but there's no point re-parsing the > > + # file in process_wks_template as well, so just put it in > > + # a variable and let the metadata deal with the deps. > > + d.setVar('_WKSUFS_TEMPLATE', body) > > + bb.build.addtask('do_write_wksufs_template', 'do_image_wic_ufs', 'do_image', d) > > + bb.build.addtask('do_image_wic_ufs', 'do_image_complete', 'do_image_wic', d) > > +} > > + > > +# > > +# Write environment variables used by wic > > +# to tmp/sysroots/<machine>/imgdata/<image>-ufs.env > > +# > > +python do_rootfs_wicufsenv () { > > + wicufsvars = d.getVar('WICUFSVARS') > > + if not wicufsvars: > > + return > > + > > + stdir = d.getVar('STAGING_DIR') > > + outdir = os.path.join(stdir, d.getVar('MACHINE'), 'imgdata') > > + bb.utils.mkdirhier(outdir) > > + basename = d.getVar('IMAGE_BASENAME') + '-ufs' > > + with open(os.path.join(outdir, basename) + '.env', 'w') as envf: > > + for var in wicufsvars.split(): > > + value = d.getVar(var) > > + if value: > > + envf.write('%s="%s"\n' % (var, value.strip())) > > + envf.close() > > + # Copy .env file to deploy directory for later use with stand alone wic > > + depdir = d.getVar('IMGDEPLOYDIR') > > + bb.utils.copyfile(os.path.join(outdir, basename) + '.env', os.path.join(depdir, basename) + '.env') > > +} > > +addtask do_flush_pseudodb after do_rootfs before do_image do_image_qa > > +addtask do_rootfs_wicufsenv after do_image before do_image_wic_ufs > > +do_rootfs_wicufsenv[vardeps] += "${WICUFSVARS}" > > +do_rootfs_wicufsenv[prefuncs] = 'set_image_size' > > This is mostly duplication of code from image_types_wic.bbclass with > different variable names, which makes it difficult to review the > meaningful differences. Why do we need a separate class here? If we do > need one, can we reduce duplication? In fact, this looks orthogonal to the other changes. Can you submit a v6 series without this patch, addressing my other comments? Then we can get things merged before the M2 build. This change can be re-submitted as a standalone patch after the wic split series. Thanks,
diff --git a/meta/classes-recipe/image.bbclass b/meta/classes-recipe/image.bbclass index 53f1a9dc45b0..97465836c14a 100644 --- a/meta/classes-recipe/image.bbclass +++ b/meta/classes-recipe/image.bbclass @@ -18,7 +18,7 @@ inherit populate_sdk_base IMGCLASSES += "${@['', 'populate_sdk_ext']['linux' in d.getVar("SDK_OS")]}" IMGCLASSES += "${@bb.utils.contains_any('IMAGE_FSTYPES', 'live iso hddimg', 'image-live', '', d)}" IMGCLASSES += "${@bb.utils.contains('IMAGE_FSTYPES', 'container', 'image-container', '', d)}" -IMGCLASSES += "image_types_wic" +IMGCLASSES += "image_types_wic image_types_ufs" IMGCLASSES += "rootfs-postcommands" IMGCLASSES += "image-postinst-intercepts" IMGCLASSES += "overlayfs-etc" diff --git a/meta/classes-recipe/image_types_ufs.bbclass b/meta/classes-recipe/image_types_ufs.bbclass new file mode 100644 index 000000000000..9a984f084289 --- /dev/null +++ b/meta/classes-recipe/image_types_ufs.bbclass @@ -0,0 +1,221 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +# The WICUFSVARS variable is used to define the base list of bitbake variables used in wic code +# variables from this list are written to <image>.env file +WICUFSVARS ?= "\ + APPEND \ + ASSUME_PROVIDED \ + BBLAYERS \ + DEPLOY_DIR_IMAGE \ + FAKEROOTCMD \ + HOSTTOOLS_DIR \ + IMAGE_BASENAME \ + IMAGE_BOOT_FILES \ + IMAGE_CLASSES \ + IMAGE_EFI_BOOT_FILES \ + IMAGE_EXTRA_PARTITION_FILES \ + IMAGE_LINK_NAME \ + IMAGE_ROOTFS \ + IMGDEPLOYDIR \ + INITRAMFS_FSTYPES \ + INITRAMFS_IMAGE \ + INITRAMFS_IMAGE_BUNDLE \ + INITRAMFS_LINK_NAME \ + INITRD \ + INITRD_LIVE \ + ISODIR \ + KERNEL_CONSOLE \ + KERNEL_IMAGETYPE \ + MACHINE \ + PSEUDO_INCLUDE_PATHS \ + RECIPE_SYSROOT_NATIVE \ + ROOTFS_SIZE \ + STAGING_DATADIR \ + STAGING_DIR \ + STAGING_DIR_HOST \ + STAGING_LIBDIR \ + TARGET_SYS \ +" + +inherit_defer ${@bb.utils.contains('INITRAMFS_IMAGE_BUNDLE', '1', 'kernel-artifact-names', '', d)} + +WKSUFS_FILE ??= "${WKS_FILE}" +WKSUFS_FILES ?= "${WKSUFS_FILE} ${IMAGE_BASENAME}.wks" +WKSUFS_SEARCH_PATH ?= "${THISDIR}:${@':'.join('%s/wic' % p for p in '${BBPATH}'.split(':'))}:${@':'.join('%s/scripts/lib/wic/canned-wks' % l for l in '${BBPATH}:${COREBASE}'.split(':'))}" +WKSUFS_FULL_PATH = "${@wks_search(d.getVar('WKSUFS_FILES').split(), d.getVar('WKSUFS_SEARCH_PATH')) or ''}" + +def wks_search(files, search_path): + for f in files: + if os.path.isabs(f): + if os.path.exists(f): + return f + else: + searched = bb.utils.which(search_path, f) + if searched: + return searched + +def wks_checksums(files, search_path): + ret = "" + for f in files: + found, hist = bb.utils.which(search_path, f, history=True) + ret = ret + " " + " ".join(h + ":False" for h in hist[:-1]) + if found: + ret = ret + " " + found + ":True" + return ret + + +WICUFS_CREATE_EXTRA_ARGS ?= "${WIC_CREATE_EXTRA_ARGS}" + +IMAGE_CMD:wic.ufs () { + out="${IMGDEPLOYDIR}/${IMAGE_NAME}" + build_wic_ufs="${WORKDIR}/build-wic-ufs" + tmp_wic_ufs="${WORKDIR}/tmp-wic-ufs" + wks="${WKSUFS_FULL_PATH}" + if [ -e "$tmp_wic_ufs" ]; then + # Ensure we don't have any junk leftover from a previously interrupted + # do_image_wic_ufs execution + rm -rf "$tmp_wic_ufs" + fi + if [ -z "$wks" ]; then + bbfatal "No kickstart files from WKSUFS_FILES were found: ${WKSUFS_FILES}. Please set WKSUFS_FILE or WKSUFS_FILES appropriately." + fi + BUILDDIR="${TOPDIR}" PSEUDO_UNLOAD=1 wic create --debug "$wks" --sector-size 4096 --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}-ufs" -o "$build_wic_ufs/" -w "$tmp_wic_ufs" ${WICUFS_CREATE_EXTRA_ARGS} + + # look to see if the user specifies a custom imager + IMAGER=direct + eval set -- "${WICUFS_CREATE_EXTRA_ARGS} --" + while [ 1 ]; do + case "$1" in + --imager|-i) + shift + IMAGER=$1 + ;; + --) + shift + break + ;; + esac + shift + done + mv "$build_wic_ufs/$(basename "${wks%.wks}")"*.${IMAGER} "$out.wic.ufs" +} +IMAGE_CMD:wic.ufs[vardepsexclude] = "WKSUFS_FULL_PATH WKSUFS_FILES TOPDIR" +SPDX_IMAGE_PURPOSE:wic.ufs = "diskImage" +do_image_wic_ufs[cleandirs] = "${WORKDIR}/build-wic-ufs" + +# Rebuild when the wks file or vars in WICUFSVARS change +USING_WIC_UFS = "${@bb.utils.contains_any('IMAGE_FSTYPES', 'wic.ufs ' + ' '.join('wic.ufs.%s' % c for c in '${CONVERSIONTYPES}'.split()), '1', '', d)}" +WKSUFS_FILE_CHECKSUM = "${@wks_checksums(d.getVar('WKSUFS_FILES').split(), d.getVar('WKSUFS_SEARCH_PATH')) if '${USING_WIC_UFS}' else ''}" +do_image_wic_ufs[file-checksums] += "${WKSUFS_FILE_CHECKSUM}" +do_image_wic_ufs[depends] += "${@' '.join('%s-native:do_populate_sysroot' % r for r in ('parted', 'gptfdisk', 'dosfstools', 'mtools'))}" + +# We ensure all artfacts are deployed (e.g virtual/bootloader) +do_image_wic_ufs[recrdeptask] += "do_deploy" +do_image_wic_ufs[deptask] += "do_image_complete" + +WKSUFS_FILE_DEPENDS_DEFAULT = '${@bb.utils.contains_any("BUILD_ARCH", [ 'x86_64', 'i686' ], "syslinux-native", "",d)}' +WKSUFS_FILE_DEPENDS_DEFAULT += "bmaptool-native cdrtools-native btrfs-tools-native squashfs-tools-native e2fsprogs-native erofs-utils-native" +# Unified kernel images need objcopy +WKSUFS_FILE_DEPENDS_DEFAULT += "virtual/cross-binutils" +WKSUFS_FILE_DEPENDS_BOOTLOADERS = "" +WKSUFS_FILE_DEPENDS_BOOTLOADERS:aarch64 = "grub-efi systemd-boot" +WKSUFS_FILE_DEPENDS_BOOTLOADERS:arm = "systemd-boot" +WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86 = "syslinux grub-efi systemd-boot" +WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86-64 = "syslinux grub-efi systemd-boot" +WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86-x32 = "syslinux grub-efi" + +WKSUFS_FILE_DEPENDS ??= "${WKSUFS_FILE_DEPENDS_DEFAULT} ${WKSUFS_FILE_DEPENDS_BOOTLOADERS}" + +DEPENDS += "${@ '${WKSUFS_FILE_DEPENDS}' if d.getVar('USING_WIC_UFS') else '' }" + +python do_write_wksufs_template () { + """Write out expanded template contents to WKSUFS_FULL_PATH.""" + import re + + template_body = d.getVar('_WKSUFS_TEMPLATE') + + # Remove any remnant variable references left behind by the expansion + # due to undefined variables + expand_var_regexp = re.compile(r"\${[^{}@\n\t :]+}") + while True: + new_body = re.sub(expand_var_regexp, '', template_body) + if new_body == template_body: + break + else: + template_body = new_body + + wks_file = d.getVar('WKSUFS_FULL_PATH') + with open(wks_file, 'w') as f: + f.write(template_body) + f.close() + # Copy the finalized wks file to the deploy directory for later use + depdir = d.getVar('IMGDEPLOYDIR') + basename = d.getVar('IMAGE_BASENAME') + '-ufs' + bb.utils.copyfile(wks_file, "%s/%s" % (depdir, basename + '-' + os.path.basename(wks_file))) +} + +do_flush_pseudodb() { + ${FAKEROOTENV} ${FAKEROOTCMD} -S +} + +python () { + if d.getVar('USING_WIC_UFS'): + wksufs_file_u = d.getVar('WKSUFS_FULL_PATH', False) + wksufs_file = d.expand(wksufs_file_u) + base, ext = os.path.splitext(wksufs_file) + if ext == '.in' and os.path.exists(wksufs_file): + wksufs_out_file = os.path.join(d.getVar('WORKDIR'), os.path.basename(base)) + d.setVar('WKSUFS_FULL_PATH', wksufs_out_file) + d.setVar('WKSUFS_TEMPLATE_PATH', wksufs_file_u) + d.setVar('WKSUFS_FILE_CHECKSUM', '${WKSUFS_TEMPLATE_PATH}:True') + + # We need to re-parse each time the file changes, and bitbake + # needs to be told about that explicitly. + bb.parse.mark_dependency(d, wksufs_file) + + try: + with open(wksufs_file, 'r') as f: + body = f.read() + except (IOError, OSError) as exc: + pass + else: + # Previously, I used expandWithRefs to get the dependency list + # and add it to WICUFSVARS, but there's no point re-parsing the + # file in process_wks_template as well, so just put it in + # a variable and let the metadata deal with the deps. + d.setVar('_WKSUFS_TEMPLATE', body) + bb.build.addtask('do_write_wksufs_template', 'do_image_wic_ufs', 'do_image', d) + bb.build.addtask('do_image_wic_ufs', 'do_image_complete', 'do_image_wic', d) +} + +# +# Write environment variables used by wic +# to tmp/sysroots/<machine>/imgdata/<image>-ufs.env +# +python do_rootfs_wicufsenv () { + wicufsvars = d.getVar('WICUFSVARS') + if not wicufsvars: + return + + stdir = d.getVar('STAGING_DIR') + outdir = os.path.join(stdir, d.getVar('MACHINE'), 'imgdata') + bb.utils.mkdirhier(outdir) + basename = d.getVar('IMAGE_BASENAME') + '-ufs' + with open(os.path.join(outdir, basename) + '.env', 'w') as envf: + for var in wicufsvars.split(): + value = d.getVar(var) + if value: + envf.write('%s="%s"\n' % (var, value.strip())) + envf.close() + # Copy .env file to deploy directory for later use with stand alone wic + depdir = d.getVar('IMGDEPLOYDIR') + bb.utils.copyfile(os.path.join(outdir, basename) + '.env', os.path.join(depdir, basename) + '.env') +} +addtask do_flush_pseudodb after do_rootfs before do_image do_image_qa +addtask do_rootfs_wicufsenv after do_image before do_image_wic_ufs +do_rootfs_wicufsenv[vardeps] += "${WICUFSVARS}" +do_rootfs_wicufsenv[prefuncs] = 'set_image_size' diff --git a/scripts/lib/wic/canned-wks/mkdisk-ufs.wks b/scripts/lib/wic/canned-wks/mkdisk-ufs.wks new file mode 100644 index 000000000000..dfd2f3854890 --- /dev/null +++ b/scripts/lib/wic/canned-wks/mkdisk-ufs.wks @@ -0,0 +1,5 @@ +bootloader --ptable gpt + +part /boot --source rootfs --fstype=vfat --label boot --change-directory boot/ +part / --source rootfs --fstype=ext4 --label root --exclude-path boot/ +part swap --fstype=swap --label swap --size 1M