1*96ff1984SBrad Bishop#!/usr/bin/env python3 2eb8dc403SDave Cobbley# 3eb8dc403SDave Cobbley# Copyright (c) 2011 Intel, Inc. 4eb8dc403SDave Cobbley# 5c342db35SBrad Bishop# SPDX-License-Identifier: GPL-2.0-only 6eb8dc403SDave Cobbley# 7eb8dc403SDave Cobbley 8eb8dc403SDave Cobbley__all__ = ['ImagerPlugin', 'SourcePlugin'] 9eb8dc403SDave Cobbley 10eb8dc403SDave Cobbleyimport os 11eb8dc403SDave Cobbleyimport logging 12eb8dc403SDave Cobbley 13eb8dc403SDave Cobbleyfrom collections import defaultdict 14eb8dc403SDave Cobbleyfrom importlib.machinery import SourceFileLoader 15eb8dc403SDave Cobbley 16eb8dc403SDave Cobbleyfrom wic import WicError 17eb8dc403SDave Cobbleyfrom wic.misc import get_bitbake_var 18eb8dc403SDave Cobbley 19eb8dc403SDave CobbleyPLUGIN_TYPES = ["imager", "source"] 20eb8dc403SDave Cobbley 21eb8dc403SDave CobbleySCRIPTS_PLUGIN_DIR = "scripts/lib/wic/plugins" 22eb8dc403SDave Cobbley 23eb8dc403SDave Cobbleylogger = logging.getLogger('wic') 24eb8dc403SDave Cobbley 25eb8dc403SDave CobbleyPLUGINS = defaultdict(dict) 26eb8dc403SDave Cobbley 27eb8dc403SDave Cobbleyclass PluginMgr: 28eb8dc403SDave Cobbley _plugin_dirs = [] 29eb8dc403SDave Cobbley 30eb8dc403SDave Cobbley @classmethod 31eb8dc403SDave Cobbley def get_plugins(cls, ptype): 32eb8dc403SDave Cobbley """Get dictionary of <plugin_name>:<class> pairs.""" 33eb8dc403SDave Cobbley if ptype not in PLUGIN_TYPES: 34eb8dc403SDave Cobbley raise WicError('%s is not valid plugin type' % ptype) 35eb8dc403SDave Cobbley 36eb8dc403SDave Cobbley # collect plugin directories 37eb8dc403SDave Cobbley if not cls._plugin_dirs: 38eb8dc403SDave Cobbley cls._plugin_dirs = [os.path.join(os.path.dirname(__file__), 'plugins')] 39eb8dc403SDave Cobbley layers = get_bitbake_var("BBLAYERS") or '' 40eb8dc403SDave Cobbley for layer_path in layers.split(): 41eb8dc403SDave Cobbley path = os.path.join(layer_path, SCRIPTS_PLUGIN_DIR) 42eb8dc403SDave Cobbley path = os.path.abspath(os.path.expanduser(path)) 43eb8dc403SDave Cobbley if path not in cls._plugin_dirs and os.path.isdir(path): 44eb8dc403SDave Cobbley cls._plugin_dirs.insert(0, path) 45eb8dc403SDave Cobbley 46eb8dc403SDave Cobbley if ptype not in PLUGINS: 47eb8dc403SDave Cobbley # load all ptype plugins 48eb8dc403SDave Cobbley for pdir in cls._plugin_dirs: 49eb8dc403SDave Cobbley ppath = os.path.join(pdir, ptype) 50eb8dc403SDave Cobbley if os.path.isdir(ppath): 51eb8dc403SDave Cobbley for fname in os.listdir(ppath): 52eb8dc403SDave Cobbley if fname.endswith('.py'): 53eb8dc403SDave Cobbley mname = fname[:-3] 54eb8dc403SDave Cobbley mpath = os.path.join(ppath, fname) 55eb8dc403SDave Cobbley logger.debug("loading plugin module %s", mpath) 56eb8dc403SDave Cobbley SourceFileLoader(mname, mpath).load_module() 57eb8dc403SDave Cobbley 58eb8dc403SDave Cobbley return PLUGINS.get(ptype) 59eb8dc403SDave Cobbley 60eb8dc403SDave Cobbleyclass PluginMeta(type): 61eb8dc403SDave Cobbley def __new__(cls, name, bases, attrs): 62eb8dc403SDave Cobbley class_type = type.__new__(cls, name, bases, attrs) 63eb8dc403SDave Cobbley if 'name' in attrs: 64eb8dc403SDave Cobbley PLUGINS[class_type.wic_plugin_type][attrs['name']] = class_type 65eb8dc403SDave Cobbley 66eb8dc403SDave Cobbley return class_type 67eb8dc403SDave Cobbley 68eb8dc403SDave Cobbleyclass ImagerPlugin(metaclass=PluginMeta): 69eb8dc403SDave Cobbley wic_plugin_type = "imager" 70eb8dc403SDave Cobbley 71eb8dc403SDave Cobbley def do_create(self): 72eb8dc403SDave Cobbley raise WicError("Method %s.do_create is not implemented" % 73eb8dc403SDave Cobbley self.__class__.__name__) 74eb8dc403SDave Cobbley 75eb8dc403SDave Cobbleyclass SourcePlugin(metaclass=PluginMeta): 76eb8dc403SDave Cobbley wic_plugin_type = "source" 77eb8dc403SDave Cobbley """ 78eb8dc403SDave Cobbley The methods that can be implemented by --source plugins. 79eb8dc403SDave Cobbley 80eb8dc403SDave Cobbley Any methods not implemented in a subclass inherit these. 81eb8dc403SDave Cobbley """ 82eb8dc403SDave Cobbley 83eb8dc403SDave Cobbley @classmethod 84eb8dc403SDave Cobbley def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir, 85eb8dc403SDave Cobbley bootimg_dir, kernel_dir, native_sysroot): 86eb8dc403SDave Cobbley """ 87eb8dc403SDave Cobbley Called after all partitions have been prepared and assembled into a 88eb8dc403SDave Cobbley disk image. This provides a hook to allow finalization of a 89eb8dc403SDave Cobbley disk image e.g. to write an MBR to it. 90eb8dc403SDave Cobbley """ 91eb8dc403SDave Cobbley logger.debug("SourcePlugin: do_install_disk: disk: %s", disk_name) 92eb8dc403SDave Cobbley 93eb8dc403SDave Cobbley @classmethod 94eb8dc403SDave Cobbley def do_stage_partition(cls, part, source_params, creator, cr_workdir, 95eb8dc403SDave Cobbley oe_builddir, bootimg_dir, kernel_dir, 96eb8dc403SDave Cobbley native_sysroot): 97eb8dc403SDave Cobbley """ 98eb8dc403SDave Cobbley Special content staging hook called before do_prepare_partition(), 99eb8dc403SDave Cobbley normally empty. 100eb8dc403SDave Cobbley 101eb8dc403SDave Cobbley Typically, a partition will just use the passed-in parame e.g 102eb8dc403SDave Cobbley straight bootimg_dir, etc, but in some cases, things need to 103eb8dc403SDave Cobbley be more tailored e.g. to use a deploy dir + /boot, etc. This 104eb8dc403SDave Cobbley hook allows those files to be staged in a customized fashion. 105eb8dc403SDave Cobbley Not that get_bitbake_var() allows you to acces non-standard 106eb8dc403SDave Cobbley variables that you might want to use for this. 107eb8dc403SDave Cobbley """ 108eb8dc403SDave Cobbley logger.debug("SourcePlugin: do_stage_partition: part: %s", part) 109eb8dc403SDave Cobbley 110eb8dc403SDave Cobbley @classmethod 111eb8dc403SDave Cobbley def do_configure_partition(cls, part, source_params, creator, cr_workdir, 112eb8dc403SDave Cobbley oe_builddir, bootimg_dir, kernel_dir, 113eb8dc403SDave Cobbley native_sysroot): 114eb8dc403SDave Cobbley """ 115eb8dc403SDave Cobbley Called before do_prepare_partition(), typically used to create 116eb8dc403SDave Cobbley custom configuration files for a partition, for example 117eb8dc403SDave Cobbley syslinux or grub config files. 118eb8dc403SDave Cobbley """ 119eb8dc403SDave Cobbley logger.debug("SourcePlugin: do_configure_partition: part: %s", part) 120eb8dc403SDave Cobbley 121eb8dc403SDave Cobbley @classmethod 122eb8dc403SDave Cobbley def do_prepare_partition(cls, part, source_params, creator, cr_workdir, 123eb8dc403SDave Cobbley oe_builddir, bootimg_dir, kernel_dir, rootfs_dir, 124eb8dc403SDave Cobbley native_sysroot): 125eb8dc403SDave Cobbley """ 126eb8dc403SDave Cobbley Called to do the actual content population for a partition i.e. it 127eb8dc403SDave Cobbley 'prepares' the partition to be incorporated into the image. 128eb8dc403SDave Cobbley """ 129eb8dc403SDave Cobbley logger.debug("SourcePlugin: do_prepare_partition: part: %s", part) 130eb8dc403SDave Cobbley 131eb8dc403SDave Cobbley @classmethod 132eb8dc403SDave Cobbley def do_post_partition(cls, part, source_params, creator, cr_workdir, 133eb8dc403SDave Cobbley oe_builddir, bootimg_dir, kernel_dir, rootfs_dir, 134eb8dc403SDave Cobbley native_sysroot): 135eb8dc403SDave Cobbley """ 136eb8dc403SDave Cobbley Called after the partition is created. It is useful to add post 137eb8dc403SDave Cobbley operations e.g. security signing the partition. 138eb8dc403SDave Cobbley """ 139eb8dc403SDave Cobbley logger.debug("SourcePlugin: do_post_partition: part: %s", part) 140