xref: /OK3568_Linux_fs/yocto/poky/scripts/lib/wic/plugins/source/bootimg-partition.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun# DESCRIPTION
5*4882a593Smuzhiyun# This implements the 'bootimg-partition' source plugin class for
6*4882a593Smuzhiyun# 'wic'. The plugin creates an image of boot partition, copying over
7*4882a593Smuzhiyun# files listed in IMAGE_BOOT_FILES bitbake variable.
8*4882a593Smuzhiyun#
9*4882a593Smuzhiyun# AUTHORS
10*4882a593Smuzhiyun# Maciej Borzecki <maciej.borzecki (at] open-rnd.pl>
11*4882a593Smuzhiyun#
12*4882a593Smuzhiyun
13*4882a593Smuzhiyunimport logging
14*4882a593Smuzhiyunimport os
15*4882a593Smuzhiyunimport re
16*4882a593Smuzhiyun
17*4882a593Smuzhiyunfrom glob import glob
18*4882a593Smuzhiyun
19*4882a593Smuzhiyunfrom wic import WicError
20*4882a593Smuzhiyunfrom wic.engine import get_custom_config
21*4882a593Smuzhiyunfrom wic.pluginbase import SourcePlugin
22*4882a593Smuzhiyunfrom wic.misc import exec_cmd, get_bitbake_var
23*4882a593Smuzhiyun
24*4882a593Smuzhiyunlogger = logging.getLogger('wic')
25*4882a593Smuzhiyun
26*4882a593Smuzhiyunclass BootimgPartitionPlugin(SourcePlugin):
27*4882a593Smuzhiyun    """
28*4882a593Smuzhiyun    Create an image of boot partition, copying over files
29*4882a593Smuzhiyun    listed in IMAGE_BOOT_FILES bitbake variable.
30*4882a593Smuzhiyun    """
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun    name = 'bootimg-partition'
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun    @classmethod
35*4882a593Smuzhiyun    def do_configure_partition(cls, part, source_params, cr, cr_workdir,
36*4882a593Smuzhiyun                             oe_builddir, bootimg_dir, kernel_dir,
37*4882a593Smuzhiyun                             native_sysroot):
38*4882a593Smuzhiyun        """
39*4882a593Smuzhiyun        Called before do_prepare_partition(), create u-boot specific boot config
40*4882a593Smuzhiyun        """
41*4882a593Smuzhiyun        hdddir = "%s/boot.%d" % (cr_workdir, part.lineno)
42*4882a593Smuzhiyun        install_cmd = "install -d %s" % hdddir
43*4882a593Smuzhiyun        exec_cmd(install_cmd)
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun        if not kernel_dir:
46*4882a593Smuzhiyun            kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
47*4882a593Smuzhiyun            if not kernel_dir:
48*4882a593Smuzhiyun                raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun        boot_files = None
51*4882a593Smuzhiyun        for (fmt, id) in (("_uuid-%s", part.uuid), ("_label-%s", part.label), (None, None)):
52*4882a593Smuzhiyun            if fmt:
53*4882a593Smuzhiyun                var = fmt % id
54*4882a593Smuzhiyun            else:
55*4882a593Smuzhiyun                var = ""
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun            boot_files = get_bitbake_var("IMAGE_BOOT_FILES" + var)
58*4882a593Smuzhiyun            if boot_files is not None:
59*4882a593Smuzhiyun                break
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun        if boot_files is None:
62*4882a593Smuzhiyun            raise WicError('No boot files defined, IMAGE_BOOT_FILES unset for entry #%d' % part.lineno)
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun        logger.debug('Boot files: %s', boot_files)
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun        # list of tuples (src_name, dst_name)
67*4882a593Smuzhiyun        deploy_files = []
68*4882a593Smuzhiyun        for src_entry in re.findall(r'[\w;\-\./\*]+', boot_files):
69*4882a593Smuzhiyun            if ';' in src_entry:
70*4882a593Smuzhiyun                dst_entry = tuple(src_entry.split(';'))
71*4882a593Smuzhiyun                if not dst_entry[0] or not dst_entry[1]:
72*4882a593Smuzhiyun                    raise WicError('Malformed boot file entry: %s' % src_entry)
73*4882a593Smuzhiyun            else:
74*4882a593Smuzhiyun                dst_entry = (src_entry, src_entry)
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun            logger.debug('Destination entry: %r', dst_entry)
77*4882a593Smuzhiyun            deploy_files.append(dst_entry)
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun        cls.install_task = [];
80*4882a593Smuzhiyun        for deploy_entry in deploy_files:
81*4882a593Smuzhiyun            src, dst = deploy_entry
82*4882a593Smuzhiyun            if '*' in src:
83*4882a593Smuzhiyun                # by default install files under their basename
84*4882a593Smuzhiyun                entry_name_fn = os.path.basename
85*4882a593Smuzhiyun                if dst != src:
86*4882a593Smuzhiyun                    # unless a target name was given, then treat name
87*4882a593Smuzhiyun                    # as a directory and append a basename
88*4882a593Smuzhiyun                    entry_name_fn = lambda name: \
89*4882a593Smuzhiyun                                    os.path.join(dst,
90*4882a593Smuzhiyun                                                 os.path.basename(name))
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun                srcs = glob(os.path.join(kernel_dir, src))
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun                logger.debug('Globbed sources: %s', ', '.join(srcs))
95*4882a593Smuzhiyun                for entry in srcs:
96*4882a593Smuzhiyun                    src = os.path.relpath(entry, kernel_dir)
97*4882a593Smuzhiyun                    entry_dst_name = entry_name_fn(entry)
98*4882a593Smuzhiyun                    cls.install_task.append((src, entry_dst_name))
99*4882a593Smuzhiyun            else:
100*4882a593Smuzhiyun                cls.install_task.append((src, dst))
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun        if source_params.get('loader') != "u-boot":
103*4882a593Smuzhiyun            return
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun        configfile = cr.ks.bootloader.configfile
106*4882a593Smuzhiyun        custom_cfg = None
107*4882a593Smuzhiyun        if configfile:
108*4882a593Smuzhiyun            custom_cfg = get_custom_config(configfile)
109*4882a593Smuzhiyun            if custom_cfg:
110*4882a593Smuzhiyun                # Use a custom configuration for extlinux.conf
111*4882a593Smuzhiyun                extlinux_conf = custom_cfg
112*4882a593Smuzhiyun                logger.debug("Using custom configuration file "
113*4882a593Smuzhiyun                             "%s for extlinux.cfg", configfile)
114*4882a593Smuzhiyun            else:
115*4882a593Smuzhiyun                raise WicError("configfile is specified but failed to "
116*4882a593Smuzhiyun                               "get it from %s." % configfile)
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun        if not custom_cfg:
119*4882a593Smuzhiyun            # The kernel types supported by the sysboot of u-boot
120*4882a593Smuzhiyun            kernel_types = ["zImage", "Image", "fitImage", "uImage", "vmlinux"]
121*4882a593Smuzhiyun            has_dtb = False
122*4882a593Smuzhiyun            fdt_dir = '/'
123*4882a593Smuzhiyun            kernel_name = None
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun            # Find the kernel image name, from the highest precedence to lowest
126*4882a593Smuzhiyun            for image in kernel_types:
127*4882a593Smuzhiyun                for task in cls.install_task:
128*4882a593Smuzhiyun                    src, dst = task
129*4882a593Smuzhiyun                    if re.match(image, src):
130*4882a593Smuzhiyun                        kernel_name = os.path.join('/', dst)
131*4882a593Smuzhiyun                        break
132*4882a593Smuzhiyun                if kernel_name:
133*4882a593Smuzhiyun                    break
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun            for task in cls.install_task:
136*4882a593Smuzhiyun                src, dst = task
137*4882a593Smuzhiyun                # We suppose that all the dtb are in the same directory
138*4882a593Smuzhiyun                if re.search(r'\.dtb', src) and fdt_dir == '/':
139*4882a593Smuzhiyun                    has_dtb = True
140*4882a593Smuzhiyun                    fdt_dir = os.path.join(fdt_dir, os.path.dirname(dst))
141*4882a593Smuzhiyun                    break
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun            if not kernel_name:
144*4882a593Smuzhiyun                raise WicError('No kernel file found')
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun            # Compose the extlinux.conf
147*4882a593Smuzhiyun            extlinux_conf = "default Yocto\n"
148*4882a593Smuzhiyun            extlinux_conf += "label Yocto\n"
149*4882a593Smuzhiyun            extlinux_conf += "   kernel %s\n" % kernel_name
150*4882a593Smuzhiyun            if has_dtb:
151*4882a593Smuzhiyun                extlinux_conf += "   fdtdir %s\n" % fdt_dir
152*4882a593Smuzhiyun            bootloader = cr.ks.bootloader
153*4882a593Smuzhiyun            extlinux_conf += "append root=%s rootwait %s\n" \
154*4882a593Smuzhiyun                             % (cr.rootdev, bootloader.append if bootloader.append else '')
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun        install_cmd = "install -d %s/extlinux/" % hdddir
157*4882a593Smuzhiyun        exec_cmd(install_cmd)
158*4882a593Smuzhiyun        cfg = open("%s/extlinux/extlinux.conf" % hdddir, "w")
159*4882a593Smuzhiyun        cfg.write(extlinux_conf)
160*4882a593Smuzhiyun        cfg.close()
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun    @classmethod
164*4882a593Smuzhiyun    def do_prepare_partition(cls, part, source_params, cr, cr_workdir,
165*4882a593Smuzhiyun                             oe_builddir, bootimg_dir, kernel_dir,
166*4882a593Smuzhiyun                             rootfs_dir, native_sysroot):
167*4882a593Smuzhiyun        """
168*4882a593Smuzhiyun        Called to do the actual content population for a partition i.e. it
169*4882a593Smuzhiyun        'prepares' the partition to be incorporated into the image.
170*4882a593Smuzhiyun        In this case, does the following:
171*4882a593Smuzhiyun        - sets up a vfat partition
172*4882a593Smuzhiyun        - copies all files listed in IMAGE_BOOT_FILES variable
173*4882a593Smuzhiyun        """
174*4882a593Smuzhiyun        hdddir = "%s/boot.%d" % (cr_workdir, part.lineno)
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun        if not kernel_dir:
177*4882a593Smuzhiyun            kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
178*4882a593Smuzhiyun            if not kernel_dir:
179*4882a593Smuzhiyun                raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun        logger.debug('Kernel dir: %s', bootimg_dir)
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun        for task in cls.install_task:
185*4882a593Smuzhiyun            src_path, dst_path = task
186*4882a593Smuzhiyun            logger.debug('Install %s as %s', src_path, dst_path)
187*4882a593Smuzhiyun            install_cmd = "install -m 0644 -D %s %s" \
188*4882a593Smuzhiyun                          % (os.path.join(kernel_dir, src_path),
189*4882a593Smuzhiyun                             os.path.join(hdddir, dst_path))
190*4882a593Smuzhiyun            exec_cmd(install_cmd)
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun        logger.debug('Prepare boot partition using rootfs in %s', hdddir)
193*4882a593Smuzhiyun        part.prepare_rootfs(cr_workdir, oe_builddir, hdddir,
194*4882a593Smuzhiyun                            native_sysroot, False)
195