diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2017-07-18 21:26:41 +0200 |
---|---|---|
committer | Saul Wold <sgw@linux.intel.com> | 2017-07-19 08:30:08 -0700 |
commit | 21086869beba0c6e38275be97af2e689e17820ec (patch) | |
tree | af75e9d90b91e064030a9527d25f5cfb8e23d805 /classes/uefi-comboapp.bbclass | |
parent | e76947d3ee70171cda00661d6367b0bc982cfe39 (diff) | |
download | meta-intel-21086869beba0c6e38275be97af2e689e17820ec.tar.gz |
uefi-comboapp.bbclass: support multiple UEFI combo apps + fixes
The original code in intel-iot-refkit allows to create more than one
UEFI combo app and uses that to create one for removable media and one
for fixed media (after installation), with different boot=PARTUUID=xxx
parameters. This way, an installed image never ended up booting from
the install media.
uefi-comboapp.bbclass now supports the same feature, with
create_uefiapp() as the API function that can be used to create
additional UEFI apps and create_uefiapps as the method where the call
can be added.
In addition, several shortcomings are getting addressed:
- A UEFI combo app must be stored under a name that is specific
to the image for which it gets created, otherwise different
image recipes end up overwriting (or using) files from other
images.
- Signing must be done after creating the apps and before deploying
them, otherwise the unsigned apps get copied to the image when
using do_uefiapp_deploy.
- The common code for deployment is now in uefiapp_deploy_at.
- $dest is used instead of ${DEST} because the latter might get
expanded by bitbake.
- Because do_uefiapp always had to run anew to produce the
clean, unsigned input for do_uefiapp_sign, having two different
tasks just added unnecessary complexity. Now all code is in
do_uefiapp.
- Old files matching the output pattern get removed explicitly,
because they might not get overwritten when the optional
app suffix changes between builds, or when the task fails
in the middle.
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: Saul Wold <sgw@linux.intel.com>
Diffstat (limited to 'classes/uefi-comboapp.bbclass')
-rw-r--r-- | classes/uefi-comboapp.bbclass | 71 |
1 files changed, 48 insertions, 23 deletions
diff --git a/classes/uefi-comboapp.bbclass b/classes/uefi-comboapp.bbclass index 77196863..fc7e1b6f 100644 --- a/classes/uefi-comboapp.bbclass +++ b/classes/uefi-comboapp.bbclass | |||
@@ -32,12 +32,13 @@ do_uefiapp[depends] += "${@ '${INITRD_IMAGE}:do_image_complete' if d.getVar('INI | |||
32 | # - the kernel | 32 | # - the kernel |
33 | # - an initramfs (optional) | 33 | # - an initramfs (optional) |
34 | 34 | ||
35 | python do_uefiapp() { | 35 | def create_uefiapp(d, uuid=None, app_suffix=''): |
36 | import glob, re | 36 | import glob, re |
37 | from subprocess import check_call | 37 | from subprocess import check_call |
38 | 38 | ||
39 | build_dir = d.getVar('B') | 39 | build_dir = d.getVar('B') |
40 | deploy_dir_image = d.getVar('DEPLOY_DIR_IMAGE') | 40 | deploy_dir_image = d.getVar('DEPLOY_DIR_IMAGE') |
41 | image_link_name = d.getVar('IMAGE_LINK_NAME') | ||
41 | 42 | ||
42 | cmdline = '%s/cmdline.txt' % build_dir | 43 | cmdline = '%s/cmdline.txt' % build_dir |
43 | linux = '%s/%s' % (deploy_dir_image, d.getVar('KERNEL_IMAGETYPE')) | 44 | linux = '%s/%s' % (deploy_dir_image, d.getVar('KERNEL_IMAGETYPE')) |
@@ -45,8 +46,9 @@ python do_uefiapp() { | |||
45 | 46 | ||
46 | stub_path = '%s/linux*.efi.stub' % deploy_dir_image | 47 | stub_path = '%s/linux*.efi.stub' % deploy_dir_image |
47 | stub = glob.glob(stub_path)[0] | 48 | 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 | m = re.match(r"\S*(ia32|x64)(.efi)\S*", os.path.basename(stub)) |
49 | executable = '%s/%s' % (deploy_dir_image, app) | 50 | app = "boot%s%s%s" % (m.group(1), app_suffix, m.group(2)) |
51 | executable = '%s/%s.%s' % (deploy_dir_image, image_link_name, app) | ||
50 | 52 | ||
51 | if d.getVar('INITRD_LIVE'): | 53 | if d.getVar('INITRD_LIVE'): |
52 | with open(initrd, 'wb') as dst: | 54 | with open(initrd, 'wb') as dst: |
@@ -57,7 +59,6 @@ python do_uefiapp() { | |||
57 | else: | 59 | else: |
58 | initrd_cmd = "" | 60 | initrd_cmd = "" |
59 | 61 | ||
60 | uuid = d.getVar('DISK_SIGNATURE_UUID') | ||
61 | root = 'root=PARTUUID=%s' % uuid if uuid else '' | 62 | root = 'root=PARTUUID=%s' % uuid if uuid else '' |
62 | 63 | ||
63 | with open(cmdline, 'w') as f: | 64 | with open(cmdline, 'w') as f: |
@@ -70,21 +71,22 @@ python do_uefiapp() { | |||
70 | (cmdline, linux, initrd_cmd, stub, executable) | 71 | (cmdline, linux, initrd_cmd, stub, executable) |
71 | 72 | ||
72 | check_call(objcopy_cmd, shell=True) | 73 | check_call(objcopy_cmd, shell=True) |
73 | } | ||
74 | 74 | ||
75 | do_uefiapp[vardeps] += "APPEND DISK_SIGNATURE_UUID INITRD_LIVE KERNEL_IMAGETYPE" | 75 | python create_uefiapps () { |
76 | 76 | # We must clean up anything that matches the expected output pattern, to ensure that | |
77 | do_uefiapp_deploy() { | 77 | # the next steps do not accidentally use old files. |
78 | rm -rf ${IMAGE_ROOTFS}/boot/* | 78 | import glob |
79 | mkdir -p ${IMAGE_ROOTFS}/boot/EFI/BOOT | 79 | pattern = d.expand('${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.boot*.efi') |
80 | cp --preserve=timestamps ${DEPLOY_DIR_IMAGE}/boot*.efi ${IMAGE_ROOTFS}/boot/EFI/BOOT/ | 80 | for old_efi in glob.glob(pattern): |
81 | os.unlink(old_efi) | ||
82 | uuid = d.getVar('DISK_SIGNATURE_UUID') | ||
83 | create_uefiapp(d, uuid=uuid) | ||
81 | } | 84 | } |
82 | 85 | ||
83 | do_uefiapp_deploy[depends] += "${PN}:do_uefiapp" | 86 | sign_uefiapps () { |
84 | 87 | if ${@ bb.utils.contains('IMAGE_FEATURES', 'secureboot', 'true', 'false', d) } && | |
85 | do_uefiapp_sign() { | 88 | [ -f ${UEFIAPP_SIGNING_KEY} ] && [ -f ${UEFIAPP_SIGNING_CERT} ]; then |
86 | if [ -f ${UEFIAPP_SIGNING_KEY} ] && [ -f ${UEFIAPP_SIGNING_CERT} ]; then | 89 | for i in `find ${DEPLOY_DIR_IMAGE}/ -name '${IMAGE_LINK_NAME}.boot*.efi'`; do |
87 | for i in `find ${DEPLOY_DIR_IMAGE}/ -name 'boot*.efi'`; do | ||
88 | sbsign --key ${UEFIAPP_SIGNING_KEY} --cert ${UEFIAPP_SIGNING_CERT} $i | 90 | sbsign --key ${UEFIAPP_SIGNING_KEY} --cert ${UEFIAPP_SIGNING_CERT} $i |
89 | sbverify --cert ${UEFIAPP_SIGNING_CERT} $i.signed | 91 | sbverify --cert ${UEFIAPP_SIGNING_CERT} $i.signed |
90 | mv $i.signed $i | 92 | mv $i.signed $i |
@@ -92,8 +94,35 @@ do_uefiapp_sign() { | |||
92 | fi | 94 | fi |
93 | } | 95 | } |
94 | 96 | ||
95 | do_uefiapp_sign[depends] += "${PN}:do_uefiapp_deploy \ | 97 | # This is intentionally split into different parts. This way, derived |
96 | sbsigntool-native:do_populate_sysroot" | 98 | # classes or images can extend the individual parts. We can also use |
99 | # whatever language (shell script or Python) is more suitable. | ||
100 | python do_uefiapp() { | ||
101 | bb.build.exec_func('create_uefiapps', d) | ||
102 | bb.build.exec_func('sign_uefiapps', d) | ||
103 | } | ||
104 | |||
105 | do_uefiapp[vardeps] += "APPEND DISK_SIGNATURE_UUID INITRD_LIVE KERNEL_IMAGETYPE IMAGE_LINK_NAME" | ||
106 | do_uefiapp[depends] += "${@ bb.utils.contains('IMAGE_FEATURES', 'secureboot', 'sbsigntool-native:do_populate_sysroot', '', d) }" | ||
107 | |||
108 | uefiapp_deploy_at() { | ||
109 | dest=$1 | ||
110 | for i in ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.boot*.efi; do | ||
111 | target=`basename $i` | ||
112 | target=`echo $target | sed -e 's/${IMAGE_LINK_NAME}.//'` | ||
113 | cp --preserve=timestamps -r $i $dest/$target | ||
114 | done | ||
115 | } | ||
116 | |||
117 | do_uefiapp_deploy() { | ||
118 | rm -rf ${IMAGE_ROOTFS}/boot/* | ||
119 | dest=${IMAGE_ROOTFS}/boot/EFI/BOOT | ||
120 | mkdir -p $dest | ||
121 | uefiapp_deploy_at $dest | ||
122 | } | ||
123 | |||
124 | do_uefiapp_deploy[depends] += "${PN}:do_uefiapp" | ||
125 | |||
97 | 126 | ||
98 | # This decides when/how we add our tasks to the image | 127 | # This decides when/how we add our tasks to the image |
99 | python () { | 128 | python () { |
@@ -124,17 +153,13 @@ python () { | |||
124 | if initramfs_fstypes not in image_fstypes: | 153 | if initramfs_fstypes not in image_fstypes: |
125 | bb.build.addtask('uefiapp', 'do_image', 'do_rootfs', d) | 154 | bb.build.addtask('uefiapp', 'do_image', 'do_rootfs', d) |
126 | bb.build.addtask('uefiapp_deploy', 'do_image', 'do_rootfs', d) | 155 | 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 | } | 156 | } |
131 | 157 | ||
132 | do_uefiapp[vardeps] += "UEFIAPP_SIGNING_CERT_HASH UEFIAPP_SIGNING_KEY_HASH" | 158 | do_uefiapp[vardeps] += "UEFIAPP_SIGNING_CERT_HASH UEFIAPP_SIGNING_KEY_HASH" |
133 | 159 | ||
134 | # Legacy hddimg support below this line | 160 | # Legacy hddimg support below this line |
135 | efi_hddimg_populate() { | 161 | efi_hddimg_populate() { |
136 | DEST=$1 | 162 | uefiapp_deploy_at "$1" |
137 | cp --preserve=timestamps -r ${DEPLOY_DIR_IMAGE}/boot*.efi ${DEST}/ | ||
138 | } | 163 | } |
139 | 164 | ||
140 | build_efi_cfg() { | 165 | build_efi_cfg() { |