Xiaotian Wu
2023-11-16 20:01:50 +08:00
committed by Zbigniew Jędrzejewski-Szmek
parent 5346a81024
commit 96069e57a0

View File

@@ -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')