[OS-BUILD PATCHv9 1/2] redhat/kernel.spec: add uki_addons to create UKI kernel cmdline addons

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Emanuele Giuseppe Esposito <eesposit@xxxxxxxxxx>

redhat/kernel.spec: add uki_addons to create UKI kernel cmdline addons

Upstream Status: RHEL-Only

The folder redhat/addons will contain all addons configs specifying the
UKI kernel cmdline addons to be created in the next build. An addon
config is simply a .addon plain text file, where any line
is taken as kernel cmdline, except for the ones starting with '#',
which will be automatically ignored.

redhat/scripts/uki_addons.py will take care of parsing all configs and
folders in redhat/addons and call 'ukify' to create the actual addons.
The output addon filename will be a concatenation of all folders in
redhat/addons that are part of the addon config path.

The folder hierarchy inside of redhat/addons is similar to
redhat/configs: $distro/$UKI_NAME/%arch.

It is also possible to add .sbat to all the generated addons, by
populating redhat/addons/$distro/$UKI_NAME/%arch/sbat/sbat.conf.
Syntax is same as the addons config.

At build time, Makefile will create a tar.gz archive ($distro-$UKI_NAME-addons.tar.gz)
containing all the files in redhat/addons/$distro/$UKI_NAME. It will then passed to the
kernel specfile that will extract the addons from it and generate the
UKI kernel cmdline addons.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@xxxxxxxxxx>

diff --git a/redhat/Makefile b/redhat/Makefile
index blahblah..blahblah 100644
--- a/redhat/Makefile
+++ b/redhat/Makefile
@@ -679,6 +679,13 @@ sources-rh: $(TARBALL) generate-testpatch-tmp setup-source dist-configs-check
 	@sed -e "s/%%SPECKVERSION%%/$(SPECKVERSION)/" \
 		-e "s/%%SPECKPATCHLEVEL%%/$(SPECKPATCHLEVEL)/" \
 		scripts/gating/rpminspect.yaml > $(SOURCES)/rpminspect.yaml
+	@for UKI_FLAVOR in addons/*; do \
+		FLAVOR_NAME=$$(basename $$UKI_FLAVOR); \
+		for UKI in $$UKI_FLAVOR/*; do \
+			UKI_NAME=$$(basename $$UKI); \
+			tar -czf $$FLAVOR_NAME-$$UKI_NAME-addons.tar.gz $$UKI; \
+		done; \
+	done
 	@cp scripts/kernel-tools/kvm_stat.logrotate \
 		keys/rhel*.x509 \
 		kabi/check-kabi \
@@ -690,6 +697,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 +706,7 @@ sources-rh: $(TARBALL) generate-testpatch-tmp setup-source dist-configs-check
 		README.rst \
 		kernel-local \
 		dracut-virt.conf \
+		*-addons.tar.gz \
 		$(SOURCES)/
 	@cat $$(ls -1 $(SPECPACKAGE_NAME).changelog-* | sort -t '.' -k 3 -n -r) \
 		> $(SOURCES)/kernel.changelog
diff --git a/redhat/addons/fedora/virt/aarch64/sbat/.gitkeep b/redhat/addons/fedora/virt/aarch64/sbat/.gitkeep
new file mode 100644
index blahblah..blahblah 100644
--- /dev/null
+++ b/redhat/addons/fedora/virt/aarch64/sbat/.gitkeep
diff --git a/redhat/addons/fedora/virt/x86_64/ciao.addon b/redhat/addons/fedora/virt/x86_64/ciao.addon
new file mode 100644
index blahblah..blahblah 100644
--- /dev/null
+++ b/redhat/addons/fedora/virt/x86_64/ciao.addon
@@ -0,0 +1,7 @@
+# noooooooooo
+   # noooooooooooo
+
+cmdline good
+also good 
+   also good
+
diff --git a/redhat/addons/rhel/virt/aarch64/sbat/.gitkeep b/redhat/addons/rhel/virt/aarch64/sbat/.gitkeep
new file mode 100644
index blahblah..blahblah 100644
--- /dev/null
+++ b/redhat/addons/rhel/virt/aarch64/sbat/.gitkeep
diff --git a/redhat/addons/rhel/virt/x86_64/ciao.addon b/redhat/addons/rhel/virt/x86_64/ciao.addon
new file mode 100644
index blahblah..blahblah 100644
--- /dev/null
+++ b/redhat/addons/rhel/virt/x86_64/ciao.addon
@@ -0,0 +1,7 @@
+# noooooooooo
+   # noooooooooooo
+
+cmdline good
+also good 
+   also good
+
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
@@ -913,6 +915,7 @@ Source63: filter-aarch64.sh.fedora
 Source64: filter-ppc64le.sh.fedora
 Source65: filter-s390x.sh.fedora
 Source66: filter-modules.sh.fedora
+
 %endif
 
 Source70: partial-kgcov-snip.config
@@ -933,6 +936,9 @@ Source86: dracut-virt.conf
 
 Source87: flavors
 
+Source151: uki_addons.py
+Source152: %{primary_target}-virt-addons.tar.gz
+
 Source100: rheldup3.x509
 Source101: rhelkpatch1.x509
 
@@ -1518,6 +1524,11 @@ Provides: kernel-%{?1:%{1}-}uname-r = %{KVERREL}%{uname_suffix %{?1:+%{1}}}\
 Requires: kernel%{?1:-%{1}}-modules-core-uname-r = %{KVERREL}%{uname_suffix %{?1:+%{1}}}\
 Requires(pre): %{kernel_prereq}\
 Requires(pre): systemd >= 254-1\
+%package %{?1:%{1}-}uki-virt-addons\
+Summary: %{variant_summary} unified kernel image addons for virtual machines\
+Provides: installonlypkg(kernel)\
+Requires: kernel%{?1:-%{1}}-uki-virt = %{specrpmversion}-%{release}\
+Requires(pre): systemd >= 254-1\
 %endif\
 %endif\
 %if %{with_gcov}\
@@ -1657,31 +1668,49 @@ input and output, etc.
 %if %{with_up} && %{with_debug} && %{with_efiuki}
 %description debug-uki-virt
 Prebuilt debug unified kernel image for virtual machines.
+
+%description debug-uki-virt-addons
+Prebuilt debug unified kernel image addons for virtual machines.
 %endif
 
 %if %{with_up_base} && %{with_efiuki}
 %description uki-virt
 Prebuilt default unified kernel image for virtual machines.
+
+%description uki-virt-addons
+Prebuilt default unified kernel image addons for virtual machines.
 %endif
 
 %if %{with_arm64_16k} && %{with_debug} && %{with_efiuki}
 %description 16k-debug-uki-virt
 Prebuilt 16k debug unified kernel image for virtual machines.
+
+%description 16k-debug-uki-virt-addons
+Prebuilt 16k debug unified kernel image addons for virtual machines.
 %endif
 
 %if %{with_arm64_16k_base} && %{with_efiuki}
 %description 16k-uki-virt
 Prebuilt 16k unified kernel image for virtual machines.
+
+%description 16k-uki-virt-addons
+Prebuilt 16k unified kernel image addons for virtual machines.
 %endif
 
 %if %{with_arm64_64k} && %{with_debug} && %{with_efiuki}
 %description 64k-debug-uki-virt
 Prebuilt 64k debug unified kernel image for virtual machines.
+
+%description 64k-debug-uki-virt-addons
+Prebuilt 64k debug unified kernel image addons for virtual machines.
 %endif
 
 %if %{with_arm64_64k_base} && %{with_efiuki}
 %description 64k-uki-virt
 Prebuilt 64k unified kernel image for virtual machines.
+
+%description 64k-uki-virt-addons
+Prebuilt 64k unified kernel image addons for virtual machines.
 %endif
 
 %if %{with_ipaclones}
@@ -2525,6 +2554,12 @@ BuildKernel() {
            --kernel-cmdline 'console=tty0 console=ttyS0' \
 	   $KernelUnifiedImage
 
+  tar -xvf %{SOURCE152} -C $KernelUnifiedImageDir
+  KernelAddonsDir="$KernelUnifiedImageDir/addons/%{primary_target}/virt/%{_target_cpu}"
+  KernelAddonsDirOut="$RPM_BUILD_ROOT/usr/lib/linux/extra.d"
+  mkdir -p $KernelAddonsDirOut
+  python3 %{SOURCE151} $KernelAddonsDir $KernelAddonsDirOut %{_target_cpu}
+
 %if %{signkernel}
 
 	%pesign -s -i $KernelUnifiedImage -o $KernelUnifiedImage.tmp -a %{secureboot_ca_0} -c %{secureboot_key_0} -n %{pesign_name_0}
@@ -2537,9 +2572,17 @@ BuildKernel() {
     	fi
     	mv $KernelUnifiedImage.signed $KernelUnifiedImage
 
+      for addon in "$KernelAddonsDirOut"/*; 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
 
+  rm -rf $KernelAddonsDir
+
 	pushd $RPM_BUILD_ROOT
 
 # with_efiuki
@@ -3693,6 +3736,8 @@ fi\
 /lib/modules/%{KVERREL}%{?3:+%{3}}/modules.builtin*\
 %attr(0644, root, root) /lib/modules/%{KVERREL}%{?3:+%{3}}/%{?-k:%{-k*}}%{!?-k:vmlinuz}-virt.efi\
 %ghost /%{image_install_path}/efi/EFI/Linux/%{?-k:%{-k*}}%{!?-k:*}-%{KVERREL}%{?3:+%{3}}.efi\
+%{expand:%%files %{?3:%{3}-}uki-virt-addons}\
+/usr/lib/linux/extra.d/*.addon.efi\
 %endif\
 %endif\
 %if %{?3:1} %{!?3:0}\
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 @@
+#!/usr/bin/env python3
+#
+# This script recursively inspects a given uki directory, and creates an addon
+# for each file found.
+#
+# Usage: python uki_addons.py input_dir out_dir arch
+#
+# input_dir must be a path ending with this format:
+# [..]/$distro/$uki_name/$arch/
+#
+# This tool requires the systemd-ukify and systemd-boot packages.
+#
+# Addon file
+#-----------
+# Each addon terminates with .addon
+# Each addon contains only two types of lines:
+# Lines beginning with '#' are description and thus ignored
+# All other lines are command line to be added.
+# The name of the end resulting addon is taken from the folder hierarchy.
+# For example, and addon in rhel/virt/x86_64/hello.addon will result in
+# an UKI addon file generated in out_dir called hello-virt.rhel.x86_64.addon.efi
+#
+# sbat.conf
+#----------
+# This file is containing the sbat string for *all* addons being created.
+# This file is optional, but when used has to be put in out_dir/sbat/sbat.conf.
+# It follows the same syntax as the addon files, meaning '#' is comment and
+# the rest is taken as sbat string and feed to ukify.
+
+import os
+import sys
+import collections
+import subprocess
+
+SYSTEMD_STUB_PATH = '/usr/lib/systemd/boot/efi/'
+SYSTEMD_STUB_x86_64 = 'addonx64.efi.stub'
+SYSTEMD_STUB_aarch64 = 'addonaa64.efi.stub'
+CURRENT_SYSTEMD_STUB = None # set in __main__
+
+UKIFY_PATH = '/usr/lib/systemd/ukify'
+SBAT_LOCATION = '/sbat/sbat.conf'
+
+def usage(err):
+    print(f'Usage: {os.path.basename(__file__)} input_dir output_dir arch')
+    print(f'Error:{err}')
+    sys.exit(1)
+
+def check_clean_arguments(in_dir, out_dir):
+    # Remove end '/'
+    if in_dir[-1:] == '/':
+        in_dir = in_dir[:-1]
+    if out_dir[-1:] == '/':
+        out_dir = out_dir[:-1]
+    if not os.path.isdir(in_dir):
+        usage(f'in_dir {in_dir} is not a dir, or does not exist!')
+    if not os.path.isdir(out_dir):
+        usage(f'out_dir_dir {out_dir} is not a dir, or does not exist!')
+    return in_dir, out_dir
+
+UKICmdlineAddon = collections.namedtuple('UKICmdlineAddon', ['name', 'cmdline'])
+uki_addon_list = []
+
+def parse_addon_conf(path, rstrip=True):
+    with open(path, 'r') as addons:
+        lines = addons.readlines()
+    cmdline = ''
+    for l in lines:
+        l = l.lstrip()
+        if not l:
+            continue
+        if l[0] == '#':
+            continue
+        if rstrip:
+            l = l.rstrip() + ' '
+        cmdline += l
+    if cmdline == '':
+        return ''
+    return cmdline
+
+def parse_in_dir(in_dir):
+    for (dirpath, _, filenames) in os.walk(in_dir):
+        path = dirpath.split("/")
+        if len(path) < 3:
+            continue
+        arch = path[-1]
+        uki = path[-2]
+        distro = path[-3]
+        for addon_f in filenames:
+            if addon_f.endswith('.addon'):
+                addon_name = addon_f.replace(".addon","")
+                addon_full_name = f'{addon_name}-{uki}.{distro}.{arch}.addon.efi'
+                cmdline = parse_addon_conf(dirpath+'/'+addon_f)
+                if cmdline:
+                    uki_addon_list.append(UKICmdlineAddon(addon_full_name, cmdline))
+
+def parse_sbat(in_dir):
+    sbat_loc = in_dir + SBAT_LOCATION
+    if not os.path.isfile(sbat_loc):
+        return
+    return parse_addon_conf(sbat_loc, rstrip=False)
+
+def main(in_dir, out_dir):
+    sbat_string = parse_sbat(in_dir)
+    for uki_addon in uki_addon_list:
+        out_path = out_dir + '/' + uki_addon.name
+        cmd = [
+            f'{UKIFY_PATH}', 'build',
+            f'--stub={CURRENT_SYSTEMD_STUB}',
+            f'--cmdline="{uki_addon.cmdline}"',
+            f'--output={out_path}']
+        if sbat_string:
+            cmd.append('--sbat="' + sbat_string.rstrip() +'"')
+
+        print(cmd)
+        subprocess.check_call(cmd, text=True)
+
+if __name__ == "__main__":
+    argc = len(sys.argv) - 1
+    if argc != 2:
+        usage('too few or too many parameters!')
+
+    in_dir = sys.argv[1]
+    out_dir = sys.argv[2]
+    arch = sys.argv[3]
+    if arch is 'x86_64':
+        stub_arc = SYSTEMD_STUB_x86_64
+    elif arch is 'aarch64':
+        stub_arc = SYSTEMD_STUB_aarch64
+    else:
+        usage(f'arch {arch} not recognized!')
+    CURRENT_SYSTEMD_STUB = SYSTEMD_STUB_PATH + stub_arc
+
+    in_dir, out_dir = check_clean_arguments(in_dir, out_dir)
+    parse_in_dir(in_dir)
+    main(in_dir, out_dir)
+
+

--
https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2917
--
_______________________________________________
kernel mailing list -- kernel@xxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to kernel-leave@xxxxxxxxxxxxxxxxxxxxxxx
Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: https://lists.fedoraproject.org/archives/list/kernel@xxxxxxxxxxxxxxxxxxxxxxx
Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue




[Index of Archives]     [Fedora General Discussion]     [Older Fedora Users Archive]     [Fedora Advisory Board]     [Fedora Security]     [Fedora Devel Java]     [Fedora Legacy]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Mentors]     [Fedora Package Announce]     [Fedora Package Review]     [Fedora Music]     [Fedora Packaging]     [Centos]     [Fedora SELinux]     [Coolkey]     [Yum Users]     [Tux]     [Yosemite News]     [KDE Users]     [Fedora Art]     [Fedora Docs]     [USB]     [Asterisk PBX]

  Powered by Linux