diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py index 9013e64b62d..097a7ee0c66 100755 --- a/src/ukify/ukify.py +++ b/src/ukify/ukify.py @@ -194,9 +194,9 @@ def get_zboot_kernel(f: IO[bytes]) -> bytes: 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 cast(bytes, zstd.uncompress(f.read(size))) + elif comp_type.startswith(b'zstd'): + zstd = try_import('zstandard') + return cast(bytes, zstd.ZstdDecompressor().stream_reader(f.read(size)).read()) raise NotImplementedError(f'unknown compressed type: {comp_type!r}') @@ -226,8 +226,8 @@ def maybe_decompress(filename: Union[str, Path]) -> bytes: return cast(bytes, gzip.open(f).read()) if start.startswith(b'\x28\xb5\x2f\xfd'): - zstd = try_import('zstd') - return cast(bytes, zstd.uncompress(f.read())) + zstd = try_import('zstandard') + return cast(bytes, zstd.ZstdDecompressor().stream_reader(f.read()).read()) if start.startswith(b'\x02\x21\x4c\x18'): lz4 = try_import('lz4.frame', 'lz4') @@ -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) @@ -2374,7 +2389,7 @@ def finalize_options(opts: argparse.Namespace) -> None: if opts.efi_arch is None: opts.efi_arch = guess_efi_arch() - if opts.stub is None: + if opts.stub is None and not opts.join_pcrsig: if opts.linux is not None: opts.stub = Path(f'/usr/lib/systemd/boot/efi/linux{opts.efi_arch}.efi.stub') else: