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