summaryrefslogtreecommitdiffstats
path: root/classes/uefi-comboapp.bbclass
diff options
context:
space:
mode:
Diffstat (limited to 'classes/uefi-comboapp.bbclass')
-rw-r--r--classes/uefi-comboapp.bbclass155
1 files changed, 155 insertions, 0 deletions
diff --git a/classes/uefi-comboapp.bbclass b/classes/uefi-comboapp.bbclass
new file mode 100644
index 00000000..77196863
--- /dev/null
+++ b/classes/uefi-comboapp.bbclass
@@ -0,0 +1,155 @@
1# This class brings a more generic version of the UEFI combo app from refkit to meta-intel.
2# It uses a combo file, containing kernel, initramfs and
3# command line, presented to the BIOS as UEFI application, by prepending
4# it with the efi stub obtained from systemd-boot.
5
6# Don't add syslinux or build an ISO
7PCBIOS_forcevariable = "0"
8NOISO_forcevariable = "1"
9
10# image-live.bbclass will default INITRD_LIVE to the image INITRD_IMAGE creates.
11# We want behavior to be consistent whether or not "live" is in IMAGE_FSTYPES, so
12# we default INITRD_LIVE to the INITRD_IMAGE as well.
13INITRD_IMAGE ?= "core-image-minimal-initramfs"
14INITRD_LIVE ?= " ${@ ('${DEPLOY_DIR_IMAGE}/' + d.getVar('INITRD_IMAGE', expand=True) + '-${MACHINE}.cpio.gz') if d.getVar('INITRD_IMAGE', True) else ''}"
15
16do_uefiapp[depends] += " \
17 intel-microcode:do_deploy \
18 systemd-boot:do_deploy \
19 virtual/kernel:do_deploy \
20 "
21
22# INITRD_IMAGE is added to INITRD_LIVE, which we use to create our initrd, so depend on it if it is set
23do_uefiapp[depends] += "${@ '${INITRD_IMAGE}:do_image_complete' if d.getVar('INITRD_IMAGE') else ''}"
24
25# The image does without traditional bootloader.
26# In its place, instead, it uses a single UEFI executable binary, which is
27# composed by:
28# - an UEFI stub
29# The linux kernel can generate a UEFI stub, however the one from systemd-boot can fetch
30# the command line from a separate section of the EFI application, avoiding the need to
31# rebuild the kernel.
32# - the kernel
33# - an initramfs (optional)
34
35python do_uefiapp() {
36 import glob, re
37 from subprocess import check_call
38
39 build_dir = d.getVar('B')
40 deploy_dir_image = d.getVar('DEPLOY_DIR_IMAGE')
41
42 cmdline = '%s/cmdline.txt' % build_dir
43 linux = '%s/%s' % (deploy_dir_image, d.getVar('KERNEL_IMAGETYPE'))
44 initrd = '%s/initrd' % build_dir
45
46 stub_path = '%s/linux*.efi.stub' % deploy_dir_image
47 stub = glob.glob(stub_path)[0]
48 app = re.sub(r"\S*(ia32|x64)(.efi)\S*", r"boot\1\2", os.path.basename(stub))
49 executable = '%s/%s' % (deploy_dir_image, app)
50
51 if d.getVar('INITRD_LIVE'):
52 with open(initrd, 'wb') as dst:
53 for cpio in d.getVar('INITRD_LIVE').split():
54 with open(cpio, 'rb') as src:
55 dst.write(src.read())
56 initrd_cmd = "--add-section .initrd=%s --change-section-vma .initrd=0x3000000 " % initrd
57 else:
58 initrd_cmd = ""
59
60 uuid = d.getVar('DISK_SIGNATURE_UUID')
61 root = 'root=PARTUUID=%s' % uuid if uuid else ''
62
63 with open(cmdline, 'w') as f:
64 f.write('%s %s' % (d.getVar('APPEND'), root))
65
66 objcopy_cmd = ("objcopy "
67 "--add-section .cmdline=%s --change-section-vma .cmdline=0x30000 "
68 "--add-section .linux=%s --change-section-vma .linux=0x40000 "
69 "%s %s %s") % \
70 (cmdline, linux, initrd_cmd, stub, executable)
71
72 check_call(objcopy_cmd, shell=True)
73}
74
75do_uefiapp[vardeps] += "APPEND DISK_SIGNATURE_UUID INITRD_LIVE KERNEL_IMAGETYPE"
76
77do_uefiapp_deploy() {
78 rm -rf ${IMAGE_ROOTFS}/boot/*
79 mkdir -p ${IMAGE_ROOTFS}/boot/EFI/BOOT
80 cp --preserve=timestamps ${DEPLOY_DIR_IMAGE}/boot*.efi ${IMAGE_ROOTFS}/boot/EFI/BOOT/
81}
82
83do_uefiapp_deploy[depends] += "${PN}:do_uefiapp"
84
85do_uefiapp_sign() {
86 if [ -f ${UEFIAPP_SIGNING_KEY} ] && [ -f ${UEFIAPP_SIGNING_CERT} ]; then
87 for i in `find ${DEPLOY_DIR_IMAGE}/ -name 'boot*.efi'`; do
88 sbsign --key ${UEFIAPP_SIGNING_KEY} --cert ${UEFIAPP_SIGNING_CERT} $i
89 sbverify --cert ${UEFIAPP_SIGNING_CERT} $i.signed
90 mv $i.signed $i
91 done
92 fi
93}
94
95do_uefiapp_sign[depends] += "${PN}:do_uefiapp_deploy \
96 sbsigntool-native:do_populate_sysroot"
97
98# This decides when/how we add our tasks to the image
99python () {
100 import os
101 import hashlib
102
103 secureboot = bb.utils.contains('IMAGE_FEATURES', 'secureboot', True, False, d)
104 # Ensure that if the signing key or cert change, we rerun the uefiapp process
105 if secureboot:
106 for varname in ('UEFIAPP_SIGNING_CERT', 'UEFIAPP_SIGNING_KEY'):
107 filename = d.getVar(varname)
108 if filename is None:
109 bb.fatal('%s is not set.' % varname)
110 if not os.path.isfile(filename):
111 bb.fatal('%s=%s is not a file.' % (varname, filename))
112 with open(filename, 'rb') as f:
113 data = f.read()
114 hash = hashlib.sha256(data).hexdigest()
115 d.setVar('%s_HASH' % varname, hash)
116
117 # Must reparse and thus rehash on file changes.
118 bb.parse.mark_dependency(d, filename)
119
120 image_fstypes = d.getVar('IMAGE_FSTYPES', True)
121 initramfs_fstypes = d.getVar('INITRAMFS_FSTYPES', True)
122
123 # Don't add any of these tasks to initramfs images
124 if initramfs_fstypes not in image_fstypes:
125 bb.build.addtask('uefiapp', 'do_image', 'do_rootfs', d)
126 bb.build.addtask('uefiapp_deploy', 'do_image', 'do_rootfs', d)
127 # Only sign if secureboot is enabled
128 if secureboot:
129 bb.build.addtask('uefiapp_sign', 'do_image', 'do_rootfs', d)
130}
131
132do_uefiapp[vardeps] += "UEFIAPP_SIGNING_CERT_HASH UEFIAPP_SIGNING_KEY_HASH"
133
134# Legacy hddimg support below this line
135efi_hddimg_populate() {
136 DEST=$1
137 cp --preserve=timestamps -r ${DEPLOY_DIR_IMAGE}/boot*.efi ${DEST}/
138}
139
140build_efi_cfg() {
141 # The command line is built into the combo app, so this is a null op
142 :
143}
144
145populate_kernel_append() {
146 # The kernel and initrd are built into the app, so we don't need these
147 if [ -f $dest/initrd ]; then
148 rm $dest/initrd
149 fi
150 if [ -f $dest/vmlinuz ]; then
151 rm $dest/vmlinuz
152 fi
153}
154
155IMAGE_FEATURES[validitems] += "secureboot"