1eb8dc403SDave Cobbley#
2eb8dc403SDave Cobbley# Copyright (c) 2014, Intel Corporation.
3eb8dc403SDave Cobbley#
4c342db35SBrad Bishop# SPDX-License-Identifier: GPL-2.0-only
5eb8dc403SDave Cobbley#
6eb8dc403SDave Cobbley# DESCRIPTION
7eb8dc403SDave Cobbley# This implements the 'bootimg-pcbios' source plugin class for 'wic'
8eb8dc403SDave Cobbley#
9eb8dc403SDave Cobbley# AUTHORS
10eb8dc403SDave Cobbley# Tom Zanussi <tom.zanussi (at] linux.intel.com>
11eb8dc403SDave Cobbley#
12eb8dc403SDave Cobbley
13eb8dc403SDave Cobbleyimport logging
14eb8dc403SDave Cobbleyimport os
151a4b7ee2SBrad Bishopimport re
16eb8dc403SDave Cobbley
17eb8dc403SDave Cobbleyfrom wic import WicError
18eb8dc403SDave Cobbleyfrom wic.engine import get_custom_config
19eb8dc403SDave Cobbleyfrom wic.pluginbase import SourcePlugin
20eb8dc403SDave Cobbleyfrom wic.misc import (exec_cmd, exec_native_cmd,
21eb8dc403SDave Cobbley                      get_bitbake_var, BOOTDD_EXTRA_SPACE)
22eb8dc403SDave Cobbley
23eb8dc403SDave Cobbleylogger = logging.getLogger('wic')
24eb8dc403SDave Cobbley
25eb8dc403SDave Cobbleyclass BootimgPcbiosPlugin(SourcePlugin):
26eb8dc403SDave Cobbley    """
27eb8dc403SDave Cobbley    Create MBR boot partition and install syslinux on it.
28eb8dc403SDave Cobbley    """
29eb8dc403SDave Cobbley
30eb8dc403SDave Cobbley    name = 'bootimg-pcbios'
31eb8dc403SDave Cobbley
32eb8dc403SDave Cobbley    @classmethod
33eb8dc403SDave Cobbley    def _get_bootimg_dir(cls, bootimg_dir, dirname):
34eb8dc403SDave Cobbley        """
35eb8dc403SDave Cobbley        Check if dirname exists in default bootimg_dir or in STAGING_DIR.
36eb8dc403SDave Cobbley        """
371a4b7ee2SBrad Bishop        staging_datadir = get_bitbake_var("STAGING_DATADIR")
381a4b7ee2SBrad Bishop        for result in (bootimg_dir, staging_datadir):
39eb8dc403SDave Cobbley            if os.path.exists("%s/%s" % (result, dirname)):
40eb8dc403SDave Cobbley                return result
41eb8dc403SDave Cobbley
421a4b7ee2SBrad Bishop        # STAGING_DATADIR is expanded with MLPREFIX if multilib is enabled
431a4b7ee2SBrad Bishop        # but dependency syslinux is still populated to original STAGING_DATADIR
441a4b7ee2SBrad Bishop        nonarch_datadir = re.sub('/[^/]*recipe-sysroot', '/recipe-sysroot', staging_datadir)
451a4b7ee2SBrad Bishop        if os.path.exists(os.path.join(nonarch_datadir, dirname)):
461a4b7ee2SBrad Bishop            return nonarch_datadir
471a4b7ee2SBrad Bishop
48eb8dc403SDave Cobbley        raise WicError("Couldn't find correct bootimg_dir, exiting")
49eb8dc403SDave Cobbley
50eb8dc403SDave Cobbley    @classmethod
51eb8dc403SDave Cobbley    def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir,
52eb8dc403SDave Cobbley                        bootimg_dir, kernel_dir, native_sysroot):
53eb8dc403SDave Cobbley        """
54eb8dc403SDave Cobbley        Called after all partitions have been prepared and assembled into a
55eb8dc403SDave Cobbley        disk image.  In this case, we install the MBR.
56eb8dc403SDave Cobbley        """
57eb8dc403SDave Cobbley        bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux')
58eb8dc403SDave Cobbley        mbrfile = "%s/syslinux/" % bootimg_dir
59eb8dc403SDave Cobbley        if creator.ptable_format == 'msdos':
60eb8dc403SDave Cobbley            mbrfile += "mbr.bin"
61eb8dc403SDave Cobbley        elif creator.ptable_format == 'gpt':
62eb8dc403SDave Cobbley            mbrfile += "gptmbr.bin"
63eb8dc403SDave Cobbley        else:
64eb8dc403SDave Cobbley            raise WicError("Unsupported partition table: %s" %
65eb8dc403SDave Cobbley                           creator.ptable_format)
66eb8dc403SDave Cobbley
67eb8dc403SDave Cobbley        if not os.path.exists(mbrfile):
68eb8dc403SDave Cobbley            raise WicError("Couldn't find %s.  If using the -e option, do you "
69eb8dc403SDave Cobbley                           "have the right MACHINE set in local.conf?  If not, "
70eb8dc403SDave Cobbley                           "is the bootimg_dir path correct?" % mbrfile)
71eb8dc403SDave Cobbley
72eb8dc403SDave Cobbley        full_path = creator._full_path(workdir, disk_name, "direct")
73eb8dc403SDave Cobbley        logger.debug("Installing MBR on disk %s as %s with size %s bytes",
74eb8dc403SDave Cobbley                     disk_name, full_path, disk.min_size)
75eb8dc403SDave Cobbley
76eb8dc403SDave Cobbley        dd_cmd = "dd if=%s of=%s conv=notrunc" % (mbrfile, full_path)
77eb8dc403SDave Cobbley        exec_cmd(dd_cmd, native_sysroot)
78eb8dc403SDave Cobbley
79eb8dc403SDave Cobbley    @classmethod
80eb8dc403SDave Cobbley    def do_configure_partition(cls, part, source_params, creator, cr_workdir,
81eb8dc403SDave Cobbley                               oe_builddir, bootimg_dir, kernel_dir,
82eb8dc403SDave Cobbley                               native_sysroot):
83eb8dc403SDave Cobbley        """
84eb8dc403SDave Cobbley        Called before do_prepare_partition(), creates syslinux config
85eb8dc403SDave Cobbley        """
86eb8dc403SDave Cobbley        hdddir = "%s/hdd/boot" % cr_workdir
87eb8dc403SDave Cobbley
88eb8dc403SDave Cobbley        install_cmd = "install -d %s" % hdddir
89eb8dc403SDave Cobbley        exec_cmd(install_cmd)
90eb8dc403SDave Cobbley
91eb8dc403SDave Cobbley        bootloader = creator.ks.bootloader
92eb8dc403SDave Cobbley
93eb8dc403SDave Cobbley        custom_cfg = None
94eb8dc403SDave Cobbley        if bootloader.configfile:
95eb8dc403SDave Cobbley            custom_cfg = get_custom_config(bootloader.configfile)
96eb8dc403SDave Cobbley            if custom_cfg:
97eb8dc403SDave Cobbley                # Use a custom configuration for grub
98eb8dc403SDave Cobbley                syslinux_conf = custom_cfg
99eb8dc403SDave Cobbley                logger.debug("Using custom configuration file %s "
100eb8dc403SDave Cobbley                             "for syslinux.cfg", bootloader.configfile)
101eb8dc403SDave Cobbley            else:
102eb8dc403SDave Cobbley                raise WicError("configfile is specified but failed to "
103eb8dc403SDave Cobbley                               "get it from %s." % bootloader.configfile)
104eb8dc403SDave Cobbley
105eb8dc403SDave Cobbley        if not custom_cfg:
106eb8dc403SDave Cobbley            # Create syslinux configuration using parameters from wks file
107eb8dc403SDave Cobbley            splash = os.path.join(cr_workdir, "/hdd/boot/splash.jpg")
108eb8dc403SDave Cobbley            if os.path.exists(splash):
109eb8dc403SDave Cobbley                splashline = "menu background splash.jpg"
110eb8dc403SDave Cobbley            else:
111eb8dc403SDave Cobbley                splashline = ""
112eb8dc403SDave Cobbley
113eb8dc403SDave Cobbley            syslinux_conf = ""
114eb8dc403SDave Cobbley            syslinux_conf += "PROMPT 0\n"
115eb8dc403SDave Cobbley            syslinux_conf += "TIMEOUT " + str(bootloader.timeout) + "\n"
116eb8dc403SDave Cobbley            syslinux_conf += "\n"
117eb8dc403SDave Cobbley            syslinux_conf += "ALLOWOPTIONS 1\n"
118eb8dc403SDave Cobbley            syslinux_conf += "SERIAL 0 115200\n"
119eb8dc403SDave Cobbley            syslinux_conf += "\n"
120eb8dc403SDave Cobbley            if splashline:
121eb8dc403SDave Cobbley                syslinux_conf += "%s\n" % splashline
122eb8dc403SDave Cobbley            syslinux_conf += "DEFAULT boot\n"
123eb8dc403SDave Cobbley            syslinux_conf += "LABEL boot\n"
124eb8dc403SDave Cobbley
125*028142bdSAndrew Geissler            kernel = "/" + get_bitbake_var("KERNEL_IMAGETYPE")
126eb8dc403SDave Cobbley            syslinux_conf += "KERNEL " + kernel + "\n"
127eb8dc403SDave Cobbley
128eb8dc403SDave Cobbley            syslinux_conf += "APPEND label=boot root=%s %s\n" % \
129eb8dc403SDave Cobbley                             (creator.rootdev, bootloader.append)
130eb8dc403SDave Cobbley
131eb8dc403SDave Cobbley        logger.debug("Writing syslinux config %s/hdd/boot/syslinux.cfg",
132eb8dc403SDave Cobbley                     cr_workdir)
133eb8dc403SDave Cobbley        cfg = open("%s/hdd/boot/syslinux.cfg" % cr_workdir, "w")
134eb8dc403SDave Cobbley        cfg.write(syslinux_conf)
135eb8dc403SDave Cobbley        cfg.close()
136eb8dc403SDave Cobbley
137eb8dc403SDave Cobbley    @classmethod
138eb8dc403SDave Cobbley    def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
139eb8dc403SDave Cobbley                             oe_builddir, bootimg_dir, kernel_dir,
140eb8dc403SDave Cobbley                             rootfs_dir, native_sysroot):
141eb8dc403SDave Cobbley        """
142eb8dc403SDave Cobbley        Called to do the actual content population for a partition i.e. it
143eb8dc403SDave Cobbley        'prepares' the partition to be incorporated into the image.
144eb8dc403SDave Cobbley        In this case, prepare content for legacy bios boot partition.
145eb8dc403SDave Cobbley        """
146eb8dc403SDave Cobbley        bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux')
147eb8dc403SDave Cobbley
148eb8dc403SDave Cobbley        staging_kernel_dir = kernel_dir
149eb8dc403SDave Cobbley
150eb8dc403SDave Cobbley        hdddir = "%s/hdd/boot" % cr_workdir
151eb8dc403SDave Cobbley
15215ae2509SBrad Bishop        kernel = get_bitbake_var("KERNEL_IMAGETYPE")
15396ff1984SBrad Bishop        if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1":
15496ff1984SBrad Bishop            if get_bitbake_var("INITRAMFS_IMAGE"):
15596ff1984SBrad Bishop                kernel = "%s-%s.bin" % \
15696ff1984SBrad Bishop                    (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME"))
15715ae2509SBrad Bishop
158*028142bdSAndrew Geissler        cmds = ("install -m 0644 %s/%s %s/%s" %
159*028142bdSAndrew Geissler                (staging_kernel_dir, kernel, hdddir, get_bitbake_var("KERNEL_IMAGETYPE")),
160eb8dc403SDave Cobbley                "install -m 444 %s/syslinux/ldlinux.sys %s/ldlinux.sys" %
161eb8dc403SDave Cobbley                (bootimg_dir, hdddir),
162eb8dc403SDave Cobbley                "install -m 0644 %s/syslinux/vesamenu.c32 %s/vesamenu.c32" %
163eb8dc403SDave Cobbley                (bootimg_dir, hdddir),
164eb8dc403SDave Cobbley                "install -m 444 %s/syslinux/libcom32.c32 %s/libcom32.c32" %
165eb8dc403SDave Cobbley                (bootimg_dir, hdddir),
166eb8dc403SDave Cobbley                "install -m 444 %s/syslinux/libutil.c32 %s/libutil.c32" %
167eb8dc403SDave Cobbley                (bootimg_dir, hdddir))
168eb8dc403SDave Cobbley
169eb8dc403SDave Cobbley        for install_cmd in cmds:
170eb8dc403SDave Cobbley            exec_cmd(install_cmd)
171eb8dc403SDave Cobbley
172eb8dc403SDave Cobbley        du_cmd = "du -bks %s" % hdddir
173eb8dc403SDave Cobbley        out = exec_cmd(du_cmd)
174eb8dc403SDave Cobbley        blocks = int(out.split()[0])
175eb8dc403SDave Cobbley
176eb8dc403SDave Cobbley        extra_blocks = part.get_extra_block_count(blocks)
177eb8dc403SDave Cobbley
178eb8dc403SDave Cobbley        if extra_blocks < BOOTDD_EXTRA_SPACE:
179eb8dc403SDave Cobbley            extra_blocks = BOOTDD_EXTRA_SPACE
180eb8dc403SDave Cobbley
181eb8dc403SDave Cobbley        blocks += extra_blocks
182eb8dc403SDave Cobbley
183eb8dc403SDave Cobbley        logger.debug("Added %d extra blocks to %s to get to %d total blocks",
184eb8dc403SDave Cobbley                     extra_blocks, part.mountpoint, blocks)
185eb8dc403SDave Cobbley
186eb8dc403SDave Cobbley        # dosfs image, created by mkdosfs
187eb8dc403SDave Cobbley        bootimg = "%s/boot%s.img" % (cr_workdir, part.lineno)
188eb8dc403SDave Cobbley
1895f35090dSAndrew Geissler        label = part.label if part.label else "boot"
1905f35090dSAndrew Geissler
1915f35090dSAndrew Geissler        dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
1925f35090dSAndrew Geissler                    (label, part.fsuuid, bootimg, blocks)
193eb8dc403SDave Cobbley        exec_native_cmd(dosfs_cmd, native_sysroot)
194eb8dc403SDave Cobbley
195eb8dc403SDave Cobbley        mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
196eb8dc403SDave Cobbley        exec_native_cmd(mcopy_cmd, native_sysroot)
197eb8dc403SDave Cobbley
198eb8dc403SDave Cobbley        syslinux_cmd = "syslinux %s" % bootimg
199eb8dc403SDave Cobbley        exec_native_cmd(syslinux_cmd, native_sysroot)
200eb8dc403SDave Cobbley
201eb8dc403SDave Cobbley        chmod_cmd = "chmod 644 %s" % bootimg
202eb8dc403SDave Cobbley        exec_cmd(chmod_cmd)
203eb8dc403SDave Cobbley
204eb8dc403SDave Cobbley        du_cmd = "du -Lbks %s" % bootimg
205eb8dc403SDave Cobbley        out = exec_cmd(du_cmd)
206eb8dc403SDave Cobbley        bootimg_size = out.split()[0]
207eb8dc403SDave Cobbley
208eb8dc403SDave Cobbley        part.size = int(bootimg_size)
209eb8dc403SDave Cobbley        part.source_file = bootimg
210