1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# DESCRIPTION 5*4882a593Smuzhiyun# This implements the 'bootimg-partition' source plugin class for 6*4882a593Smuzhiyun# 'wic'. The plugin creates an image of boot partition, copying over 7*4882a593Smuzhiyun# files listed in IMAGE_BOOT_FILES bitbake variable. 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun# AUTHORS 10*4882a593Smuzhiyun# Maciej Borzecki <maciej.borzecki (at] open-rnd.pl> 11*4882a593Smuzhiyun# 12*4882a593Smuzhiyun 13*4882a593Smuzhiyunimport logging 14*4882a593Smuzhiyunimport os 15*4882a593Smuzhiyunimport re 16*4882a593Smuzhiyun 17*4882a593Smuzhiyunfrom glob import glob 18*4882a593Smuzhiyun 19*4882a593Smuzhiyunfrom wic import WicError 20*4882a593Smuzhiyunfrom wic.engine import get_custom_config 21*4882a593Smuzhiyunfrom wic.pluginbase import SourcePlugin 22*4882a593Smuzhiyunfrom wic.misc import exec_cmd, get_bitbake_var 23*4882a593Smuzhiyun 24*4882a593Smuzhiyunlogger = logging.getLogger('wic') 25*4882a593Smuzhiyun 26*4882a593Smuzhiyunclass BootimgPartitionPlugin(SourcePlugin): 27*4882a593Smuzhiyun """ 28*4882a593Smuzhiyun Create an image of boot partition, copying over files 29*4882a593Smuzhiyun listed in IMAGE_BOOT_FILES bitbake variable. 30*4882a593Smuzhiyun """ 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun name = 'bootimg-partition' 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun @classmethod 35*4882a593Smuzhiyun def do_configure_partition(cls, part, source_params, cr, cr_workdir, 36*4882a593Smuzhiyun oe_builddir, bootimg_dir, kernel_dir, 37*4882a593Smuzhiyun native_sysroot): 38*4882a593Smuzhiyun """ 39*4882a593Smuzhiyun Called before do_prepare_partition(), create u-boot specific boot config 40*4882a593Smuzhiyun """ 41*4882a593Smuzhiyun hdddir = "%s/boot.%d" % (cr_workdir, part.lineno) 42*4882a593Smuzhiyun install_cmd = "install -d %s" % hdddir 43*4882a593Smuzhiyun exec_cmd(install_cmd) 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun if not kernel_dir: 46*4882a593Smuzhiyun kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") 47*4882a593Smuzhiyun if not kernel_dir: 48*4882a593Smuzhiyun raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun boot_files = None 51*4882a593Smuzhiyun for (fmt, id) in (("_uuid-%s", part.uuid), ("_label-%s", part.label), (None, None)): 52*4882a593Smuzhiyun if fmt: 53*4882a593Smuzhiyun var = fmt % id 54*4882a593Smuzhiyun else: 55*4882a593Smuzhiyun var = "" 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun boot_files = get_bitbake_var("IMAGE_BOOT_FILES" + var) 58*4882a593Smuzhiyun if boot_files is not None: 59*4882a593Smuzhiyun break 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun if boot_files is None: 62*4882a593Smuzhiyun raise WicError('No boot files defined, IMAGE_BOOT_FILES unset for entry #%d' % part.lineno) 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun logger.debug('Boot files: %s', boot_files) 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun # list of tuples (src_name, dst_name) 67*4882a593Smuzhiyun deploy_files = [] 68*4882a593Smuzhiyun for src_entry in re.findall(r'[\w;\-\./\*]+', boot_files): 69*4882a593Smuzhiyun if ';' in src_entry: 70*4882a593Smuzhiyun dst_entry = tuple(src_entry.split(';')) 71*4882a593Smuzhiyun if not dst_entry[0] or not dst_entry[1]: 72*4882a593Smuzhiyun raise WicError('Malformed boot file entry: %s' % src_entry) 73*4882a593Smuzhiyun else: 74*4882a593Smuzhiyun dst_entry = (src_entry, src_entry) 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun logger.debug('Destination entry: %r', dst_entry) 77*4882a593Smuzhiyun deploy_files.append(dst_entry) 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun cls.install_task = []; 80*4882a593Smuzhiyun for deploy_entry in deploy_files: 81*4882a593Smuzhiyun src, dst = deploy_entry 82*4882a593Smuzhiyun if '*' in src: 83*4882a593Smuzhiyun # by default install files under their basename 84*4882a593Smuzhiyun entry_name_fn = os.path.basename 85*4882a593Smuzhiyun if dst != src: 86*4882a593Smuzhiyun # unless a target name was given, then treat name 87*4882a593Smuzhiyun # as a directory and append a basename 88*4882a593Smuzhiyun entry_name_fn = lambda name: \ 89*4882a593Smuzhiyun os.path.join(dst, 90*4882a593Smuzhiyun os.path.basename(name)) 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun srcs = glob(os.path.join(kernel_dir, src)) 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun logger.debug('Globbed sources: %s', ', '.join(srcs)) 95*4882a593Smuzhiyun for entry in srcs: 96*4882a593Smuzhiyun src = os.path.relpath(entry, kernel_dir) 97*4882a593Smuzhiyun entry_dst_name = entry_name_fn(entry) 98*4882a593Smuzhiyun cls.install_task.append((src, entry_dst_name)) 99*4882a593Smuzhiyun else: 100*4882a593Smuzhiyun cls.install_task.append((src, dst)) 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun if source_params.get('loader') != "u-boot": 103*4882a593Smuzhiyun return 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun configfile = cr.ks.bootloader.configfile 106*4882a593Smuzhiyun custom_cfg = None 107*4882a593Smuzhiyun if configfile: 108*4882a593Smuzhiyun custom_cfg = get_custom_config(configfile) 109*4882a593Smuzhiyun if custom_cfg: 110*4882a593Smuzhiyun # Use a custom configuration for extlinux.conf 111*4882a593Smuzhiyun extlinux_conf = custom_cfg 112*4882a593Smuzhiyun logger.debug("Using custom configuration file " 113*4882a593Smuzhiyun "%s for extlinux.cfg", configfile) 114*4882a593Smuzhiyun else: 115*4882a593Smuzhiyun raise WicError("configfile is specified but failed to " 116*4882a593Smuzhiyun "get it from %s." % configfile) 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun if not custom_cfg: 119*4882a593Smuzhiyun # The kernel types supported by the sysboot of u-boot 120*4882a593Smuzhiyun kernel_types = ["zImage", "Image", "fitImage", "uImage", "vmlinux"] 121*4882a593Smuzhiyun has_dtb = False 122*4882a593Smuzhiyun fdt_dir = '/' 123*4882a593Smuzhiyun kernel_name = None 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun # Find the kernel image name, from the highest precedence to lowest 126*4882a593Smuzhiyun for image in kernel_types: 127*4882a593Smuzhiyun for task in cls.install_task: 128*4882a593Smuzhiyun src, dst = task 129*4882a593Smuzhiyun if re.match(image, src): 130*4882a593Smuzhiyun kernel_name = os.path.join('/', dst) 131*4882a593Smuzhiyun break 132*4882a593Smuzhiyun if kernel_name: 133*4882a593Smuzhiyun break 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun for task in cls.install_task: 136*4882a593Smuzhiyun src, dst = task 137*4882a593Smuzhiyun # We suppose that all the dtb are in the same directory 138*4882a593Smuzhiyun if re.search(r'\.dtb', src) and fdt_dir == '/': 139*4882a593Smuzhiyun has_dtb = True 140*4882a593Smuzhiyun fdt_dir = os.path.join(fdt_dir, os.path.dirname(dst)) 141*4882a593Smuzhiyun break 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun if not kernel_name: 144*4882a593Smuzhiyun raise WicError('No kernel file found') 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun # Compose the extlinux.conf 147*4882a593Smuzhiyun extlinux_conf = "default Yocto\n" 148*4882a593Smuzhiyun extlinux_conf += "label Yocto\n" 149*4882a593Smuzhiyun extlinux_conf += " kernel %s\n" % kernel_name 150*4882a593Smuzhiyun if has_dtb: 151*4882a593Smuzhiyun extlinux_conf += " fdtdir %s\n" % fdt_dir 152*4882a593Smuzhiyun bootloader = cr.ks.bootloader 153*4882a593Smuzhiyun extlinux_conf += "append root=%s rootwait %s\n" \ 154*4882a593Smuzhiyun % (cr.rootdev, bootloader.append if bootloader.append else '') 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun install_cmd = "install -d %s/extlinux/" % hdddir 157*4882a593Smuzhiyun exec_cmd(install_cmd) 158*4882a593Smuzhiyun cfg = open("%s/extlinux/extlinux.conf" % hdddir, "w") 159*4882a593Smuzhiyun cfg.write(extlinux_conf) 160*4882a593Smuzhiyun cfg.close() 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun @classmethod 164*4882a593Smuzhiyun def do_prepare_partition(cls, part, source_params, cr, cr_workdir, 165*4882a593Smuzhiyun oe_builddir, bootimg_dir, kernel_dir, 166*4882a593Smuzhiyun rootfs_dir, native_sysroot): 167*4882a593Smuzhiyun """ 168*4882a593Smuzhiyun Called to do the actual content population for a partition i.e. it 169*4882a593Smuzhiyun 'prepares' the partition to be incorporated into the image. 170*4882a593Smuzhiyun In this case, does the following: 171*4882a593Smuzhiyun - sets up a vfat partition 172*4882a593Smuzhiyun - copies all files listed in IMAGE_BOOT_FILES variable 173*4882a593Smuzhiyun """ 174*4882a593Smuzhiyun hdddir = "%s/boot.%d" % (cr_workdir, part.lineno) 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun if not kernel_dir: 177*4882a593Smuzhiyun kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") 178*4882a593Smuzhiyun if not kernel_dir: 179*4882a593Smuzhiyun raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun logger.debug('Kernel dir: %s', bootimg_dir) 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun for task in cls.install_task: 185*4882a593Smuzhiyun src_path, dst_path = task 186*4882a593Smuzhiyun logger.debug('Install %s as %s', src_path, dst_path) 187*4882a593Smuzhiyun install_cmd = "install -m 0644 -D %s %s" \ 188*4882a593Smuzhiyun % (os.path.join(kernel_dir, src_path), 189*4882a593Smuzhiyun os.path.join(hdddir, dst_path)) 190*4882a593Smuzhiyun exec_cmd(install_cmd) 191*4882a593Smuzhiyun 192*4882a593Smuzhiyun logger.debug('Prepare boot partition using rootfs in %s', hdddir) 193*4882a593Smuzhiyun part.prepare_rootfs(cr_workdir, oe_builddir, hdddir, 194*4882a593Smuzhiyun native_sysroot, False) 195