1eb8dc403SDave Cobbley#
2*92b42cb3SPatrick Williams# Copyright OpenEmbedded Contributors
3*92b42cb3SPatrick Williams#
4c342db35SBrad Bishop# SPDX-License-Identifier: GPL-2.0-only
5eb8dc403SDave Cobbley#
6eb8dc403SDave Cobbley# DESCRIPTION
7eb8dc403SDave Cobbley# This implements the 'isoimage-isohybrid' source plugin class for 'wic'
8eb8dc403SDave Cobbley#
9eb8dc403SDave Cobbley# AUTHORS
10eb8dc403SDave Cobbley# Mihaly Varga <mihaly.varga (at] ni.com>
11eb8dc403SDave Cobbley
12eb8dc403SDave Cobbleyimport glob
13eb8dc403SDave Cobbleyimport logging
14eb8dc403SDave Cobbleyimport os
15eb8dc403SDave Cobbleyimport re
16eb8dc403SDave Cobbleyimport shutil
17eb8dc403SDave Cobbley
18eb8dc403SDave Cobbleyfrom wic import WicError
19eb8dc403SDave Cobbleyfrom wic.engine import get_custom_config
20eb8dc403SDave Cobbleyfrom wic.pluginbase import SourcePlugin
21eb8dc403SDave Cobbleyfrom wic.misc import exec_cmd, exec_native_cmd, get_bitbake_var
22eb8dc403SDave Cobbley
23eb8dc403SDave Cobbleylogger = logging.getLogger('wic')
24eb8dc403SDave Cobbley
25eb8dc403SDave Cobbleyclass IsoImagePlugin(SourcePlugin):
26eb8dc403SDave Cobbley    """
27eb8dc403SDave Cobbley    Create a bootable ISO image
28eb8dc403SDave Cobbley
29eb8dc403SDave Cobbley    This plugin creates a hybrid, legacy and EFI bootable ISO image. The
30eb8dc403SDave Cobbley    generated image can be used on optical media as well as USB media.
31eb8dc403SDave Cobbley
32eb8dc403SDave Cobbley    Legacy boot uses syslinux and EFI boot uses grub or gummiboot (not
33eb8dc403SDave Cobbley    implemented yet) as bootloader. The plugin creates the directories required
34eb8dc403SDave Cobbley    by bootloaders and populates them by creating and configuring the
35eb8dc403SDave Cobbley    bootloader files.
36eb8dc403SDave Cobbley
37eb8dc403SDave Cobbley    Example kickstart file:
38eb8dc403SDave Cobbley    part /boot --source isoimage-isohybrid --sourceparams="loader=grub-efi, \\
391a4b7ee2SBrad Bishop    image_name= IsoImage" --ondisk cd --label LIVECD
40eb8dc403SDave Cobbley    bootloader  --timeout=10  --append=" "
41eb8dc403SDave Cobbley
42eb8dc403SDave Cobbley    In --sourceparams "loader" specifies the bootloader used for booting in EFI
43eb8dc403SDave Cobbley    mode, while "image_name" specifies the name of the generated image. In the
44eb8dc403SDave Cobbley    example above, wic creates an ISO image named IsoImage-cd.direct (default
45eb8dc403SDave Cobbley    extension added by direct imeger plugin) and a file named IsoImage-cd.iso
46eb8dc403SDave Cobbley    """
47eb8dc403SDave Cobbley
48eb8dc403SDave Cobbley    name = 'isoimage-isohybrid'
49eb8dc403SDave Cobbley
50eb8dc403SDave Cobbley    @classmethod
51eb8dc403SDave Cobbley    def do_configure_syslinux(cls, creator, cr_workdir):
52eb8dc403SDave Cobbley        """
53eb8dc403SDave Cobbley        Create loader-specific (syslinux) config
54eb8dc403SDave Cobbley        """
55eb8dc403SDave Cobbley        splash = os.path.join(cr_workdir, "ISO/boot/splash.jpg")
56eb8dc403SDave Cobbley        if os.path.exists(splash):
57eb8dc403SDave Cobbley            splashline = "menu background splash.jpg"
58eb8dc403SDave Cobbley        else:
59eb8dc403SDave Cobbley            splashline = ""
60eb8dc403SDave Cobbley
61eb8dc403SDave Cobbley        bootloader = creator.ks.bootloader
62eb8dc403SDave Cobbley
63eb8dc403SDave Cobbley        syslinux_conf = ""
64eb8dc403SDave Cobbley        syslinux_conf += "PROMPT 0\n"
65eb8dc403SDave Cobbley        syslinux_conf += "TIMEOUT %s \n" % (bootloader.timeout or 10)
66eb8dc403SDave Cobbley        syslinux_conf += "\n"
67eb8dc403SDave Cobbley        syslinux_conf += "ALLOWOPTIONS 1\n"
68eb8dc403SDave Cobbley        syslinux_conf += "SERIAL 0 115200\n"
69eb8dc403SDave Cobbley        syslinux_conf += "\n"
70eb8dc403SDave Cobbley        if splashline:
71eb8dc403SDave Cobbley            syslinux_conf += "%s\n" % splashline
72eb8dc403SDave Cobbley        syslinux_conf += "DEFAULT boot\n"
73eb8dc403SDave Cobbley        syslinux_conf += "LABEL boot\n"
74eb8dc403SDave Cobbley
7515ae2509SBrad Bishop        kernel = get_bitbake_var("KERNEL_IMAGETYPE")
7696ff1984SBrad Bishop        if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1":
7796ff1984SBrad Bishop            if get_bitbake_var("INITRAMFS_IMAGE"):
7896ff1984SBrad Bishop                kernel = "%s-%s.bin" % \
7996ff1984SBrad Bishop                    (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME"))
8096ff1984SBrad Bishop
8115ae2509SBrad Bishop        syslinux_conf += "KERNEL /" + kernel + "\n"
82eb8dc403SDave Cobbley        syslinux_conf += "APPEND initrd=/initrd LABEL=boot %s\n" \
83eb8dc403SDave Cobbley                             % bootloader.append
84eb8dc403SDave Cobbley
85eb8dc403SDave Cobbley        logger.debug("Writing syslinux config %s/ISO/isolinux/isolinux.cfg",
86eb8dc403SDave Cobbley                     cr_workdir)
87eb8dc403SDave Cobbley
88eb8dc403SDave Cobbley        with open("%s/ISO/isolinux/isolinux.cfg" % cr_workdir, "w") as cfg:
89eb8dc403SDave Cobbley            cfg.write(syslinux_conf)
90eb8dc403SDave Cobbley
91eb8dc403SDave Cobbley    @classmethod
92eb8dc403SDave Cobbley    def do_configure_grubefi(cls, part, creator, target_dir):
93eb8dc403SDave Cobbley        """
94eb8dc403SDave Cobbley        Create loader-specific (grub-efi) config
95eb8dc403SDave Cobbley        """
96eb8dc403SDave Cobbley        configfile = creator.ks.bootloader.configfile
97eb8dc403SDave Cobbley        if configfile:
98eb8dc403SDave Cobbley            grubefi_conf = get_custom_config(configfile)
99eb8dc403SDave Cobbley            if grubefi_conf:
100eb8dc403SDave Cobbley                logger.debug("Using custom configuration file %s for grub.cfg",
101eb8dc403SDave Cobbley                             configfile)
102eb8dc403SDave Cobbley            else:
103eb8dc403SDave Cobbley                raise WicError("configfile is specified "
104eb8dc403SDave Cobbley                               "but failed to get it from %s", configfile)
105eb8dc403SDave Cobbley        else:
106eb8dc403SDave Cobbley            splash = os.path.join(target_dir, "splash.jpg")
107eb8dc403SDave Cobbley            if os.path.exists(splash):
108eb8dc403SDave Cobbley                splashline = "menu background splash.jpg"
109eb8dc403SDave Cobbley            else:
110eb8dc403SDave Cobbley                splashline = ""
111eb8dc403SDave Cobbley
112eb8dc403SDave Cobbley            bootloader = creator.ks.bootloader
113eb8dc403SDave Cobbley
114eb8dc403SDave Cobbley            grubefi_conf = ""
115eb8dc403SDave Cobbley            grubefi_conf += "serial --unit=0 --speed=115200 --word=8 "
116eb8dc403SDave Cobbley            grubefi_conf += "--parity=no --stop=1\n"
117eb8dc403SDave Cobbley            grubefi_conf += "default=boot\n"
118eb8dc403SDave Cobbley            grubefi_conf += "timeout=%s\n" % (bootloader.timeout or 10)
119eb8dc403SDave Cobbley            grubefi_conf += "\n"
120eb8dc403SDave Cobbley            grubefi_conf += "search --set=root --label %s " % part.label
121eb8dc403SDave Cobbley            grubefi_conf += "\n"
122eb8dc403SDave Cobbley            grubefi_conf += "menuentry 'boot'{\n"
123eb8dc403SDave Cobbley
12415ae2509SBrad Bishop            kernel = get_bitbake_var("KERNEL_IMAGETYPE")
12596ff1984SBrad Bishop            if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1":
12696ff1984SBrad Bishop                if get_bitbake_var("INITRAMFS_IMAGE"):
12796ff1984SBrad Bishop                    kernel = "%s-%s.bin" % \
12896ff1984SBrad Bishop                        (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME"))
129eb8dc403SDave Cobbley
13015ae2509SBrad Bishop            grubefi_conf += "linux /%s rootwait %s\n" \
131eb8dc403SDave Cobbley                            % (kernel, bootloader.append)
132eb8dc403SDave Cobbley            grubefi_conf += "initrd /initrd \n"
133eb8dc403SDave Cobbley            grubefi_conf += "}\n"
134eb8dc403SDave Cobbley
135eb8dc403SDave Cobbley            if splashline:
136eb8dc403SDave Cobbley                grubefi_conf += "%s\n" % splashline
137eb8dc403SDave Cobbley
138eb8dc403SDave Cobbley        cfg_path = os.path.join(target_dir, "grub.cfg")
139eb8dc403SDave Cobbley        logger.debug("Writing grubefi config %s", cfg_path)
140eb8dc403SDave Cobbley
141eb8dc403SDave Cobbley        with open(cfg_path, "w") as cfg:
142eb8dc403SDave Cobbley            cfg.write(grubefi_conf)
143eb8dc403SDave Cobbley
144eb8dc403SDave Cobbley    @staticmethod
145eb8dc403SDave Cobbley    def _build_initramfs_path(rootfs_dir, cr_workdir):
146eb8dc403SDave Cobbley        """
147eb8dc403SDave Cobbley        Create path for initramfs image
148eb8dc403SDave Cobbley        """
149eb8dc403SDave Cobbley
150eb8dc403SDave Cobbley        initrd = get_bitbake_var("INITRD_LIVE") or get_bitbake_var("INITRD")
151eb8dc403SDave Cobbley        if not initrd:
152eb8dc403SDave Cobbley            initrd_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
153eb8dc403SDave Cobbley            if not initrd_dir:
154eb8dc403SDave Cobbley                raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting.")
155eb8dc403SDave Cobbley
156eb8dc403SDave Cobbley            image_name = get_bitbake_var("IMAGE_BASENAME")
157eb8dc403SDave Cobbley            if not image_name:
158eb8dc403SDave Cobbley                raise WicError("Couldn't find IMAGE_BASENAME, exiting.")
159eb8dc403SDave Cobbley
160eb8dc403SDave Cobbley            image_type = get_bitbake_var("INITRAMFS_FSTYPES")
161eb8dc403SDave Cobbley            if not image_type:
162eb8dc403SDave Cobbley                raise WicError("Couldn't find INITRAMFS_FSTYPES, exiting.")
163eb8dc403SDave Cobbley
164eb8dc403SDave Cobbley            machine = os.path.basename(initrd_dir)
165eb8dc403SDave Cobbley
166eb8dc403SDave Cobbley            pattern = '%s/%s*%s.%s' % (initrd_dir, image_name, machine, image_type)
167eb8dc403SDave Cobbley            files = glob.glob(pattern)
168eb8dc403SDave Cobbley            if files:
169eb8dc403SDave Cobbley                initrd = files[0]
170eb8dc403SDave Cobbley
171eb8dc403SDave Cobbley        if not initrd or not os.path.exists(initrd):
172eb8dc403SDave Cobbley            # Create initrd from rootfs directory
173eb8dc403SDave Cobbley            initrd = "%s/initrd.cpio.gz" % cr_workdir
174eb8dc403SDave Cobbley            initrd_dir = "%s/INITRD" % cr_workdir
175eb8dc403SDave Cobbley            shutil.copytree("%s" % rootfs_dir, \
176eb8dc403SDave Cobbley                            "%s" % initrd_dir, symlinks=True)
177eb8dc403SDave Cobbley
178eb8dc403SDave Cobbley            if os.path.isfile("%s/init" % rootfs_dir):
179eb8dc403SDave Cobbley                shutil.copy2("%s/init" % rootfs_dir, "%s/init" % initrd_dir)
180eb8dc403SDave Cobbley            elif os.path.lexists("%s/init" % rootfs_dir):
181eb8dc403SDave Cobbley                os.symlink(os.readlink("%s/init" % rootfs_dir), \
182eb8dc403SDave Cobbley                            "%s/init" % initrd_dir)
183eb8dc403SDave Cobbley            elif os.path.isfile("%s/sbin/init" % rootfs_dir):
184eb8dc403SDave Cobbley                shutil.copy2("%s/sbin/init" % rootfs_dir, \
185eb8dc403SDave Cobbley                            "%s" % initrd_dir)
186eb8dc403SDave Cobbley            elif os.path.lexists("%s/sbin/init" % rootfs_dir):
187eb8dc403SDave Cobbley                os.symlink(os.readlink("%s/sbin/init" % rootfs_dir), \
188eb8dc403SDave Cobbley                            "%s/init" % initrd_dir)
189eb8dc403SDave Cobbley            else:
190eb8dc403SDave Cobbley                raise WicError("Couldn't find or build initrd, exiting.")
191eb8dc403SDave Cobbley
1921a4b7ee2SBrad Bishop            exec_cmd("cd %s && find . | cpio -o -H newc -R root:root >%s/initrd.cpio " \
1931a4b7ee2SBrad Bishop                     % (initrd_dir, cr_workdir), as_shell=True)
1941a4b7ee2SBrad Bishop            exec_cmd("gzip -f -9 %s/initrd.cpio" % cr_workdir, as_shell=True)
195eb8dc403SDave Cobbley            shutil.rmtree(initrd_dir)
196eb8dc403SDave Cobbley
197eb8dc403SDave Cobbley        return initrd
198eb8dc403SDave Cobbley
199eb8dc403SDave Cobbley    @classmethod
200eb8dc403SDave Cobbley    def do_configure_partition(cls, part, source_params, creator, cr_workdir,
201eb8dc403SDave Cobbley                               oe_builddir, bootimg_dir, kernel_dir,
202eb8dc403SDave Cobbley                               native_sysroot):
203eb8dc403SDave Cobbley        """
204eb8dc403SDave Cobbley        Called before do_prepare_partition(), creates loader-specific config
205eb8dc403SDave Cobbley        """
206eb8dc403SDave Cobbley        isodir = "%s/ISO/" % cr_workdir
207eb8dc403SDave Cobbley
208eb8dc403SDave Cobbley        if os.path.exists(isodir):
209eb8dc403SDave Cobbley            shutil.rmtree(isodir)
210eb8dc403SDave Cobbley
211eb8dc403SDave Cobbley        install_cmd = "install -d %s " % isodir
212eb8dc403SDave Cobbley        exec_cmd(install_cmd)
213eb8dc403SDave Cobbley
214eb8dc403SDave Cobbley        # Overwrite the name of the created image
215eb8dc403SDave Cobbley        logger.debug(source_params)
216eb8dc403SDave Cobbley        if 'image_name' in source_params and \
217eb8dc403SDave Cobbley                    source_params['image_name'].strip():
218eb8dc403SDave Cobbley            creator.name = source_params['image_name'].strip()
219eb8dc403SDave Cobbley            logger.debug("The name of the image is: %s", creator.name)
220eb8dc403SDave Cobbley
2216ce62a20SAndrew Geissler    @staticmethod
2226ce62a20SAndrew Geissler    def _install_payload(source_params, iso_dir):
2236ce62a20SAndrew Geissler        """
2246ce62a20SAndrew Geissler        Copies contents of payload directory (as specified in 'payload_dir' param) into iso_dir
2256ce62a20SAndrew Geissler        """
2266ce62a20SAndrew Geissler
2276ce62a20SAndrew Geissler        if source_params.get('payload_dir'):
2286ce62a20SAndrew Geissler            payload_dir = source_params['payload_dir']
2296ce62a20SAndrew Geissler
2306ce62a20SAndrew Geissler            logger.debug("Payload directory: %s", payload_dir)
2316ce62a20SAndrew Geissler            shutil.copytree(payload_dir, iso_dir, symlinks=True, dirs_exist_ok=True)
2326ce62a20SAndrew Geissler
233eb8dc403SDave Cobbley    @classmethod
234eb8dc403SDave Cobbley    def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
235eb8dc403SDave Cobbley                             oe_builddir, bootimg_dir, kernel_dir,
236eb8dc403SDave Cobbley                             rootfs_dir, native_sysroot):
237eb8dc403SDave Cobbley        """
238eb8dc403SDave Cobbley        Called to do the actual content population for a partition i.e. it
239eb8dc403SDave Cobbley        'prepares' the partition to be incorporated into the image.
240eb8dc403SDave Cobbley        In this case, prepare content for a bootable ISO image.
241eb8dc403SDave Cobbley        """
242eb8dc403SDave Cobbley
243eb8dc403SDave Cobbley        isodir = "%s/ISO" % cr_workdir
244eb8dc403SDave Cobbley
2456ce62a20SAndrew Geissler        cls._install_payload(source_params, isodir)
2466ce62a20SAndrew Geissler
247eb8dc403SDave Cobbley        if part.rootfs_dir is None:
248eb8dc403SDave Cobbley            if not 'ROOTFS_DIR' in rootfs_dir:
249eb8dc403SDave Cobbley                raise WicError("Couldn't find --rootfs-dir, exiting.")
250eb8dc403SDave Cobbley            rootfs_dir = rootfs_dir['ROOTFS_DIR']
251eb8dc403SDave Cobbley        else:
252eb8dc403SDave Cobbley            if part.rootfs_dir in rootfs_dir:
253eb8dc403SDave Cobbley                rootfs_dir = rootfs_dir[part.rootfs_dir]
254eb8dc403SDave Cobbley            elif part.rootfs_dir:
255eb8dc403SDave Cobbley                rootfs_dir = part.rootfs_dir
256eb8dc403SDave Cobbley            else:
257eb8dc403SDave Cobbley                raise WicError("Couldn't find --rootfs-dir=%s connection "
258eb8dc403SDave Cobbley                               "or it is not a valid path, exiting." %
259eb8dc403SDave Cobbley                               part.rootfs_dir)
260eb8dc403SDave Cobbley
261eb8dc403SDave Cobbley        if not os.path.isdir(rootfs_dir):
262eb8dc403SDave Cobbley            rootfs_dir = get_bitbake_var("IMAGE_ROOTFS")
263eb8dc403SDave Cobbley        if not os.path.isdir(rootfs_dir):
264eb8dc403SDave Cobbley            raise WicError("Couldn't find IMAGE_ROOTFS, exiting.")
265eb8dc403SDave Cobbley
266eb8dc403SDave Cobbley        part.rootfs_dir = rootfs_dir
267eb8dc403SDave Cobbley        deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
268eb8dc403SDave Cobbley        img_iso_dir = get_bitbake_var("ISODIR")
269eb8dc403SDave Cobbley
270eb8dc403SDave Cobbley        # Remove the temporary file created by part.prepare_rootfs()
271eb8dc403SDave Cobbley        if os.path.isfile(part.source_file):
272eb8dc403SDave Cobbley            os.remove(part.source_file)
273eb8dc403SDave Cobbley
274eb8dc403SDave Cobbley        # Support using a different initrd other than default
275eb8dc403SDave Cobbley        if source_params.get('initrd'):
276eb8dc403SDave Cobbley            initrd = source_params['initrd']
277eb8dc403SDave Cobbley            if not deploy_dir:
278eb8dc403SDave Cobbley                raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
279eb8dc403SDave Cobbley            cp_cmd = "cp %s/%s %s" % (deploy_dir, initrd, cr_workdir)
280eb8dc403SDave Cobbley            exec_cmd(cp_cmd)
281eb8dc403SDave Cobbley        else:
282eb8dc403SDave Cobbley            # Prepare initial ramdisk
283eb8dc403SDave Cobbley            initrd = "%s/initrd" % deploy_dir
284eb8dc403SDave Cobbley            if not os.path.isfile(initrd):
285eb8dc403SDave Cobbley                initrd = "%s/initrd" % img_iso_dir
286eb8dc403SDave Cobbley            if not os.path.isfile(initrd):
287eb8dc403SDave Cobbley                initrd = cls._build_initramfs_path(rootfs_dir, cr_workdir)
288eb8dc403SDave Cobbley
289eb8dc403SDave Cobbley        install_cmd = "install -m 0644 %s %s/initrd" % (initrd, isodir)
290eb8dc403SDave Cobbley        exec_cmd(install_cmd)
291eb8dc403SDave Cobbley
292eb8dc403SDave Cobbley        # Remove the temporary file created by _build_initramfs_path function
293eb8dc403SDave Cobbley        if os.path.isfile("%s/initrd.cpio.gz" % cr_workdir):
294eb8dc403SDave Cobbley            os.remove("%s/initrd.cpio.gz" % cr_workdir)
295eb8dc403SDave Cobbley
29615ae2509SBrad Bishop        kernel = get_bitbake_var("KERNEL_IMAGETYPE")
29796ff1984SBrad Bishop        if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1":
29896ff1984SBrad Bishop            if get_bitbake_var("INITRAMFS_IMAGE"):
29996ff1984SBrad Bishop                kernel = "%s-%s.bin" % \
30096ff1984SBrad Bishop                    (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME"))
30115ae2509SBrad Bishop
30215ae2509SBrad Bishop        install_cmd = "install -m 0644 %s/%s %s/%s" % \
30315ae2509SBrad Bishop                      (kernel_dir, kernel, isodir, kernel)
304eb8dc403SDave Cobbley        exec_cmd(install_cmd)
305eb8dc403SDave Cobbley
306eb8dc403SDave Cobbley        #Create bootloader for efi boot
307eb8dc403SDave Cobbley        try:
308eb8dc403SDave Cobbley            target_dir = "%s/EFI/BOOT" % isodir
309eb8dc403SDave Cobbley            if os.path.exists(target_dir):
310eb8dc403SDave Cobbley                shutil.rmtree(target_dir)
311eb8dc403SDave Cobbley
312eb8dc403SDave Cobbley            os.makedirs(target_dir)
313eb8dc403SDave Cobbley
314eb8dc403SDave Cobbley            if source_params['loader'] == 'grub-efi':
315eb8dc403SDave Cobbley                # Builds bootx64.efi/bootia32.efi if ISODIR didn't exist or
316eb8dc403SDave Cobbley                # didn't contains it
317eb8dc403SDave Cobbley                target_arch = get_bitbake_var("TARGET_SYS")
318eb8dc403SDave Cobbley                if not target_arch:
319eb8dc403SDave Cobbley                    raise WicError("Coludn't find target architecture")
320eb8dc403SDave Cobbley
321eb8dc403SDave Cobbley                if re.match("x86_64", target_arch):
322c4ea075dSBrad Bishop                    grub_src_image = "grub-efi-bootx64.efi"
323c4ea075dSBrad Bishop                    grub_dest_image = "bootx64.efi"
324eb8dc403SDave Cobbley                elif re.match('i.86', target_arch):
325c4ea075dSBrad Bishop                    grub_src_image = "grub-efi-bootia32.efi"
326c4ea075dSBrad Bishop                    grub_dest_image = "bootia32.efi"
327eb8dc403SDave Cobbley                else:
328eb8dc403SDave Cobbley                    raise WicError("grub-efi is incompatible with target %s" %
329eb8dc403SDave Cobbley                                   target_arch)
330eb8dc403SDave Cobbley
331c4ea075dSBrad Bishop                grub_target = os.path.join(target_dir, grub_dest_image)
332eb8dc403SDave Cobbley                if not os.path.isfile(grub_target):
333c4ea075dSBrad Bishop                    grub_src = os.path.join(deploy_dir, grub_src_image)
334eb8dc403SDave Cobbley                    if not os.path.exists(grub_src):
335eb8dc403SDave Cobbley                        raise WicError("Grub loader %s is not found in %s. "
3361a4b7ee2SBrad Bishop                                       "Please build grub-efi first" % (grub_src_image, deploy_dir))
337eb8dc403SDave Cobbley                    shutil.copy(grub_src, grub_target)
338eb8dc403SDave Cobbley
339eb8dc403SDave Cobbley                if not os.path.isfile(os.path.join(target_dir, "boot.cfg")):
340eb8dc403SDave Cobbley                    cls.do_configure_grubefi(part, creator, target_dir)
341eb8dc403SDave Cobbley
342eb8dc403SDave Cobbley            else:
343eb8dc403SDave Cobbley                raise WicError("unrecognized bootimg-efi loader: %s" %
344eb8dc403SDave Cobbley                               source_params['loader'])
345eb8dc403SDave Cobbley        except KeyError:
346eb8dc403SDave Cobbley            raise WicError("bootimg-efi requires a loader, none specified")
347eb8dc403SDave Cobbley
348eb8dc403SDave Cobbley        # Create efi.img that contains bootloader files for EFI booting
349eb8dc403SDave Cobbley        # if ISODIR didn't exist or didn't contains it
350eb8dc403SDave Cobbley        if os.path.isfile("%s/efi.img" % img_iso_dir):
351eb8dc403SDave Cobbley            install_cmd = "install -m 0644 %s/efi.img %s/efi.img" % \
352eb8dc403SDave Cobbley                (img_iso_dir, isodir)
353eb8dc403SDave Cobbley            exec_cmd(install_cmd)
354eb8dc403SDave Cobbley        else:
3551d80a2eaSBrad Bishop            # Default to 100 blocks of extra space for file system overhead
3561d80a2eaSBrad Bishop            esp_extra_blocks = int(source_params.get('esp_extra_blocks', '100'))
3571d80a2eaSBrad Bishop
358eb8dc403SDave Cobbley            du_cmd = "du -bks %s/EFI" % isodir
359eb8dc403SDave Cobbley            out = exec_cmd(du_cmd)
360eb8dc403SDave Cobbley            blocks = int(out.split()[0])
3611d80a2eaSBrad Bishop            blocks += esp_extra_blocks
362eb8dc403SDave Cobbley            logger.debug("Added 100 extra blocks to %s to get to %d "
363eb8dc403SDave Cobbley                         "total blocks", part.mountpoint, blocks)
364eb8dc403SDave Cobbley
365eb8dc403SDave Cobbley            # dosfs image for EFI boot
366eb8dc403SDave Cobbley            bootimg = "%s/efi.img" % isodir
367eb8dc403SDave Cobbley
3681d80a2eaSBrad Bishop            esp_label = source_params.get('esp_label', 'EFIimg')
3691d80a2eaSBrad Bishop
3701d80a2eaSBrad Bishop            dosfs_cmd = 'mkfs.vfat -n \'%s\' -S 512 -C %s %d' \
3711d80a2eaSBrad Bishop                        % (esp_label, bootimg, blocks)
372eb8dc403SDave Cobbley            exec_native_cmd(dosfs_cmd, native_sysroot)
373eb8dc403SDave Cobbley
374eb8dc403SDave Cobbley            mmd_cmd = "mmd -i %s ::/EFI" % bootimg
375eb8dc403SDave Cobbley            exec_native_cmd(mmd_cmd, native_sysroot)
376eb8dc403SDave Cobbley
377eb8dc403SDave Cobbley            mcopy_cmd = "mcopy -i %s -s %s/EFI/* ::/EFI/" \
378eb8dc403SDave Cobbley                        % (bootimg, isodir)
379eb8dc403SDave Cobbley            exec_native_cmd(mcopy_cmd, native_sysroot)
380eb8dc403SDave Cobbley
381eb8dc403SDave Cobbley            chmod_cmd = "chmod 644 %s" % bootimg
382eb8dc403SDave Cobbley            exec_cmd(chmod_cmd)
383eb8dc403SDave Cobbley
384eb8dc403SDave Cobbley        # Prepare files for legacy boot
385eb8dc403SDave Cobbley        syslinux_dir = get_bitbake_var("STAGING_DATADIR")
386eb8dc403SDave Cobbley        if not syslinux_dir:
387eb8dc403SDave Cobbley            raise WicError("Couldn't find STAGING_DATADIR, exiting.")
388eb8dc403SDave Cobbley
389eb8dc403SDave Cobbley        if os.path.exists("%s/isolinux" % isodir):
390eb8dc403SDave Cobbley            shutil.rmtree("%s/isolinux" % isodir)
391eb8dc403SDave Cobbley
392eb8dc403SDave Cobbley        install_cmd = "install -d %s/isolinux" % isodir
393eb8dc403SDave Cobbley        exec_cmd(install_cmd)
394eb8dc403SDave Cobbley
395eb8dc403SDave Cobbley        cls.do_configure_syslinux(creator, cr_workdir)
396eb8dc403SDave Cobbley
397eb8dc403SDave Cobbley        install_cmd = "install -m 444 %s/syslinux/ldlinux.sys " % syslinux_dir
398eb8dc403SDave Cobbley        install_cmd += "%s/isolinux/ldlinux.sys" % isodir
399eb8dc403SDave Cobbley        exec_cmd(install_cmd)
400eb8dc403SDave Cobbley
401eb8dc403SDave Cobbley        install_cmd = "install -m 444 %s/syslinux/isohdpfx.bin " % syslinux_dir
402eb8dc403SDave Cobbley        install_cmd += "%s/isolinux/isohdpfx.bin" % isodir
403eb8dc403SDave Cobbley        exec_cmd(install_cmd)
404eb8dc403SDave Cobbley
405eb8dc403SDave Cobbley        install_cmd = "install -m 644 %s/syslinux/isolinux.bin " % syslinux_dir
406eb8dc403SDave Cobbley        install_cmd += "%s/isolinux/isolinux.bin" % isodir
407eb8dc403SDave Cobbley        exec_cmd(install_cmd)
408eb8dc403SDave Cobbley
409eb8dc403SDave Cobbley        install_cmd = "install -m 644 %s/syslinux/ldlinux.c32 " % syslinux_dir
410eb8dc403SDave Cobbley        install_cmd += "%s/isolinux/ldlinux.c32" % isodir
411eb8dc403SDave Cobbley        exec_cmd(install_cmd)
412eb8dc403SDave Cobbley
413eb8dc403SDave Cobbley        #create ISO image
414eb8dc403SDave Cobbley        iso_img = "%s/tempiso_img.iso" % cr_workdir
415eb8dc403SDave Cobbley        iso_bootimg = "isolinux/isolinux.bin"
416eb8dc403SDave Cobbley        iso_bootcat = "isolinux/boot.cat"
417eb8dc403SDave Cobbley        efi_img = "efi.img"
418eb8dc403SDave Cobbley
419eb8dc403SDave Cobbley        mkisofs_cmd = "mkisofs -V %s " % part.label
420eb8dc403SDave Cobbley        mkisofs_cmd += "-o %s -U " % iso_img
421eb8dc403SDave Cobbley        mkisofs_cmd += "-J -joliet-long -r -iso-level 2 -b %s " % iso_bootimg
422eb8dc403SDave Cobbley        mkisofs_cmd += "-c %s -no-emul-boot -boot-load-size 4 " % iso_bootcat
423eb8dc403SDave Cobbley        mkisofs_cmd += "-boot-info-table -eltorito-alt-boot "
424eb8dc403SDave Cobbley        mkisofs_cmd += "-eltorito-platform 0xEF -eltorito-boot %s " % efi_img
425eb8dc403SDave Cobbley        mkisofs_cmd += "-no-emul-boot %s " % isodir
426eb8dc403SDave Cobbley
427eb8dc403SDave Cobbley        logger.debug("running command: %s", mkisofs_cmd)
428eb8dc403SDave Cobbley        exec_native_cmd(mkisofs_cmd, native_sysroot)
429eb8dc403SDave Cobbley
430eb8dc403SDave Cobbley        shutil.rmtree(isodir)
431eb8dc403SDave Cobbley
432eb8dc403SDave Cobbley        du_cmd = "du -Lbks %s" % iso_img
433eb8dc403SDave Cobbley        out = exec_cmd(du_cmd)
434eb8dc403SDave Cobbley        isoimg_size = int(out.split()[0])
435eb8dc403SDave Cobbley
436eb8dc403SDave Cobbley        part.size = isoimg_size
437eb8dc403SDave Cobbley        part.source_file = iso_img
438eb8dc403SDave Cobbley
439eb8dc403SDave Cobbley    @classmethod
440eb8dc403SDave Cobbley    def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir,
441eb8dc403SDave Cobbley                        bootimg_dir, kernel_dir, native_sysroot):
442eb8dc403SDave Cobbley        """
443eb8dc403SDave Cobbley        Called after all partitions have been prepared and assembled into a
444eb8dc403SDave Cobbley        disk image.  In this case, we insert/modify the MBR using isohybrid
445eb8dc403SDave Cobbley        utility for booting via BIOS from disk storage devices.
446eb8dc403SDave Cobbley        """
447eb8dc403SDave Cobbley
448eb8dc403SDave Cobbley        iso_img = "%s.p1" % disk.path
449eb8dc403SDave Cobbley        full_path = creator._full_path(workdir, disk_name, "direct")
450eb8dc403SDave Cobbley        full_path_iso = creator._full_path(workdir, disk_name, "iso")
451eb8dc403SDave Cobbley
452eb8dc403SDave Cobbley        isohybrid_cmd = "isohybrid -u %s" % iso_img
453eb8dc403SDave Cobbley        logger.debug("running command: %s", isohybrid_cmd)
454eb8dc403SDave Cobbley        exec_native_cmd(isohybrid_cmd, native_sysroot)
455eb8dc403SDave Cobbley
456eb8dc403SDave Cobbley        # Replace the image created by direct plugin with the one created by
457eb8dc403SDave Cobbley        # mkisofs command. This is necessary because the iso image created by
458eb8dc403SDave Cobbley        # mkisofs has a very specific MBR is system area of the ISO image, and
459eb8dc403SDave Cobbley        # direct plugin adds and configures an another MBR.
460eb8dc403SDave Cobbley        logger.debug("Replaceing the image created by direct plugin\n")
461eb8dc403SDave Cobbley        os.remove(disk.path)
462eb8dc403SDave Cobbley        shutil.copy2(iso_img, full_path_iso)
463eb8dc403SDave Cobbley        shutil.copy2(full_path_iso, full_path)
464