blob: 4adb80becc11a6d30ffeae64ff87ebeb959dde86 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3#
4# Copyright (c) 2014, Intel Corporation.
5# All rights reserved.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 2 as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20# DESCRIPTION
21# This implements the 'bootimg-efi' source plugin class for 'wic'
22#
23# AUTHORS
24# Tom Zanussi <tom.zanussi (at] linux.intel.com>
25#
26
27import os
28import shutil
29
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050030from wic import msger
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031from wic.pluginbase import SourcePlugin
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050032from wic.utils.misc import get_custom_config
Patrick Williamsc124f4f2015-09-15 14:41:29 -050033from wic.utils.oe.misc import exec_cmd, exec_native_cmd, get_bitbake_var, \
34 BOOTDD_EXTRA_SPACE
35
36class BootimgEFIPlugin(SourcePlugin):
37 """
38 Create EFI boot partition.
39 This plugin supports GRUB 2 and gummiboot bootloaders.
40 """
41
42 name = 'bootimg-efi'
43
44 @classmethod
45 def do_configure_grubefi(cls, hdddir, creator, cr_workdir):
46 """
47 Create loader-specific (grub-efi) config
48 """
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050049 configfile = creator.ks.bootloader.configfile
50 custom_cfg = None
51 if configfile:
52 custom_cfg = get_custom_config(configfile)
53 if custom_cfg:
54 # Use a custom configuration for grub
55 grubefi_conf = custom_cfg
56 msger.debug("Using custom configuration file "
57 "%s for grub.cfg" % configfile)
58 else:
59 msger.error("configfile is specified but failed to "
60 "get it from %s." % configfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050061
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050062 if not custom_cfg:
63 # Create grub configuration using parameters from wks file
64 bootloader = creator.ks.bootloader
Patrick Williamsc124f4f2015-09-15 14:41:29 -050065
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050066 grubefi_conf = ""
67 grubefi_conf += "serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1\n"
68 grubefi_conf += "default=boot\n"
69 grubefi_conf += "timeout=%s\n" % bootloader.timeout
70 grubefi_conf += "menuentry 'boot'{\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050071
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050072 kernel = "/bzImage"
73
74 grubefi_conf += "linux %s root=%s rootwait %s\n" \
75 % (kernel, creator.rootdev, bootloader.append)
76 grubefi_conf += "}\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050077
78 msger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg" \
79 % cr_workdir)
80 cfg = open("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir, "w")
81 cfg.write(grubefi_conf)
82 cfg.close()
83
84 @classmethod
85 def do_configure_gummiboot(cls, hdddir, creator, cr_workdir):
86 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -060087 Create loader-specific systemd-boot/gummiboot config
Patrick Williamsc124f4f2015-09-15 14:41:29 -050088 """
89 install_cmd = "install -d %s/loader" % hdddir
90 exec_cmd(install_cmd)
91
92 install_cmd = "install -d %s/loader/entries" % hdddir
93 exec_cmd(install_cmd)
94
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050095 bootloader = creator.ks.bootloader
Patrick Williamsc124f4f2015-09-15 14:41:29 -050096
97 loader_conf = ""
98 loader_conf += "default boot\n"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050099 loader_conf += "timeout %d\n" % bootloader.timeout
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500100
101 msger.debug("Writing gummiboot config %s/hdd/boot/loader/loader.conf" \
102 % cr_workdir)
103 cfg = open("%s/hdd/boot/loader/loader.conf" % cr_workdir, "w")
104 cfg.write(loader_conf)
105 cfg.close()
106
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500107 configfile = creator.ks.bootloader.configfile
108 custom_cfg = None
109 if configfile:
110 custom_cfg = get_custom_config(configfile)
111 if custom_cfg:
112 # Use a custom configuration for gummiboot
113 boot_conf = custom_cfg
114 msger.debug("Using custom configuration file "
115 "%s for gummiboots's boot.conf" % configfile)
116 else:
117 msger.error("configfile is specified but failed to "
118 "get it from %s." % configfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500119
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500120 if not custom_cfg:
121 # Create gummiboot configuration using parameters from wks file
122 kernel = "/bzImage"
123
124 boot_conf = ""
125 boot_conf += "title boot\n"
126 boot_conf += "linux %s\n" % kernel
127 boot_conf += "options LABEL=Boot root=%s %s\n" % \
128 (creator.rootdev, bootloader.append)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500129
130 msger.debug("Writing gummiboot config %s/hdd/boot/loader/entries/boot.conf" \
131 % cr_workdir)
132 cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w")
133 cfg.write(boot_conf)
134 cfg.close()
135
136
137 @classmethod
138 def do_configure_partition(cls, part, source_params, creator, cr_workdir,
139 oe_builddir, bootimg_dir, kernel_dir,
140 native_sysroot):
141 """
142 Called before do_prepare_partition(), creates loader-specific config
143 """
144 hdddir = "%s/hdd/boot" % cr_workdir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500145
146 install_cmd = "install -d %s/EFI/BOOT" % hdddir
147 exec_cmd(install_cmd)
148
149 try:
150 if source_params['loader'] == 'grub-efi':
151 cls.do_configure_grubefi(hdddir, creator, cr_workdir)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600152 elif source_params['loader'] == 'gummiboot' \
153 or source_params['loader'] == 'systemd-boot':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500154 cls.do_configure_gummiboot(hdddir, creator, cr_workdir)
155 else:
156 msger.error("unrecognized bootimg-efi loader: %s" % source_params['loader'])
157 except KeyError:
158 msger.error("bootimg-efi requires a loader, none specified")
159
160
161 @classmethod
162 def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
163 oe_builddir, bootimg_dir, kernel_dir,
164 rootfs_dir, native_sysroot):
165 """
166 Called to do the actual content population for a partition i.e. it
167 'prepares' the partition to be incorporated into the image.
168 In this case, prepare content for an EFI (grub) boot partition.
169 """
170 if not bootimg_dir:
171 bootimg_dir = get_bitbake_var("HDDDIR")
172 if not bootimg_dir:
173 msger.error("Couldn't find HDDDIR, exiting\n")
174 # just so the result notes display it
175 creator.set_bootimg_dir(bootimg_dir)
176
177 staging_kernel_dir = kernel_dir
178
179 hdddir = "%s/hdd/boot" % cr_workdir
180
181 install_cmd = "install -m 0644 %s/bzImage %s/bzImage" % \
182 (staging_kernel_dir, hdddir)
183 exec_cmd(install_cmd)
184
185 try:
186 if source_params['loader'] == 'grub-efi':
187 shutil.copyfile("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir,
188 "%s/grub.cfg" % cr_workdir)
189 cp_cmd = "cp %s/EFI/BOOT/* %s/EFI/BOOT" % (bootimg_dir, hdddir)
190 exec_cmd(cp_cmd, True)
191 shutil.move("%s/grub.cfg" % cr_workdir,
192 "%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600193 elif source_params['loader'] == 'gummiboot' \
194 or source_params['loader'] == 'systemd-boot':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500195 cp_cmd = "cp %s/EFI/BOOT/* %s/EFI/BOOT" % (bootimg_dir, hdddir)
196 exec_cmd(cp_cmd, True)
197 else:
198 msger.error("unrecognized bootimg-efi loader: %s" % source_params['loader'])
199 except KeyError:
200 msger.error("bootimg-efi requires a loader, none specified")
201
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600202 startup = os.path.join(bootimg_dir, "startup.nsh")
203 if os.path.exists(startup):
204 cp_cmd = "cp %s %s/" % (startup, hdddir)
205 exec_cmd(cp_cmd, True)
206
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500207 du_cmd = "du -bks %s" % hdddir
208 out = exec_cmd(du_cmd)
209 blocks = int(out.split()[0])
210
211 extra_blocks = part.get_extra_block_count(blocks)
212
213 if extra_blocks < BOOTDD_EXTRA_SPACE:
214 extra_blocks = BOOTDD_EXTRA_SPACE
215
216 blocks += extra_blocks
217
218 msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \
219 (extra_blocks, part.mountpoint, blocks))
220
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500221 # dosfs image, created by mkdosfs
222 bootimg = "%s/boot.img" % cr_workdir
223
224 dosfs_cmd = "mkdosfs -n efi -C %s %d" % (bootimg, blocks)
225 exec_native_cmd(dosfs_cmd, native_sysroot)
226
227 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
228 exec_native_cmd(mcopy_cmd, native_sysroot)
229
230 chmod_cmd = "chmod 644 %s" % bootimg
231 exec_cmd(chmod_cmd)
232
233 du_cmd = "du -Lbks %s" % bootimg
234 out = exec_cmd(du_cmd)
235 bootimg_size = out.split()[0]
236
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500237 part.size = int(bootimg_size)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500238 part.source_file = bootimg