diff --git a/scripts/docker-image-create-uefi.sh b/scripts/docker-image-create-uefi.sh index d3f2322..c64185b 100755 --- a/scripts/docker-image-create-uefi.sh +++ b/scripts/docker-image-create-uefi.sh @@ -31,13 +31,13 @@ echo "Copying kernel to staging..." cp $KERNEL_PATH /staging/esp/boot/vmlinuz if [ -f "$INITRD_PATH" ]; then cp $INITRD_PATH /staging/esp/boot/initrd.img; fi -# Create GRUB configuration +# Create GRUB configuration for immutable root with overlay printf '%s\n' \ 'set timeout=3' \ 'set default=0' \ '' \ - 'menuentry "SparkOS" {' \ - ' linux /boot/vmlinuz root=LABEL=SparkOS rw init=/sbin/init console=tty1 quiet' \ + 'menuentry "SparkOS (Immutable Base + Overlay)" {' \ + ' linux /boot/vmlinuz root=LABEL=SparkOS ro init=/sbin/init console=tty1 quiet' \ '}' \ > /staging/esp/boot/grub/grub.cfg @@ -84,7 +84,14 @@ sgdisk -n 2:411648:0 -t 2:8300 -c 2:"Linux filesystem" /output/sparkos.img # Extract partition regions using dd echo "Extracting partition regions..." dd if=/output/sparkos.img of=/tmp/esp.img bs=512 skip=2048 count=409600 2>/dev/null -dd if=/output/sparkos.img of=/tmp/root.img bs=512 skip=411648 2>/dev/null + +# Calculate exact size for root partition +ROOT_START=411648 +ROOT_END=$(sgdisk -p /output/sparkos.img | grep "^ 2" | awk '{print $3}') +ROOT_SIZE=$((ROOT_END - ROOT_START + 1)) +echo "Root partition: start=$ROOT_START, end=$ROOT_END, size=$ROOT_SIZE sectors" + +dd if=/output/sparkos.img of=/tmp/root.img bs=512 skip=$ROOT_START count=$ROOT_SIZE 2>/dev/null # Format ESP partition (FAT32) echo "Formatting EFI System Partition (FAT32)..." @@ -111,7 +118,7 @@ mke2fs -t ext4 -L "SparkOS" -d /staging/root /tmp/root.img >/dev/null 2>&1 # Write partitions back to image echo "Writing partitions to image..." dd if=/tmp/esp.img of=/output/sparkos.img bs=512 seek=2048 count=409600 conv=notrunc 2>/dev/null -dd if=/tmp/root.img of=/output/sparkos.img bs=512 seek=411648 conv=notrunc 2>/dev/null +dd if=/tmp/root.img of=/output/sparkos.img bs=512 seek=$ROOT_START count=$ROOT_SIZE conv=notrunc 2>/dev/null # Clean up temporary files rm -f /tmp/esp.img /tmp/root.img diff --git a/src/init.c b/src/init.c index fb957fb..b002f28 100644 --- a/src/init.c +++ b/src/init.c @@ -100,6 +100,28 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Warning: Failed to mount /tmp\n"); } + // Set up overlay filesystem for immutable base OS + printf("Setting up overlay filesystem for writable layer...\n"); + + // Create overlay directories in tmpfs + if (system("mkdir -p /tmp/overlay/upper /tmp/overlay/work 2>/dev/null") != 0) { + fprintf(stderr, "Warning: Failed to create overlay directories\n"); + } + + // Mount overlay on /var for logs and runtime data + if (system("mount -t overlay overlay -o lowerdir=/var,upperdir=/tmp/overlay/upper,workdir=/tmp/overlay/work /var 2>/dev/null") != 0) { + fprintf(stderr, "Warning: Failed to mount overlay on /var - system may be read-only\n"); + } else { + printf("Overlay filesystem mounted on /var (base OS is immutable)\n"); + } + + // Mount tmpfs on /run for runtime data + if (system("mkdir -p /run 2>/dev/null") == 0) { + if (system("mount -t tmpfs tmpfs /run 2>/dev/null") != 0) { + fprintf(stderr, "Warning: Failed to mount /run\n"); + } + } + // Initialize network (wired only for bootstrap) printf("Initializing wired network...\n"); if (system("/sbin/init-network 2>/dev/null") != 0) { @@ -108,7 +130,9 @@ int main(int argc, char *argv[]) { printf("Starting shell...\n"); printf("Welcome to SparkOS!\n"); - printf("===================\n\n"); + printf("===================\n"); + printf("Base OS: Read-only (immutable)\n"); + printf("Writable: /tmp, /var (overlay), /run\n\n"); // Main loop - keep respawning shell while (1) {