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