fix: disk image build, piCore64 URL, license
Some checks failed
CI / Go Tests (push) Has been cancelled
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
CI / Shellcheck (push) Has been cancelled
Release / Test (push) Has been cancelled
Release / Build Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
Release / Build Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
Release / Build ISO (amd64) (push) Has been cancelled
Release / Create Release (push) Has been cancelled
Some checks failed
CI / Go Tests (push) Has been cancelled
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
CI / Shellcheck (push) Has been cancelled
Release / Test (push) Has been cancelled
Release / Build Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
Release / Build Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
Release / Build ISO (amd64) (push) Has been cancelled
Release / Create Release (push) Has been cancelled
- Add kpartx for reliable loop partition mapping in Docker containers - Fix piCore64 download URL (changed from .img.gz to .zip format) - Fix piCore64 boot partition mount (initramfs on p1, not p2) - Fix tar --wildcards for RPi firmware extraction - Add MIT license (same as KubeSolo) - Add kpartx and unzip to Docker builder image Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Anthony De Lorenzo
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -237,4 +237,4 @@ Metrics include: `kubesolo_os_info`, `boot_success`, `boot_counter`, `uptime_sec
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
TBD
|
MIT License — see [LICENSE](LICENSE) for details.
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
gcc-aarch64-linux-gnu \
|
gcc-aarch64-linux-gnu \
|
||||||
binutils-aarch64-linux-gnu \
|
binutils-aarch64-linux-gnu \
|
||||||
git \
|
git \
|
||||||
|
kpartx \
|
||||||
|
unzip \
|
||||||
wget \
|
wget \
|
||||||
xorriso \
|
xorriso \
|
||||||
xz-utils \
|
xz-utils \
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ NET_BRIDGING_TCZ_SHA256=""
|
|||||||
IPTABLES_TCZ_SHA256=""
|
IPTABLES_TCZ_SHA256=""
|
||||||
|
|
||||||
# piCore64 (ARM64 — Raspberry Pi)
|
# piCore64 (ARM64 — Raspberry Pi)
|
||||||
PICORE_VERSION=15.0
|
PICORE_VERSION=15.0.0
|
||||||
PICORE_ARCH=aarch64
|
PICORE_ARCH=aarch64
|
||||||
PICORE_IMAGE=piCore-${PICORE_VERSION}.img.gz
|
PICORE_IMAGE=piCore64-${PICORE_VERSION}.zip
|
||||||
PICORE_IMAGE_URL=http://www.tinycorelinux.net/${PICORE_VERSION%%.*}.x/${PICORE_ARCH}/releases/RPi/${PICORE_IMAGE}
|
PICORE_IMAGE_URL=http://www.tinycorelinux.net/${PICORE_VERSION%%.*}.x/${PICORE_ARCH}/releases/RPi/${PICORE_IMAGE}
|
||||||
|
|
||||||
# Raspberry Pi firmware (boot blobs, DTBs)
|
# Raspberry Pi firmware (boot blobs, DTBs)
|
||||||
|
|||||||
@@ -51,10 +51,39 @@ size=1048576, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, name="SystemB"
|
|||||||
type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, name="Data"
|
type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, name="Data"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Set up loop device
|
# Set up loop device with partition mappings
|
||||||
LOOP=$(losetup --show -fP "$IMG_OUTPUT")
|
LOOP=$(losetup --show -f "$IMG_OUTPUT")
|
||||||
echo "==> Loop device: $LOOP"
|
echo "==> Loop device: $LOOP"
|
||||||
|
|
||||||
|
# Use kpartx for reliable partition device nodes (works in Docker/containers)
|
||||||
|
USE_KPARTX=false
|
||||||
|
if [ ! -b "${LOOP}p1" ]; then
|
||||||
|
if command -v kpartx >/dev/null 2>&1; then
|
||||||
|
kpartx -a "$LOOP"
|
||||||
|
USE_KPARTX=true
|
||||||
|
sleep 1
|
||||||
|
LOOP_NAME=$(basename "$LOOP")
|
||||||
|
P1="/dev/mapper/${LOOP_NAME}p1"
|
||||||
|
P2="/dev/mapper/${LOOP_NAME}p2"
|
||||||
|
P3="/dev/mapper/${LOOP_NAME}p3"
|
||||||
|
P4="/dev/mapper/${LOOP_NAME}p4"
|
||||||
|
else
|
||||||
|
# Retry with -P flag
|
||||||
|
losetup -d "$LOOP"
|
||||||
|
LOOP=$(losetup --show -fP "$IMG_OUTPUT")
|
||||||
|
sleep 1
|
||||||
|
P1="${LOOP}p1"
|
||||||
|
P2="${LOOP}p2"
|
||||||
|
P3="${LOOP}p3"
|
||||||
|
P4="${LOOP}p4"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
P1="${LOOP}p1"
|
||||||
|
P2="${LOOP}p2"
|
||||||
|
P3="${LOOP}p3"
|
||||||
|
P4="${LOOP}p4"
|
||||||
|
fi
|
||||||
|
|
||||||
MNT_EFI=$(mktemp -d)
|
MNT_EFI=$(mktemp -d)
|
||||||
MNT_SYSA=$(mktemp -d)
|
MNT_SYSA=$(mktemp -d)
|
||||||
MNT_SYSB=$(mktemp -d)
|
MNT_SYSB=$(mktemp -d)
|
||||||
@@ -65,22 +94,25 @@ cleanup() {
|
|||||||
umount "$MNT_SYSA" 2>/dev/null || true
|
umount "$MNT_SYSA" 2>/dev/null || true
|
||||||
umount "$MNT_SYSB" 2>/dev/null || true
|
umount "$MNT_SYSB" 2>/dev/null || true
|
||||||
umount "$MNT_DATA" 2>/dev/null || true
|
umount "$MNT_DATA" 2>/dev/null || true
|
||||||
|
if [ "$USE_KPARTX" = true ]; then
|
||||||
|
kpartx -d "$LOOP" 2>/dev/null || true
|
||||||
|
fi
|
||||||
losetup -d "$LOOP" 2>/dev/null || true
|
losetup -d "$LOOP" 2>/dev/null || true
|
||||||
rm -rf "$MNT_EFI" "$MNT_SYSA" "$MNT_SYSB" "$MNT_DATA" 2>/dev/null || true
|
rm -rf "$MNT_EFI" "$MNT_SYSA" "$MNT_SYSB" "$MNT_DATA" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
# Format partitions
|
# Format partitions
|
||||||
mkfs.vfat -F 32 -n KSOLOEFI "${LOOP}p1"
|
mkfs.vfat -F 32 -n KSOLOEFI "$P1"
|
||||||
mkfs.ext4 -q -L KSOLOA "${LOOP}p2"
|
mkfs.ext4 -q -L KSOLOA "$P2"
|
||||||
mkfs.ext4 -q -L KSOLOB "${LOOP}p3"
|
mkfs.ext4 -q -L KSOLOB "$P3"
|
||||||
mkfs.ext4 -q -L KSOLODATA "${LOOP}p4"
|
mkfs.ext4 -q -L KSOLODATA "$P4"
|
||||||
|
|
||||||
# Mount all partitions
|
# Mount all partitions
|
||||||
mount "${LOOP}p1" "$MNT_EFI"
|
mount "$P1" "$MNT_EFI"
|
||||||
mount "${LOOP}p2" "$MNT_SYSA"
|
mount "$P2" "$MNT_SYSA"
|
||||||
mount "${LOOP}p3" "$MNT_SYSB"
|
mount "$P3" "$MNT_SYSB"
|
||||||
mount "${LOOP}p4" "$MNT_DATA"
|
mount "$P4" "$MNT_DATA"
|
||||||
|
|
||||||
# --- EFI/Boot Partition ---
|
# --- EFI/Boot Partition ---
|
||||||
echo " Installing GRUB..."
|
echo " Installing GRUB..."
|
||||||
|
|||||||
@@ -29,23 +29,40 @@ if [ "$EXTRACT_ARCH" = "arm64" ]; then
|
|||||||
|
|
||||||
echo "==> Extracting piCore64 image: $PICORE_IMG"
|
echo "==> Extracting piCore64 image: $PICORE_IMG"
|
||||||
|
|
||||||
# Decompress .img.gz to raw image
|
# Decompress to raw image (.img.gz or .zip)
|
||||||
PICORE_RAW="$CACHE_DIR/piCore-${PICORE_VERSION}.img"
|
PICORE_RAW="$CACHE_DIR/piCore-${PICORE_VERSION}.img"
|
||||||
if [ ! -f "$PICORE_RAW" ]; then
|
if [ ! -f "$PICORE_RAW" ]; then
|
||||||
echo " Decompressing..."
|
echo " Decompressing..."
|
||||||
gunzip -k "$PICORE_IMG" 2>/dev/null || \
|
case "$PICORE_IMG" in
|
||||||
zcat "$PICORE_IMG" > "$PICORE_RAW"
|
*.zip)
|
||||||
|
unzip -o -j "$PICORE_IMG" '*.img' -d "$CACHE_DIR" 2>/dev/null || \
|
||||||
|
unzip -o "$PICORE_IMG" -d "$CACHE_DIR"
|
||||||
|
# Find the extracted .img file
|
||||||
|
EXTRACTED_IMG=$(find "$CACHE_DIR" -maxdepth 1 -name '*.img' -newer "$PICORE_IMG" | head -1)
|
||||||
|
if [ -n "$EXTRACTED_IMG" ] && [ "$EXTRACTED_IMG" != "$PICORE_RAW" ]; then
|
||||||
|
mv "$EXTRACTED_IMG" "$PICORE_RAW"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*.img.gz)
|
||||||
|
gunzip -k "$PICORE_IMG" 2>/dev/null || \
|
||||||
|
zcat "$PICORE_IMG" > "$PICORE_RAW"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: Unknown piCore image format: $PICORE_IMG"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Mount the piCore rootfs partition (partition 2 in the SD image)
|
# Mount the piCore boot partition (partition 1) to find kernel/initramfs
|
||||||
# Use losetup to find the partition offset
|
# piCore layout: p1=boot (FAT32, has kernel+initramfs), p2=rootfs (ext4, has tce/)
|
||||||
IMG_MNT=$(mktemp -d)
|
IMG_MNT=$(mktemp -d)
|
||||||
echo " Mounting piCore rootfs partition..."
|
echo " Mounting piCore boot partition..."
|
||||||
|
|
||||||
# Get partition 2 offset (piCore layout: boot=p1, rootfs=p2)
|
# Get partition 1 offset (boot/FAT partition with kernel+initramfs)
|
||||||
OFFSET=$(fdisk -l "$PICORE_RAW" 2>/dev/null | awk '/^.*img2/{print $2}')
|
OFFSET=$(fdisk -l "$PICORE_RAW" 2>/dev/null | awk '/^.*img1/{print $2}')
|
||||||
if [ -z "$OFFSET" ]; then
|
if [ -z "$OFFSET" ]; then
|
||||||
# Fallback: try sfdisk
|
# Fallback: try sfdisk (first partition)
|
||||||
OFFSET=$(sfdisk -d "$PICORE_RAW" 2>/dev/null | awk -F'[=,]' '/start=/{print $2; exit}' | tr -d ' ')
|
OFFSET=$(sfdisk -d "$PICORE_RAW" 2>/dev/null | awk -F'[=,]' '/start=/{print $2; exit}' | tr -d ' ')
|
||||||
fi
|
fi
|
||||||
if [ -z "$OFFSET" ]; then
|
if [ -z "$OFFSET" ]; then
|
||||||
@@ -56,13 +73,13 @@ if [ "$EXTRACT_ARCH" = "arm64" ]; then
|
|||||||
|
|
||||||
BYTE_OFFSET=$((OFFSET * 512))
|
BYTE_OFFSET=$((OFFSET * 512))
|
||||||
mount -o loop,ro,offset="$BYTE_OFFSET" "$PICORE_RAW" "$IMG_MNT" || {
|
mount -o loop,ro,offset="$BYTE_OFFSET" "$PICORE_RAW" "$IMG_MNT" || {
|
||||||
echo "ERROR: Failed to mount piCore rootfs (need root for losetup)"
|
echo "ERROR: Failed to mount piCore boot partition (need root for losetup)"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Find initramfs in the piCore rootfs
|
# Find initramfs in the piCore boot partition
|
||||||
COREGZ=""
|
COREGZ=""
|
||||||
for f in "$IMG_MNT"/boot/corepure64.gz "$IMG_MNT"/boot/core.gz "$IMG_MNT"/*.gz; do
|
for f in "$IMG_MNT"/rootfs-piCore64*.gz "$IMG_MNT"/boot/corepure64.gz "$IMG_MNT"/boot/core.gz "$IMG_MNT"/corepure64.gz "$IMG_MNT"/core.gz; do
|
||||||
[ -f "$f" ] && COREGZ="$f" && break
|
[ -f "$f" ] && COREGZ="$f" && break
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ trap 'rm -rf "$TEMP_DIR"' EXIT
|
|||||||
|
|
||||||
# Extract only the boot/ directory from the archive
|
# Extract only the boot/ directory from the archive
|
||||||
# Archive structure: firmware-<tag>/boot/...
|
# Archive structure: firmware-<tag>/boot/...
|
||||||
tar -xzf "$RPI_FW_ARCHIVE" -C "$TEMP_DIR" --strip-components=1 '*/boot/'
|
tar -xzf "$RPI_FW_ARCHIVE" -C "$TEMP_DIR" --strip-components=1 --wildcards '*/boot/'
|
||||||
|
|
||||||
BOOT_SRC="$TEMP_DIR/boot"
|
BOOT_SRC="$TEMP_DIR/boot"
|
||||||
if [ ! -d "$BOOT_SRC" ]; then
|
if [ ! -d "$BOOT_SRC" ]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user