1 #!/bin/sh 2 # SPDX-License-Identifier: 0BSD 3 # 4 # This is a wrapper for xz to compress the kernel image using appropriate 5 # compression options depending on the architecture. 6 # 7 # Author: Lasse Collin <lasse.collin@tukaani.org> 8 9 # This has specialized settings for the following archs. However, 10 # XZ-compressed kernel isn't currently supported on every listed arch. 11 # 12 # Arch Align Notes 13 # arm 2/4 ARM and ARM-Thumb2 14 # arm64 4 15 # csky 2 16 # loongarch 4 17 # mips 2/4 MicroMIPS is 2-byte aligned 18 # parisc 4 19 # powerpc 4 Uses its own wrapper for compressors instead of this. 20 # riscv 2/4 21 # s390 2 22 # sh 2 23 # sparc 4 24 # x86 1 25 26 # A few archs use 2-byte or 4-byte aligned instructions depending on 27 # the kernel config. This function is used to check if the relevant 28 # config option is set to "y". 29 is_enabled() 30 { 31 grep -q "^$1=y$" include/config/auto.conf 32 } 33 34 # XZ_VERSION is needed to disable features that aren't available in 35 # old XZ Utils versions. 36 XZ_VERSION=$($XZ --robot --version) || exit 37 XZ_VERSION=$(printf '%s\n' "$XZ_VERSION" | sed -n 's/^XZ_VERSION=//p') 38 39 # Assume that no BCJ filter is available. 40 BCJ= 41 42 # Set the instruction alignment to 1, 2, or 4 bytes. 43 # 44 # Set the BCJ filter if one is available. 45 # It must match the #ifdef usage in lib/decompress_unxz.c. 46 case $SRCARCH in 47 arm) 48 if is_enabled CONFIG_THUMB2_KERNEL; then 49 ALIGN=2 50 BCJ=--armthumb 51 else 52 ALIGN=4 53 BCJ=--arm 54 fi 55 ;; 56 57 arm64) 58 ALIGN=4 59 60 # ARM64 filter was added in XZ Utils 5.4.0. 61 if [ "$XZ_VERSION" -ge 50040002 ]; then 62 BCJ=--arm64 63 else 64 echo "$0: Upgrading to xz >= 5.4.0" \ 65 "would enable the ARM64 filter" \ 66 "for better compression" >&2 67 fi 68 ;; 69 70 csky) 71 ALIGN=2 72 ;; 73 74 loongarch) 75 ALIGN=4 76 ;; 77 78 mips) 79 if is_enabled CONFIG_CPU_MICROMIPS; then 80 ALIGN=2 81 else 82 ALIGN=4 83 fi 84 ;; 85 86 parisc) 87 ALIGN=4 88 ;; 89 90 powerpc) 91 ALIGN=4 92 93 # The filter is only for big endian instruction encoding. 94 if is_enabled CONFIG_CPU_BIG_ENDIAN; then 95 BCJ=--powerpc 96 fi 97 ;; 98 99 riscv) 100 if is_enabled CONFIG_RISCV_ISA_C; then 101 ALIGN=2 102 else 103 ALIGN=4 104 fi 105 106 # RISC-V filter was added in XZ Utils 5.6.0. 107 if [ "$XZ_VERSION" -ge 50060002 ]; then 108 BCJ=--riscv 109 else 110 echo "$0: Upgrading to xz >= 5.6.0" \ 111 "would enable the RISC-V filter" \ 112 "for better compression" >&2 113 fi 114 ;; 115 116 s390) 117 ALIGN=2 118 ;; 119 120 sh) 121 ALIGN=2 122 ;; 123 124 sparc) 125 ALIGN=4 126 BCJ=--sparc 127 ;; 128 129 x86) 130 ALIGN=1 131 BCJ=--x86 132 ;; 133 134 *) 135 echo "$0: Arch-specific tuning is missing for '$SRCARCH'" >&2 136 137 # Guess 2-byte-aligned instructions. Guessing too low 138 # should hurt less than guessing too high. 139 ALIGN=2 140 ;; 141 esac 142 143 # Select the LZMA2 options matching the instruction alignment. 144 case $ALIGN in 145 1) LZMA2OPTS= ;; 146 2) LZMA2OPTS=lp=1 ;; 147 4) LZMA2OPTS=lp=2,lc=2 ;; 148 *) echo "$0: ALIGN wrong or missing" >&2; exit 1 ;; 149 esac 150 151 # Use single-threaded mode because it compresses a little better 152 # (and uses less RAM) than multithreaded mode. 153 # 154 # For the best compression, the dictionary size shouldn't be 155 # smaller than the uncompressed kernel. 128 MiB dictionary 156 # needs less than 1400 MiB of RAM in single-threaded mode. 157 # 158 # On the archs that use this script to compress the kernel, 159 # decompression in the preboot code is done in single-call mode. 160 # Thus the dictionary size doesn't affect the memory requirements 161 # of the preboot decompressor at all. 162 exec $XZ --check=crc32 --threads=1 $BCJ --lzma2=$LZMA2OPTS,dict=128MiB 163