scripts v1.22.0 — ISO boot screen + single-entry GRUB menu (R-38 GRUB slice)

Two jobs, one repack pass.

BRANDING. Every ISO now carries a Felhom boot screen built from the website's
og-image_2.png at repack time (ImageMagick in the assistant container), so the
boot card has ONE source and not a second pre-rendered copy in the repo to
drift. The card is scaled onto a 1024x768 gfxterm canvas, top-centered, and the
card's own subtle background grid is continued across the letterbox fill
PHASE-LOCKED to where the card's grid lands — the fill is seamless rather than a
square of grid floating in flat navy. Menu positioning needs a gfxmenu theme
(plain background_image cannot move the menu off the wordmark), so the stock
pvetheme is replaced by felhomtheme, which puts the menu in the lower third the
layout deliberately leaves empty.

SAFETY — the half that matters. The stock PVE menu offers Graphical, Terminal
UI and serial installers plus an Advanced Options submenu (nomodeset x2, three
debug variants, Rescue Boot, memtest, UEFI settings). Every one of them reaches
the MANUAL installer, whose first question is which disk to wipe. A customer, or
their helpful nephew, must not be able to get there from a boot menu. They are
not hidden and not password-gated: they are NOT EMITTED. What ships is one
entry, 'Felhom telepítés', default, 5s.

Boot behavior is unchanged. The kernel/append and initrd lines are lifted
VERBATIM from the ISO's own 'Install Proxmox VE (Automated)' entry rather than
frozen into a copy here, so a PVE bump tracks automatically; the build fails if
they cannot be found, if the append line has lost proxmox-start-auto-installer,
or if auto-installer-mode.toml is absent (which would mean the one Felhom-
labelled entry boots a manual installer). The rendered menu is then gated for
exactly 1 entry, 0 submenus, and zero references to proxtui/proxdebug/nomodeset/
Rescue Boot/memtest/fwsetup — and re-verified by reading the menu back OUT of
the finished ISO, not merely out of the extract tree.

mkimage-surgery.sh -> iso-repack.sh: branding and the slice-B loader swap need
the same extract -> modify -> re-master cycle, so they share one pass instead of
re-mastering twice. The mkimage recipe is untouched. The embedded module list is
still derived from the STOCK grub.cfg (snapshotted before branding rewrites it),
plus gfxmenu's bitmap/bitmap_scale/trig renderer deps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nn3VgQk9iwEGgyx6QJ2NvE
This commit is contained in:
2026-07-19 08:45:45 +02:00
parent 3e2078be8a
commit 317037f8eb
9 changed files with 609 additions and 186 deletions
+46
View File
@@ -0,0 +1,46 @@
# Felhom ISO — GRUB gfxmenu theme (scripts v1.22.0, R-38 GRUB slice).
#
# WHY A THEME AND NOT `background_image`: plain gfxterm draws the menu in the terminal's own region
# (top-left), which on our card lands the text straight across the cloud/wordmark. A gfxmenu theme is
# the only way to POSITION the menu, so the menu sits in the clean lower third that
# generate-grub-background.sh deliberately leaves empty (the card is composited into the TOP 516px of
# a 1024x768 canvas). Keep this file and the background generator's CARD/CARD_Y constants in sync —
# if the card grows, `boot_menu.top` must move down with it.
#
# Colors are design-system v2: --blue #0083D8 for the selected item, light text on the near-black
# navy (#0D1117) the card itself uses.
title-text: ""
desktop-image: "background.png"
desktop-color: "#0D1117"
# The single entry ("Felhom telepítés"). Below the card, horizontally centered.
+ boot_menu {
left = 25%
top = 70%
width = 50%
height = 14%
item_color = "#E6EDF3"
selected_item_color = "#0083D8"
item_height = 32
item_padding = 0
item_icon_space = 0
item_spacing = 2
}
# Honest countdown — the customer sees that something IS about to happen, not a frozen screen.
# NOTE: no "e: edit entry / esc: back" hint label (the stock PVE theme has one). Advertising the
# editor works against the point of the single-entry menu.
+ label {
id = "__timeout__"
text = "Indítás %d másodperc múlva..."
left = 25%
top = 84%
width = 50%
height = 30
color = "#8B949E"
align = "center"
}
@@ -0,0 +1,96 @@
#!/bin/bash
#===============================================================================
# generate-grub-background.sh — build the Felhom GRUB boot background (scripts v1.22.0, R-38).
#
# Turns Viktor's square brand card (website/assets/og-image_2.png, 1017x1016) into a GRUB-friendly
# 1024x768 PNG. Runs INSIDE the felhom-iso-assistant container (needs ImageMagick); called by
# iso-repack.sh.
#
# THE LAYOUT, AND WHY:
#
# * 1024x768 canvas — gfxterm-safe. The stock PVE grub.cfg already asks for `gfxmode=1024x768`, so
# this is the mode the ISO's GRUB is known to get on real firmware. Anything larger risks a
# fallback to 800x600 and a scaled/cropped background.
#
# * The card is scaled to 500x500 and composited TOP-CENTERED (y=16). That deliberately leaves the
# bottom ~250px empty: it is where felhom-theme.txt positions the boot menu (top=70%) and the
# countdown label (top=84%). Menu text therefore never lands on the cloud/wordmark/tagline. If
# you change CARD or CARD_Y here, move `boot_menu.top` in felhom-theme.txt to match.
#
# * THE GRID. The card carries a subtle background grid (4px lines of #0D131A on #0D1117, every
# 131px) and Viktor asked for it to stay visible. Two things could destroy it: the downscale
# (handled — at 500/1017 the lines land at ~2px, still legible), and the letterbox fill. A flat
# navy fill would leave an obvious 500px square of grid floating in a plain field.
#
# So the grid is drawn across the WHOLE canvas first, PHASE-LOCKED to where the card's own grid
# will land, in the card's own line color — then the card is composited on top. Inside the card
# region the card's real grid shows; outside, the drawn continuation lines up exactly. The seam
# is invisible because the card's background (#0D1117) is also the canvas fill.
#
# The phase-lock math: source line centers are x=81.5+n*131, y=21.5+n*131 (measured, not guessed
# — sampled from og-image_2.png). Scale s=CARD/SRC_W maps them onto the canvas, offset by the
# card's origin. Line width scales the same way.
#
# Usage: generate-grub-background.sh <source.png> <out.png>
#===============================================================================
set -euo pipefail
SRC="${1:?source card PNG required}"
OUT="${2:?output PNG path required}"
# --- canvas ---------------------------------------------------------------------------------------
CW=1024; CH=768
BG="#0D1117" # the card's own background — the letterbox must be seamless, not merely "navy"
GRID="#0D131A" # the card's own grid line color (sampled)
# --- card placement (keep in sync with felhom-theme.txt boot_menu.top) ------------------------------
CARD=500; CARD_X=262; CARD_Y=16
# --- measured properties of og-image_2.png ----------------------------------------------------------
SRC_W=1017 # source width; the card is square (1017x1016)
PITCH=131 # grid pitch in source px
V0=81.5 # center of the first vertical grid line, source px
H0=21.5 # center of the first horizontal grid line, source px
LINE=4 # grid line width in source px
command -v magick >/dev/null && IM=magick || IM=convert
[[ -f "$SRC" ]] || { echo "generate-grub-background: source card not found: $SRC" >&2; exit 2; }
# Refuse a source whose geometry no longer matches the measured constants above — a silently swapped
# asset would misplace every grid line, and the result only shows up on a boot screen nobody re-checks.
GEOM="$($IM identify -format '%wx%h' "$SRC")"
[[ "$GEOM" == "1017x1016" ]] || {
echo "generate-grub-background: source card is ${GEOM}, expected 1017x1016." >&2
echo " The grid phase-lock constants (PITCH/V0/H0/LINE) were measured against that geometry." >&2
echo " Re-measure them for the new asset before changing this check." >&2
exit 3
}
S=$(awk -v c="$CARD" -v w="$SRC_W" 'BEGIN{printf "%.6f", c/w}') # card scale factor
P=$(awk -v p="$PITCH" -v s="$S" 'BEGIN{printf "%.4f", p*s}') # canvas grid pitch
LW=$(awk -v l="$LINE" -v s="$S" 'BEGIN{printf "%.2f", l*s}') # canvas grid line width
# Walk n outward far enough to cover the canvas in both axes from the card-anchored origin.
draw=""
for n in $(seq -20 40); do
x=$(awk -v a="$CARD_X" -v v="$V0" -v s="$S" -v p="$P" -v n="$n" 'BEGIN{printf "%.2f", a+v*s+n*p}')
if awk -v x="$x" -v w="$CW" 'BEGIN{exit !(x>-2 && x<w+2)}'; then
draw="$draw line $x,0 $x,$CH"
fi
y=$(awk -v a="$CARD_Y" -v v="$H0" -v s="$S" -v p="$P" -v n="$n" 'BEGIN{printf "%.2f", a+v*s+n*p}')
if awk -v y="$y" -v h="$CH" 'BEGIN{exit !(y>-2 && y<h+2)}'; then
draw="$draw line 0,$y $CW,$y"
fi
done
[[ -n "$draw" ]] || { echo "generate-grub-background: grid draw list came out empty" >&2; exit 4; }
# PNG24 (no palette, no alpha): GRUB's png module reads plain 8-bit RGB reliably; an indexed or
# 16-bit PNG is where "the background silently doesn't render" comes from.
$IM -size "${CW}x${CH}" xc:"$BG" \
-stroke "$GRID" -strokewidth "$LW" -draw "$draw" -stroke none \
\( "$SRC" -resize "${CARD}x${CARD}!" \) -geometry "+${CARD_X}+${CARD_Y}" -composite \
-depth 8 "PNG24:$OUT"
[[ -s "$OUT" ]] || { echo "generate-grub-background: produced no output" >&2; exit 5; }
OGEOM="$($IM identify -format '%wx%h %[channels] %[depth]' "$OUT")"
echo "generate-grub-background: $OUT ($OGEOM, $(stat -c%s "$OUT") bytes)"
+76
View File
@@ -0,0 +1,76 @@
# Felhom ISO — GRUB menu (scripts v1.22.0, R-38 GRUB slice). GENERATED by iso-repack.sh; the stock
# PVE grub.cfg is REPLACED by this file at repack time.
#
# TWO jobs, one file:
#
# 1. BRANDING — a Felhom gfxmenu theme (felhomtheme/) over a 1024x768 card built from the website's
# og-image_2.png. The stock `set theme=/boot/grub/pvetheme/theme.txt` is gone.
#
# 2. SAFETY — exactly ONE entry is exposed. The stock menu offers Graphical / Terminal UI / serial,
# plus an "Advanced Options" submenu with nomodeset, three debug variants, Rescue Boot, memtest
# and UEFI firmware settings. Every one of those reaches the MANUAL installer, whose first
# question is which disk to wipe. A customer — or their helpful nephew — must not be able to get
# there from a boot menu. They are not hidden, they are NOT EMITTED.
#
# The `linux` / `initrd` lines below are lifted VERBATIM by iso-repack.sh from the stock
# 'Install Proxmox VE (Automated)' entry of the ISO being repacked, so a PVE version bump that
# changes the kernel path or the append line is tracked automatically instead of silently diverging
# from a copy frozen here. iso-repack.sh fails the build if it cannot find them, and asserts the
# append line still carries `proxmox-start-auto-installer` — the flag that makes the install
# unattended. Boot behavior is therefore byte-identical to v1.21.0; only the menu around it changed.
insmod gzio
insmod iso9660
insmod png
insmod gfxmenu
if [ x$feature_default_font_path = xy ] ; then
font=unicode
else
font=$prefix/unicode.pf2
fi
# Matches the background canvas exactly (1024x768). 800x600/640x480 are fallbacks for firmware that
# refuses the preferred mode — the theme is percentage-positioned, so it degrades cleanly.
set gfxmode=1024x768,800x600,640x480
set gfxpayload=1024x768
if loadfont $font; then
if test "${grub_platform}" = "efi"; then
insmod efi_gop
insmod efi_uga
fi
insmod video_bochs
insmod video_cirrus
insmod all_video
insmod gfxterm
set theme=/boot/grub/felhomtheme/theme.txt
export theme
terminal_input console
terminal_output gfxterm
fi
# Serial stays available for operator/nested-canary debugging (the stock cfg does this too). What we
# do NOT do is the stock's `set show_serial_entry=y` — that would add a fourth menu entry.
insmod serial
insmod usbserial_common
insmod usbserial_ftdi
insmod usbserial_pl2303
insmod usbserial_usbdebug
if serial --unit=0 --speed=115200; then
terminal_input --append serial
terminal_output --append serial
fi
# Short and decisive: one entry, default, 5s. Note `timeout_style` (underscore) — the stock cfg
# writes `timeout-style`, which GRUB does not recognise as a variable name at all.
set timeout_style=menu
set timeout=5
set default=0
menuentry 'Felhom telepítés' --class felhom --class os {
echo 'A Felhom telepítése indul...'
@@LINUX@@
echo 'Rendszerbetöltő betöltése...'
@@INITRD@@
}