fix: UEFI boot fallback — search by file when label fails
The embedded GRUB EFI config only searched by volume label ARCHIPELAGO. Some UEFI firmware presents USB devices differently, causing the search to fail and GRUB to stall. Added fallbacks: 1. search --file /archipelago/auto-install.sh (known ISO file) 2. Fall back to $cmdpath (EFI partition itself) 3. Use configfile before normal for explicit config loading 4. Added search_fs_file module to grub-mkstandalone Also added same fallback to the main ISO grub.cfg. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6e356412b8
commit
e9903e7b4b
@ -561,9 +561,10 @@ export INSTALLER_STARTED=1
|
|||||||
sleep 1
|
sleep 1
|
||||||
clear
|
clear
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\033[1;37m a r c h i p e l a g o\033[0m"
|
echo -e "\033[38;5;208m ▄▀█ █▀▄ █▀▀ █ █ █ █▀█ █▀▀ █ ▄▀█ █▀▀ █▀█\033[0m"
|
||||||
echo -e "\033[1;33m ━━━━━━━━━━━━━━━━━━━━━\033[0m"
|
echo -e "\033[38;5;208m █▀█ █▀▄ █ █▀█ █ █▀▀ ██▀ █ █▀█ █ █ █ █\033[0m"
|
||||||
echo -e "\033[37m automatic installer\033[0m"
|
echo -e "\033[38;5;208m ▀ ▀ ▀ ▀ ▀▀▀ ▀ ▀ ▀ ▀ ▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀\033[0m"
|
||||||
|
echo -e " \033[38;5;130mbitcoin node os\033[0m"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
BOOT_MEDIA=""
|
BOOT_MEDIA=""
|
||||||
@ -687,19 +688,38 @@ mksquashfs /installer /output/filesystem.squashfs -comp xz -Xbcj x86 -noappend -
|
|||||||
echo " [container] Building GRUB EFI image..."
|
echo " [container] Building GRUB EFI image..."
|
||||||
cat > /tmp/grub-embed.cfg <<GRUBEMBED
|
cat > /tmp/grub-embed.cfg <<GRUBEMBED
|
||||||
insmod part_gpt
|
insmod part_gpt
|
||||||
|
insmod part_msdos
|
||||||
insmod fat
|
insmod fat
|
||||||
insmod iso9660
|
insmod iso9660
|
||||||
|
insmod search
|
||||||
insmod search_label
|
insmod search_label
|
||||||
|
insmod search_fs_file
|
||||||
insmod normal
|
insmod normal
|
||||||
insmod linux
|
insmod linux
|
||||||
insmod all_video
|
insmod all_video
|
||||||
|
|
||||||
|
# Try label first (standard path)
|
||||||
search --no-floppy --set=root --label ARCHIPELAGO
|
search --no-floppy --set=root --label ARCHIPELAGO
|
||||||
|
|
||||||
|
# Fallback: search for a known file on the ISO
|
||||||
|
if [ -z "\$root" ]; then
|
||||||
|
search --no-floppy --set=root --file /archipelago/auto-install.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback: try configfile from the EFI partition path
|
||||||
|
if [ -z "\$root" ]; then
|
||||||
|
set root=\$cmdpath
|
||||||
|
fi
|
||||||
|
|
||||||
set prefix=(\$root)/boot/grub
|
set prefix=(\$root)/boot/grub
|
||||||
|
configfile (\$root)/boot/grub/grub.cfg
|
||||||
|
|
||||||
|
# If configfile fails, try normal
|
||||||
normal
|
normal
|
||||||
GRUBEMBED
|
GRUBEMBED
|
||||||
|
|
||||||
grub-mkstandalone -O x86_64-efi \
|
grub-mkstandalone -O x86_64-efi \
|
||||||
--modules="part_gpt part_msdos fat iso9660 search search_label normal linux all_video font gfxterm configfile echo cat ls test true loopback png" \
|
--modules="part_gpt part_msdos fat iso9660 search search_label search_fs_file normal linux all_video font gfxterm configfile echo cat ls test true loopback png" \
|
||||||
--locales="" \
|
--locales="" \
|
||||||
--themes="" \
|
--themes="" \
|
||||||
--fonts="" \
|
--fonts="" \
|
||||||
@ -1405,81 +1425,56 @@ case "$(uname -m)" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Colors (basic ANSI — works on bare-metal Linux console)
|
# Colors — 256-color ANSI (works on Linux fbcon console)
|
||||||
|
ORANGE=$'\033[38;5;208m'
|
||||||
|
ORANGE_DIM=$'\033[38;5;130m'
|
||||||
|
ORANGE_BRIGHT=$'\033[38;5;214m'
|
||||||
RED=$'\033[31m'
|
RED=$'\033[31m'
|
||||||
GREEN=$'\033[32m'
|
GREEN=$'\033[32m'
|
||||||
YELLOW=$'\033[1;33m'
|
|
||||||
ORANGE=$'\033[1;33m'
|
|
||||||
DIM=$'\033[37m'
|
|
||||||
CYAN=$'\033[36m'
|
|
||||||
WHITE=$'\033[1;37m'
|
WHITE=$'\033[1;37m'
|
||||||
|
DIM=$'\033[38;5;242m'
|
||||||
|
DIMMER=$'\033[38;5;238m'
|
||||||
NC=$'\033[0m'
|
NC=$'\033[0m'
|
||||||
|
BOLD=$'\033[1m'
|
||||||
|
|
||||||
# Adaptive centering
|
# Fixed left-margin layout (no more mixed centering)
|
||||||
TW=$(tput cols 2>/dev/null || echo 60)
|
TW=$(tput cols 2>/dev/null || echo 60)
|
||||||
[ "$TW" -gt 120 ] && TW=120
|
[ "$TW" -gt 100 ] && TW=100
|
||||||
cc() { local s=$(echo -e "$1" | sed 's/\x1b\[[0-9;]*m//g'); local p=$(( (TW - ${#s}) / 2 )); [ $p -lt 0 ] && p=0; printf "%*s" "$p" ""; echo -e "$1"; }
|
PAD=$(( (TW - 50) / 2 ))
|
||||||
hrule() { local len=$((TW > 50 ? 50 : TW - 4)); local hr=""; for i in $(seq 1 $len); do hr="${hr}─"; done; cc "${DIM}${hr}${NC}"; }
|
[ "$PAD" -lt 0 ] && PAD=0
|
||||||
|
PADS=$(printf "%*s" "$PAD" "")
|
||||||
|
|
||||||
box() {
|
p() { printf "%s%b\n" "$PADS" "$1"; }
|
||||||
local bw=$((TW > 52 ? 52 : TW - 4))
|
hrule() { local hr=""; for i in $(seq 1 48); do hr="${hr}*"; done; p "${ORANGE_DIM}${hr}${NC}"; }
|
||||||
local inner=$((bw - 2))
|
|
||||||
local top="╭"; local bot="╰"
|
|
||||||
for i in $(seq 1 $inner); do top="${top}─"; bot="${bot}─"; done
|
|
||||||
top="${top}╮"; bot="${bot}╯"
|
|
||||||
cc "${DIM}${top}${NC}"
|
|
||||||
}
|
|
||||||
boxend() {
|
|
||||||
local bw=$((TW > 52 ? 52 : TW - 4))
|
|
||||||
local inner=$((bw - 2))
|
|
||||||
local bot="╰"
|
|
||||||
for i in $(seq 1 $inner); do bot="${bot}─"; done
|
|
||||||
bot="${bot}╯"
|
|
||||||
cc "${DIM}${bot}${NC}"
|
|
||||||
}
|
|
||||||
boxline() {
|
|
||||||
local bw=$((TW > 52 ? 52 : TW - 4))
|
|
||||||
local inner=$((bw - 2))
|
|
||||||
local stripped=$(echo -e "$1" | sed 's/\x1b\[[0-9;]*m//g')
|
|
||||||
local pad=$((inner - ${#stripped}))
|
|
||||||
[ $pad -lt 0 ] && pad=0
|
|
||||||
local right=""
|
|
||||||
for i in $(seq 1 $pad); do right="${right} "; done
|
|
||||||
cc "${DIM}│${NC} $1${right}${DIM}│${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# TUI helpers — Claude Code-inspired status display
|
# Phase display
|
||||||
STEP=0
|
STEP=0
|
||||||
TOTAL_STEPS=8
|
TOTAL_STEPS=8
|
||||||
step() {
|
step() {
|
||||||
STEP=$((STEP + 1))
|
STEP=$((STEP + 1))
|
||||||
echo ""
|
echo ""
|
||||||
cc "${WHITE}[$STEP/$TOTAL_STEPS]${NC} ${DIM}$1${NC}"
|
p "${ORANGE}[$STEP/$TOTAL_STEPS] $1${NC}"
|
||||||
}
|
}
|
||||||
ok() { cc " ${GREEN}$1${NC}"; }
|
ok() { p " ${ORANGE_BRIGHT}✓ $1${NC}"; }
|
||||||
warn() { cc " ${YELLOW}$1${NC}"; }
|
warn() { p " ${ORANGE}⚠ $1${NC}"; }
|
||||||
fail() { cc " ${RED}$1${NC}"; }
|
fail() { p " ${RED}✗ $1${NC}"; }
|
||||||
spinner() {
|
spinner() {
|
||||||
local pid=$1 msg=$2
|
local pid=$1 msg=$2
|
||||||
local frames='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
|
local frames='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
|
||||||
local i=0
|
local i=0
|
||||||
while kill -0 "$pid" 2>/dev/null; do
|
while kill -0 "$pid" 2>/dev/null; do
|
||||||
printf "\r ${DIM}%s %s${NC}" "${frames:i%10:1}" "$msg"
|
printf "\r%s %b%s %s%b" "$PADS" "$ORANGE" "${frames:i%10:1}" "$msg" "$NC"
|
||||||
i=$((i + 1))
|
i=$((i + 1))
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
done
|
done
|
||||||
printf "\r ${GREEN}✓ %s${NC}\n" "$msg"
|
printf "\r%s %b✓ %s%b\n" "$PADS" "$ORANGE_BRIGHT" "$msg" "$NC"
|
||||||
}
|
}
|
||||||
|
|
||||||
clear
|
clear
|
||||||
echo ""
|
echo -e " ${ORANGE}▄▀█ █▀▄ █▀▀ █ █ █ █▀█ █▀▀ █ ▄▀█ █▀▀ █▀█${NC}"
|
||||||
box
|
echo -e " ${ORANGE}█▀█ █▀▄ █ █▀█ █ █▀▀ ██▀ █ █▀█ █ █ █ █${NC}"
|
||||||
boxline ""
|
echo -e " ${ORANGE}▀ ▀ ▀ ▀ ▀▀▀ ▀ ▀ ▀ ▀ ▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀${NC}"
|
||||||
boxline "${WHITE}a r c h i p e l a g o${NC}"
|
echo -e " ${ORANGE_DIM}bitcoin node os${NC}"
|
||||||
boxline "${ORANGE}━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
||||||
boxline "${DIM}automatic installation${NC}"
|
|
||||||
boxline ""
|
|
||||||
boxend
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Check required tools are present (should be bundled in ISO)
|
# Check required tools are present (should be bundled in ISO)
|
||||||
@ -1582,9 +1577,9 @@ ok "$TARGET_DISK ($TARGET_SIZE)"
|
|||||||
echo ""
|
echo ""
|
||||||
hrule
|
hrule
|
||||||
echo ""
|
echo ""
|
||||||
cc "${RED}all data on $TARGET_DISK will be erased${NC}"
|
p "${ORANGE} ⚠ all data on $TARGET_DISK will be erased${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
cc "${DIM}press enter to install | ctrl+c to cancel${NC}"
|
p "${ORANGE_DIM} press enter to install | ctrl+c to cancel${NC}"
|
||||||
read -s
|
read -s
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
@ -1631,7 +1626,7 @@ mkfs.ext4 -F -L archipelago "$ROOT_PART"
|
|||||||
# Mount root + extract rootfs (need cryptsetup from rootfs for LUKS)
|
# Mount root + extract rootfs (need cryptsetup from rootfs for LUKS)
|
||||||
ok "Partitions created"
|
ok "Partitions created"
|
||||||
echo ""
|
echo ""
|
||||||
cc "${DIM}Mounting filesystems...${NC}"
|
p " ${ORANGE_DIM}Mounting filesystems...${NC}"
|
||||||
mkdir -p /mnt/target
|
mkdir -p /mnt/target
|
||||||
mount "$ROOT_PART" /mnt/target
|
mount "$ROOT_PART" /mnt/target
|
||||||
mkdir -p /mnt/target/boot/efi
|
mkdir -p /mnt/target/boot/efi
|
||||||
@ -1877,31 +1872,29 @@ if [ -t 0 ] && [ -z "$ARCHIPELAGO_WELCOMED" ]; then
|
|||||||
done
|
done
|
||||||
|
|
||||||
O='\033[38;5;208m'
|
O='\033[38;5;208m'
|
||||||
D='\033[38;5;242m'
|
OD='\033[38;5;130m'
|
||||||
|
W='\033[1;37m'
|
||||||
N='\033[0m'
|
N='\033[0m'
|
||||||
|
|
||||||
clear
|
clear
|
||||||
echo ""
|
echo -e " ${O}▄▀█ █▀▄ █▀▀ █ █ █ █▀█ █▀▀ █ ▄▀█ █▀▀ █▀█${N}"
|
||||||
echo -e " ${O}█▀█ █▀▄ █▀▀ █ █ █ █▀▄▀█ █▀▀ █ █▀█ █▀▀ █▀█${N}"
|
echo -e " ${O}█▀█ █▀▄ █ █▀█ █ █▀▀ ██▀ █ █▀█ █ █ █ █${N}"
|
||||||
echo -e " ${O}█▀█ █▀▄ █ █▀█ █ █ ▀ █ ██▀ █ █▀█ █ █ █ █${N}"
|
echo -e " ${O}▀ ▀ ▀ ▀ ▀▀▀ ▀ ▀ ▀ ▀ ▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀${N}"
|
||||||
echo -e " ${O}▀ ▀ ▀ ▀ ▀▀▀ ▀ ▀ ▀ ▀ ▀ ▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀${N}"
|
echo -e " ${OD}bitcoin node os${N}"
|
||||||
echo -e " ${D}bitcoin node os${N}"
|
|
||||||
echo ""
|
|
||||||
if [ -n "$IP" ]; then
|
if [ -n "$IP" ]; then
|
||||||
echo -e " ${D}web ui${N} http://$IP"
|
echo -e " ${W}web ui http://$IP${N}"
|
||||||
echo -e " ${D}ssh${N} archipelago@$IP"
|
echo -e " ${W}ssh archipelago@$IP${N}"
|
||||||
echo -e " ${D}password${N} archipelago (SSH) / password123 (Web)"
|
echo -e " ${W}password archipelago (SSH) / password123 (Web)${N}"
|
||||||
else
|
else
|
||||||
echo -e " ${D}Waiting for network...${N}"
|
echo -e " ${OD}Waiting for network...${N}"
|
||||||
fi
|
fi
|
||||||
echo ""
|
|
||||||
if [ -b /dev/mapper/archipelago-data ]; then
|
if [ -b /dev/mapper/archipelago-data ]; then
|
||||||
echo -e " ${D}storage${N} LUKS2 encrypted"
|
echo -e " ${OD}storage LUKS2 encrypted${N}"
|
||||||
fi
|
fi
|
||||||
if systemctl is-active archipelago-kiosk.service >/dev/null 2>&1; then
|
if systemctl is-active archipelago-kiosk.service >/dev/null 2>&1; then
|
||||||
echo -e " ${D}display${N} Kiosk active (Ctrl+Alt+F1 for terminal)"
|
echo -e " ${OD}display Kiosk active (Ctrl+Alt+F1 for terminal)${N}"
|
||||||
else
|
else
|
||||||
echo -e " ${D}display${N} Console (Ctrl+Alt+F7 for kiosk)"
|
echo -e " ${OD}display Console (Ctrl+Alt+F7 for kiosk)${N}"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
@ -2533,25 +2526,20 @@ cryptsetup close archipelago-data 2>/dev/null || true
|
|||||||
umount /mnt/target 2>/dev/null || true
|
umount /mnt/target 2>/dev/null || true
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
echo -e " ${ORANGE}▄▀█ █▀▄ █▀▀ █ █ █ █▀█ █▀▀ █ ▄▀█ █▀▀ █▀█${NC}"
|
||||||
|
echo -e " ${ORANGE}█▀█ █▀▄ █ █▀█ █ █▀▀ ██▀ █ █▀█ █ █ █ █${NC}"
|
||||||
|
echo -e " ${ORANGE}▀ ▀ ▀ ▀ ▀▀▀ ▀ ▀ ▀ ▀ ▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀${NC}"
|
||||||
|
echo -e " ${ORANGE_DIM}bitcoin node os${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
box
|
p "${ORANGE_BRIGHT} ✓ Installation Complete${NC}"
|
||||||
boxline ""
|
|
||||||
boxline "${WHITE}A R C H I P E L A G O${NC}"
|
|
||||||
boxline "${GREEN}━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
||||||
boxline "${GREEN}Installation Complete${NC}"
|
|
||||||
boxline ""
|
|
||||||
boxend
|
|
||||||
echo ""
|
echo ""
|
||||||
cc "${DIM}After reboot, open the Web UI from any device on your network.${NC}"
|
p "${ORANGE_DIM} After reboot, access from any device:${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
cc "${DIM}Web UI:${NC} ${WHITE}http://<this machine's IP>${NC}"
|
p "${ORANGE} http://<this machine's IP>${NC}"
|
||||||
cc "${DIM}SSH:${NC} ${DIM}ssh archipelago@<IP>${NC}"
|
|
||||||
cc "${DIM}Password:${NC} ${DIM}archipelago${NC}"
|
|
||||||
cc "${DIM}Web Login:${NC} ${DIM}password123${NC}"
|
|
||||||
echo ""
|
echo ""
|
||||||
cc "${DIM}Pre-loaded apps (start via Web UI):${NC}"
|
p "${WHITE} SSH ssh archipelago@<IP>${NC}"
|
||||||
cc "${DIM}Bitcoin Knots, LND, Home Assistant,${NC}"
|
p "${WHITE} Password archipelago${NC}"
|
||||||
cc "${DIM}BTCPay Server, Mempool, Nostr Relay${NC}"
|
p "${WHITE} Web Login password123${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
hrule
|
hrule
|
||||||
echo ""
|
echo ""
|
||||||
@ -2562,19 +2550,19 @@ echo 1 > /proc/sys/kernel/printk 2>/dev/null || true
|
|||||||
cat > /tmp/archipelago-reboot.sh <<'REBOOTSCRIPT'
|
cat > /tmp/archipelago-reboot.sh <<'REBOOTSCRIPT'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# This script runs from tmpfs — safe after USB removal
|
# This script runs from tmpfs — safe after USB removal
|
||||||
TW=$(tput cols 2>/dev/null || echo 60)
|
O=$'\033[38;5;208m'
|
||||||
[ "$TW" -gt 120 ] && TW=120
|
OD=$'\033[38;5;130m'
|
||||||
cc() { local s=$(echo -e "$1" | sed 's/\x1b\[[0-9;]*m//g'); local p=$(( (TW - ${#s}) / 2 )); [ $p -lt 0 ] && p=0; printf "%*s" "$p" ""; echo -e "$1"; }
|
N=$'\033[0m'
|
||||||
|
|
||||||
cc "\033[1;33m>>> REMOVE THE USB DRIVE NOW <<<\033[0m"
|
echo -e " ${O}>>> REMOVE THE USB DRIVE NOW <<<${N}"
|
||||||
echo ""
|
echo ""
|
||||||
cc "\033[37mPress Enter to reboot (or wait 30 seconds)\033[0m"
|
echo -e " ${OD}Press Enter to reboot (or wait 30 seconds)${N}"
|
||||||
|
|
||||||
# Wait for Enter or timeout
|
# Wait for Enter or timeout
|
||||||
read -t 30 -s 2>/dev/null || true
|
read -t 30 -s 2>/dev/null || true
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
cc "\033[37mRebooting...\033[0m"
|
echo -e " ${OD}Rebooting...${N}"
|
||||||
sleep 1
|
sleep 1
|
||||||
reboot -f
|
reboot -f
|
||||||
REBOOTSCRIPT
|
REBOOTSCRIPT
|
||||||
@ -2628,8 +2616,15 @@ insmod part_msdos
|
|||||||
insmod fat
|
insmod fat
|
||||||
insmod iso9660
|
insmod iso9660
|
||||||
insmod all_video
|
insmod all_video
|
||||||
|
insmod search
|
||||||
|
insmod search_label
|
||||||
|
insmod search_fs_file
|
||||||
|
|
||||||
|
# Find boot media — try label first, then known file fallback
|
||||||
search --no-floppy --set=root --label ARCHIPELAGO
|
search --no-floppy --set=root --label ARCHIPELAGO
|
||||||
|
if [ -z "$root" ]; then
|
||||||
|
search --no-floppy --set=root --file /archipelago/auto-install.sh
|
||||||
|
fi
|
||||||
|
|
||||||
set timeout=5
|
set timeout=5
|
||||||
set default=0
|
set default=0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user