diff options
author | Adrian Calianu <adrian.calianu@enea.com> | 2018-03-13 09:22:57 +0100 |
---|---|---|
committer | Adrian Dudau <adrian.dudau@enea.com> | 2018-03-21 11:20:43 +0100 |
commit | 67ea7dff95f14e603916b53e2dee6359bbf9529b (patch) | |
tree | 304522325ec3c50690fba51b68aab9f0d5a20e53 | |
parent | 0f8054fac4d121594476941307794d0b0b50bd89 (diff) | |
download | meta-el-nfv-access-67ea7dff95f14e603916b53e2dee6359bbf9529b.tar.gz |
qemuarm64: generate one self contained image
that can be booted from qemu like a HDD image.
Building enea-nfv-access-vnf image on aarch64 will result in a
qcow2 image (ready to be booted on a UEFI bootloader) containing
two partitions:
sda1: ESP/FAT32
- grub-efi
- startup.nsh
sda2: ext4
- rootfs
Comparing to qemux86-64 on qemuarm64 must be selected the BIOS:
qemu-system-aarch64 -pflash flash0.img -pflash flash1.img -hda
enea-nfv-access-vnf.qcow2
To generate such a image wic was used. Since wic is using some
hardcoded values specific to x86 (like kernel name) it was decided
for now to create and store locally wic specific modification for arm64.
Currently is no support to build EDKII/UEFI bootloader for aarch64.
It must be built or downloaded from Linaro.
Signed-off-by: Adrian Calianu <adrian.calianu@enea.com>
Signed-off-by: Adrian Dudau <adrian.dudau@enea.com>
-rw-r--r-- | classes/enea-qcow2.bbclass | 7 | ||||
-rw-r--r-- | images/enea-nfv-access-vnf.bb | 11 | ||||
-rw-r--r-- | scripts/lib/wic/canned-wks/enea-systemd-bootdisk-efi.wks | 9 | ||||
-rw-r--r-- | scripts/lib/wic/plugins/source/enea-bootimg-efi.py | 261 |
4 files changed, 283 insertions, 5 deletions
diff --git a/classes/enea-qcow2.bbclass b/classes/enea-qcow2.bbclass new file mode 100644 index 0000000..b086069 --- /dev/null +++ b/classes/enea-qcow2.bbclass | |||
@@ -0,0 +1,7 @@ | |||
1 | IMAGE_TYPES += "wic wic.qcow2" | ||
2 | CONVERSIONTYPES += "qcow2" | ||
3 | CONVERSION_DEPENDS_qcow2 = "qemu-native" | ||
4 | CONVERSION_CMD_qcow2 = "qemu-img convert -O qcow2 ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.${type} ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.qcow2" | ||
5 | |||
6 | IMAGE_FSTYPES += "wic wic.qcow2" | ||
7 | WKS_FILE = "enea-systemd-bootdisk-efi.wks" | ||
diff --git a/images/enea-nfv-access-vnf.bb b/images/enea-nfv-access-vnf.bb index fdf7083..d5da06b 100644 --- a/images/enea-nfv-access-vnf.bb +++ b/images/enea-nfv-access-vnf.bb | |||
@@ -3,12 +3,13 @@ DESCRIPTION = "VNF image of the Enea NFV Access Platform, includes kernel, rootf | |||
3 | require images/enea-nfv-access-common.inc | 3 | require images/enea-nfv-access-common.inc |
4 | 4 | ||
5 | # Enea VNF boot configuration | 5 | # Enea VNF boot configuration |
6 | ROOT_VM = "root=/dev/vda2" | 6 | # image-vm is supported only for x86-64 , for all other arch use enea-qcow2 class |
7 | APPEND = "console=ttyS0,115200 hugepagesz=2M hugepages=512 isolcpus=1 nohz_full=1 rcu_nocbs=1 audit=0 quiet" | 7 | ROOT_VM_x86-64 = "root=/dev/vda2" |
8 | SYSLINUX_TIMEOUT = "30" | 8 | APPEND_x86-64 = "console=ttyS0,115200 hugepagesz=2M hugepages=512 isolcpus=1 nohz_full=1 rcu_nocbs=1 audit=0 quiet" |
9 | SYSLINUX_TIMEOUT_x86-64 = "30" | ||
9 | 10 | ||
10 | inherit image-vm | 11 | inherit ${@'image-vm' if "${TUNE_ARCH}" == "x86_64" else 'enea-qcow2'} |
11 | IMAGE_FSTYPES += "qcow2" | 12 | IMAGE_FSTYPES_x86-64 += "qcow2" |
12 | 13 | ||
13 | CLOUDINITPKGS = "cloud-init util-linux-blkid" | 14 | CLOUDINITPKGS = "cloud-init util-linux-blkid" |
14 | CLOUDINITPKGS += " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'cloud-init-systemd', '', d)}" | 15 | CLOUDINITPKGS += " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'cloud-init-systemd', '', d)}" |
diff --git a/scripts/lib/wic/canned-wks/enea-systemd-bootdisk-efi.wks b/scripts/lib/wic/canned-wks/enea-systemd-bootdisk-efi.wks new file mode 100644 index 0000000..a9af3b3 --- /dev/null +++ b/scripts/lib/wic/canned-wks/enea-systemd-bootdisk-efi.wks | |||
@@ -0,0 +1,9 @@ | |||
1 | # short-description: Create an EFI disk image with grub-efi | ||
2 | # long-description: Creates a partitioned EFI disk image that the user | ||
3 | # can directly dd to boot media. The selected bootloader is grub-efi. | ||
4 | |||
5 | part /boot --source enea-bootimg-efi --sourceparams="loader=grub-efi" --ondisk vda --fstype=vfat --label EFI --active --align 1024 | ||
6 | |||
7 | part / --source rootfs --ondisk vda --fstype=ext4 --label platform --align 1024 | ||
8 | |||
9 | bootloader --ptable gpt --timeout=10 --append="rootfstype=ext4 console=ttyAMA0,115200 console=tty0 coherent_pool=16M" | ||
diff --git a/scripts/lib/wic/plugins/source/enea-bootimg-efi.py b/scripts/lib/wic/plugins/source/enea-bootimg-efi.py new file mode 100644 index 0000000..1cf8c97 --- /dev/null +++ b/scripts/lib/wic/plugins/source/enea-bootimg-efi.py | |||
@@ -0,0 +1,261 @@ | |||
1 | # 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 'enea-bootimg-efi' source plugin class for 'wic' | ||
22 | # This is a copy of bootimg-efi source plugin. Following changes has been made: | ||
23 | # - renamed plugin to "enea-bootimg-efi" | ||
24 | # - rename bzImage with Image - on ARM we have only Image | ||
25 | # | ||
26 | # AUTHORS | ||
27 | # Tom Zanussi <tom.zanussi (at] linux.intel.com> | ||
28 | # Adrian Calianu <adrian.calianu (at] enea.com> | ||
29 | # | ||
30 | |||
31 | import logging | ||
32 | import os | ||
33 | import shutil | ||
34 | |||
35 | from wic import WicError | ||
36 | from wic.engine import get_custom_config | ||
37 | from wic.pluginbase import SourcePlugin | ||
38 | from wic.utils.misc import (exec_cmd, exec_native_cmd, get_bitbake_var, | ||
39 | BOOTDD_EXTRA_SPACE) | ||
40 | |||
41 | logger = logging.getLogger('wic') | ||
42 | |||
43 | class EneaBootimgEFIPlugin(SourcePlugin): | ||
44 | """ | ||
45 | Create EFI boot partition. | ||
46 | This plugin supports GRUB 2 and systemd-boot bootloaders. | ||
47 | """ | ||
48 | |||
49 | name = 'enea-bootimg-efi' | ||
50 | |||
51 | @classmethod | ||
52 | def do_configure_grubefi(cls, creator, cr_workdir): | ||
53 | """ | ||
54 | Create loader-specific (grub-efi) config | ||
55 | """ | ||
56 | configfile = creator.ks.bootloader.configfile | ||
57 | custom_cfg = None | ||
58 | if configfile: | ||
59 | custom_cfg = get_custom_config(configfile) | ||
60 | if custom_cfg: | ||
61 | # Use a custom configuration for grub | ||
62 | grubefi_conf = custom_cfg | ||
63 | logger.debug("Using custom configuration file " | ||
64 | "%s for grub.cfg", configfile) | ||
65 | else: | ||
66 | raise WicError("configfile is specified but failed to " | ||
67 | "get it from %s." % configfile) | ||
68 | |||
69 | if not custom_cfg: | ||
70 | # Create grub configuration using parameters from wks file | ||
71 | bootloader = creator.ks.bootloader | ||
72 | |||
73 | grubefi_conf = "" | ||
74 | grubefi_conf += "serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1\n" | ||
75 | grubefi_conf += "default=boot\n" | ||
76 | grubefi_conf += "timeout=%s\n" % bootloader.timeout | ||
77 | grubefi_conf += "menuentry 'boot'{\n" | ||
78 | |||
79 | kernel = "/Image" | ||
80 | |||
81 | grubefi_conf += "linux %s root=%s rootwait %s\n" \ | ||
82 | % (kernel, creator.rootdev, bootloader.append) | ||
83 | grubefi_conf += "}\n" | ||
84 | |||
85 | logger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg", | ||
86 | cr_workdir) | ||
87 | cfg = open("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir, "w") | ||
88 | cfg.write(grubefi_conf) | ||
89 | cfg.close() | ||
90 | |||
91 | @classmethod | ||
92 | def do_configure_systemdboot(cls, hdddir, creator, cr_workdir, source_params): | ||
93 | """ | ||
94 | Create loader-specific systemd-boot/gummiboot config | ||
95 | """ | ||
96 | install_cmd = "install -d %s/loader" % hdddir | ||
97 | exec_cmd(install_cmd) | ||
98 | |||
99 | install_cmd = "install -d %s/loader/entries" % hdddir | ||
100 | exec_cmd(install_cmd) | ||
101 | |||
102 | bootloader = creator.ks.bootloader | ||
103 | |||
104 | loader_conf = "" | ||
105 | loader_conf += "default boot\n" | ||
106 | loader_conf += "timeout %d\n" % bootloader.timeout | ||
107 | |||
108 | initrd = source_params.get('initrd') | ||
109 | |||
110 | if initrd: | ||
111 | # obviously we need to have a common common deploy var | ||
112 | bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") | ||
113 | if not bootimg_dir: | ||
114 | raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") | ||
115 | |||
116 | cp_cmd = "cp %s/%s %s" % (bootimg_dir, initrd, hdddir) | ||
117 | exec_cmd(cp_cmd, True) | ||
118 | else: | ||
119 | logger.debug("Ignoring missing initrd") | ||
120 | |||
121 | logger.debug("Writing systemd-boot config " | ||
122 | "%s/hdd/boot/loader/loader.conf", cr_workdir) | ||
123 | cfg = open("%s/hdd/boot/loader/loader.conf" % cr_workdir, "w") | ||
124 | cfg.write(loader_conf) | ||
125 | cfg.close() | ||
126 | |||
127 | configfile = creator.ks.bootloader.configfile | ||
128 | custom_cfg = None | ||
129 | if configfile: | ||
130 | custom_cfg = get_custom_config(configfile) | ||
131 | if custom_cfg: | ||
132 | # Use a custom configuration for systemd-boot | ||
133 | boot_conf = custom_cfg | ||
134 | logger.debug("Using custom configuration file " | ||
135 | "%s for systemd-boots's boot.conf", configfile) | ||
136 | else: | ||
137 | raise WicError("configfile is specified but failed to " | ||
138 | "get it from %s.", configfile) | ||
139 | |||
140 | if not custom_cfg: | ||
141 | # Create systemd-boot configuration using parameters from wks file | ||
142 | kernel = "/Image" | ||
143 | |||
144 | boot_conf = "" | ||
145 | boot_conf += "title boot\n" | ||
146 | boot_conf += "linux %s\n" % kernel | ||
147 | boot_conf += "options LABEL=Boot root=%s %s\n" % \ | ||
148 | (creator.rootdev, bootloader.append) | ||
149 | |||
150 | 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) | ||
155 | 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 | ||
168 | |||
169 | install_cmd = "install -d %s/EFI/BOOT" % hdddir | ||
170 | exec_cmd(install_cmd) | ||
171 | |||
172 | try: | ||
173 | if source_params['loader'] == 'grub-efi': | ||
174 | cls.do_configure_grubefi(creator, cr_workdir) | ||
175 | elif source_params['loader'] == 'systemd-boot': | ||
176 | cls.do_configure_systemdboot(hdddir, creator, cr_workdir, source_params) | ||
177 | else: | ||
178 | raise WicError("unrecognized bootimg-efi loader: %s" % source_params['loader']) | ||
179 | except KeyError: | ||
180 | raise WicError("bootimg-efi requires a loader, none specified") | ||
181 | |||
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 | """ | ||
192 | 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") | ||
196 | |||
197 | staging_kernel_dir = kernel_dir | ||
198 | |||
199 | hdddir = "%s/hdd/boot" % cr_workdir | ||
200 | |||
201 | install_cmd = "install -m 0644 %s/Image %s/Image" % \ | ||
202 | (staging_kernel_dir, hdddir) | ||
203 | exec_cmd(install_cmd) | ||
204 | |||
205 | |||
206 | 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) | ||
210 | 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) | ||
213 | shutil.move("%s/grub.cfg" % cr_workdir, | ||
214 | "%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir) | ||
215 | 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) | ||
219 | else: | ||
220 | raise WicError("unrecognized bootimg-efi loader: %s" % | ||
221 | source_params['loader']) | ||
222 | except KeyError: | ||
223 | raise WicError("bootimg-efi requires a loader, none specified") | ||
224 | |||
225 | startup = os.path.join(kernel_dir, "startup.nsh") | ||
226 | if os.path.exists(startup): | ||
227 | cp_cmd = "cp %s %s/" % (startup, hdddir) | ||
228 | exec_cmd(cp_cmd, True) | ||
229 | |||
230 | 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 | |||
241 | logger.debug("Added %d extra blocks to %s to get to %d total blocks", | ||
242 | extra_blocks, part.mountpoint, blocks) | ||
243 | |||
244 | # dosfs image, created by mkdosfs | ||
245 | bootimg = "%s/boot.img" % cr_workdir | ||
246 | |||
247 | dosfs_cmd = "mkdosfs -n efi -C %s %d" % (bootimg, blocks) | ||
248 | exec_native_cmd(dosfs_cmd, native_sysroot) | ||
249 | |||
250 | mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir) | ||
251 | exec_native_cmd(mcopy_cmd, native_sysroot) | ||
252 | |||
253 | chmod_cmd = "chmod 644 %s" % bootimg | ||
254 | exec_cmd(chmod_cmd) | ||
255 | |||
256 | du_cmd = "du -Lbks %s" % bootimg | ||
257 | out = exec_cmd(du_cmd) | ||
258 | bootimg_size = out.split()[0] | ||
259 | |||
260 | part.size = int(bootimg_size) | ||
261 | part.source_file = bootimg | ||