From 67ea7dff95f14e603916b53e2dee6359bbf9529b Mon Sep 17 00:00:00 2001 From: Adrian Calianu Date: Tue, 13 Mar 2018 09:22:57 +0100 Subject: qemuarm64: generate one self contained image that can be booted from qemu like a HDD image. Building enea-nfv-access-vnf image on aarch64 will result in a qcow2 image (ready to be booted on a UEFI bootloader) containing two partitions: sda1: ESP/FAT32 - grub-efi - startup.nsh sda2: ext4 - rootfs Comparing to qemux86-64 on qemuarm64 must be selected the BIOS: qemu-system-aarch64 -pflash flash0.img -pflash flash1.img -hda enea-nfv-access-vnf.qcow2 To generate such a image wic was used. Since wic is using some hardcoded values specific to x86 (like kernel name) it was decided for now to create and store locally wic specific modification for arm64. Currently is no support to build EDKII/UEFI bootloader for aarch64. It must be built or downloaded from Linaro. Signed-off-by: Adrian Calianu Signed-off-by: Adrian Dudau --- classes/enea-qcow2.bbclass | 7 + images/enea-nfv-access-vnf.bb | 11 +- .../wic/canned-wks/enea-systemd-bootdisk-efi.wks | 9 + scripts/lib/wic/plugins/source/enea-bootimg-efi.py | 261 +++++++++++++++++++++ 4 files changed, 283 insertions(+), 5 deletions(-) create mode 100644 classes/enea-qcow2.bbclass create mode 100644 scripts/lib/wic/canned-wks/enea-systemd-bootdisk-efi.wks create mode 100644 scripts/lib/wic/plugins/source/enea-bootimg-efi.py diff --git a/classes/enea-qcow2.bbclass b/classes/enea-qcow2.bbclass new file mode 100644 index 0000000..b086069 --- /dev/null +++ b/classes/enea-qcow2.bbclass @@ -0,0 +1,7 @@ +IMAGE_TYPES += "wic wic.qcow2" +CONVERSIONTYPES += "qcow2" +CONVERSION_DEPENDS_qcow2 = "qemu-native" +CONVERSION_CMD_qcow2 = "qemu-img convert -O qcow2 ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.${type} ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.qcow2" + +IMAGE_FSTYPES += "wic wic.qcow2" +WKS_FILE = "enea-systemd-bootdisk-efi.wks" diff --git a/images/enea-nfv-access-vnf.bb b/images/enea-nfv-access-vnf.bb index fdf7083..d5da06b 100644 --- a/images/enea-nfv-access-vnf.bb +++ b/images/enea-nfv-access-vnf.bb @@ -3,12 +3,13 @@ DESCRIPTION = "VNF image of the Enea NFV Access Platform, includes kernel, rootf require images/enea-nfv-access-common.inc # Enea VNF boot configuration -ROOT_VM = "root=/dev/vda2" -APPEND = "console=ttyS0,115200 hugepagesz=2M hugepages=512 isolcpus=1 nohz_full=1 rcu_nocbs=1 audit=0 quiet" -SYSLINUX_TIMEOUT = "30" +# image-vm is supported only for x86-64 , for all other arch use enea-qcow2 class +ROOT_VM_x86-64 = "root=/dev/vda2" +APPEND_x86-64 = "console=ttyS0,115200 hugepagesz=2M hugepages=512 isolcpus=1 nohz_full=1 rcu_nocbs=1 audit=0 quiet" +SYSLINUX_TIMEOUT_x86-64 = "30" -inherit image-vm -IMAGE_FSTYPES += "qcow2" +inherit ${@'image-vm' if "${TUNE_ARCH}" == "x86_64" else 'enea-qcow2'} +IMAGE_FSTYPES_x86-64 += "qcow2" CLOUDINITPKGS = "cloud-init util-linux-blkid" CLOUDINITPKGS += " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'cloud-init-systemd', '', d)}" diff --git a/scripts/lib/wic/canned-wks/enea-systemd-bootdisk-efi.wks b/scripts/lib/wic/canned-wks/enea-systemd-bootdisk-efi.wks new file mode 100644 index 0000000..a9af3b3 --- /dev/null +++ b/scripts/lib/wic/canned-wks/enea-systemd-bootdisk-efi.wks @@ -0,0 +1,9 @@ +# short-description: Create an EFI disk image with grub-efi +# long-description: Creates a partitioned EFI disk image that the user +# can directly dd to boot media. The selected bootloader is grub-efi. + +part /boot --source enea-bootimg-efi --sourceparams="loader=grub-efi" --ondisk vda --fstype=vfat --label EFI --active --align 1024 + +part / --source rootfs --ondisk vda --fstype=ext4 --label platform --align 1024 + +bootloader --ptable gpt --timeout=10 --append="rootfstype=ext4 console=ttyAMA0,115200 console=tty0 coherent_pool=16M" diff --git a/scripts/lib/wic/plugins/source/enea-bootimg-efi.py b/scripts/lib/wic/plugins/source/enea-bootimg-efi.py new file mode 100644 index 0000000..1cf8c97 --- /dev/null +++ b/scripts/lib/wic/plugins/source/enea-bootimg-efi.py @@ -0,0 +1,261 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2014, Intel Corporation. +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This implements the 'enea-bootimg-efi' source plugin class for 'wic' +# This is a copy of bootimg-efi source plugin. Following changes has been made: +# - renamed plugin to "enea-bootimg-efi" +# - rename bzImage with Image - on ARM we have only Image +# +# AUTHORS +# Tom Zanussi +# Adrian Calianu +# + +import logging +import os +import shutil + +from wic import WicError +from wic.engine import get_custom_config +from wic.pluginbase import SourcePlugin +from wic.utils.misc import (exec_cmd, exec_native_cmd, get_bitbake_var, + BOOTDD_EXTRA_SPACE) + +logger = logging.getLogger('wic') + +class EneaBootimgEFIPlugin(SourcePlugin): + """ + Create EFI boot partition. + This plugin supports GRUB 2 and systemd-boot bootloaders. + """ + + name = 'enea-bootimg-efi' + + @classmethod + def do_configure_grubefi(cls, creator, cr_workdir): + """ + Create loader-specific (grub-efi) config + """ + configfile = creator.ks.bootloader.configfile + custom_cfg = None + if configfile: + custom_cfg = get_custom_config(configfile) + if custom_cfg: + # Use a custom configuration for grub + grubefi_conf = custom_cfg + logger.debug("Using custom configuration file " + "%s for grub.cfg", configfile) + else: + raise WicError("configfile is specified but failed to " + "get it from %s." % configfile) + + if not custom_cfg: + # Create grub configuration using parameters from wks file + bootloader = creator.ks.bootloader + + grubefi_conf = "" + grubefi_conf += "serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1\n" + grubefi_conf += "default=boot\n" + grubefi_conf += "timeout=%s\n" % bootloader.timeout + grubefi_conf += "menuentry 'boot'{\n" + + kernel = "/Image" + + grubefi_conf += "linux %s root=%s rootwait %s\n" \ + % (kernel, creator.rootdev, bootloader.append) + grubefi_conf += "}\n" + + logger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg", + cr_workdir) + cfg = open("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir, "w") + cfg.write(grubefi_conf) + cfg.close() + + @classmethod + def do_configure_systemdboot(cls, hdddir, creator, cr_workdir, source_params): + """ + Create loader-specific systemd-boot/gummiboot config + """ + install_cmd = "install -d %s/loader" % hdddir + exec_cmd(install_cmd) + + install_cmd = "install -d %s/loader/entries" % hdddir + exec_cmd(install_cmd) + + bootloader = creator.ks.bootloader + + loader_conf = "" + loader_conf += "default boot\n" + loader_conf += "timeout %d\n" % bootloader.timeout + + initrd = source_params.get('initrd') + + if initrd: + # obviously we need to have a common common deploy var + bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") + if not bootimg_dir: + raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") + + cp_cmd = "cp %s/%s %s" % (bootimg_dir, initrd, hdddir) + exec_cmd(cp_cmd, True) + else: + logger.debug("Ignoring missing initrd") + + logger.debug("Writing systemd-boot config " + "%s/hdd/boot/loader/loader.conf", cr_workdir) + cfg = open("%s/hdd/boot/loader/loader.conf" % cr_workdir, "w") + cfg.write(loader_conf) + cfg.close() + + configfile = creator.ks.bootloader.configfile + custom_cfg = None + if configfile: + custom_cfg = get_custom_config(configfile) + if custom_cfg: + # Use a custom configuration for systemd-boot + boot_conf = custom_cfg + logger.debug("Using custom configuration file " + "%s for systemd-boots's boot.conf", configfile) + else: + raise WicError("configfile is specified but failed to " + "get it from %s.", configfile) + + if not custom_cfg: + # Create systemd-boot configuration using parameters from wks file + kernel = "/Image" + + boot_conf = "" + boot_conf += "title boot\n" + boot_conf += "linux %s\n" % kernel + boot_conf += "options LABEL=Boot root=%s %s\n" % \ + (creator.rootdev, bootloader.append) + + if initrd: + boot_conf += "initrd /%s\n" % initrd + + logger.debug("Writing systemd-boot config " + "%s/hdd/boot/loader/entries/boot.conf", cr_workdir) + cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w") + cfg.write(boot_conf) + cfg.close() + + + @classmethod + def do_configure_partition(cls, part, source_params, creator, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + native_sysroot): + """ + Called before do_prepare_partition(), creates loader-specific config + """ + hdddir = "%s/hdd/boot" % cr_workdir + + install_cmd = "install -d %s/EFI/BOOT" % hdddir + exec_cmd(install_cmd) + + try: + if source_params['loader'] == 'grub-efi': + cls.do_configure_grubefi(creator, cr_workdir) + elif source_params['loader'] == 'systemd-boot': + cls.do_configure_systemdboot(hdddir, creator, cr_workdir, source_params) + else: + raise WicError("unrecognized bootimg-efi loader: %s" % source_params['loader']) + except KeyError: + raise WicError("bootimg-efi requires a loader, none specified") + + + @classmethod + def do_prepare_partition(cls, part, source_params, creator, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + rootfs_dir, native_sysroot): + """ + Called to do the actual content population for a partition i.e. it + 'prepares' the partition to be incorporated into the image. + In this case, prepare content for an EFI (grub) boot partition. + """ + if not kernel_dir: + kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") + if not kernel_dir: + raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") + + staging_kernel_dir = kernel_dir + + hdddir = "%s/hdd/boot" % cr_workdir + + install_cmd = "install -m 0644 %s/Image %s/Image" % \ + (staging_kernel_dir, hdddir) + exec_cmd(install_cmd) + + + try: + if source_params['loader'] == 'grub-efi': + shutil.copyfile("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir, + "%s/grub.cfg" % cr_workdir) + for mod in [x for x in os.listdir(kernel_dir) if x.startswith("grub-efi-")]: + cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[9:]) + exec_cmd(cp_cmd, True) + shutil.move("%s/grub.cfg" % cr_workdir, + "%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir) + elif source_params['loader'] == 'systemd-boot': + for mod in [x for x in os.listdir(kernel_dir) if x.startswith("systemd-")]: + cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[8:]) + exec_cmd(cp_cmd, True) + else: + raise WicError("unrecognized bootimg-efi loader: %s" % + source_params['loader']) + except KeyError: + raise WicError("bootimg-efi requires a loader, none specified") + + startup = os.path.join(kernel_dir, "startup.nsh") + if os.path.exists(startup): + cp_cmd = "cp %s %s/" % (startup, hdddir) + exec_cmd(cp_cmd, True) + + du_cmd = "du -bks %s" % hdddir + out = exec_cmd(du_cmd) + blocks = int(out.split()[0]) + + extra_blocks = part.get_extra_block_count(blocks) + + if extra_blocks < BOOTDD_EXTRA_SPACE: + extra_blocks = BOOTDD_EXTRA_SPACE + + blocks += extra_blocks + + logger.debug("Added %d extra blocks to %s to get to %d total blocks", + extra_blocks, part.mountpoint, blocks) + + # dosfs image, created by mkdosfs + bootimg = "%s/boot.img" % cr_workdir + + dosfs_cmd = "mkdosfs -n efi -C %s %d" % (bootimg, blocks) + exec_native_cmd(dosfs_cmd, native_sysroot) + + mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir) + exec_native_cmd(mcopy_cmd, native_sysroot) + + chmod_cmd = "chmod 644 %s" % bootimg + exec_cmd(chmod_cmd) + + du_cmd = "du -Lbks %s" % bootimg + out = exec_cmd(du_cmd) + bootimg_size = out.split()[0] + + part.size = int(bootimg_size) + part.source_file = bootimg -- cgit v1.2.3-54-g00ecf