summaryrefslogtreecommitdiffstats
path: root/scripts/lib/wic/plugins/source/bootimg-efi.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib/wic/plugins/source/bootimg-efi.py')
-rw-r--r--scripts/lib/wic/plugins/source/bootimg-efi.py211
1 files changed, 179 insertions, 32 deletions
diff --git a/scripts/lib/wic/plugins/source/bootimg-efi.py b/scripts/lib/wic/plugins/source/bootimg-efi.py
index cdc72543c2..13a9cddf4e 100644
--- a/scripts/lib/wic/plugins/source/bootimg-efi.py
+++ b/scripts/lib/wic/plugins/source/bootimg-efi.py
@@ -12,6 +12,7 @@
12 12
13import logging 13import logging
14import os 14import os
15import tempfile
15import shutil 16import shutil
16import re 17import re
17 18
@@ -34,6 +35,26 @@ class BootimgEFIPlugin(SourcePlugin):
34 name = 'bootimg-efi' 35 name = 'bootimg-efi'
35 36
36 @classmethod 37 @classmethod
38 def _copy_additional_files(cls, hdddir, initrd, dtb):
39 bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
40 if not bootimg_dir:
41 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
42
43 if initrd:
44 initrds = initrd.split(';')
45 for rd in initrds:
46 cp_cmd = "cp %s/%s %s" % (bootimg_dir, rd, hdddir)
47 exec_cmd(cp_cmd, True)
48 else:
49 logger.debug("Ignoring missing initrd")
50
51 if dtb:
52 if ';' in dtb:
53 raise WicError("Only one DTB supported, exiting")
54 cp_cmd = "cp %s/%s %s" % (bootimg_dir, dtb, hdddir)
55 exec_cmd(cp_cmd, True)
56
57 @classmethod
37 def do_configure_grubefi(cls, hdddir, creator, cr_workdir, source_params): 58 def do_configure_grubefi(cls, hdddir, creator, cr_workdir, source_params):
38 """ 59 """
39 Create loader-specific (grub-efi) config 60 Create loader-specific (grub-efi) config
@@ -52,18 +73,9 @@ class BootimgEFIPlugin(SourcePlugin):
52 "get it from %s." % configfile) 73 "get it from %s." % configfile)
53 74
54 initrd = source_params.get('initrd') 75 initrd = source_params.get('initrd')
76 dtb = source_params.get('dtb')
55 77
56 if initrd: 78 cls._copy_additional_files(hdddir, initrd, dtb)
57 bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
58 if not bootimg_dir:
59 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
60
61 initrds = initrd.split(';')
62 for rd in initrds:
63 cp_cmd = "cp %s/%s %s" % (bootimg_dir, rd, hdddir)
64 exec_cmd(cp_cmd, True)
65 else:
66 logger.debug("Ignoring missing initrd")
67 79
68 if not custom_cfg: 80 if not custom_cfg:
69 # Create grub configuration using parameters from wks file 81 # Create grub configuration using parameters from wks file
@@ -97,6 +109,9 @@ class BootimgEFIPlugin(SourcePlugin):
97 grubefi_conf += " /%s" % rd 109 grubefi_conf += " /%s" % rd
98 grubefi_conf += "\n" 110 grubefi_conf += "\n"
99 111
112 if dtb:
113 grubefi_conf += "devicetree /%s\n" % dtb
114
100 grubefi_conf += "}\n" 115 grubefi_conf += "}\n"
101 116
102 logger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg", 117 logger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg",
@@ -118,24 +133,18 @@ class BootimgEFIPlugin(SourcePlugin):
118 133
119 bootloader = creator.ks.bootloader 134 bootloader = creator.ks.bootloader
120 135
136 unified_image = source_params.get('create-unified-kernel-image') == "true"
137
121 loader_conf = "" 138 loader_conf = ""
122 loader_conf += "default boot\n" 139 if not unified_image:
140 loader_conf += "default boot\n"
123 loader_conf += "timeout %d\n" % bootloader.timeout 141 loader_conf += "timeout %d\n" % bootloader.timeout
124 142
125 initrd = source_params.get('initrd') 143 initrd = source_params.get('initrd')
144 dtb = source_params.get('dtb')
126 145
127 if initrd: 146 if not unified_image:
128 # obviously we need to have a common common deploy var 147 cls._copy_additional_files(hdddir, initrd, dtb)
129 bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
130 if not bootimg_dir:
131 raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")
132
133 initrds = initrd.split(';')
134 for rd in initrds:
135 cp_cmd = "cp %s/%s %s" % (bootimg_dir, rd, hdddir)
136 exec_cmd(cp_cmd, True)
137 else:
138 logger.debug("Ignoring missing initrd")
139 148
140 logger.debug("Writing systemd-boot config " 149 logger.debug("Writing systemd-boot config "
141 "%s/hdd/boot/loader/loader.conf", cr_workdir) 150 "%s/hdd/boot/loader/loader.conf", cr_workdir)
@@ -183,11 +192,15 @@ class BootimgEFIPlugin(SourcePlugin):
183 for rd in initrds: 192 for rd in initrds:
184 boot_conf += "initrd /%s\n" % rd 193 boot_conf += "initrd /%s\n" % rd
185 194
186 logger.debug("Writing systemd-boot config " 195 if dtb:
187 "%s/hdd/boot/loader/entries/boot.conf", cr_workdir) 196 boot_conf += "devicetree /%s\n" % dtb
188 cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w") 197
189 cfg.write(boot_conf) 198 if not unified_image:
190 cfg.close() 199 logger.debug("Writing systemd-boot config "
200 "%s/hdd/boot/loader/entries/boot.conf", cr_workdir)
201 cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w")
202 cfg.write(boot_conf)
203 cfg.close()
191 204
192 205
193 @classmethod 206 @classmethod
@@ -207,6 +220,8 @@ class BootimgEFIPlugin(SourcePlugin):
207 cls.do_configure_grubefi(hdddir, creator, cr_workdir, source_params) 220 cls.do_configure_grubefi(hdddir, creator, cr_workdir, source_params)
208 elif source_params['loader'] == 'systemd-boot': 221 elif source_params['loader'] == 'systemd-boot':
209 cls.do_configure_systemdboot(hdddir, creator, cr_workdir, source_params) 222 cls.do_configure_systemdboot(hdddir, creator, cr_workdir, source_params)
223 elif source_params['loader'] == 'uefi-kernel':
224 pass
210 else: 225 else:
211 raise WicError("unrecognized bootimg-efi loader: %s" % source_params['loader']) 226 raise WicError("unrecognized bootimg-efi loader: %s" % source_params['loader'])
212 except KeyError: 227 except KeyError:
@@ -288,9 +303,107 @@ class BootimgEFIPlugin(SourcePlugin):
288 kernel = "%s-%s.bin" % \ 303 kernel = "%s-%s.bin" % \
289 (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME")) 304 (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME"))
290 305
291 install_cmd = "install -m 0644 %s/%s %s/%s" % \ 306 if source_params.get('create-unified-kernel-image') == "true":
292 (staging_kernel_dir, kernel, hdddir, kernel) 307 initrd = source_params.get('initrd')
293 exec_cmd(install_cmd) 308 if not initrd:
309 raise WicError("initrd= must be specified when create-unified-kernel-image=true, exiting")
310
311 deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
312 efi_stub = glob("%s/%s" % (deploy_dir, "linux*.efi.stub"))
313 if len(efi_stub) == 0:
314 raise WicError("Unified Kernel Image EFI stub not found, exiting")
315 efi_stub = efi_stub[0]
316
317 with tempfile.TemporaryDirectory() as tmp_dir:
318 label = source_params.get('label')
319 label_conf = "root=%s" % creator.rootdev
320 if label:
321 label_conf = "LABEL=%s" % label
322
323 bootloader = creator.ks.bootloader
324 cmdline = open("%s/cmdline" % tmp_dir, "w")
325 cmdline.write("%s %s" % (label_conf, bootloader.append))
326 cmdline.close()
327
328 initrds = initrd.split(';')
329 initrd = open("%s/initrd" % tmp_dir, "wb")
330 for f in initrds:
331 with open("%s/%s" % (deploy_dir, f), 'rb') as in_file:
332 shutil.copyfileobj(in_file, initrd)
333 initrd.close()
334
335 # Searched by systemd-boot:
336 # https://systemd.io/BOOT_LOADER_SPECIFICATION/#type-2-efi-unified-kernel-images
337 install_cmd = "install -d %s/EFI/Linux" % hdddir
338 exec_cmd(install_cmd)
339
340 staging_dir_host = get_bitbake_var("STAGING_DIR_HOST")
341 target_sys = get_bitbake_var("TARGET_SYS")
342
343 objdump_cmd = "%s-objdump" % target_sys
344 objdump_cmd += " -p %s" % efi_stub
345 objdump_cmd += " | awk '{ if ($1 == \"SectionAlignment\"){print $2} }'"
346
347 ret, align_str = exec_native_cmd(objdump_cmd, native_sysroot)
348 align = int(align_str, 16)
349
350 objdump_cmd = "%s-objdump" % target_sys
351 objdump_cmd += " -h %s | tail -2" % efi_stub
352 ret, output = exec_native_cmd(objdump_cmd, native_sysroot)
353
354 offset = int(output.split()[2], 16) + int(output.split()[3], 16)
355
356 osrel_off = offset + align - offset % align
357 osrel_path = "%s/usr/lib/os-release" % staging_dir_host
358 osrel_sz = os.stat(osrel_path).st_size
359
360 cmdline_off = osrel_off + osrel_sz
361 cmdline_off = cmdline_off + align - cmdline_off % align
362 cmdline_sz = os.stat(cmdline.name).st_size
363
364 dtb_off = cmdline_off + cmdline_sz
365 dtb_off = dtb_off + align - dtb_off % align
366
367 dtb = source_params.get('dtb')
368 if dtb:
369 if ';' in dtb:
370 raise WicError("Only one DTB supported, exiting")
371 dtb_path = "%s/%s" % (deploy_dir, dtb)
372 dtb_params = '--add-section .dtb=%s --change-section-vma .dtb=0x%x' % \
373 (dtb_path, dtb_off)
374 linux_off = dtb_off + os.stat(dtb_path).st_size
375 linux_off = linux_off + align - linux_off % align
376 else:
377 dtb_params = ''
378 linux_off = dtb_off
379
380 linux_path = "%s/%s" % (staging_kernel_dir, kernel)
381 linux_sz = os.stat(linux_path).st_size
382
383 initrd_off = linux_off + linux_sz
384 initrd_off = initrd_off + align - initrd_off % align
385
386 # https://www.freedesktop.org/software/systemd/man/systemd-stub.html
387 objcopy_cmd = "%s-objcopy" % target_sys
388 objcopy_cmd += " --enable-deterministic-archives"
389 objcopy_cmd += " --preserve-dates"
390 objcopy_cmd += " --add-section .osrel=%s" % osrel_path
391 objcopy_cmd += " --change-section-vma .osrel=0x%x" % osrel_off
392 objcopy_cmd += " --add-section .cmdline=%s" % cmdline.name
393 objcopy_cmd += " --change-section-vma .cmdline=0x%x" % cmdline_off
394 objcopy_cmd += dtb_params
395 objcopy_cmd += " --add-section .linux=%s" % linux_path
396 objcopy_cmd += " --change-section-vma .linux=0x%x" % linux_off
397 objcopy_cmd += " --add-section .initrd=%s" % initrd.name
398 objcopy_cmd += " --change-section-vma .initrd=0x%x" % initrd_off
399 objcopy_cmd += " %s %s/EFI/Linux/linux.efi" % (efi_stub, hdddir)
400
401 exec_native_cmd(objcopy_cmd, native_sysroot)
402 else:
403 if source_params.get('install-kernel-into-boot-dir') != 'false':
404 install_cmd = "install -m 0644 %s/%s %s/%s" % \
405 (staging_kernel_dir, kernel, hdddir, kernel)
406 exec_cmd(install_cmd)
294 407
295 if get_bitbake_var("IMAGE_EFI_BOOT_FILES"): 408 if get_bitbake_var("IMAGE_EFI_BOOT_FILES"):
296 for src_path, dst_path in cls.install_task: 409 for src_path, dst_path in cls.install_task:
@@ -312,6 +425,28 @@ class BootimgEFIPlugin(SourcePlugin):
312 for mod in [x for x in os.listdir(kernel_dir) if x.startswith("systemd-")]: 425 for mod in [x for x in os.listdir(kernel_dir) if x.startswith("systemd-")]:
313 cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[8:]) 426 cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, mod[8:])
314 exec_cmd(cp_cmd, True) 427 exec_cmd(cp_cmd, True)
428 elif source_params['loader'] == 'uefi-kernel':
429 kernel = get_bitbake_var("KERNEL_IMAGETYPE")
430 if not kernel:
431 raise WicError("Empty KERNEL_IMAGETYPE %s\n" % target)
432 target = get_bitbake_var("TARGET_SYS")
433 if not target:
434 raise WicError("Unknown arch (TARGET_SYS) %s\n" % target)
435
436 if re.match("x86_64", target):
437 kernel_efi_image = "bootx64.efi"
438 elif re.match('i.86', target):
439 kernel_efi_image = "bootia32.efi"
440 elif re.match('aarch64', target):
441 kernel_efi_image = "bootaa64.efi"
442 elif re.match('arm', target):
443 kernel_efi_image = "bootarm.efi"
444 else:
445 raise WicError("UEFI stub kernel is incompatible with target %s" % target)
446
447 for mod in [x for x in os.listdir(kernel_dir) if x.startswith(kernel)]:
448 cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (kernel_dir, mod, hdddir, kernel_efi_image)
449 exec_cmd(cp_cmd, True)
315 else: 450 else:
316 raise WicError("unrecognized bootimg-efi loader: %s" % 451 raise WicError("unrecognized bootimg-efi loader: %s" %
317 source_params['loader']) 452 source_params['loader'])
@@ -323,6 +458,11 @@ class BootimgEFIPlugin(SourcePlugin):
323 cp_cmd = "cp %s %s/" % (startup, hdddir) 458 cp_cmd = "cp %s %s/" % (startup, hdddir)
324 exec_cmd(cp_cmd, True) 459 exec_cmd(cp_cmd, True)
325 460
461 for paths in part.include_path or []:
462 for path in paths:
463 cp_cmd = "cp -r %s %s/" % (path, hdddir)
464 exec_cmd(cp_cmd, True)
465
326 du_cmd = "du -bks %s" % hdddir 466 du_cmd = "du -bks %s" % hdddir
327 out = exec_cmd(du_cmd) 467 out = exec_cmd(du_cmd)
328 blocks = int(out.split()[0]) 468 blocks = int(out.split()[0])
@@ -337,6 +477,13 @@ class BootimgEFIPlugin(SourcePlugin):
337 logger.debug("Added %d extra blocks to %s to get to %d total blocks", 477 logger.debug("Added %d extra blocks to %s to get to %d total blocks",
338 extra_blocks, part.mountpoint, blocks) 478 extra_blocks, part.mountpoint, blocks)
339 479
480 # required for compatibility with certain devices expecting file system
481 # block count to be equal to partition block count
482 if blocks < part.fixed_size:
483 blocks = part.fixed_size
484 logger.debug("Overriding %s to %d total blocks for compatibility",
485 part.mountpoint, blocks)
486
340 # dosfs image, created by mkdosfs 487 # dosfs image, created by mkdosfs
341 bootimg = "%s/boot.img" % cr_workdir 488 bootimg = "%s/boot.img" % cr_workdir
342 489