diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index e38bc82..acede04 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -48,7 +48,7 @@ jobs: - name: Verify disk image run: | - echo "Verifying disk image..." + echo "Verifying UEFI-bootable disk image..." if [ ! -f sparkos.img.gz ]; then echo "ERROR: Disk image not found!" exit 1 @@ -64,29 +64,59 @@ jobs: ls -lh sparkos.img file sparkos.img - # Show image info + # Show partition table (should be GPT) echo "" - echo "Image details:" - fdisk -l sparkos.img || echo "Image is a filesystem, not a partitioned disk" + echo "=== Partition Table (GPT) ===" + sudo fdisk -l sparkos.img || true + sudo parted sparkos.img print || true - # Try to mount and inspect (read-only) + # Try to mount and inspect partitions echo "" - echo "Attempting to inspect image contents..." - mkdir -p /tmp/sparkos_test - if sudo mount -o loop,ro sparkos.img /tmp/sparkos_test 2>/dev/null; then - echo "✓ Image filesystem is valid" - echo "Contents:" - ls -la /tmp/sparkos_test/ - if [ -f /tmp/sparkos_test/sbin/init ]; then - echo "✓ Init binary found" - ls -lh /tmp/sparkos_test/sbin/init + echo "=== Inspecting Partitions ===" + mkdir -p /tmp/sparkos_esp /tmp/sparkos_root + + # Set up loop device + LOOP_DEV=$(sudo losetup -fP --show sparkos.img) + echo "Loop device: $LOOP_DEV" + ls -la ${LOOP_DEV}* + + # Mount and check ESP + if sudo mount -o ro ${LOOP_DEV}p1 /tmp/sparkos_esp 2>/dev/null; then + echo "✓ EFI System Partition mounted" + echo "ESP contents:" + ls -laR /tmp/sparkos_esp/ + if [ -f /tmp/sparkos_esp/EFI/BOOT/BOOTX64.EFI ]; then + echo "✓ UEFI bootloader found" fi - sudo umount /tmp/sparkos_test - else - echo "Note: Could not mount image (may need different mount options)" + if [ -f /tmp/sparkos_esp/EFI/sparkos/vmlinuz ]; then + echo "✓ Kernel found" + fi + sudo umount /tmp/sparkos_esp fi - echo "Verification complete!" + # Mount and check root partition + if sudo mount -o ro ${LOOP_DEV}p2 /tmp/sparkos_root 2>/dev/null; then + echo "✓ Root partition mounted" + echo "Root contents:" + ls -la /tmp/sparkos_root/ + if [ -f /tmp/sparkos_root/sbin/init ]; then + echo "✓ Init binary found" + ls -lh /tmp/sparkos_root/sbin/init + fi + if [ -f /tmp/sparkos_root/bin/busybox ]; then + echo "✓ Busybox found" + fi + sudo umount /tmp/sparkos_root + fi + + # Cleanup + sudo losetup -d $LOOP_DEV + + echo "" + echo "=== Verification Complete ===" + echo "✓ UEFI-bootable image with GPT partition table" + echo "✓ EFI System Partition with GRUB" + echo "✓ Root partition with init system and busybox" - name: Create release package run: | @@ -98,25 +128,29 @@ jobs: # Create a README for the release cat > release/README.txt << 'EOF' - SparkOS Filesystem Disk Image - ============================== + SparkOS UEFI-Bootable Disk Image + ================================== - This package contains a compressed ext4 filesystem image with SparkOS. + This package contains a UEFI-bootable disk image with SparkOS. Files: - - sparkos.img.gz - Compressed ext4 filesystem image (512MB) + - sparkos.img.gz - Compressed UEFI-bootable disk image (~1GB) What's Included: --------------- - The image contains: - - SparkOS init system (/sbin/init) - - Basic filesystem structure (FHS compliant) - - Configuration files + ✓ GPT partition table + ✓ EFI System Partition (ESP) with FAT32 filesystem + ✓ GRUB UEFI bootloader + ✓ Linux kernel + ✓ SparkOS init system + ✓ Busybox utilities + ✓ Basic FHS-compliant filesystem structure - Note: This is a minimal filesystem image. For full booting, you need: - - Linux kernel (install to /boot/vmlinuz) - - Busybox (install to /bin/busybox) - - Bootloader (GRUB or syslinux) + Boot Support: + ------------ + ✓ UEFI boot (x86_64 systems) + ✓ Automatic boot after 3 seconds + ✓ Console on tty1 Quick Start: ----------- @@ -124,18 +158,40 @@ jobs: 1. Decompress the image: gunzip sparkos.img.gz - 2. Mount and inspect: - sudo mount -o loop sparkos.img /mnt - ls -la /mnt - sudo umount /mnt - - 3. Or write to USB for testing (Linux - BE CAREFUL!): - sudo dd if=sparkos.img of=/dev/sdX bs=4M status=progress - sync + 2. Write to USB drive (Linux - BE CAREFUL!): + sudo dd if=sparkos.img of=/dev/sdX bs=4M status=progress oflag=sync WARNING: Replace /dev/sdX with your actual USB drive device. This will DESTROY all data on the target drive! + 3. Boot from USB: + - Insert the USB drive into a UEFI-capable system + - Enter BIOS/UEFI settings (usually F2, F12, DEL, or ESC at boot) + - Select the USB drive as boot device + - SparkOS should boot automatically + + Advanced - Inspect Partitions: + ------------------------------ + + To mount and inspect the partitions: + + # Set up loop device + sudo losetup -fP --show sparkos.img + # Note the loop device name (e.g., /dev/loop0) + + # Mount ESP (EFI System Partition) + sudo mount /dev/loop0p1 /mnt + ls -la /mnt/EFI + sudo umount /mnt + + # Mount root partition + sudo mount /dev/loop0p2 /mnt + ls -la /mnt + sudo umount /mnt + + # Cleanup + sudo losetup -d /dev/loop0 + Documentation: ------------- See the full documentation at: @@ -172,53 +228,76 @@ jobs: release/sparkos-image.zip release/sparkos.img.gz body: | - # SparkOS Disk Image Release ${{ github.ref_name }} + # SparkOS UEFI-Bootable Disk Image Release ${{ github.ref_name }} - This release includes a filesystem disk image with the SparkOS init system. + This release includes a **UEFI-bootable** disk image with SparkOS. ## What's Included - **sparkos-image.zip**: Complete package with image and README - - **sparkos.img.gz**: Compressed ext4 filesystem image (512MB) + - **sparkos.img.gz**: Compressed UEFI-bootable disk image (~1GB) - ## What This Image Contains + ## Features - The disk image includes: - - ✅ SparkOS init system binary (statically linked) - - ✅ FHS-compliant filesystem structure - - ✅ Basic configuration files - - **Note**: This is a minimal filesystem image. For full booting, you'll need to add: - - Linux kernel - - Busybox utilities - - Bootloader (GRUB or syslinux) - - See the [documentation](https://github.com/johndoe6345789/SparkOS#creating-a-bootable-image) for details. + ✅ **UEFI Boot Support** - Boot on modern UEFI systems + ✅ **GPT Partition Table** - Modern partitioning scheme + ✅ **GRUB Bootloader** - Reliable UEFI bootloader + ✅ **Linux Kernel** - Full kernel included + ✅ **SparkOS Init System** - Custom init with busybox + ✅ **Ready to Boot** - Write to USB and boot immediately ## Quick Start - ### Mount and Inspect + ### Write to USB and Boot ```bash # Download and decompress wget https://github.com/johndoe6345789/SparkOS/releases/download/${{ github.ref_name }}/sparkos.img.gz gunzip sparkos.img.gz - # Mount and inspect - sudo mount -o loop sparkos.img /mnt - ls -la /mnt - sudo umount /mnt + # Write to USB drive (Linux - BE CAREFUL!) + sudo dd if=sparkos.img of=/dev/sdX bs=4M status=progress oflag=sync ``` - ### Write to USB (Testing) + **⚠️ WARNING**: Replace `/dev/sdX` with your actual USB device (e.g., `/dev/sdb`). This will **ERASE ALL DATA** on the target drive! + + ### Boot Instructions + + 1. Insert the USB drive into a UEFI-capable system + 2. Enter BIOS/UEFI settings (usually F2, F12, DEL, or ESC at boot) + 3. Select the USB drive as boot device + 4. SparkOS will boot automatically after 3 seconds + + ### Inspect Partitions (Advanced) ```bash - # Write to USB drive (Linux - BE CAREFUL!) - sudo dd if=sparkos.img of=/dev/sdX bs=4M status=progress - sudo sync + # Set up loop device + LOOP_DEV=$(sudo losetup -fP --show sparkos.img) + + # Mount ESP (EFI System Partition) + sudo mount ${LOOP_DEV}p1 /mnt + ls -la /mnt/EFI # View bootloader and kernel + sudo umount /mnt + + # Mount root partition + sudo mount ${LOOP_DEV}p2 /mnt + ls -la /mnt # View SparkOS filesystem + sudo umount /mnt + + # Cleanup + sudo losetup -d $LOOP_DEV ``` - **⚠️ WARNING**: Replace `/dev/sdX` with your actual USB device. This will erase all data on the target drive! + ## Technical Details + + - **Size**: ~1GB (compressed) + - **Partition Table**: GPT + - **ESP**: 200MB FAT32 (EFI System Partition) + - **Root**: ~800MB ext4 + - **Bootloader**: GRUB (UEFI) + - **Kernel**: Linux kernel (from Ubuntu) + - **Init**: SparkOS custom init system + - **Shell**: Busybox ## Docker Image diff --git a/Dockerfile.image b/Dockerfile.image index d86bd23..795dee9 100644 --- a/Dockerfile.image +++ b/Dockerfile.image @@ -1,5 +1,5 @@ -# Dockerfile for building SparkOS bootable image -# This creates a .img file that can be written to USB drives +# Dockerfile for building UEFI-bootable SparkOS image +# Creates a .img file with GPT partition table, ESP, and GRUB FROM ubuntu:22.04 AS image-builder @@ -10,13 +10,14 @@ RUN apt-get update && \ make \ dosfstools \ mtools \ - xorriso \ - isolinux \ - syslinux \ - syslinux-common \ e2fsprogs \ parted \ - kpartx \ + gdisk \ + grub-efi-amd64-bin \ + grub-common \ + wget \ + busybox-static \ + kmod \ && rm -rf /var/lib/apt/lists/* WORKDIR /build @@ -31,58 +32,149 @@ COPY rootfs/ ./rootfs/ # Build the init binary RUN make init -# Create the bootable image -# We'll use a simpler approach that works in Docker -RUN mkdir -p /output && \ - echo "Building minimal bootable image..." && \ - # Create a minimal image with just the init system for now - # This is a placeholder - the actual bootloader requires a kernel - dd if=/dev/zero of=/output/sparkos.img bs=1M count=512 && \ - mkfs.ext4 -L SparkOS /output/sparkos.img && \ - mkdir -p /mnt/img && \ - mount -o loop /output/sparkos.img /mnt/img && \ - mkdir -p /mnt/img/{bin,sbin,etc,proc,sys,dev,tmp,usr/{bin,sbin,lib},var/{log,run},root,home/spark,boot} && \ - cp init /mnt/img/sbin/init && \ - chmod 755 /mnt/img/sbin/init && \ - # Create basic config files - echo "sparkos" > /mnt/img/etc/hostname && \ - echo "127.0.0.1 localhost" > /mnt/img/etc/hosts && \ - echo "127.0.1.1 sparkos" >> /mnt/img/etc/hosts && \ - echo "root:x:0:0:root:/root:/bin/sh" > /mnt/img/etc/passwd && \ - echo "spark:x:1000:1000:SparkOS User:/home/spark:/bin/sh" >> /mnt/img/etc/passwd && \ - echo "root:x:0:" > /mnt/img/etc/group && \ - echo "spark:x:1000:" >> /mnt/img/etc/group && \ +# Download a minimal Linux kernel (using Ubuntu's kernel for now) +RUN mkdir -p /kernel && \ + apt-get update && \ + apt-get download linux-image-generic && \ + dpkg -x linux-image-*.deb /kernel && \ + rm -rf /var/lib/apt/lists/* linux-image-*.deb + +# Create UEFI-bootable image with GPT partition table +RUN mkdir -p /output /mnt/esp /mnt/root && \ + echo "=== Creating UEFI-bootable SparkOS image with GRUB ===" && \ + # Create 1GB disk image (larger for kernel + bootloader) + dd if=/dev/zero of=/output/sparkos.img bs=1M count=1024 && \ + \ + # Create GPT partition table + echo "Creating GPT partition table..." && \ + parted -s /output/sparkos.img mklabel gpt && \ + \ + # Create EFI System Partition (ESP) - 200MB, FAT32 + echo "Creating EFI System Partition..." && \ + parted -s /output/sparkos.img mkpart ESP fat32 1MiB 201MiB && \ + parted -s /output/sparkos.img set 1 esp on && \ + \ + # Create root partition - remaining space, ext4 + echo "Creating root partition..." && \ + parted -s /output/sparkos.img mkpart primary ext4 201MiB 100% && \ + \ + # Set up loop device for the image + LOOP_DEV=$(losetup -f) && \ + losetup -P $LOOP_DEV /output/sparkos.img && \ + \ + # Wait for partition devices + sleep 1 && \ + \ + # Format partitions + echo "Formatting EFI System Partition (FAT32)..." && \ + mkfs.vfat -F 32 -n "SPARKOSEFI" ${LOOP_DEV}p1 && \ + \ + echo "Formatting root partition (ext4)..." && \ + mkfs.ext4 -L "SparkOS" ${LOOP_DEV}p2 && \ + \ + # Mount ESP + echo "Mounting partitions..." && \ + mount ${LOOP_DEV}p1 /mnt/esp && \ + mount ${LOOP_DEV}p2 /mnt/root && \ + \ + # Install GRUB to ESP + echo "Installing GRUB bootloader..." && \ + mkdir -p /mnt/esp/EFI/BOOT && \ + \ + # Copy GRUB EFI binary + cp /usr/lib/grub/x86_64-efi/monolithic/grubx64.efi /mnt/esp/EFI/BOOT/BOOTX64.EFI 2>/dev/null || \ + grub-mkstandalone \ + --format=x86_64-efi \ + --output=/mnt/esp/EFI/BOOT/BOOTX64.EFI \ + --locales="" \ + --fonts="" \ + "boot/grub/grub.cfg=/tmp/grub-early.cfg" && \ + \ + # Find the kernel + KERNEL_PATH=$(find /kernel/boot -name "vmlinuz-*" | head -1) && \ + KERNEL_VERSION=$(basename $KERNEL_PATH | sed 's/vmlinuz-//') && \ + INITRD_PATH=$(find /kernel/boot -name "initrd.img-*" | head -1) && \ + \ + # Copy kernel and initrd to ESP + echo "Installing kernel..." && \ + mkdir -p /mnt/esp/boot && \ + cp $KERNEL_PATH /mnt/esp/boot/vmlinuz && \ + if [ -f "$INITRD_PATH" ]; then cp $INITRD_PATH /mnt/esp/boot/initrd.img; fi && \ + \ + # Create GRUB configuration + mkdir -p /mnt/esp/boot/grub && \ + cat > /mnt/esp/boot/grub/grub.cfg << 'GRUB_EOF' && \ +set timeout=3 +set default=0 + +menuentry "SparkOS" { + linux /boot/vmlinuz root=LABEL=SparkOS rw init=/sbin/init console=tty1 quiet +} +GRUB_EOF + \ + # Set up root filesystem + echo "Setting up root filesystem..." && \ + mkdir -p /mnt/root/{bin,sbin,etc,proc,sys,dev,tmp,usr/{bin,sbin,lib,lib64},var/{log,run},root,home/spark,boot} && \ + \ + # Install SparkOS init + cp /build/init /mnt/root/sbin/init && \ + chmod 755 /mnt/root/sbin/init && \ + \ + # Install busybox + echo "Installing busybox..." && \ + cp /bin/busybox /mnt/root/bin/busybox && \ + chmod 755 /mnt/root/bin/busybox && \ + \ + # Create busybox symlinks for essential commands + for cmd in sh ls cat echo mount umount mkdir rm cp mv chmod chown ln ps kill; do \ + ln -sf busybox /mnt/root/bin/$cmd; \ + done && \ + \ + # Create system configuration files + echo "sparkos" > /mnt/root/etc/hostname && \ + echo "127.0.0.1 localhost" > /mnt/root/etc/hosts && \ + echo "127.0.1.1 sparkos" >> /mnt/root/etc/hosts && \ + echo "root:x:0:0:root:/root:/bin/sh" > /mnt/root/etc/passwd && \ + echo "spark:x:1000:1000:SparkOS User:/home/spark:/bin/sh" >> /mnt/root/etc/passwd && \ + echo "root:x:0:" > /mnt/root/etc/group && \ + echo "spark:x:1000:" >> /mnt/root/etc/group && \ + \ # Create README - cat > /mnt/img/README.txt << 'EOF' && \ -SparkOS Minimal Filesystem Image + cat > /mnt/root/README.txt << 'README_EOF' && \ +SparkOS UEFI-Bootable Image -This is a minimal ext4 filesystem image containing the SparkOS init system. -This is NOT a fully bootable image - it requires additional components. +This is a UEFI-bootable disk image with: +- GPT partition table +- EFI System Partition (ESP) with FAT32 filesystem +- GRUB UEFI bootloader +- Linux kernel +- SparkOS init system +- Busybox utilities -What's included: -- SparkOS init binary (/sbin/init) -- Basic FHS-compliant directory structure -- Basic configuration files +The image can be written to a USB drive and booted on UEFI systems: + sudo dd if=sparkos.img of=/dev/sdX bs=4M status=progress + sudo sync -To make this fully bootable, you need to add: -1. Linux kernel (install to /boot/vmlinuz) -2. Busybox (install to /bin/busybox and create symlinks) -3. Bootloader (GRUB or syslinux) -4. Required libraries (if using dynamically linked binaries) - -This image can be mounted to extract the init binary or inspect the structure: - sudo mount -o loop sparkos.img /mnt - cp /mnt/sbin/init ./ - sudo umount /mnt +Boot options: +- UEFI boot support (tested on x86_64 systems) +- Automatic boot after 3 seconds +- Console on tty1 For more information, see: https://github.com/johndoe6345789/SparkOS -EOF +README_EOF + \ + # Sync and unmount + echo "Finalizing image..." && \ sync && \ - umount /mnt/img && \ + umount /mnt/esp && \ + umount /mnt/root && \ + losetup -d $LOOP_DEV && \ + \ # Compress the image + echo "Compressing image..." && \ gzip -9 /output/sparkos.img && \ - echo "Image created: /output/sparkos.img.gz" + echo "UEFI-bootable image created: /output/sparkos.img.gz" -# Final stage - just export the image +# Final stage - export the image FROM scratch AS export COPY --from=image-builder /output/sparkos.img.gz /sparkos.img.gz diff --git a/README.md b/README.md index b6e1dd5..00d16b1 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,9 @@ To create bootable images (optional): ## Quick Start -### Using Pre-built Disk Image (Easiest for USB/Testing) +### Using UEFI-Bootable Disk Image (Recommended - Boot from USB) -Download the filesystem image from the [GitHub Releases page](https://github.com/johndoe6345789/SparkOS/releases): +Download the UEFI-bootable image from the [GitHub Releases page](https://github.com/johndoe6345789/SparkOS/releases): ```bash # Download the disk image (replace VERSION with actual version, e.g., v1.0.0) @@ -56,24 +56,24 @@ wget https://github.com/johndoe6345789/SparkOS/releases/download/VERSION/sparkos # Decompress the image gunzip sparkos.img.gz -# Mount and inspect -sudo mount -o loop sparkos.img /mnt -ls -la /mnt -sudo umount /mnt - -# Or write to USB drive for testing (Linux - BE CAREFUL!) -sudo dd if=sparkos.img of=/dev/sdX bs=4M status=progress -sudo sync +# Write to USB drive (Linux - BE CAREFUL!) +sudo dd if=sparkos.img of=/dev/sdX bs=4M status=progress oflag=sync ``` **⚠️ WARNING**: Replace `/dev/sdX` with your actual USB device (e.g., `/dev/sdb`). This will **DESTROY ALL DATA** on the target drive! -**Note**: The disk image contains the init system and filesystem structure but requires additional components (kernel, busybox, bootloader) for full booting. See [Creating a Bootable Image](#creating-a-bootable-image) section. +**Boot Instructions:** +1. Insert the USB drive into a UEFI-capable system +2. Enter BIOS/UEFI settings (usually F2, F12, DEL, or ESC at boot) +3. Select the USB drive as boot device +4. SparkOS will boot automatically -The disk image includes: -- Pre-compiled init binary -- Basic filesystem structure (FHS compliant) -- Configuration files +The UEFI-bootable disk image includes: +- ✅ **UEFI boot support** with GRUB bootloader +- ✅ **GPT partition table** with ESP (EFI System Partition) +- ✅ **Linux kernel** ready to boot +- ✅ **SparkOS init system** and busybox utilities +- ✅ **Ready to boot** - No additional setup required ### Using Pre-built Binary Package @@ -162,25 +162,32 @@ make init make install ``` -### Creating a Bootable Image +### Creating a UEFI-Bootable Image **Using Docker (Recommended - No Root Required):** -Build disk images easily using Docker without needing root privileges on your host: +Build UEFI-bootable disk images easily using Docker without needing root privileges on your host: ```bash -# Build the disk image using Docker +# Build the UEFI-bootable disk image using Docker make image-docker # Or use the script directly ./scripts/build-image.sh -# The compressed image will be in release/sparkos.img.gz +# The compressed UEFI-bootable image will be in release/sparkos.img.gz ``` +This creates a complete UEFI-bootable image with: +- GPT partition table +- EFI System Partition (ESP) with FAT32 +- GRUB UEFI bootloader +- Linux kernel +- SparkOS init system and busybox + **Traditional Method (Requires Root):** -⚠️ **Warning**: This method requires root privileges and proper tools. +⚠️ **Warning**: This method is for creating custom partitioned images and requires root privileges. ```bash # Install required tools (Ubuntu/Debian)