From c164b0ced4b387779a93434717bea4623db8d41c Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 13 Feb 2025 19:44:12 +0000 Subject: [PATCH] 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) Related: RHEL-97625 --- src/ukify/ukify.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py index cf35daf821..45ce8e017c 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)