summaryrefslogtreecommitdiffstats
path: root/src/ukify/ukify.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-25 02:54:53 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-25 02:54:53 +0000
commit527e791c5346846e2bc7d32f7597d70f9a274499 (patch)
treed2bd96487387b049f0a99182d4cfd066adddd039 /src/ukify/ukify.py
parentAdding debian version 255.4-1. (diff)
downloadsystemd-527e791c5346846e2bc7d32f7597d70f9a274499.tar.xz
systemd-527e791c5346846e2bc7d32f7597d70f9a274499.zip
Merging upstream version 255.5.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/ukify/ukify.py')
-rwxr-xr-xsrc/ukify/ukify.py61
1 files changed, 56 insertions, 5 deletions
diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py
index 6abf1b6..b0d0961 100755
--- a/src/ukify/ukify.py
+++ b/src/ukify/ukify.py
@@ -40,6 +40,7 @@ import subprocess
import sys
import tempfile
import textwrap
+import struct
from hashlib import sha256
from typing import (Any,
Callable,
@@ -128,6 +129,45 @@ def try_import(modname, name=None):
except ImportError as e:
raise ValueError(f'Kernel is compressed with {name or modname}, but module unavailable') from e
+def get_zboot_kernel(f):
+ """Decompress zboot efistub kernel if compressed. Return contents."""
+ # See linux/drivers/firmware/efi/libstub/Makefile.zboot
+ # and linux/drivers/firmware/efi/libstub/zboot-header.S
+
+ # 4 bytes at offset 0x08 contain the starting offset of compressed data
+ f.seek(8)
+ _start = f.read(4)
+ start = struct.unpack('<i', _start)[0]
+
+ # Reading 4 bytes from address 0x0c is the size of compressed data,
+ # but it needs to be corrected according to the compressed type.
+ f.seek(0xc)
+ _sizes = f.read(4)
+ size = struct.unpack('<i', _sizes)[0]
+
+ # Read 6 bytes from address 0x18, which is a nul-terminated
+ # string representing the compressed type.
+ f.seek(0x18)
+ comp_type = f.read(6)
+ f.seek(start)
+ if comp_type.startswith(b'gzip'):
+ gzip = try_import('gzip')
+ return gzip.open(f).read(size)
+ elif comp_type.startswith(b'lz4'):
+ lz4 = try_import('lz4.frame', 'lz4')
+ return lz4.frame.decompress(f.read(size))
+ elif comp_type.startswith(b'lzma'):
+ lzma = try_import('lzma')
+ return lzma.open(f).read(size)
+ elif comp_type.startswith(b'lzo'):
+ raise NotImplementedError('lzo decompression not implemented')
+ elif comp_type.startswith(b'xzkern'):
+ raise NotImplementedError('xzkern decompression not implemented')
+ elif comp_type.startswith(b'zstd22'):
+ zstd = try_import('zstd')
+ return zstd.uncompress(f.read(size))
+ else:
+ raise NotImplementedError(f'unknown compressed type: {comp_type}')
def maybe_decompress(filename):
"""Decompress file if compressed. Return contents."""
@@ -140,8 +180,14 @@ def maybe_decompress(filename):
return f.read()
if start.startswith(b'MZ'):
- # not compressed aarch64 and riscv64
- return f.read()
+ f.seek(4)
+ img_type = f.read(4)
+ if img_type.startswith(b'zimg'):
+ # zboot efistub kernel
+ return get_zboot_kernel(f)
+ else:
+ # not compressed aarch64 and riscv64
+ return f.read()
if start.startswith(b'\x1f\x8b'):
gzip = try_import('gzip')
@@ -804,14 +850,19 @@ def make_uki(opts):
if linux is not None:
# Merge the .sbat sections from stub, kernel and parameter, so that revocation can be done on either.
- uki.add_section(Section.create('.sbat', merge_sbat([opts.stub, linux], opts.sbat), measure=True))
+ input_pes = [opts.stub, linux]
+ if not opts.sbat:
+ opts.sbat = ["""sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
+uki,1,UKI,uki,1,https://uapi-group.org/specifications/specs/unified_kernel_image/
+"""]
else:
# Addons don't use the stub so we add SBAT manually
+ input_pes = []
if not opts.sbat:
opts.sbat = ["""sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
-uki,1,UKI,uki,1,https://www.freedesktop.org/software/systemd/man/systemd-stub.html
+uki-addon,1,UKI Addon,addon,1,https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html
"""]
- uki.add_section(Section.create('.sbat', merge_sbat([], opts.sbat), measure=False))
+ uki.add_section(Section.create('.sbat', merge_sbat(input_pes, opts.sbat), measure=linux is not None))
# PCR measurement and signing