blob: 652323fa77b2247b6f39fcaa2d334469624cd905 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
2# Copyright (c) 2014, Intel Corporation.
Patrick Williamsc124f4f2015-09-15 14:41:29 -05003#
Brad Bishopc342db32019-05-15 21:57:59 -04004# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -05005#
6# DESCRIPTION
7# This implements the 'bootimg-efi' source plugin class for 'wic'
8#
9# AUTHORS
10# Tom Zanussi <tom.zanussi (at] linux.intel.com>
11#
12
Brad Bishop6e60e8b2018-02-01 10:27:11 -050013import logging
Patrick Williamsc124f4f2015-09-15 14:41:29 -050014import os
15import shutil
16
Brad Bishop6e60e8b2018-02-01 10:27:11 -050017from wic import WicError
18from wic.engine import get_custom_config
Patrick Williamsc124f4f2015-09-15 14:41:29 -050019from wic.pluginbase import SourcePlugin
Brad Bishopd7bf8c12018-02-25 22:55:05 -050020from wic.misc import (exec_cmd, exec_native_cmd,
21 get_bitbake_var, BOOTDD_EXTRA_SPACE)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050022
23logger = logging.getLogger('wic')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050024
25class BootimgEFIPlugin(SourcePlugin):
26 """
27 Create EFI boot partition.
Brad Bishop6e60e8b2018-02-01 10:27:11 -050028 This plugin supports GRUB 2 and systemd-boot bootloaders.
Patrick Williamsc124f4f2015-09-15 14:41:29 -050029 """
30
31 name = 'bootimg-efi'
32
33 @classmethod
Brad Bishopd5ae7d92018-06-14 09:52:03 -070034 def do_configure_grubefi(cls, hdddir, creator, cr_workdir, source_params):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050035 """
36 Create loader-specific (grub-efi) config
37 """
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050038 configfile = creator.ks.bootloader.configfile
39 custom_cfg = None
40 if configfile:
41 custom_cfg = get_custom_config(configfile)
42 if custom_cfg:
43 # Use a custom configuration for grub
44 grubefi_conf = custom_cfg
Brad Bishop6e60e8b2018-02-01 10:27:11 -050045 logger.debug("Using custom configuration file "
46 "%s for grub.cfg", configfile)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050047 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050048 raise WicError("configfile is specified but failed to "
49 "get it from %s." % configfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050050
Brad Bishopd5ae7d92018-06-14 09:52:03 -070051 initrd = source_params.get('initrd')
52
53 if initrd:
54 bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
55 if not bootimg_dir:
56 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
57
58 cp_cmd = "cp %s/%s %s" % (bootimg_dir, initrd, hdddir)
59 exec_cmd(cp_cmd, True)
60 else:
61 logger.debug("Ignoring missing initrd")
62
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050063 if not custom_cfg:
64 # Create grub configuration using parameters from wks file
65 bootloader = creator.ks.bootloader
Brad Bishop19323692019-04-05 15:28:33 -040066 title = source_params.get('title')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050067
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050068 grubefi_conf = ""
69 grubefi_conf += "serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1\n"
70 grubefi_conf += "default=boot\n"
71 grubefi_conf += "timeout=%s\n" % bootloader.timeout
Brad Bishop19323692019-04-05 15:28:33 -040072 grubefi_conf += "menuentry '%s'{\n" % (title if title else "boot")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050073
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050074 kernel = "/bzImage"
75
76 grubefi_conf += "linux %s root=%s rootwait %s\n" \
77 % (kernel, creator.rootdev, bootloader.append)
Brad Bishopd5ae7d92018-06-14 09:52:03 -070078
79 if initrd:
80 grubefi_conf += "initrd /%s\n" % initrd
81
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050082 grubefi_conf += "}\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050083
Brad Bishop6e60e8b2018-02-01 10:27:11 -050084 logger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg",
85 cr_workdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050086 cfg = open("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir, "w")
87 cfg.write(grubefi_conf)
88 cfg.close()
89
90 @classmethod
Brad Bishop6e60e8b2018-02-01 10:27:11 -050091 def do_configure_systemdboot(cls, hdddir, creator, cr_workdir, source_params):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050092 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -060093 Create loader-specific systemd-boot/gummiboot config
Patrick Williamsc124f4f2015-09-15 14:41:29 -050094 """
95 install_cmd = "install -d %s/loader" % hdddir
96 exec_cmd(install_cmd)
97
98 install_cmd = "install -d %s/loader/entries" % hdddir
99 exec_cmd(install_cmd)
100
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500101 bootloader = creator.ks.bootloader
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500102
103 loader_conf = ""
104 loader_conf += "default boot\n"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500105 loader_conf += "timeout %d\n" % bootloader.timeout
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500106
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500107 initrd = source_params.get('initrd')
108
109 if initrd:
110 # obviously we need to have a common common deploy var
111 bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
112 if not bootimg_dir:
113 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
114
115 cp_cmd = "cp %s/%s %s" % (bootimg_dir, initrd, hdddir)
116 exec_cmd(cp_cmd, True)
117 else:
118 logger.debug("Ignoring missing initrd")
119
120 logger.debug("Writing systemd-boot config "
121 "%s/hdd/boot/loader/loader.conf", cr_workdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500122 cfg = open("%s/hdd/boot/loader/loader.conf" % cr_workdir, "w")
123 cfg.write(loader_conf)
124 cfg.close()
125
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500126 configfile = creator.ks.bootloader.configfile
127 custom_cfg = None
128 if configfile:
129 custom_cfg = get_custom_config(configfile)
130 if custom_cfg:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500131 # Use a custom configuration for systemd-boot
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500132 boot_conf = custom_cfg
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500133 logger.debug("Using custom configuration file "
134 "%s for systemd-boots's boot.conf", configfile)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500135 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500136 raise WicError("configfile is specified but failed to "
137 "get it from %s.", configfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500138
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500139 if not custom_cfg:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500140 # Create systemd-boot configuration using parameters from wks file
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500141 kernel = "/bzImage"
Brad Bishop19323692019-04-05 15:28:33 -0400142 title = source_params.get('title')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500143
144 boot_conf = ""
Brad Bishop19323692019-04-05 15:28:33 -0400145 boot_conf += "title %s\n" % (title if title else "boot")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500146 boot_conf += "linux %s\n" % kernel
147 boot_conf += "options LABEL=Boot root=%s %s\n" % \
148 (creator.rootdev, bootloader.append)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500149
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500150 if initrd:
151 boot_conf += "initrd /%s\n" % initrd
152
153 logger.debug("Writing systemd-boot config "
154 "%s/hdd/boot/loader/entries/boot.conf", cr_workdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500155 cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w")
156 cfg.write(boot_conf)
157 cfg.close()
158
159
160 @classmethod
161 def do_configure_partition(cls, part, source_params, creator, cr_workdir,
162 oe_builddir, bootimg_dir, kernel_dir,
163 native_sysroot):
164 """
165 Called before do_prepare_partition(), creates loader-specific config
166 """
167 hdddir = "%s/hdd/boot" % cr_workdir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500168
169 install_cmd = "install -d %s/EFI/BOOT" % hdddir
170 exec_cmd(install_cmd)
171
172 try:
173 if source_params['loader'] == 'grub-efi':
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700174 cls.do_configure_grubefi(hdddir, creator, cr_workdir, source_params)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500175 elif source_params['loader'] == 'systemd-boot':
176 cls.do_configure_systemdboot(hdddir, creator, cr_workdir, source_params)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500177 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500178 raise WicError("unrecognized bootimg-efi loader: %s" % source_params['loader'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500179 except KeyError:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500180 raise WicError("bootimg-efi requires a loader, none specified")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500181
182
183 @classmethod
184 def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
185 oe_builddir, bootimg_dir, kernel_dir,
186 rootfs_dir, native_sysroot):
187 """
188 Called to do the actual content population for a partition i.e. it
189 'prepares' the partition to be incorporated into the image.
190 In this case, prepare content for an EFI (grub) boot partition.
191 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500192 if not kernel_dir:
193 kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
194 if not kernel_dir:
195 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500196
197 staging_kernel_dir = kernel_dir
198
199 hdddir = "%s/hdd/boot" % cr_workdir
200
201 install_cmd = "install -m 0644 %s/bzImage %s/bzImage" % \
202 (staging_kernel_dir, hdddir)
203 exec_cmd(install_cmd)
204
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500205
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500206 try:
207 if source_params['loader'] == 'grub-efi':
208 shutil.copyfile("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir,
209 "%s/grub.cfg" % cr_workdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500210 for mod in [x for x in os.listdir(kernel_dir) if x.startswith("grub-efi-")]:
211 cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[9:])
212 exec_cmd(cp_cmd, True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500213 shutil.move("%s/grub.cfg" % cr_workdir,
214 "%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500215 elif source_params['loader'] == 'systemd-boot':
216 for mod in [x for x in os.listdir(kernel_dir) if x.startswith("systemd-")]:
217 cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[8:])
218 exec_cmd(cp_cmd, True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500219 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500220 raise WicError("unrecognized bootimg-efi loader: %s" %
221 source_params['loader'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500222 except KeyError:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500223 raise WicError("bootimg-efi requires a loader, none specified")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500224
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500225 startup = os.path.join(kernel_dir, "startup.nsh")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600226 if os.path.exists(startup):
227 cp_cmd = "cp %s %s/" % (startup, hdddir)
228 exec_cmd(cp_cmd, True)
229
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500230 du_cmd = "du -bks %s" % hdddir
231 out = exec_cmd(du_cmd)
232 blocks = int(out.split()[0])
233
234 extra_blocks = part.get_extra_block_count(blocks)
235
236 if extra_blocks < BOOTDD_EXTRA_SPACE:
237 extra_blocks = BOOTDD_EXTRA_SPACE
238
239 blocks += extra_blocks
240
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500241 logger.debug("Added %d extra blocks to %s to get to %d total blocks",
242 extra_blocks, part.mountpoint, blocks)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500243
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500244 # dosfs image, created by mkdosfs
245 bootimg = "%s/boot.img" % cr_workdir
246
Brad Bishopc342db32019-05-15 21:57:59 -0400247 label = part.label if part.label else "ESP"
248
249 dosfs_cmd = "mkdosfs -n %s -i %s -C %s %d" % \
250 (label, part.fsuuid, bootimg, blocks)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500251 exec_native_cmd(dosfs_cmd, native_sysroot)
252
253 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
254 exec_native_cmd(mcopy_cmd, native_sysroot)
255
256 chmod_cmd = "chmod 644 %s" % bootimg
257 exec_cmd(chmod_cmd)
258
259 du_cmd = "du -Lbks %s" % bootimg
260 out = exec_cmd(du_cmd)
261 bootimg_size = out.split()[0]
262
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500263 part.size = int(bootimg_size)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500264 part.source_file = bootimg