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". 29is_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. 36XZ_VERSION=$($XZ --robot --version) || exit 37XZ_VERSION=$(printf '%s\n' "$XZ_VERSION" | sed -n 's/^XZ_VERSION=//p') 38 39# Assume that no BCJ filter is available. 40BCJ= 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. 46case $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 ;; 141esac 142 143# Select the LZMA2 options matching the instruction alignment. 144case $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 ;; 149esac 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. 162exec $XZ --check=crc32 --threads=1 $BCJ --lzma2=$LZMA2OPTS,dict=128MiB 163