From: Luca Boccassi Date: Thu, 13 Feb 2025 19:44:12 +0000 (+0000) Subject: ukify: if the specified kernel is not a valid PE file try to decompress it X-Git-Tag: v257.4~57 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c9811b21b695090e1b25d192e865d52a2a5b2865;p=thirdparty%2Fsystemd.git ukify: if the specified kernel is not a valid PE file try to decompress it 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. (cherry picked from commit 0dd03215f1e402092f6c6da213708045e445a9ed) --- diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py index cf35daf8217..45ce8e017c3 100755 --- a/src/ukify/ukify.py +++ b/src/ukify/ukify.py @@ -1110,7 +1110,22 @@ def make_uki(opts: UkifyConfig) -> None: sign_kernel = opts.sign_kernel linux = opts.linux - 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) @@ -1120,12 +1135,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.stub) initrd = join_initrds(opts.initrd)