build-kernel.sh RawHistoryFolder
1#!/usr/bin/env bash
2# SPDX-License-Identifier: MIT
3#
4# Build the Firecracker guest kernel (Linux 6.18 LTS) from kernel.org.
5#
6# scripts/build-kernel.sh [OUT_DIR]
7#
8# Environment:
9# KERNEL_VERSION version to build (default 6.18.56)
10# ARCH_NAME x86_64 (default: uname -m) or arm64 (aarch64)
11# WORK_DIR download and build directory (default tmp/kernel, gitignored)
12# JOBS make parallelism (default: nproc)
13#
14# Output: OUT_DIR/vmlinux (x86_64 ELF, accepted by Firecracker) or
15# OUT_DIR/Image (arm64), plus OUT_DIR/kernel.config. No root needed. The tarball
16# is verified against the sha256sums.asc published next to it on kernel.org
17# (integrity over TLS; the PGP signature is not checked, see README).
18set -euo pipefail
19
20root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
21version=${KERNEL_VERSION:-6.18.56}
22major=${version%%.*}
23work=${WORK_DIR:-$root/tmp/kernel}
24out=${1:-$root/tmp/image}
25jobs=${JOBS:-$(nproc)}
26arch_name=${ARCH_NAME:-$(uname -m)}
27
28case "$arch_name" in
29 x86_64|amd64) karch=x86; arch_frag=x86_64; target=vmlinux; artifact=vmlinux ;;
30 aarch64|arm64) karch=arm64; arch_frag=arm64; target=Image; artifact=arch/arm64/boot/Image ;;
31 *) echo "unsupported architecture: $arch_name" >&2; exit 2 ;;
32esac
33
34mkdir -p "$work" "$out"
35work=$(cd "$work" && pwd)
36out=$(cd "$out" && pwd)
37tarball="linux-$version.tar.xz"
38base="https://cdn.kernel.org/pub/linux/kernel/v${major}.x"
39
40if [ ! -f "$work/$tarball" ]; then
41 curl -fsSL -o "$work/$tarball.part" "$base/$tarball"
42 mv "$work/$tarball.part" "$work/$tarball"
43fi
44if [ ! -f "$work/sha256sums.asc" ] || ! grep -qF " $tarball" "$work/sha256sums.asc"; then
45 curl -fsSL -o "$work/sha256sums.asc" "$base/sha256sums.asc"
46fi
47want=$(awk -v f="$tarball" '$2 == f {print $1; exit}' "$work/sha256sums.asc")
48have=$(sha256sum "$work/$tarball" | awk '{print $1}')
49if [ -z "$want" ] || [ "$want" != "$have" ]; then
50 echo "checksum mismatch for $tarball (want '$want', have '$have')" >&2
51 exit 1
52fi
53
54src="$work/linux-$version"
55[ -d "$src" ] || tar -C "$work" -xf "$work/$tarball"
56
57cd "$src"
58export ARCH=$karch
59make tinyconfig >/dev/null
60scripts/kconfig/merge_config.sh -m .config \
61 "$root/images/kernel/config-6.18" "$root/images/kernel/config-6.18.$arch_frag" >/dev/null
62make olddefconfig >/dev/null
63
64# Fail if an option of the fragments was dropped by a missing dependency.
65missing=0
66while IFS== read -r key val; do
67 # Whole-line, fixed-string matches: option names contain no regex, but
68 # CONFIG_FOO must never match CONFIG_FOO_BAR=y.
69 if grep -qxF "$key=$val" .config; then continue; fi
70 if [ "$val" = n ] && ! grep -q "^${key}=" .config; then continue; fi
71 echo "kernel option not applied: $key=$val" >&2
72 missing=1
73done < <(cat "$root/images/kernel/config-6.18" "$root/images/kernel/config-6.18.$arch_frag" | grep -E '^CONFIG_[A-Z0-9_]+=')
74[ "$missing" = 0 ] || exit 1
75
76make -j"$jobs" "$target"
77cp "$artifact" "$out/$(basename "$artifact")"
78cp .config "$out/kernel.config"
79echo "kernel: $out/$(basename "$artifact")"