#!/bin/sh # SPDX-License-Identifier: 0BSD # # This is a wrapper for xz to compress the kernel image using appropriate # compression options depending on the architecture. # # Author: Lasse Collin # This has specialized settings for the following archs. However, # XZ-compressed kernel isn't currently supported on every listed arch. # # Arch Align Notes # arm 2/4 ARM and ARM-Thumb2 # arm64 4 # csky 2 # loongarch 4 # mips 2/4 MicroMIPS is 2-byte aligned # parisc 4 # powerpc 4 Uses its own wrapper for compressors instead of this. # riscv 2/4 # s390 2 # sh 2 # sparc 4 # x86 1 # A few archs use 2-byte or 4-byte aligned instructions depending on # the kernel config. This function is used to check if the relevant # config option is set to "y". is_enabled() { grep -q "^$1=y$" include/config/auto.conf } # XZ_VERSION is needed to disable features that aren't available in # old XZ Utils versions. XZ_VERSION=$($XZ --robot --version) || exit XZ_VERSION=$(printf '%s\n' "$XZ_VERSION" | sed -n 's/^XZ_VERSION=//p') # Assume that no BCJ filter is available. BCJ= # Set the instruction alignment to 1, 2, or 4 bytes. # # Set the BCJ filter if one is available. # It must match the #ifdef usage in lib/decompress_unxz.c. case $SRCARCH in arm) if is_enabled CONFIG_THUMB2_KERNEL; then ALIGN=2 BCJ=--armthumb else ALIGN=4 BCJ=--arm fi ;; arm64) ALIGN=4 # ARM64 filter was added in XZ Utils 5.4.0. if [ "$XZ_VERSION" -ge 50040002 ]; then BCJ=--arm64 else echo "$0: Upgrading to xz >= 5.4.0" \ "would enable the ARM64 filter" \ "for better compression" >&2 fi ;; csky) ALIGN=2 ;; loongarch) ALIGN=4 ;; mips) if is_enabled CONFIG_CPU_MICROMIPS; then ALIGN=2 else ALIGN=4 fi ;; parisc) ALIGN=4 ;; powerpc) ALIGN=4 # The filter is only for big endian instruction encoding. if is_enabled CONFIG_CPU_BIG_ENDIAN; then BCJ=--powerpc fi ;; riscv) if is_enabled CONFIG_RISCV_ISA_C; then ALIGN=2 else ALIGN=4 fi # RISC-V filter was added in XZ Utils 5.6.0. if [ "$XZ_VERSION" -ge 50060002 ]; then BCJ=--riscv else echo "$0: Upgrading to xz >= 5.6.0" \ "would enable the RISC-V filter" \ "for better compression" >&2 fi ;; s390) ALIGN=2 ;; sh) ALIGN=2 ;; sparc) ALIGN=4 BCJ=--sparc ;; x86) ALIGN=1 BCJ=--x86 ;; *) echo "$0: Arch-specific tuning is missing for '$SRCARCH'" >&2 # Guess 2-byte-aligned instructions. Guessing too low # should hurt less than guessing too high. ALIGN=2 ;; esac # Select the LZMA2 options matching the instruction alignment. case $ALIGN in 1) LZMA2OPTS= ;; 2) LZMA2OPTS=lp=1 ;; 4) LZMA2OPTS=lp=2,lc=2 ;; *) echo "$0: ALIGN wrong or missing" >&2; exit 1 ;; esac # Use single-threaded mode because it compresses a little better # (and uses less RAM) than multithreaded mode. # # For the best compression, the dictionary size shouldn't be # smaller than the uncompressed kernel. 128 MiB dictionary # needs less than 1400 MiB of RAM in single-threaded mode. # # On the archs that use this script to compress the kernel, # decompression in the preboot code is done in single-call mode. # Thus the dictionary size doesn't affect the memory requirements # of the preboot decompressor at all. exec $XZ --check=crc32 --threads=1 $BCJ --lzma2=$LZMA2OPTS,dict=128MiB