| #!/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 <lasse.collin@tukaani.org> | |
| # 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 |