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 kernel_dir: kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") if not kernel_dir: raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") logger.debug('Kernel dir: %s', kernel_dir) if 'file' not in source_params: raise WicError("No file specified") src = os.path.join(kernel_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=int(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 = int(out.split()[0]) if filesize > part.size: part.size = filesize part.source_file = dst
def do_prepare_partition(cls, part, source_params, cr, cr_workdir, oe_builddir, bootimg_dir, kernel_dir, rootfs_dir): """ Called to do the actual content population for a partition i.e. it 'prepares' the partition to be incorporated into the image. """ 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") logger.debug('Kernel dir: %s', kernel_dir) if 'file' not in source_params: raise WicError("No file specified") src = os.path.join(kernel_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=int(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 = int(out.split()[0]) if filesize > part.size: part.size = filesize part.source_file = dst
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 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, source_params['file']) 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 _get_part_image(self, pnum): if pnum not in self.partitions: raise WicError("Partition %s is not in the image") part = self.partitions[pnum] if not part.fstype.startswith("fat"): raise WicError("Not supported fstype: {}".format(part.fstype)) if pnum not in self._partimages: tmpf = tempfile.NamedTemporaryFile(prefix="wic-part") dst_fname = tmpf.name tmpf.close() sparse_copy(self.imagepath, dst_fname, skip=part.start, length=part.size) self._partimages[pnum] = dst_fname return self._partimages[pnum]
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 kernel_dir: kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") if not kernel_dir: raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") logger.debug('Kernel dir: %s', kernel_dir) if 'file' not in source_params: raise WicError("No file specified") if 'unpack' in source_params: img = os.path.join(kernel_dir, source_params['file']) src = os.path.join(cr_workdir, os.path.splitext(source_params['file'])[0]) RawCopyPlugin.do_image_uncompression(img, src, cr_workdir) else: src = os.path.join(kernel_dir, source_params['file']) dst = os.path.join( cr_workdir, "%s.%s" % (os.path.basename(source_params['file']), part.lineno)) if not os.path.exists(os.path.dirname(dst)): os.makedirs(os.path.dirname(dst)) if 'skip' in source_params: sparse_copy(src, dst, skip=int(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 = int(out.split()[0]) if filesize > part.size: part.size = filesize if part.label: RawCopyPlugin.do_image_label(part.fstype, dst, part.label) part.source_file = dst
def assemble(self, image_file): msger.debug("Installing partitions") for part in self.partitions: source = part['source_file'] if source: # install source_file contents into a partition sparse_copy(source, image_file, part['start'] * self.sector_size) msger.debug("Installed %s in partition %d, sectors %d-%d, " "size %d sectors" % \ (source, part['num'], part['start'], part['start'] + part['size'] - 1, part['size'])) os.rename(source, image_file + '.p%d' % part['num'])
def assemble(self): logger.debug("Installing partitions") for part in self.partitions: source = part.source_file if source: # install source_file contents into a partition sparse_copy(source, self.path, seek=part.start * self.sector_size) logger.debug("Installed %s in partition %d, sectors %d-%d, " "size %d sectors", source, part.num, part.start, part.start + part.size_sec - 1, part.size_sec) partimage = self.path + '.p%d' % part.num os.rename(source, partimage) self.partimages.append(partimage)
def write(self, target, expand): """Write disk image to the media or file.""" def write_sfdisk_script(outf, parts): for key, val in parts['partitiontable'].items(): if key in ("partitions", "device", "firstlba", "lastlba"): continue if key == "id": key = "label-id" outf.write("{}: {}\n".format(key, val)) outf.write("\n") for part in parts['partitiontable']['partitions']: line = '' for name in ('attrs', 'name', 'size', 'type', 'uuid'): if name == 'size' and part['type'] == 'f': # don't write size for extended partition continue val = part.get(name) if val: line += '{}={}, '.format(name, val) if line: line = line[:-2] # strip ', ' if part.get('bootable'): line += ' ,bootable' outf.write("{}\n".format(line)) outf.flush() def read_ptable(path): out = exec_cmd("{} -dJ {}".format(self.sfdisk, path)) return json.loads(out) def write_ptable(parts, target): with tempfile.NamedTemporaryFile(prefix="wic-sfdisk-", mode='w') as outf: write_sfdisk_script(outf, parts) cmd = "{} --no-reread {} < {} ".format(self.sfdisk, target, outf.name) exec_cmd(cmd, as_shell=True) if expand is None: sparse_copy(self.imagepath, target) else: # copy first sectors that may contain bootloader sparse_copy(self.imagepath, target, length=2048 * self._lsector_size) # copy source partition table to the target parts = read_ptable(self.imagepath) write_ptable(parts, target) # get size of unpartitioned space free = None for line in exec_cmd("{} -F {}".format(self.sfdisk, target)).splitlines(): if line.startswith("Unpartitioned space ") and line.endswith("sectors"): free = int(line.split()[-2]) # Align free space to a 2048 sector boundary. YOCTO #12840. free = free - (free % 2048) if free is None: raise WicError("Can't get size of unpartitioned space") # calculate expanded partitions sizes sizes = {} num_auto_resize = 0 for num, part in enumerate(parts['partitiontable']['partitions'], 1): if num in expand: if expand[num] != 0: # don't resize partition if size is set to 0 sectors = expand[num] // self._lsector_size free -= sectors - part['size'] part['size'] = sectors sizes[num] = sectors elif part['type'] != 'f': sizes[num] = -1 num_auto_resize += 1 for num, part in enumerate(parts['partitiontable']['partitions'], 1): if sizes.get(num) == -1: part['size'] += free // num_auto_resize # write resized partition table to the target write_ptable(parts, target) # read resized partition table parts = read_ptable(target) # copy partitions content for num, part in enumerate(parts['partitiontable']['partitions'], 1): pnum = str(num) fstype = self.partitions[pnum].fstype # copy unchanged partition if part['size'] == self.partitions[pnum].size // self._lsector_size: logger.info("copying unchanged partition {}".format(pnum)) sparse_copy(self._get_part_image(pnum), target, seek=part['start'] * self._lsector_size) continue # resize or re-create partitions if fstype.startswith('ext') or fstype.startswith('fat') or \ fstype.startswith('linux-swap'): partfname = None with tempfile.NamedTemporaryFile(prefix="wic-part{}-".format(pnum)) as partf: partfname = partf.name if fstype.startswith('ext'): logger.info("resizing ext partition {}".format(pnum)) partimg = self._get_part_image(pnum) sparse_copy(partimg, partfname) exec_cmd("{} -pf {}".format(self.e2fsck, partfname)) exec_cmd("{} {} {}s".format(\ self.resize2fs, partfname, part['size'])) elif fstype.startswith('fat'): logger.info("copying content of the fat partition {}".format(pnum)) with tempfile.TemporaryDirectory(prefix='wic-fatdir-') as tmpdir: # copy content to the temporary directory cmd = "{} -snompi {} :: {}".format(self.mcopy, self._get_part_image(pnum), tmpdir) exec_cmd(cmd) # create new msdos partition label = part.get("name") label_str = "-n {}".format(label) if label else '' cmd = "{} {} -C {} {}".format(self.mkdosfs, label_str, partfname, part['size']) exec_cmd(cmd) # copy content from the temporary directory to the new partition cmd = "{} -snompi {} {}/* ::".format(self.mcopy, partfname, tmpdir) exec_cmd(cmd, as_shell=True) elif fstype.startswith('linux-swap'): logger.info("creating swap partition {}".format(pnum)) label = part.get("name") label_str = "-L {}".format(label) if label else '' uuid = part.get("uuid") uuid_str = "-U {}".format(uuid) if uuid else '' with open(partfname, 'w') as sparse: os.ftruncate(sparse.fileno(), part['size'] * self._lsector_size) exec_cmd("{} {} {} {}".format(self.mkswap, label_str, uuid_str, partfname)) sparse_copy(partfname, target, seek=part['start'] * self._lsector_size) os.unlink(partfname) elif part['type'] != 'f': logger.warning("skipping partition {}: unsupported fstype {}".format(pnum, fstype))
def _put_part_image(self, pnum): """Put partition image into partitioned image.""" sparse_copy(self._partimages[pnum], self.imagepath, seek=self.partitions[pnum].start)
def do_prepare_partition(cls, 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 data partition that mounts to a specific directory in rootfs. """ # Passed in Parameters (from Partition(object).prepare() entry point) # part => Partition(object).instance # source_params => srcparams_dict # cr => creator # cr_workdir => cr_workdir # oe_builddir => oe_builddir # bootimg_dir => bootimg_dir # kernel_dir => kernel_dir # krootfs_dir => krootfs_dir # native_sysroot => native_sysroot # # original wic do_create command entry point: DirectPlugin(ImagerPlugin).do_create()-> # try: # self.create() # self.assemble() # self.finalize() # self.print_info() # finally: # self.cleanup() # # direct.py's PartitionedImage(object).create()-> # self._image.prepare(...) i.e. loop all partitions in wks file and prepare the partition # self._image.layout_partitions(...) i.e. calculate positions of all partitions # self._image.create() -> exec_native_cmd() i.e. call parted cmd to generate partition # # partition.py's class Partition(object).prepare()-> # plugin.do_configure_partition(...) # plugin.do_stage_partition(...) # plugin.do_prepare_partition(...) # plugin.do_post_partition(...) # # must find the datafs partition image specified by --sourceparams from deployed directory 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") if 'file' not in source_params: raise WicError("No file specified") # Note: We only care about TN_PARTITION_IMAGE (from image_type_tn.bbclass) # or TN_DOCKER_PARTITION_IMAGE (from docker-disk.inc/pico-imx8mm.conf) # or anyother PARTITION_IMAGE that we want to write to the additional data partition # which is used in wic/tn-imx8-imxboot-rootfs-container.wks.in # and this src image was created with mkfs command: # mkfs.ext4 -E lazy_itable_init=0,lazy_journal_init=0 -i 8192 -d ${DATA_VOLUME}/docker -F ${BUILD}/${PARTITION_IMAGE} src = os.path.join(kernel_dir, source_params['file']) # prepare the dst partition image first dst = os.path.join( cr_workdir, "fs_{}.{}.{}".format(part.label, part.lineno, part.fstype)) logger.info("datafs src: {}\ndatafs dst: {}\n".format(src, dst)) if os.path.isfile(dst): os.remove(dst) # copy src to dst in binary if 'skip' in source_params: sparse_copy(src, dst, skip=int(source_params['skip'])) else: sparse_copy(src, dst) # check the ext4 file system on the dst file mkfs_cmd = "fsck.{} -pvfD {}".format(part.fstype, dst) exec_native_cmd(mkfs_cmd, native_sysroot) # get the size in the right units for kickstart (kB) du_cmd = "du -Lbks {}".format(dst) out = exec_cmd(du_cmd) filesize = int(out.split()[0]) if filesize > part.size: part.size = filesize # update the partition label if part.label: DatafsPlugin.do_image_label(part.fstype, dst, part.label) part.source_file = dst