summaryrefslogtreecommitdiffstats
path: root/scripts/lib
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib')
-rw-r--r--scripts/lib/devtool/standard.py43
-rw-r--r--scripts/lib/devtool/upgrade.py4
-rw-r--r--scripts/lib/recipetool/create_npm.py6
-rw-r--r--scripts/lib/wic/canned-wks/common.wks.inc2
-rw-r--r--scripts/lib/wic/canned-wks/directdisk-gpt.wks2
-rw-r--r--scripts/lib/wic/canned-wks/mkefidisk.wks2
-rw-r--r--scripts/lib/wic/ksparser.py17
-rw-r--r--scripts/lib/wic/misc.py8
-rw-r--r--scripts/lib/wic/partition.py82
-rw-r--r--scripts/lib/wic/plugins/imager/direct.py61
-rw-r--r--scripts/lib/wic/plugins/source/rootfs.py33
11 files changed, 203 insertions, 57 deletions
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index 261d642d4a..f364a45283 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -474,7 +474,11 @@ def symlink_oelocal_files_srctree(rd,srctree):
474 destpth = os.path.join(srctree, relpth, fn) 474 destpth = os.path.join(srctree, relpth, fn)
475 if os.path.exists(destpth): 475 if os.path.exists(destpth):
476 os.unlink(destpth) 476 os.unlink(destpth)
477 os.symlink('oe-local-files/%s' % fn, destpth) 477 if relpth != '.':
478 back_relpth = os.path.relpath(local_files_dir, root)
479 os.symlink('%s/oe-local-files/%s/%s' % (back_relpth, relpth, fn), destpth)
480 else:
481 os.symlink('oe-local-files/%s' % fn, destpth)
478 addfiles.append(os.path.join(relpth, fn)) 482 addfiles.append(os.path.join(relpth, fn))
479 if addfiles: 483 if addfiles:
480 bb.process.run('git add %s' % ' '.join(addfiles), cwd=srctree) 484 bb.process.run('git add %s' % ' '.join(addfiles), cwd=srctree)
@@ -589,6 +593,16 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works
589 else: 593 else:
590 task = 'do_patch' 594 task = 'do_patch'
591 595
596 if 'noexec' in (d.getVarFlags(task, False) or []) or 'task' not in (d.getVarFlags(task, False) or []):
597 logger.info('The %s recipe has %s disabled. Running only '
598 'do_configure task dependencies' % (pn, task))
599
600 if 'depends' in d.getVarFlags('do_configure', False):
601 pn = d.getVarFlags('do_configure', False)['depends']
602 pn = pn.replace('${PV}', d.getVar('PV'))
603 pn = pn.replace('${COMPILERDEP}', d.getVar('COMPILERDEP'))
604 task = None
605
592 # Run the fetch + unpack tasks 606 # Run the fetch + unpack tasks
593 res = tinfoil.build_targets(pn, 607 res = tinfoil.build_targets(pn,
594 task, 608 task,
@@ -600,6 +614,17 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works
600 if not res: 614 if not res:
601 raise DevtoolError('Extracting source for %s failed' % pn) 615 raise DevtoolError('Extracting source for %s failed' % pn)
602 616
617 if not is_kernel_yocto and ('noexec' in (d.getVarFlags('do_patch', False) or []) or 'task' not in (d.getVarFlags('do_patch', False) or [])):
618 workshareddir = d.getVar('S')
619 if os.path.islink(srctree):
620 os.unlink(srctree)
621
622 os.symlink(workshareddir, srctree)
623
624 # The initial_rev file is created in devtool_post_unpack function that will not be executed if
625 # do_unpack/do_patch tasks are disabled so we have to directly say that source extraction was successful
626 return True, True
627
603 try: 628 try:
604 with open(os.path.join(tempdir, 'initial_rev'), 'r') as f: 629 with open(os.path.join(tempdir, 'initial_rev'), 'r') as f:
605 initial_rev = f.read() 630 initial_rev = f.read()
@@ -847,10 +872,11 @@ def modify(args, config, basepath, workspace):
847 if not initial_rev: 872 if not initial_rev:
848 return 1 873 return 1
849 logger.info('Source tree extracted to %s' % srctree) 874 logger.info('Source tree extracted to %s' % srctree)
850 # Get list of commits since this revision 875 if os.path.exists(os.path.join(srctree, '.git')):
851 (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_rev, cwd=srctree) 876 # Get list of commits since this revision
852 commits = stdout.split() 877 (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_rev, cwd=srctree)
853 check_commits = True 878 commits = stdout.split()
879 check_commits = True
854 else: 880 else:
855 if os.path.exists(os.path.join(srctree, '.git')): 881 if os.path.exists(os.path.join(srctree, '.git')):
856 # Check if it's a tree previously extracted by us. This is done 882 # Check if it's a tree previously extracted by us. This is done
@@ -927,12 +953,17 @@ def modify(args, config, basepath, workspace):
927 953
928 if bb.data.inherits_class('kernel', rd): 954 if bb.data.inherits_class('kernel', rd):
929 f.write('SRCTREECOVEREDTASKS = "do_validate_branches do_kernel_checkout ' 955 f.write('SRCTREECOVEREDTASKS = "do_validate_branches do_kernel_checkout '
930 'do_fetch do_unpack do_kernel_configme do_kernel_configcheck"\n') 956 'do_fetch do_unpack do_kernel_configcheck"\n')
931 f.write('\ndo_patch[noexec] = "1"\n') 957 f.write('\ndo_patch[noexec] = "1"\n')
932 f.write('\ndo_configure_append() {\n' 958 f.write('\ndo_configure_append() {\n'
933 ' cp ${B}/.config ${S}/.config.baseline\n' 959 ' cp ${B}/.config ${S}/.config.baseline\n'
934 ' ln -sfT ${B}/.config ${S}/.config.new\n' 960 ' ln -sfT ${B}/.config ${S}/.config.new\n'
935 '}\n') 961 '}\n')
962 f.write('\ndo_kernel_configme_prepend() {\n'
963 ' if [ -e ${S}/.config ]; then\n'
964 ' mv ${S}/.config ${S}/.config.old\n'
965 ' fi\n'
966 '}\n')
936 if rd.getVarFlag('do_menuconfig','task'): 967 if rd.getVarFlag('do_menuconfig','task'):
937 f.write('\ndo_configure_append() {\n' 968 f.write('\ndo_configure_append() {\n'
938 ' if [ ! ${DEVTOOL_DISABLE_MENUCONFIG} ]; then\n' 969 ' if [ ! ${DEVTOOL_DISABLE_MENUCONFIG} ]; then\n'
diff --git a/scripts/lib/devtool/upgrade.py b/scripts/lib/devtool/upgrade.py
index 0c1de8cdc7..5a057e95f5 100644
--- a/scripts/lib/devtool/upgrade.py
+++ b/scripts/lib/devtool/upgrade.py
@@ -178,7 +178,7 @@ def _extract_new_source(newpv, srctree, no_patch, srcrev, srcbranch, branch, kee
178 uri, rev = _get_uri(crd) 178 uri, rev = _get_uri(crd)
179 if srcrev: 179 if srcrev:
180 rev = srcrev 180 rev = srcrev
181 if uri.startswith('git://'): 181 if uri.startswith('git://') or uri.startswith('gitsm://'):
182 __run('git fetch') 182 __run('git fetch')
183 __run('git checkout %s' % rev) 183 __run('git checkout %s' % rev)
184 __run('git tag -f devtool-base-new') 184 __run('git tag -f devtool-base-new')
@@ -270,7 +270,7 @@ def _extract_new_source(newpv, srctree, no_patch, srcrev, srcbranch, branch, kee
270 else: 270 else:
271 logger.warning('Command \'%s\' failed:\n%s' % (e.command, e.stdout)) 271 logger.warning('Command \'%s\' failed:\n%s' % (e.command, e.stdout))
272 if not skiptag: 272 if not skiptag:
273 if uri.startswith('git://'): 273 if uri.startswith('git://') or uri.startswith('gitsm://'):
274 suffix = 'new' 274 suffix = 'new'
275 else: 275 else:
276 suffix = newpv 276 suffix = newpv
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py
index 579b7ae48a..2bcae91dfa 100644
--- a/scripts/lib/recipetool/create_npm.py
+++ b/scripts/lib/recipetool/create_npm.py
@@ -204,6 +204,9 @@ class NpmRecipeHandler(RecipeHandler):
204 self._run_npm_install(d, srctree, registry, dev) 204 self._run_npm_install(d, srctree, registry, dev)
205 shrinkwrap_file = self._generate_shrinkwrap(d, srctree, dev) 205 shrinkwrap_file = self._generate_shrinkwrap(d, srctree, dev)
206 206
207 with open(shrinkwrap_file, "r") as f:
208 shrinkwrap = json.load(f)
209
207 if os.path.exists(lock_copy): 210 if os.path.exists(lock_copy):
208 bb.utils.movefile(lock_copy, lock_file) 211 bb.utils.movefile(lock_copy, lock_file)
209 212
@@ -226,7 +229,8 @@ class NpmRecipeHandler(RecipeHandler):
226 value = origvalue.replace("version=" + data["version"], "version=${PV}") 229 value = origvalue.replace("version=" + data["version"], "version=${PV}")
227 value = value.replace("version=latest", "version=${PV}") 230 value = value.replace("version=latest", "version=${PV}")
228 values = [line.strip() for line in value.strip('\n').splitlines()] 231 values = [line.strip() for line in value.strip('\n').splitlines()]
229 values.append(url_recipe) 232 if "dependencies" in shrinkwrap:
233 values.append(url_recipe)
230 return values, None, 4, False 234 return values, None, 4, False
231 235
232 (_, newlines) = bb.utils.edit_metadata(lines_before, ["SRC_URI"], _handle_srcuri) 236 (_, newlines) = bb.utils.edit_metadata(lines_before, ["SRC_URI"], _handle_srcuri)
diff --git a/scripts/lib/wic/canned-wks/common.wks.inc b/scripts/lib/wic/canned-wks/common.wks.inc
index 89880b417b..4fd29fa8c1 100644
--- a/scripts/lib/wic/canned-wks/common.wks.inc
+++ b/scripts/lib/wic/canned-wks/common.wks.inc
@@ -1,3 +1,3 @@
1# This file is included into 3 canned wks files from this directory 1# This file is included into 3 canned wks files from this directory
2part /boot --source bootimg-pcbios --ondisk sda --label boot --active --align 1024 2part /boot --source bootimg-pcbios --ondisk sda --label boot --active --align 1024
3part / --source rootfs --use-uuid --fstype=ext4 --label platform --align 1024 3part / --source rootfs --use-uuid --fstype=ext4 --mkfs-extraopts "-T default" --label platform --align 1024
diff --git a/scripts/lib/wic/canned-wks/directdisk-gpt.wks b/scripts/lib/wic/canned-wks/directdisk-gpt.wks
index 8d7d8de6ea..cf16c0c30b 100644
--- a/scripts/lib/wic/canned-wks/directdisk-gpt.wks
+++ b/scripts/lib/wic/canned-wks/directdisk-gpt.wks
@@ -4,7 +4,7 @@
4 4
5 5
6part /boot --source bootimg-pcbios --ondisk sda --label boot --active --align 1024 6part /boot --source bootimg-pcbios --ondisk sda --label boot --active --align 1024
7part / --source rootfs --ondisk sda --fstype=ext4 --label platform --align 1024 --use-uuid 7part / --source rootfs --ondisk sda --fstype=ext4 --mkfs-extraopts "-T default" --label platform --align 1024 --use-uuid
8 8
9bootloader --ptable gpt --timeout=0 --append="rootwait rootfstype=ext4 video=vesafb vga=0x318 console=tty0 console=ttyS0,115200n8" 9bootloader --ptable gpt --timeout=0 --append="rootwait rootfstype=ext4 video=vesafb vga=0x318 console=tty0 console=ttyS0,115200n8"
10 10
diff --git a/scripts/lib/wic/canned-wks/mkefidisk.wks b/scripts/lib/wic/canned-wks/mkefidisk.wks
index 9f534fe184..d1878e23e5 100644
--- a/scripts/lib/wic/canned-wks/mkefidisk.wks
+++ b/scripts/lib/wic/canned-wks/mkefidisk.wks
@@ -4,7 +4,7 @@
4 4
5part /boot --source bootimg-efi --sourceparams="loader=grub-efi" --ondisk sda --label msdos --active --align 1024 5part /boot --source bootimg-efi --sourceparams="loader=grub-efi" --ondisk sda --label msdos --active --align 1024
6 6
7part / --source rootfs --ondisk sda --fstype=ext4 --label platform --align 1024 --use-uuid 7part / --source rootfs --ondisk sda --fstype=ext4 --mkfs-extraopts "-T default" --label platform --align 1024 --use-uuid
8 8
9part swap --ondisk sda --size 44 --label swap1 --fstype=swap 9part swap --ondisk sda --size 44 --label swap1 --fstype=swap
10 10
diff --git a/scripts/lib/wic/ksparser.py b/scripts/lib/wic/ksparser.py
index 913e3283dc..3eb669da39 100644
--- a/scripts/lib/wic/ksparser.py
+++ b/scripts/lib/wic/ksparser.py
@@ -229,6 +229,23 @@ class KickStart():
229 err = "%s:%d: SquashFS does not support LABEL" \ 229 err = "%s:%d: SquashFS does not support LABEL" \
230 % (confpath, lineno) 230 % (confpath, lineno)
231 raise KickStartError(err) 231 raise KickStartError(err)
232 if parsed.fstype == 'msdos' or parsed.fstype == 'vfat':
233 if parsed.fsuuid:
234 if parsed.fsuuid.upper().startswith('0X'):
235 if len(parsed.fsuuid) > 10:
236 err = "%s:%d: fsuuid %s given in wks kickstart file " \
237 "exceeds the length limit for %s filesystem. " \
238 "It should be in the form of a 32 bit hexadecimal" \
239 "number (for example, 0xABCD1234)." \
240 % (confpath, lineno, parsed.fsuuid, parsed.fstype)
241 raise KickStartError(err)
242 elif len(parsed.fsuuid) > 8:
243 err = "%s:%d: fsuuid %s given in wks kickstart file " \
244 "exceeds the length limit for %s filesystem. " \
245 "It should be in the form of a 32 bit hexadecimal" \
246 "number (for example, 0xABCD1234)." \
247 % (confpath, lineno, parsed.fsuuid, parsed.fstype)
248 raise KickStartError(err)
232 if parsed.use_label and not parsed.label: 249 if parsed.use_label and not parsed.label:
233 err = "%s:%d: Must set the label with --label" \ 250 err = "%s:%d: Must set the label with --label" \
234 % (confpath, lineno) 251 % (confpath, lineno)
diff --git a/scripts/lib/wic/misc.py b/scripts/lib/wic/misc.py
index 4b08d649c6..57c042c503 100644
--- a/scripts/lib/wic/misc.py
+++ b/scripts/lib/wic/misc.py
@@ -26,6 +26,7 @@ logger = logging.getLogger('wic')
26 26
27# executable -> recipe pairs for exec_native_cmd 27# executable -> recipe pairs for exec_native_cmd
28NATIVE_RECIPES = {"bmaptool": "bmap-tools", 28NATIVE_RECIPES = {"bmaptool": "bmap-tools",
29 "dumpe2fs": "e2fsprogs",
29 "grub-mkimage": "grub-efi", 30 "grub-mkimage": "grub-efi",
30 "isohybrid": "syslinux", 31 "isohybrid": "syslinux",
31 "mcopy": "mtools", 32 "mcopy": "mtools",
@@ -138,9 +139,12 @@ def exec_native_cmd(cmd_and_args, native_sysroot, pseudo=""):
138 if pseudo: 139 if pseudo:
139 cmd_and_args = pseudo + cmd_and_args 140 cmd_and_args = pseudo + cmd_and_args
140 141
141 native_paths = "%s/sbin:%s/usr/sbin:%s/usr/bin:%s/bin" % \ 142 hosttools_dir = get_bitbake_var("HOSTTOOLS_DIR")
143
144 native_paths = "%s/sbin:%s/usr/sbin:%s/usr/bin:%s/bin:%s" % \
142 (native_sysroot, native_sysroot, 145 (native_sysroot, native_sysroot,
143 native_sysroot, native_sysroot) 146 native_sysroot, native_sysroot,
147 hosttools_dir)
144 148
145 native_cmd_and_args = "export PATH=%s:$PATH;%s" % \ 149 native_cmd_and_args = "export PATH=%s:$PATH;%s" % \
146 (native_paths, cmd_and_args) 150 (native_paths, cmd_and_args)
diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
index ebe250b00d..85f9847047 100644
--- a/scripts/lib/wic/partition.py
+++ b/scripts/lib/wic/partition.py
@@ -54,6 +54,9 @@ class Partition():
54 self.uuid = args.uuid 54 self.uuid = args.uuid
55 self.fsuuid = args.fsuuid 55 self.fsuuid = args.fsuuid
56 self.type = args.type 56 self.type = args.type
57 self.updated_fstab_path = None
58 self.has_fstab = False
59 self.update_fstab_in_rootfs = False
57 60
58 self.lineno = lineno 61 self.lineno = lineno
59 self.source_file = "" 62 self.source_file = ""
@@ -118,11 +121,15 @@ class Partition():
118 return self.fixed_size if self.fixed_size else self.size 121 return self.fixed_size if self.fixed_size else self.size
119 122
120 def prepare(self, creator, cr_workdir, oe_builddir, rootfs_dir, 123 def prepare(self, creator, cr_workdir, oe_builddir, rootfs_dir,
121 bootimg_dir, kernel_dir, native_sysroot): 124 bootimg_dir, kernel_dir, native_sysroot, updated_fstab_path):
122 """ 125 """
123 Prepare content for individual partitions, depending on 126 Prepare content for individual partitions, depending on
124 partition command parameters. 127 partition command parameters.
125 """ 128 """
129 self.updated_fstab_path = updated_fstab_path
130 if self.updated_fstab_path and not (self.fstype.startswith("ext") or self.fstype == "msdos"):
131 self.update_fstab_in_rootfs = True
132
126 if not self.source: 133 if not self.source:
127 if not self.size and not self.fixed_size: 134 if not self.size and not self.fixed_size:
128 raise WicError("The %s partition has a size of zero. Please " 135 raise WicError("The %s partition has a size of zero. Please "
@@ -207,11 +214,21 @@ class Partition():
207 214
208 p_prefix = os.environ.get("PSEUDO_PREFIX", "%s/usr" % native_sysroot) 215 p_prefix = os.environ.get("PSEUDO_PREFIX", "%s/usr" % native_sysroot)
209 if (pseudo_dir): 216 if (pseudo_dir):
217 # Canonicalize the ignore paths. This corresponds to
218 # calling oe.path.canonicalize(), which is used in bitbake.conf.
219 ignore_paths = [rootfs] + (get_bitbake_var("PSEUDO_IGNORE_PATHS") or "").split(",")
220 canonical_paths = []
221 for path in ignore_paths:
222 if "$" not in path:
223 trailing_slash = path.endswith("/") and "/" or ""
224 canonical_paths.append(os.path.realpath(path) + trailing_slash)
225 ignore_paths = ",".join(canonical_paths)
226
210 pseudo = "export PSEUDO_PREFIX=%s;" % p_prefix 227 pseudo = "export PSEUDO_PREFIX=%s;" % p_prefix
211 pseudo += "export PSEUDO_LOCALSTATEDIR=%s;" % pseudo_dir 228 pseudo += "export PSEUDO_LOCALSTATEDIR=%s;" % pseudo_dir
212 pseudo += "export PSEUDO_PASSWD=%s;" % rootfs_dir 229 pseudo += "export PSEUDO_PASSWD=%s;" % rootfs_dir
213 pseudo += "export PSEUDO_NOSYMLINKEXP=1;" 230 pseudo += "export PSEUDO_NOSYMLINKEXP=1;"
214 pseudo += "export PSEUDO_IGNORE_PATHS=%s;" % (rootfs + "," + (get_bitbake_var("PSEUDO_IGNORE_PATHS") or "")) 231 pseudo += "export PSEUDO_IGNORE_PATHS=%s;" % ignore_paths
215 pseudo += "%s " % get_bitbake_var("FAKEROOTCMD") 232 pseudo += "%s " % get_bitbake_var("FAKEROOTCMD")
216 else: 233 else:
217 pseudo = None 234 pseudo = None
@@ -237,7 +254,7 @@ class Partition():
237 254
238 prefix = "ext" if self.fstype.startswith("ext") else self.fstype 255 prefix = "ext" if self.fstype.startswith("ext") else self.fstype
239 method = getattr(self, "prepare_rootfs_" + prefix) 256 method = getattr(self, "prepare_rootfs_" + prefix)
240 method(rootfs, oe_builddir, rootfs_dir, native_sysroot, pseudo) 257 method(rootfs, cr_workdir, oe_builddir, rootfs_dir, native_sysroot, pseudo)
241 self.source_file = rootfs 258 self.source_file = rootfs
242 259
243 # get the rootfs size in the right units for kickstart (kB) 260 # get the rootfs size in the right units for kickstart (kB)
@@ -245,7 +262,7 @@ class Partition():
245 out = exec_cmd(du_cmd) 262 out = exec_cmd(du_cmd)
246 self.size = int(out.split()[0]) 263 self.size = int(out.split()[0])
247 264
248 def prepare_rootfs_ext(self, rootfs, oe_builddir, rootfs_dir, 265 def prepare_rootfs_ext(self, rootfs, cr_workdir, oe_builddir, rootfs_dir,
249 native_sysroot, pseudo): 266 native_sysroot, pseudo):
250 """ 267 """
251 Prepare content for an ext2/3/4 rootfs partition. 268 Prepare content for an ext2/3/4 rootfs partition.
@@ -269,10 +286,21 @@ class Partition():
269 (self.fstype, extraopts, rootfs, label_str, self.fsuuid, rootfs_dir) 286 (self.fstype, extraopts, rootfs, label_str, self.fsuuid, rootfs_dir)
270 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo) 287 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo)
271 288
289 if self.updated_fstab_path and self.has_fstab:
290 debugfs_script_path = os.path.join(cr_workdir, "debugfs_script")
291 with open(debugfs_script_path, "w") as f:
292 f.write("cd etc\n")
293 f.write("rm fstab\n")
294 f.write("write %s fstab\n" % (self.updated_fstab_path))
295 debugfs_cmd = "debugfs -w -f %s %s" % (debugfs_script_path, rootfs)
296 exec_native_cmd(debugfs_cmd, native_sysroot)
297
272 mkfs_cmd = "fsck.%s -pvfD %s" % (self.fstype, rootfs) 298 mkfs_cmd = "fsck.%s -pvfD %s" % (self.fstype, rootfs)
273 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo) 299 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo)
274 300
275 def prepare_rootfs_btrfs(self, rootfs, oe_builddir, rootfs_dir, 301 self.check_for_Y2038_problem(rootfs, native_sysroot)
302
303 def prepare_rootfs_btrfs(self, rootfs, cr_workdir, oe_builddir, rootfs_dir,
276 native_sysroot, pseudo): 304 native_sysroot, pseudo):
277 """ 305 """
278 Prepare content for a btrfs rootfs partition. 306 Prepare content for a btrfs rootfs partition.
@@ -295,7 +323,7 @@ class Partition():
295 self.mkfs_extraopts, self.fsuuid, rootfs) 323 self.mkfs_extraopts, self.fsuuid, rootfs)
296 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo) 324 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo)
297 325
298 def prepare_rootfs_msdos(self, rootfs, oe_builddir, rootfs_dir, 326 def prepare_rootfs_msdos(self, rootfs, cr_workdir, oe_builddir, rootfs_dir,
299 native_sysroot, pseudo): 327 native_sysroot, pseudo):
300 """ 328 """
301 Prepare content for a msdos/vfat rootfs partition. 329 Prepare content for a msdos/vfat rootfs partition.
@@ -324,12 +352,16 @@ class Partition():
324 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (rootfs, rootfs_dir) 352 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (rootfs, rootfs_dir)
325 exec_native_cmd(mcopy_cmd, native_sysroot) 353 exec_native_cmd(mcopy_cmd, native_sysroot)
326 354
355 if self.updated_fstab_path and self.has_fstab:
356 mcopy_cmd = "mcopy -i %s %s ::/etc/fstab" % (rootfs, self.updated_fstab_path)
357 exec_native_cmd(mcopy_cmd, native_sysroot)
358
327 chmod_cmd = "chmod 644 %s" % rootfs 359 chmod_cmd = "chmod 644 %s" % rootfs
328 exec_cmd(chmod_cmd) 360 exec_cmd(chmod_cmd)
329 361
330 prepare_rootfs_vfat = prepare_rootfs_msdos 362 prepare_rootfs_vfat = prepare_rootfs_msdos
331 363
332 def prepare_rootfs_squashfs(self, rootfs, oe_builddir, rootfs_dir, 364 def prepare_rootfs_squashfs(self, rootfs, cr_workdir, oe_builddir, rootfs_dir,
333 native_sysroot, pseudo): 365 native_sysroot, pseudo):
334 """ 366 """
335 Prepare content for a squashfs rootfs partition. 367 Prepare content for a squashfs rootfs partition.
@@ -358,6 +390,8 @@ class Partition():
358 (self.fstype, extraopts, label_str, self.fsuuid, rootfs) 390 (self.fstype, extraopts, label_str, self.fsuuid, rootfs)
359 exec_native_cmd(mkfs_cmd, native_sysroot) 391 exec_native_cmd(mkfs_cmd, native_sysroot)
360 392
393 self.check_for_Y2038_problem(rootfs, native_sysroot)
394
361 def prepare_empty_partition_btrfs(self, rootfs, oe_builddir, 395 def prepare_empty_partition_btrfs(self, rootfs, oe_builddir,
362 native_sysroot): 396 native_sysroot):
363 """ 397 """
@@ -419,3 +453,37 @@ class Partition():
419 453
420 mkswap_cmd = "mkswap %s -U %s %s" % (label_str, self.fsuuid, path) 454 mkswap_cmd = "mkswap %s -U %s %s" % (label_str, self.fsuuid, path)
421 exec_native_cmd(mkswap_cmd, native_sysroot) 455 exec_native_cmd(mkswap_cmd, native_sysroot)
456
457 def check_for_Y2038_problem(self, rootfs, native_sysroot):
458 """
459 Check if the filesystem is affected by the Y2038 problem
460 (Y2038 problem = 32 bit time_t overflow in January 2038)
461 """
462 def get_err_str(part):
463 err = "The {} filesystem {} has no Y2038 support."
464 if part.mountpoint:
465 args = [part.fstype, "mounted at %s" % part.mountpoint]
466 elif part.label:
467 args = [part.fstype, "labeled '%s'" % part.label]
468 elif part.part_name:
469 args = [part.fstype, "in partition '%s'" % part.part_name]
470 else:
471 args = [part.fstype, "in partition %s" % part.num]
472 return err.format(*args)
473
474 # ext2 and ext3 are always affected by the Y2038 problem
475 if self.fstype in ["ext2", "ext3"]:
476 logger.warn(get_err_str(self))
477 return
478
479 ret, out = exec_native_cmd("dumpe2fs %s" % rootfs, native_sysroot)
480
481 # if ext4 is affected by the Y2038 problem depends on the inode size
482 for line in out.splitlines():
483 if line.startswith("Inode size:"):
484 size = int(line.split(":")[1].strip())
485 if size < 256:
486 logger.warn("%s Inodes (of size %d) are too small." %
487 (get_err_str(self), size))
488 break
489
diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py
index 55db826e93..ea709e8c54 100644
--- a/scripts/lib/wic/plugins/imager/direct.py
+++ b/scripts/lib/wic/plugins/imager/direct.py
@@ -54,15 +54,16 @@ class DirectPlugin(ImagerPlugin):
54 self.native_sysroot = native_sysroot 54 self.native_sysroot = native_sysroot
55 self.oe_builddir = oe_builddir 55 self.oe_builddir = oe_builddir
56 56
57 self.debug = options.debug
57 self.outdir = options.outdir 58 self.outdir = options.outdir
58 self.compressor = options.compressor 59 self.compressor = options.compressor
59 self.bmap = options.bmap 60 self.bmap = options.bmap
60 self.no_fstab_update = options.no_fstab_update 61 self.no_fstab_update = options.no_fstab_update
61 self.original_fstab = None 62 self.updated_fstab_path = None
62 63
63 self.name = "%s-%s" % (os.path.splitext(os.path.basename(wks_file))[0], 64 self.name = "%s-%s" % (os.path.splitext(os.path.basename(wks_file))[0],
64 strftime("%Y%m%d%H%M")) 65 strftime("%Y%m%d%H%M"))
65 self.workdir = tempfile.mkdtemp(dir=self.outdir, prefix='tmp.wic.') 66 self.workdir = self.setup_workdir(options.workdir)
66 self._image = None 67 self._image = None
67 self.ptable_format = self.ks.bootloader.ptable 68 self.ptable_format = self.ks.bootloader.ptable
68 self.parts = self.ks.partitions 69 self.parts = self.ks.partitions
@@ -78,6 +79,16 @@ class DirectPlugin(ImagerPlugin):
78 self._image = PartitionedImage(image_path, self.ptable_format, 79 self._image = PartitionedImage(image_path, self.ptable_format,
79 self.parts, self.native_sysroot) 80 self.parts, self.native_sysroot)
80 81
82 def setup_workdir(self, workdir):
83 if workdir:
84 if os.path.exists(workdir):
85 raise WicError("Internal workdir '%s' specified in wic arguments already exists!" % (workdir))
86
87 os.makedirs(workdir)
88 return workdir
89 else:
90 return tempfile.mkdtemp(dir=self.outdir, prefix='tmp.wic.')
91
81 def do_create(self): 92 def do_create(self):
82 """ 93 """
83 Plugin entry point. 94 Plugin entry point.
@@ -90,11 +101,8 @@ class DirectPlugin(ImagerPlugin):
90 finally: 101 finally:
91 self.cleanup() 102 self.cleanup()
92 103
93 def _write_fstab(self, image_rootfs): 104 def update_fstab(self, image_rootfs):
94 """overriden to generate fstab (temporarily) in rootfs. This is called 105 """Assume partition order same as in wks"""
95 from _create, make sure it doesn't get called from
96 BaseImage.create()
97 """
98 if not image_rootfs: 106 if not image_rootfs:
99 return 107 return
100 108
@@ -104,18 +112,9 @@ class DirectPlugin(ImagerPlugin):
104 112
105 with open(fstab_path) as fstab: 113 with open(fstab_path) as fstab:
106 fstab_lines = fstab.readlines() 114 fstab_lines = fstab.readlines()
107 self.original_fstab = fstab_lines.copy()
108
109 if self._update_fstab(fstab_lines, self.parts):
110 with open(fstab_path, "w") as fstab:
111 fstab.writelines(fstab_lines)
112 else:
113 self.original_fstab = None
114 115
115 def _update_fstab(self, fstab_lines, parts):
116 """Assume partition order same as in wks"""
117 updated = False 116 updated = False
118 for part in parts: 117 for part in self.parts:
119 if not part.realnum or not part.mountpoint \ 118 if not part.realnum or not part.mountpoint \
120 or part.mountpoint == "/": 119 or part.mountpoint == "/":
121 continue 120 continue
@@ -144,7 +143,10 @@ class DirectPlugin(ImagerPlugin):
144 fstab_lines.append(line) 143 fstab_lines.append(line)
145 updated = True 144 updated = True
146 145
147 return updated 146 if updated:
147 self.updated_fstab_path = os.path.join(self.workdir, "fstab")
148 with open(self.updated_fstab_path, "w") as f:
149 f.writelines(fstab_lines)
148 150
149 def _full_path(self, path, name, extention): 151 def _full_path(self, path, name, extention):
150 """ Construct full file path to a file we generate. """ 152 """ Construct full file path to a file we generate. """
@@ -160,7 +162,7 @@ class DirectPlugin(ImagerPlugin):
160 a partitioned image. 162 a partitioned image.
161 """ 163 """
162 if not self.no_fstab_update: 164 if not self.no_fstab_update:
163 self._write_fstab(self.rootfs_dir.get("ROOTFS_DIR")) 165 self.update_fstab(self.rootfs_dir.get("ROOTFS_DIR"))
164 166
165 for part in self.parts: 167 for part in self.parts:
166 # get rootfs size from bitbake variable if it's not set in .ks file 168 # get rootfs size from bitbake variable if it's not set in .ks file
@@ -273,14 +275,9 @@ class DirectPlugin(ImagerPlugin):
273 if os.path.isfile(path): 275 if os.path.isfile(path):
274 shutil.move(path, os.path.join(self.outdir, fname)) 276 shutil.move(path, os.path.join(self.outdir, fname))
275 277
276 #Restore original fstab 278 # remove work directory when it is not in debugging mode
277 if self.original_fstab: 279 if not self.debug:
278 fstab_path = self.rootfs_dir.get("ROOTFS_DIR") + "/etc/fstab" 280 shutil.rmtree(self.workdir, ignore_errors=True)
279 with open(fstab_path, "w") as fstab:
280 fstab.writelines(self.original_fstab)
281
282 # remove work directory
283 shutil.rmtree(self.workdir, ignore_errors=True)
284 281
285# Overhead of the MBR partitioning scheme (just one sector) 282# Overhead of the MBR partitioning scheme (just one sector)
286MBR_OVERHEAD = 1 283MBR_OVERHEAD = 1
@@ -343,6 +340,13 @@ class PartitionedImage():
343 part.fsuuid = '0x' + str(uuid.uuid4())[:8].upper() 340 part.fsuuid = '0x' + str(uuid.uuid4())[:8].upper()
344 else: 341 else:
345 part.fsuuid = str(uuid.uuid4()) 342 part.fsuuid = str(uuid.uuid4())
343 else:
344 #make sure the fsuuid for vfat/msdos align with format 0xYYYYYYYY
345 if part.fstype == 'vfat' or part.fstype == 'msdos':
346 if part.fsuuid.upper().startswith("0X"):
347 part.fsuuid = '0x' + part.fsuuid.upper()[2:].rjust(8,"0")
348 else:
349 part.fsuuid = '0x' + part.fsuuid.upper().rjust(8,"0")
346 350
347 def prepare(self, imager): 351 def prepare(self, imager):
348 """Prepare an image. Call prepare method of all image partitions.""" 352 """Prepare an image. Call prepare method of all image partitions."""
@@ -351,7 +355,8 @@ class PartitionedImage():
351 # sizes before we can add them and do the layout. 355 # sizes before we can add them and do the layout.
352 part.prepare(imager, imager.workdir, imager.oe_builddir, 356 part.prepare(imager, imager.workdir, imager.oe_builddir,
353 imager.rootfs_dir, imager.bootimg_dir, 357 imager.rootfs_dir, imager.bootimg_dir,
354 imager.kernel_dir, imager.native_sysroot) 358 imager.kernel_dir, imager.native_sysroot,
359 imager.updated_fstab_path)
355 360
356 # Converting kB to sectors for parted 361 # Converting kB to sectors for parted
357 part.size_sec = part.disk_size * 1024 // self.sector_size 362 part.size_sec = part.disk_size * 1024 // self.sector_size
diff --git a/scripts/lib/wic/plugins/source/rootfs.py b/scripts/lib/wic/plugins/source/rootfs.py
index f1db83f8a1..96d940a91d 100644
--- a/scripts/lib/wic/plugins/source/rootfs.py
+++ b/scripts/lib/wic/plugins/source/rootfs.py
@@ -94,6 +94,7 @@ class RootfsPlugin(SourcePlugin):
94 "it is not a valid path, exiting" % part.rootfs_dir) 94 "it is not a valid path, exiting" % part.rootfs_dir)
95 95
96 part.rootfs_dir = cls.__get_rootfs_dir(rootfs_dir) 96 part.rootfs_dir = cls.__get_rootfs_dir(rootfs_dir)
97 part.has_fstab = os.path.exists(os.path.join(part.rootfs_dir, "etc/fstab"))
97 pseudo_dir = os.path.join(part.rootfs_dir, "../pseudo") 98 pseudo_dir = os.path.join(part.rootfs_dir, "../pseudo")
98 if not os.path.lexists(pseudo_dir): 99 if not os.path.lexists(pseudo_dir):
99 logger.warn("%s folder does not exist. " 100 logger.warn("%s folder does not exist. "
@@ -103,9 +104,9 @@ class RootfsPlugin(SourcePlugin):
103 new_rootfs = None 104 new_rootfs = None
104 new_pseudo = None 105 new_pseudo = None
105 # Handle excluded paths. 106 # Handle excluded paths.
106 if part.exclude_path or part.include_path or part.change_directory: 107 if part.exclude_path or part.include_path or part.change_directory or part.update_fstab_in_rootfs:
107 # We need a new rootfs directory we can delete files from. Copy to 108 # We need a new rootfs directory we can safely modify without
108 # workdir. 109 # interfering with other tasks. Copy to workdir.
109 new_rootfs = os.path.realpath(os.path.join(cr_workdir, "rootfs%d" % part.lineno)) 110 new_rootfs = os.path.realpath(os.path.join(cr_workdir, "rootfs%d" % part.lineno))
110 111
111 if os.path.lexists(new_rootfs): 112 if os.path.lexists(new_rootfs):
@@ -199,17 +200,33 @@ class RootfsPlugin(SourcePlugin):
199 if not os.path.lexists(full_path): 200 if not os.path.lexists(full_path):
200 continue 201 continue
201 202
203 if new_pseudo:
204 pseudo = cls.__get_pseudo(native_sysroot, new_rootfs, new_pseudo)
205 else:
206 pseudo = None
202 if path.endswith(os.sep): 207 if path.endswith(os.sep):
203 # Delete content only. 208 # Delete content only.
204 for entry in os.listdir(full_path): 209 for entry in os.listdir(full_path):
205 full_entry = os.path.join(full_path, entry) 210 full_entry = os.path.join(full_path, entry)
206 if os.path.isdir(full_entry) and not os.path.islink(full_entry): 211 rm_cmd = "rm -rf %s" % (full_entry)
207 shutil.rmtree(full_entry) 212 exec_native_cmd(rm_cmd, native_sysroot, pseudo)
208 else:
209 os.remove(full_entry)
210 else: 213 else:
211 # Delete whole directory. 214 # Delete whole directory.
212 shutil.rmtree(full_path) 215 rm_cmd = "rm -rf %s" % (full_path)
216 exec_native_cmd(rm_cmd, native_sysroot, pseudo)
217
218 # Update part.has_fstab here as fstab may have been added or
219 # removed by the above modifications.
220 part.has_fstab = os.path.exists(os.path.join(new_rootfs, "etc/fstab"))
221 if part.update_fstab_in_rootfs and part.has_fstab:
222 fstab_path = os.path.join(new_rootfs, "etc/fstab")
223 # Assume that fstab should always be owned by root with fixed permissions
224 install_cmd = "install -m 0644 %s %s" % (part.updated_fstab_path, fstab_path)
225 if new_pseudo:
226 pseudo = cls.__get_pseudo(native_sysroot, new_rootfs, new_pseudo)
227 else:
228 pseudo = None
229 exec_native_cmd(install_cmd, native_sysroot, pseudo)
213 230
214 part.prepare_rootfs(cr_workdir, oe_builddir, 231 part.prepare_rootfs(cr_workdir, oe_builddir,
215 new_rootfs or part.rootfs_dir, native_sysroot, 232 new_rootfs or part.rootfs_dir, native_sysroot,