summaryrefslogtreecommitdiffstats
path: root/scripts/lib/wic
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib/wic')
-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/directdisk-multi-rootfs.wks2
-rw-r--r--scripts/lib/wic/canned-wks/efi-bootdisk.wks.in2
-rw-r--r--scripts/lib/wic/canned-wks/efi-uki-bootdisk.wks.in3
-rw-r--r--scripts/lib/wic/canned-wks/mkefidisk.wks4
-rw-r--r--scripts/lib/wic/canned-wks/mkhybridiso.wks2
-rw-r--r--scripts/lib/wic/canned-wks/sdimage-bootpart.wks2
-rw-r--r--scripts/lib/wic/canned-wks/systemd-bootdisk.wks2
-rw-r--r--scripts/lib/wic/engine.py22
-rw-r--r--scripts/lib/wic/help.py62
-rw-r--r--scripts/lib/wic/ksparser.py30
-rw-r--r--scripts/lib/wic/partition.py94
-rw-r--r--scripts/lib/wic/pluginbase.py2
-rw-r--r--scripts/lib/wic/plugins/imager/direct.py58
-rw-r--r--scripts/lib/wic/plugins/source/bootimg-pcbios.py209
-rw-r--r--scripts/lib/wic/plugins/source/bootimg_biosplusefi.py (renamed from scripts/lib/wic/plugins/source/bootimg-biosplusefi.py)30
-rw-r--r--scripts/lib/wic/plugins/source/bootimg_efi.py (renamed from scripts/lib/wic/plugins/source/bootimg-efi.py)208
-rw-r--r--scripts/lib/wic/plugins/source/bootimg_partition.py (renamed from scripts/lib/wic/plugins/source/bootimg-partition.py)43
-rw-r--r--scripts/lib/wic/plugins/source/bootimg_pcbios.py483
-rw-r--r--scripts/lib/wic/plugins/source/isoimage_isohybrid.py (renamed from scripts/lib/wic/plugins/source/isoimage-isohybrid.py)10
-rw-r--r--scripts/lib/wic/plugins/source/rootfs.py2
22 files changed, 769 insertions, 505 deletions
diff --git a/scripts/lib/wic/canned-wks/common.wks.inc b/scripts/lib/wic/canned-wks/common.wks.inc
index 89880b417b..4a440ddafe 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 --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..cb640056f1 100644
--- a/scripts/lib/wic/canned-wks/directdisk-gpt.wks
+++ b/scripts/lib/wic/canned-wks/directdisk-gpt.wks
@@ -3,7 +3,7 @@
3# can directly dd to boot media. 3# can directly dd to boot media.
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 --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"
diff --git a/scripts/lib/wic/canned-wks/directdisk-multi-rootfs.wks b/scripts/lib/wic/canned-wks/directdisk-multi-rootfs.wks
index f61d941d6d..4fd1999ffb 100644
--- a/scripts/lib/wic/canned-wks/directdisk-multi-rootfs.wks
+++ b/scripts/lib/wic/canned-wks/directdisk-multi-rootfs.wks
@@ -15,7 +15,7 @@
15# 15#
16# - or any combinations of -r and --rootfs command line options 16# - or any combinations of -r and --rootfs command line options
17 17
18part /boot --source bootimg-pcbios --ondisk sda --label boot --active --align 1024 18part /boot --source bootimg_pcbios --ondisk sda --label boot --active --align 1024
19part / --source rootfs --rootfs-dir=rootfs1 --ondisk sda --fstype=ext4 --label platform --align 1024 19part / --source rootfs --rootfs-dir=rootfs1 --ondisk sda --fstype=ext4 --label platform --align 1024
20part /rescue --source rootfs --rootfs-dir=rootfs2 --ondisk sda --fstype=ext4 --label secondary --align 1024 20part /rescue --source rootfs --rootfs-dir=rootfs2 --ondisk sda --fstype=ext4 --label secondary --align 1024
21 21
diff --git a/scripts/lib/wic/canned-wks/efi-bootdisk.wks.in b/scripts/lib/wic/canned-wks/efi-bootdisk.wks.in
index 2fd286ff98..5211972955 100644
--- a/scripts/lib/wic/canned-wks/efi-bootdisk.wks.in
+++ b/scripts/lib/wic/canned-wks/efi-bootdisk.wks.in
@@ -1,3 +1,3 @@
1bootloader --ptable gpt 1bootloader --ptable gpt
2part /boot --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/boot --fstype=vfat --label boot --active --align 1024 --use-uuid --overhead-factor 1.1 2part /boot --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/boot --fstype=vfat --label boot --active --align 1024 --use-uuid --overhead-factor 1.2
3part / --source rootfs --fstype=ext4 --label root --align 1024 --exclude-path boot/ 3part / --source rootfs --fstype=ext4 --label root --align 1024 --exclude-path boot/
diff --git a/scripts/lib/wic/canned-wks/efi-uki-bootdisk.wks.in b/scripts/lib/wic/canned-wks/efi-uki-bootdisk.wks.in
new file mode 100644
index 0000000000..cac0fa32cd
--- /dev/null
+++ b/scripts/lib/wic/canned-wks/efi-uki-bootdisk.wks.in
@@ -0,0 +1,3 @@
1bootloader --ptable gpt --timeout=5
2part /boot --source bootimg_efi --sourceparams="loader=${EFI_PROVIDER}" --label boot --active --align 1024 --use-uuid --part-name="ESP" --part-type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B --overhead-factor=1
3part / --source rootfs --fstype=ext4 --label root --align 1024 --exclude-path boot/
diff --git a/scripts/lib/wic/canned-wks/mkefidisk.wks b/scripts/lib/wic/canned-wks/mkefidisk.wks
index 9f534fe184..16dfe76dfe 100644
--- a/scripts/lib/wic/canned-wks/mkefidisk.wks
+++ b/scripts/lib/wic/canned-wks/mkefidisk.wks
@@ -2,10 +2,10 @@
2# long-description: Creates a partitioned EFI disk image that the user 2# long-description: Creates a partitioned EFI disk image that the user
3# can directly dd to boot media. 3# can directly dd to boot media.
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 --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
11bootloader --ptable gpt --timeout=5 --append="rootfstype=ext4 console=ttyS0,115200 console=tty0" 11bootloader --ptable gpt --timeout=5 --append="rootfstype=ext4 console=${KERNEL_CONSOLE} console=tty0"
diff --git a/scripts/lib/wic/canned-wks/mkhybridiso.wks b/scripts/lib/wic/canned-wks/mkhybridiso.wks
index 48c5ac4791..c3a030e5b4 100644
--- a/scripts/lib/wic/canned-wks/mkhybridiso.wks
+++ b/scripts/lib/wic/canned-wks/mkhybridiso.wks
@@ -2,6 +2,6 @@
2# long-description: Creates an EFI and legacy bootable hybrid ISO image 2# long-description: Creates an EFI and legacy bootable hybrid ISO image
3# which can be used on optical media as well as USB media. 3# which can be used on optical media as well as USB media.
4 4
5part /boot --source isoimage-isohybrid --sourceparams="loader=grub-efi,image_name=HYBRID_ISO_IMG" --ondisk cd --label HYBRIDISO 5part /boot --source isoimage_isohybrid --sourceparams="loader=grub-efi,image_name=HYBRID_ISO_IMG" --ondisk cd --label HYBRIDISO
6 6
7bootloader --timeout=15 --append="" 7bootloader --timeout=15 --append=""
diff --git a/scripts/lib/wic/canned-wks/sdimage-bootpart.wks b/scripts/lib/wic/canned-wks/sdimage-bootpart.wks
index 63bc4dab6a..f9f8044f7d 100644
--- a/scripts/lib/wic/canned-wks/sdimage-bootpart.wks
+++ b/scripts/lib/wic/canned-wks/sdimage-bootpart.wks
@@ -2,5 +2,5 @@
2# long-description: Creates a partitioned SD card image. Boot files 2# long-description: Creates a partitioned SD card image. Boot files
3# are located in the first vfat partition. 3# are located in the first vfat partition.
4 4
5part /boot --source bootimg-partition --ondisk mmcblk0 --fstype=vfat --label boot --active --align 4 --size 16 5part /boot --source bootimg_partition --ondisk mmcblk0 --fstype=vfat --label boot --active --align 4 --size 16
6part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --label root --align 4 6part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --label root --align 4
diff --git a/scripts/lib/wic/canned-wks/systemd-bootdisk.wks b/scripts/lib/wic/canned-wks/systemd-bootdisk.wks
index 95d7b97a60..3fb2c0e35f 100644
--- a/scripts/lib/wic/canned-wks/systemd-bootdisk.wks
+++ b/scripts/lib/wic/canned-wks/systemd-bootdisk.wks
@@ -2,7 +2,7 @@
2# long-description: Creates a partitioned EFI disk image that the user 2# long-description: Creates a partitioned EFI disk image that the user
3# can directly dd to boot media. The selected bootloader is systemd-boot. 3# can directly dd to boot media. The selected bootloader is systemd-boot.
4 4
5part /boot --source bootimg-efi --sourceparams="loader=systemd-boot" --ondisk sda --label msdos --active --align 1024 --use-uuid 5part /boot --source bootimg_efi --sourceparams="loader=systemd-boot" --ondisk sda --label msdos --active --align 1024 --use-uuid
6 6
7part / --source rootfs --ondisk sda --fstype=ext4 --label platform --align 1024 --use-uuid 7part / --source rootfs --ondisk sda --fstype=ext4 --label platform --align 1024 --use-uuid
8 8
diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
index 674ccfc244..b9e60cbe4e 100644
--- a/scripts/lib/wic/engine.py
+++ b/scripts/lib/wic/engine.py
@@ -180,6 +180,8 @@ def wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir,
180 os.makedirs(options.outdir) 180 os.makedirs(options.outdir)
181 181
182 pname = options.imager 182 pname = options.imager
183 # Don't support '-' in plugin names
184 pname = pname.replace("-", "_")
183 plugin_class = PluginMgr.get_plugins('imager').get(pname) 185 plugin_class = PluginMgr.get_plugins('imager').get(pname)
184 if not plugin_class: 186 if not plugin_class:
185 raise WicError('Unknown plugin: %s' % pname) 187 raise WicError('Unknown plugin: %s' % pname)
@@ -232,6 +234,16 @@ class Disk:
232 self._psector_size = None 234 self._psector_size = None
233 self._ptable_format = None 235 self._ptable_format = None
234 236
237 # define sector size
238 sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
239 if sector_size_str is not None:
240 try:
241 self.sector_size = int(sector_size_str)
242 except ValueError:
243 self.sector_size = None
244 else:
245 self.sector_size = None
246
235 # find parted 247 # find parted
236 # read paths from $PATH environment variable 248 # read paths from $PATH environment variable
237 # if it fails, use hardcoded paths 249 # if it fails, use hardcoded paths
@@ -258,7 +270,13 @@ class Disk:
258 def get_partitions(self): 270 def get_partitions(self):
259 if self._partitions is None: 271 if self._partitions is None:
260 self._partitions = OrderedDict() 272 self._partitions = OrderedDict()
261 out = exec_cmd("%s -sm %s unit B print" % (self.parted, self.imagepath)) 273
274 if self.sector_size is not None:
275 out = exec_cmd("export PARTED_SECTOR_SIZE=%d; %s -sm %s unit B print" % \
276 (self.sector_size, self.parted, self.imagepath), True)
277 else:
278 out = exec_cmd("%s -sm %s unit B print" % (self.parted, self.imagepath))
279
262 parttype = namedtuple("Part", "pnum start end size fstype") 280 parttype = namedtuple("Part", "pnum start end size fstype")
263 splitted = out.splitlines() 281 splitted = out.splitlines()
264 # skip over possible errors in exec_cmd output 282 # skip over possible errors in exec_cmd output
@@ -359,7 +377,7 @@ class Disk:
359 Remove files/dirs and their contents from the partition. 377 Remove files/dirs and their contents from the partition.
360 This only applies to ext* partition. 378 This only applies to ext* partition.
361 """ 379 """
362 abs_path = re.sub('\/\/+', '/', path) 380 abs_path = re.sub(r'\/\/+', '/', path)
363 cmd = "{} {} -wR 'rm \"{}\"'".format(self.debugfs, 381 cmd = "{} {} -wR 'rm \"{}\"'".format(self.debugfs,
364 self._get_part_image(pnum), 382 self._get_part_image(pnum),
365 abs_path) 383 abs_path)
diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
index 163535e431..6b49a67de9 100644
--- a/scripts/lib/wic/help.py
+++ b/scripts/lib/wic/help.py
@@ -544,18 +544,18 @@ DESCRIPTION
544 the --source param given to that partition. For example, if the 544 the --source param given to that partition. For example, if the
545 partition is set up like this: 545 partition is set up like this:
546 546
547 part /boot --source bootimg-pcbios ... 547 part /boot --source bootimg_pcbios ...
548 548
549 then the methods defined as class members of the plugin having the 549 then the methods defined as class members of the plugin having the
550 matching bootimg-pcbios .name class member would be used. 550 matching bootimg_pcbios .name class member would be used.
551 551
552 To be more concrete, here's the plugin definition that would match 552 To be more concrete, here's the plugin definition that would match
553 a '--source bootimg-pcbios' usage, along with an example method 553 a '--source bootimg_pcbios' usage, along with an example method
554 that would be called by the wic implementation when it needed to 554 that would be called by the wic implementation when it needed to
555 invoke an implementation-specific partition-preparation function: 555 invoke an implementation-specific partition-preparation function:
556 556
557 class BootimgPcbiosPlugin(SourcePlugin): 557 class BootimgPcbiosPlugin(SourcePlugin):
558 name = 'bootimg-pcbios' 558 name = 'bootimg_pcbios'
559 559
560 @classmethod 560 @classmethod
561 def do_prepare_partition(self, part, ...) 561 def do_prepare_partition(self, part, ...)
@@ -794,7 +794,7 @@ DESCRIPTION
794 794
795 Here is a content of test.wks: 795 Here is a content of test.wks:
796 796
797 part /boot --source bootimg-pcbios --ondisk sda --label boot --active --align 1024 797 part /boot --source bootimg_pcbios --ondisk sda --label boot --active --align 1024
798 part / --source rootfs --ondisk sda --fstype=ext3 --label platform --align 1024 798 part / --source rootfs --ondisk sda --fstype=ext3 --label platform --align 1024
799 799
800 bootloader --timeout=0 --append="rootwait rootfstype=ext3 video=vesafb vga=0x318 console=tty0" 800 bootloader --timeout=0 --append="rootwait rootfstype=ext3 video=vesafb vga=0x318 console=tty0"
@@ -916,6 +916,10 @@ DESCRIPTION
916 will create empty partition. --size parameter has 916 will create empty partition. --size parameter has
917 to be used to specify size of empty partition. 917 to be used to specify size of empty partition.
918 918
919 --sourceparams: This option is specific to wic. Supply additional
920 parameters to the source plugin in
921 key1=value1,key2 format.
922
919 --ondisk or --ondrive: Forces the partition to be created on 923 --ondisk or --ondrive: Forces the partition to be created on
920 a particular disk. 924 a particular disk.
921 925
@@ -932,6 +936,7 @@ DESCRIPTION
932 squashfs 936 squashfs
933 erofs 937 erofs
934 swap 938 swap
939 none
935 940
936 --fsoptions: Specifies a free-form string of options to be 941 --fsoptions: Specifies a free-form string of options to be
937 used when mounting the filesystem. This string 942 used when mounting the filesystem. This string
@@ -965,6 +970,14 @@ DESCRIPTION
965 to start a partition on an x KBytes 970 to start a partition on an x KBytes
966 boundary. 971 boundary.
967 972
973 --offset: This option is specific to wic that says to place a partition
974 at exactly the specified offset. If the partition cannot be
975 placed at the specified offset, the image build will fail.
976 Specify as an integer value optionally followed by one of the
977 units s/S for 512 byte sector, k/K for kibibyte, M for
978 mebibyte and G for gibibyte. The default unit if none is
979 given is k.
980
968 --no-table: This option is specific to wic. Space will be 981 --no-table: This option is specific to wic. Space will be
969 reserved for the partition and it will be 982 reserved for the partition and it will be
970 populated but it will not be added to the 983 populated but it will not be added to the
@@ -1000,12 +1013,20 @@ DESCRIPTION
1000 --no-fstab-update: This option is specific to wic. It does not update the 1013 --no-fstab-update: This option is specific to wic. It does not update the
1001 '/etc/fstab' stock file for the given partition. 1014 '/etc/fstab' stock file for the given partition.
1002 1015
1003 --extra-space: This option is specific to wic. It adds extra 1016 --extra-filesystem-space: This option is specific to wic. It adds extra
1004 space after the space filled by the content 1017 space after the space filled by the content
1005 of the partition. The final size can go 1018 of the partition. The final size can go
1006 beyond the size specified by --size. 1019 beyond the size specified by --size.
1007 By default, 10MB. This option cannot be used 1020 By default, 10MB. This option cannot be used
1008 with --fixed-size option. 1021 with --fixed-size option.
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.
1009 1030
1010 --overhead-factor: This option is specific to wic. The 1031 --overhead-factor: This option is specific to wic. The
1011 size of the partition is multiplied by 1032 size of the partition is multiplied by
@@ -1045,6 +1066,18 @@ DESCRIPTION
1045 not take effect when --mkfs-extraopts is used. This should be taken into 1066 not take effect when --mkfs-extraopts is used. This should be taken into
1046 account when using --mkfs-extraopts. 1067 account when using --mkfs-extraopts.
1047 1068
1069 --type: This option is specific to wic. Valid values are 'primary',
1070 'logical'. For msdos partition tables, this option specifies
1071 the partition type.
1072
1073 --hidden: This option is specific to wic. This option sets the
1074 RequiredPartition bit (bit 0) on GPT partitions.
1075
1076 --mbr: This option is specific to wic. This option is used with the
1077 gpt-hybrid partition type that uses both a GPT partition and
1078 an MBR header. Partitions with this flag will be included in
1079 this MBR header.
1080
1048 * bootloader 1081 * bootloader
1049 1082
1050 This command allows the user to specify various bootloader 1083 This command allows the user to specify various bootloader
@@ -1063,6 +1096,13 @@ DESCRIPTION
1063 file. Using this option will override any other 1096 file. Using this option will override any other
1064 bootloader option. 1097 bootloader option.
1065 1098
1099 --ptable: Specifies the partition table format. Valid values are
1100 'msdos', 'gpt', 'gpt-hybrid'.
1101
1102 --source: Specifies the source plugin. If not specified, the
1103 --source value will be copied from the partition that has
1104 /boot as mountpoint.
1105
1066 Note that bootloader functionality and boot partitions are 1106 Note that bootloader functionality and boot partitions are
1067 implemented by the various --source plugins that implement 1107 implemented by the various --source plugins that implement
1068 bootloader functionality; the bootloader command essentially 1108 bootloader functionality; the bootloader command essentially
diff --git a/scripts/lib/wic/ksparser.py b/scripts/lib/wic/ksparser.py
index 7ef3dc83dd..a762d3b6cf 100644
--- a/scripts/lib/wic/ksparser.py
+++ b/scripts/lib/wic/ksparser.py
@@ -132,7 +132,7 @@ def systemidtype(arg):
132class KickStart(): 132class KickStart():
133 """Kickstart parser implementation.""" 133 """Kickstart parser implementation."""
134 134
135 DEFAULT_EXTRA_SPACE = 10*1024 135 DEFAULT_EXTRA_FILESYSTEM_SPACE = 10*1024
136 DEFAULT_OVERHEAD_FACTOR = 1.3 136 DEFAULT_OVERHEAD_FACTOR = 1.3
137 137
138 def __init__(self, confpath): 138 def __init__(self, confpath):
@@ -153,7 +153,8 @@ class KickStart():
153 part.add_argument('--exclude-path', nargs='+') 153 part.add_argument('--exclude-path', nargs='+')
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-filesystem-space', '--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',
@@ -174,9 +175,9 @@ class KickStart():
174 part.add_argument('--hidden', action='store_true') 175 part.add_argument('--hidden', action='store_true')
175 176
176 # --size and --fixed-size cannot be specified together; options 177 # --size and --fixed-size cannot be specified together; options
177 # ----extra-space and --overhead-factor should also raise a parser 178 # ----extra-filesystem-space and --overhead-factor should also raise a
178 # --error, but since nesting mutually exclusive groups does not work, 179 # parser error, but since nesting mutually exclusive groups does not work,
179 # ----extra-space/--overhead-factor are handled later 180 # ----extra-filesystem-space/--overhead-factor are handled later
180 sizeexcl = part.add_mutually_exclusive_group() 181 sizeexcl = part.add_mutually_exclusive_group()
181 sizeexcl.add_argument('--size', type=sizetype("M"), default=0) 182 sizeexcl.add_argument('--size', type=sizetype("M"), default=0)
182 sizeexcl.add_argument('--fixed-size', type=sizetype("M"), default=0) 183 sizeexcl.add_argument('--fixed-size', type=sizetype("M"), default=0)
@@ -259,14 +260,17 @@ 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-filesystem-space
265 # with --fixed-size, so at least detect when these were 268 # cannot be used with --fixed-size, so at least detect
266 # passed with non-0 values ... 269 # when these were passed with non-0 values ...
267 if parsed.fixed_size: 270 if parsed.fixed_size:
268 if parsed.overhead_factor or parsed.extra_space: 271 if parsed.overhead_factor or parsed.extra_filesystem_space:
269 err = "%s:%d: arguments --overhead-factor and --extra-space not "\ 272 err = "%s:%d: arguments --overhead-factor and "\
273 "--extra-filesystem-space not "\
270 "allowed with argument --fixed-size" \ 274 "allowed with argument --fixed-size" \
271 % (confpath, lineno) 275 % (confpath, lineno)
272 raise KickStartError(err) 276 raise KickStartError(err)
@@ -275,10 +279,10 @@ class KickStart():
275 # --fixed-size iff given option was not used 279 # --fixed-size iff given option was not used
276 # (again, one cannot tell if option was passed but 280 # (again, one cannot tell if option was passed but
277 # with value equal to 0) 281 # with value equal to 0)
278 if '--overhead-factor' not in line_args: 282 if not parsed.overhead_factor:
279 parsed.overhead_factor = self.DEFAULT_OVERHEAD_FACTOR 283 parsed.overhead_factor = self.DEFAULT_OVERHEAD_FACTOR
280 if '--extra-space' not in line_args: 284 if not parsed.extra_filesystem_space:
281 parsed.extra_space = self.DEFAULT_EXTRA_SPACE 285 parsed.extra_filesystem_space = self.DEFAULT_EXTRA_FILESYSTEM_SPACE
282 286
283 self.partnum += 1 287 self.partnum += 1
284 self.partitions.append(Partition(parsed, self.partnum)) 288 self.partitions.append(Partition(parsed, self.partnum))
diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
index 795707ec5d..531ac6eb3d 100644
--- a/scripts/lib/wic/partition.py
+++ b/scripts/lib/wic/partition.py
@@ -28,7 +28,8 @@ class Partition():
28 self.align = args.align 28 self.align = args.align
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_filesystem_space = args.extra_filesystem_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,21 +92,20 @@ 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" %
104 (actual_rootfs_size, rootfs_size)) 104 (actual_rootfs_size, rootfs_size))
105 else: 105 else:
106 extra_blocks = self.get_extra_block_count(actual_rootfs_size) 106 extra_blocks = self.get_extra_block_count(actual_rootfs_size)
107 if extra_blocks < self.extra_space: 107 if extra_blocks < self.extra_filesystem_space:
108 extra_blocks = self.extra_space 108 extra_blocks = self.extra_filesystem_space
109 109
110 rootfs_size = actual_rootfs_size + extra_blocks 110 rootfs_size = actual_rootfs_size + extra_blocks
111 rootfs_size = int(rootfs_size * self.overhead_factor) 111 rootfs_size = int(rootfs_size * self.overhead_factor)
@@ -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):
@@ -164,10 +172,13 @@ class Partition():
164 172
165 plugins = PluginMgr.get_plugins('source') 173 plugins = PluginMgr.get_plugins('source')
166 174
175 # Don't support '-' in plugin names
176 self.source = self.source.replace("-", "_")
177
167 if self.source not in plugins: 178 if self.source not in plugins:
168 raise WicError("The '%s' --source specified for %s doesn't exist.\n\t" 179 raise WicError("The '%s' --source specified for %s doesn't exist.\n\t"
169 "See 'wic list source-plugins' for a list of available" 180 "See 'wic list source-plugins' for a list of available"
170 " --sources.\n\tSee 'wic help source-plugins' for " 181 " --sources.\n\tSee 'wic help plugins' for "
171 "details on adding a new source plugin." % 182 "details on adding a new source plugin." %
172 (self.source, self.mountpoint)) 183 (self.source, self.mountpoint))
173 184
@@ -178,7 +189,7 @@ class Partition():
178 splitted = self.sourceparams.split(',') 189 splitted = self.sourceparams.split(',')
179 srcparams_dict = dict((par.split('=', 1) + [None])[:2] for par in splitted if par) 190 srcparams_dict = dict((par.split('=', 1) + [None])[:2] for par in splitted if par)
180 191
181 plugin = PluginMgr.get_plugins('source')[self.source] 192 plugin = plugins[self.source]
182 plugin.do_configure_partition(self, srcparams_dict, creator, 193 plugin.do_configure_partition(self, srcparams_dict, creator,
183 cr_workdir, oe_builddir, bootimg_dir, 194 cr_workdir, oe_builddir, bootimg_dir,
184 kernel_dir, native_sysroot) 195 kernel_dir, native_sysroot)
@@ -199,10 +210,10 @@ class Partition():
199 "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." %
200 (self.mountpoint, self.source)) 211 (self.mountpoint, self.source))
201 212
202 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:
203 raise WicError("File system image of partition %s is " 214 raise WicError("File system image of partition %s is "
204 "larger (%d kB) than its allowed size %d kB" % 215 "larger (%d kB + %d kB extra part space) than its allowed size %d kB" %
205 (self.mountpoint, self.size, self.fixed_size)) 216 (self.mountpoint, self.size, self.extra_partition_space, self.fixed_size))
206 217
207 def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir, 218 def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir,
208 native_sysroot, real_rootfs = True, pseudo_dir = None): 219 native_sysroot, real_rootfs = True, pseudo_dir = None):
@@ -222,19 +233,19 @@ class Partition():
222 if (pseudo_dir): 233 if (pseudo_dir):
223 # Canonicalize the ignore paths. This corresponds to 234 # Canonicalize the ignore paths. This corresponds to
224 # calling oe.path.canonicalize(), which is used in bitbake.conf. 235 # calling oe.path.canonicalize(), which is used in bitbake.conf.
225 ignore_paths = [rootfs] + (get_bitbake_var("PSEUDO_IGNORE_PATHS") or "").split(",") 236 include_paths = [rootfs_dir] + (get_bitbake_var("PSEUDO_INCLUDE_PATHS") or "").split(",")
226 canonical_paths = [] 237 canonical_paths = []
227 for path in ignore_paths: 238 for path in include_paths:
228 if "$" not in path: 239 if "$" not in path:
229 trailing_slash = path.endswith("/") and "/" or "" 240 trailing_slash = path.endswith("/") and "/" or ""
230 canonical_paths.append(os.path.realpath(path) + trailing_slash) 241 canonical_paths.append(os.path.realpath(path) + trailing_slash)
231 ignore_paths = ",".join(canonical_paths) 242 include_paths = ",".join(canonical_paths)
232 243
233 pseudo = "export PSEUDO_PREFIX=%s;" % p_prefix 244 pseudo = "export PSEUDO_PREFIX=%s;" % p_prefix
234 pseudo += "export PSEUDO_LOCALSTATEDIR=%s;" % pseudo_dir 245 pseudo += "export PSEUDO_LOCALSTATEDIR=%s;" % pseudo_dir
235 pseudo += "export PSEUDO_PASSWD=%s;" % rootfs_dir 246 pseudo += "export PSEUDO_PASSWD=%s;" % rootfs_dir
236 pseudo += "export PSEUDO_NOSYMLINKEXP=1;" 247 pseudo += "export PSEUDO_NOSYMLINKEXP=1;"
237 pseudo += "export PSEUDO_IGNORE_PATHS=%s;" % ignore_paths 248 pseudo += "export PSEUDO_INCLUDE_PATHS=%s;" % include_paths
238 pseudo += "%s " % get_bitbake_var("FAKEROOTCMD") 249 pseudo += "%s " % get_bitbake_var("FAKEROOTCMD")
239 else: 250 else:
240 pseudo = None 251 pseudo = None
@@ -244,7 +255,7 @@ class Partition():
244 # from bitbake variable 255 # from bitbake variable
245 rsize_bb = get_bitbake_var('ROOTFS_SIZE') 256 rsize_bb = get_bitbake_var('ROOTFS_SIZE')
246 rdir = get_bitbake_var('IMAGE_ROOTFS') 257 rdir = get_bitbake_var('IMAGE_ROOTFS')
247 if rsize_bb and rdir == rootfs_dir: 258 if rsize_bb and (rdir == rootfs_dir or (rootfs_dir.split('/')[-2] == "tmp-wic" and rootfs_dir.split('/')[-1][:6] == "rootfs")):
248 # Bitbake variable ROOTFS_SIZE is calculated in 259 # Bitbake variable ROOTFS_SIZE is calculated in
249 # Image._get_rootfs_size method from meta/lib/oe/image.py 260 # Image._get_rootfs_size method from meta/lib/oe/image.py
250 # using IMAGE_ROOTFS_SIZE, IMAGE_ROOTFS_ALIGNMENT, 261 # using IMAGE_ROOTFS_SIZE, IMAGE_ROOTFS_ALIGNMENT,
@@ -284,19 +295,8 @@ class Partition():
284 295
285 extraopts = self.mkfs_extraopts or "-F -i 8192" 296 extraopts = self.mkfs_extraopts or "-F -i 8192"
286 297
287 if os.getenv('SOURCE_DATE_EPOCH'): 298 # use hash_seed to generate reproducible ext4 images
288 sde_time = int(os.getenv('SOURCE_DATE_EPOCH')) 299 (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, pseudo)
289 if pseudo:
290 pseudo = "export E2FSPROGS_FAKE_TIME=%s;%s " % (sde_time, pseudo)
291 else:
292 pseudo = "export E2FSPROGS_FAKE_TIME=%s; " % sde_time
293
294 # Set hash_seed to generate deterministic directory indexes
295 namespace = uuid.UUID("e7429877-e7b3-4a68-a5c9-2f2fdf33d460")
296 if self.fsuuid:
297 namespace = uuid.UUID(self.fsuuid)
298 hash_seed = str(uuid.uuid5(namespace, str(sde_time)))
299 extraopts += " -E hash_seed=%s" % hash_seed
300 300
301 label_str = "" 301 label_str = ""
302 if self.label: 302 if self.label:
@@ -344,6 +344,23 @@ class Partition():
344 344
345 self.check_for_Y2038_problem(rootfs, native_sysroot) 345 self.check_for_Y2038_problem(rootfs, native_sysroot)
346 346
347 def get_hash_seed_ext4(self, extraopts, pseudo):
348 if os.getenv('SOURCE_DATE_EPOCH'):
349 sde_time = int(os.getenv('SOURCE_DATE_EPOCH'))
350 if pseudo:
351 pseudo = "export E2FSPROGS_FAKE_TIME=%s;%s " % (sde_time, pseudo)
352 else:
353 pseudo = "export E2FSPROGS_FAKE_TIME=%s; " % sde_time
354
355 # Set hash_seed to generate deterministic directory indexes
356 namespace = uuid.UUID("e7429877-e7b3-4a68-a5c9-2f2fdf33d460")
357 if self.fsuuid:
358 namespace = uuid.UUID(self.fsuuid)
359 hash_seed = str(uuid.uuid5(namespace, str(sde_time)))
360 extraopts += " -E hash_seed=%s" % hash_seed
361
362 return (extraopts, pseudo)
363
347 def prepare_rootfs_btrfs(self, rootfs, cr_workdir, oe_builddir, rootfs_dir, 364 def prepare_rootfs_btrfs(self, rootfs, cr_workdir, oe_builddir, rootfs_dir,
348 native_sysroot, pseudo): 365 native_sysroot, pseudo):
349 """ 366 """
@@ -431,19 +448,22 @@ class Partition():
431 """ 448 """
432 Prepare an empty ext2/3/4 partition. 449 Prepare an empty ext2/3/4 partition.
433 """ 450 """
434 size = self.disk_size 451 size = self.fs_size
435 with open(rootfs, 'w') as sparse: 452 with open(rootfs, 'w') as sparse:
436 os.ftruncate(sparse.fileno(), size * 1024) 453 os.ftruncate(sparse.fileno(), size * 1024)
437 454
438 extraopts = self.mkfs_extraopts or "-i 8192" 455 extraopts = self.mkfs_extraopts or "-i 8192"
439 456
457 # use hash_seed to generate reproducible ext4 images
458 (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, None)
459
440 label_str = "" 460 label_str = ""
441 if self.label: 461 if self.label:
442 label_str = "-L %s" % self.label 462 label_str = "-L %s" % self.label
443 463
444 mkfs_cmd = "mkfs.%s -F %s %s -U %s %s" % \ 464 mkfs_cmd = "mkfs.%s -F %s %s -U %s %s" % \
445 (self.fstype, extraopts, label_str, self.fsuuid, rootfs) 465 (self.fstype, extraopts, label_str, self.fsuuid, rootfs)
446 exec_native_cmd(mkfs_cmd, native_sysroot) 466 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo)
447 467
448 self.check_for_Y2038_problem(rootfs, native_sysroot) 468 self.check_for_Y2038_problem(rootfs, native_sysroot)
449 469
@@ -452,7 +472,7 @@ class Partition():
452 """ 472 """
453 Prepare an empty btrfs partition. 473 Prepare an empty btrfs partition.
454 """ 474 """
455 size = self.disk_size 475 size = self.fs_size
456 with open(rootfs, 'w') as sparse: 476 with open(rootfs, 'w') as sparse:
457 os.ftruncate(sparse.fileno(), size * 1024) 477 os.ftruncate(sparse.fileno(), size * 1024)
458 478
@@ -470,7 +490,7 @@ class Partition():
470 """ 490 """
471 Prepare an empty vfat partition. 491 Prepare an empty vfat partition.
472 """ 492 """
473 blocks = self.disk_size 493 blocks = self.fs_size
474 494
475 label_str = "-n boot" 495 label_str = "-n boot"
476 if self.label: 496 if self.label:
diff --git a/scripts/lib/wic/pluginbase.py b/scripts/lib/wic/pluginbase.py
index b64568339b..640da292d3 100644
--- a/scripts/lib/wic/pluginbase.py
+++ b/scripts/lib/wic/pluginbase.py
@@ -44,7 +44,7 @@ class PluginMgr:
44 path = os.path.join(layer_path, script_plugin_dir) 44 path = os.path.join(layer_path, script_plugin_dir)
45 path = os.path.abspath(os.path.expanduser(path)) 45 path = os.path.abspath(os.path.expanduser(path))
46 if path not in cls._plugin_dirs and os.path.isdir(path): 46 if path not in cls._plugin_dirs and os.path.isdir(path):
47 cls._plugin_dirs.insert(0, path) 47 cls._plugin_dirs.append(path)
48 48
49 if ptype not in PLUGINS: 49 if ptype not in PLUGINS:
50 # load all ptype plugins 50 # load all ptype plugins
diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py
index a1d152659b..6e1f1c8cba 100644
--- a/scripts/lib/wic/plugins/imager/direct.py
+++ b/scripts/lib/wic/plugins/imager/direct.py
@@ -203,6 +203,8 @@ class DirectPlugin(ImagerPlugin):
203 source_plugin = self.ks.bootloader.source 203 source_plugin = self.ks.bootloader.source
204 disk_name = self.parts[0].disk 204 disk_name = self.parts[0].disk
205 if source_plugin: 205 if source_plugin:
206 # Don't support '-' in plugin names
207 source_plugin = source_plugin.replace("-", "_")
206 plugin = PluginMgr.get_plugins('source')[source_plugin] 208 plugin = PluginMgr.get_plugins('source')[source_plugin]
207 plugin.do_install_disk(self._image, disk_name, self, self.workdir, 209 plugin.do_install_disk(self._image, disk_name, self, self.workdir,
208 self.oe_builddir, self.bootimg_dir, 210 self.oe_builddir, self.bootimg_dir,
@@ -321,7 +323,15 @@ class PartitionedImage():
321 self.partitions = partitions 323 self.partitions = partitions
322 self.partimages = [] 324 self.partimages = []
323 # Size of a sector used in calculations 325 # Size of a sector used in calculations
324 self.sector_size = SECTOR_SIZE 326 sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
327 if sector_size_str is not None:
328 try:
329 self.sector_size = int(sector_size_str)
330 except ValueError:
331 self.sector_size = SECTOR_SIZE
332 else:
333 self.sector_size = SECTOR_SIZE
334
325 self.native_sysroot = native_sysroot 335 self.native_sysroot = native_sysroot
326 num_real_partitions = len([p for p in self.partitions if not p.no_table]) 336 num_real_partitions = len([p for p in self.partitions if not p.no_table])
327 self.extra_space = extra_space 337 self.extra_space = extra_space
@@ -508,7 +518,8 @@ class PartitionedImage():
508 logger.debug("Added '%s' partition, sectors %d-%d, size %d sectors", 518 logger.debug("Added '%s' partition, sectors %d-%d, size %d sectors",
509 parttype, start, end, size) 519 parttype, start, end, size)
510 520
511 cmd = "parted -s %s unit s mkpart %s" % (device, parttype) 521 cmd = "export PARTED_SECTOR_SIZE=%d; parted -s %s unit s mkpart %s" % \
522 (self.sector_size, device, parttype)
512 if fstype: 523 if fstype:
513 cmd += " %s" % fstype 524 cmd += " %s" % fstype
514 cmd += " %d %d" % (start, end) 525 cmd += " %d %d" % (start, end)
@@ -527,8 +538,8 @@ class PartitionedImage():
527 os.ftruncate(sparse.fileno(), min_size) 538 os.ftruncate(sparse.fileno(), min_size)
528 539
529 logger.debug("Initializing partition table for %s", device) 540 logger.debug("Initializing partition table for %s", device)
530 exec_native_cmd("parted -s %s mklabel %s" % (device, ptable_format), 541 exec_native_cmd("export PARTED_SECTOR_SIZE=%d; parted -s %s mklabel %s" %
531 self.native_sysroot) 542 (self.sector_size, device, ptable_format), self.native_sysroot)
532 543
533 def _write_disk_guid(self): 544 def _write_disk_guid(self):
534 if self.ptable_format in ('gpt', 'gpt-hybrid'): 545 if self.ptable_format in ('gpt', 'gpt-hybrid'):
@@ -538,7 +549,8 @@ class PartitionedImage():
538 self.disk_guid = uuid.uuid4() 549 self.disk_guid = uuid.uuid4()
539 550
540 logger.debug("Set disk guid %s", self.disk_guid) 551 logger.debug("Set disk guid %s", self.disk_guid)
541 sfdisk_cmd = "sfdisk --disk-id %s %s" % (self.path, self.disk_guid) 552 sfdisk_cmd = "sfdisk --sector-size %s --disk-id %s %s" % \
553 (self.sector_size, self.path, self.disk_guid)
542 exec_native_cmd(sfdisk_cmd, self.native_sysroot) 554 exec_native_cmd(sfdisk_cmd, self.native_sysroot)
543 555
544 def create(self): 556 def create(self):
@@ -613,45 +625,44 @@ class PartitionedImage():
613 partition_label = part.part_name if part.part_name else part.label 625 partition_label = part.part_name if part.part_name else part.label
614 logger.debug("partition %d: set name to %s", 626 logger.debug("partition %d: set name to %s",
615 part.num, partition_label) 627 part.num, partition_label)
616 exec_native_cmd("sgdisk --change-name=%d:%s %s" % \ 628 exec_native_cmd("sfdisk --sector-size %s --part-label %s %d %s" % \
617 (part.num, partition_label, 629 (self.sector_size, self.path, part.num,
618 self.path), self.native_sysroot) 630 partition_label), self.native_sysroot)
619
620 if part.part_type: 631 if part.part_type:
621 logger.debug("partition %d: set type UID to %s", 632 logger.debug("partition %d: set type UID to %s",
622 part.num, part.part_type) 633 part.num, part.part_type)
623 exec_native_cmd("sgdisk --typecode=%d:%s %s" % \ 634 exec_native_cmd("sfdisk --sector-size %s --part-type %s %d %s" % \
624 (part.num, part.part_type, 635 (self.sector_size, self.path, part.num,
625 self.path), self.native_sysroot) 636 part.part_type), self.native_sysroot)
626 637
627 if part.uuid and self.ptable_format in ("gpt", "gpt-hybrid"): 638 if part.uuid and self.ptable_format in ("gpt", "gpt-hybrid"):
628 logger.debug("partition %d: set UUID to %s", 639 logger.debug("partition %d: set UUID to %s",
629 part.num, part.uuid) 640 part.num, part.uuid)
630 exec_native_cmd("sgdisk --partition-guid=%d:%s %s" % \ 641 exec_native_cmd("sfdisk --sector-size %s --part-uuid %s %d %s" % \
631 (part.num, part.uuid, self.path), 642 (self.sector_size, self.path, part.num, part.uuid),
632 self.native_sysroot) 643 self.native_sysroot)
633 644
634 if part.active: 645 if part.active:
635 flag_name = "legacy_boot" if self.ptable_format in ('gpt', 'gpt-hybrid') else "boot" 646 flag_name = "legacy_boot" if self.ptable_format in ('gpt', 'gpt-hybrid') else "boot"
636 logger.debug("Set '%s' flag for partition '%s' on disk '%s'", 647 logger.debug("Set '%s' flag for partition '%s' on disk '%s'",
637 flag_name, part.num, self.path) 648 flag_name, part.num, self.path)
638 exec_native_cmd("parted -s %s set %d %s on" % \ 649 exec_native_cmd("export PARTED_SECTOR_SIZE=%d; parted -s %s set %d %s on" % \
639 (self.path, part.num, flag_name), 650 (self.sector_size, self.path, part.num, flag_name),
640 self.native_sysroot) 651 self.native_sysroot)
641 if self.ptable_format == 'gpt-hybrid' and part.mbr: 652 if self.ptable_format == 'gpt-hybrid' and part.mbr:
642 exec_native_cmd("parted -s %s set %d %s on" % \ 653 exec_native_cmd("export PARTED_SECTOR_SIZE=%d; parted -s %s set %d %s on" % \
643 (mbr_path, hybrid_mbr_part_num, "boot"), 654 (self.sector_size, mbr_path, hybrid_mbr_part_num, "boot"),
644 self.native_sysroot) 655 self.native_sysroot)
645 if part.system_id: 656 if part.system_id:
646 exec_native_cmd("sfdisk --part-type %s %s %s" % \ 657 exec_native_cmd("sfdisk --sector-size %s --part-type %s %s %s" % \
647 (self.path, part.num, part.system_id), 658 (self.sector_size, self.path, part.num, part.system_id),
648 self.native_sysroot) 659 self.native_sysroot)
649 660
650 if part.hidden and self.ptable_format == "gpt": 661 if part.hidden and self.ptable_format == "gpt":
651 logger.debug("Set hidden attribute for partition '%s' on disk '%s'", 662 logger.debug("Set hidden attribute for partition '%s' on disk '%s'",
652 part.num, self.path) 663 part.num, self.path)
653 exec_native_cmd("sfdisk --part-attrs %s %s RequiredPartition" % \ 664 exec_native_cmd("sfdisk --sector-size %s --part-attrs %s %s RequiredPartition" % \
654 (self.path, part.num), 665 (self.sector_size, self.path, part.num),
655 self.native_sysroot) 666 self.native_sysroot)
656 667
657 if self.ptable_format == "gpt-hybrid": 668 if self.ptable_format == "gpt-hybrid":
@@ -664,7 +675,8 @@ class PartitionedImage():
664 # create with an arbitrary type, then change it to the correct type 675 # create with an arbitrary type, then change it to the correct type
665 # with sfdisk 676 # with sfdisk
666 self._create_partition(mbr_path, "primary", "fat32", 1, GPT_OVERHEAD) 677 self._create_partition(mbr_path, "primary", "fat32", 1, GPT_OVERHEAD)
667 exec_native_cmd("sfdisk --part-type %s %d 0xee" % (mbr_path, hybrid_mbr_part_num), 678 exec_native_cmd("sfdisk --sector-size %s --part-type %s %d 0xee" % \
679 (self.sector_size, mbr_path, hybrid_mbr_part_num),
668 self.native_sysroot) 680 self.native_sysroot)
669 681
670 # Copy hybrid MBR 682 # Copy hybrid MBR
diff --git a/scripts/lib/wic/plugins/source/bootimg-pcbios.py b/scripts/lib/wic/plugins/source/bootimg-pcbios.py
deleted file mode 100644
index a207a83530..0000000000
--- a/scripts/lib/wic/plugins/source/bootimg-pcbios.py
+++ /dev/null
@@ -1,209 +0,0 @@
1#
2# Copyright (c) 2014, Intel Corporation.
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6# DESCRIPTION
7# This implements the 'bootimg-pcbios' source plugin class for 'wic'
8#
9# AUTHORS
10# Tom Zanussi <tom.zanussi (at] linux.intel.com>
11#
12
13import logging
14import os
15import re
16
17from wic import WicError
18from wic.engine import get_custom_config
19from wic.pluginbase import SourcePlugin
20from wic.misc import (exec_cmd, exec_native_cmd,
21 get_bitbake_var, BOOTDD_EXTRA_SPACE)
22
23logger = logging.getLogger('wic')
24
25class BootimgPcbiosPlugin(SourcePlugin):
26 """
27 Create MBR boot partition and install syslinux on it.
28 """
29
30 name = 'bootimg-pcbios'
31
32 @classmethod
33 def _get_bootimg_dir(cls, bootimg_dir, dirname):
34 """
35 Check if dirname exists in default bootimg_dir or in STAGING_DIR.
36 """
37 staging_datadir = get_bitbake_var("STAGING_DATADIR")
38 for result in (bootimg_dir, staging_datadir):
39 if os.path.exists("%s/%s" % (result, dirname)):
40 return result
41
42 # STAGING_DATADIR is expanded with MLPREFIX if multilib is enabled
43 # but dependency syslinux is still populated to original STAGING_DATADIR
44 nonarch_datadir = re.sub('/[^/]*recipe-sysroot', '/recipe-sysroot', staging_datadir)
45 if os.path.exists(os.path.join(nonarch_datadir, dirname)):
46 return nonarch_datadir
47
48 raise WicError("Couldn't find correct bootimg_dir, exiting")
49
50 @classmethod
51 def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir,
52 bootimg_dir, kernel_dir, native_sysroot):
53 """
54 Called after all partitions have been prepared and assembled into a
55 disk image. In this case, we install the MBR.
56 """
57 bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux')
58 mbrfile = "%s/syslinux/" % bootimg_dir
59 if creator.ptable_format == 'msdos':
60 mbrfile += "mbr.bin"
61 elif creator.ptable_format == 'gpt':
62 mbrfile += "gptmbr.bin"
63 else:
64 raise WicError("Unsupported partition table: %s" %
65 creator.ptable_format)
66
67 if not os.path.exists(mbrfile):
68 raise WicError("Couldn't find %s. If using the -e option, do you "
69 "have the right MACHINE set in local.conf? If not, "
70 "is the bootimg_dir path correct?" % mbrfile)
71
72 full_path = creator._full_path(workdir, disk_name, "direct")
73 logger.debug("Installing MBR on disk %s as %s with size %s bytes",
74 disk_name, full_path, disk.min_size)
75
76 dd_cmd = "dd if=%s of=%s conv=notrunc" % (mbrfile, full_path)
77 exec_cmd(dd_cmd, native_sysroot)
78
79 @classmethod
80 def do_configure_partition(cls, part, source_params, creator, cr_workdir,
81 oe_builddir, bootimg_dir, kernel_dir,
82 native_sysroot):
83 """
84 Called before do_prepare_partition(), creates syslinux config
85 """
86 hdddir = "%s/hdd/boot" % cr_workdir
87
88 install_cmd = "install -d %s" % hdddir
89 exec_cmd(install_cmd)
90
91 bootloader = creator.ks.bootloader
92
93 custom_cfg = None
94 if bootloader.configfile:
95 custom_cfg = get_custom_config(bootloader.configfile)
96 if custom_cfg:
97 # Use a custom configuration for grub
98 syslinux_conf = custom_cfg
99 logger.debug("Using custom configuration file %s "
100 "for syslinux.cfg", bootloader.configfile)
101 else:
102 raise WicError("configfile is specified but failed to "
103 "get it from %s." % bootloader.configfile)
104
105 if not custom_cfg:
106 # Create syslinux configuration using parameters from wks file
107 splash = os.path.join(cr_workdir, "/hdd/boot/splash.jpg")
108 if os.path.exists(splash):
109 splashline = "menu background splash.jpg"
110 else:
111 splashline = ""
112
113 syslinux_conf = ""
114 syslinux_conf += "PROMPT 0\n"
115 syslinux_conf += "TIMEOUT " + str(bootloader.timeout) + "\n"
116 syslinux_conf += "\n"
117 syslinux_conf += "ALLOWOPTIONS 1\n"
118 syslinux_conf += "SERIAL 0 115200\n"
119 syslinux_conf += "\n"
120 if splashline:
121 syslinux_conf += "%s\n" % splashline
122 syslinux_conf += "DEFAULT boot\n"
123 syslinux_conf += "LABEL boot\n"
124
125 kernel = "/" + get_bitbake_var("KERNEL_IMAGETYPE")
126 syslinux_conf += "KERNEL " + kernel + "\n"
127
128 syslinux_conf += "APPEND label=boot root=%s %s\n" % \
129 (creator.rootdev, bootloader.append)
130
131 logger.debug("Writing syslinux config %s/hdd/boot/syslinux.cfg",
132 cr_workdir)
133 cfg = open("%s/hdd/boot/syslinux.cfg" % cr_workdir, "w")
134 cfg.write(syslinux_conf)
135 cfg.close()
136
137 @classmethod
138 def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
139 oe_builddir, bootimg_dir, kernel_dir,
140 rootfs_dir, native_sysroot):
141 """
142 Called to do the actual content population for a partition i.e. it
143 'prepares' the partition to be incorporated into the image.
144 In this case, prepare content for legacy bios boot partition.
145 """
146 bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux')
147
148 staging_kernel_dir = kernel_dir
149
150 hdddir = "%s/hdd/boot" % cr_workdir
151
152 kernel = get_bitbake_var("KERNEL_IMAGETYPE")
153 if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1":
154 if get_bitbake_var("INITRAMFS_IMAGE"):
155 kernel = "%s-%s.bin" % \
156 (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME"))
157
158 cmds = ("install -m 0644 %s/%s %s/%s" %
159 (staging_kernel_dir, kernel, hdddir, get_bitbake_var("KERNEL_IMAGETYPE")),
160 "install -m 444 %s/syslinux/ldlinux.sys %s/ldlinux.sys" %
161 (bootimg_dir, hdddir),
162 "install -m 0644 %s/syslinux/vesamenu.c32 %s/vesamenu.c32" %
163 (bootimg_dir, hdddir),
164 "install -m 444 %s/syslinux/libcom32.c32 %s/libcom32.c32" %
165 (bootimg_dir, hdddir),
166 "install -m 444 %s/syslinux/libutil.c32 %s/libutil.c32" %
167 (bootimg_dir, hdddir))
168
169 for install_cmd in cmds:
170 exec_cmd(install_cmd)
171
172 du_cmd = "du -bks %s" % hdddir
173 out = exec_cmd(du_cmd)
174 blocks = int(out.split()[0])
175
176 extra_blocks = part.get_extra_block_count(blocks)
177
178 if extra_blocks < BOOTDD_EXTRA_SPACE:
179 extra_blocks = BOOTDD_EXTRA_SPACE
180
181 blocks += extra_blocks
182
183 logger.debug("Added %d extra blocks to %s to get to %d total blocks",
184 extra_blocks, part.mountpoint, blocks)
185
186 # dosfs image, created by mkdosfs
187 bootimg = "%s/boot%s.img" % (cr_workdir, part.lineno)
188
189 label = part.label if part.label else "boot"
190
191 dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
192 (label, part.fsuuid, bootimg, blocks)
193 exec_native_cmd(dosfs_cmd, native_sysroot)
194
195 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
196 exec_native_cmd(mcopy_cmd, native_sysroot)
197
198 syslinux_cmd = "syslinux %s" % bootimg
199 exec_native_cmd(syslinux_cmd, native_sysroot)
200
201 chmod_cmd = "chmod 644 %s" % bootimg
202 exec_cmd(chmod_cmd)
203
204 du_cmd = "du -Lbks %s" % bootimg
205 out = exec_cmd(du_cmd)
206 bootimg_size = out.split()[0]
207
208 part.size = int(bootimg_size)
209 part.source_file = bootimg
diff --git a/scripts/lib/wic/plugins/source/bootimg-biosplusefi.py b/scripts/lib/wic/plugins/source/bootimg_biosplusefi.py
index 5bd7390680..4279ddded8 100644
--- a/scripts/lib/wic/plugins/source/bootimg-biosplusefi.py
+++ b/scripts/lib/wic/plugins/source/bootimg_biosplusefi.py
@@ -13,7 +13,7 @@
13# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 13# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14# 14#
15# DESCRIPTION 15# DESCRIPTION
16# This implements the 'bootimg-biosplusefi' source plugin class for 'wic' 16# This implements the 'bootimg_biosplusefi' source plugin class for 'wic'
17# 17#
18# AUTHORS 18# AUTHORS
19# William Bourque <wbourque [at) gmail.com> 19# William Bourque <wbourque [at) gmail.com>
@@ -34,7 +34,7 @@ class BootimgBiosPlusEFIPlugin(SourcePlugin):
34 34
35 Note it is possible to create an image that can boot from both 35 Note it is possible to create an image that can boot from both
36 legacy BIOS and EFI by defining two partitions : one with arg 36 legacy BIOS and EFI by defining two partitions : one with arg
37 --source bootimg-efi and another one with --source bootimg-pcbios. 37 --source bootimg_efi and another one with --source bootimg_pcbios.
38 However, this method has the obvious downside that it requires TWO 38 However, this method has the obvious downside that it requires TWO
39 partitions to be created on the storage device. 39 partitions to be created on the storage device.
40 Both partitions will also be marked as "bootable" which does not work on 40 Both partitions will also be marked as "bootable" which does not work on
@@ -45,7 +45,7 @@ class BootimgBiosPlusEFIPlugin(SourcePlugin):
45 the first partition will be duplicated into the second, even though it 45 the first partition will be duplicated into the second, even though it
46 will not be used at all. 46 will not be used at all.
47 47
48 Also, unlike "isoimage-isohybrid" that also does BIOS and EFI, this plugin 48 Also, unlike "isoimage_isohybrid" that also does BIOS and EFI, this plugin
49 allows you to have more than only a single rootfs partitions and does 49 allows you to have more than only a single rootfs partitions and does
50 not turn the rootfs into an initramfs RAM image. 50 not turn the rootfs into an initramfs RAM image.
51 51
@@ -53,32 +53,32 @@ class BootimgBiosPlusEFIPlugin(SourcePlugin):
53 does not have the limitations listed above. 53 does not have the limitations listed above.
54 54
55 The plugin is made so it does tries not to reimplement what's already 55 The plugin is made so it does tries not to reimplement what's already
56 been done in other plugins; as such it imports "bootimg-pcbios" 56 been done in other plugins; as such it imports "bootimg_pcbios"
57 and "bootimg-efi". 57 and "bootimg_efi".
58 Plugin "bootimg-pcbios" is used to generate legacy BIOS boot. 58 Plugin "bootimg_pcbios" is used to generate legacy BIOS boot.
59 Plugin "bootimg-efi" is used to generate the UEFI boot. Note that it 59 Plugin "bootimg_efi" is used to generate the UEFI boot. Note that it
60 requires a --sourceparams argument to know which loader to use; refer 60 requires a --sourceparams argument to know which loader to use; refer
61 to "bootimg-efi" code/documentation for the list of loader. 61 to "bootimg_efi" code/documentation for the list of loader.
62 62
63 Imports are handled with "SourceFileLoader" from importlib as it is 63 Imports are handled with "SourceFileLoader" from importlib as it is
64 otherwise very difficult to import module that has hyphen "-" in their 64 otherwise very difficult to import module that has hyphen "-" in their
65 filename. 65 filename.
66 The SourcePlugin() methods used in the plugins (do_install_disk, 66 The SourcePlugin() methods used in the plugins (do_install_disk,
67 do_configure_partition, do_prepare_partition) are then called on both, 67 do_configure_partition, do_prepare_partition) are then called on both,
68 beginning by "bootimg-efi". 68 beginning by "bootimg_efi".
69 69
70 Plugin options, such as "--sourceparams" can still be passed to a 70 Plugin options, such as "--sourceparams" can still be passed to a
71 plugin, as long they does not cause issue in the other plugin. 71 plugin, as long they does not cause issue in the other plugin.
72 72
73 Example wic configuration: 73 Example wic configuration:
74 part /boot --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\\ 74 part /boot --source bootimg_biosplusefi --sourceparams="loader=grub-efi"\\
75 --ondisk sda --label os_boot --active --align 1024 --use-uuid 75 --ondisk sda --label os_boot --active --align 1024 --use-uuid
76 """ 76 """
77 77
78 name = 'bootimg-biosplusefi' 78 name = 'bootimg_biosplusefi'
79 79
80 __PCBIOS_MODULE_NAME = "bootimg-pcbios" 80 __PCBIOS_MODULE_NAME = "bootimg_pcbios"
81 __EFI_MODULE_NAME = "bootimg-efi" 81 __EFI_MODULE_NAME = "bootimg_efi"
82 82
83 __imgEFIObj = None 83 __imgEFIObj = None
84 __imgBiosObj = None 84 __imgBiosObj = None
@@ -100,7 +100,7 @@ class BootimgBiosPlusEFIPlugin(SourcePlugin):
100 100
101 """ 101 """
102 102
103 # Import bootimg-pcbios (class name "BootimgPcbiosPlugin") 103 # Import bootimg_pcbios (class name "BootimgPcbiosPlugin")
104 modulePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 104 modulePath = os.path.join(os.path.dirname(os.path.realpath(__file__)),
105 cls.__PCBIOS_MODULE_NAME + ".py") 105 cls.__PCBIOS_MODULE_NAME + ".py")
106 loader = SourceFileLoader(cls.__PCBIOS_MODULE_NAME, modulePath) 106 loader = SourceFileLoader(cls.__PCBIOS_MODULE_NAME, modulePath)
@@ -108,7 +108,7 @@ class BootimgBiosPlusEFIPlugin(SourcePlugin):
108 loader.exec_module(mod) 108 loader.exec_module(mod)
109 cls.__imgBiosObj = mod.BootimgPcbiosPlugin() 109 cls.__imgBiosObj = mod.BootimgPcbiosPlugin()
110 110
111 # Import bootimg-efi (class name "BootimgEFIPlugin") 111 # Import bootimg_efi (class name "BootimgEFIPlugin")
112 modulePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 112 modulePath = os.path.join(os.path.dirname(os.path.realpath(__file__)),
113 cls.__EFI_MODULE_NAME + ".py") 113 cls.__EFI_MODULE_NAME + ".py")
114 loader = SourceFileLoader(cls.__EFI_MODULE_NAME, modulePath) 114 loader = SourceFileLoader(cls.__EFI_MODULE_NAME, modulePath)
diff --git a/scripts/lib/wic/plugins/source/bootimg-efi.py b/scripts/lib/wic/plugins/source/bootimg_efi.py
index 13a9cddf4e..cf16705a28 100644
--- a/scripts/lib/wic/plugins/source/bootimg-efi.py
+++ b/scripts/lib/wic/plugins/source/bootimg_efi.py
@@ -4,7 +4,7 @@
4# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
5# 5#
6# DESCRIPTION 6# DESCRIPTION
7# This implements the 'bootimg-efi' source plugin class for 'wic' 7# This implements the 'bootimg_efi' source plugin class for 'wic'
8# 8#
9# AUTHORS 9# AUTHORS
10# Tom Zanussi <tom.zanussi (at] linux.intel.com> 10# Tom Zanussi <tom.zanussi (at] linux.intel.com>
@@ -32,7 +32,7 @@ class BootimgEFIPlugin(SourcePlugin):
32 This plugin supports GRUB 2 and systemd-boot bootloaders. 32 This plugin supports GRUB 2 and systemd-boot bootloaders.
33 """ 33 """
34 34
35 name = 'bootimg-efi' 35 name = 'bootimg_efi'
36 36
37 @classmethod 37 @classmethod
38 def _copy_additional_files(cls, hdddir, initrd, dtb): 38 def _copy_additional_files(cls, hdddir, initrd, dtb):
@@ -43,16 +43,18 @@ class BootimgEFIPlugin(SourcePlugin):
43 if initrd: 43 if initrd:
44 initrds = initrd.split(';') 44 initrds = initrd.split(';')
45 for rd in initrds: 45 for rd in initrds:
46 cp_cmd = "cp %s/%s %s" % (bootimg_dir, rd, hdddir) 46 cp_cmd = "cp -v -p %s/%s %s" % (bootimg_dir, rd, hdddir)
47 exec_cmd(cp_cmd, True) 47 out = exec_cmd(cp_cmd, True)
48 logger.debug("initrd files:\n%s" % (out))
48 else: 49 else:
49 logger.debug("Ignoring missing initrd") 50 logger.debug("Ignoring missing initrd")
50 51
51 if dtb: 52 if dtb:
52 if ';' in dtb: 53 if ';' in dtb:
53 raise WicError("Only one DTB supported, exiting") 54 raise WicError("Only one DTB supported, exiting")
54 cp_cmd = "cp %s/%s %s" % (bootimg_dir, dtb, hdddir) 55 cp_cmd = "cp -v -p %s/%s %s" % (bootimg_dir, dtb, hdddir)
55 exec_cmd(cp_cmd, True) 56 out = exec_cmd(cp_cmd, True)
57 logger.debug("dtb files:\n%s" % (out))
56 58
57 @classmethod 59 @classmethod
58 def do_configure_grubefi(cls, hdddir, creator, cr_workdir, source_params): 60 def do_configure_grubefi(cls, hdddir, creator, cr_workdir, source_params):
@@ -123,8 +125,16 @@ class BootimgEFIPlugin(SourcePlugin):
123 @classmethod 125 @classmethod
124 def do_configure_systemdboot(cls, hdddir, creator, cr_workdir, source_params): 126 def do_configure_systemdboot(cls, hdddir, creator, cr_workdir, source_params):
125 """ 127 """
126 Create loader-specific systemd-boot/gummiboot config 128 Create loader-specific systemd-boot/gummiboot config. Unified Kernel Image (uki)
129 support is done in image recipe with uki.bbclass and only systemd-boot loader config
130 and ESP partition structure is created here.
127 """ 131 """
132 # detect uki.bbclass usage
133 image_classes = get_bitbake_var("IMAGE_CLASSES").split()
134 unified_image = False
135 if "uki" in image_classes:
136 unified_image = True
137
128 install_cmd = "install -d %s/loader" % hdddir 138 install_cmd = "install -d %s/loader" % hdddir
129 exec_cmd(install_cmd) 139 exec_cmd(install_cmd)
130 140
@@ -132,28 +142,26 @@ class BootimgEFIPlugin(SourcePlugin):
132 exec_cmd(install_cmd) 142 exec_cmd(install_cmd)
133 143
134 bootloader = creator.ks.bootloader 144 bootloader = creator.ks.bootloader
135
136 unified_image = source_params.get('create-unified-kernel-image') == "true"
137
138 loader_conf = "" 145 loader_conf = ""
139 if not unified_image:
140 loader_conf += "default boot\n"
141 loader_conf += "timeout %d\n" % bootloader.timeout
142 146
143 initrd = source_params.get('initrd') 147 # 5 seconds is a sensible default timeout
144 dtb = source_params.get('dtb') 148 loader_conf += "timeout %d\n" % (bootloader.timeout or 5)
145
146 if not unified_image:
147 cls._copy_additional_files(hdddir, initrd, dtb)
148 149
149 logger.debug("Writing systemd-boot config " 150 logger.debug("Writing systemd-boot config "
150 "%s/hdd/boot/loader/loader.conf", cr_workdir) 151 "%s/hdd/boot/loader/loader.conf", cr_workdir)
151 cfg = open("%s/hdd/boot/loader/loader.conf" % cr_workdir, "w") 152 cfg = open("%s/hdd/boot/loader/loader.conf" % cr_workdir, "w")
152 cfg.write(loader_conf) 153 cfg.write(loader_conf)
154 logger.debug("loader.conf:\n%s" % (loader_conf))
153 cfg.close() 155 cfg.close()
154 156
157 initrd = source_params.get('initrd')
158 dtb = source_params.get('dtb')
159 if not unified_image:
160 cls._copy_additional_files(hdddir, initrd, dtb)
161
155 configfile = creator.ks.bootloader.configfile 162 configfile = creator.ks.bootloader.configfile
156 custom_cfg = None 163 custom_cfg = None
164 boot_conf = ""
157 if configfile: 165 if configfile:
158 custom_cfg = get_custom_config(configfile) 166 custom_cfg = get_custom_config(configfile)
159 if custom_cfg: 167 if custom_cfg:
@@ -164,8 +172,7 @@ class BootimgEFIPlugin(SourcePlugin):
164 else: 172 else:
165 raise WicError("configfile is specified but failed to " 173 raise WicError("configfile is specified but failed to "
166 "get it from %s.", configfile) 174 "get it from %s.", configfile)
167 175 else:
168 if not custom_cfg:
169 # Create systemd-boot configuration using parameters from wks file 176 # Create systemd-boot configuration using parameters from wks file
170 kernel = get_bitbake_var("KERNEL_IMAGETYPE") 177 kernel = get_bitbake_var("KERNEL_IMAGETYPE")
171 if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1": 178 if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1":
@@ -175,7 +182,6 @@ class BootimgEFIPlugin(SourcePlugin):
175 182
176 title = source_params.get('title') 183 title = source_params.get('title')
177 184
178 boot_conf = ""
179 boot_conf += "title %s\n" % (title if title else "boot") 185 boot_conf += "title %s\n" % (title if title else "boot")
180 boot_conf += "linux /%s\n" % kernel 186 boot_conf += "linux /%s\n" % kernel
181 187
@@ -200,6 +206,7 @@ class BootimgEFIPlugin(SourcePlugin):
200 "%s/hdd/boot/loader/entries/boot.conf", cr_workdir) 206 "%s/hdd/boot/loader/entries/boot.conf", cr_workdir)
201 cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w") 207 cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w")
202 cfg.write(boot_conf) 208 cfg.write(boot_conf)
209 logger.debug("boot.conf:\n%s" % (boot_conf))
203 cfg.close() 210 cfg.close()
204 211
205 212
@@ -223,9 +230,9 @@ class BootimgEFIPlugin(SourcePlugin):
223 elif source_params['loader'] == 'uefi-kernel': 230 elif source_params['loader'] == 'uefi-kernel':
224 pass 231 pass
225 else: 232 else:
226 raise WicError("unrecognized bootimg-efi loader: %s" % source_params['loader']) 233 raise WicError("unrecognized bootimg_efi loader: %s" % source_params['loader'])
227 except KeyError: 234 except KeyError:
228 raise WicError("bootimg-efi requires a loader, none specified") 235 raise WicError("bootimg_efi requires a loader, none specified")
229 236
230 if get_bitbake_var("IMAGE_EFI_BOOT_FILES") is None: 237 if get_bitbake_var("IMAGE_EFI_BOOT_FILES") is None:
231 logger.debug('No boot files defined in IMAGE_EFI_BOOT_FILES') 238 logger.debug('No boot files defined in IMAGE_EFI_BOOT_FILES')
@@ -245,7 +252,7 @@ class BootimgEFIPlugin(SourcePlugin):
245 252
246 # list of tuples (src_name, dst_name) 253 # list of tuples (src_name, dst_name)
247 deploy_files = [] 254 deploy_files = []
248 for src_entry in re.findall(r'[\w;\-\./\*]+', boot_files): 255 for src_entry in re.findall(r'[\w;\-\.\+/\*]+', boot_files):
249 if ';' in src_entry: 256 if ';' in src_entry:
250 dst_entry = tuple(src_entry.split(';')) 257 dst_entry = tuple(src_entry.split(';'))
251 if not dst_entry[0] or not dst_entry[1]: 258 if not dst_entry[0] or not dst_entry[1]:
@@ -304,134 +311,43 @@ class BootimgEFIPlugin(SourcePlugin):
304 (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME")) 311 (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME"))
305 312
306 if source_params.get('create-unified-kernel-image') == "true": 313 if source_params.get('create-unified-kernel-image') == "true":
307 initrd = source_params.get('initrd') 314 raise WicError("create-unified-kernel-image is no longer supported. Please use uki.bbclass.")
308 if not initrd:
309 raise WicError("initrd= must be specified when create-unified-kernel-image=true, exiting")
310
311 deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
312 efi_stub = glob("%s/%s" % (deploy_dir, "linux*.efi.stub"))
313 if len(efi_stub) == 0:
314 raise WicError("Unified Kernel Image EFI stub not found, exiting")
315 efi_stub = efi_stub[0]
316
317 with tempfile.TemporaryDirectory() as tmp_dir:
318 label = source_params.get('label')
319 label_conf = "root=%s" % creator.rootdev
320 if label:
321 label_conf = "LABEL=%s" % label
322
323 bootloader = creator.ks.bootloader
324 cmdline = open("%s/cmdline" % tmp_dir, "w")
325 cmdline.write("%s %s" % (label_conf, bootloader.append))
326 cmdline.close()
327 315
328 initrds = initrd.split(';') 316 if source_params.get('install-kernel-into-boot-dir') != 'false':
329 initrd = open("%s/initrd" % tmp_dir, "wb") 317 install_cmd = "install -v -p -m 0644 %s/%s %s/%s" % \
330 for f in initrds: 318 (staging_kernel_dir, kernel, hdddir, kernel)
331 with open("%s/%s" % (deploy_dir, f), 'rb') as in_file: 319 out = exec_cmd(install_cmd)
332 shutil.copyfileobj(in_file, initrd) 320 logger.debug("Installed kernel files:\n%s" % out)
333 initrd.close()
334
335 # Searched by systemd-boot:
336 # https://systemd.io/BOOT_LOADER_SPECIFICATION/#type-2-efi-unified-kernel-images
337 install_cmd = "install -d %s/EFI/Linux" % hdddir
338 exec_cmd(install_cmd)
339
340 staging_dir_host = get_bitbake_var("STAGING_DIR_HOST")
341 target_sys = get_bitbake_var("TARGET_SYS")
342
343 objdump_cmd = "%s-objdump" % target_sys
344 objdump_cmd += " -p %s" % efi_stub
345 objdump_cmd += " | awk '{ if ($1 == \"SectionAlignment\"){print $2} }'"
346
347 ret, align_str = exec_native_cmd(objdump_cmd, native_sysroot)
348 align = int(align_str, 16)
349
350 objdump_cmd = "%s-objdump" % target_sys
351 objdump_cmd += " -h %s | tail -2" % efi_stub
352 ret, output = exec_native_cmd(objdump_cmd, native_sysroot)
353
354 offset = int(output.split()[2], 16) + int(output.split()[3], 16)
355
356 osrel_off = offset + align - offset % align
357 osrel_path = "%s/usr/lib/os-release" % staging_dir_host
358 osrel_sz = os.stat(osrel_path).st_size
359
360 cmdline_off = osrel_off + osrel_sz
361 cmdline_off = cmdline_off + align - cmdline_off % align
362 cmdline_sz = os.stat(cmdline.name).st_size
363
364 dtb_off = cmdline_off + cmdline_sz
365 dtb_off = dtb_off + align - dtb_off % align
366
367 dtb = source_params.get('dtb')
368 if dtb:
369 if ';' in dtb:
370 raise WicError("Only one DTB supported, exiting")
371 dtb_path = "%s/%s" % (deploy_dir, dtb)
372 dtb_params = '--add-section .dtb=%s --change-section-vma .dtb=0x%x' % \
373 (dtb_path, dtb_off)
374 linux_off = dtb_off + os.stat(dtb_path).st_size
375 linux_off = linux_off + align - linux_off % align
376 else:
377 dtb_params = ''
378 linux_off = dtb_off
379
380 linux_path = "%s/%s" % (staging_kernel_dir, kernel)
381 linux_sz = os.stat(linux_path).st_size
382
383 initrd_off = linux_off + linux_sz
384 initrd_off = initrd_off + align - initrd_off % align
385
386 # https://www.freedesktop.org/software/systemd/man/systemd-stub.html
387 objcopy_cmd = "%s-objcopy" % target_sys
388 objcopy_cmd += " --enable-deterministic-archives"
389 objcopy_cmd += " --preserve-dates"
390 objcopy_cmd += " --add-section .osrel=%s" % osrel_path
391 objcopy_cmd += " --change-section-vma .osrel=0x%x" % osrel_off
392 objcopy_cmd += " --add-section .cmdline=%s" % cmdline.name
393 objcopy_cmd += " --change-section-vma .cmdline=0x%x" % cmdline_off
394 objcopy_cmd += dtb_params
395 objcopy_cmd += " --add-section .linux=%s" % linux_path
396 objcopy_cmd += " --change-section-vma .linux=0x%x" % linux_off
397 objcopy_cmd += " --add-section .initrd=%s" % initrd.name
398 objcopy_cmd += " --change-section-vma .initrd=0x%x" % initrd_off
399 objcopy_cmd += " %s %s/EFI/Linux/linux.efi" % (efi_stub, hdddir)
400
401 exec_native_cmd(objcopy_cmd, native_sysroot)
402 else:
403 if source_params.get('install-kernel-into-boot-dir') != 'false':
404 install_cmd = "install -m 0644 %s/%s %s/%s" % \
405 (staging_kernel_dir, kernel, hdddir, kernel)
406 exec_cmd(install_cmd)
407 321
408 if get_bitbake_var("IMAGE_EFI_BOOT_FILES"): 322 if get_bitbake_var("IMAGE_EFI_BOOT_FILES"):
409 for src_path, dst_path in cls.install_task: 323 for src_path, dst_path in cls.install_task:
410 install_cmd = "install -m 0644 -D %s %s" \ 324 install_cmd = "install -v -p -m 0644 -D %s %s" \
411 % (os.path.join(kernel_dir, src_path), 325 % (os.path.join(kernel_dir, src_path),
412 os.path.join(hdddir, dst_path)) 326 os.path.join(hdddir, dst_path))
413 exec_cmd(install_cmd) 327 out = exec_cmd(install_cmd)
328 logger.debug("Installed IMAGE_EFI_BOOT_FILES:\n%s" % out)
414 329
415 try: 330 try:
416 if source_params['loader'] == 'grub-efi': 331 if source_params['loader'] == 'grub-efi':
417 shutil.copyfile("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir, 332 shutil.copyfile("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir,
418 "%s/grub.cfg" % cr_workdir) 333 "%s/grub.cfg" % cr_workdir)
419 for mod in [x for x in os.listdir(kernel_dir) if x.startswith("grub-efi-")]: 334 for mod in [x for x in os.listdir(kernel_dir) if x.startswith("grub-efi-")]:
420 cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[9:]) 335 cp_cmd = "cp -v -p %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[9:])
421 exec_cmd(cp_cmd, True) 336 exec_cmd(cp_cmd, True)
422 shutil.move("%s/grub.cfg" % cr_workdir, 337 shutil.move("%s/grub.cfg" % cr_workdir,
423 "%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir) 338 "%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir)
424 elif source_params['loader'] == 'systemd-boot': 339 elif source_params['loader'] == 'systemd-boot':
425 for mod in [x for x in os.listdir(kernel_dir) if x.startswith("systemd-")]: 340 for mod in [x for x in os.listdir(kernel_dir) if x.startswith("systemd-")]:
426 cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[8:]) 341 cp_cmd = "cp -v -p %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[8:])
427 exec_cmd(cp_cmd, True) 342 out = exec_cmd(cp_cmd, True)
343 logger.debug("systemd-boot files:\n%s" % out)
428 elif source_params['loader'] == 'uefi-kernel': 344 elif source_params['loader'] == 'uefi-kernel':
429 kernel = get_bitbake_var("KERNEL_IMAGETYPE") 345 kernel = get_bitbake_var("KERNEL_IMAGETYPE")
430 if not kernel: 346 if not kernel:
431 raise WicError("Empty KERNEL_IMAGETYPE %s\n" % target) 347 raise WicError("Empty KERNEL_IMAGETYPE")
432 target = get_bitbake_var("TARGET_SYS") 348 target = get_bitbake_var("TARGET_SYS")
433 if not target: 349 if not target:
434 raise WicError("Unknown arch (TARGET_SYS) %s\n" % target) 350 raise WicError("Empty TARGET_SYS")
435 351
436 if re.match("x86_64", target): 352 if re.match("x86_64", target):
437 kernel_efi_image = "bootx64.efi" 353 kernel_efi_image = "bootx64.efi"
@@ -445,23 +361,33 @@ class BootimgEFIPlugin(SourcePlugin):
445 raise WicError("UEFI stub kernel is incompatible with target %s" % target) 361 raise WicError("UEFI stub kernel is incompatible with target %s" % target)
446 362
447 for mod in [x for x in os.listdir(kernel_dir) if x.startswith(kernel)]: 363 for mod in [x for x in os.listdir(kernel_dir) if x.startswith(kernel)]:
448 cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, kernel_efi_image) 364 cp_cmd = "cp -v -p %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, kernel_efi_image)
449 exec_cmd(cp_cmd, True) 365 out = exec_cmd(cp_cmd, True)
366 logger.debug("uefi-kernel files:\n%s" % out)
450 else: 367 else:
451 raise WicError("unrecognized bootimg-efi loader: %s" % 368 raise WicError("unrecognized bootimg_efi loader: %s" %
452 source_params['loader']) 369 source_params['loader'])
370
371 # must have installed at least one EFI bootloader
372 out = glob(os.path.join(hdddir, 'EFI', 'BOOT', 'boot*.efi'))
373 logger.debug("Installed EFI loader files:\n%s" % out)
374 if not out:
375 raise WicError("No EFI loaders installed to ESP partition. Check that grub-efi, systemd-boot or similar is installed.")
376
453 except KeyError: 377 except KeyError:
454 raise WicError("bootimg-efi requires a loader, none specified") 378 raise WicError("bootimg_efi requires a loader, none specified")
455 379
456 startup = os.path.join(kernel_dir, "startup.nsh") 380 startup = os.path.join(kernel_dir, "startup.nsh")
457 if os.path.exists(startup): 381 if os.path.exists(startup):
458 cp_cmd = "cp %s %s/" % (startup, hdddir) 382 cp_cmd = "cp -v -p %s %s/" % (startup, hdddir)
459 exec_cmd(cp_cmd, True) 383 out = exec_cmd(cp_cmd, True)
384 logger.debug("startup files:\n%s" % out)
460 385
461 for paths in part.include_path or []: 386 for paths in part.include_path or []:
462 for path in paths: 387 for path in paths:
463 cp_cmd = "cp -r %s %s/" % (path, hdddir) 388 cp_cmd = "cp -v -p -r %s %s/" % (path, hdddir)
464 exec_cmd(cp_cmd, True) 389 exec_cmd(cp_cmd, True)
390 logger.debug("include_path files:\n%s" % out)
465 391
466 du_cmd = "du -bks %s" % hdddir 392 du_cmd = "du -bks %s" % hdddir
467 out = exec_cmd(du_cmd) 393 out = exec_cmd(du_cmd)
@@ -489,12 +415,14 @@ class BootimgEFIPlugin(SourcePlugin):
489 415
490 label = part.label if part.label else "ESP" 416 label = part.label if part.label else "ESP"
491 417
492 dosfs_cmd = "mkdosfs -n %s -i %s -C %s %d" % \ 418 dosfs_cmd = "mkdosfs -v -n %s -i %s -C %s %d" % \
493 (label, part.fsuuid, bootimg, blocks) 419 (label, part.fsuuid, bootimg, blocks)
494 exec_native_cmd(dosfs_cmd, native_sysroot) 420 exec_native_cmd(dosfs_cmd, native_sysroot)
421 logger.debug("mkdosfs:\n%s" % (str(out)))
495 422
496 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir) 423 mcopy_cmd = "mcopy -v -p -i %s -s %s/* ::/" % (bootimg, hdddir)
497 exec_native_cmd(mcopy_cmd, native_sysroot) 424 out = exec_native_cmd(mcopy_cmd, native_sysroot)
425 logger.debug("mcopy:\n%s" % (str(out)))
498 426
499 chmod_cmd = "chmod 644 %s" % bootimg 427 chmod_cmd = "chmod 644 %s" % bootimg
500 exec_cmd(chmod_cmd) 428 exec_cmd(chmod_cmd)
diff --git a/scripts/lib/wic/plugins/source/bootimg-partition.py b/scripts/lib/wic/plugins/source/bootimg_partition.py
index 1071d1af3f..cc121a78f0 100644
--- a/scripts/lib/wic/plugins/source/bootimg-partition.py
+++ b/scripts/lib/wic/plugins/source/bootimg_partition.py
@@ -4,7 +4,7 @@
4# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
5# 5#
6# DESCRIPTION 6# DESCRIPTION
7# This implements the 'bootimg-partition' source plugin class for 7# This implements the 'bootimg_partition' source plugin class for
8# 'wic'. The plugin creates an image of boot partition, copying over 8# 'wic'. The plugin creates an image of boot partition, copying over
9# files listed in IMAGE_BOOT_FILES bitbake variable. 9# files listed in IMAGE_BOOT_FILES bitbake variable.
10# 10#
@@ -16,7 +16,7 @@ import logging
16import os 16import os
17import re 17import re
18 18
19from glob import glob 19from oe.bootfiles import get_boot_files
20 20
21from wic import WicError 21from wic import WicError
22from wic.engine import get_custom_config 22from wic.engine import get_custom_config
@@ -31,7 +31,7 @@ class BootimgPartitionPlugin(SourcePlugin):
31 listed in IMAGE_BOOT_FILES bitbake variable. 31 listed in IMAGE_BOOT_FILES bitbake variable.
32 """ 32 """
33 33
34 name = 'bootimg-partition' 34 name = 'bootimg_partition'
35 image_boot_files_var_name = 'IMAGE_BOOT_FILES' 35 image_boot_files_var_name = 'IMAGE_BOOT_FILES'
36 36
37 @classmethod 37 @classmethod
@@ -66,42 +66,7 @@ class BootimgPartitionPlugin(SourcePlugin):
66 66
67 logger.debug('Boot files: %s', boot_files) 67 logger.debug('Boot files: %s', boot_files)
68 68
69 # list of tuples (src_name, dst_name) 69 cls.install_task = get_boot_files(kernel_dir, boot_files)
70 deploy_files = []
71 for src_entry in re.findall(r'[\w;\-\./\*]+', boot_files):
72 if ';' in src_entry:
73 dst_entry = tuple(src_entry.split(';'))
74 if not dst_entry[0] or not dst_entry[1]:
75 raise WicError('Malformed boot file entry: %s' % src_entry)
76 else:
77 dst_entry = (src_entry, src_entry)
78
79 logger.debug('Destination entry: %r', dst_entry)
80 deploy_files.append(dst_entry)
81
82 cls.install_task = [];
83 for deploy_entry in deploy_files:
84 src, dst = deploy_entry
85 if '*' in src:
86 # by default install files under their basename
87 entry_name_fn = os.path.basename
88 if dst != src:
89 # unless a target name was given, then treat name
90 # as a directory and append a basename
91 entry_name_fn = lambda name: \
92 os.path.join(dst,
93 os.path.basename(name))
94
95 srcs = glob(os.path.join(kernel_dir, src))
96
97 logger.debug('Globbed sources: %s', ', '.join(srcs))
98 for entry in srcs:
99 src = os.path.relpath(entry, kernel_dir)
100 entry_dst_name = entry_name_fn(entry)
101 cls.install_task.append((src, entry_dst_name))
102 else:
103 cls.install_task.append((src, dst))
104
105 if source_params.get('loader') != "u-boot": 70 if source_params.get('loader') != "u-boot":
106 return 71 return
107 72
diff --git a/scripts/lib/wic/plugins/source/bootimg_pcbios.py b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
new file mode 100644
index 0000000000..caabda6318
--- /dev/null
+++ b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
@@ -0,0 +1,483 @@
1#
2# Copyright (c) 2014, Intel Corporation.
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6# DESCRIPTION
7# This implements the 'bootimg_pcbios' source plugin class for 'wic'
8#
9# AUTHORS
10# Tom Zanussi <tom.zanussi (at] linux.intel.com>
11#
12
13import logging
14import os
15import re
16import shutil
17
18from glob import glob
19from wic import WicError
20from wic.engine import get_custom_config
21from wic.pluginbase import SourcePlugin
22from wic.misc import (exec_cmd, exec_native_cmd,
23 get_bitbake_var, BOOTDD_EXTRA_SPACE)
24
25logger = logging.getLogger('wic')
26
27class BootimgPcbiosPlugin(SourcePlugin):
28 """
29 Creates boot partition that is legacy BIOS firmare bootable with
30 MBR/MSDOS as partition table format. Plugin will install caller
31 selected bootloader directly to resulting wic image.
32
33 Supported Bootloaders:
34 * syslinux (default)
35 * grub
36
37 ****************** Wic Plugin Depends/Vars ******************
38 WKS_FILE_DEPENDS = "grub-native grub"
39 WKS_FILE_DEPENDS = "syslinux-native syslinux"
40
41 # Optional variables
42 # GRUB_MKIMAGE_FORMAT_PC - Used to define target platform.
43 # GRUB_PREFIX_PATH - Used to define which directory
44 # grub config and modules are going
45 # to reside in.
46 GRUB_PREFIX_PATH = '/boot/grub2' # Default: /boot/grub
47 GRUB_MKIMAGE_FORMAT_PC = 'i386-pc' # Default: i386-pc
48
49 WICVARS:append = "\
50 GRUB_PREFIX_PATH \
51 GRUB_MKIMAGE_FORMAT_PC \
52 "
53 ****************** Wic Plugin Depends/Vars ******************
54
55
56 **************** Example kickstart Legacy Bios Grub Boot ****************
57 part boot --label bios_boot --fstype ext4 --offset 1024 --fixed-size 78M
58 --source bootimg_pcbios --sourceparams="loader-bios=grub" --active
59
60 part roots --label rootfs --fstype ext4 --source rootfs --use-uuid
61 bootloader --ptable msdos --source bootimg_pcbios
62 **************** Example kickstart Legacy Bios Grub Boot ****************
63
64
65 *************** Example kickstart Legacy Bios Syslinux Boot ****************
66 part /boot --source bootimg_pcbios --sourceparams="loader-bios=syslinux"
67 --ondisk sda --label boot --fstype vfat --align 1024 --active
68
69 part roots --label rootfs --fstype ext4 --source rootfs --use-uuid
70 bootloader --ptable msdos --source bootimg_pcbios
71 """
72
73 name = 'bootimg_pcbios'
74
75 # Variable required for do_install_disk
76 loader = ''
77
78 @classmethod
79 def _get_bootimg_dir(cls, bootimg_dir, dirname):
80 """
81 Check if dirname exists in default bootimg_dir or in STAGING_DIR.
82 """
83 staging_datadir = get_bitbake_var("STAGING_DATADIR")
84 for result in (bootimg_dir, staging_datadir):
85 if os.path.exists("%s/%s" % (result, dirname)):
86 return result
87
88 # STAGING_DATADIR is expanded with MLPREFIX if multilib is enabled
89 # but dependency syslinux is still populated to original STAGING_DATADIR
90 nonarch_datadir = re.sub('/[^/]*recipe-sysroot', '/recipe-sysroot', staging_datadir)
91 if os.path.exists(os.path.join(nonarch_datadir, dirname)):
92 return nonarch_datadir
93
94 raise WicError("Couldn't find correct bootimg_dir, exiting")
95
96 @classmethod
97 def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir,
98 bootimg_dir, kernel_dir, native_sysroot):
99 full_path = creator._full_path(workdir, disk_name, "direct")
100 logger.debug("Installing MBR on disk %s as %s with size %s bytes",
101 disk_name, full_path, disk.min_size)
102
103 if cls.loader == 'grub':
104 cls._do_install_grub(creator, kernel_dir,
105 native_sysroot, full_path)
106 elif cls.loader == 'syslinux':
107 cls._do_install_syslinux(creator, bootimg_dir,
108 native_sysroot, full_path)
109 else:
110 raise WicError("boot loader some how not specified check do_prepare_partition")
111
112 @classmethod
113 def do_configure_partition(cls, part, source_params, creator, cr_workdir,
114 oe_builddir, bootimg_dir, kernel_dir,
115 native_sysroot):
116 try:
117 if source_params['loader-bios'] == 'grub':
118 cls._do_configure_grub(part, creator, cr_workdir)
119 elif source_params['loader-bios'] == 'syslinux':
120 cls._do_configure_syslinux(part, creator, cr_workdir)
121 else:
122 raise WicError("unrecognized bootimg_pcbios loader: %s" % source_params['loader-bios'])
123 except KeyError:
124 cls._do_configure_syslinux(part, creator, cr_workdir)
125
126 @classmethod
127 def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
128 oe_builddir, bootimg_dir, kernel_dir,
129 rootfs_dir, native_sysroot):
130 try:
131 if source_params['loader-bios'] == 'grub':
132 cls._do_prepare_grub(part, cr_workdir, oe_builddir,
133 kernel_dir, rootfs_dir, native_sysroot)
134 elif source_params['loader-bios'] == 'syslinux':
135 cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
136 kernel_dir, native_sysroot)
137 else:
138 raise WicError("unrecognized bootimg_pcbios loader: %s" % source_params['loader-bios'])
139
140 # Required by do_install_disk
141 cls.loader = source_params['loader-bios']
142 except KeyError:
143 # Required by do_install_disk
144 cls.loader = 'syslinux'
145 cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
146 kernel_dir, native_sysroot)
147
148 @classmethod
149 def _get_staging_libdir(cls):
150 """
151 For unknown reasons when running test with poky
152 STAGING_LIBDIR gets unset when wic create is executed.
153 Bellow is a hack to determine what STAGING_LIBDIR should
154 be if not specified.
155 """
156
157 staging_libdir = get_bitbake_var('STAGING_LIBDIR')
158 staging_dir_target = get_bitbake_var('STAGING_DIR_TARGET')
159
160 if not staging_libdir:
161 staging_libdir = '%s/usr/lib64' % staging_dir_target
162 if not os.path.isdir(staging_libdir):
163 staging_libdir = '%s/usr/lib32' % staging_dir_target
164 if not os.path.isdir(staging_libdir):
165 staging_libdir = '%s/usr/lib' % staging_dir_target
166
167 return staging_libdir
168
169 @classmethod
170 def _get_bootloader_config(cls, bootloader, loader):
171 custom_cfg = None
172
173 if bootloader.configfile:
174 custom_cfg = get_custom_config(bootloader.configfile)
175 if custom_cfg:
176 logger.debug("Using custom configuration file %s "
177 "for %s.cfg", bootloader.configfile,
178 loader)
179 return custom_cfg
180 else:
181 raise WicError("configfile is specified but failed to "
182 "get it from %s." % bootloader.configfile)
183 return custom_cfg
184
185 @classmethod
186 def _do_configure_syslinux(cls, part, creator, cr_workdir):
187 """
188 Called before do_prepare_partition(), creates syslinux config
189 """
190
191 hdddir = "%s/hdd/boot" % cr_workdir
192
193 install_cmd = "install -d %s" % hdddir
194 exec_cmd(install_cmd)
195
196 bootloader = creator.ks.bootloader
197 syslinux_conf = cls._get_bootloader_config(bootloader, 'syslinux')
198
199 if not syslinux_conf:
200 # Create syslinux configuration using parameters from wks file
201 splash = os.path.join(hdddir, "/splash.jpg")
202 if os.path.exists(splash):
203 splashline = "menu background splash.jpg"
204 else:
205 splashline = ""
206
207 # Set a default timeout if none specified to avoid
208 # 'None' being the value placed within the configuration
209 # file.
210 if not bootloader.timeout:
211 bootloader.timeout = 500
212
213 # Set a default kernel params string if none specified
214 # to avoid 'None' being the value placed within the
215 # configuration file.
216 if not bootloader.append:
217 bootloader.append = "rootwait console=ttyS0,115200 console=tty0"
218
219 syslinux_conf = ""
220 syslinux_conf += "PROMPT 0\n"
221 syslinux_conf += "TIMEOUT " + str(bootloader.timeout) + "\n"
222 syslinux_conf += "\n"
223 syslinux_conf += "ALLOWOPTIONS 1\n"
224 syslinux_conf += "SERIAL 0 115200\n"
225 syslinux_conf += "\n"
226 if splashline:
227 syslinux_conf += "%s\n" % splashline
228 syslinux_conf += "DEFAULT boot\n"
229 syslinux_conf += "LABEL boot\n"
230
231 kernel = "/" + get_bitbake_var("KERNEL_IMAGETYPE")
232 syslinux_conf += "KERNEL " + kernel + "\n"
233
234 syslinux_conf += "APPEND label=boot root=%s %s\n" % \
235 (creator.rootdev, bootloader.append)
236
237 logger.debug("Writing syslinux config %s/syslinux.cfg", hdddir)
238 cfg = open("%s/hdd/boot/syslinux.cfg" % cr_workdir, "w")
239 cfg.write(syslinux_conf)
240 cfg.close()
241
242 @classmethod
243 def _do_prepare_syslinux(cls, part, cr_workdir, bootimg_dir,
244 kernel_dir, native_sysroot):
245 """
246 Called to do the actual content population for a partition i.e. it
247 'prepares' the partition to be incorporated into the image.
248 In this case, prepare content for legacy bios boot partition.
249 """
250 bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux')
251
252 staging_kernel_dir = kernel_dir
253
254 hdddir = "%s/hdd/boot" % cr_workdir
255
256 kernel = get_bitbake_var("KERNEL_IMAGETYPE")
257 if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1":
258 if get_bitbake_var("INITRAMFS_IMAGE"):
259 kernel = "%s-%s.bin" % \
260 (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME"))
261
262 cmds = ("install -m 0644 %s/%s %s/%s" %
263 (staging_kernel_dir, kernel, hdddir, get_bitbake_var("KERNEL_IMAGETYPE")),
264 "install -m 444 %s/syslinux/ldlinux.sys %s/ldlinux.sys" %
265 (bootimg_dir, hdddir),
266 "install -m 0644 %s/syslinux/vesamenu.c32 %s/vesamenu.c32" %
267 (bootimg_dir, hdddir),
268 "install -m 444 %s/syslinux/libcom32.c32 %s/libcom32.c32" %
269 (bootimg_dir, hdddir),
270 "install -m 444 %s/syslinux/libutil.c32 %s/libutil.c32" %
271 (bootimg_dir, hdddir))
272
273 for install_cmd in cmds:
274 exec_cmd(install_cmd)
275
276 du_cmd = "du -bks %s" % hdddir
277 out = exec_cmd(du_cmd)
278 blocks = int(out.split()[0])
279
280 extra_blocks = part.get_extra_block_count(blocks)
281
282 if extra_blocks < BOOTDD_EXTRA_SPACE:
283 extra_blocks = BOOTDD_EXTRA_SPACE
284
285 blocks += extra_blocks
286
287 logger.debug("Added %d extra blocks to %s to get to %d total blocks",
288 extra_blocks, part.mountpoint, blocks)
289
290 # dosfs image, created by mkdosfs
291 bootimg = "%s/boot%s.img" % (cr_workdir, part.lineno)
292
293 label = part.label if part.label else "boot"
294
295 dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
296 (label, part.fsuuid, bootimg, blocks)
297 exec_native_cmd(dosfs_cmd, native_sysroot)
298
299 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
300 exec_native_cmd(mcopy_cmd, native_sysroot)
301
302 syslinux_cmd = "syslinux %s" % bootimg
303 exec_native_cmd(syslinux_cmd, native_sysroot)
304
305 chmod_cmd = "chmod 644 %s" % bootimg
306 exec_cmd(chmod_cmd)
307
308 du_cmd = "du -Lbks %s" % bootimg
309 out = exec_cmd(du_cmd)
310 bootimg_size = out.split()[0]
311
312 part.size = int(bootimg_size)
313 part.source_file = bootimg
314
315 @classmethod
316 def _do_install_syslinux(cls, creator, bootimg_dir,
317 native_sysroot, full_path):
318 """
319 Called after all partitions have been prepared and assembled into a
320 disk image. In this case, we install the MBR.
321 """
322
323 bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux')
324 mbrfile = "%s/syslinux/" % bootimg_dir
325 if creator.ptable_format == 'msdos':
326 mbrfile += "mbr.bin"
327 elif creator.ptable_format == 'gpt':
328 mbrfile += "gptmbr.bin"
329 else:
330 raise WicError("Unsupported partition table: %s" %
331 creator.ptable_format)
332
333 if not os.path.exists(mbrfile):
334 raise WicError("Couldn't find %s. If using the -e option, do you "
335 "have the right MACHINE set in local.conf? If not, "
336 "is the bootimg_dir path correct?" % mbrfile)
337
338 dd_cmd = "dd if=%s of=%s conv=notrunc" % (mbrfile, full_path)
339 exec_cmd(dd_cmd, native_sysroot)
340
341 @classmethod
342 def _do_configure_grub(cls, part, creator, cr_workdir):
343 hdddir = "%s/hdd" % cr_workdir
344 bootloader = creator.ks.bootloader
345
346 grub_conf = cls._get_bootloader_config(bootloader, 'grub')
347
348 grub_prefix_path = get_bitbake_var('GRUB_PREFIX_PATH')
349 if not grub_prefix_path:
350 grub_prefix_path = '/boot/grub'
351
352 grub_path = "%s/%s" %(hdddir, grub_prefix_path)
353 install_cmd = "install -d %s" % grub_path
354 exec_cmd(install_cmd)
355
356 if not grub_conf:
357 # Set a default timeout if none specified to avoid
358 # 'None' being the value placed within the configuration
359 # file.
360 if not bootloader.timeout:
361 bootloader.timeout = 500
362
363 # Set a default kernel params string if none specified
364 # to avoid 'None' being the value placed within the
365 # configuration file.
366 if not bootloader.append:
367 bootloader.append = "rootwait rootfstype=%s " % (part.fstype)
368 bootloader.append += "console=ttyS0,115200 console=tty0"
369
370 kernel = "/boot/" + get_bitbake_var("KERNEL_IMAGETYPE")
371
372 grub_conf = 'serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1\n'
373 grub_conf += 'set gfxmode=auto\n'
374 grub_conf += 'set gfxpayload=keep\n\n'
375 grub_conf += 'set default=0\n\n'
376 grub_conf += '# Boot automatically after %d secs.\n' % (bootloader.timeout)
377 grub_conf += 'set timeout=%d\n\n' % (bootloader.timeout)
378 grub_conf += 'menuentry \'default\' {\n'
379 grub_conf += '\tsearch --no-floppy --set=root --file %s\n' % (kernel)
380 grub_conf += '\tprobe --set partuuid --part-uuid ($root)\n'
381 grub_conf += '\tlinux %s root=PARTUUID=$partuuid %s\n}\n' % \
382 (kernel, bootloader.append)
383
384 logger.debug("Writing grub config %s/grub.cfg", grub_path)
385 cfg = open("%s/grub.cfg" % grub_path, "w")
386 cfg.write(grub_conf)
387 cfg.close()
388
389 @classmethod
390 def _do_prepare_grub(cls, part, cr_workdir, oe_builddir,
391 kernel_dir, rootfs_dir, native_sysroot):
392 """
393 1. Generate embed.cfg that'll later be embedded into core.img.
394 So, that core.img knows where to search for grub.cfg.
395 2. Generate core.img or grub stage 1.5.
396 3. Copy modules into partition.
397 4. Create partition rootfs file.
398 """
399
400 hdddir = "%s/hdd" % cr_workdir
401
402 copy_types = [ '*.mod', '*.o', '*.lst' ]
403
404 builtin_modules = 'boot linux ext2 fat serial part_msdos part_gpt \
405 normal multiboot probe biosdisk msdospart configfile search loadenv test'
406
407 staging_libdir = cls._get_staging_libdir()
408
409 grub_format = get_bitbake_var('GRUB_MKIMAGE_FORMAT_PC')
410 if not grub_format:
411 grub_format = 'i386-pc'
412
413 grub_prefix_path = get_bitbake_var('GRUB_PREFIX_PATH')
414 if not grub_prefix_path:
415 grub_prefix_path = '/boot/grub'
416
417 grub_path = "%s/%s" %(hdddir, grub_prefix_path)
418 core_img = '%s/grub-bios-core.img' % (kernel_dir)
419 grub_mods_path = '%s/grub/%s' % (staging_libdir, grub_format)
420
421 # Generate embedded grub config
422 embed_cfg_str = 'search.file %s/grub.cfg root\n' % (grub_prefix_path)
423 embed_cfg_str += 'set prefix=($root)%s\n' % (grub_prefix_path)
424 embed_cfg_str += 'configfile ($root)%s/grub.cfg\n' % (grub_prefix_path)
425 cfg = open('%s/embed.cfg' % (kernel_dir), 'w+')
426 cfg.write(embed_cfg_str)
427 cfg.close()
428
429 # core.img doesn't get included into boot partition
430 # it's later dd onto the resulting wic image.
431 grub_mkimage = 'grub-mkimage \
432 --prefix=%s \
433 --format=%s \
434 --config=%s/embed.cfg \
435 --directory=%s \
436 --output=%s %s' % \
437 (grub_prefix_path, grub_format, kernel_dir,
438 grub_mods_path, core_img, builtin_modules)
439 exec_native_cmd(grub_mkimage, native_sysroot)
440
441 # Copy grub modules
442 install_dir = '%s/%s/%s' % (hdddir, grub_prefix_path, grub_format)
443 os.makedirs(install_dir, exist_ok=True)
444
445 for ctype in copy_types:
446 files = glob('%s/grub/%s/%s' % \
447 (staging_libdir, grub_format, ctype))
448 for file in files:
449 shutil.copy2(file, install_dir, follow_symlinks=True)
450
451 # Create boot partition
452 logger.debug('Prepare partition using rootfs in %s', hdddir)
453 part.prepare_rootfs(cr_workdir, oe_builddir, hdddir,
454 native_sysroot, False)
455
456 @classmethod
457 def _do_install_grub(cls, creator, kernel_dir,
458 native_sysroot, full_path):
459 core_img = '%s/grub-bios-core.img' % (kernel_dir)
460
461 staging_libdir = cls._get_staging_libdir()
462
463 grub_format = get_bitbake_var('GRUB_MKIMAGE_FORMAT_PC')
464 if not grub_format:
465 grub_format = 'i386-pc'
466
467 boot_img = '%s/grub/%s/boot.img' % (staging_libdir, grub_format)
468 if not os.path.exists(boot_img):
469 raise WicError("Couldn't find %s. Did you include "
470 "do_image_wic[depends] += \"grub:do_populate_sysroot\" "
471 "in your image recipe" % boot_img)
472
473 # Install boot.img or grub stage 1
474 dd_cmd = "dd if=%s of=%s conv=notrunc bs=1 seek=0 count=440" % (boot_img, full_path)
475 exec_cmd(dd_cmd, native_sysroot)
476
477 if creator.ptable_format == 'msdos':
478 # Install core.img or grub stage 1.5
479 dd_cmd = "dd if=%s of=%s conv=notrunc bs=1 seek=512" % (core_img, full_path)
480 exec_cmd(dd_cmd, native_sysroot)
481 else:
482 raise WicError("Unsupported partition table: %s" %
483 creator.ptable_format)
diff --git a/scripts/lib/wic/plugins/source/isoimage-isohybrid.py b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
index 607356ad13..5d42eb5d3e 100644
--- a/scripts/lib/wic/plugins/source/isoimage-isohybrid.py
+++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
@@ -4,7 +4,7 @@
4# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
5# 5#
6# DESCRIPTION 6# DESCRIPTION
7# This implements the 'isoimage-isohybrid' source plugin class for 'wic' 7# This implements the 'isoimage_isohybrid' source plugin class for 'wic'
8# 8#
9# AUTHORS 9# AUTHORS
10# Mihaly Varga <mihaly.varga (at] ni.com> 10# Mihaly Varga <mihaly.varga (at] ni.com>
@@ -35,7 +35,7 @@ class IsoImagePlugin(SourcePlugin):
35 bootloader files. 35 bootloader files.
36 36
37 Example kickstart file: 37 Example kickstart file:
38 part /boot --source isoimage-isohybrid --sourceparams="loader=grub-efi, \\ 38 part /boot --source isoimage_isohybrid --sourceparams="loader=grub-efi, \\
39 image_name= IsoImage" --ondisk cd --label LIVECD 39 image_name= IsoImage" --ondisk cd --label LIVECD
40 bootloader --timeout=10 --append=" " 40 bootloader --timeout=10 --append=" "
41 41
@@ -45,7 +45,7 @@ class IsoImagePlugin(SourcePlugin):
45 extension added by direct imeger plugin) and a file named IsoImage-cd.iso 45 extension added by direct imeger plugin) and a file named IsoImage-cd.iso
46 """ 46 """
47 47
48 name = 'isoimage-isohybrid' 48 name = 'isoimage_isohybrid'
49 49
50 @classmethod 50 @classmethod
51 def do_configure_syslinux(cls, creator, cr_workdir): 51 def do_configure_syslinux(cls, creator, cr_workdir):
@@ -340,10 +340,10 @@ class IsoImagePlugin(SourcePlugin):
340 cls.do_configure_grubefi(part, creator, target_dir) 340 cls.do_configure_grubefi(part, creator, target_dir)
341 341
342 else: 342 else:
343 raise WicError("unrecognized bootimg-efi loader: %s" % 343 raise WicError("unrecognized bootimg_efi loader: %s" %
344 source_params['loader']) 344 source_params['loader'])
345 except KeyError: 345 except KeyError:
346 raise WicError("bootimg-efi requires a loader, none specified") 346 raise WicError("bootimg_efi requires a loader, none specified")
347 347
348 # Create efi.img that contains bootloader files for EFI booting 348 # Create efi.img that contains bootloader files for EFI booting
349 # if ISODIR didn't exist or didn't contains it 349 # if ISODIR didn't exist or didn't contains it
diff --git a/scripts/lib/wic/plugins/source/rootfs.py b/scripts/lib/wic/plugins/source/rootfs.py
index c990143c0d..06fce06bb1 100644
--- a/scripts/lib/wic/plugins/source/rootfs.py
+++ b/scripts/lib/wic/plugins/source/rootfs.py
@@ -41,7 +41,7 @@ class RootfsPlugin(SourcePlugin):
41 # Disallow climbing outside of parent directory using '..', 41 # Disallow climbing outside of parent directory using '..',
42 # because doing so could be quite disastrous (we will delete the 42 # because doing so could be quite disastrous (we will delete the
43 # directory, or modify a directory outside OpenEmbedded). 43 # directory, or modify a directory outside OpenEmbedded).
44 full_path = os.path.realpath(os.path.join(rootfs_dir, path)) 44 full_path = os.path.abspath(os.path.join(rootfs_dir, path))
45 if not full_path.startswith(os.path.realpath(rootfs_dir)): 45 if not full_path.startswith(os.path.realpath(rootfs_dir)):
46 logger.error("%s: Must point inside the rootfs: %s" % (cmd, path)) 46 logger.error("%s: Must point inside the rootfs: %s" % (cmd, path))
47 sys.exit(1) 47 sys.exit(1)