summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Watt <JPEWhacker@gmail.com>2020-06-02 08:42:05 -0500
committerRichard Purdie <richard.purdie@linuxfoundation.org>2020-06-04 13:27:32 +0100
commitba9be4bfa58efc73f1485eb5dc0dff0d23716821 (patch)
treeaf7a989c4e2caf3c08c2b7f77be5679c533966ca
parent6b4299df5d86ba079e7525ad09def756359b9502 (diff)
downloadpoky-ba9be4bfa58efc73f1485eb5dc0dff0d23716821.tar.gz
wic: Add --offset argument for partitions
Add support for an --offset argument when defining a partition. Many SoCs require that boot partitions be located at specific offsets. Prior to this argument, most WKS files were using the --align attribute to specify the location of these fixed partitions but this is not ideal because in the event that the partition couldn't be placed in the specified location, wic would move it to the next sector with that alignment, often preventing the device from booting. Unlike the --align argument, wic will fail if a partition cannot be placed at the exact offset specified with --offset. Changes in V2: * Fixed a small typo that prevented test_fixed_size_error from passing (From OE-Core rev: 467f84e12b96bc977d57575023517dd6f8ef7f29) Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/lib/oeqa/selftest/cases/wic.py118
-rw-r--r--scripts/lib/wic/ksparser.py46
-rw-r--r--scripts/lib/wic/partition.py1
-rw-r--r--scripts/lib/wic/plugins/imager/direct.py15
4 files changed, 135 insertions, 45 deletions
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py
index c8765e5330..9e7be6168e 100644
--- a/meta/lib/oeqa/selftest/cases/wic.py
+++ b/meta/lib/oeqa/selftest/cases/wic.py
@@ -790,41 +790,50 @@ class Wic2(WicTestCase):
790 tempf.write("part " \ 790 tempf.write("part " \
791 "--source rootfs --ondisk hda --align 4 --fixed-size %d " 791 "--source rootfs --ondisk hda --align 4 --fixed-size %d "
792 "--fstype=ext4\n" % size) 792 "--fstype=ext4\n" % size)
793 wksname = os.path.splitext(os.path.basename(wkspath))[0]
794 793
795 return wkspath, wksname 794 return wkspath
796 795
797 def test_fixed_size(self): 796 def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False):
798 """ 797 p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir),
799 Test creation of a simple image with partition size controlled through 798 ignore_status=ignore_status)
800 --fixed-size flag 799
801 """ 800 if p.status:
802 wkspath, wksname = Wic2._make_fixed_size_wks(200) 801 return (p, None)
802
803 wksname = os.path.splitext(os.path.basename(wkspath))[0]
803 804
804 runCmd("wic create %s -e core-image-minimal -o %s" \
805 % (wkspath, self.resultdir))
806 os.remove(wkspath)
807 wicout = glob(self.resultdir + "%s-*direct" % wksname) 805 wicout = glob(self.resultdir + "%s-*direct" % wksname)
808 self.assertEqual(1, len(wicout)) 806
807 if not wicout:
808 return (p, None)
809 809
810 wicimg = wicout[0] 810 wicimg = wicout[0]
811 811
812 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 812 if not native_sysroot:
813 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
813 814
814 # verify partition size with wic 815 # verify partition size with wic
815 res = runCmd("parted -m %s unit mib p 2>/dev/null" % wicimg, 816 res = runCmd("parted -m %s unit kib p 2>/dev/null" % wicimg,
816 native_sysroot=native_sysroot) 817 native_sysroot=native_sysroot)
817 818
818 # parse parted output which looks like this: 819 # parse parted output which looks like this:
819 # BYT;\n 820 # BYT;\n
820 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n 821 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
821 # 1:0.00MiB:200MiB:200MiB:ext4::;\n 822 # 1:0.00MiB:200MiB:200MiB:ext4::;\n
822 partlns = res.output.splitlines()[2:] 823 return (p, res.output.splitlines()[2:])
823 824
824 self.assertEqual(1, len(partlns), 825 def test_fixed_size(self):
825 msg="Partition list '%s'" % res.output) 826 """
826 self.assertEqual("1:0.00MiB:200MiB:200MiB:ext4::;", partlns[0], 827 Test creation of a simple image with partition size controlled through
827 msg="Partition list '%s'" % res.output) 828 --fixed-size flag
829 """
830 wkspath = Wic2._make_fixed_size_wks(200)
831 _, partlns = self._get_wic_partitions(wkspath)
832 os.remove(wkspath)
833
834 self.assertEqual(partlns, [
835 "1:4.00kiB:204804kiB:204800kiB:ext4::;",
836 ])
828 837
829 def test_fixed_size_error(self): 838 def test_fixed_size_error(self):
830 """ 839 """
@@ -832,13 +841,72 @@ class Wic2(WicTestCase):
832 --fixed-size flag. The size of partition is intentionally set to 1MiB 841 --fixed-size flag. The size of partition is intentionally set to 1MiB
833 in order to trigger an error in wic. 842 in order to trigger an error in wic.
834 """ 843 """
835 wkspath, wksname = Wic2._make_fixed_size_wks(1) 844 wkspath = Wic2._make_fixed_size_wks(1)
836 845 p, _ = self._get_wic_partitions(wkspath, ignore_status=True)
837 self.assertEqual(1, runCmd("wic create %s -e core-image-minimal -o %s" \
838 % (wkspath, self.resultdir), ignore_status=True).status)
839 os.remove(wkspath) 846 os.remove(wkspath)
840 wicout = glob(self.resultdir + "%s-*direct" % wksname) 847
841 self.assertEqual(0, len(wicout)) 848 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
849
850 def test_offset(self):
851 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
852
853 with NamedTemporaryFile("w", suffix=".wks") as tempf:
854 # Test that partitions are placed at the correct offsets, default KB
855 tempf.write("bootloader --ptable gpt\n" \
856 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \
857 "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n")
858 tempf.flush()
859
860 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
861 self.assertEqual(partlns, [
862 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
863 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
864 ])
865
866 with NamedTemporaryFile("w", suffix=".wks") as tempf:
867 # Test that partitions are placed at the correct offsets, same with explicit KB
868 tempf.write("bootloader --ptable gpt\n" \
869 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \
870 "part /bar --ondisk hda --offset 102432K --fixed-size 100M --fstype=ext4\n")
871 tempf.flush()
872
873 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
874 self.assertEqual(partlns, [
875 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
876 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
877 ])
878
879 with NamedTemporaryFile("w", suffix=".wks") as tempf:
880 # Test that partitions are placed at the correct offsets using MB
881 tempf.write("bootloader --ptable gpt\n" \
882 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \
883 "part /bar --ondisk hda --offset 101M --fixed-size 100M --fstype=ext4\n")
884 tempf.flush()
885
886 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
887 self.assertEqual(partlns, [
888 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
889 "2:103424kiB:205824kiB:102400kiB:ext4:primary:;",
890 ])
891
892 with NamedTemporaryFile("w", suffix=".wks") as tempf:
893 # Test that image creation fails if the partitions would overlap
894 tempf.write("bootloader --ptable gpt\n" \
895 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \
896 "part /bar --ondisk hda --offset 102431 --fixed-size 100M --fstype=ext4\n")
897 tempf.flush()
898
899 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True)
900 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
901
902 with NamedTemporaryFile("w", suffix=".wks") as tempf:
903 # Test that partitions are not allowed to overlap with the booloader
904 tempf.write("bootloader --ptable gpt\n" \
905 "part / --source rootfs --ondisk hda --offset 8 --fixed-size 100M --fstype=ext4\n")
906 tempf.flush()
907
908 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True)
909 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
842 910
843 @only_for_arch(['i586', 'i686', 'x86_64']) 911 @only_for_arch(['i586', 'i686', 'x86_64'])
844 def test_rawcopy_plugin_qemu(self): 912 def test_rawcopy_plugin_qemu(self):
diff --git a/scripts/lib/wic/ksparser.py b/scripts/lib/wic/ksparser.py
index b8befe78e3..05ae292ef5 100644
--- a/scripts/lib/wic/ksparser.py
+++ b/scripts/lib/wic/ksparser.py
@@ -51,26 +51,31 @@ class KickStartParser(ArgumentParser):
51 def error(self, message): 51 def error(self, message):
52 raise ArgumentError(None, message) 52 raise ArgumentError(None, message)
53 53
54def sizetype(arg): 54def sizetype(default):
55 """ 55 def f(arg):
56 Custom type for ArgumentParser 56 """
57 Converts size string in <num>[K|k|M|G] format into the integer value 57 Custom type for ArgumentParser
58 """ 58 Converts size string in <num>[K|k|M|G] format into the integer value
59 if arg.isdigit(): 59 """
60 return int(arg) * 1024 60 try:
61 suffix = default
62 size = int(arg)
63 except ValueError:
64 try:
65 suffix = arg[-1:]
66 size = int(arg[:-1])
67 except ValueError:
68 raise ArgumentTypeError("Invalid size: %r" % arg)
69
70 if suffix == "k" or suffix == "K":
71 return size
72 if suffix == "M":
73 return size * 1024
74 if suffix == "G":
75 return size * 1024 * 1024
61 76
62 if not arg[:-1].isdigit():
63 raise ArgumentTypeError("Invalid size: %r" % arg) 77 raise ArgumentTypeError("Invalid size: %r" % arg)
64 78 return f
65 size = int(arg[:-1])
66 if arg.endswith("k") or arg.endswith("K"):
67 return size
68 if arg.endswith("M"):
69 return size * 1024
70 if arg.endswith("G"):
71 return size * 1024 * 1024
72
73 raise ArgumentTypeError("Invalid size: %r" % arg)
74 79
75def overheadtype(arg): 80def overheadtype(arg):
76 """ 81 """
@@ -136,6 +141,7 @@ class KickStart():
136 part.add_argument('mountpoint', nargs='?') 141 part.add_argument('mountpoint', nargs='?')
137 part.add_argument('--active', action='store_true') 142 part.add_argument('--active', action='store_true')
138 part.add_argument('--align', type=int) 143 part.add_argument('--align', type=int)
144 part.add_argument('--offset', type=sizetype("K"))
139 part.add_argument('--exclude-path', nargs='+') 145 part.add_argument('--exclude-path', nargs='+')
140 part.add_argument('--include-path', nargs='+', action='append') 146 part.add_argument('--include-path', nargs='+', action='append')
141 part.add_argument('--change-directory') 147 part.add_argument('--change-directory')
@@ -161,8 +167,8 @@ class KickStart():
161 # --error, but since nesting mutually exclusive groups does not work, 167 # --error, but since nesting mutually exclusive groups does not work,
162 # ----extra-space/--overhead-factor are handled later 168 # ----extra-space/--overhead-factor are handled later
163 sizeexcl = part.add_mutually_exclusive_group() 169 sizeexcl = part.add_mutually_exclusive_group()
164 sizeexcl.add_argument('--size', type=sizetype, default=0) 170 sizeexcl.add_argument('--size', type=sizetype("M"), default=0)
165 sizeexcl.add_argument('--fixed-size', type=sizetype, default=0) 171 sizeexcl.add_argument('--fixed-size', type=sizetype("M"), default=0)
166 172
167 part.add_argument('--source') 173 part.add_argument('--source')
168 part.add_argument('--sourceparams') 174 part.add_argument('--sourceparams')
diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
index 7d9dd616a6..85eb15c8b8 100644
--- a/scripts/lib/wic/partition.py
+++ b/scripts/lib/wic/partition.py
@@ -40,6 +40,7 @@ class Partition():
40 self.mountpoint = args.mountpoint 40 self.mountpoint = args.mountpoint
41 self.no_table = args.no_table 41 self.no_table = args.no_table
42 self.num = None 42 self.num = None
43 self.offset = args.offset
43 self.overhead_factor = args.overhead_factor 44 self.overhead_factor = args.overhead_factor
44 self.part_name = args.part_name 45 self.part_name = args.part_name
45 self.part_type = args.part_type 46 self.part_type = args.part_type
diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py
index 2d06c242b6..1f65a7afe5 100644
--- a/scripts/lib/wic/plugins/imager/direct.py
+++ b/scripts/lib/wic/plugins/imager/direct.py
@@ -428,6 +428,21 @@ class PartitionedImage():
428 # increase the offset so we actually start the partition on right alignment 428 # increase the offset so we actually start the partition on right alignment
429 self.offset += align_sectors 429 self.offset += align_sectors
430 430
431 if part.offset is not None:
432 offset = (part.offset * 1024) // self.sector_size
433
434 if offset * self.sector_size != part.offset * 1024:
435 raise WicError("Could not place %s%s at offset %dK with sector size %d" % (part.disk, self.numpart, part.offset, self.sector_size))
436
437 delta = offset - self.offset
438 if delta < 0:
439 raise WicError("Could not place %s%s at offset %dK: next free sector is %d (delta: %d)" % (part.disk, self.numpart, part.offset, offset, delta))
440
441 logger.debug("Skipping %d sectors to place %s%s at offset %dK",
442 delta, part.disk, self.numpart, part.offset)
443
444 self.offset = offset
445
431 part.start = self.offset 446 part.start = self.offset
432 self.offset += part.size_sec 447 self.offset += part.size_sec
433 448