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