#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
# SPDX-FileCopyrightText: 2023-2025 Harald Sitter <sitter@kde.org>

set -ex

. /etc/os-release

kernel_version="$1"
if [ -z "$kernel_version" ]; then
  versions=(/usr/lib/modules/*)
  version="${versions[-1]}"
  kernel_version="$(basename "$version")"
fi

if [ -z "$kernel_version" ]; then
  echo "No kernel version specified/found"
  exit 1
fi

# NOTE: plymouth MUST be after systemd as per the wiki!
cat <<- EOF > mkinitcpio.conf
MODULES=(overlay)
BINARIES=()
FILES=()
HOOKS=(base systemd modconf kms keyboard block sd-encrypt filesystems fsck systemd-extension plymouth microcode sd-shutdown)
EOF

echo "rw \
  systemd.volatile=overlay systemd.firstboot=false systemd.hostname=kde-linux kde-linux.live=1 plasma.live.user=live \
  lsm=landlock,lockdown,yama,integrity,bpf \
  zswap.enabled=0 \
  preempt=full threadirqs \
  nohz=on nohz_full=all \
  rcu_nocbs=all rcutree.enable_rcu_lazy=1 \
  amdgpu.dcdebugmask=0x10 \
  vt.global_cursor_default=0 quiet splash loglevel=3" > cmdline
mkinitcpio --config mkinitcpio.conf --generate initrd --kernel "$kernel_version"

# Delete af_alg et al. kernel modules; they're dangerous and unused by anything
# relevant except for iwd and non-default cryptsetup algorithms, neither of which
# are supported on KDE Linux.
#
# Also delete esp4, esp6, and rxrpc, which are exploitable via the dirtyfrag
# vulnerability and are only used for IPsec-in-IPv4, IPsec-in-IPv6, and the
# AF_RXRPC socket protocol (used by AFS/kAFS clients) respectively, none of which
# are used on KDE Linux.
#
# Also delete kafs because it requires rxrpc, and it's of very very very very
# limited utility.
#
# See also:
# - https://www.secwest.net/copyfail-mitigation
# - https://news.ycombinator.com/item?id=47956312
# - https://github.com/V4bel/dirtyfrag
#
# We have to do this here before we create the UKI or else they get pulled in by accident!
rm -rf \
    /usr/lib/modules/$kernel_version/kernel/crypto/af_alg.ko.zst \
    /usr/lib/modules/$kernel_version/kernel/crypto/algif_aead.ko.zst \
    /usr/lib/modules/$kernel_version/kernel/crypto/algif_hash.ko.zst \
    /usr/lib/modules/$kernel_version/kernel/crypto/algif_rng.ko.zst \
    /usr/lib/modules/$kernel_version/kernel/crypto/algif_skcipher.ko.zst \
    /usr/lib/modules/$kernel_version/kernel/net/ipv4/esp4.ko.zst \
    /usr/lib/modules/$kernel_version/kernel/net/ipv6/esp6.ko.zst \
    /usr/lib/modules/$kernel_version/kernel/net/rxrpc/ \
    /usr/lib/modules/$kernel_version/kernel/fs/afs/

ukify build \
  --linux /usr/lib/modules/$kernel_version/vmlinuz \
  --initrd initrd \
  --cmdline @cmdline \
  --output live.efi

# "preempt=full threadirqs" reduces latency especially for audio and gaming workflows.

# "nohz=on nohz_full=all" stops waking up a CPU more than once a second if it has fewer
# than 2 tasks. This reduces latency for userspace software and may also save power. The
# kernel requires at least one CPU to not be using this mode, but it will choose one for
# us. This requires nohz=on, which is the default, but we manually specify it here anyway
# because nohz_full=all needs it and we don't want that to break.

# "rcu_nocbs=all rcutree.enable_rcu_lazy=1" turns on batched/lazy RCU on all CPUs,
# reducing wake-ups and therefore power usage. rcu_nocbs=all is actually turned on
# automatically by nohz_full=all, but we manually specify it here anyway because
# rcutree.enable_rcu_lazy=1 needs it and we don't want that to break.

# amdgpu.dcdebugmask=0x10 works around https://gitlab.freedesktop.org/drm/amd/-/issues/4831
echo "rw rootflags=subvol=@system,compress=zstd:-4,lazytime \
  lsm=landlock,lockdown,yama,integrity,bpf \
  zswap.enabled=0 \
  preempt=full threadirqs \
  nohz=on nohz_full=all \
  rcu_nocbs=all rcutree.enable_rcu_lazy=1 \
  amdgpu.dcdebugmask=0x10 \
  systemd.hostname=kde-linux \
  vt.global_cursor_default=0 quiet splash loglevel=3" > cmdline
mkinitcpio --config mkinitcpio.conf --generate initrd --kernel "$kernel_version"
ukify build \
  --linux /usr/lib/modules/$kernel_version/vmlinuz \
  --initrd initrd \
  --cmdline @cmdline \
  --output kde-linux.efi

# Mock artifact for upgrades, see build.sh
ukify build \
  --cmdline "kde-linux.erofs.silence" \
  --output erofs.addon.efi
