#!/bin/bash # extract-core.sh — Extract Tiny Core Linux rootfs from ISO set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" CACHE_DIR="${CACHE_DIR:-$PROJECT_ROOT/build/cache}" ROOTFS_DIR="${ROOTFS_DIR:-$PROJECT_ROOT/build/rootfs-work}" # shellcheck source=../config/versions.env . "$SCRIPT_DIR/../config/versions.env" EXTRACT_ARCH="${TARGET_ARCH:-amd64}" # Clean previous rootfs rm -rf "$ROOTFS_DIR" mkdir -p "$ROOTFS_DIR" # ========================================================================= # ARM64: piCore64 .img.gz extraction (SD card image, not ISO) # ========================================================================= if [ "$EXTRACT_ARCH" = "arm64" ]; then PICORE_IMG="$CACHE_DIR/$PICORE_IMAGE" if [ ! -f "$PICORE_IMG" ]; then echo "ERROR: piCore64 image not found: $PICORE_IMG" echo "Run 'TARGET_ARCH=arm64 make fetch' first." exit 1 fi echo "==> Extracting piCore64 image: $PICORE_IMG" # Decompress to raw image (.img.gz or .zip) PICORE_RAW="$CACHE_DIR/piCore-${PICORE_VERSION}.img" if [ ! -f "$PICORE_RAW" ]; then echo " Decompressing..." case "$PICORE_IMG" in *.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 # Mount the piCore boot partition (partition 1) to find kernel/initramfs # piCore layout: p1=boot (FAT32, has kernel+initramfs), p2=rootfs (ext4, has tce/) IMG_MNT=$(mktemp -d) echo " Mounting piCore boot partition..." # Get partition 1 offset (boot/FAT partition with kernel+initramfs) OFFSET=$(fdisk -l "$PICORE_RAW" 2>/dev/null | awk '/^.*img1/{print $2}') if [ -z "$OFFSET" ]; then # Fallback: try sfdisk (first partition) OFFSET=$(sfdisk -d "$PICORE_RAW" 2>/dev/null | awk -F'[=,]' '/start=/{print $2; exit}' | tr -d ' ') fi if [ -z "$OFFSET" ]; then echo "ERROR: Could not determine partition offset in piCore image" fdisk -l "$PICORE_RAW" || true exit 1 fi BYTE_OFFSET=$((OFFSET * 512)) mount -o loop,ro,offset="$BYTE_OFFSET" "$PICORE_RAW" "$IMG_MNT" || { echo "ERROR: Failed to mount piCore boot partition (need root for losetup)" exit 1 } # Find initramfs in the piCore boot partition COREGZ="" 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 done if [ -z "$COREGZ" ]; then echo "ERROR: Could not find initramfs in piCore image" echo "Contents:" ls -la "$IMG_MNT"/ ls -la "$IMG_MNT"/boot/ 2>/dev/null || true umount "$IMG_MNT" 2>/dev/null || true exit 1 fi echo "==> Found initramfs: $COREGZ" # Extract initramfs mkdir -p "$ROOTFS_DIR/rootfs" cd "$ROOTFS_DIR/rootfs" zcat "$COREGZ" | cpio -idm 2>/dev/null # Note: ARM64 kernel comes from build-kernel-arm64.sh, not from piCore # We only use piCore for the BusyBox userland cd "$PROJECT_ROOT" umount "$IMG_MNT" 2>/dev/null || true rm -rf "$IMG_MNT" echo "==> ARM64 rootfs extracted: $ROOTFS_DIR/rootfs" echo " Size: $(du -sh "$ROOTFS_DIR/rootfs" | cut -f1)" echo "==> Extract complete (ARM64). Kernel will come from build-kernel-arm64.sh" exit 0 fi # ========================================================================= # x86_64: Tiny Core ISO extraction # ========================================================================= TC_ISO="$CACHE_DIR/$TINYCORE_ISO" ISO_MNT="$ROOTFS_DIR/iso-mount" if [ ! -f "$TC_ISO" ]; then echo "ERROR: Tiny Core ISO not found: $TC_ISO" echo "Run 'make fetch' first." exit 1 fi mkdir -p "$ISO_MNT" # --- Mount ISO and extract kernel + initramfs --- echo "==> Mounting ISO: $TC_ISO" mount -o loop,ro "$TC_ISO" "$ISO_MNT" 2>/dev/null || { # Fallback for non-root: use 7z or bsdtar echo " mount failed (need root?), trying bsdtar..." mkdir -p "$ISO_MNT" bsdtar xf "$TC_ISO" -C "$ISO_MNT" 2>/dev/null || { echo " bsdtar failed, trying 7z..." 7z x -o"$ISO_MNT" "$TC_ISO" >/dev/null 2>&1 } } # Find vmlinuz and core.gz (path varies by Tiny Core version/arch) VMLINUZ="" COREGZ="" for f in "$ISO_MNT"/boot/vmlinuz64 "$ISO_MNT"/boot/vmlinuz; do [ -f "$f" ] && VMLINUZ="$f" && break done for f in "$ISO_MNT"/boot/corepure64.gz "$ISO_MNT"/boot/core.gz; do [ -f "$f" ] && COREGZ="$f" && break done if [ -z "$VMLINUZ" ] || [ -z "$COREGZ" ]; then echo "ERROR: Could not find vmlinuz/core.gz in ISO" echo "ISO contents:" find "$ISO_MNT" -type f umount "$ISO_MNT" 2>/dev/null || true exit 1 fi echo "==> Found kernel: $VMLINUZ" echo "==> Found initramfs: $COREGZ" # Copy kernel cp "$VMLINUZ" "$ROOTFS_DIR/vmlinuz" # --- Extract initramfs (core.gz → rootfs) --- echo "==> Extracting initramfs..." mkdir -p "$ROOTFS_DIR/rootfs" cd "$ROOTFS_DIR/rootfs" zcat "$COREGZ" | cpio -idm 2>/dev/null # Unmount ISO cd "$PROJECT_ROOT" umount "$ISO_MNT" 2>/dev/null || true rm -rf "$ISO_MNT" echo "==> Rootfs extracted: $ROOTFS_DIR/rootfs" echo " Size: $(du -sh "$ROOTFS_DIR/rootfs" | cut -f1)" echo " Kernel: $ROOTFS_DIR/vmlinuz ($(du -h "$ROOTFS_DIR/vmlinuz" | cut -f1))" # --- Audit kernel config if available --- if [ -f "$ROOTFS_DIR/rootfs/proc/config.gz" ]; then echo "==> Kernel config found in rootfs, auditing..." "$SCRIPT_DIR/../config/kernel-audit.sh" <(zcat "$ROOTFS_DIR/rootfs/proc/config.gz") || true fi echo "==> Extract complete."