summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre-Loup GOSSE <pierre-loup.gosse@smile.fr>2025-09-03 16:45:27 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2025-09-08 18:02:39 +0100
commit21d98bd960132033b2bbd460a40274d40ea28b60 (patch)
tree6ced7d142b61b8adfc270b85c9c332190c025d4a
parent857bb50a3533f897290add64706b98b72a0bded2 (diff)
downloadpoky-21d98bd960132033b2bbd460a40274d40ea28b60.tar.gz
wic: add --extra-partition-space option to set unused space
By default, the content of the partition is filled by the filesystem without leaving any unused free space. The --extra-space flag adds extra space to the filesystem size, not to the partition. Unused free space after the filesystem can be useful for some cases, such as encrypting a partition at runtime. With --extra-partition-space 32M, we ensure that the last 32M of the partition is unused: this space does not contain filesystem data and can store the LUKS2 header. The implementation sets a difference between the partition and filesystem size: - With --fixed-size, the extra part space is removed from the filesystem size. - Otherwise (with or without --size flag), the extra part space is added to the partition size. (From OE-Core rev: 22fd1702aedf40257aa53963b62b5ef1bbd2818a) Signed-off-by: Pierre-Loup GOSSE <pierre-loup.gosse@smile.fr> CC: Alexander Kanavin <alex.kanavin@gmail.com> CC: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com> Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/lib/oeqa/selftest/cases/wic.py49
-rw-r--r--scripts/lib/wic/help.py8
-rw-r--r--scripts/lib/wic/ksparser.py3
-rw-r--r--scripts/lib/wic/partition.py34
4 files changed, 79 insertions, 15 deletions
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py
index 44442e402d..c244c9f188 100644
--- a/meta/lib/oeqa/selftest/cases/wic.py
+++ b/meta/lib/oeqa/selftest/cases/wic.py
@@ -1166,7 +1166,7 @@ run_wic_cmd() {
1166 1166
1167 return wkspath 1167 return wkspath
1168 1168
1169 def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False): 1169 def _get_wic(self, wkspath, ignore_status=False):
1170 p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir), 1170 p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir),
1171 ignore_status=ignore_status) 1171 ignore_status=ignore_status)
1172 1172
@@ -1180,7 +1180,13 @@ run_wic_cmd() {
1180 if not wicout: 1180 if not wicout:
1181 return (p, None) 1181 return (p, None)
1182 1182
1183 wicimg = wicout[0] 1183 return (p, wicout[0])
1184
1185 def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False):
1186 p, wicimg = self._get_wic(wkspath, ignore_status)
1187
1188 if wicimg is None:
1189 return (p, None)
1184 1190
1185 if not native_sysroot: 1191 if not native_sysroot:
1186 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 1192 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
@@ -1320,6 +1326,45 @@ run_wic_cmd() {
1320 size = int(size[:-3]) 1326 size = int(size[:-3])
1321 self.assertGreaterEqual(size, 204800) 1327 self.assertGreaterEqual(size, 204800)
1322 1328
1329 def test_extra_partition_space(self):
1330 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
1331
1332 with NamedTemporaryFile("w", suffix=".wks") as tempf:
1333 tempf.write("bootloader --ptable gpt\n" \
1334 "part --ondisk hda --size 10M --extra-partition-space 10M --fstype=ext4\n" \
1335 "part --ondisk hda --fixed-size 20M --extra-partition-space 10M --fstype=ext4\n" \
1336 "part --source rootfs --ondisk hda --extra-partition-space 10M --fstype=ext4\n" \
1337 "part --source rootfs --ondisk hda --fixed-size 200M --extra-partition-space 10M --fstype=ext4\n")
1338 tempf.flush()
1339
1340 _, wicimg = self._get_wic(tempf.name)
1341
1342 res = runCmd("parted -m %s unit b p" % wicimg,
1343 native_sysroot=native_sysroot, stderr=subprocess.PIPE)
1344
1345 # parse parted output which looks like this:
1346 # BYT;\n
1347 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
1348 # 1:0.00MiB:200MiB:200MiB:ext4::;\n
1349 partlns = res.output.splitlines()[2:]
1350
1351 self.assertEqual(4, len(partlns))
1352
1353 # Test for each partitions that the extra part space exists
1354 for part in range(0, len(partlns)):
1355 part_file = os.path.join(self.resultdir, "selftest_img.part%d" % (part + 1))
1356 partln = partlns[part].split(":")
1357 self.assertEqual(7, len(partln))
1358 self.assertRegex(partln[3], r'^[0-9]+B$')
1359 part_size = int(partln[3].rstrip("B"))
1360 start = int(partln[1].rstrip("B")) / 512
1361 length = part_size / 512
1362 runCmd("dd if=%s of=%s skip=%d count=%d" %
1363 (wicimg, part_file, start, length))
1364 res = runCmd("dumpe2fs %s -h | grep \"^Block count\"" % part_file)
1365 fs_size = int(res.output.split(":")[1].strip()) * 1024
1366 self.assertLessEqual(fs_size + 10485760, part_size, "part file: %s" % part_file)
1367
1323 # TODO this test could also work on aarch64 1368 # TODO this test could also work on aarch64
1324 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1369 @skipIfNotArch(['i586', 'i686', 'x86_64'])
1325 @OETestTag("runqemu") 1370 @OETestTag("runqemu")
diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
index 2e3061f343..800c0abf0f 100644
--- a/scripts/lib/wic/help.py
+++ b/scripts/lib/wic/help.py
@@ -1020,6 +1020,14 @@ DESCRIPTION
1020 By default, 10MB. This option cannot be used 1020 By default, 10MB. This option cannot be used
1021 with --fixed-size option. 1021 with --fixed-size option.
1022 1022
1023 --extra-partition-space: This option is specific to wic. It adds extra
1024 empty space after the space filled by the
1025 filesystem. With --fixed-size, the extra
1026 partition space is removed from the filesystem
1027 size. Otherwise (with or without --size flag),
1028 the extra partition space is added to the final
1029 paritition size. The default value is 0MB.
1030
1023 --overhead-factor: This option is specific to wic. The 1031 --overhead-factor: This option is specific to wic. The
1024 size of the partition is multiplied by 1032 size of the partition is multiplied by
1025 this factor. It has to be greater than or 1033 this factor. It has to be greater than or
diff --git a/scripts/lib/wic/ksparser.py b/scripts/lib/wic/ksparser.py
index 596b6e8e7e..a1aaf1b4b3 100644
--- a/scripts/lib/wic/ksparser.py
+++ b/scripts/lib/wic/ksparser.py
@@ -154,6 +154,7 @@ class KickStart():
154 part.add_argument('--include-path', nargs='+', action='append') 154 part.add_argument('--include-path', nargs='+', action='append')
155 part.add_argument('--change-directory') 155 part.add_argument('--change-directory')
156 part.add_argument("--extra-space", type=sizetype("M")) 156 part.add_argument("--extra-space", type=sizetype("M"))
157 part.add_argument('--extra-partition-space', type=sizetype("M"))
157 part.add_argument('--fsoptions', dest='fsopts') 158 part.add_argument('--fsoptions', dest='fsopts')
158 part.add_argument('--fspassno', dest='fspassno') 159 part.add_argument('--fspassno', dest='fspassno')
159 part.add_argument('--fstype', default='vfat', 160 part.add_argument('--fstype', default='vfat',
@@ -259,6 +260,8 @@ class KickStart():
259 err = "%s:%d: Must set the label with --label" \ 260 err = "%s:%d: Must set the label with --label" \
260 % (confpath, lineno) 261 % (confpath, lineno)
261 raise KickStartError(err) 262 raise KickStartError(err)
263 if not parsed.extra_partition_space:
264 parsed.extra_partition_space = 0
262 # using ArgumentParser one cannot easily tell if option 265 # using ArgumentParser one cannot easily tell if option
263 # was passed as argument, if said option has a default 266 # was passed as argument, if said option has a default
264 # value; --overhead-factor/--extra-space cannot be used 267 # value; --overhead-factor/--extra-space cannot be used
diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
index b34691d313..d358aabbd6 100644
--- a/scripts/lib/wic/partition.py
+++ b/scripts/lib/wic/partition.py
@@ -29,6 +29,7 @@ class Partition():
29 self.disk = args.disk 29 self.disk = args.disk
30 self.device = None 30 self.device = None
31 self.extra_space = args.extra_space 31 self.extra_space = args.extra_space
32 self.extra_partition_space = args.extra_partition_space
32 self.exclude_path = args.exclude_path 33 self.exclude_path = args.exclude_path
33 self.include_path = args.include_path 34 self.include_path = args.include_path
34 self.change_directory = args.change_directory 35 self.change_directory = args.change_directory
@@ -91,13 +92,12 @@ class Partition():
91 def get_rootfs_size(self, actual_rootfs_size=0): 92 def get_rootfs_size(self, actual_rootfs_size=0):
92 """ 93 """
93 Calculate the required size of rootfs taking into consideration 94 Calculate the required size of rootfs taking into consideration
94 --size/--fixed-size flags as well as overhead and extra space, as 95 --size/--fixed-size and --extra-partition-space flags as well as overhead
95 specified in kickstart file. Raises an error if the 96 and extra space, as specified in kickstart file. Raises an error
96 `actual_rootfs_size` is larger than fixed-size rootfs. 97 if the `actual_rootfs_size` is larger than fixed-size rootfs.
97
98 """ 98 """
99 if self.fixed_size: 99 if self.fixed_size:
100 rootfs_size = self.fixed_size 100 rootfs_size = self.fixed_size - self.extra_partition_space
101 if actual_rootfs_size > rootfs_size: 101 if actual_rootfs_size > rootfs_size:
102 raise WicError("Actual rootfs size (%d kB) is larger than " 102 raise WicError("Actual rootfs size (%d kB) is larger than "
103 "allowed size %d kB" % 103 "allowed size %d kB" %
@@ -119,10 +119,18 @@ class Partition():
119 def disk_size(self): 119 def disk_size(self):
120 """ 120 """
121 Obtain on-disk size of partition taking into consideration 121 Obtain on-disk size of partition taking into consideration
122 --size/--fixed-size options. 122 --size/--fixed-size and --extra-partition-space options.
123
124 """
125 return self.fixed_size if self.fixed_size else self.size + self.extra_partition_space
123 126
127 @property
128 def fs_size(self):
129 """
130 Obtain on-disk size of filesystem inside the partition taking into
131 consideration --size/--fixed-size and --extra-partition-space options.
124 """ 132 """
125 return self.fixed_size if self.fixed_size else self.size 133 return self.fixed_size - self.extra_partition_space if self.fixed_size else self.size
126 134
127 def prepare(self, creator, cr_workdir, oe_builddir, rootfs_dir, 135 def prepare(self, creator, cr_workdir, oe_builddir, rootfs_dir,
128 bootimg_dir, kernel_dir, native_sysroot, updated_fstab_path): 136 bootimg_dir, kernel_dir, native_sysroot, updated_fstab_path):
@@ -202,10 +210,10 @@ class Partition():
202 "This a bug in source plugin %s and needs to be fixed." % 210 "This a bug in source plugin %s and needs to be fixed." %
203 (self.mountpoint, self.source)) 211 (self.mountpoint, self.source))
204 212
205 if self.fixed_size and self.size > self.fixed_size: 213 if self.fixed_size and self.size + self.extra_partition_space > self.fixed_size:
206 raise WicError("File system image of partition %s is " 214 raise WicError("File system image of partition %s is "
207 "larger (%d kB) than its allowed size %d kB" % 215 "larger (%d kB + %d kB extra part space) than its allowed size %d kB" %
208 (self.mountpoint, self.size, self.fixed_size)) 216 (self.mountpoint, self.size, self.extra_partition_space, self.fixed_size))
209 217
210 def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir, 218 def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir,
211 native_sysroot, real_rootfs = True, pseudo_dir = None): 219 native_sysroot, real_rootfs = True, pseudo_dir = None):
@@ -440,7 +448,7 @@ class Partition():
440 """ 448 """
441 Prepare an empty ext2/3/4 partition. 449 Prepare an empty ext2/3/4 partition.
442 """ 450 """
443 size = self.disk_size 451 size = self.fs_size
444 with open(rootfs, 'w') as sparse: 452 with open(rootfs, 'w') as sparse:
445 os.ftruncate(sparse.fileno(), size * 1024) 453 os.ftruncate(sparse.fileno(), size * 1024)
446 454
@@ -464,7 +472,7 @@ class Partition():
464 """ 472 """
465 Prepare an empty btrfs partition. 473 Prepare an empty btrfs partition.
466 """ 474 """
467 size = self.disk_size 475 size = self.fs_size
468 with open(rootfs, 'w') as sparse: 476 with open(rootfs, 'w') as sparse:
469 os.ftruncate(sparse.fileno(), size * 1024) 477 os.ftruncate(sparse.fileno(), size * 1024)
470 478
@@ -482,7 +490,7 @@ class Partition():
482 """ 490 """
483 Prepare an empty vfat partition. 491 Prepare an empty vfat partition.
484 """ 492 """
485 blocks = self.disk_size 493 blocks = self.fs_size
486 494
487 label_str = "-n boot" 495 label_str = "-n boot"
488 if self.label: 496 if self.label: