def do_prepare_partition(self, part, source_params, cr, cr_workdir, oe_builddir, bootimg_dir, kernel_dir, krootfs_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 legacy bios boot partition. """ if part.rootfs is None: if not 'ROOTFS_DIR' in krootfs_dir: msg = "Couldn't find --rootfs-dir, exiting" msger.error(msg) rootfs_dir = krootfs_dir['ROOTFS_DIR'] else: if part.rootfs in krootfs_dir: rootfs_dir = krootfs_dir[part.rootfs] elif part.rootfs: rootfs_dir = part.rootfs else: msg = "Couldn't find --rootfs-dir=%s connection" msg += " or it is not a valid path, exiting" msger.error(msg % part.rootfs) real_rootfs_dir = self.__get_rootfs_dir(rootfs_dir) part.set_rootfs(real_rootfs_dir) part.prepare_rootfs(cr_workdir, oe_builddir, real_rootfs_dir, native_sysroot)
def do_install_disk(self, disk, disk_name, cr, workdir, oe_builddir, bootimg_dir, kernel_dir, native_sysroot): """ Called after all partitions have been prepared and assembled into a disk image. In this case, we install the MBR. """ mbrfile = "%s/syslinux/" % bootimg_dir if cr._ptable_format == 'msdos': mbrfile += "mbr.bin" if not os.path.exists(mbrfile): msger.error( "Couldn't find %s. If using the -e option, do you have the right MACHINE set in local.conf? If not, is the bootimg_dir path correct?" % mbrfile) full_path = cr._full_path(workdir, disk_name, "direct") msger.debug("Installing MBR on disk %s as %s with size %s bytes" \ % (disk_name, full_path, disk['min_size'])) rc = runner.show( ['dd', 'if=%s' % mbrfile, 'of=%s' % full_path, 'conv=notrunc']) if rc != 0: raise ImageError("Unable to set MBR to %s" % full_path)
def postoptparse(self, options): abspath = lambda pth: os.path.abspath(os.path.expanduser(pth)) if options.verbose: msger.set_loglevel('verbose') if options.debug: msger.set_loglevel('debug') if options.logfile: logfile_abs_path = abspath(options.logfile) if os.path.isdir(logfile_abs_path): raise errors.Usage("logfile's path %s should be file" % options.logfile) if not os.path.exists(os.path.dirname(logfile_abs_path)): os.makedirs(os.path.dirname(logfile_abs_path)) msger.set_interactive(False) msger.set_logfile(logfile_abs_path) configmgr.create['logfile'] = options.logfile if options.config: configmgr.reset() configmgr._siteconf = options.config if options.outdir is not None: configmgr.create['outdir'] = abspath(options.outdir) cdir = 'outdir' if os.path.exists(configmgr.create[cdir]) \ and not os.path.isdir(configmgr.create[cdir]): msger.error('Invalid directory specified: %s' \ % configmgr.create[cdir]) if options.enabletmpfs: configmgr.create['enabletmpfs'] = options.enabletmpfs
def do_prepare_partition(cls, part, source_params, cr, 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. """ if not bootimg_dir: bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") if not bootimg_dir: msger.error("Couldn't find DEPLOY_DIR_IMAGE, exiting\n") msger.debug('Bootimg dir: %s' % bootimg_dir) if 'file' not in source_params: msger.error("No file specified\n") return src = os.path.join(bootimg_dir, source_params['file']) dst = os.path.join(cr_workdir, "%s.%s" % (source_params['file'], part.lineno)) if 'skip' in source_params: sparse_copy(src, dst, skip=source_params['skip']) else: sparse_copy(src, dst) # get the size in the right units for kickstart (kB) du_cmd = "du -Lbks %s" % dst out = exec_cmd(du_cmd) filesize = out.split()[0] if int(filesize) > int(part.size): part.size = filesize part.source_file = dst
def exec_native_cmd(cmd_and_args, native_sysroot, catch = 3): """ Execute native command, catching stderr, stdout Need to execute as_shell if the command uses wildcards Always need to execute native commands as_shell """ native_paths = \ "export PATH=%s/sbin:%s/usr/sbin:%s/usr/bin" % \ (native_sysroot, native_sysroot, native_sysroot) native_cmd_and_args = "%s;%s" % (native_paths, cmd_and_args) msger.debug("exec_native_cmd: %s" % cmd_and_args) args = cmd_and_args.split() msger.debug(args) rc, out = __exec_cmd(native_cmd_and_args, True, catch) if rc == 127: # shell command-not-found msger.error("A native program %s required to build the image " "was not found (see details above). Please make sure " "it's installed and try again." % args[0]) return (rc, out)
def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir, bootimg_dir, kernel_dir, native_sysroot): """ Called after all partitions have been prepared and assembled into a disk image. In this case, we install the MBR. """ mbrfile = "%s/syslinux/" % bootimg_dir if creator.ptable_format == 'msdos': mbrfile += "mbr.bin" elif creator.ptable_format == 'gpt': mbrfile += "gptmbr.bin" else: msger.error("Unsupported partition table: %s" % creator.ptable_format) if not os.path.exists(mbrfile): msger.error("Couldn't find %s. If using the -e option, do you " "have the right MACHINE set in local.conf? If not, " "is the bootimg_dir path correct?" % mbrfile) full_path = creator._full_path(workdir, disk_name, "direct") msger.debug("Installing MBR on disk %s as %s with size %s bytes" \ % (disk_name, full_path, disk['min_size'])) rcode = runner.show(['dd', 'if=%s' % mbrfile, 'of=%s' % full_path, 'conv=notrunc']) if rcode != 0: raise ImageError("Unable to set MBR to %s" % full_path)
def read_kickstart(path): """Parse a kickstart file and return a KickstartParser instance. This is a simple utility function which takes a path to a kickstart file, parses it and returns a pykickstart KickstartParser instance which can be then passed to an ImageCreator constructor. If an error occurs, a CreatorError exception is thrown. """ # version = ksversion.makeVersion() # ks = ksparser.KickstartParser(version) using_version = ksversion.DEVEL commandMap[using_version]["bootloader"] = wicboot.Wic_Bootloader commandMap[using_version]["part"] = partition.Wic_Partition commandMap[using_version]["partition"] = partition.Wic_Partition dataMap[using_version]["PartData"] = partition.Wic_PartData superclass = ksversion.returnClassForVersion(version=using_version) class KSHandlers(superclass): def __init__(self): superclass.__init__(self, mapping=commandMap[using_version]) kickstart = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=True) try: kickstart.readKickstart(path) except (kserrors.KickstartParseError, kserrors.KickstartError), err: msger.warning("Errors occurred when parsing kickstart file: %s\n" % path) msger.error("%s" % err)
def get_rootfs_size(self, actual_rootfs_size=0): """ Calculate the required size of rootfs taking into consideration --size/--fixed-size flags as well as overhead and extra space, as specified in kickstart file. Raises an error if the `actual_rootfs_size` is larger than fixed-size rootfs. """ if self.fixed_size: rootfs_size = self.fixed_size if actual_rootfs_size > rootfs_size: msger.error("Actual rootfs size (%d kB) is larger than allowed size %d kB" \ %(actual_rootfs_size, rootfs_size)) else: extra_blocks = self.get_extra_block_count(actual_rootfs_size) if extra_blocks < self.extra_space: extra_blocks = self.extra_space rootfs_size = actual_rootfs_size + extra_blocks rootfs_size *= self.overhead_factor msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \ (extra_blocks, self.mountpoint, rootfs_size)) return rootfs_size
def read_kickstart(path): """Parse a kickstart file and return a KickstartParser instance. This is a simple utility function which takes a path to a kickstart file, parses it and returns a pykickstart KickstartParser instance which can be then passed to an ImageCreator constructor. If an error occurs, a CreatorError exception is thrown. """ #version = ksversion.makeVersion() #ks = ksparser.KickstartParser(version) using_version = ksversion.DEVEL commandMap[using_version]["bootloader"] = wicboot.Wic_Bootloader commandMap[using_version]["part"] = partition.Wic_Partition commandMap[using_version]["partition"] = partition.Wic_Partition dataMap[using_version]["PartData"] = partition.Wic_PartData superclass = ksversion.returnClassForVersion(version=using_version) class KSHandlers(superclass): def __init__(self): superclass.__init__(self, mapping=commandMap[using_version]) kickstart = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=True) try: kickstart.readKickstart(path) except (kserrors.KickstartParseError, kserrors.KickstartError), err: msger.warning("Errors occurred when parsing kickstart file: %s\n" % path) msger.error("%s" % err)
def do_install_disk(cls, disk, disk_name, image_creator, workdir, oe_builddir, bootimg_dir, kernel_dir, native_sysroot): """ Assemble partitions to disk image Called after all partitions have been prepared and assembled into a disk image. In this case, we install the MBR. """ mbrfile = os.path.join(native_sysroot, "usr/share/syslinux/") if image_creator.ptable_format == 'msdos': mbrfile += "mbr.bin" elif image_creator.ptable_format == 'gpt': mbrfile += "gptmbr.bin" else: msger.error("Unsupported partition table: %s" % \ image_creator.ptable_format) if not os.path.exists(mbrfile): msger.error("Couldn't find %s. Has syslinux-native been baked?" % mbrfile) full_path = disk['disk'].device msger.debug("Installing MBR on disk %s as %s with size %s bytes" \ % (disk_name, full_path, disk['min_size'])) ret_code = runner.show( ['dd', 'if=%s' % mbrfile, 'of=%s' % full_path, 'conv=notrunc']) if ret_code != 0: raise ImageError("Unable to set MBR to %s" % full_path)
def do_prepare_partition(self, part, source_params, cr, 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. """ if not bootimg_dir: bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") if not bootimg_dir: msger.error("Couldn't find DEPLOY_DIR_IMAGE, exiting\n") msger.debug('Bootimg dir: %s' % bootimg_dir) if ('file' not in source_params): msger.error("No file specified\n") return src = os.path.join(bootimg_dir, source_params['file']) # get the size in the right units for kickstart (kB) du_cmd = "du -Lbks %s" % src out = exec_cmd(du_cmd) filesize = out.split()[0] if filesize > part.size: part.size = filesize part.source_file = src
def exec_native_cmd(cmd_and_args, native_sysroot, catch=3): """ Execute native command, catching stderr, stdout Need to execute as_shell if the command uses wildcards Always need to execute native commands as_shell """ native_paths = \ "export PATH=%s/sbin:%s/usr/sbin:%s/usr/bin:$PATH" % \ (native_sysroot, native_sysroot, native_sysroot) native_cmd_and_args = "%s;%s" % (native_paths, cmd_and_args) msger.debug("exec_native_cmd: %s" % cmd_and_args) args = cmd_and_args.split() msger.debug(args) rc, out = __exec_cmd(native_cmd_and_args, True, catch) if rc == 127: # shell command-not-found msger.error("A native (host) program required to build the image " "was not found (see details above). Please make sure " "it's installed and try again.") return (rc, out)
def do_install_disk(cls, disk, disk_name, image_creator, workdir, oe_builddir, bootimg_dir, kernel_dir, native_sysroot): """ Assemble partitions to disk image Called after all partitions have been prepared and assembled into a disk image. In this case, we install the MBR. """ mbrfile = os.path.join(native_sysroot, "usr/share/syslinux/") if image_creator.ptable_format == 'msdos': mbrfile += "mbr.bin" elif image_creator.ptable_format == 'gpt': mbrfile += "gptmbr.bin" else: msger.error("Unsupported partition table: %s" % \ image_creator.ptable_format) if not os.path.exists(mbrfile): msger.error("Couldn't find %s. Has syslinux-native been baked?" % mbrfile) full_path = disk['disk'].device msger.debug("Installing MBR on disk %s as %s with size %s bytes" \ % (disk_name, full_path, disk['min_size'])) ret_code = runner.show(['dd', 'if=%s' % mbrfile, 'of=%s' % full_path, 'conv=notrunc']) if ret_code != 0: raise ImageError("Unable to set MBR to %s" % full_path)
def runtool(cmdln_or_args, catch=1): """ wrapper for most of the subprocess calls input: cmdln_or_args: can be both args and cmdln str (shell=True) catch: 0, quitely run 1, only STDOUT 2, only STDERR 3, both STDOUT and STDERR return: (rc, output) if catch==0: the output will always None """ if catch not in (0, 1, 2, 3): # invalid catch selection, will cause exception, that's good return None if isinstance(cmdln_or_args, list): cmd = cmdln_or_args[0] shell = False else: import shlex cmd = shlex.split(cmdln_or_args)[0] shell = True if catch != 3: dev_null = os.open("/dev/null", os.O_WRONLY) if catch == 0: sout = dev_null serr = dev_null elif catch == 1: sout = subprocess.PIPE serr = dev_null elif catch == 2: sout = dev_null serr = subprocess.PIPE elif catch == 3: sout = subprocess.PIPE serr = subprocess.STDOUT try: process = subprocess.Popen(cmdln_or_args, stdout=sout, stderr=serr, shell=shell) (sout, serr) = process.communicate() # combine stdout and stderr, filter None out and decode out = ''.join([out.decode('utf-8') for out in [sout, serr] if out]) except OSError as err: if err.errno == 2: # [Errno 2] No such file or directory msger.error('Cannot run command: %s, lost dependency?' % cmd) else: raise # relay finally: if catch != 3: os.close(dev_null) return (process.returncode, out)
def __init__(self, wks_file, rootfs_dir, bootimg_dir, kernel_dir, native_sysroot, scripts_path, oe_builddir, options): try: self.ks = KickStart(wks_file) except KickStartError as err: msger.error(str(err)) # parse possible 'rootfs=name' items self.rootfs_dir = dict( rdir.split('=') for rdir in rootfs_dir.split(' ')) self.bootimg_dir = bootimg_dir self.kernel_dir = kernel_dir self.native_sysroot = native_sysroot self.oe_builddir = oe_builddir self.outdir = options.outdir self.compressor = options.compressor self.bmap = options.bmap self.name = "%s-%s" % (os.path.splitext( os.path.basename(wks_file))[0], strftime("%Y%m%d%H%M")) self.workdir = tempfile.mkdtemp(dir=self.outdir, prefix='tmp.wic.') self._image = None self._disks = {} self._disk_format = "direct" self._disk_names = [] self.ptable_format = self.ks.bootloader.ptable
def wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir, native_sysroot, scripts_path, options): """ Create image wks_file - user-defined OE kickstart file rootfs_dir - absolute path to the build's /rootfs dir bootimg_dir - absolute path to the build's boot artifacts directory kernel_dir - absolute path to the build's kernel directory native_sysroot - absolute path to the build's native sysroots dir scripts_path - absolute path to /scripts dir image_output_dir - dirname to create for image options - wic command line options (debug, bmap, etc) Normally, the values for the build artifacts values are determined by 'wic -e' from the output of the 'bitbake -e' command given an image name e.g. 'core-image-minimal' and a given machine set in local.conf. If that's the case, the variables get the following values from the output of 'bitbake -e': rootfs_dir: IMAGE_ROOTFS kernel_dir: DEPLOY_DIR_IMAGE native_sysroot: STAGING_DIR_NATIVE In the above case, bootimg_dir remains unset and the plugin-specific image creation code is responsible for finding the bootimg artifacts. In the case where the values are passed in explicitly i.e 'wic -e' is not used but rather the individual 'wic' options are used to explicitly specify these values. """ try: oe_builddir = os.environ["BUILDDIR"] except KeyError: print( "BUILDDIR not found, exiting. (Did you forget to source oe-init-build-env?)" ) sys.exit(1) if options.debug: msger.set_loglevel('debug') if not os.path.exists(options.outdir): os.makedirs(options.outdir) pname = 'direct' plugin_class = pluginmgr.get_plugins('imager').get(pname) if not plugin_class: msger.error('Unknown plugin: %s' % pname) plugin = plugin_class(wks_file, rootfs_dir, bootimg_dir, kernel_dir, native_sysroot, scripts_path, oe_builddir, options) plugin.do_create() print("\nThe image(s) were created using OE kickstart file:\n %s" % wks_file)
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 syslinux config """ hdddir = "%s/hdd/boot" % cr_workdir rm_cmd = "rm -rf " + cr_workdir exec_cmd(rm_cmd) install_cmd = "install -d %s" % hdddir exec_cmd(install_cmd) bootloader = creator.ks.bootloader custom_cfg = None if bootloader.configfile: custom_cfg = get_custom_config(bootloader.configfile) if custom_cfg: # Use a custom configuration for grub syslinux_conf = custom_cfg msger.debug("Using custom configuration file " "%s for syslinux.cfg" % bootloader.configfile) else: msger.error("configfile is specified but failed to " "get it from %s." % bootloader.configfile) if not custom_cfg: # Create syslinux configuration using parameters from wks file splash = os.path.join(cr_workdir, "/hdd/boot/splash.jpg") if os.path.exists(splash): splashline = "menu background splash.jpg" else: splashline = "" syslinux_conf = "" syslinux_conf += "PROMPT 0\n" syslinux_conf += "TIMEOUT " + str(bootloader.timeout) + "\n" syslinux_conf += "\n" syslinux_conf += "ALLOWOPTIONS 1\n" syslinux_conf += "SERIAL 0 115200\n" syslinux_conf += "\n" if splashline: syslinux_conf += "%s\n" % splashline syslinux_conf += "DEFAULT boot\n" syslinux_conf += "LABEL boot\n" kernel = "/vmlinuz" syslinux_conf += "KERNEL " + kernel + "\n" syslinux_conf += "APPEND label=boot root=%s %s\n" % \ (creator.rootdev, bootloader.append) msger.debug("Writing syslinux config %s/hdd/boot/syslinux.cfg" \ % cr_workdir) cfg = open("%s/hdd/boot/syslinux.cfg" % cr_workdir, "w") cfg.write(syslinux_conf) cfg.close()
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 syslinux config """ hdddir = "%s/hdd/boot" % cr_workdir install_cmd = "install -d %s" % hdddir exec_cmd(install_cmd) bootloader = creator.ks.bootloader custom_cfg = None if bootloader.configfile: custom_cfg = get_custom_config(bootloader.configfile) if custom_cfg: # Use a custom configuration for grub syslinux_conf = custom_cfg msger.debug("Using custom configuration file " "%s for syslinux.cfg" % bootloader.configfile) else: msger.error("configfile is specified but failed to " "get it from %s." % bootloader.configfile) if not custom_cfg: # Create syslinux configuration using parameters from wks file splash = os.path.join(cr_workdir, "/hdd/boot/splash.jpg") if os.path.exists(splash): splashline = "menu background splash.jpg" else: splashline = "" syslinux_conf = "" syslinux_conf += "PROMPT 0\n" syslinux_conf += "TIMEOUT " + str(bootloader.timeout) + "\n" syslinux_conf += "\n" syslinux_conf += "ALLOWOPTIONS 1\n" syslinux_conf += "SERIAL 0 115200\n" syslinux_conf += "\n" if splashline: syslinux_conf += "%s\n" % splashline syslinux_conf += "DEFAULT boot\n" syslinux_conf += "LABEL boot\n" kernel = "/vmlinuz" syslinux_conf += "KERNEL " + kernel + "\n" syslinux_conf += "APPEND label=boot root=%s %s\n" % \ (creator.rootdev, bootloader.append) msger.debug("Writing syslinux config %s/hdd/boot/syslinux.cfg" \ % cr_workdir) cfg = open("%s/hdd/boot/syslinux.cfg" % cr_workdir, "w") cfg.write(syslinux_conf) cfg.close()
def do_prepare_partition(self, part, source_params, cr, 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, does the following: - sets up a vfat partition - copies all files listed in IMAGE_BOOT_FILES variable """ hdddir = "%s/boot" % cr_workdir rm_cmd = "rm -rf %s" % cr_workdir exec_cmd(rm_cmd) install_cmd = "install -d %s" % hdddir exec_cmd(install_cmd) if not bootimg_dir: bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") if not bootimg_dir: msger.error("Couldn't find DEPLOY_DIR_IMAGE, exiting\n") msger.debug('Bootimg dir: %s' % bootimg_dir) boot_files = get_bitbake_var("IMAGE_BOOT_FILES") if not boot_files: msger.error('No boot files defined, IMAGE_BOOT_FILES unset') msger.debug('Boot files: %s' % boot_files) # list of tuples (src_name, dst_name) deploy_files = [] for src_entry in re.findall(r'[\w;\-\./]+', boot_files): if ';' in src_entry: dst_entry = tuple(src_entry.split(';')) else: dst_entry = (src_entry, src_entry) msger.debug('Destination entry: %r' % (dst_entry,)) deploy_files.append(dst_entry) for deploy_entry in deploy_files: src, dst = deploy_entry src_path = os.path.join(bootimg_dir, src) dst_path = os.path.join(hdddir, dst) msger.debug('Install %s as %s' % (os.path.basename(src_path), dst_path)) install_cmd = "install -m 0644 -D %s %s" \ % (src_path, dst_path) exec_cmd(install_cmd) msger.debug('Prepare boot partition using rootfs in %s' % (hdddir)) part.prepare_rootfs(cr_workdir, oe_builddir, hdddir, native_sysroot)
def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir, native_sysroot): """ Prepare content for a rootfs partition i.e. create a partition and fill it from a /rootfs dir. Currently handles ext2/3/4, btrfs and vfat. """ p_prefix = os.environ.get("PSEUDO_PREFIX", "%s/usr" % native_sysroot) p_localstatedir = os.environ.get("PSEUDO_LOCALSTATEDIR", "%s/../pseudo" % rootfs_dir) p_passwd = os.environ.get("PSEUDO_PASSWD", rootfs_dir) p_nosymlinkexp = os.environ.get("PSEUDO_NOSYMLINKEXP", "1") pseudo = "export PSEUDO_PREFIX=%s;" % p_prefix pseudo += "export PSEUDO_LOCALSTATEDIR=%s;" % p_localstatedir pseudo += "export PSEUDO_PASSWD=%s;" % p_passwd pseudo += "export PSEUDO_NOSYMLINKEXP=%s;" % p_nosymlinkexp pseudo += "%s " % get_bitbake_var("FAKEROOTCMD") rootfs = "%s/rootfs_%s.%s.%s" % (cr_workdir, self.label, self.lineno, self.fstype) if os.path.isfile(rootfs): os.remove(rootfs) if not self.fstype: msger.error("File system for partition %s not specified in kickstart, " \ "use --fstype option" % (self.mountpoint)) # Get rootfs size from bitbake variable if it's not set in .ks file if not self.size: # Bitbake variable ROOTFS_SIZE is calculated in # Image._get_rootfs_size method from meta/lib/oe/image.py # using IMAGE_ROOTFS_SIZE, IMAGE_ROOTFS_ALIGNMENT, # IMAGE_OVERHEAD_FACTOR and IMAGE_ROOTFS_EXTRA_SPACE rsize_bb = get_bitbake_var('ROOTFS_SIZE') if rsize_bb: msger.warning( 'overhead-factor was specified, but size was not,' ' so bitbake variables will be used for the size.' ' In this case both IMAGE_OVERHEAD_FACTOR and ' '--overhead-factor will be applied') self.size = int(round(float(rsize_bb))) for prefix in ("ext", "btrfs", "vfat", "squashfs"): if self.fstype.startswith(prefix): method = getattr(self, "prepare_rootfs_" + prefix) method(rootfs, oe_builddir, rootfs_dir, native_sysroot, pseudo) self.source_file = rootfs # get the rootfs size in the right units for kickstart (kB) du_cmd = "du -Lbks %s" % rootfs out = exec_cmd(du_cmd) self.size = int(out.split()[0]) break
def _build_initramfs_path(rootfs_dir, cr_workdir): """ Create path for initramfs image """ initrd = get_bitbake_var("INITRD") if not initrd: initrd_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") if not initrd_dir: msger.error("Couldn't find DEPLOY_DIR_IMAGE, exiting.\n") image_name = get_bitbake_var("IMAGE_BASENAME") if not image_name: msger.error("Couldn't find IMAGE_BASENAME, exiting.\n") image_type = get_bitbake_var("INITRAMFS_FSTYPES") if not image_type: msger.error("Couldn't find INITRAMFS_FSTYPES, exiting.\n") machine_arch = get_bitbake_var("MACHINE_ARCH") if not machine_arch: msger.error("Couldn't find MACHINE_ARCH, exiting.\n") initrd = glob.glob( '%s/%s*%s.%s' % (initrd_dir, image_name, machine_arch, image_type))[0] if not os.path.exists(initrd): # Create initrd from rootfs directory initrd = "%s/initrd.cpio.gz" % cr_workdir initrd_dir = "%s/INITRD" % cr_workdir shutil.copytree("%s" % rootfs_dir, \ "%s" % initrd_dir, symlinks=True) if os.path.isfile("%s/init" % rootfs_dir): shutil.copy2("%s/init" % rootfs_dir, "%s/init" % initrd_dir) elif os.path.lexists("%s/init" % rootfs_dir): os.symlink(os.readlink("%s/init" % rootfs_dir), \ "%s/init" % initrd_dir) elif os.path.isfile("%s/sbin/init" % rootfs_dir): shutil.copy2("%s/sbin/init" % rootfs_dir, \ "%s" % initrd_dir) elif os.path.lexists("%s/sbin/init" % rootfs_dir): os.symlink(os.readlink("%s/sbin/init" % rootfs_dir), \ "%s/init" % initrd_dir) else: msger.error("Couldn't find or build initrd, exiting.\n") exec_cmd("cd %s && find . | cpio -o -H newc -R +0:+0 >./initrd.cpio " \ % initrd_dir, as_shell=True) exec_cmd("gzip -f -9 -c %s/initrd.cpio > %s" \ % (cr_workdir, initrd), as_shell=True) shutil.rmtree(initrd_dir) return initrd
def _build_initramfs_path(rootfs_dir, cr_workdir): """ Create path for initramfs image """ initrd = get_bitbake_var("INITRD") if not initrd: initrd_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") if not initrd_dir: msger.error("Couldn't find DEPLOY_DIR_IMAGE, exiting.\n") image_name = get_bitbake_var("IMAGE_BASENAME") if not image_name: msger.error("Couldn't find IMAGE_BASENAME, exiting.\n") image_type = get_bitbake_var("INITRAMFS_FSTYPES") if not image_type: msger.error("Couldn't find INITRAMFS_FSTYPES, exiting.\n") machine_arch = get_bitbake_var("MACHINE_ARCH") if not machine_arch: msger.error("Couldn't find MACHINE_ARCH, exiting.\n") initrd = "%s/%s-initramfs-%s.%s" \ % (initrd_dir, image_name, machine_arch, image_type) if not os.path.exists(initrd): # Create initrd from rootfs directory initrd = "%s/initrd.cpio.gz" % cr_workdir initrd_dir = "%s/INITRD" % cr_workdir shutil.copytree("%s" % rootfs_dir, \ "%s" % initrd_dir, symlinks=True) if os.path.isfile("%s/init" % rootfs_dir): shutil.copy2("%s/init" % rootfs_dir, "%s/init" % initrd_dir) elif os.path.lexists("%s/init" % rootfs_dir): os.symlink(os.readlink("%s/init" % rootfs_dir), \ "%s/init" % initrd_dir) elif os.path.isfile("%s/sbin/init" % rootfs_dir): shutil.copy2("%s/sbin/init" % rootfs_dir, \ "%s" % initrd_dir) elif os.path.lexists("%s/sbin/init" % rootfs_dir): os.symlink(os.readlink("%s/sbin/init" % rootfs_dir), \ "%s/init" % initrd_dir) else: msger.error("Couldn't find or build initrd, exiting.\n") exec_cmd("cd %s && find . | cpio -o -H newc >%s/initrd.cpio " \ % (initrd_dir, cr_workdir), as_shell=True) exec_cmd("gzip -f -9 -c %s/initrd.cpio > %s" \ % (cr_workdir, initrd), as_shell=True) shutil.rmtree(initrd_dir) return initrd
def do_configure_gummiboot(cls, hdddir, creator, cr_workdir): """ Create loader-specific (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) options = creator.ks.handler.bootloader.appendLine timeout = kickstart.get_timeout(creator.ks) if not timeout: timeout = 0 loader_conf = "" loader_conf += "default boot\n" loader_conf += "timeout %d\n" % timeout msger.debug("Writing gummiboot 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 = kickstart.get_bootloader_file(creator.ks) custom_cfg = None if configfile: custom_cfg = get_custom_config(configfile) if custom_cfg: # Use a custom configuration for gummiboot boot_conf = custom_cfg msger.debug("Using custom configuration file " "%s for gummiboots's boot.conf" % configfile) else: msger.error("configfile is specified but failed to " "get it from %s." % configfile) if not custom_cfg: # Create gummiboot configuration using parameters from wks file kernel = "/bzImage" boot_conf = "" boot_conf += "title boot\n" boot_conf += "linux %s\n" % kernel boot_conf += "options LABEL=Boot root=%s %s\n" % (creator.rootdev, options) msger.debug("Writing gummiboot 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()
def __get_rootfs_dir(rootfs_dir): if os.path.isdir(rootfs_dir): return rootfs_dir image_rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", rootfs_dir) if not os.path.isdir(image_rootfs_dir): msg = "No valid artifact IMAGE_ROOTFS from image named" msg += " %s has been found at %s, exiting.\n" % \ (rootfs_dir, image_rootfs_dir) msger.error(msg) return image_rootfs_dir
def exec_cmd(cmd_and_args, as_shell=False, catch=3): """ Execute command, catching stderr, stdout Exits if rc non-zero """ rc, out = __exec_cmd(cmd_and_args, as_shell, catch) if rc != 0: msger.error("exec_cmd: %s returned '%s' instead of 0" % (cmd_and_args, rc)) return out
def exec_cmd(cmd_and_args, as_shell = False, catch = 3): """ Execute command, catching stderr, stdout Exits if rc non-zero """ rc, out = __exec_cmd(cmd_and_args, as_shell, catch) if rc != 0: msger.error("exec_cmd: %s returned '%s' instead of 0" % (cmd_and_args, rc)) return out
def exec_native_cmd(cmd_and_args, native_sysroot, catch=3, pseudo=""): """ Execute native command, catching stderr, stdout Need to execute as_shell if the command uses wildcards Always need to execute native commands as_shell """ # The reason -1 is used is because there may be "export" commands. args = cmd_and_args.split(';')[-1].split() msger.debug(args) if pseudo: cmd_and_args = pseudo + cmd_and_args native_paths = \ "%s/sbin:%s/usr/sbin:%s/usr/bin" % \ (native_sysroot, native_sysroot, native_sysroot) native_cmd_and_args = "export PATH=%s:$PATH;%s" % \ (native_paths, cmd_and_args) msger.debug("exec_native_cmd: %s" % cmd_and_args) # If the command isn't in the native sysroot say we failed. if spawn.find_executable(args[0], native_paths): ret, out = _exec_cmd(native_cmd_and_args, True, catch) else: ret = 127 prog = args[0] # shell command-not-found if ret == 127 \ or (pseudo and ret == 1 and out == "Can't find '%s' in $PATH." % prog): msg = "A native program %s required to build the image "\ "was not found (see details above).\n\n" % prog recipe = NATIVE_RECIPES.get(prog) if recipe: msg += "Please bake it with 'bitbake %s-native' "\ "and try again.\n" % recipe else: msg += "Wic failed to find a recipe to build native %s. Please "\ "file a bug against wic.\n" % prog msger.error(msg) if out: msger.debug('"%s" output: %s' % (args[0], out)) if ret != 0: msger.error("exec_cmd: '%s' returned '%s' instead of 0" % \ (cmd_and_args, ret)) return ret, out
def exec_native_cmd(cmd_and_args, native_sysroot, catch=3, pseudo=""): """ Execute native command, catching stderr, stdout Need to execute as_shell if the command uses wildcards Always need to execute native commands as_shell """ # The reason -1 is used is because there may be "export" commands. args = cmd_and_args.split(';')[-1].split() msger.debug(args) if pseudo: cmd_and_args = pseudo + cmd_and_args native_paths = \ "%s/sbin:%s/usr/sbin:%s/usr/bin" % \ (native_sysroot, native_sysroot, native_sysroot) native_cmd_and_args = "export PATH=%s:$PATH;%s" % \ (native_paths, cmd_and_args) msger.debug("exec_native_cmd: %s" % cmd_and_args) # If the command isn't in the native sysroot say we failed. if cmd_in_path(args[0], native_paths): ret, out = _exec_cmd(native_cmd_and_args, True, catch) else: ret = 127 prog = args[0] # shell command-not-found if ret == 127 \ or (pseudo and ret == 1 and out == "Can't find '%s' in $PATH." % prog): msg = "A native program %s required to build the image "\ "was not found (see details above).\n\n" % prog recipe = NATIVE_RECIPES.get(prog) if recipe: msg += "Please bake it with 'bitbake %s-native' "\ "and try again.\n" % recipe else: msg += "Wic failed to find a recipe to build native %s. Please "\ "file a bug against wic.\n" % prog msger.error(msg) if out: msger.debug('"%s" output: %s' % (args[0], out)) if ret != 0: msger.error("exec_cmd: '%s' returned '%s' instead of 0" % \ (cmd_and_args, ret)) return ret, out
def _parse_kickstart(self, ksconf=None): if not ksconf: return try: ksobj = KickStart(ksconf) except KickStartError as err: msger.error(str(err)) self.create['ks'] = ksobj self.create['name'] = os.path.splitext(os.path.basename(ksconf))[0] self.create['name'] = misc.build_name(ksconf, self.create['release'], self.create['name_prefix'], self.create['name_suffix'])
def main(self, argv=None): if argv is None: argv = sys.argv else: argv = argv[:] # don't modify caller's list pname = argv[0] if pname not in self._subcmds: msger.error('Unknown plugin: %s' % pname) optparser = self.get_optparser() options, args = optparser.parse_args(argv) self.postoptparse(options) return self._subcmds[pname](options, *args[1:])
def __get_rootfs_dir(rootfs_dir): if os.path.isdir(rootfs_dir): return rootfs_dir bitbake_env_lines = find_bitbake_env_lines(rootfs_dir) if not bitbake_env_lines: msg = "Couldn't get bitbake environment, exiting." msger.error(msg) image_rootfs_dir = find_artifact(bitbake_env_lines, "IMAGE_ROOTFS") if not os.path.isdir(image_rootfs_dir): msg = "No valid artifact IMAGE_ROOTFS from image named" msg += " %s has been found at %s, exiting.\n" % (rootfs_dir, image_rootfs_dir) msger.error(msg) return image_rootfs_dir
def do_stage_partition(cls, part, source_params, creator, cr_workdir, oe_builddir, bootimg_dir, kernel_dir, native_sysroot): """ Special content staging called before do_prepare_partition(). It cheks if all necessary tools are available, if not tries to instal them. """ # Make sure parted is available in native sysroot if not os.path.isfile("%s/usr/sbin/parted" % native_sysroot): msger.info("Building parted-native...\n") exec_cmd("bitbake parted-native") # Make sure mkfs.ext2/3/4 is available in native sysroot if not os.path.isfile("%s/sbin/mkfs.ext2" % native_sysroot): msger.info("Building e2fsprogs-native...\n") exec_cmd("bitbake e2fsprogs-native") # Make sure syslinux is available in sysroot and in native sysroot syslinux_dir = get_bitbake_var("STAGING_DATADIR") if not syslinux_dir: msger.error("Couldn't find STAGING_DATADIR, exiting.\n") if not os.path.exists("%s/syslinux" % syslinux_dir): msger.info("Building syslinux...\n") exec_cmd("bitbake syslinux") if not os.path.exists("%s/syslinux" % syslinux_dir): msger.error("Please build syslinux first\n") # Make sure syslinux is available in native sysroot if not os.path.exists("%s/usr/bin/syslinux" % native_sysroot): msger.info("Building syslinux-native...\n") exec_cmd("bitbake syslinux-native") #Make sure mkisofs is available in native sysroot if not os.path.isfile("%s/usr/bin/mkisofs" % native_sysroot): msger.info("Building cdrtools-native...\n") exec_cmd("bitbake cdrtools-native") # Make sure mkfs.vfat is available in native sysroot if not os.path.isfile("%s/sbin/mkfs.vfat" % native_sysroot): msger.info("Building dosfstools-native...\n") exec_cmd("bitbake dosfstools-native") # Make sure mtools is available in native sysroot if not os.path.isfile("%s/usr/bin/mcopy" % native_sysroot): msger.info("Building mtools-native...\n") exec_cmd("bitbake mtools-native")
def __run_parted(self, args): """ Run parted with arguments specified in the 'args' list. """ args.insert(0, self.parted) msger.debug(args) rc, out = runner.runtool(args, catch = 3) out = out.strip() if out: msger.debug('"parted" output: %s' % out) if rc != 0: # We don't throw exception when return code is not 0, because # parted always fails to reload part table with loop devices. This # prevents us from distinguishing real errors based on return # code. msger.error("WARNING: parted returned '%s' instead of 0 (use --debug for details)" % rc)
def __get_rootfs_dir(rootfs_dir): if os.path.isdir(rootfs_dir): return rootfs_dir bitbake_env_lines = find_bitbake_env_lines(rootfs_dir) if not bitbake_env_lines: msg = "Couldn't get bitbake environment, exiting." msger.error(msg) image_rootfs_dir = find_artifact(bitbake_env_lines, "IMAGE_ROOTFS") if not os.path.isdir(image_rootfs_dir): msg = "No valid artifact IMAGE_ROOTFS from image named" msg += " %s has been found at %s, exiting.\n" % \ (rootfs_dir, image_rootfs_dir) msger.error(msg) return image_rootfs_dir
def do_configure_grubefi(cls, part, creator, cr_workdir): """ Create loader-specific (grub-efi) config """ configfile = creator.ks.bootloader.configfile if configfile: grubefi_conf = get_custom_config(configfile) if grubefi_conf: msger.debug("Using custom configuration file " "%s for grub.cfg" % configfile) else: msger.error("configfile is specified but failed to " "get it from %s." % configfile) else: splash = os.path.join(cr_workdir, "EFI/boot/splash.jpg") if os.path.exists(splash): splashline = "menu background splash.jpg" else: splashline = "" bootloader = creator.ks.bootloader grubefi_conf = "" grubefi_conf += "serial --unit=0 --speed=115200 --word=8 " grubefi_conf += "--parity=no --stop=1\n" grubefi_conf += "default=boot\n" grubefi_conf += "timeout=%s\n" % (bootloader.timeout or 10) grubefi_conf += "\n" grubefi_conf += "search --set=root --label %s " % part.label grubefi_conf += "\n" grubefi_conf += "menuentry 'boot'{\n" kernel = "/bzImage" grubefi_conf += "linux %s rootwait %s\n" \ % (kernel, bootloader.append) grubefi_conf += "initrd /initrd \n" grubefi_conf += "}\n" if splashline: grubefi_conf += "%s\n" % splashline msger.debug("Writing grubefi config %s/EFI/BOOT/grub.cfg" \ % cr_workdir) with open("%s/EFI/BOOT/grub.cfg" % cr_workdir, "w") as cfg: cfg.write(grubefi_conf)
def _get_rootfs_dir(rootfs_dir): """ Find rootfs pseudo dir If rootfs_dir is a directory consider it as rootfs directory. Otherwise ask bitbake about the IMAGE_ROOTFS directory. """ if os.path.isdir(rootfs_dir): return rootfs_dir image_rootfs_dir = misc.get_bitbake_var("IMAGE_ROOTFS", rootfs_dir) if not os.path.isdir(image_rootfs_dir): msg = "No valid artifact IMAGE_ROOTFS from image named" msg += " %s has been found at %s, exiting.\n" % \ (rootfs_dir, image_rootfs_dir) msger.error(msg) return image_rootfs_dir
def do_prepare_partition(cls, part, source_params, cr, 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. """ bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") if not bootimg_dir: msger.error("Couldn't find DEPLOY_DIR_IMAGE, exiting\n") msger.debug('Bootimg dir: %s' % bootimg_dir) src = bootimg_dir + "/" + get_bitbake_var( "IMAGE_LINK_NAME") + ".otaimg" msger.debug('Preparing partition using image %s' % (src)) part.prepare_rootfs_from_fs_image(cr_workdir, src, "")
def __run_parted(self, args): """ Run parted with arguments specified in the 'args' list. """ args.insert(0, "parted") args = ' '.join(args) msger.debug(args) rc, out = exec_native_cmd(args, self.native_sysroot) if out: msger.debug('"parted" output: %s' % out) if rc != 0: # We don't throw exception when return code is not 0, because # parted always fails to reload part table with loop devices. This # prevents us from distinguishing real errors based on return # code. msger.error("WARNING: parted returned '%s' instead of 0 (use --debug for details)" % rc)
def main(self, argv=None): if argv is None: argv = sys.argv else: argv = argv[:] # don't modify caller's list self.optparser = self.get_optparser() if self.optparser: try: argv = self.preoptparse(argv) self.options, args = self.optparser.parse_args(argv) except cmdln.CmdlnUserError, ex: msg = "%s: %s\nTry '%s help' for info.\n"\ % (self.name, ex, self.name) msger.error(msg) except cmdln.StopOptionProcessing, ex: return 0
def __run_parted(self, args): """ Run parted with arguments specified in the 'args' list. """ args.insert(0, self.parted) msger.debug(args) rc, out = runner.runtool(args, catch=3) out = out.strip() if out: msger.debug('"parted" output: %s' % out) if rc != 0: # We don't throw exception when return code is not 0, because # parted always fails to reload part table with loop devices. This # prevents us from distinguishing real errors based on return # code. msger.error( "WARNING: parted returned '%s' instead of 0 (use --debug for details)" % rc)
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(hdddir, creator, cr_workdir) elif source_params['loader'] == 'systemd-boot': cls.do_configure_systemdboot(hdddir, creator, cr_workdir) else: msger.error("unrecognized bootimg-efi loader: %s" % source_params['loader']) except KeyError: msger.error("bootimg-efi requires a loader, none specified")
def do_configure_grubefi(cls, hdddir, creator, cr_workdir): """ Create loader-specific (grub-efi) config """ configfile = kickstart.get_bootloader_file(creator.ks) custom_cfg = None if configfile: custom_cfg = get_custom_config(configfile) if custom_cfg: # Use a custom configuration for grub grubefi_conf = custom_cfg msger.debug("Using custom configuration file " "%s for grub.cfg" % configfile) else: msger.error("configfile is specified but failed to " "get it from %s." % configfile) if not custom_cfg: # Create grub configuration using parameters from wks file options = creator.ks.handler.bootloader.appendLine grubefi_conf = "" grubefi_conf += "serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1\n" grubefi_conf += "default=boot\n" timeout = kickstart.get_timeout(creator.ks) if not timeout: timeout = 0 grubefi_conf += "timeout=%s\n" % timeout grubefi_conf += "menuentry 'boot'{\n" kernel = "/bzImage" grubefi_conf += "linux %s root=%s rootwait %s\n" \ % (kernel, creator.rootdev, options) grubefi_conf += "}\n" msger.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()
def do_install_disk(self, disk, disk_name, cr, workdir, oe_builddir, bootimg_dir, kernel_dir, native_sysroot): """ Called after all partitions have been prepared and assembled into a disk image. In this case, we install the MBR. """ mbrfile = "%s/syslinux/" % bootimg_dir if cr._ptable_format == "msdos": mbrfile += "mbr.bin" if not os.path.exists(mbrfile): msger.error( "Couldn't find %s. If using the -e option, do you have the right MACHINE set in local.conf? If not, is the bootimg_dir path correct?" % mbrfile ) full_path = cr._full_path(workdir, disk_name, "direct") msger.debug("Installing MBR on disk %s as %s with size %s bytes" % (disk_name, full_path, disk["min_size"])) rc = runner.show(["dd", "if=%s" % mbrfile, "of=%s" % full_path, "conv=notrunc"]) if rc != 0: raise ImageError("Unable to set MBR to %s" % full_path)
def _get_rootfs_dir(rootfs_dir): """ Find rootfs pseudo dir If rootfs_dir is a directory consider it as rootfs directory. Otherwise ask bitbake about the IMAGE_ROOTFS directory. """ if os.path.isdir(rootfs_dir): return rootfs_dir bitbake_env_lines = misc.find_bitbake_env_lines(rootfs_dir) if not bitbake_env_lines: msger.error("Couldn't get bitbake environment, exiting.") image_rootfs_dir = misc.find_artifact(bitbake_env_lines, "IMAGE_ROOTFS") if not os.path.isdir(image_rootfs_dir): msg = "No valid artifact IMAGE_ROOTFS from image named" msg += " %s has been found at %s, exiting.\n" % \ (rootfs_dir, image_rootfs_dir) msger.error(msg) return image_rootfs_dir
def do_prepare_partition( cls, part, source_params, cr, 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. """ if not bootimg_dir: bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") if not bootimg_dir: msger.error("Couldn't find DEPLOY_DIR_IMAGE, exiting\n") msger.debug("Bootimg dir: %s" % bootimg_dir) if "file" not in source_params: msger.error("No file specified\n") return src = os.path.join(bootimg_dir, source_params["file"]) msger.debug("Preparing partition using image %s" % (src)) part.prepare_rootfs_from_fs_image(cr_workdir, src, "")
def do_configure_partition( self, part, source_params, cr, 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 rm_cmd = "rm -rf %s" % cr_workdir exec_cmd(rm_cmd) install_cmd = "install -d %s/EFI/BOOT" % hdddir exec_cmd(install_cmd) try: if source_params["loader"] == "grub-efi": self.do_configure_grubefi(hdddir, cr, cr_workdir) elif source_params["loader"] == "gummiboot": self.do_configure_gummiboot(hdddir, cr, cr_workdir) else: msger.error("unrecognized bootimg-efi loader: %s" % source_params["loader"]) except KeyError: msger.error("bootimg-efi requires a loader, none specified")