summaryrefslogtreecommitdiffstats
path: root/scripts/lib/wic/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib/wic/plugins')
-rw-r--r--scripts/lib/wic/plugins/imager/direct.py174
-rw-r--r--scripts/lib/wic/plugins/source/bootimg-pcbios.py207
-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)189
-rw-r--r--scripts/lib/wic/plugins/source/bootimg_partition.py (renamed from scripts/lib/wic/plugins/source/bootimg-partition.py)52
-rw-r--r--scripts/lib/wic/plugins/source/bootimg_pcbios.py483
-rw-r--r--scripts/lib/wic/plugins/source/empty.py59
-rw-r--r--scripts/lib/wic/plugins/source/extra_partition.py134
-rw-r--r--scripts/lib/wic/plugins/source/isoimage_isohybrid.py (renamed from scripts/lib/wic/plugins/source/isoimage-isohybrid.py)12
-rw-r--r--scripts/lib/wic/plugins/source/rawcopy.py42
-rw-r--r--scripts/lib/wic/plugins/source/rootfs.py15
11 files changed, 1016 insertions, 381 deletions
diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py
index ea709e8c54..6e1f1c8cba 100644
--- a/scripts/lib/wic/plugins/imager/direct.py
+++ b/scripts/lib/wic/plugins/imager/direct.py
@@ -77,7 +77,8 @@ class DirectPlugin(ImagerPlugin):
77 77
78 image_path = self._full_path(self.workdir, self.parts[0].disk, "direct") 78 image_path = self._full_path(self.workdir, self.parts[0].disk, "direct")
79 self._image = PartitionedImage(image_path, self.ptable_format, 79 self._image = PartitionedImage(image_path, self.ptable_format,
80 self.parts, self.native_sysroot) 80 self.parts, self.native_sysroot,
81 options.extra_space)
81 82
82 def setup_workdir(self, workdir): 83 def setup_workdir(self, workdir):
83 if workdir: 84 if workdir:
@@ -116,7 +117,7 @@ class DirectPlugin(ImagerPlugin):
116 updated = False 117 updated = False
117 for part in self.parts: 118 for part in self.parts:
118 if not part.realnum or not part.mountpoint \ 119 if not part.realnum or not part.mountpoint \
119 or part.mountpoint == "/": 120 or part.mountpoint == "/" or not (part.mountpoint.startswith('/') or part.mountpoint == "swap"):
120 continue 121 continue
121 122
122 if part.use_uuid: 123 if part.use_uuid:
@@ -137,8 +138,9 @@ class DirectPlugin(ImagerPlugin):
137 device_name = "/dev/%s%s%d" % (part.disk, prefix, part.realnum) 138 device_name = "/dev/%s%s%d" % (part.disk, prefix, part.realnum)
138 139
139 opts = part.fsopts if part.fsopts else "defaults" 140 opts = part.fsopts if part.fsopts else "defaults"
141 passno = part.fspassno if part.fspassno else "0"
140 line = "\t".join([device_name, part.mountpoint, part.fstype, 142 line = "\t".join([device_name, part.mountpoint, part.fstype,
141 opts, "0", "0"]) + "\n" 143 opts, "0", passno]) + "\n"
142 144
143 fstab_lines.append(line) 145 fstab_lines.append(line)
144 updated = True 146 updated = True
@@ -147,6 +149,9 @@ class DirectPlugin(ImagerPlugin):
147 self.updated_fstab_path = os.path.join(self.workdir, "fstab") 149 self.updated_fstab_path = os.path.join(self.workdir, "fstab")
148 with open(self.updated_fstab_path, "w") as f: 150 with open(self.updated_fstab_path, "w") as f:
149 f.writelines(fstab_lines) 151 f.writelines(fstab_lines)
152 if os.getenv('SOURCE_DATE_EPOCH'):
153 fstab_time = int(os.getenv('SOURCE_DATE_EPOCH'))
154 os.utime(self.updated_fstab_path, (fstab_time, fstab_time))
150 155
151 def _full_path(self, path, name, extention): 156 def _full_path(self, path, name, extention):
152 """ Construct full file path to a file we generate. """ 157 """ Construct full file path to a file we generate. """
@@ -198,6 +203,8 @@ class DirectPlugin(ImagerPlugin):
198 source_plugin = self.ks.bootloader.source 203 source_plugin = self.ks.bootloader.source
199 disk_name = self.parts[0].disk 204 disk_name = self.parts[0].disk
200 if source_plugin: 205 if source_plugin:
206 # Don't support '-' in plugin names
207 source_plugin = source_plugin.replace("-", "_")
201 plugin = PluginMgr.get_plugins('source')[source_plugin] 208 plugin = PluginMgr.get_plugins('source')[source_plugin]
202 plugin.do_install_disk(self._image, disk_name, self, self.workdir, 209 plugin.do_install_disk(self._image, disk_name, self, self.workdir,
203 self.oe_builddir, self.bootimg_dir, 210 self.oe_builddir, self.bootimg_dir,
@@ -258,6 +265,8 @@ class DirectPlugin(ImagerPlugin):
258 if part.mountpoint == "/": 265 if part.mountpoint == "/":
259 if part.uuid: 266 if part.uuid:
260 return "PARTUUID=%s" % part.uuid 267 return "PARTUUID=%s" % part.uuid
268 elif part.label and self.ptable_format != 'msdos':
269 return "PARTLABEL=%s" % part.label
261 else: 270 else:
262 suffix = 'p' if part.disk.startswith('mmcblk') else '' 271 suffix = 'p' if part.disk.startswith('mmcblk') else ''
263 return "/dev/%s%s%-d" % (part.disk, suffix, part.realnum) 272 return "/dev/%s%s%-d" % (part.disk, suffix, part.realnum)
@@ -293,7 +302,7 @@ class PartitionedImage():
293 Partitioned image in a file. 302 Partitioned image in a file.
294 """ 303 """
295 304
296 def __init__(self, path, ptable_format, partitions, native_sysroot=None): 305 def __init__(self, path, ptable_format, partitions, native_sysroot=None, extra_space=0):
297 self.path = path # Path to the image file 306 self.path = path # Path to the image file
298 self.numpart = 0 # Number of allocated partitions 307 self.numpart = 0 # Number of allocated partitions
299 self.realpart = 0 # Number of partitions in the partition table 308 self.realpart = 0 # Number of partitions in the partition table
@@ -306,14 +315,26 @@ class PartitionedImage():
306 # all partitions (in bytes) 315 # all partitions (in bytes)
307 self.ptable_format = ptable_format # Partition table format 316 self.ptable_format = ptable_format # Partition table format
308 # Disk system identifier 317 # Disk system identifier
309 self.identifier = random.SystemRandom().randint(1, 0xffffffff) 318 if os.getenv('SOURCE_DATE_EPOCH'):
319 self.identifier = random.Random(int(os.getenv('SOURCE_DATE_EPOCH'))).randint(1, 0xffffffff)
320 else:
321 self.identifier = random.SystemRandom().randint(1, 0xffffffff)
310 322
311 self.partitions = partitions 323 self.partitions = partitions
312 self.partimages = [] 324 self.partimages = []
313 # Size of a sector used in calculations 325 # Size of a sector used in calculations
314 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
315 self.native_sysroot = native_sysroot 335 self.native_sysroot = native_sysroot
316 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])
337 self.extra_space = extra_space
317 338
318 # calculate the real partition number, accounting for partitions not 339 # calculate the real partition number, accounting for partitions not
319 # in the partition table and logical partitions 340 # in the partition table and logical partitions
@@ -331,7 +352,7 @@ class PartitionedImage():
331 # generate parition and filesystem UUIDs 352 # generate parition and filesystem UUIDs
332 for part in self.partitions: 353 for part in self.partitions:
333 if not part.uuid and part.use_uuid: 354 if not part.uuid and part.use_uuid:
334 if self.ptable_format == 'gpt': 355 if self.ptable_format in ('gpt', 'gpt-hybrid'):
335 part.uuid = str(uuid.uuid4()) 356 part.uuid = str(uuid.uuid4())
336 else: # msdos partition table 357 else: # msdos partition table
337 part.uuid = '%08x-%02d' % (self.identifier, part.realnum) 358 part.uuid = '%08x-%02d' % (self.identifier, part.realnum)
@@ -387,6 +408,10 @@ class PartitionedImage():
387 raise WicError("setting custom partition type is not " \ 408 raise WicError("setting custom partition type is not " \
388 "implemented for msdos partitions") 409 "implemented for msdos partitions")
389 410
411 if part.mbr and self.ptable_format != 'gpt-hybrid':
412 raise WicError("Partition may only be included in MBR with " \
413 "a gpt-hybrid partition table")
414
390 # Get the disk where the partition is located 415 # Get the disk where the partition is located
391 self.numpart += 1 416 self.numpart += 1
392 if not part.no_table: 417 if not part.no_table:
@@ -395,7 +420,7 @@ class PartitionedImage():
395 if self.numpart == 1: 420 if self.numpart == 1:
396 if self.ptable_format == "msdos": 421 if self.ptable_format == "msdos":
397 overhead = MBR_OVERHEAD 422 overhead = MBR_OVERHEAD
398 elif self.ptable_format == "gpt": 423 elif self.ptable_format in ("gpt", "gpt-hybrid"):
399 overhead = GPT_OVERHEAD 424 overhead = GPT_OVERHEAD
400 425
401 # Skip one sector required for the partitioning scheme overhead 426 # Skip one sector required for the partitioning scheme overhead
@@ -479,10 +504,11 @@ class PartitionedImage():
479 # Once all the partitions have been layed out, we can calculate the 504 # Once all the partitions have been layed out, we can calculate the
480 # minumim disk size 505 # minumim disk size
481 self.min_size = self.offset 506 self.min_size = self.offset
482 if self.ptable_format == "gpt": 507 if self.ptable_format in ("gpt", "gpt-hybrid"):
483 self.min_size += GPT_OVERHEAD 508 self.min_size += GPT_OVERHEAD
484 509
485 self.min_size *= self.sector_size 510 self.min_size *= self.sector_size
511 self.min_size += self.extra_space
486 512
487 def _create_partition(self, device, parttype, fstype, start, size): 513 def _create_partition(self, device, parttype, fstype, start, size):
488 """ Create a partition on an image described by the 'device' object. """ 514 """ Create a partition on an image described by the 'device' object. """
@@ -492,29 +518,58 @@ class PartitionedImage():
492 logger.debug("Added '%s' partition, sectors %d-%d, size %d sectors", 518 logger.debug("Added '%s' partition, sectors %d-%d, size %d sectors",
493 parttype, start, end, size) 519 parttype, start, end, size)
494 520
495 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)
496 if fstype: 523 if fstype:
497 cmd += " %s" % fstype 524 cmd += " %s" % fstype
498 cmd += " %d %d" % (start, end) 525 cmd += " %d %d" % (start, end)
499 526
500 return exec_native_cmd(cmd, self.native_sysroot) 527 return exec_native_cmd(cmd, self.native_sysroot)
501 528
529 def _write_identifier(self, device, identifier):
530 logger.debug("Set disk identifier %x", identifier)
531 with open(device, 'r+b') as img:
532 img.seek(0x1B8)
533 img.write(identifier.to_bytes(4, 'little'))
534
535 def _make_disk(self, device, ptable_format, min_size):
536 logger.debug("Creating sparse file %s", device)
537 with open(device, 'w') as sparse:
538 os.ftruncate(sparse.fileno(), min_size)
539
540 logger.debug("Initializing partition table for %s", device)
541 exec_native_cmd("export PARTED_SECTOR_SIZE=%d; parted -s %s mklabel %s" %
542 (self.sector_size, device, ptable_format), self.native_sysroot)
543
544 def _write_disk_guid(self):
545 if self.ptable_format in ('gpt', 'gpt-hybrid'):
546 if os.getenv('SOURCE_DATE_EPOCH'):
547 self.disk_guid = uuid.UUID(int=int(os.getenv('SOURCE_DATE_EPOCH')))
548 else:
549 self.disk_guid = uuid.uuid4()
550
551 logger.debug("Set disk guid %s", self.disk_guid)
552 sfdisk_cmd = "sfdisk --sector-size %s --disk-id %s %s" % \
553 (self.sector_size, self.path, self.disk_guid)
554 exec_native_cmd(sfdisk_cmd, self.native_sysroot)
555
502 def create(self): 556 def create(self):
503 logger.debug("Creating sparse file %s", self.path) 557 self._make_disk(self.path,
504 with open(self.path, 'w') as sparse: 558 "gpt" if self.ptable_format == "gpt-hybrid" else self.ptable_format,
505 os.ftruncate(sparse.fileno(), self.min_size) 559 self.min_size)
506 560
507 logger.debug("Initializing partition table for %s", self.path) 561 self._write_identifier(self.path, self.identifier)
508 exec_native_cmd("parted -s %s mklabel %s" % 562 self._write_disk_guid()
509 (self.path, self.ptable_format), self.native_sysroot)
510 563
511 logger.debug("Set disk identifier %x", self.identifier) 564 if self.ptable_format == "gpt-hybrid":
512 with open(self.path, 'r+b') as img: 565 mbr_path = self.path + ".mbr"
513 img.seek(0x1B8) 566 self._make_disk(mbr_path, "msdos", self.min_size)
514 img.write(self.identifier.to_bytes(4, 'little')) 567 self._write_identifier(mbr_path, self.identifier)
515 568
516 logger.debug("Creating partitions") 569 logger.debug("Creating partitions")
517 570
571 hybrid_mbr_part_num = 0
572
518 for part in self.partitions: 573 for part in self.partitions:
519 if part.num == 0: 574 if part.num == 0:
520 continue 575 continue
@@ -559,46 +614,77 @@ class PartitionedImage():
559 self._create_partition(self.path, part.type, 614 self._create_partition(self.path, part.type,
560 parted_fs_type, part.start, part.size_sec) 615 parted_fs_type, part.start, part.size_sec)
561 616
562 if part.part_name: 617 if self.ptable_format == "gpt-hybrid" and part.mbr:
563 logger.debug("partition %d: set name to %s", 618 hybrid_mbr_part_num += 1
564 part.num, part.part_name) 619 if hybrid_mbr_part_num > 4:
565 exec_native_cmd("sgdisk --change-name=%d:%s %s" % \ 620 raise WicError("Extended MBR partitions are not supported in hybrid MBR")
566 (part.num, part.part_name, 621 self._create_partition(mbr_path, "primary",
567 self.path), self.native_sysroot) 622 parted_fs_type, part.start, part.size_sec)
568 623
624 if self.ptable_format in ("gpt", "gpt-hybrid") and (part.part_name or part.label):
625 partition_label = part.part_name if part.part_name else part.label
626 logger.debug("partition %d: set name to %s",
627 part.num, partition_label)
628 exec_native_cmd("sfdisk --sector-size %s --part-label %s %d %s" % \
629 (self.sector_size, self.path, part.num,
630 partition_label), self.native_sysroot)
569 if part.part_type: 631 if part.part_type:
570 logger.debug("partition %d: set type UID to %s", 632 logger.debug("partition %d: set type UID to %s",
571 part.num, part.part_type) 633 part.num, part.part_type)
572 exec_native_cmd("sgdisk --typecode=%d:%s %s" % \ 634 exec_native_cmd("sfdisk --sector-size %s --part-type %s %d %s" % \
573 (part.num, part.part_type, 635 (self.sector_size, self.path, part.num,
574 self.path), self.native_sysroot) 636 part.part_type), self.native_sysroot)
575 637
576 if part.uuid and self.ptable_format == "gpt": 638 if part.uuid and self.ptable_format in ("gpt", "gpt-hybrid"):
577 logger.debug("partition %d: set UUID to %s", 639 logger.debug("partition %d: set UUID to %s",
578 part.num, part.uuid) 640 part.num, part.uuid)
579 exec_native_cmd("sgdisk --partition-guid=%d:%s %s" % \ 641 exec_native_cmd("sfdisk --sector-size %s --part-uuid %s %d %s" % \
580 (part.num, part.uuid, self.path), 642 (self.sector_size, self.path, part.num, part.uuid),
581 self.native_sysroot)
582
583 if part.label and self.ptable_format == "gpt":
584 logger.debug("partition %d: set name to %s",
585 part.num, part.label)
586 exec_native_cmd("parted -s %s name %d %s" % \
587 (self.path, part.num, part.label),
588 self.native_sysroot) 643 self.native_sysroot)
589 644
590 if part.active: 645 if part.active:
591 flag_name = "legacy_boot" if self.ptable_format == 'gpt' else "boot" 646 flag_name = "legacy_boot" if self.ptable_format in ('gpt', 'gpt-hybrid') else "boot"
592 logger.debug("Set '%s' flag for partition '%s' on disk '%s'", 647 logger.debug("Set '%s' flag for partition '%s' on disk '%s'",
593 flag_name, part.num, self.path) 648 flag_name, part.num, self.path)
594 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" % \
595 (self.path, part.num, flag_name), 650 (self.sector_size, self.path, part.num, flag_name),
596 self.native_sysroot) 651 self.native_sysroot)
652 if self.ptable_format == 'gpt-hybrid' and part.mbr:
653 exec_native_cmd("export PARTED_SECTOR_SIZE=%d; parted -s %s set %d %s on" % \
654 (self.sector_size, mbr_path, hybrid_mbr_part_num, "boot"),
655 self.native_sysroot)
597 if part.system_id: 656 if part.system_id:
598 exec_native_cmd("sfdisk --part-type %s %s %s" % \ 657 exec_native_cmd("sfdisk --sector-size %s --part-type %s %s %s" % \
599 (self.path, part.num, part.system_id), 658 (self.sector_size, self.path, part.num, part.system_id),
600 self.native_sysroot) 659 self.native_sysroot)
601 660
661 if part.hidden and self.ptable_format == "gpt":
662 logger.debug("Set hidden attribute for partition '%s' on disk '%s'",
663 part.num, self.path)
664 exec_native_cmd("sfdisk --sector-size %s --part-attrs %s %s RequiredPartition" % \
665 (self.sector_size, self.path, part.num),
666 self.native_sysroot)
667
668 if self.ptable_format == "gpt-hybrid":
669 # Write a protective GPT partition
670 hybrid_mbr_part_num += 1
671 if hybrid_mbr_part_num > 4:
672 raise WicError("Extended MBR partitions are not supported in hybrid MBR")
673
674 # parted cannot directly create a protective GPT partition, so
675 # create with an arbitrary type, then change it to the correct type
676 # with sfdisk
677 self._create_partition(mbr_path, "primary", "fat32", 1, GPT_OVERHEAD)
678 exec_native_cmd("sfdisk --sector-size %s --part-type %s %d 0xee" % \
679 (self.sector_size, mbr_path, hybrid_mbr_part_num),
680 self.native_sysroot)
681
682 # Copy hybrid MBR
683 with open(mbr_path, "rb") as mbr_file:
684 with open(self.path, "r+b") as image_file:
685 mbr = mbr_file.read(512)
686 image_file.write(mbr)
687
602 def cleanup(self): 688 def cleanup(self):
603 pass 689 pass
604 690
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 f2639e7004..0000000000
--- a/scripts/lib/wic/plugins/source/bootimg-pcbios.py
+++ /dev/null
@@ -1,207 +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 = "/vmlinuz"
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/vmlinuz" %
159 (staging_kernel_dir, kernel, hdddir),
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 dosfs_cmd = "mkdosfs -n boot -i %s -S 512 -C %s %d" % \
190 (part.fsuuid, bootimg, blocks)
191 exec_native_cmd(dosfs_cmd, native_sysroot)
192
193 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
194 exec_native_cmd(mcopy_cmd, native_sysroot)
195
196 syslinux_cmd = "syslinux %s" % bootimg
197 exec_native_cmd(syslinux_cmd, native_sysroot)
198
199 chmod_cmd = "chmod 644 %s" % bootimg
200 exec_cmd(chmod_cmd)
201
202 du_cmd = "du -Lbks %s" % bootimg
203 out = exec_cmd(du_cmd)
204 bootimg_size = out.split()[0]
205
206 part.size = int(bootimg_size)
207 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 cdc72543c2..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>
@@ -12,6 +12,7 @@
12 12
13import logging 13import logging
14import os 14import os
15import tempfile
15import shutil 16import shutil
16import re 17import re
17 18
@@ -31,7 +32,29 @@ class BootimgEFIPlugin(SourcePlugin):
31 This plugin supports GRUB 2 and systemd-boot bootloaders. 32 This plugin supports GRUB 2 and systemd-boot bootloaders.
32 """ 33 """
33 34
34 name = 'bootimg-efi' 35 name = 'bootimg_efi'
36
37 @classmethod
38 def _copy_additional_files(cls, hdddir, initrd, dtb):
39 bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
40 if not bootimg_dir:
41 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
42
43 if initrd:
44 initrds = initrd.split(';')
45 for rd in initrds:
46 cp_cmd = "cp -v -p %s/%s %s" % (bootimg_dir, rd, hdddir)
47 out = exec_cmd(cp_cmd, True)
48 logger.debug("initrd files:\n%s" % (out))
49 else:
50 logger.debug("Ignoring missing initrd")
51
52 if dtb:
53 if ';' in dtb:
54 raise WicError("Only one DTB supported, exiting")
55 cp_cmd = "cp -v -p %s/%s %s" % (bootimg_dir, dtb, hdddir)
56 out = exec_cmd(cp_cmd, True)
57 logger.debug("dtb files:\n%s" % (out))
35 58
36 @classmethod 59 @classmethod
37 def do_configure_grubefi(cls, hdddir, creator, cr_workdir, source_params): 60 def do_configure_grubefi(cls, hdddir, creator, cr_workdir, source_params):
@@ -52,18 +75,9 @@ class BootimgEFIPlugin(SourcePlugin):
52 "get it from %s." % configfile) 75 "get it from %s." % configfile)
53 76
54 initrd = source_params.get('initrd') 77 initrd = source_params.get('initrd')
78 dtb = source_params.get('dtb')
55 79
56 if initrd: 80 cls._copy_additional_files(hdddir, initrd, dtb)
57 bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
58 if not bootimg_dir:
59 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
60
61 initrds = initrd.split(';')
62 for rd in initrds:
63 cp_cmd = "cp %s/%s %s" % (bootimg_dir, rd, hdddir)
64 exec_cmd(cp_cmd, True)
65 else:
66 logger.debug("Ignoring missing initrd")
67 81
68 if not custom_cfg: 82 if not custom_cfg:
69 # Create grub configuration using parameters from wks file 83 # Create grub configuration using parameters from wks file
@@ -97,6 +111,9 @@ class BootimgEFIPlugin(SourcePlugin):
97 grubefi_conf += " /%s" % rd 111 grubefi_conf += " /%s" % rd
98 grubefi_conf += "\n" 112 grubefi_conf += "\n"
99 113
114 if dtb:
115 grubefi_conf += "devicetree /%s\n" % dtb
116
100 grubefi_conf += "}\n" 117 grubefi_conf += "}\n"
101 118
102 logger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg", 119 logger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg",
@@ -108,8 +125,16 @@ class BootimgEFIPlugin(SourcePlugin):
108 @classmethod 125 @classmethod
109 def do_configure_systemdboot(cls, hdddir, creator, cr_workdir, source_params): 126 def do_configure_systemdboot(cls, hdddir, creator, cr_workdir, source_params):
110 """ 127 """
111 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.
112 """ 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
113 install_cmd = "install -d %s/loader" % hdddir 138 install_cmd = "install -d %s/loader" % hdddir
114 exec_cmd(install_cmd) 139 exec_cmd(install_cmd)
115 140
@@ -117,34 +142,26 @@ class BootimgEFIPlugin(SourcePlugin):
117 exec_cmd(install_cmd) 142 exec_cmd(install_cmd)
118 143
119 bootloader = creator.ks.bootloader 144 bootloader = creator.ks.bootloader
120
121 loader_conf = "" 145 loader_conf = ""
122 loader_conf += "default boot\n"
123 loader_conf += "timeout %d\n" % bootloader.timeout
124
125 initrd = source_params.get('initrd')
126
127 if initrd:
128 # obviously we need to have a common common deploy var
129 bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
130 if not bootimg_dir:
131 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
132 146
133 initrds = initrd.split(';') 147 # 5 seconds is a sensible default timeout
134 for rd in initrds: 148 loader_conf += "timeout %d\n" % (bootloader.timeout or 5)
135 cp_cmd = "cp %s/%s %s" % (bootimg_dir, rd, hdddir)
136 exec_cmd(cp_cmd, True)
137 else:
138 logger.debug("Ignoring missing initrd")
139 149
140 logger.debug("Writing systemd-boot config " 150 logger.debug("Writing systemd-boot config "
141 "%s/hdd/boot/loader/loader.conf", cr_workdir) 151 "%s/hdd/boot/loader/loader.conf", cr_workdir)
142 cfg = open("%s/hdd/boot/loader/loader.conf" % cr_workdir, "w") 152 cfg = open("%s/hdd/boot/loader/loader.conf" % cr_workdir, "w")
143 cfg.write(loader_conf) 153 cfg.write(loader_conf)
154 logger.debug("loader.conf:\n%s" % (loader_conf))
144 cfg.close() 155 cfg.close()
145 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
146 configfile = creator.ks.bootloader.configfile 162 configfile = creator.ks.bootloader.configfile
147 custom_cfg = None 163 custom_cfg = None
164 boot_conf = ""
148 if configfile: 165 if configfile:
149 custom_cfg = get_custom_config(configfile) 166 custom_cfg = get_custom_config(configfile)
150 if custom_cfg: 167 if custom_cfg:
@@ -155,8 +172,7 @@ class BootimgEFIPlugin(SourcePlugin):
155 else: 172 else:
156 raise WicError("configfile is specified but failed to " 173 raise WicError("configfile is specified but failed to "
157 "get it from %s.", configfile) 174 "get it from %s.", configfile)
158 175 else:
159 if not custom_cfg:
160 # Create systemd-boot configuration using parameters from wks file 176 # Create systemd-boot configuration using parameters from wks file
161 kernel = get_bitbake_var("KERNEL_IMAGETYPE") 177 kernel = get_bitbake_var("KERNEL_IMAGETYPE")
162 if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1": 178 if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1":
@@ -166,7 +182,6 @@ class BootimgEFIPlugin(SourcePlugin):
166 182
167 title = source_params.get('title') 183 title = source_params.get('title')
168 184
169 boot_conf = ""
170 boot_conf += "title %s\n" % (title if title else "boot") 185 boot_conf += "title %s\n" % (title if title else "boot")
171 boot_conf += "linux /%s\n" % kernel 186 boot_conf += "linux /%s\n" % kernel
172 187
@@ -183,11 +198,16 @@ class BootimgEFIPlugin(SourcePlugin):
183 for rd in initrds: 198 for rd in initrds:
184 boot_conf += "initrd /%s\n" % rd 199 boot_conf += "initrd /%s\n" % rd
185 200
186 logger.debug("Writing systemd-boot config " 201 if dtb:
187 "%s/hdd/boot/loader/entries/boot.conf", cr_workdir) 202 boot_conf += "devicetree /%s\n" % dtb
188 cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w") 203
189 cfg.write(boot_conf) 204 if not unified_image:
190 cfg.close() 205 logger.debug("Writing systemd-boot config "
206 "%s/hdd/boot/loader/entries/boot.conf", cr_workdir)
207 cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w")
208 cfg.write(boot_conf)
209 logger.debug("boot.conf:\n%s" % (boot_conf))
210 cfg.close()
191 211
192 212
193 @classmethod 213 @classmethod
@@ -207,10 +227,12 @@ class BootimgEFIPlugin(SourcePlugin):
207 cls.do_configure_grubefi(hdddir, creator, cr_workdir, source_params) 227 cls.do_configure_grubefi(hdddir, creator, cr_workdir, source_params)
208 elif source_params['loader'] == 'systemd-boot': 228 elif source_params['loader'] == 'systemd-boot':
209 cls.do_configure_systemdboot(hdddir, creator, cr_workdir, source_params) 229 cls.do_configure_systemdboot(hdddir, creator, cr_workdir, source_params)
230 elif source_params['loader'] == 'uefi-kernel':
231 pass
210 else: 232 else:
211 raise WicError("unrecognized bootimg-efi loader: %s" % source_params['loader']) 233 raise WicError("unrecognized bootimg_efi loader: %s" % source_params['loader'])
212 except KeyError: 234 except KeyError:
213 raise WicError("bootimg-efi requires a loader, none specified") 235 raise WicError("bootimg_efi requires a loader, none specified")
214 236
215 if get_bitbake_var("IMAGE_EFI_BOOT_FILES") is None: 237 if get_bitbake_var("IMAGE_EFI_BOOT_FILES") is None:
216 logger.debug('No boot files defined in IMAGE_EFI_BOOT_FILES') 238 logger.debug('No boot files defined in IMAGE_EFI_BOOT_FILES')
@@ -230,7 +252,7 @@ class BootimgEFIPlugin(SourcePlugin):
230 252
231 # list of tuples (src_name, dst_name) 253 # list of tuples (src_name, dst_name)
232 deploy_files = [] 254 deploy_files = []
233 for src_entry in re.findall(r'[\w;\-\./\*]+', boot_files): 255 for src_entry in re.findall(r'[\w;\-\.\+/\*]+', boot_files):
234 if ';' in src_entry: 256 if ';' in src_entry:
235 dst_entry = tuple(src_entry.split(';')) 257 dst_entry = tuple(src_entry.split(';'))
236 if not dst_entry[0] or not dst_entry[1]: 258 if not dst_entry[0] or not dst_entry[1]:
@@ -288,40 +310,84 @@ class BootimgEFIPlugin(SourcePlugin):
288 kernel = "%s-%s.bin" % \ 310 kernel = "%s-%s.bin" % \
289 (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME")) 311 (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME"))
290 312
291 install_cmd = "install -m 0644 %s/%s %s/%s" % \ 313 if source_params.get('create-unified-kernel-image') == "true":
292 (staging_kernel_dir, kernel, hdddir, kernel) 314 raise WicError("create-unified-kernel-image is no longer supported. Please use uki.bbclass.")
293 exec_cmd(install_cmd) 315
316 if source_params.get('install-kernel-into-boot-dir') != 'false':
317 install_cmd = "install -v -p -m 0644 %s/%s %s/%s" % \
318 (staging_kernel_dir, kernel, hdddir, kernel)
319 out = exec_cmd(install_cmd)
320 logger.debug("Installed kernel files:\n%s" % out)
294 321
295 if get_bitbake_var("IMAGE_EFI_BOOT_FILES"): 322 if get_bitbake_var("IMAGE_EFI_BOOT_FILES"):
296 for src_path, dst_path in cls.install_task: 323 for src_path, dst_path in cls.install_task:
297 install_cmd = "install -m 0644 -D %s %s" \ 324 install_cmd = "install -v -p -m 0644 -D %s %s" \
298 % (os.path.join(kernel_dir, src_path), 325 % (os.path.join(kernel_dir, src_path),
299 os.path.join(hdddir, dst_path)) 326 os.path.join(hdddir, dst_path))
300 exec_cmd(install_cmd) 327 out = exec_cmd(install_cmd)
328 logger.debug("Installed IMAGE_EFI_BOOT_FILES:\n%s" % out)
301 329
302 try: 330 try:
303 if source_params['loader'] == 'grub-efi': 331 if source_params['loader'] == 'grub-efi':
304 shutil.copyfile("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir, 332 shutil.copyfile("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir,
305 "%s/grub.cfg" % cr_workdir) 333 "%s/grub.cfg" % cr_workdir)
306 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-")]:
307 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:])
308 exec_cmd(cp_cmd, True) 336 exec_cmd(cp_cmd, True)
309 shutil.move("%s/grub.cfg" % cr_workdir, 337 shutil.move("%s/grub.cfg" % cr_workdir,
310 "%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir) 338 "%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir)
311 elif source_params['loader'] == 'systemd-boot': 339 elif source_params['loader'] == 'systemd-boot':
312 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-")]:
313 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:])
314 exec_cmd(cp_cmd, True) 342 out = exec_cmd(cp_cmd, True)
343 logger.debug("systemd-boot files:\n%s" % out)
344 elif source_params['loader'] == 'uefi-kernel':
345 kernel = get_bitbake_var("KERNEL_IMAGETYPE")
346 if not kernel:
347 raise WicError("Empty KERNEL_IMAGETYPE")
348 target = get_bitbake_var("TARGET_SYS")
349 if not target:
350 raise WicError("Empty TARGET_SYS")
351
352 if re.match("x86_64", target):
353 kernel_efi_image = "bootx64.efi"
354 elif re.match('i.86', target):
355 kernel_efi_image = "bootia32.efi"
356 elif re.match('aarch64', target):
357 kernel_efi_image = "bootaa64.efi"
358 elif re.match('arm', target):
359 kernel_efi_image = "bootarm.efi"
360 else:
361 raise WicError("UEFI stub kernel is incompatible with target %s" % target)
362
363 for mod in [x for x in os.listdir(kernel_dir) if x.startswith(kernel)]:
364 cp_cmd = "cp -v -p %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, kernel_efi_image)
365 out = exec_cmd(cp_cmd, True)
366 logger.debug("uefi-kernel files:\n%s" % out)
315 else: 367 else:
316 raise WicError("unrecognized bootimg-efi loader: %s" % 368 raise WicError("unrecognized bootimg_efi loader: %s" %
317 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
318 except KeyError: 377 except KeyError:
319 raise WicError("bootimg-efi requires a loader, none specified") 378 raise WicError("bootimg_efi requires a loader, none specified")
320 379
321 startup = os.path.join(kernel_dir, "startup.nsh") 380 startup = os.path.join(kernel_dir, "startup.nsh")
322 if os.path.exists(startup): 381 if os.path.exists(startup):
323 cp_cmd = "cp %s %s/" % (startup, hdddir) 382 cp_cmd = "cp -v -p %s %s/" % (startup, hdddir)
324 exec_cmd(cp_cmd, True) 383 out = exec_cmd(cp_cmd, True)
384 logger.debug("startup files:\n%s" % out)
385
386 for paths in part.include_path or []:
387 for path in paths:
388 cp_cmd = "cp -v -p -r %s %s/" % (path, hdddir)
389 exec_cmd(cp_cmd, True)
390 logger.debug("include_path files:\n%s" % out)
325 391
326 du_cmd = "du -bks %s" % hdddir 392 du_cmd = "du -bks %s" % hdddir
327 out = exec_cmd(du_cmd) 393 out = exec_cmd(du_cmd)
@@ -337,17 +403,26 @@ class BootimgEFIPlugin(SourcePlugin):
337 logger.debug("Added %d extra blocks to %s to get to %d total blocks", 403 logger.debug("Added %d extra blocks to %s to get to %d total blocks",
338 extra_blocks, part.mountpoint, blocks) 404 extra_blocks, part.mountpoint, blocks)
339 405
406 # required for compatibility with certain devices expecting file system
407 # block count to be equal to partition block count
408 if blocks < part.fixed_size:
409 blocks = part.fixed_size
410 logger.debug("Overriding %s to %d total blocks for compatibility",
411 part.mountpoint, blocks)
412
340 # dosfs image, created by mkdosfs 413 # dosfs image, created by mkdosfs
341 bootimg = "%s/boot.img" % cr_workdir 414 bootimg = "%s/boot.img" % cr_workdir
342 415
343 label = part.label if part.label else "ESP" 416 label = part.label if part.label else "ESP"
344 417
345 dosfs_cmd = "mkdosfs -n %s -i %s -C %s %d" % \ 418 dosfs_cmd = "mkdosfs -v -n %s -i %s -C %s %d" % \
346 (label, part.fsuuid, bootimg, blocks) 419 (label, part.fsuuid, bootimg, blocks)
347 exec_native_cmd(dosfs_cmd, native_sysroot) 420 exec_native_cmd(dosfs_cmd, native_sysroot)
421 logger.debug("mkdosfs:\n%s" % (str(out)))
348 422
349 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir) 423 mcopy_cmd = "mcopy -v -p -i %s -s %s/* ::/" % (bootimg, hdddir)
350 exec_native_cmd(mcopy_cmd, native_sysroot) 424 out = exec_native_cmd(mcopy_cmd, native_sysroot)
425 logger.debug("mcopy:\n%s" % (str(out)))
351 426
352 chmod_cmd = "chmod 644 %s" % bootimg 427 chmod_cmd = "chmod 644 %s" % bootimg
353 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 5dbe2558d2..cc121a78f0 100644
--- a/scripts/lib/wic/plugins/source/bootimg-partition.py
+++ b/scripts/lib/wic/plugins/source/bootimg_partition.py
@@ -1,8 +1,10 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4# DESCRIPTION 6# DESCRIPTION
5# This implements the 'bootimg-partition' source plugin class for 7# This implements the 'bootimg_partition' source plugin class for
6# 'wic'. The plugin creates an image of boot partition, copying over 8# 'wic'. The plugin creates an image of boot partition, copying over
7# files listed in IMAGE_BOOT_FILES bitbake variable. 9# files listed in IMAGE_BOOT_FILES bitbake variable.
8# 10#
@@ -14,7 +16,7 @@ import logging
14import os 16import os
15import re 17import re
16 18
17from glob import glob 19from oe.bootfiles import get_boot_files
18 20
19from wic import WicError 21from wic import WicError
20from wic.engine import get_custom_config 22from wic.engine import get_custom_config
@@ -29,7 +31,8 @@ class BootimgPartitionPlugin(SourcePlugin):
29 listed in IMAGE_BOOT_FILES bitbake variable. 31 listed in IMAGE_BOOT_FILES bitbake variable.
30 """ 32 """
31 33
32 name = 'bootimg-partition' 34 name = 'bootimg_partition'
35 image_boot_files_var_name = 'IMAGE_BOOT_FILES'
33 36
34 @classmethod 37 @classmethod
35 def do_configure_partition(cls, part, source_params, cr, cr_workdir, 38 def do_configure_partition(cls, part, source_params, cr, cr_workdir,
@@ -54,51 +57,16 @@ class BootimgPartitionPlugin(SourcePlugin):
54 else: 57 else:
55 var = "" 58 var = ""
56 59
57 boot_files = get_bitbake_var("IMAGE_BOOT_FILES" + var) 60 boot_files = get_bitbake_var(cls.image_boot_files_var_name + var)
58 if boot_files is not None: 61 if boot_files is not None:
59 break 62 break
60 63
61 if boot_files is None: 64 if boot_files is None:
62 raise WicError('No boot files defined, IMAGE_BOOT_FILES unset for entry #%d' % part.lineno) 65 raise WicError('No boot files defined, %s unset for entry #%d' % (cls.image_boot_files_var_name, part.lineno))
63 66
64 logger.debug('Boot files: %s', boot_files) 67 logger.debug('Boot files: %s', boot_files)
65 68
66 # list of tuples (src_name, dst_name) 69 cls.install_task = get_boot_files(kernel_dir, boot_files)
67 deploy_files = []
68 for src_entry in re.findall(r'[\w;\-\./\*]+', boot_files):
69 if ';' in src_entry:
70 dst_entry = tuple(src_entry.split(';'))
71 if not dst_entry[0] or not dst_entry[1]:
72 raise WicError('Malformed boot file entry: %s' % src_entry)
73 else:
74 dst_entry = (src_entry, src_entry)
75
76 logger.debug('Destination entry: %r', dst_entry)
77 deploy_files.append(dst_entry)
78
79 cls.install_task = [];
80 for deploy_entry in deploy_files:
81 src, dst = deploy_entry
82 if '*' in src:
83 # by default install files under their basename
84 entry_name_fn = os.path.basename
85 if dst != src:
86 # unless a target name was given, then treat name
87 # as a directory and append a basename
88 entry_name_fn = lambda name: \
89 os.path.join(dst,
90 os.path.basename(name))
91
92 srcs = glob(os.path.join(kernel_dir, src))
93
94 logger.debug('Globbed sources: %s', ', '.join(srcs))
95 for entry in srcs:
96 src = os.path.relpath(entry, kernel_dir)
97 entry_dst_name = entry_name_fn(entry)
98 cls.install_task.append((src, entry_dst_name))
99 else:
100 cls.install_task.append((src, dst))
101
102 if source_params.get('loader') != "u-boot": 70 if source_params.get('loader') != "u-boot":
103 return 71 return
104 72
@@ -110,7 +78,7 @@ class BootimgPartitionPlugin(SourcePlugin):
110 # Use a custom configuration for extlinux.conf 78 # Use a custom configuration for extlinux.conf
111 extlinux_conf = custom_cfg 79 extlinux_conf = custom_cfg
112 logger.debug("Using custom configuration file " 80 logger.debug("Using custom configuration file "
113 "%s for extlinux.cfg", configfile) 81 "%s for extlinux.conf", configfile)
114 else: 82 else:
115 raise WicError("configfile is specified but failed to " 83 raise WicError("configfile is specified but failed to "
116 "get it from %s." % configfile) 84 "get it from %s." % configfile)
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/empty.py b/scripts/lib/wic/plugins/source/empty.py
index 041617d648..4178912377 100644
--- a/scripts/lib/wic/plugins/source/empty.py
+++ b/scripts/lib/wic/plugins/source/empty.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -7,9 +9,19 @@
7# To use it you must pass "empty" as argument for the "--source" parameter in 9# To use it you must pass "empty" as argument for the "--source" parameter in
8# the wks file. For example: 10# the wks file. For example:
9# part foo --source empty --ondisk sda --size="1024" --align 1024 11# part foo --source empty --ondisk sda --size="1024" --align 1024
12#
13# The plugin supports writing zeros to the start of the
14# partition. This is useful to overwrite old content like
15# filesystem signatures which may be re-recognized otherwise.
16# This feature can be enabled with
17# '--sourceparams="[fill|size=<N>[S|s|K|k|M|G]][,][bs=<N>[S|s|K|k|M|G]]"'
18# Conflicting or missing options throw errors.
10 19
11import logging 20import logging
21import os
12 22
23from wic import WicError
24from wic.ksparser import sizetype
13from wic.pluginbase import SourcePlugin 25from wic.pluginbase import SourcePlugin
14 26
15logger = logging.getLogger('wic') 27logger = logging.getLogger('wic')
@@ -17,6 +29,16 @@ logger = logging.getLogger('wic')
17class EmptyPartitionPlugin(SourcePlugin): 29class EmptyPartitionPlugin(SourcePlugin):
18 """ 30 """
19 Populate unformatted empty partition. 31 Populate unformatted empty partition.
32
33 The following sourceparams are supported:
34 - fill
35 Fill the entire partition with zeros. Requires '--fixed-size' option
36 to be set.
37 - size=<N>[S|s|K|k|M|G]
38 Set the first N bytes of the partition to zero. Default unit is 'K'.
39 - bs=<N>[S|s|K|k|M|G]
40 Write at most N bytes at a time during source file creation.
41 Defaults to '1M'. Default unit is 'K'.
20 """ 42 """
21 43
22 name = 'empty' 44 name = 'empty'
@@ -29,4 +51,39 @@ class EmptyPartitionPlugin(SourcePlugin):
29 Called to do the actual content population for a partition i.e. it 51 Called to do the actual content population for a partition i.e. it
30 'prepares' the partition to be incorporated into the image. 52 'prepares' the partition to be incorporated into the image.
31 """ 53 """
32 return 54 get_byte_count = sizetype('K', True)
55 size = 0
56
57 if 'fill' in source_params and 'size' in source_params:
58 raise WicError("Conflicting source parameters 'fill' and 'size' specified, exiting.")
59
60 # Set the size of the zeros to be written to the partition
61 if 'fill' in source_params:
62 if part.fixed_size == 0:
63 raise WicError("Source parameter 'fill' only works with the '--fixed-size' option, exiting.")
64 size = get_byte_count(part.fixed_size)
65 elif 'size' in source_params:
66 size = get_byte_count(source_params['size'])
67
68 if size == 0:
69 # Nothing to do, create empty partition
70 return
71
72 if 'bs' in source_params:
73 bs = get_byte_count(source_params['bs'])
74 else:
75 bs = get_byte_count('1M')
76
77 # Create a binary file of the requested size filled with zeros
78 source_file = os.path.join(cr_workdir, 'empty-plugin-zeros%s.bin' % part.lineno)
79 if not os.path.exists(os.path.dirname(source_file)):
80 os.makedirs(os.path.dirname(source_file))
81
82 quotient, remainder = divmod(size, bs)
83 with open(source_file, 'wb') as file:
84 for _ in range(quotient):
85 file.write(bytearray(bs))
86 file.write(bytearray(remainder))
87
88 part.size = (size + 1024 - 1) // 1024 # size in KB rounded up
89 part.source_file = source_file
diff --git a/scripts/lib/wic/plugins/source/extra_partition.py b/scripts/lib/wic/plugins/source/extra_partition.py
new file mode 100644
index 0000000000..d370b0107e
--- /dev/null
+++ b/scripts/lib/wic/plugins/source/extra_partition.py
@@ -0,0 +1,134 @@
1import logging
2import os
3import re
4
5from glob import glob
6
7from wic import WicError
8from wic.pluginbase import SourcePlugin
9from wic.misc import exec_cmd, get_bitbake_var
10
11logger = logging.getLogger('wic')
12
13class ExtraPartitionPlugin(SourcePlugin):
14 """
15 Populates an extra partition with files listed in the IMAGE_EXTRA_PARTITION_FILES
16 BitBake variable. Files should be deployed to the DEPLOY_DIR_IMAGE directory.
17
18 The plugin supports:
19 - Glob pattern matching for file selection.
20 - File renaming.
21 - Suffixes to specify the target partition (by label, UUID, or partname),
22 enabling multiple extra partitions to coexist.
23
24 For example:
25
26 IMAGE_EXTRA_PARTITION_FILES_label-foo = "bar.conf;foo.conf"
27 IMAGE_EXTRA_PARTITION_FILES_uuid-e7d0824e-cda3-4bed-9f54-9ef5312d105d = "bar.conf;foobar.conf"
28 IMAGE_EXTRA_PARTITION_FILES = "foo/*"
29 WICVARS:append = "\
30 IMAGE_EXTRA_PARTITION_FILES_label-foo \
31 IMAGE_EXTRA_PARTITION_FILES_uuid-e7d0824e-cda3-4bed-9f54-9ef5312d105d \
32 "
33
34 """
35
36 name = 'extra_partition'
37 image_extra_partition_files_var_name = 'IMAGE_EXTRA_PARTITION_FILES'
38
39 @classmethod
40 def do_configure_partition(cls, part, source_params, cr, cr_workdir,
41 oe_builddir, bootimg_dir, kernel_dir,
42 native_sysroot):
43 """
44 Called before do_prepare_partition(), list the files to copy
45 """
46 extradir = "%s/extra.%d" % (cr_workdir, part.lineno)
47 install_cmd = "install -d %s" % extradir
48 exec_cmd(install_cmd)
49
50 if not kernel_dir:
51 kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
52 if not kernel_dir:
53 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
54
55 extra_files = None
56 for (fmt, id) in (("_uuid-%s", part.uuid), ("_label-%s", part.label), ("_part-name-%s", part.part_name), (None, None)):
57 if fmt:
58 var = fmt % id
59 else:
60 var = ""
61 extra_files = get_bitbake_var(cls.image_extra_partition_files_var_name + var)
62 if extra_files is not None:
63 break
64
65 if extra_files is None:
66 raise WicError('No extra files defined, %s unset for entry #%d' % (cls.image_extra_partition_files_var_name, part.lineno))
67
68 logger.info('Extra files: %s', extra_files)
69
70 # list of tuples (src_name, dst_name)
71 deploy_files = []
72 for src_entry in re.findall(r'[\w;\-\./\*]+', extra_files):
73 if ';' in src_entry:
74 dst_entry = tuple(src_entry.split(';'))
75 if not dst_entry[0] or not dst_entry[1]:
76 raise WicError('Malformed extra file entry: %s' % src_entry)
77 else:
78 dst_entry = (src_entry, src_entry)
79
80 logger.debug('Destination entry: %r', dst_entry)
81 deploy_files.append(dst_entry)
82
83 cls.install_task = [];
84 for deploy_entry in deploy_files:
85 src, dst = deploy_entry
86 if '*' in src:
87 # by default install files under their basename
88 entry_name_fn = os.path.basename
89 if dst != src:
90 # unless a target name was given, then treat name
91 # as a directory and append a basename
92 entry_name_fn = lambda name: \
93 os.path.join(dst,
94 os.path.basename(name))
95
96 srcs = glob(os.path.join(kernel_dir, src))
97
98 logger.debug('Globbed sources: %s', ', '.join(srcs))
99 for entry in srcs:
100 src = os.path.relpath(entry, kernel_dir)
101 entry_dst_name = entry_name_fn(entry)
102 cls.install_task.append((src, entry_dst_name))
103 else:
104 cls.install_task.append((src, dst))
105
106
107 @classmethod
108 def do_prepare_partition(cls, part, source_params, cr, cr_workdir,
109 oe_builddir, bootimg_dir, kernel_dir,
110 rootfs_dir, native_sysroot):
111 """
112 Called to do the actual content population for a partition i.e. it
113 'prepares' the partition to be incorporated into the image.
114 In this case, we copies all files listed in IMAGE_EXTRA_PARTITION_FILES variable.
115 """
116 extradir = "%s/extra.%d" % (cr_workdir, part.lineno)
117
118 if not kernel_dir:
119 kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
120 if not kernel_dir:
121 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
122
123 for task in cls.install_task:
124 src_path, dst_path = task
125 logger.debug('Install %s as %s', src_path, dst_path)
126 install_cmd = "install -m 0644 -D %s %s" \
127 % (os.path.join(kernel_dir, src_path),
128 os.path.join(extradir, dst_path))
129 exec_cmd(install_cmd)
130
131 logger.debug('Prepare extra partition using rootfs in %s', extradir)
132 part.prepare_rootfs(cr_workdir, oe_builddir, extradir,
133 native_sysroot, False)
134
diff --git a/scripts/lib/wic/plugins/source/isoimage-isohybrid.py b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
index afc9ea0f8f..5d42eb5d3e 100644
--- a/scripts/lib/wic/plugins/source/isoimage-isohybrid.py
+++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
@@ -1,8 +1,10 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4# DESCRIPTION 6# DESCRIPTION
5# This implements the 'isoimage-isohybrid' source plugin class for 'wic' 7# This implements the 'isoimage_isohybrid' source plugin class for 'wic'
6# 8#
7# AUTHORS 9# AUTHORS
8# Mihaly Varga <mihaly.varga (at] ni.com> 10# Mihaly Varga <mihaly.varga (at] ni.com>
@@ -33,7 +35,7 @@ class IsoImagePlugin(SourcePlugin):
33 bootloader files. 35 bootloader files.
34 36
35 Example kickstart file: 37 Example kickstart file:
36 part /boot --source isoimage-isohybrid --sourceparams="loader=grub-efi, \\ 38 part /boot --source isoimage_isohybrid --sourceparams="loader=grub-efi, \\
37 image_name= IsoImage" --ondisk cd --label LIVECD 39 image_name= IsoImage" --ondisk cd --label LIVECD
38 bootloader --timeout=10 --append=" " 40 bootloader --timeout=10 --append=" "
39 41
@@ -43,7 +45,7 @@ class IsoImagePlugin(SourcePlugin):
43 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
44 """ 46 """
45 47
46 name = 'isoimage-isohybrid' 48 name = 'isoimage_isohybrid'
47 49
48 @classmethod 50 @classmethod
49 def do_configure_syslinux(cls, creator, cr_workdir): 51 def do_configure_syslinux(cls, creator, cr_workdir):
@@ -338,10 +340,10 @@ class IsoImagePlugin(SourcePlugin):
338 cls.do_configure_grubefi(part, creator, target_dir) 340 cls.do_configure_grubefi(part, creator, target_dir)
339 341
340 else: 342 else:
341 raise WicError("unrecognized bootimg-efi loader: %s" % 343 raise WicError("unrecognized bootimg_efi loader: %s" %
342 source_params['loader']) 344 source_params['loader'])
343 except KeyError: 345 except KeyError:
344 raise WicError("bootimg-efi requires a loader, none specified") 346 raise WicError("bootimg_efi requires a loader, none specified")
345 347
346 # Create efi.img that contains bootloader files for EFI booting 348 # Create efi.img that contains bootloader files for EFI booting
347 # 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/rawcopy.py b/scripts/lib/wic/plugins/source/rawcopy.py
index 3c4997d8ba..21903c2f23 100644
--- a/scripts/lib/wic/plugins/source/rawcopy.py
+++ b/scripts/lib/wic/plugins/source/rawcopy.py
@@ -1,9 +1,13 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
5import logging 7import logging
6import os 8import os
9import signal
10import subprocess
7 11
8from wic import WicError 12from wic import WicError
9from wic.pluginbase import SourcePlugin 13from wic.pluginbase import SourcePlugin
@@ -21,6 +25,10 @@ class RawCopyPlugin(SourcePlugin):
21 25
22 @staticmethod 26 @staticmethod
23 def do_image_label(fstype, dst, label): 27 def do_image_label(fstype, dst, label):
28 # don't create label when fstype is none
29 if fstype == 'none':
30 return
31
24 if fstype.startswith('ext'): 32 if fstype.startswith('ext'):
25 cmd = 'tune2fs -L %s %s' % (label, dst) 33 cmd = 'tune2fs -L %s %s' % (label, dst)
26 elif fstype in ('msdos', 'vfat'): 34 elif fstype in ('msdos', 'vfat'):
@@ -29,15 +37,35 @@ class RawCopyPlugin(SourcePlugin):
29 cmd = 'btrfs filesystem label %s %s' % (dst, label) 37 cmd = 'btrfs filesystem label %s %s' % (dst, label)
30 elif fstype == 'swap': 38 elif fstype == 'swap':
31 cmd = 'mkswap -L %s %s' % (label, dst) 39 cmd = 'mkswap -L %s %s' % (label, dst)
32 elif fstype == 'squashfs': 40 elif fstype in ('squashfs', 'erofs'):
33 raise WicError("It's not possible to update a squashfs " 41 raise WicError("It's not possible to update a %s "
34 "filesystem label '%s'" % (label)) 42 "filesystem label '%s'" % (fstype, label))
35 else: 43 else:
36 raise WicError("Cannot update filesystem label: " 44 raise WicError("Cannot update filesystem label: "
37 "Unknown fstype: '%s'" % (fstype)) 45 "Unknown fstype: '%s'" % (fstype))
38 46
39 exec_cmd(cmd) 47 exec_cmd(cmd)
40 48
49 @staticmethod
50 def do_image_uncompression(src, dst, workdir):
51 def subprocess_setup():
52 # Python installs a SIGPIPE handler by default. This is usually not what
53 # non-Python subprocesses expect.
54 # SIGPIPE errors are known issues with gzip/bash
55 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
56
57 extension = os.path.splitext(src)[1]
58 decompressor = {
59 ".bz2": "bzip2",
60 ".gz": "gzip",
61 ".xz": "xz",
62 ".zst": "zstd -f",
63 }.get(extension)
64 if not decompressor:
65 raise WicError("Not supported compressor filename extension: %s" % extension)
66 cmd = "%s -dc %s > %s" % (decompressor, src, dst)
67 subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True, cwd=workdir)
68
41 @classmethod 69 @classmethod
42 def do_prepare_partition(cls, part, source_params, cr, cr_workdir, 70 def do_prepare_partition(cls, part, source_params, cr, cr_workdir,
43 oe_builddir, bootimg_dir, kernel_dir, 71 oe_builddir, bootimg_dir, kernel_dir,
@@ -56,7 +84,13 @@ class RawCopyPlugin(SourcePlugin):
56 if 'file' not in source_params: 84 if 'file' not in source_params:
57 raise WicError("No file specified") 85 raise WicError("No file specified")
58 86
59 src = os.path.join(kernel_dir, source_params['file']) 87 if 'unpack' in source_params:
88 img = os.path.join(kernel_dir, source_params['file'])
89 src = os.path.join(cr_workdir, os.path.splitext(source_params['file'])[0])
90 RawCopyPlugin.do_image_uncompression(img, src, cr_workdir)
91 else:
92 src = os.path.join(kernel_dir, source_params['file'])
93
60 dst = os.path.join(cr_workdir, "%s.%s" % (os.path.basename(source_params['file']), part.lineno)) 94 dst = os.path.join(cr_workdir, "%s.%s" % (os.path.basename(source_params['file']), part.lineno))
61 95
62 if not os.path.exists(os.path.dirname(dst)): 96 if not os.path.exists(os.path.dirname(dst)):
diff --git a/scripts/lib/wic/plugins/source/rootfs.py b/scripts/lib/wic/plugins/source/rootfs.py
index 96d940a91d..06fce06bb1 100644
--- a/scripts/lib/wic/plugins/source/rootfs.py
+++ b/scripts/lib/wic/plugins/source/rootfs.py
@@ -35,22 +35,22 @@ class RootfsPlugin(SourcePlugin):
35 @staticmethod 35 @staticmethod
36 def __validate_path(cmd, rootfs_dir, path): 36 def __validate_path(cmd, rootfs_dir, path):
37 if os.path.isabs(path): 37 if os.path.isabs(path):
38 logger.error("%s: Must be relative: %s" % (cmd, orig_path)) 38 logger.error("%s: Must be relative: %s" % (cmd, path))
39 sys.exit(1) 39 sys.exit(1)
40 40
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:" % (cmd, path)) 46 logger.error("%s: Must point inside the rootfs: %s" % (cmd, path))
47 sys.exit(1) 47 sys.exit(1)
48 48
49 return full_path 49 return full_path
50 50
51 @staticmethod 51 @staticmethod
52 def __get_rootfs_dir(rootfs_dir): 52 def __get_rootfs_dir(rootfs_dir):
53 if os.path.isdir(rootfs_dir): 53 if rootfs_dir and os.path.isdir(rootfs_dir):
54 return os.path.realpath(rootfs_dir) 54 return os.path.realpath(rootfs_dir)
55 55
56 image_rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", rootfs_dir) 56 image_rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", rootfs_dir)
@@ -97,6 +97,9 @@ class RootfsPlugin(SourcePlugin):
97 part.has_fstab = os.path.exists(os.path.join(part.rootfs_dir, "etc/fstab")) 97 part.has_fstab = os.path.exists(os.path.join(part.rootfs_dir, "etc/fstab"))
98 pseudo_dir = os.path.join(part.rootfs_dir, "../pseudo") 98 pseudo_dir = os.path.join(part.rootfs_dir, "../pseudo")
99 if not os.path.lexists(pseudo_dir): 99 if not os.path.lexists(pseudo_dir):
100 pseudo_dir = os.path.join(cls.__get_rootfs_dir(None), '../pseudo')
101
102 if not os.path.lexists(pseudo_dir):
100 logger.warn("%s folder does not exist. " 103 logger.warn("%s folder does not exist. "
101 "Usernames and permissions will be invalid " % pseudo_dir) 104 "Usernames and permissions will be invalid " % pseudo_dir)
102 pseudo_dir = None 105 pseudo_dir = None
@@ -218,10 +221,10 @@ class RootfsPlugin(SourcePlugin):
218 # Update part.has_fstab here as fstab may have been added or 221 # Update part.has_fstab here as fstab may have been added or
219 # removed by the above modifications. 222 # removed by the above modifications.
220 part.has_fstab = os.path.exists(os.path.join(new_rootfs, "etc/fstab")) 223 part.has_fstab = os.path.exists(os.path.join(new_rootfs, "etc/fstab"))
221 if part.update_fstab_in_rootfs and part.has_fstab: 224 if part.update_fstab_in_rootfs and part.has_fstab and not part.no_fstab_update:
222 fstab_path = os.path.join(new_rootfs, "etc/fstab") 225 fstab_path = os.path.join(new_rootfs, "etc/fstab")
223 # Assume that fstab should always be owned by root with fixed permissions 226 # Assume that fstab should always be owned by root with fixed permissions
224 install_cmd = "install -m 0644 %s %s" % (part.updated_fstab_path, fstab_path) 227 install_cmd = "install -m 0644 -p %s %s" % (part.updated_fstab_path, fstab_path)
225 if new_pseudo: 228 if new_pseudo:
226 pseudo = cls.__get_pseudo(native_sysroot, new_rootfs, new_pseudo) 229 pseudo = cls.__get_pseudo(native_sysroot, new_rootfs, new_pseudo)
227 else: 230 else: