xref: /linux/scripts/xz_wrap.sh (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
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