mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-29 15:37:03 +00:00
feat(multiboot): Add multi-architecture boot system with shared data
Create a multi-boot storage system for Pi Zero Eye Remote that supports: - ARM64: ESPRESSObin/MOCHAbin via U-Boot boot.scr - AMD64: Any x86_64 UEFI system via GRUB - Shared data: Cross-architecture application data on partition 4 Partition layout (16GB+ recommended): - P1: EFI/FAT32 (512MB) - Boot files for both architectures - P2: ext4 (3GB) - ARM64 rootfs - P3: ext4 (3GB) - AMD64 rootfs - P4: ext4 (remaining) - Shared SecuBox configs, state, logs Features: - Automatic bind mounts for /etc/secubox, /var/lib/secubox, /srv/secubox - eMMC flasher image included in EFI partition - Debootstrap-based AMD64 rootfs builder - U-Boot script with USB/MMC detection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
52c6b42665
commit
5cf69c0ce1
100
image/multiboot/README.md
Normal file
100
image/multiboot/README.md
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# SecuBox Multi-Boot Storage System
|
||||
|
||||
## Overview
|
||||
|
||||
Multi-architecture bootable storage for Pi Zero Eye Remote that supports:
|
||||
- **ARM64**: ESPRESSObin/MOCHAbin via U-Boot
|
||||
- **AMD64**: Any x86_64 UEFI system
|
||||
- **Shared Data**: Cross-architecture application data
|
||||
|
||||
## Partition Layout (16GB+ recommended)
|
||||
|
||||
| Part | Type | Size | Mount | Purpose |
|
||||
|------|------|------|-------|---------|
|
||||
| 1 | EFI (FAT32) | 512MB | /boot/efi | UEFI + U-Boot boot files |
|
||||
| 2 | ext4 | 3GB | / (ARM64) | SecuBox ARM64 live rootfs |
|
||||
| 3 | ext4 | 3GB | / (AMD64) | SecuBox AMD64 live rootfs |
|
||||
| 4 | ext4 | 8GB+ | /srv/data | Shared application data |
|
||||
|
||||
## Boot Files (Partition 1)
|
||||
|
||||
```
|
||||
/boot/efi/
|
||||
├── EFI/
|
||||
│ └── BOOT/
|
||||
│ ├── BOOTX64.EFI # GRUB for AMD64
|
||||
│ └── grub.cfg # GRUB config
|
||||
├── Image # ARM64 kernel
|
||||
├── initrd.img # ARM64 initramfs
|
||||
├── dtbs/ # ARM64 device trees
|
||||
├── boot.scr # U-Boot script (ARM64)
|
||||
├── grub/
|
||||
│ └── grub.cfg # GRUB config (AMD64)
|
||||
├── vmlinuz # AMD64 kernel
|
||||
├── initrd-amd64.img # AMD64 initramfs
|
||||
└── flash/
|
||||
└── secubox-emmc.img.gz # eMMC flasher image
|
||||
```
|
||||
|
||||
## Shared Data Structure (Partition 4)
|
||||
|
||||
```
|
||||
/srv/data/
|
||||
├── etc/
|
||||
│ └── secubox/ # Shared configs
|
||||
│ ├── api.toml
|
||||
│ ├── users.json
|
||||
│ ├── tls/
|
||||
│ └── modules/
|
||||
├── var/
|
||||
│ └── lib/
|
||||
│ └── secubox/ # Application state
|
||||
│ ├── crowdsec/
|
||||
│ ├── haproxy/
|
||||
│ ├── wireguard/
|
||||
│ └── dpi/
|
||||
├── srv/
|
||||
│ └── secubox/ # Service data
|
||||
│ ├── mitmproxy/
|
||||
│ ├── nginx/
|
||||
│ └── certs/
|
||||
└── log/
|
||||
└── secubox/ # Shared logs
|
||||
```
|
||||
|
||||
## Boot Flow
|
||||
|
||||
### ARM64 (ESPRESSObin)
|
||||
1. U-Boot loads `boot.scr` from partition 1
|
||||
2. Kernel + initrd from partition 1
|
||||
3. Rootfs from partition 2
|
||||
4. Mounts partition 4 as /srv/data
|
||||
5. Bind-mounts shared paths
|
||||
|
||||
### AMD64 (UEFI)
|
||||
1. UEFI loads GRUB from EFI/BOOT/BOOTX64.EFI
|
||||
2. GRUB loads vmlinuz + initrd from partition 1
|
||||
3. Rootfs from partition 3
|
||||
4. Mounts partition 4 as /srv/data
|
||||
5. Bind-mounts shared paths
|
||||
|
||||
### eMMC Flash
|
||||
From either architecture:
|
||||
```bash
|
||||
secubox-flash-emmc # Interactive
|
||||
# or
|
||||
gunzip -c /boot/efi/flash/secubox-emmc.img.gz | dd of=/dev/mmcblk0 bs=4M status=progress
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
# Build complete multi-boot image
|
||||
./build-multiboot.sh --size 16G --output secubox-multiboot.img
|
||||
|
||||
# Build AMD64 rootfs only
|
||||
./build-amd64-rootfs.sh --output rootfs-amd64/
|
||||
|
||||
# Build ARM64 rootfs only
|
||||
./build-arm64-rootfs.sh --output rootfs-arm64/
|
||||
```
|
||||
295
image/multiboot/build-amd64-rootfs.sh
Executable file
295
image/multiboot/build-amd64-rootfs.sh
Executable file
|
|
@ -0,0 +1,295 @@
|
|||
#!/usr/bin/env bash
|
||||
# SecuBox AMD64 Live Rootfs Builder
|
||||
# Creates Debian bookworm AMD64 rootfs with SecuBox packages
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
OUTPUT_DIR=""
|
||||
MINIMAL=false
|
||||
INCLUDE_DESKTOP=false
|
||||
MIRROR="http://deb.debian.org/debian"
|
||||
SECUBOX_REPO="https://apt.secubox.in"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [OPTIONS]
|
||||
|
||||
Build SecuBox AMD64 rootfs
|
||||
|
||||
Options:
|
||||
-o, --output DIR Output directory for rootfs
|
||||
--minimal Minimal installation (no SecuBox packages)
|
||||
--desktop Include desktop environment
|
||||
--mirror URL Debian mirror (default: $MIRROR)
|
||||
-h, --help Show this help
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
log() { echo "[$(date '+%H:%M:%S')] $*"; }
|
||||
err() { echo "[ERROR] $*" >&2; exit 1; }
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-o|--output) OUTPUT_DIR="$2"; shift 2 ;;
|
||||
--minimal) MINIMAL=true; shift ;;
|
||||
--desktop) INCLUDE_DESKTOP=true; shift ;;
|
||||
--mirror) MIRROR="$2"; shift 2 ;;
|
||||
-h|--help) usage ;;
|
||||
*) err "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$OUTPUT_DIR" ]] && err "Output directory required (-o)"
|
||||
}
|
||||
|
||||
check_deps() {
|
||||
local deps=(debootstrap chroot)
|
||||
for cmd in "${deps[@]}"; do
|
||||
command -v "$cmd" &>/dev/null || err "Missing: $cmd"
|
||||
done
|
||||
[[ $EUID -eq 0 ]] || err "Must run as root"
|
||||
}
|
||||
|
||||
bootstrap_rootfs() {
|
||||
log "Bootstrapping Debian bookworm AMD64..."
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
debootstrap --arch=amd64 \
|
||||
--include=systemd,systemd-sysv,dbus,locales,apt-transport-https,ca-certificates,curl,gnupg \
|
||||
bookworm "$OUTPUT_DIR" "$MIRROR"
|
||||
}
|
||||
|
||||
configure_rootfs() {
|
||||
log "Configuring rootfs..."
|
||||
|
||||
# Set hostname
|
||||
echo "secubox-amd64" > "$OUTPUT_DIR/etc/hostname"
|
||||
|
||||
# Configure hosts
|
||||
cat > "$OUTPUT_DIR/etc/hosts" <<EOF
|
||||
127.0.0.1 localhost
|
||||
127.0.1.1 secubox-amd64
|
||||
|
||||
::1 localhost ip6-localhost ip6-loopback
|
||||
ff02::1 ip6-allnodes
|
||||
ff02::2 ip6-allrouters
|
||||
EOF
|
||||
|
||||
# Configure locales
|
||||
echo "en_US.UTF-8 UTF-8" > "$OUTPUT_DIR/etc/locale.gen"
|
||||
chroot "$OUTPUT_DIR" locale-gen
|
||||
|
||||
# Configure timezone
|
||||
ln -sf /usr/share/zoneinfo/UTC "$OUTPUT_DIR/etc/localtime"
|
||||
|
||||
# Configure apt sources
|
||||
cat > "$OUTPUT_DIR/etc/apt/sources.list" <<EOF
|
||||
deb $MIRROR bookworm main contrib non-free non-free-firmware
|
||||
deb $MIRROR bookworm-updates main contrib non-free non-free-firmware
|
||||
deb http://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware
|
||||
EOF
|
||||
|
||||
# Configure network
|
||||
cat > "$OUTPUT_DIR/etc/network/interfaces" <<EOF
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet dhcp
|
||||
EOF
|
||||
|
||||
# Create fstab
|
||||
cat > "$OUTPUT_DIR/etc/fstab" <<EOF
|
||||
# <file system> <mount point> <type> <options> <dump> <pass>
|
||||
LABEL=secubox-amd64 / ext4 errors=remount-ro 0 1
|
||||
LABEL=SECUBOX-EFI /boot/efi vfat umask=0077 0 1
|
||||
EOF
|
||||
}
|
||||
|
||||
install_kernel() {
|
||||
log "Installing Linux kernel..."
|
||||
|
||||
chroot "$OUTPUT_DIR" apt-get update
|
||||
chroot "$OUTPUT_DIR" apt-get install -y \
|
||||
linux-image-amd64 \
|
||||
linux-headers-amd64 \
|
||||
firmware-linux \
|
||||
firmware-linux-nonfree
|
||||
}
|
||||
|
||||
install_base_packages() {
|
||||
log "Installing base packages..."
|
||||
|
||||
chroot "$OUTPUT_DIR" apt-get install -y \
|
||||
openssh-server \
|
||||
sudo \
|
||||
vim \
|
||||
nano \
|
||||
htop \
|
||||
tmux \
|
||||
git \
|
||||
wget \
|
||||
net-tools \
|
||||
iproute2 \
|
||||
iputils-ping \
|
||||
dnsutils \
|
||||
tcpdump \
|
||||
iptables \
|
||||
nftables \
|
||||
nginx \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
python3-uvicorn \
|
||||
python3-fastapi \
|
||||
python3-jose \
|
||||
python3-httpx \
|
||||
python3-psutil \
|
||||
python3-jinja2
|
||||
}
|
||||
|
||||
add_secubox_repo() {
|
||||
if [[ "$MINIMAL" == "true" ]]; then
|
||||
log "Skipping SecuBox repo (minimal mode)"
|
||||
return
|
||||
fi
|
||||
|
||||
log "Adding SecuBox repository..."
|
||||
|
||||
# Add SecuBox GPG key
|
||||
mkdir -p "$OUTPUT_DIR/etc/apt/keyrings"
|
||||
curl -fsSL "${SECUBOX_REPO}/gpg.key" | gpg --dearmor -o "$OUTPUT_DIR/etc/apt/keyrings/secubox.gpg" 2>/dev/null || true
|
||||
|
||||
# Add SecuBox repo
|
||||
cat > "$OUTPUT_DIR/etc/apt/sources.list.d/secubox.list" <<EOF
|
||||
deb [signed-by=/etc/apt/keyrings/secubox.gpg] ${SECUBOX_REPO} bookworm main
|
||||
EOF
|
||||
|
||||
chroot "$OUTPUT_DIR" apt-get update || true
|
||||
}
|
||||
|
||||
install_secubox_packages() {
|
||||
if [[ "$MINIMAL" == "true" ]]; then
|
||||
log "Skipping SecuBox packages (minimal mode)"
|
||||
return
|
||||
fi
|
||||
|
||||
log "Installing SecuBox packages..."
|
||||
|
||||
# Install core SecuBox packages
|
||||
chroot "$OUTPUT_DIR" apt-get install -y \
|
||||
secubox-core \
|
||||
secubox-hub \
|
||||
secubox-haproxy \
|
||||
secubox-crowdsec \
|
||||
secubox-system \
|
||||
secubox-hardening \
|
||||
secubox-ipblock \
|
||||
|| log "WARNING: Some SecuBox packages failed to install"
|
||||
}
|
||||
|
||||
install_desktop() {
|
||||
if [[ "$INCLUDE_DESKTOP" != "true" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
log "Installing desktop environment..."
|
||||
|
||||
chroot "$OUTPUT_DIR" apt-get install -y \
|
||||
xorg \
|
||||
xfce4 \
|
||||
xfce4-terminal \
|
||||
lightdm \
|
||||
firefox-esr \
|
||||
|| log "WARNING: Desktop installation incomplete"
|
||||
}
|
||||
|
||||
setup_users() {
|
||||
log "Setting up users..."
|
||||
|
||||
# Set root password
|
||||
echo "root:secubox" | chroot "$OUTPUT_DIR" chpasswd
|
||||
|
||||
# Create secubox user
|
||||
chroot "$OUTPUT_DIR" useradd -m -s /bin/bash -G sudo secubox || true
|
||||
echo "secubox:secubox" | chroot "$OUTPUT_DIR" chpasswd
|
||||
|
||||
# Allow sudo without password for secubox
|
||||
echo "secubox ALL=(ALL) NOPASSWD:ALL" > "$OUTPUT_DIR/etc/sudoers.d/secubox"
|
||||
chmod 440 "$OUTPUT_DIR/etc/sudoers.d/secubox"
|
||||
}
|
||||
|
||||
setup_boot() {
|
||||
log "Setting up boot configuration..."
|
||||
|
||||
# Install GRUB for UEFI
|
||||
chroot "$OUTPUT_DIR" apt-get install -y grub-efi-amd64 || true
|
||||
|
||||
# Create boot directory structure
|
||||
mkdir -p "$OUTPUT_DIR/boot/efi"
|
||||
}
|
||||
|
||||
setup_secubox_branding() {
|
||||
log "Adding SecuBox branding..."
|
||||
|
||||
# MOTD
|
||||
cat > "$OUTPUT_DIR/etc/motd" <<'MOTD'
|
||||
|
||||
██████ ███████ ██████ ██ ██ ██████ ██████ ██ ██
|
||||
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
███████ █████ ██ ██ ██ ██████ ██ ██ ███
|
||||
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
███████ ███████ ██████ ██████ ██████ ██████ ██ ██
|
||||
|
||||
SecuBox AMD64 Live System
|
||||
https://secubox.in
|
||||
|
||||
MOTD
|
||||
|
||||
# Issue
|
||||
cat > "$OUTPUT_DIR/etc/issue" <<'ISSUE'
|
||||
SecuBox AMD64 \n \l
|
||||
|
||||
ISSUE
|
||||
}
|
||||
|
||||
cleanup_rootfs() {
|
||||
log "Cleaning up rootfs..."
|
||||
|
||||
chroot "$OUTPUT_DIR" apt-get clean
|
||||
rm -rf "$OUTPUT_DIR/var/lib/apt/lists/"*
|
||||
rm -rf "$OUTPUT_DIR/tmp/"*
|
||||
rm -f "$OUTPUT_DIR/var/log/"*.log
|
||||
}
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
check_deps
|
||||
|
||||
log "Building SecuBox AMD64 Rootfs"
|
||||
log "Output: $OUTPUT_DIR"
|
||||
log "Minimal: $MINIMAL"
|
||||
|
||||
bootstrap_rootfs
|
||||
configure_rootfs
|
||||
install_kernel
|
||||
install_base_packages
|
||||
add_secubox_repo
|
||||
install_secubox_packages
|
||||
install_desktop
|
||||
setup_users
|
||||
setup_boot
|
||||
setup_secubox_branding
|
||||
cleanup_rootfs
|
||||
|
||||
log "============================================"
|
||||
log "AMD64 Rootfs Complete: $OUTPUT_DIR"
|
||||
log "============================================"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
529
image/multiboot/build-multiboot.sh
Executable file
529
image/multiboot/build-multiboot.sh
Executable file
|
|
@ -0,0 +1,529 @@
|
|||
#!/usr/bin/env bash
|
||||
# SecuBox Multi-Boot Storage Builder
|
||||
# Creates bootable image for ARM64 + AMD64 with shared data
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
OUTPUT_DIR="${REPO_ROOT}/output"
|
||||
CACHE_DIR="${REPO_ROOT}/cache"
|
||||
|
||||
# Defaults
|
||||
IMAGE_SIZE="16G"
|
||||
OUTPUT_FILE=""
|
||||
ARM64_ROOTFS=""
|
||||
AMD64_ROOTFS=""
|
||||
EMMC_IMAGE=""
|
||||
INCLUDE_EMMC=true
|
||||
VERBOSE=false
|
||||
|
||||
# Partition sizes (in MB)
|
||||
EFI_SIZE=512
|
||||
ARM64_SIZE=3072
|
||||
AMD64_SIZE=3072
|
||||
# DATA_SIZE = remaining space
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [OPTIONS]
|
||||
|
||||
Build SecuBox multi-boot storage image (ARM64 + AMD64 + Shared Data)
|
||||
|
||||
Options:
|
||||
-s, --size SIZE Image size (default: 16G)
|
||||
-o, --output FILE Output image file
|
||||
--arm64-rootfs DIR ARM64 rootfs directory
|
||||
--amd64-rootfs DIR AMD64 rootfs directory
|
||||
--emmc-image FILE eMMC image to include for flashing
|
||||
--no-emmc Don't include eMMC flasher image
|
||||
-v, --verbose Verbose output
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
$(basename "$0") -s 16G -o multiboot.img
|
||||
$(basename "$0") --arm64-rootfs /path/to/arm64 --amd64-rootfs /path/to/amd64
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
log() { echo "[$(date '+%H:%M:%S')] $*"; }
|
||||
err() { echo "[ERROR] $*" >&2; exit 1; }
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-s|--size) IMAGE_SIZE="$2"; shift 2 ;;
|
||||
-o|--output) OUTPUT_FILE="$2"; shift 2 ;;
|
||||
--arm64-rootfs) ARM64_ROOTFS="$2"; shift 2 ;;
|
||||
--amd64-rootfs) AMD64_ROOTFS="$2"; shift 2 ;;
|
||||
--emmc-image) EMMC_IMAGE="$2"; shift 2 ;;
|
||||
--no-emmc) INCLUDE_EMMC=false; shift ;;
|
||||
-v|--verbose) VERBOSE=true; shift ;;
|
||||
-h|--help) usage ;;
|
||||
*) err "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$OUTPUT_FILE" ]] && OUTPUT_FILE="${OUTPUT_DIR}/secubox-multiboot-$(date +%Y%m%d).img"
|
||||
}
|
||||
|
||||
check_deps() {
|
||||
local deps=(parted mkfs.vfat mkfs.ext4 debootstrap grub-mkimage losetup)
|
||||
for cmd in "${deps[@]}"; do
|
||||
command -v "$cmd" &>/dev/null || err "Missing: $cmd"
|
||||
done
|
||||
[[ $EUID -eq 0 ]] || err "Must run as root"
|
||||
}
|
||||
|
||||
create_image() {
|
||||
log "Creating ${IMAGE_SIZE} image: ${OUTPUT_FILE}"
|
||||
mkdir -p "$(dirname "$OUTPUT_FILE")"
|
||||
truncate -s "$IMAGE_SIZE" "$OUTPUT_FILE"
|
||||
}
|
||||
|
||||
partition_image() {
|
||||
log "Partitioning image..."
|
||||
|
||||
parted -s "$OUTPUT_FILE" mklabel gpt
|
||||
|
||||
local start=1
|
||||
local end=$((start + EFI_SIZE))
|
||||
|
||||
# Partition 1: EFI System Partition
|
||||
parted -s "$OUTPUT_FILE" mkpart ESP fat32 ${start}MiB ${end}MiB
|
||||
parted -s "$OUTPUT_FILE" set 1 esp on
|
||||
parted -s "$OUTPUT_FILE" set 1 boot on
|
||||
start=$end
|
||||
end=$((start + ARM64_SIZE))
|
||||
|
||||
# Partition 2: ARM64 rootfs
|
||||
parted -s "$OUTPUT_FILE" mkpart arm64-root ext4 ${start}MiB ${end}MiB
|
||||
start=$end
|
||||
end=$((start + AMD64_SIZE))
|
||||
|
||||
# Partition 3: AMD64 rootfs
|
||||
parted -s "$OUTPUT_FILE" mkpart amd64-root ext4 ${start}MiB ${end}MiB
|
||||
start=$end
|
||||
|
||||
# Partition 4: Shared data (rest of disk)
|
||||
parted -s "$OUTPUT_FILE" mkpart shared-data ext4 ${start}MiB 100%
|
||||
|
||||
parted -s "$OUTPUT_FILE" print
|
||||
}
|
||||
|
||||
setup_loop() {
|
||||
log "Setting up loop device..."
|
||||
LOOP_DEV=$(losetup -f --show -P "$OUTPUT_FILE")
|
||||
log "Loop device: $LOOP_DEV"
|
||||
sleep 1
|
||||
}
|
||||
|
||||
format_partitions() {
|
||||
log "Formatting partitions..."
|
||||
|
||||
mkfs.vfat -F 32 -n SECUBOX-EFI "${LOOP_DEV}p1"
|
||||
mkfs.ext4 -L secubox-arm64 "${LOOP_DEV}p2"
|
||||
mkfs.ext4 -L secubox-amd64 "${LOOP_DEV}p3"
|
||||
mkfs.ext4 -L secubox-data "${LOOP_DEV}p4"
|
||||
}
|
||||
|
||||
mount_partitions() {
|
||||
log "Mounting partitions..."
|
||||
|
||||
MNT_EFI=$(mktemp -d)
|
||||
MNT_ARM64=$(mktemp -d)
|
||||
MNT_AMD64=$(mktemp -d)
|
||||
MNT_DATA=$(mktemp -d)
|
||||
|
||||
mount "${LOOP_DEV}p1" "$MNT_EFI"
|
||||
mount "${LOOP_DEV}p2" "$MNT_ARM64"
|
||||
mount "${LOOP_DEV}p3" "$MNT_AMD64"
|
||||
mount "${LOOP_DEV}p4" "$MNT_DATA"
|
||||
}
|
||||
|
||||
install_efi_boot() {
|
||||
log "Installing EFI boot files..."
|
||||
|
||||
mkdir -p "$MNT_EFI/EFI/BOOT"
|
||||
mkdir -p "$MNT_EFI/grub"
|
||||
mkdir -p "$MNT_EFI/dtbs/marvell"
|
||||
mkdir -p "$MNT_EFI/flash"
|
||||
|
||||
# Install GRUB for AMD64 UEFI
|
||||
if command -v grub-mkimage &>/dev/null; then
|
||||
grub-mkimage -o "$MNT_EFI/EFI/BOOT/BOOTX64.EFI" \
|
||||
-O x86_64-efi \
|
||||
-p /grub \
|
||||
part_gpt part_msdos fat ext2 normal linux boot \
|
||||
configfile loopback chain efifwsetup efi_gop \
|
||||
efi_uga ls search search_label search_fs_uuid \
|
||||
search_fs_file gfxterm gfxterm_background gfxmenu test all_video
|
||||
fi
|
||||
|
||||
# GRUB config for AMD64
|
||||
cat > "$MNT_EFI/grub/grub.cfg" <<'GRUBCFG'
|
||||
set timeout=5
|
||||
set default=0
|
||||
|
||||
menuentry "SecuBox AMD64 Live" {
|
||||
linux /vmlinuz root=LABEL=secubox-amd64 ro quiet
|
||||
initrd /initrd-amd64.img
|
||||
}
|
||||
|
||||
menuentry "SecuBox AMD64 Live (Recovery)" {
|
||||
linux /vmlinuz root=LABEL=secubox-amd64 ro single
|
||||
initrd /initrd-amd64.img
|
||||
}
|
||||
|
||||
menuentry "Flash SecuBox to eMMC (ARM64 only)" {
|
||||
echo "This option is for ARM64 systems only"
|
||||
echo "Boot the ARM64 system and run: secubox-flash-emmc"
|
||||
sleep 5
|
||||
}
|
||||
GRUBCFG
|
||||
|
||||
# Copy GRUB config to EFI/BOOT as well
|
||||
cp "$MNT_EFI/grub/grub.cfg" "$MNT_EFI/EFI/BOOT/"
|
||||
}
|
||||
|
||||
install_uboot_boot() {
|
||||
log "Installing U-Boot boot files for ARM64..."
|
||||
|
||||
# Create boot.scr for ARM64 (ESPRESSObin)
|
||||
cat > /tmp/boot.cmd <<'BOOTCMD'
|
||||
# SecuBox Multi-Boot U-Boot Script
|
||||
# For ESPRESSObin/MOCHAbin ARM64
|
||||
|
||||
echo "============================================"
|
||||
echo "SecuBox Multi-Boot — ARM64"
|
||||
echo "============================================"
|
||||
|
||||
# Detect boot device
|
||||
if test "${devtype}" = "usb"; then
|
||||
setenv bootpart "usb 0:1"
|
||||
setenv rootpart "/dev/sda2"
|
||||
echo "Booting from USB storage"
|
||||
elif test "${devtype}" = "mmc"; then
|
||||
setenv bootpart "mmc ${devnum}:1"
|
||||
setenv rootpart "/dev/mmcblk${devnum}p2"
|
||||
echo "Booting from MMC/SD"
|
||||
else
|
||||
# Default to USB
|
||||
usb start
|
||||
setenv bootpart "usb 0:1"
|
||||
setenv rootpart "/dev/sda2"
|
||||
fi
|
||||
|
||||
# Load kernel
|
||||
echo "Loading ARM64 kernel..."
|
||||
load ${bootpart} ${kernel_addr_r} Image
|
||||
|
||||
# Load device tree
|
||||
echo "Loading device tree..."
|
||||
if load ${bootpart} ${fdt_addr_r} dtbs/marvell/armada-3720-espressobin-v7-emmc.dtb; then
|
||||
echo "Loaded ESPRESSObin v7 eMMC DTB"
|
||||
else
|
||||
load ${bootpart} ${fdt_addr_r} dtbs/marvell/armada-3720-espressobin-v7.dtb
|
||||
fi
|
||||
|
||||
# Load initramfs
|
||||
echo "Loading initramfs..."
|
||||
if load ${bootpart} ${ramdisk_addr_r} initrd.img; then
|
||||
setenv initrd_size ${filesize}
|
||||
setenv use_initrd 1
|
||||
else
|
||||
setenv use_initrd 0
|
||||
fi
|
||||
|
||||
# Boot arguments
|
||||
# Data partition is partition 4
|
||||
setenv bootargs "root=${rootpart} rootfstype=ext4 rootwait rootdelay=5 console=ttyMV0,115200 net.ifnames=0 secubox.data=/dev/sda4"
|
||||
|
||||
echo "Booting SecuBox ARM64..."
|
||||
if test "${use_initrd}" = "1"; then
|
||||
booti ${kernel_addr_r} ${ramdisk_addr_r}:${initrd_size} ${fdt_addr_r}
|
||||
else
|
||||
booti ${kernel_addr_r} - ${fdt_addr_r}
|
||||
fi
|
||||
BOOTCMD
|
||||
|
||||
# Compile boot.scr if mkimage available
|
||||
if command -v mkimage &>/dev/null; then
|
||||
mkimage -A arm64 -T script -C none -d /tmp/boot.cmd "$MNT_EFI/boot.scr"
|
||||
else
|
||||
cp /tmp/boot.cmd "$MNT_EFI/boot.cmd"
|
||||
fi
|
||||
}
|
||||
|
||||
install_arm64_rootfs() {
|
||||
log "Installing ARM64 rootfs..."
|
||||
|
||||
if [[ -n "$ARM64_ROOTFS" && -d "$ARM64_ROOTFS" ]]; then
|
||||
log "Copying from $ARM64_ROOTFS"
|
||||
rsync -aHAX "$ARM64_ROOTFS/" "$MNT_ARM64/"
|
||||
else
|
||||
# Check for existing built image
|
||||
local arm64_img="${OUTPUT_DIR}/secubox-espressobin-v7-bookworm.img"
|
||||
if [[ -f "$arm64_img" ]]; then
|
||||
log "Extracting rootfs from $arm64_img"
|
||||
local tmp_loop=$(losetup -f --show -P "$arm64_img")
|
||||
local tmp_mnt=$(mktemp -d)
|
||||
mount "${tmp_loop}p2" "$tmp_mnt"
|
||||
rsync -aHAX "$tmp_mnt/" "$MNT_ARM64/"
|
||||
umount "$tmp_mnt"
|
||||
losetup -d "$tmp_loop"
|
||||
rmdir "$tmp_mnt"
|
||||
|
||||
# Also copy kernel/initrd/dtbs to EFI partition
|
||||
mount "${tmp_loop}p1" "$tmp_mnt" 2>/dev/null || true
|
||||
if [[ -f "$tmp_mnt/Image" ]]; then
|
||||
cp "$tmp_mnt/Image" "$MNT_EFI/"
|
||||
cp "$tmp_mnt/initrd.img" "$MNT_EFI/" 2>/dev/null || true
|
||||
cp -r "$tmp_mnt/dtbs" "$MNT_EFI/" 2>/dev/null || true
|
||||
fi
|
||||
umount "$tmp_mnt" 2>/dev/null || true
|
||||
else
|
||||
log "WARNING: No ARM64 rootfs source found, partition will be empty"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Setup shared data mounts in fstab
|
||||
setup_shared_mounts "$MNT_ARM64"
|
||||
}
|
||||
|
||||
install_amd64_rootfs() {
|
||||
log "Installing AMD64 rootfs..."
|
||||
|
||||
if [[ -n "$AMD64_ROOTFS" && -d "$AMD64_ROOTFS" ]]; then
|
||||
log "Copying from $AMD64_ROOTFS"
|
||||
rsync -aHAX "$AMD64_ROOTFS/" "$MNT_AMD64/"
|
||||
else
|
||||
# Build AMD64 rootfs with debootstrap
|
||||
log "Building AMD64 rootfs with debootstrap..."
|
||||
"${SCRIPT_DIR}/build-amd64-rootfs.sh" --output "$MNT_AMD64" --minimal
|
||||
fi
|
||||
|
||||
# Copy AMD64 kernel to EFI partition
|
||||
if [[ -f "$MNT_AMD64/boot/vmlinuz-"* ]]; then
|
||||
cp "$MNT_AMD64/boot/vmlinuz-"* "$MNT_EFI/vmlinuz"
|
||||
cp "$MNT_AMD64/boot/initrd.img-"* "$MNT_EFI/initrd-amd64.img" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Setup shared data mounts in fstab
|
||||
setup_shared_mounts "$MNT_AMD64"
|
||||
}
|
||||
|
||||
setup_shared_mounts() {
|
||||
local rootfs="$1"
|
||||
|
||||
log "Setting up shared data mounts for $rootfs"
|
||||
|
||||
# Create mount points
|
||||
mkdir -p "$rootfs/srv/data"
|
||||
|
||||
# Add to fstab
|
||||
cat >> "$rootfs/etc/fstab" <<'FSTAB'
|
||||
|
||||
# SecuBox Shared Data Partition
|
||||
LABEL=secubox-data /srv/data ext4 defaults,noatime 0 2
|
||||
FSTAB
|
||||
|
||||
# Create systemd mount for bind mounts
|
||||
mkdir -p "$rootfs/etc/systemd/system"
|
||||
cat > "$rootfs/etc/systemd/system/secubox-shared-data.service" <<'SERVICE'
|
||||
[Unit]
|
||||
Description=SecuBox Shared Data Bind Mounts
|
||||
After=srv-data.mount
|
||||
Requires=srv-data.mount
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/usr/local/bin/secubox-mount-shared
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
SERVICE
|
||||
|
||||
# Create mount script
|
||||
mkdir -p "$rootfs/usr/local/bin"
|
||||
cat > "$rootfs/usr/local/bin/secubox-mount-shared" <<'SCRIPT'
|
||||
#!/bin/bash
|
||||
# Mount shared SecuBox data directories
|
||||
|
||||
DATA_ROOT="/srv/data"
|
||||
|
||||
# Create shared directories if they don't exist
|
||||
mkdir -p "$DATA_ROOT"/{etc/secubox,var/lib/secubox,srv/secubox,log/secubox}
|
||||
|
||||
# Bind mount shared configs
|
||||
mkdir -p /etc/secubox
|
||||
mount --bind "$DATA_ROOT/etc/secubox" /etc/secubox
|
||||
|
||||
# Bind mount application state
|
||||
mkdir -p /var/lib/secubox
|
||||
mount --bind "$DATA_ROOT/var/lib/secubox" /var/lib/secubox
|
||||
|
||||
# Bind mount service data
|
||||
mkdir -p /srv/secubox
|
||||
mount --bind "$DATA_ROOT/srv/secubox" /srv/secubox
|
||||
|
||||
# Bind mount logs
|
||||
mkdir -p /var/log/secubox
|
||||
mount --bind "$DATA_ROOT/log/secubox" /var/log/secubox
|
||||
|
||||
echo "SecuBox shared data mounted"
|
||||
SCRIPT
|
||||
chmod +x "$rootfs/usr/local/bin/secubox-mount-shared"
|
||||
|
||||
# Enable the service
|
||||
ln -sf ../secubox-shared-data.service "$rootfs/etc/systemd/system/multi-user.target.wants/" 2>/dev/null || true
|
||||
}
|
||||
|
||||
setup_shared_data() {
|
||||
log "Setting up shared data partition structure..."
|
||||
|
||||
mkdir -p "$MNT_DATA"/{etc/secubox,var/lib/secubox,srv/secubox,log/secubox}
|
||||
mkdir -p "$MNT_DATA/etc/secubox"/{tls,modules}
|
||||
mkdir -p "$MNT_DATA/var/lib/secubox"/{crowdsec,haproxy,wireguard,dpi,hub}
|
||||
mkdir -p "$MNT_DATA/srv/secubox"/{mitmproxy,nginx,certs}
|
||||
|
||||
# Create default configs
|
||||
cat > "$MNT_DATA/etc/secubox/api.toml" <<'TOML'
|
||||
# SecuBox API Configuration (Shared)
|
||||
[api]
|
||||
jwt_secret = "" # Generated on first boot
|
||||
|
||||
[logging]
|
||||
level = "INFO"
|
||||
TOML
|
||||
|
||||
# Create empty users.json
|
||||
echo '{}' > "$MNT_DATA/etc/secubox/users.json"
|
||||
|
||||
# Set permissions
|
||||
chmod 750 "$MNT_DATA/etc/secubox"
|
||||
chmod 750 "$MNT_DATA/var/lib/secubox"
|
||||
}
|
||||
|
||||
install_emmc_flasher() {
|
||||
if [[ "$INCLUDE_EMMC" != "true" ]]; then
|
||||
log "Skipping eMMC flasher image"
|
||||
return
|
||||
fi
|
||||
|
||||
log "Installing eMMC flasher image..."
|
||||
|
||||
mkdir -p "$MNT_EFI/flash"
|
||||
|
||||
if [[ -n "$EMMC_IMAGE" && -f "$EMMC_IMAGE" ]]; then
|
||||
if [[ "$EMMC_IMAGE" == *.gz ]]; then
|
||||
cp "$EMMC_IMAGE" "$MNT_EFI/flash/secubox-emmc.img.gz"
|
||||
else
|
||||
gzip -c "$EMMC_IMAGE" > "$MNT_EFI/flash/secubox-emmc.img.gz"
|
||||
fi
|
||||
else
|
||||
# Look for existing image
|
||||
local emmc_img="${OUTPUT_DIR}/secubox-espressobin-v7-bookworm.img"
|
||||
if [[ -f "$emmc_img" ]]; then
|
||||
log "Compressing $emmc_img for eMMC flash..."
|
||||
gzip -c "$emmc_img" > "$MNT_EFI/flash/secubox-emmc.img.gz"
|
||||
else
|
||||
log "WARNING: No eMMC image found, flash directory will be empty"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create flash script
|
||||
cat > "$MNT_EFI/flash/flash-emmc.sh" <<'FLASH'
|
||||
#!/bin/bash
|
||||
# SecuBox eMMC Flasher
|
||||
set -e
|
||||
|
||||
EMMC_DEV="/dev/mmcblk0"
|
||||
IMG="/boot/efi/flash/secubox-emmc.img.gz"
|
||||
|
||||
echo "============================================"
|
||||
echo "SecuBox eMMC Flasher"
|
||||
echo "============================================"
|
||||
|
||||
if [[ ! -f "$IMG" ]]; then
|
||||
echo "ERROR: Image not found: $IMG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -b "$EMMC_DEV" ]]; then
|
||||
echo "ERROR: eMMC device not found: $EMMC_DEV"
|
||||
echo "Available block devices:"
|
||||
lsblk
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "WARNING: This will erase all data on $EMMC_DEV"
|
||||
echo "Image: $IMG"
|
||||
echo ""
|
||||
read -p "Continue? [y/N] " confirm
|
||||
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
|
||||
echo "Aborted."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Flashing to $EMMC_DEV..."
|
||||
gunzip -c "$IMG" | dd of="$EMMC_DEV" bs=4M status=progress conv=fsync
|
||||
|
||||
echo "Syncing..."
|
||||
sync
|
||||
|
||||
echo "============================================"
|
||||
echo "Flash complete! You can now boot from eMMC."
|
||||
echo "============================================"
|
||||
FLASH
|
||||
chmod +x "$MNT_EFI/flash/flash-emmc.sh"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
log "Cleaning up..."
|
||||
|
||||
umount "$MNT_EFI" 2>/dev/null || true
|
||||
umount "$MNT_ARM64" 2>/dev/null || true
|
||||
umount "$MNT_AMD64" 2>/dev/null || true
|
||||
umount "$MNT_DATA" 2>/dev/null || true
|
||||
|
||||
[[ -n "${LOOP_DEV:-}" ]] && losetup -d "$LOOP_DEV" 2>/dev/null || true
|
||||
|
||||
rmdir "$MNT_EFI" "$MNT_ARM64" "$MNT_AMD64" "$MNT_DATA" 2>/dev/null || true
|
||||
}
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
check_deps
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
log "Building SecuBox Multi-Boot Image"
|
||||
log "Size: $IMAGE_SIZE"
|
||||
log "Output: $OUTPUT_FILE"
|
||||
|
||||
create_image
|
||||
partition_image
|
||||
setup_loop
|
||||
format_partitions
|
||||
mount_partitions
|
||||
|
||||
install_efi_boot
|
||||
install_uboot_boot
|
||||
install_arm64_rootfs
|
||||
install_amd64_rootfs
|
||||
setup_shared_data
|
||||
install_emmc_flasher
|
||||
|
||||
log "============================================"
|
||||
log "Multi-Boot Image Complete: $OUTPUT_FILE"
|
||||
log "============================================"
|
||||
log "Partitions:"
|
||||
log " 1: EFI/Boot (FAT32) - UEFI + U-Boot"
|
||||
log " 2: ARM64 rootfs (ext4)"
|
||||
log " 3: AMD64 rootfs (ext4)"
|
||||
log " 4: Shared data (ext4)"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Loading…
Reference in New Issue
Block a user