[OS-BUILD PATCH] redhat/kernel.spec: add uki_addons to create UKI
kernel
cmdline addons
by Emanuele Giuseppe Esposito (via Email Bridge)
From: Emanuele Giuseppe Esposito <eesposit(a)redhat.com>
redhat/kernel.spec: add uki_addons to create UKI kernel cmdline addons
Upstream Status: RHEL-Only
By defininig an addon in uki_cmdline_addons.conf, the script
uki_addons.py will automatically create an UKI addon to be shipped
together in the same package.
For additional info on how to format uki_cmdline_addons.conf, check
uki_addons.py head comment.
Signed-off-by: Emanuele Giuseppe Esposito <eesposit(a)redhat.com>
diff --git a/redhat/Makefile b/redhat/Makefile
index blahblah..blahblah 100644
--- a/redhat/Makefile
+++ b/redhat/Makefile
@@ -690,6 +690,7 @@ sources-rh: $(TARBALL) generate-testpatch-tmp setup-source dist-configs-check
scripts/mod/mod-partner.list \
scripts/mod/mod-sign.sh \
scripts/mod/mod-kvm.list \
+ scripts/uki_addons.py \
configs/flavors \
configs/generate_all_configs.sh \
configs/merge.py \
@@ -698,6 +699,7 @@ sources-rh: $(TARBALL) generate-testpatch-tmp setup-source dist-configs-check
README.rst \
kernel-local \
dracut-virt.conf \
+ uki_cmdline_addons.conf \
$(SOURCES)/
@cat $$(ls -1 $(SPECPACKAGE_NAME).changelog-* | sort -t '.' -k 3 -n -r) \
> $(SOURCES)/kernel.changelog
diff --git a/redhat/kernel.spec.template b/redhat/kernel.spec.template
index blahblah..blahblah 100644
--- a/redhat/kernel.spec.template
+++ b/redhat/kernel.spec.template
@@ -792,6 +792,8 @@ BuildRequires: binutils
BuildRequires: lvm2
BuildRequires: systemd-boot-unsigned
# For systemd-stub and systemd-pcrphase
+BuildRequires: systemd-ukify
+# For UKI kernel cmdline addons
BuildRequires: systemd-udev >= 252-1
# For TPM operations in UKI initramfs
BuildRequires: tpm2-tools
@@ -933,6 +935,9 @@ Source86: dracut-virt.conf
Source87: flavors
+Source151: uki_addons.py
+Source152: uki_cmdline_addons.conf
+
Source100: rheldup3.x509
Source101: rhelkpatch1.x509
@@ -2537,6 +2542,15 @@ BuildKernel() {
fi
mv $KernelUnifiedImage.signed $KernelUnifiedImage
+ KernelAddonsDir="$KernelUnifiedImageDir/addons"
+ mkdir -p $KernelAddonsDir
+ python3 %{SOURCE151} %{SOURCE152} $KernelAddonsDir
+ for addon in "$KernelAddonsDir"/*; do
+ %pesign -s -i $addon -o $addon.signed -a %{secureboot_ca_1} -c %{secureboot_key_1} -n %{pesign_name_1}
+ rm -f $addon
+ mv $addon.signed $addon
+ done
+
# signkernel
%endif
@@ -3692,6 +3706,7 @@ fi\
/lib/modules/%{KVERREL}%{?3:+%{3}}/config\
/lib/modules/%{KVERREL}%{?3:+%{3}}/modules.builtin*\
%attr(0644, root, root) /lib/modules/%{KVERREL}%{?3:+%{3}}/%{?-k:%{-k*}}%{!?-k:vmlinuz}-virt.efi\
+/lib/modules/%{KVERREL}%{?3:+%{3}}/addons/*.addon.efi\
%ghost /%{image_install_path}/efi/EFI/Linux/%{?-k:%{-k*}}%{!?-k:*}-%{KVERREL}%{?3:+%{3}}.efi\
%endif\
%endif\
diff --git a/redhat/scripts/uki_addons.py b/redhat/scripts/uki_addons.py
new file mode 100644
index blahblah..blahblah 100644
--- /dev/null
+++ b/redhat/scripts/uki_addons.py
@@ -0,0 +1,137 @@
+#!/bin/bash
+#
+# This script reads a given uki addons config file list, and creates an addon
+# for each definition given.
+#
+# Usage: python uki_addons.py cfgfile cert.pem key output_dir
+#
+# This tool requires the systemd-ukify and systemd-boot yum packages.
+#
+# Cfgfile definition
+#-------------------
+# Each addon is separate from the next by an empty line.
+# Each addon has 3 mandatory fields, plus one optional (sbat).
+# Each field (except the fourth) is terminated by a single newline.
+# No multiline fields! If a cmdline starts to be too long, maybe it's time to
+# create multiple addons.
+#
+# Cfgfile fields
+#---------------
+# - Name: name of the addon. This tool will create an addon called <name>.addon.efi
+# and put it in @output_dir. Name might or might not contain .addon.efi.
+# If it is missing, it will be added automatically.
+# - Description: human readable description of the addon. Not included in the
+# generated file.
+# - Command line: the command line to be inserted into the addon.
+# - SBAT (optional): If this field is specified, replace .sbat with the provided
+# one. This field can be multiline, but must have an additional
+# newline (or EOF) to separate from the next addon.
+
+import os
+import sys
+import collections
+import subprocess
+
+SYSTEMD_STUB_PATH = '/usr/lib/systemd/boot/efi/addonx64.efi.stub'
+UKIFY_PATH = '/usr/lib/systemd/ukify'
+
+def usage(err):
+ print(f'Usage: {os.path.basename(__file__)} cfgfile cert.pem key output_dir')
+ if err:
+ print(f'Error:{err}')
+ sys.exit(1)
+
+def cfgfile_fields_help():
+ print("Cfgfile fields")
+ print("---------------")
+ print(" - Name: name of the addon. This tool will create an addon called <name>.addon.efi")
+ print(" and put it in @output_dir. Name might or might not contain .addon.efi.")
+ print(" If it is missing, it will be added automatically.")
+ print(" - Description: human readable description of the addon. Not included in the")
+ print(" generated file.")
+ print(" - Command line: the command line to be inserted into the addon.")
+ print(" - SBAT (optional): If this field is specified, replace .sbat with the provided")
+ print(" one. This field can be multiline, but must have an additional")
+ print(" newline (or EOF) to separate from the next addon.")
+ sys.exit(1)
+
+def check_arguments(cfgfile, output):
+ if not os.path.isfile(cfgfile):
+ usage(f'cfgfile {cfgfile} is not a file, or does not exist!')
+
+ if not os.path.isdir(output):
+ usage(f'output_dir {output} is not a dir, or does not exist!')
+
+UKICmdlineAddon = collections.namedtuple('UKICmdlineAddon', ['name', 'desc', 'cmdline', 'sbat'])
+
+def create_uki_addon(start, end, lines):
+ name = lines[start].rstrip()
+ if not name.endswith('.addon.efi'):
+ name += '.addon.efi'
+ desc = lines[start + 1].rstrip()
+ cmdline = lines[start + 2].rstrip()
+ sbat = ''.join(lines[start+3:end])
+ return UKICmdlineAddon(name, desc, cmdline, sbat)
+
+def parse_addon(i, lines):
+ start = -1
+ while i < len(lines) and start < 0:
+ if lines[i] != '\n':
+ start = i
+ i += 1
+
+ end = -1
+ while i < len(lines) and end < 0:
+ if lines[i] == '\n':
+ end = i
+ i += 1
+ if i == len(lines) and end < 0:
+ end = i
+
+ if start < 0 or end < 0:
+ return None, i
+
+ if start + 3 > end: # too small, fields ignored
+ print(f'Addon line {start+1}:{end} ignored, must contain at least name-descr-cmdline')
+ return None, i
+
+ return create_uki_addon(start, end, lines), i
+
+def main(cfgfile, output):
+ if not output.endswith('/'):
+ output += '/'
+
+ with open(cfgfile, 'r') as addons:
+ lines = addons.readlines()
+
+ i = 0
+ while i < len(lines):
+ addon, i = parse_addon(i, lines)
+ if not addon:
+ continue
+ out_path = output + addon.name
+ cmd = [
+ f'{UKIFY_PATH}', 'build',
+ f'--stub={SYSTEMD_STUB_PATH}',
+ f'--cmdline="{addon.cmdline}"',
+ f'--output={out_path}']
+ if addon.sbat != '':
+ cmd.append('--sbat=' + addon.sbat.rstrip() +'')
+
+ # print(''.join(cmd))
+ print(cmd)
+ print()
+ subprocess.check_call(cmd, text=True)
+
+if __name__ == "__main__":
+ argc = len(sys.argv) - 1
+ if argc != 2:
+ usage('too few or too many parameters!')
+
+ cfgfile = sys.argv[1]
+ output = sys.argv[2]
+
+ check_arguments(cfgfile, output)
+ main(cfgfile, output)
+
+
diff --git a/redhat/uki_cmdline_addons.conf b/redhat/uki_cmdline_addons.conf
new file mode 100644
index blahblah..blahblah 100644
--- /dev/null
+++ b/redhat/uki_cmdline_addons.conf
--
https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2917