1eb8dc403SDave Cobbley# 2eb8dc403SDave Cobbley# Copyright (c) 2013-2016 Intel Corporation. 3eb8dc403SDave Cobbley# 4c342db35SBrad Bishop# SPDX-License-Identifier: GPL-2.0-only 5eb8dc403SDave Cobbley# 6eb8dc403SDave Cobbley# DESCRIPTION 7eb8dc403SDave Cobbley# This module provides the OpenEmbedded partition object definitions. 8eb8dc403SDave Cobbley# 9eb8dc403SDave Cobbley# AUTHORS 10eb8dc403SDave Cobbley# Tom Zanussi <tom.zanussi (at] linux.intel.com> 11eb8dc403SDave Cobbley# Ed Bartosh <ed.bartosh> (at] linux.intel.com> 12eb8dc403SDave Cobbley 13eb8dc403SDave Cobbleyimport logging 14eb8dc403SDave Cobbleyimport os 15eb8dc403SDave Cobbleyimport uuid 16eb8dc403SDave Cobbley 17eb8dc403SDave Cobbleyfrom wic import WicError 18eb8dc403SDave Cobbleyfrom wic.misc import exec_cmd, exec_native_cmd, get_bitbake_var 19eb8dc403SDave Cobbleyfrom wic.pluginbase import PluginMgr 20eb8dc403SDave Cobbley 21eb8dc403SDave Cobbleylogger = logging.getLogger('wic') 22eb8dc403SDave Cobbley 23eb8dc403SDave Cobbleyclass Partition(): 24eb8dc403SDave Cobbley 25eb8dc403SDave Cobbley def __init__(self, args, lineno): 26eb8dc403SDave Cobbley self.args = args 27eb8dc403SDave Cobbley self.active = args.active 28eb8dc403SDave Cobbley self.align = args.align 29eb8dc403SDave Cobbley self.disk = args.disk 30eb8dc403SDave Cobbley self.device = None 31eb8dc403SDave Cobbley self.extra_space = args.extra_space 32eb8dc403SDave Cobbley self.exclude_path = args.exclude_path 3382c905dcSAndrew Geissler self.include_path = args.include_path 3482c905dcSAndrew Geissler self.change_directory = args.change_directory 35eb8dc403SDave Cobbley self.fsopts = args.fsopts 36d583833aSAndrew Geissler self.fspassno = args.fspassno 37eb8dc403SDave Cobbley self.fstype = args.fstype 38eb8dc403SDave Cobbley self.label = args.label 391a4b7ee2SBrad Bishop self.use_label = args.use_label 40eb8dc403SDave Cobbley self.mkfs_extraopts = args.mkfs_extraopts 41eb8dc403SDave Cobbley self.mountpoint = args.mountpoint 42eb8dc403SDave Cobbley self.no_table = args.no_table 43eb8dc403SDave Cobbley self.num = None 444ed12e16SAndrew Geissler self.offset = args.offset 45eb8dc403SDave Cobbley self.overhead_factor = args.overhead_factor 46eb8dc403SDave Cobbley self.part_name = args.part_name 47eb8dc403SDave Cobbley self.part_type = args.part_type 48eb8dc403SDave Cobbley self.rootfs_dir = args.rootfs_dir 49eb8dc403SDave Cobbley self.size = args.size 50eb8dc403SDave Cobbley self.fixed_size = args.fixed_size 51eb8dc403SDave Cobbley self.source = args.source 52eb8dc403SDave Cobbley self.sourceparams = args.sourceparams 53eb8dc403SDave Cobbley self.system_id = args.system_id 54eb8dc403SDave Cobbley self.use_uuid = args.use_uuid 55eb8dc403SDave Cobbley self.uuid = args.uuid 56eb8dc403SDave Cobbley self.fsuuid = args.fsuuid 5708902b01SBrad Bishop self.type = args.type 58d159c7fbSAndrew Geissler self.no_fstab_update = args.no_fstab_update 59d1e89497SAndrew Geissler self.updated_fstab_path = None 60d1e89497SAndrew Geissler self.has_fstab = False 61d1e89497SAndrew Geissler self.update_fstab_in_rootfs = False 62e760df85SPatrick Williams self.hidden = args.hidden 635082cc7fSAndrew Geissler self.mbr = args.mbr 64eb8dc403SDave Cobbley 65eb8dc403SDave Cobbley self.lineno = lineno 66eb8dc403SDave Cobbley self.source_file = "" 67eb8dc403SDave Cobbley 68eb8dc403SDave Cobbley def get_extra_block_count(self, current_blocks): 69eb8dc403SDave Cobbley """ 70eb8dc403SDave Cobbley The --size param is reflected in self.size (in kB), and we already 71eb8dc403SDave Cobbley have current_blocks (1k) blocks, calculate and return the 72eb8dc403SDave Cobbley number of (1k) blocks we need to add to get to --size, 0 if 73eb8dc403SDave Cobbley we're already there or beyond. 74eb8dc403SDave Cobbley """ 75eb8dc403SDave Cobbley logger.debug("Requested partition size for %s: %d", 76eb8dc403SDave Cobbley self.mountpoint, self.size) 77eb8dc403SDave Cobbley 78eb8dc403SDave Cobbley if not self.size: 79eb8dc403SDave Cobbley return 0 80eb8dc403SDave Cobbley 81eb8dc403SDave Cobbley requested_blocks = self.size 82eb8dc403SDave Cobbley 83eb8dc403SDave Cobbley logger.debug("Requested blocks %d, current_blocks %d", 84eb8dc403SDave Cobbley requested_blocks, current_blocks) 85eb8dc403SDave Cobbley 86eb8dc403SDave Cobbley if requested_blocks > current_blocks: 87eb8dc403SDave Cobbley return requested_blocks - current_blocks 88eb8dc403SDave Cobbley else: 89eb8dc403SDave Cobbley return 0 90eb8dc403SDave Cobbley 91eb8dc403SDave Cobbley def get_rootfs_size(self, actual_rootfs_size=0): 92eb8dc403SDave Cobbley """ 93eb8dc403SDave Cobbley Calculate the required size of rootfs taking into consideration 94eb8dc403SDave Cobbley --size/--fixed-size flags as well as overhead and extra space, as 95eb8dc403SDave Cobbley specified in kickstart file. Raises an error if the 96eb8dc403SDave Cobbley `actual_rootfs_size` is larger than fixed-size rootfs. 97eb8dc403SDave Cobbley 98eb8dc403SDave Cobbley """ 99eb8dc403SDave Cobbley if self.fixed_size: 100eb8dc403SDave Cobbley rootfs_size = self.fixed_size 101eb8dc403SDave Cobbley if actual_rootfs_size > rootfs_size: 102eb8dc403SDave Cobbley raise WicError("Actual rootfs size (%d kB) is larger than " 103eb8dc403SDave Cobbley "allowed size %d kB" % 104eb8dc403SDave Cobbley (actual_rootfs_size, rootfs_size)) 105eb8dc403SDave Cobbley else: 106eb8dc403SDave Cobbley extra_blocks = self.get_extra_block_count(actual_rootfs_size) 107eb8dc403SDave Cobbley if extra_blocks < self.extra_space: 108eb8dc403SDave Cobbley extra_blocks = self.extra_space 109eb8dc403SDave Cobbley 110eb8dc403SDave Cobbley rootfs_size = actual_rootfs_size + extra_blocks 1115199d831SAndrew Geissler rootfs_size = int(rootfs_size * self.overhead_factor) 112eb8dc403SDave Cobbley 113eb8dc403SDave Cobbley logger.debug("Added %d extra blocks to %s to get to %d total blocks", 114eb8dc403SDave Cobbley extra_blocks, self.mountpoint, rootfs_size) 115eb8dc403SDave Cobbley 116eb8dc403SDave Cobbley return rootfs_size 117eb8dc403SDave Cobbley 118eb8dc403SDave Cobbley @property 119eb8dc403SDave Cobbley def disk_size(self): 120eb8dc403SDave Cobbley """ 121eb8dc403SDave Cobbley Obtain on-disk size of partition taking into consideration 122eb8dc403SDave Cobbley --size/--fixed-size options. 123eb8dc403SDave Cobbley 124eb8dc403SDave Cobbley """ 125eb8dc403SDave Cobbley return self.fixed_size if self.fixed_size else self.size 126eb8dc403SDave Cobbley 127eb8dc403SDave Cobbley def prepare(self, creator, cr_workdir, oe_builddir, rootfs_dir, 128d1e89497SAndrew Geissler bootimg_dir, kernel_dir, native_sysroot, updated_fstab_path): 129eb8dc403SDave Cobbley """ 130eb8dc403SDave Cobbley Prepare content for individual partitions, depending on 131eb8dc403SDave Cobbley partition command parameters. 132eb8dc403SDave Cobbley """ 133d1e89497SAndrew Geissler self.updated_fstab_path = updated_fstab_path 134d1e89497SAndrew Geissler if self.updated_fstab_path and not (self.fstype.startswith("ext") or self.fstype == "msdos"): 135d1e89497SAndrew Geissler self.update_fstab_in_rootfs = True 136d1e89497SAndrew Geissler 137eb8dc403SDave Cobbley if not self.source: 1385082cc7fSAndrew Geissler if self.fstype == "none" or self.no_table: 1396aa7eec5SAndrew Geissler return 140eb8dc403SDave Cobbley if not self.size and not self.fixed_size: 141eb8dc403SDave Cobbley raise WicError("The %s partition has a size of zero. Please " 142eb8dc403SDave Cobbley "specify a non-zero --size/--fixed-size for that " 143eb8dc403SDave Cobbley "partition." % self.mountpoint) 144eb8dc403SDave Cobbley 145eb8dc403SDave Cobbley if self.fstype == "swap": 146eb8dc403SDave Cobbley self.prepare_swap_partition(cr_workdir, oe_builddir, 147eb8dc403SDave Cobbley native_sysroot) 148eb8dc403SDave Cobbley self.source_file = "%s/fs.%s" % (cr_workdir, self.fstype) 149eb8dc403SDave Cobbley else: 150ac69b488SWilliam A. Kennington III if self.fstype in ('squashfs', 'erofs'): 151ac69b488SWilliam A. Kennington III raise WicError("It's not possible to create empty %s " 152ac69b488SWilliam A. Kennington III "partition '%s'" % (self.fstype, self.mountpoint)) 153eb8dc403SDave Cobbley 154eb8dc403SDave Cobbley rootfs = "%s/fs_%s.%s.%s" % (cr_workdir, self.label, 155eb8dc403SDave Cobbley self.lineno, self.fstype) 156eb8dc403SDave Cobbley if os.path.isfile(rootfs): 157eb8dc403SDave Cobbley os.remove(rootfs) 158eb8dc403SDave Cobbley 159eb8dc403SDave Cobbley prefix = "ext" if self.fstype.startswith("ext") else self.fstype 160eb8dc403SDave Cobbley method = getattr(self, "prepare_empty_partition_" + prefix) 161eb8dc403SDave Cobbley method(rootfs, oe_builddir, native_sysroot) 162eb8dc403SDave Cobbley self.source_file = rootfs 163eb8dc403SDave Cobbley return 164eb8dc403SDave Cobbley 165eb8dc403SDave Cobbley plugins = PluginMgr.get_plugins('source') 166eb8dc403SDave Cobbley 167eb8dc403SDave Cobbley if self.source not in plugins: 168eb8dc403SDave Cobbley raise WicError("The '%s' --source specified for %s doesn't exist.\n\t" 169eb8dc403SDave Cobbley "See 'wic list source-plugins' for a list of available" 170eb8dc403SDave Cobbley " --sources.\n\tSee 'wic help source-plugins' for " 171eb8dc403SDave Cobbley "details on adding a new source plugin." % 172eb8dc403SDave Cobbley (self.source, self.mountpoint)) 173eb8dc403SDave Cobbley 174eb8dc403SDave Cobbley srcparams_dict = {} 175eb8dc403SDave Cobbley if self.sourceparams: 176eb8dc403SDave Cobbley # Split sourceparams string of the form key1=val1[,key2=val2,...] 177eb8dc403SDave Cobbley # into a dict. Also accepts valueless keys i.e. without = 178eb8dc403SDave Cobbley splitted = self.sourceparams.split(',') 1797e0e3c0cSAndrew Geissler srcparams_dict = dict((par.split('=', 1) + [None])[:2] for par in splitted if par) 180eb8dc403SDave Cobbley 181eb8dc403SDave Cobbley plugin = PluginMgr.get_plugins('source')[self.source] 182eb8dc403SDave Cobbley plugin.do_configure_partition(self, srcparams_dict, creator, 183eb8dc403SDave Cobbley cr_workdir, oe_builddir, bootimg_dir, 184eb8dc403SDave Cobbley kernel_dir, native_sysroot) 185eb8dc403SDave Cobbley plugin.do_stage_partition(self, srcparams_dict, creator, 186eb8dc403SDave Cobbley cr_workdir, oe_builddir, bootimg_dir, 187eb8dc403SDave Cobbley kernel_dir, native_sysroot) 188eb8dc403SDave Cobbley plugin.do_prepare_partition(self, srcparams_dict, creator, 189eb8dc403SDave Cobbley cr_workdir, oe_builddir, bootimg_dir, 190eb8dc403SDave Cobbley kernel_dir, rootfs_dir, native_sysroot) 191eb8dc403SDave Cobbley plugin.do_post_partition(self, srcparams_dict, creator, 192eb8dc403SDave Cobbley cr_workdir, oe_builddir, bootimg_dir, 193eb8dc403SDave Cobbley kernel_dir, rootfs_dir, native_sysroot) 194eb8dc403SDave Cobbley 195eb8dc403SDave Cobbley # further processing required Partition.size to be an integer, make 196eb8dc403SDave Cobbley # sure that it is one 197eb8dc403SDave Cobbley if not isinstance(self.size, int): 198eb8dc403SDave Cobbley raise WicError("Partition %s internal size is not an integer. " 199eb8dc403SDave Cobbley "This a bug in source plugin %s and needs to be fixed." % 200eb8dc403SDave Cobbley (self.mountpoint, self.source)) 201eb8dc403SDave Cobbley 202eb8dc403SDave Cobbley if self.fixed_size and self.size > self.fixed_size: 203eb8dc403SDave Cobbley raise WicError("File system image of partition %s is " 204eb8dc403SDave Cobbley "larger (%d kB) than its allowed size %d kB" % 205eb8dc403SDave Cobbley (self.mountpoint, self.size, self.fixed_size)) 206eb8dc403SDave Cobbley 207eb8dc403SDave Cobbley def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir, 20882c905dcSAndrew Geissler native_sysroot, real_rootfs = True, pseudo_dir = None): 209eb8dc403SDave Cobbley """ 210eb8dc403SDave Cobbley Prepare content for a rootfs partition i.e. create a partition 211eb8dc403SDave Cobbley and fill it from a /rootfs dir. 212eb8dc403SDave Cobbley 213eb8dc403SDave Cobbley Currently handles ext2/3/4, btrfs, vfat and squashfs. 214eb8dc403SDave Cobbley """ 215f0343792SAndrew Geissler 216f0343792SAndrew Geissler rootfs = "%s/rootfs_%s.%s.%s" % (cr_workdir, self.label, 217f0343792SAndrew Geissler self.lineno, self.fstype) 218f0343792SAndrew Geissler if os.path.isfile(rootfs): 219f0343792SAndrew Geissler os.remove(rootfs) 220f0343792SAndrew Geissler 221eb8dc403SDave Cobbley p_prefix = os.environ.get("PSEUDO_PREFIX", "%s/usr" % native_sysroot) 22282c905dcSAndrew Geissler if (pseudo_dir): 223d1e89497SAndrew Geissler # Canonicalize the ignore paths. This corresponds to 224d1e89497SAndrew Geissler # calling oe.path.canonicalize(), which is used in bitbake.conf. 225d1e89497SAndrew Geissler ignore_paths = [rootfs] + (get_bitbake_var("PSEUDO_IGNORE_PATHS") or "").split(",") 226d1e89497SAndrew Geissler canonical_paths = [] 227d1e89497SAndrew Geissler for path in ignore_paths: 228d1e89497SAndrew Geissler if "$" not in path: 229d1e89497SAndrew Geissler trailing_slash = path.endswith("/") and "/" or "" 230d1e89497SAndrew Geissler canonical_paths.append(os.path.realpath(path) + trailing_slash) 231d1e89497SAndrew Geissler ignore_paths = ",".join(canonical_paths) 232d1e89497SAndrew Geissler 233eb8dc403SDave Cobbley pseudo = "export PSEUDO_PREFIX=%s;" % p_prefix 23482c905dcSAndrew Geissler pseudo += "export PSEUDO_LOCALSTATEDIR=%s;" % pseudo_dir 23582c905dcSAndrew Geissler pseudo += "export PSEUDO_PASSWD=%s;" % rootfs_dir 23682c905dcSAndrew Geissler pseudo += "export PSEUDO_NOSYMLINKEXP=1;" 237d1e89497SAndrew Geissler pseudo += "export PSEUDO_IGNORE_PATHS=%s;" % ignore_paths 238eb8dc403SDave Cobbley pseudo += "%s " % get_bitbake_var("FAKEROOTCMD") 23982c905dcSAndrew Geissler else: 24082c905dcSAndrew Geissler pseudo = None 241eb8dc403SDave Cobbley 242eb8dc403SDave Cobbley if not self.size and real_rootfs: 24300e122a7SBrad Bishop # The rootfs size is not set in .ks file so try to get it 24400e122a7SBrad Bishop # from bitbake variable 24500e122a7SBrad Bishop rsize_bb = get_bitbake_var('ROOTFS_SIZE') 24600e122a7SBrad Bishop rdir = get_bitbake_var('IMAGE_ROOTFS') 24700e122a7SBrad Bishop if rsize_bb and rdir == rootfs_dir: 24800e122a7SBrad Bishop # Bitbake variable ROOTFS_SIZE is calculated in 24900e122a7SBrad Bishop # Image._get_rootfs_size method from meta/lib/oe/image.py 25000e122a7SBrad Bishop # using IMAGE_ROOTFS_SIZE, IMAGE_ROOTFS_ALIGNMENT, 25100e122a7SBrad Bishop # IMAGE_OVERHEAD_FACTOR and IMAGE_ROOTFS_EXTRA_SPACE 25200e122a7SBrad Bishop self.size = int(round(float(rsize_bb))) 25300e122a7SBrad Bishop else: 25400e122a7SBrad Bishop # Bitbake variable ROOTFS_SIZE is not defined so compute it 25500e122a7SBrad Bishop # from the rootfs_dir size using the same logic found in 25600e122a7SBrad Bishop # get_rootfs_size() from meta/classes/image.bbclass 25708902b01SBrad Bishop du_cmd = "du -ks %s" % rootfs_dir 25808902b01SBrad Bishop out = exec_cmd(du_cmd) 25908902b01SBrad Bishop self.size = int(out.split()[0]) 260eb8dc403SDave Cobbley 261eb8dc403SDave Cobbley prefix = "ext" if self.fstype.startswith("ext") else self.fstype 262eb8dc403SDave Cobbley method = getattr(self, "prepare_rootfs_" + prefix) 263d1e89497SAndrew Geissler method(rootfs, cr_workdir, oe_builddir, rootfs_dir, native_sysroot, pseudo) 264eb8dc403SDave Cobbley self.source_file = rootfs 265eb8dc403SDave Cobbley 266eb8dc403SDave Cobbley # get the rootfs size in the right units for kickstart (kB) 267eb8dc403SDave Cobbley du_cmd = "du -Lbks %s" % rootfs 268eb8dc403SDave Cobbley out = exec_cmd(du_cmd) 269eb8dc403SDave Cobbley self.size = int(out.split()[0]) 270eb8dc403SDave Cobbley 271d1e89497SAndrew Geissler def prepare_rootfs_ext(self, rootfs, cr_workdir, oe_builddir, rootfs_dir, 272eb8dc403SDave Cobbley native_sysroot, pseudo): 273eb8dc403SDave Cobbley """ 274eb8dc403SDave Cobbley Prepare content for an ext2/3/4 rootfs partition. 275eb8dc403SDave Cobbley """ 276eb8dc403SDave Cobbley du_cmd = "du -ks %s" % rootfs_dir 277eb8dc403SDave Cobbley out = exec_cmd(du_cmd) 278eb8dc403SDave Cobbley actual_rootfs_size = int(out.split()[0]) 279eb8dc403SDave Cobbley 280eb8dc403SDave Cobbley rootfs_size = self.get_rootfs_size(actual_rootfs_size) 281eb8dc403SDave Cobbley 282eb8dc403SDave Cobbley with open(rootfs, 'w') as sparse: 283eb8dc403SDave Cobbley os.ftruncate(sparse.fileno(), rootfs_size * 1024) 284eb8dc403SDave Cobbley 285eb8dc403SDave Cobbley extraopts = self.mkfs_extraopts or "-F -i 8192" 286eb8dc403SDave Cobbley 287*169d7bccSPatrick Williams if os.getenv('SOURCE_DATE_EPOCH'): 288*169d7bccSPatrick Williams sde_time = int(os.getenv('SOURCE_DATE_EPOCH')) 289*169d7bccSPatrick Williams if pseudo: 290*169d7bccSPatrick Williams pseudo = "export E2FSPROGS_FAKE_TIME=%s;%s " % (sde_time, pseudo) 291*169d7bccSPatrick Williams else: 292*169d7bccSPatrick Williams pseudo = "export E2FSPROGS_FAKE_TIME=%s; " % sde_time 293*169d7bccSPatrick Williams 294*169d7bccSPatrick Williams # Set hash_seed to generate deterministic directory indexes 295*169d7bccSPatrick Williams namespace = uuid.UUID("e7429877-e7b3-4a68-a5c9-2f2fdf33d460") 296*169d7bccSPatrick Williams if self.fsuuid: 297*169d7bccSPatrick Williams namespace = uuid.UUID(self.fsuuid) 298*169d7bccSPatrick Williams hash_seed = str(uuid.uuid5(namespace, str(sde_time))) 299*169d7bccSPatrick Williams extraopts += " -E hash_seed=%s" % hash_seed 300*169d7bccSPatrick Williams 301eb8dc403SDave Cobbley label_str = "" 302eb8dc403SDave Cobbley if self.label: 303eb8dc403SDave Cobbley label_str = "-L %s" % self.label 304eb8dc403SDave Cobbley 305eb8dc403SDave Cobbley mkfs_cmd = "mkfs.%s %s %s %s -U %s -d %s" % \ 306eb8dc403SDave Cobbley (self.fstype, extraopts, rootfs, label_str, self.fsuuid, rootfs_dir) 307eb8dc403SDave Cobbley exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo) 308eb8dc403SDave Cobbley 309d159c7fbSAndrew Geissler if self.updated_fstab_path and self.has_fstab and not self.no_fstab_update: 310d1e89497SAndrew Geissler debugfs_script_path = os.path.join(cr_workdir, "debugfs_script") 311d1e89497SAndrew Geissler with open(debugfs_script_path, "w") as f: 312d1e89497SAndrew Geissler f.write("cd etc\n") 313d1e89497SAndrew Geissler f.write("rm fstab\n") 314d1e89497SAndrew Geissler f.write("write %s fstab\n" % (self.updated_fstab_path)) 315d1e89497SAndrew Geissler debugfs_cmd = "debugfs -w -f %s %s" % (debugfs_script_path, rootfs) 316d1e89497SAndrew Geissler exec_native_cmd(debugfs_cmd, native_sysroot) 317d1e89497SAndrew Geissler 318eb8dc403SDave Cobbley mkfs_cmd = "fsck.%s -pvfD %s" % (self.fstype, rootfs) 319eb8dc403SDave Cobbley exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo) 320eb8dc403SDave Cobbley 3217784c429SPatrick Williams if os.getenv('SOURCE_DATE_EPOCH'): 3227784c429SPatrick Williams sde_time = hex(int(os.getenv('SOURCE_DATE_EPOCH'))) 3237784c429SPatrick Williams debugfs_script_path = os.path.join(cr_workdir, "debugfs_script") 3247784c429SPatrick Williams files = [] 3257784c429SPatrick Williams for root, dirs, others in os.walk(rootfs_dir): 3267784c429SPatrick Williams base = root.replace(rootfs_dir, "").rstrip(os.sep) 3277784c429SPatrick Williams files += [ "/" if base == "" else base ] 3287784c429SPatrick Williams files += [ base + "/" + n for n in dirs + others ] 3297784c429SPatrick Williams with open(debugfs_script_path, "w") as f: 3307784c429SPatrick Williams f.write("set_current_time %s\n" % (sde_time)) 3317784c429SPatrick Williams if self.updated_fstab_path and self.has_fstab and not self.no_fstab_update: 3327784c429SPatrick Williams f.write("set_inode_field /etc/fstab mtime %s\n" % (sde_time)) 3337784c429SPatrick Williams f.write("set_inode_field /etc/fstab mtime_extra 0\n") 3347784c429SPatrick Williams for file in set(files): 3357784c429SPatrick Williams for time in ["atime", "ctime", "crtime"]: 3367784c429SPatrick Williams f.write("set_inode_field \"%s\" %s %s\n" % (file, time, sde_time)) 3377784c429SPatrick Williams f.write("set_inode_field \"%s\" %s_extra 0\n" % (file, time)) 3387784c429SPatrick Williams for time in ["wtime", "mkfs_time", "lastcheck"]: 3397784c429SPatrick Williams f.write("set_super_value %s %s\n" % (time, sde_time)) 3407784c429SPatrick Williams for time in ["mtime", "first_error_time", "last_error_time"]: 3417784c429SPatrick Williams f.write("set_super_value %s 0\n" % (time)) 3427784c429SPatrick Williams debugfs_cmd = "debugfs -w -f %s %s" % (debugfs_script_path, rootfs) 3437784c429SPatrick Williams exec_native_cmd(debugfs_cmd, native_sysroot) 3447784c429SPatrick Williams 34590fd73cbSAndrew Geissler self.check_for_Y2038_problem(rootfs, native_sysroot) 34690fd73cbSAndrew Geissler 347d1e89497SAndrew Geissler def prepare_rootfs_btrfs(self, rootfs, cr_workdir, oe_builddir, rootfs_dir, 348eb8dc403SDave Cobbley native_sysroot, pseudo): 349eb8dc403SDave Cobbley """ 350eb8dc403SDave Cobbley Prepare content for a btrfs rootfs partition. 351eb8dc403SDave Cobbley """ 352eb8dc403SDave Cobbley du_cmd = "du -ks %s" % rootfs_dir 353eb8dc403SDave Cobbley out = exec_cmd(du_cmd) 354eb8dc403SDave Cobbley actual_rootfs_size = int(out.split()[0]) 355eb8dc403SDave Cobbley 356eb8dc403SDave Cobbley rootfs_size = self.get_rootfs_size(actual_rootfs_size) 357eb8dc403SDave Cobbley 358eb8dc403SDave Cobbley with open(rootfs, 'w') as sparse: 359eb8dc403SDave Cobbley os.ftruncate(sparse.fileno(), rootfs_size * 1024) 360eb8dc403SDave Cobbley 361eb8dc403SDave Cobbley label_str = "" 362eb8dc403SDave Cobbley if self.label: 363eb8dc403SDave Cobbley label_str = "-L %s" % self.label 364eb8dc403SDave Cobbley 365eb8dc403SDave Cobbley mkfs_cmd = "mkfs.%s -b %d -r %s %s %s -U %s %s" % \ 366eb8dc403SDave Cobbley (self.fstype, rootfs_size * 1024, rootfs_dir, label_str, 367eb8dc403SDave Cobbley self.mkfs_extraopts, self.fsuuid, rootfs) 368eb8dc403SDave Cobbley exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo) 369eb8dc403SDave Cobbley 370d1e89497SAndrew Geissler def prepare_rootfs_msdos(self, rootfs, cr_workdir, oe_builddir, rootfs_dir, 371eb8dc403SDave Cobbley native_sysroot, pseudo): 372eb8dc403SDave Cobbley """ 373eb8dc403SDave Cobbley Prepare content for a msdos/vfat rootfs partition. 374eb8dc403SDave Cobbley """ 375eb8dc403SDave Cobbley du_cmd = "du -bks %s" % rootfs_dir 376eb8dc403SDave Cobbley out = exec_cmd(du_cmd) 377eb8dc403SDave Cobbley blocks = int(out.split()[0]) 378eb8dc403SDave Cobbley 379eb8dc403SDave Cobbley rootfs_size = self.get_rootfs_size(blocks) 380eb8dc403SDave Cobbley 381eb8dc403SDave Cobbley label_str = "-n boot" 382eb8dc403SDave Cobbley if self.label: 383eb8dc403SDave Cobbley label_str = "-n %s" % self.label 384eb8dc403SDave Cobbley 385eb8dc403SDave Cobbley size_str = "" 386eb8dc403SDave Cobbley 387eb8dc403SDave Cobbley extraopts = self.mkfs_extraopts or '-S 512' 388eb8dc403SDave Cobbley 389eb8dc403SDave Cobbley dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \ 390eb8dc403SDave Cobbley (label_str, self.fsuuid, size_str, extraopts, rootfs, 391c342db35SBrad Bishop rootfs_size) 392eb8dc403SDave Cobbley exec_native_cmd(dosfs_cmd, native_sysroot) 393eb8dc403SDave Cobbley 394eb8dc403SDave Cobbley mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (rootfs, rootfs_dir) 395eb8dc403SDave Cobbley exec_native_cmd(mcopy_cmd, native_sysroot) 396eb8dc403SDave Cobbley 397d159c7fbSAndrew Geissler if self.updated_fstab_path and self.has_fstab and not self.no_fstab_update: 3982390b1b6SPatrick Williams mcopy_cmd = "mcopy -m -i %s %s ::/etc/fstab" % (rootfs, self.updated_fstab_path) 399d1e89497SAndrew Geissler exec_native_cmd(mcopy_cmd, native_sysroot) 400d1e89497SAndrew Geissler 401eb8dc403SDave Cobbley chmod_cmd = "chmod 644 %s" % rootfs 402eb8dc403SDave Cobbley exec_cmd(chmod_cmd) 403eb8dc403SDave Cobbley 404eb8dc403SDave Cobbley prepare_rootfs_vfat = prepare_rootfs_msdos 405eb8dc403SDave Cobbley 406d1e89497SAndrew Geissler def prepare_rootfs_squashfs(self, rootfs, cr_workdir, oe_builddir, rootfs_dir, 407eb8dc403SDave Cobbley native_sysroot, pseudo): 408eb8dc403SDave Cobbley """ 409eb8dc403SDave Cobbley Prepare content for a squashfs rootfs partition. 410eb8dc403SDave Cobbley """ 411eb8dc403SDave Cobbley extraopts = self.mkfs_extraopts or '-noappend' 412eb8dc403SDave Cobbley squashfs_cmd = "mksquashfs %s %s %s" % \ 413eb8dc403SDave Cobbley (rootfs_dir, rootfs, extraopts) 414eb8dc403SDave Cobbley exec_native_cmd(squashfs_cmd, native_sysroot, pseudo=pseudo) 415eb8dc403SDave Cobbley 416ac69b488SWilliam A. Kennington III def prepare_rootfs_erofs(self, rootfs, cr_workdir, oe_builddir, rootfs_dir, 417ac69b488SWilliam A. Kennington III native_sysroot, pseudo): 418ac69b488SWilliam A. Kennington III """ 419ac69b488SWilliam A. Kennington III Prepare content for a erofs rootfs partition. 420ac69b488SWilliam A. Kennington III """ 421ac69b488SWilliam A. Kennington III extraopts = self.mkfs_extraopts or '' 422ac69b488SWilliam A. Kennington III erofs_cmd = "mkfs.erofs %s -U %s %s %s" % \ 423ac69b488SWilliam A. Kennington III (extraopts, self.fsuuid, rootfs, rootfs_dir) 424ac69b488SWilliam A. Kennington III exec_native_cmd(erofs_cmd, native_sysroot, pseudo=pseudo) 425ac69b488SWilliam A. Kennington III 4266aa7eec5SAndrew Geissler def prepare_empty_partition_none(self, rootfs, oe_builddir, native_sysroot): 4276aa7eec5SAndrew Geissler pass 4286aa7eec5SAndrew Geissler 429eb8dc403SDave Cobbley def prepare_empty_partition_ext(self, rootfs, oe_builddir, 430eb8dc403SDave Cobbley native_sysroot): 431eb8dc403SDave Cobbley """ 432eb8dc403SDave Cobbley Prepare an empty ext2/3/4 partition. 433eb8dc403SDave Cobbley """ 434eb8dc403SDave Cobbley size = self.disk_size 435eb8dc403SDave Cobbley with open(rootfs, 'w') as sparse: 436eb8dc403SDave Cobbley os.ftruncate(sparse.fileno(), size * 1024) 437eb8dc403SDave Cobbley 438eb8dc403SDave Cobbley extraopts = self.mkfs_extraopts or "-i 8192" 439eb8dc403SDave Cobbley 440eb8dc403SDave Cobbley label_str = "" 441eb8dc403SDave Cobbley if self.label: 442eb8dc403SDave Cobbley label_str = "-L %s" % self.label 443eb8dc403SDave Cobbley 444eb8dc403SDave Cobbley mkfs_cmd = "mkfs.%s -F %s %s -U %s %s" % \ 445eb8dc403SDave Cobbley (self.fstype, extraopts, label_str, self.fsuuid, rootfs) 446eb8dc403SDave Cobbley exec_native_cmd(mkfs_cmd, native_sysroot) 447eb8dc403SDave Cobbley 44890fd73cbSAndrew Geissler self.check_for_Y2038_problem(rootfs, native_sysroot) 44990fd73cbSAndrew Geissler 450eb8dc403SDave Cobbley def prepare_empty_partition_btrfs(self, rootfs, oe_builddir, 451eb8dc403SDave Cobbley native_sysroot): 452eb8dc403SDave Cobbley """ 453eb8dc403SDave Cobbley Prepare an empty btrfs partition. 454eb8dc403SDave Cobbley """ 455eb8dc403SDave Cobbley size = self.disk_size 456eb8dc403SDave Cobbley with open(rootfs, 'w') as sparse: 457eb8dc403SDave Cobbley os.ftruncate(sparse.fileno(), size * 1024) 458eb8dc403SDave Cobbley 459eb8dc403SDave Cobbley label_str = "" 460eb8dc403SDave Cobbley if self.label: 461eb8dc403SDave Cobbley label_str = "-L %s" % self.label 462eb8dc403SDave Cobbley 463eb8dc403SDave Cobbley mkfs_cmd = "mkfs.%s -b %d %s -U %s %s %s" % \ 464eb8dc403SDave Cobbley (self.fstype, self.size * 1024, label_str, self.fsuuid, 465eb8dc403SDave Cobbley self.mkfs_extraopts, rootfs) 466eb8dc403SDave Cobbley exec_native_cmd(mkfs_cmd, native_sysroot) 467eb8dc403SDave Cobbley 468eb8dc403SDave Cobbley def prepare_empty_partition_msdos(self, rootfs, oe_builddir, 469eb8dc403SDave Cobbley native_sysroot): 470eb8dc403SDave Cobbley """ 471eb8dc403SDave Cobbley Prepare an empty vfat partition. 472eb8dc403SDave Cobbley """ 473eb8dc403SDave Cobbley blocks = self.disk_size 474eb8dc403SDave Cobbley 475eb8dc403SDave Cobbley label_str = "-n boot" 476eb8dc403SDave Cobbley if self.label: 477eb8dc403SDave Cobbley label_str = "-n %s" % self.label 478eb8dc403SDave Cobbley 479eb8dc403SDave Cobbley size_str = "" 480eb8dc403SDave Cobbley 481eb8dc403SDave Cobbley extraopts = self.mkfs_extraopts or '-S 512' 482eb8dc403SDave Cobbley 483eb8dc403SDave Cobbley dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \ 484eb8dc403SDave Cobbley (label_str, self.fsuuid, extraopts, size_str, rootfs, 485eb8dc403SDave Cobbley blocks) 486eb8dc403SDave Cobbley 487eb8dc403SDave Cobbley exec_native_cmd(dosfs_cmd, native_sysroot) 488eb8dc403SDave Cobbley 489eb8dc403SDave Cobbley chmod_cmd = "chmod 644 %s" % rootfs 490eb8dc403SDave Cobbley exec_cmd(chmod_cmd) 491eb8dc403SDave Cobbley 492eb8dc403SDave Cobbley prepare_empty_partition_vfat = prepare_empty_partition_msdos 493eb8dc403SDave Cobbley 494eb8dc403SDave Cobbley def prepare_swap_partition(self, cr_workdir, oe_builddir, native_sysroot): 495eb8dc403SDave Cobbley """ 496eb8dc403SDave Cobbley Prepare a swap partition. 497eb8dc403SDave Cobbley """ 498eb8dc403SDave Cobbley path = "%s/fs.%s" % (cr_workdir, self.fstype) 499eb8dc403SDave Cobbley 500eb8dc403SDave Cobbley with open(path, 'w') as sparse: 501eb8dc403SDave Cobbley os.ftruncate(sparse.fileno(), self.size * 1024) 502eb8dc403SDave Cobbley 503eb8dc403SDave Cobbley label_str = "" 504eb8dc403SDave Cobbley if self.label: 505eb8dc403SDave Cobbley label_str = "-L %s" % self.label 506eb8dc403SDave Cobbley 507eb8dc403SDave Cobbley mkswap_cmd = "mkswap %s -U %s %s" % (label_str, self.fsuuid, path) 508eb8dc403SDave Cobbley exec_native_cmd(mkswap_cmd, native_sysroot) 50990fd73cbSAndrew Geissler 51090fd73cbSAndrew Geissler def check_for_Y2038_problem(self, rootfs, native_sysroot): 51190fd73cbSAndrew Geissler """ 51290fd73cbSAndrew Geissler Check if the filesystem is affected by the Y2038 problem 51390fd73cbSAndrew Geissler (Y2038 problem = 32 bit time_t overflow in January 2038) 51490fd73cbSAndrew Geissler """ 51590fd73cbSAndrew Geissler def get_err_str(part): 51690fd73cbSAndrew Geissler err = "The {} filesystem {} has no Y2038 support." 51790fd73cbSAndrew Geissler if part.mountpoint: 51890fd73cbSAndrew Geissler args = [part.fstype, "mounted at %s" % part.mountpoint] 51990fd73cbSAndrew Geissler elif part.label: 52090fd73cbSAndrew Geissler args = [part.fstype, "labeled '%s'" % part.label] 52190fd73cbSAndrew Geissler elif part.part_name: 52290fd73cbSAndrew Geissler args = [part.fstype, "in partition '%s'" % part.part_name] 52390fd73cbSAndrew Geissler else: 52490fd73cbSAndrew Geissler args = [part.fstype, "in partition %s" % part.num] 52590fd73cbSAndrew Geissler return err.format(*args) 52690fd73cbSAndrew Geissler 52790fd73cbSAndrew Geissler # ext2 and ext3 are always affected by the Y2038 problem 52890fd73cbSAndrew Geissler if self.fstype in ["ext2", "ext3"]: 52990fd73cbSAndrew Geissler logger.warn(get_err_str(self)) 53090fd73cbSAndrew Geissler return 53190fd73cbSAndrew Geissler 53290fd73cbSAndrew Geissler ret, out = exec_native_cmd("dumpe2fs %s" % rootfs, native_sysroot) 53390fd73cbSAndrew Geissler 53490fd73cbSAndrew Geissler # if ext4 is affected by the Y2038 problem depends on the inode size 53590fd73cbSAndrew Geissler for line in out.splitlines(): 53690fd73cbSAndrew Geissler if line.startswith("Inode size:"): 53790fd73cbSAndrew Geissler size = int(line.split(":")[1].strip()) 53890fd73cbSAndrew Geissler if size < 256: 53990fd73cbSAndrew Geissler logger.warn("%s Inodes (of size %d) are too small." % 54090fd73cbSAndrew Geissler (get_err_str(self), size)) 54190fd73cbSAndrew Geissler break 54290fd73cbSAndrew Geissler 543