]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ukify: if the specified kernel is not a valid PE file try to decompress it
authorLuca Boccassi <luca.boccassi@gmail.com>
Thu, 13 Feb 2025 19:44:12 +0000 (19:44 +0000)
committerLuca Boccassi <luca.boccassi@gmail.com>
Fri, 14 Feb 2025 10:57:03 +0000 (10:57 +0000)
On some distros on some architectures (e.g.: Ubuntu arm64) the kernel is shipped as
a gzipped file, which the UEFI firmware does not understand.
If pefile fails to parse it, try to decompress it.

src/ukify/ukify.py

index 001ab956da290d570f5074d25874ecbbf1c5f77b..6400618648316f031b4df09d40f7fe2ef28d064a 100755 (executable)
@@ -1297,7 +1297,22 @@ def make_uki(opts: UkifyConfig) -> None:
     linux = opts.linux
     combined_sigs = '{}'
 
-    if opts.linux and sign_args_present:
+    # On some distros, on some architectures, the vmlinuz is a gzip file, so we need to decompress it
+    # if it's not a valid PE file, as it will fail to be booted by the firmware.
+    if linux:
+        try:
+            pefile.PE(linux, fast_load=True)
+        except pefile.PEFormatError:
+            try:
+                decompressed = maybe_decompress(linux)
+            except NotImplementedError:
+                print(f'{linux} is not a valid PE file and cannot be decompressed either', file=sys.stderr)
+            else:
+                print(f'{linux} is compressed and cannot be loaded by UEFI, decompressing', file=sys.stderr)
+                linux = Path(tempfile.NamedTemporaryFile(prefix='linux-decompressed').name)
+                linux.write_bytes(decompressed)
+
+    if linux and sign_args_present:
         assert opts.signtool is not None
         signtool = SignTool.from_string(opts.signtool)
 
@@ -1307,12 +1322,12 @@ def make_uki(opts: UkifyConfig) -> None:
 
         if sign_kernel:
             linux_signed = tempfile.NamedTemporaryFile(prefix='linux-signed')
+            signtool.sign(os.fspath(linux), os.fspath(Path(linux_signed.name)), opts=opts)
             linux = Path(linux_signed.name)
-            signtool.sign(os.fspath(opts.linux), os.fspath(linux), opts=opts)
 
-    if opts.uname is None and opts.linux is not None:
+    if opts.uname is None and linux is not None:
         print('Kernel version not specified, starting autodetection ðŸ˜–.', file=sys.stderr)
-        opts.uname = Uname.scrape(opts.linux, opts=opts)
+        opts.uname = Uname.scrape(linux, opts=opts)
 
     uki = UKI(opts.join_pcrsig if opts.join_pcrsig else opts.stub)
     initrd = join_initrds(opts.initrd)