216 lines
9.6 KiB
Bash
216 lines
9.6 KiB
Bash
#!/bin/bash
|
|
# plymouth.sh — Plymouth boot splash installer
|
|
#
|
|
# Installs the M-Archy Plymouth theme: the magenta skull-monitor logo centred
|
|
# on a dark background, with the latest 3 boot-log lines polled underneath it
|
|
# as plain text (no spinner).
|
|
#
|
|
# SVG NOTE: Plymouth's image loader (ply-image) is PNG-only — it links against
|
|
# libpng and has no SVG or gdk-pixbuf dependency. The ply-image.h header is
|
|
# even commented "png file loader". bg-skull.svg must be converted to PNG with
|
|
# rsvg-convert (higher fidelity than ImageMagick for SVG) before deployment.
|
|
#
|
|
# Logo resolution order:
|
|
# 1. $PLYMOUTH_LOGO_SRC env var — caller-supplied custom image (PNG or SVG)
|
|
# 2. $DOTFILES_DIR/resources/bg-skull.svg — repo copy, always present
|
|
# 3. /root/installer/resources/bg-skull.svg — archiso embedded copy
|
|
#
|
|
# PNG inputs are used directly; SVG inputs are converted via rsvg-convert.
|
|
#
|
|
# Steps:
|
|
# 1. Install plymouth (extra repo)
|
|
# 2. Install librsvg (rsvg-convert) if logo is SVG
|
|
# 3. Produce logo.png (600 px wide) from the resolved source
|
|
# 4. Write the m-archy theme (.plymouth descriptor + .script animation)
|
|
# 5. Register with plymouth-set-default-theme
|
|
# 6. Inject plymouth / sd-plymouth hook into /etc/mkinitcpio.conf
|
|
# 7. Add 'quiet splash' to GRUB_CMDLINE_LINUX_DEFAULT
|
|
# 8. Regenerate GRUB config and initramfs
|
|
|
|
set -euo pipefail
|
|
source "$(dirname "${BASH_SOURCE[0]}")/../../lib/logging.sh"
|
|
|
|
THEME_DIR="/usr/share/plymouth/themes/m-archy"
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
# apps/ → optional-Modules → modules → setup → repo root (four levels up).
|
|
DOTFILES_DIR="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
|
|
|
|
# Resolve logo source — env var takes priority, then bundled SVG
|
|
LOGO_SRC="${PLYMOUTH_LOGO_SRC:-}"
|
|
if [[ -z "$LOGO_SRC" ]]; then
|
|
for _candidate in \
|
|
"$DOTFILES_DIR/resources/bg-skull.svg" \
|
|
"/root/installer/resources/bg-skull.svg"
|
|
do
|
|
if [[ -f "$_candidate" ]]; then
|
|
LOGO_SRC="$_candidate"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# ── Install Plymouth ──────────────────────────────────────────────────────────
|
|
log "Installing Plymouth..."
|
|
sudo pacman -S --noconfirm --needed plymouth
|
|
|
|
# ── Produce logo.png ──────────────────────────────────────────────────────────
|
|
TMP_LOGO="$(mktemp /tmp/plymouth-logo.XXXXXX.png)"
|
|
trap 'rm -f "$TMP_LOGO"' EXIT
|
|
|
|
if [[ -z "$LOGO_SRC" ]]; then
|
|
warn "No logo source found — using transparent placeholder."
|
|
if ! command -v convert &>/dev/null; then
|
|
log "Installing imagemagick (placeholder generation)..."
|
|
sudo pacman -S --noconfirm --needed imagemagick
|
|
fi
|
|
convert -size 600x600 xc:transparent "$TMP_LOGO"
|
|
elif [[ "${LOGO_SRC,,}" == *.png ]]; then
|
|
log "Using PNG directly: $LOGO_SRC"
|
|
cp "$LOGO_SRC" "$TMP_LOGO"
|
|
else
|
|
# SVG (or unknown) — convert via rsvg-convert for best fidelity
|
|
if ! command -v rsvg-convert &>/dev/null; then
|
|
log "Installing librsvg (rsvg-convert) for SVG→PNG conversion..."
|
|
sudo pacman -S --noconfirm --needed librsvg
|
|
fi
|
|
# Render at 600 px wide — the skull is centred (not full-screen), and the
|
|
# Plymouth script scales it down to a fraction of the display height, so we
|
|
# only need enough resolution to stay crisp on high-DPI panels.
|
|
log "Converting $LOGO_SRC → PNG (600 px wide)..."
|
|
rsvg-convert -w 600 "$LOGO_SRC" -o "$TMP_LOGO"
|
|
fi
|
|
|
|
# ── Install theme files ───────────────────────────────────────────────────────
|
|
log "Installing M-Archy Plymouth theme..."
|
|
sudo mkdir -p "$THEME_DIR"
|
|
sudo cp "$TMP_LOGO" "$THEME_DIR/logo.png"
|
|
|
|
sudo tee "$THEME_DIR/m-archy.plymouth" > /dev/null <<'EOF'
|
|
[Plymouth Theme]
|
|
Name=M-Archy
|
|
Description=M-Archy boot splash — centred skull logo with a boot-log tail
|
|
ModuleName=script
|
|
|
|
[script]
|
|
ImageDir=/usr/share/plymouth/themes/m-archy
|
|
ScriptFile=/usr/share/plymouth/themes/m-archy/m-archy.script
|
|
EOF
|
|
|
|
sudo tee "$THEME_DIR/m-archy.script" > /dev/null <<'EOF'
|
|
# M-Archy Plymouth splash — centred skull logo + latest 3 boot-log lines.
|
|
|
|
Window.SetBackgroundTopColor (0.10, 0.10, 0.10);
|
|
Window.SetBackgroundBottomColor (0.07, 0.07, 0.07);
|
|
|
|
screen_width = Window.GetWidth ();
|
|
screen_height = Window.GetHeight ();
|
|
|
|
# ── Skull logo, centred ───────────────────────────────────────────────────────
|
|
# logo.png is the tight skull-monitor artwork (roughly square). Scale it to a
|
|
# fraction of the screen height, preserving aspect ratio, then centre it and
|
|
# nudge it up a little so the log lines below have room to breathe.
|
|
logo.image = Image ("logo.png");
|
|
target_h = screen_height * 0.42;
|
|
scale = target_h / logo.image.GetHeight ();
|
|
scaled = logo.image.Scale (logo.image.GetWidth () * scale, target_h);
|
|
|
|
logo.sprite = Sprite (scaled);
|
|
logo.sprite.SetX ((screen_width - scaled.GetWidth ()) / 2);
|
|
logo.sprite.SetY ((screen_height - scaled.GetHeight ()) / 2 - screen_height * 0.08);
|
|
logo.sprite.SetZ (10);
|
|
|
|
# ── Boot-log tail — latest 3 lines ────────────────────────────────────────────
|
|
# A rolling buffer of the three most recent status/message strings Plymouth
|
|
# hands us, drawn as centred text beneath the logo. The newest line is the
|
|
# brightest; older lines fade back.
|
|
num_lines = 3;
|
|
line_gap = 26; # px between successive baselines
|
|
text_top = Math.Int (screen_height * 0.72); # y of the oldest (top) line
|
|
|
|
for (i = 0; i < num_lines; i++) {
|
|
log_line[i] = "";
|
|
log_sprite[i] = Sprite ();
|
|
log_sprite[i].SetZ (20);
|
|
}
|
|
|
|
fun draw_lines () {
|
|
for (i = 0; i < num_lines; i++) {
|
|
# Empty slots (before the buffer fills) stay hidden — Image.Text ("")
|
|
# is unreliable across Plymouth versions, so never render it.
|
|
if (log_line[i] == "") {
|
|
log_sprite[i].SetOpacity (0);
|
|
} else {
|
|
shade = 0.40 + 0.25 * i; # 0.40, 0.65, 0.90 top→bottom
|
|
image = Image.Text (log_line[i], shade, shade, shade);
|
|
log_sprite[i].SetImage (image);
|
|
log_sprite[i].SetX ((screen_width - image.GetWidth ()) / 2);
|
|
log_sprite[i].SetY (text_top + i * line_gap);
|
|
log_sprite[i].SetOpacity (1);
|
|
}
|
|
}
|
|
}
|
|
|
|
fun push_line (text) {
|
|
# Scroll the buffer up by one line and append the newcomer at the bottom.
|
|
for (i = 0; i < num_lines - 1; i++) {
|
|
log_line[i] = log_line[i + 1];
|
|
}
|
|
log_line[num_lines - 1] = text;
|
|
draw_lines ();
|
|
}
|
|
|
|
# Both callbacks feed the same tail: systemd unit progress arrives via the
|
|
# status function, explicit `plymouth display-message` strings via the message
|
|
# function.
|
|
Plymouth.SetUpdateStatusFunction (fun (status) { push_line (status); });
|
|
Plymouth.SetDisplayMessageFunction (fun (text) { push_line (text); });
|
|
EOF
|
|
|
|
# ── Register theme ────────────────────────────────────────────────────────────
|
|
log "Registering m-archy as default Plymouth theme..."
|
|
sudo plymouth-set-default-theme m-archy
|
|
|
|
# ── mkinitcpio: inject Plymouth hook ─────────────────────────────────────────
|
|
log "Adding Plymouth hook to /etc/mkinitcpio.conf..."
|
|
if grep -q '\bplymouth\b\|sd-plymouth' /etc/mkinitcpio.conf; then
|
|
skip "Plymouth hook already present in mkinitcpio.conf"
|
|
else
|
|
# systemd hook → sd-plymouth goes after systemd
|
|
# traditional udev hook → plymouth goes after udev
|
|
if grep -qE 'HOOKS=\([^)]*\bsystemd\b' /etc/mkinitcpio.conf; then
|
|
sudo sed -Ei 's/(\bsystemd\b)( |\))/\1 sd-plymouth\2/' /etc/mkinitcpio.conf
|
|
log "Injected sd-plymouth hook after systemd"
|
|
else
|
|
sudo sed -Ei 's/(\budev\b)( |\))/\1 plymouth\2/' /etc/mkinitcpio.conf
|
|
log "Injected plymouth hook after udev"
|
|
fi
|
|
|
|
if ! grep -q '\bplymouth\b\|sd-plymouth' /etc/mkinitcpio.conf; then
|
|
warn "Could not auto-inject Plymouth hook."
|
|
warn "Manually add 'plymouth' after 'udev' in /etc/mkinitcpio.conf."
|
|
fi
|
|
fi
|
|
|
|
# ── GRUB: add quiet splash ────────────────────────────────────────────────────
|
|
GRUB_CONF="/etc/default/grub"
|
|
if [[ -f "$GRUB_CONF" ]]; then
|
|
if grep -q '\bsplash\b' "$GRUB_CONF"; then
|
|
skip "'splash' already present in $GRUB_CONF"
|
|
else
|
|
log "Adding 'quiet splash' to GRUB_CMDLINE_LINUX_DEFAULT..."
|
|
sudo sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 quiet splash"/' "$GRUB_CONF"
|
|
sudo sed -i 's/quiet quiet/quiet/g' "$GRUB_CONF"
|
|
fi
|
|
log "Regenerating GRUB config..."
|
|
sudo grub-mkconfig -o /boot/grub/grub.cfg
|
|
else
|
|
warn "/etc/default/grub not found."
|
|
warn "If using systemd-boot, add 'quiet splash' to your loader entry manually."
|
|
fi
|
|
|
|
# ── Rebuild initramfs ─────────────────────────────────────────────────────────
|
|
log "Rebuilding initramfs (this bakes the theme into the initrd)..."
|
|
sudo mkinitcpio -P
|
|
|
|
log "Plymouth m-archy theme installed. Reboot to see the splash screen."
|