menios icon indicating copy to clipboard operation
menios copied to clipboard

Mount FAT32 boot drive as /boot and ext2 as root /

Open pbalduino opened this issue 3 months ago • 0 comments

Goal

Restructure meniOS filesystem layout to use FAT32 for boot partition (mounted at /boot) and ext2 for root filesystem (mounted at /), following standard Linux boot patterns.

Context

Currently, meniOS mounts a single FAT32 partition as the root filesystem. This works but has limitations:

  • FAT32 lacks POSIX permissions, ownership, and symbolic links
  • Mixing bootloader files with system files is non-standard
  • No support for proper UNIX filesystem features

The new layout will:

  • Use FAT32 for /boot (bootloader, kernel, initrd - UEFI/BIOS compatible)
  • Use ext2 for / (system files, binaries, user data - full UNIX features)
  • Follow standard Linux filesystem hierarchy

Definition of Done

  • Dual partition support: Detect and mount both FAT32 and ext2 partitions
  • Boot partition: FAT32 mounted at /boot with kernel and bootloader files
  • Root partition: ext2 mounted at / with full system
  • VFS hierarchy: Proper mount point structure with /boot subdirectory
  • Boot process: Update boot sequence to handle dual-partition setup
  • /bin migration: Move all binaries from FAT32 to ext2 /bin
  • Fallback: Graceful fallback if ext2 partition not found

Current vs. New Layout

Current (Single Partition)

/dev/sda1 (FAT32) mounted as /
├── /boot (bootloader files mixed with system)
│   ├── kernel.elf
│   └── limine.cfg
├── /bin
│   ├── mosh
│   ├── cat
│   ├── echo
│   └── ...
├── /dev
├── /tmp
└── /proc

New (Dual Partition)

/dev/sda1 (FAT32) mounted as /boot
├── EFI/
│   └── BOOT/
│       └── BOOTX64.EFI
├── limine.cfg
├── kernel.elf
└── initrd (future)

/dev/sda2 (ext2) mounted as /
├── /boot (mount point for sda1)
├── /bin (moved from FAT32)
│   ├── mosh
│   ├── cat
│   ├── echo
│   └── ...
├── /dev
├── /tmp
├── /proc
├── /etc
├── /home
├── /usr
├── /var
└── /root

Implementation Details

Partition Detection

// Detect partition table (GPT or MBR)
struct partition_table {
    enum { PT_GPT, PT_MBR } type;
    int num_partitions;
    struct partition *partitions;
};

struct partition {
    uint32_t start_lba;
    uint32_t size_blocks;
    uint8_t type_guid[16];  // GPT
    uint8_t type;           // MBR (0x0B/0x0C for FAT32, 0x83 for Linux)
    char *fs_type;          // "fat32" or "ext2"
};

int detect_partition_table(struct block_device *bdev, struct partition_table *pt);
struct partition *find_partition_by_type(struct partition_table *pt, const char *fs_type);

Boot Sequence Changes

// New boot initialization sequence
void init_filesystems(void) {
    struct partition_table pt;
    
    // 1. Detect partitions
    detect_partition_table(root_block_device, &pt);
    
    // 2. Find and mount boot partition (FAT32)
    struct partition *boot_part = find_partition_by_type(&pt, "fat32");
    if (boot_part) {
        struct superblock *boot_sb = mount_partition(boot_part, "fat32");
        vfs_mount(boot_sb, "/boot");
        kprintf("Mounted FAT32 boot partition at /boot\n");
    }
    
    // 3. Find and mount root partition (ext2)
    struct partition *root_part = find_partition_by_type(&pt, "ext2");
    if (root_part) {
        struct superblock *root_sb = mount_partition(root_part, "ext2");
        vfs_mount(root_sb, "/");
        kprintf("Mounted ext2 root partition at /\n");
    } else {
        // Fallback: mount FAT32 as root
        kprintf("WARNING: No ext2 partition found, using FAT32 as root\n");
        vfs_mount(boot_sb, "/");
    }
    
    // 4. Mount special filesystems
    mount_devfs();
    mount_tmpfs();
    mount_procfs();
}

Mount Point Management

// VFS mount point structure
struct mount_point {
    char *path;                     // Mount path (e.g., "/boot")
    struct superblock *sb;          // Mounted filesystem superblock
    struct dentry *root;            // Root dentry of mounted fs
    struct list_head list;          // List of all mounts
};

// Mount operations
int vfs_mount(struct superblock *sb, const char *path);
int vfs_umount(const char *path);
struct mount_point *vfs_find_mount(const char *path);
int vfs_is_mount_point(struct dentry *dentry);

Path Resolution with Mount Points

// Path lookup must handle mount points
struct dentry *vfs_path_lookup(const char *path) {
    struct dentry *current = root_dentry;
    
    // Split path and traverse
    while (has_more_components(path)) {
        const char *component = next_component(&path);
        
        // Check if current is a mount point
        struct mount_point *mp = vfs_find_mount(current->full_path);
        if (mp) {
            current = mp->root;  // Switch to mounted filesystem root
        }
        
        current = lookup_component(current, component);
    }
    
    return current;
}

Disk Image Creation

#!/bin/bash
# create_dual_boot_disk.sh

# Create disk image (1GB)
dd if=/dev/zero of=menios.img bs=1M count=1024

# Create partition table
parted menios.img mklabel gpt

# Create boot partition (100MB FAT32)
parted menios.img mkpart primary fat32 1MiB 101MiB
parted menios.img set 1 boot on

# Create root partition (900MB ext2)
parted menios.img mkpart primary ext2 101MiB 100%

# Format partitions
LOOP=$(sudo losetup -fP --show menios.img)
sudo mkfs.vfat -F 32 ${LOOP}p1
sudo mkfs.ext2 ${LOOP}p2

# Mount and populate boot partition
mkdir -p /tmp/boot
sudo mount ${LOOP}p1 /tmp/boot
sudo mkdir -p /tmp/boot/EFI/BOOT
sudo cp build/kernel.elf /tmp/boot/
sudo cp limine.cfg /tmp/boot/
sudo umount /tmp/boot

# Mount and populate root partition
mkdir -p /tmp/root
sudo mount ${LOOP}p2 /tmp/root
sudo mkdir -p /tmp/root/{bin,dev,tmp,proc,etc,home,usr,var,root,boot}
sudo cp build/bin/* /tmp/root/bin/
sudo umount /tmp/root

sudo losetup -d $LOOP

Bootloader Configuration

# limine.cfg - Updated for dual partition boot

TIMEOUT=3

:meniOS
PROTOCOL=limine
KERNEL_PATH=boot:///kernel.elf
KERNEL_CMDLINE=root=/dev/sda2 rootfstype=ext2 init=/bin/init

# Note: Bootloader lives on FAT32 partition (sda1)
# Kernel parameter tells OS to mount ext2 sda2 as root

Migration Strategy

Phase 1: Partition Detection

  • Implement GPT/MBR partition table reading
  • Partition type detection (FAT32 vs ext2)
  • Multi-partition mounting infrastructure

Phase 2: Mount Point Support

  • VFS mount point management
  • Path lookup across mount points
  • Mount/umount syscalls

Phase 3: Dual Boot Setup

  • Update boot sequence to mount both partitions
  • FAT32 at /boot, ext2 at /
  • Fallback to single FAT32 partition if needed

Phase 4: Binary Migration

  • Build system changes to install binaries to ext2
  • Copy existing /bin contents from FAT32 to ext2
  • Update PATH to use ext2 /bin

Phase 5: Standard Hierarchy

  • Create standard directories on ext2
  • Move configuration to /etc
  • User homes in /home
  • Logs in /var/log

Kernel Command Line Support

// Parse kernel command line for root partition
struct boot_params {
    char *root_device;      // "root=/dev/sda2"
    char *root_fstype;      // "rootfstype=ext2"
    char *init_path;        // "init=/bin/init"
};

void parse_kernel_cmdline(const char *cmdline, struct boot_params *params);
int mount_root_from_params(struct boot_params *params);

Testing Strategy

  • Test dual-partition detection
  • Verify FAT32 boot partition mounting
  • Verify ext2 root partition mounting
  • Test path resolution across mount points
  • Verify /bin executables work from ext2
  • Test fallback to single FAT32 partition
  • Verify boot process with new layout

Rollback Strategy

  • Keep old single-partition boot working
  • Fallback if ext2 partition missing
  • Bootloader can boot old layout
  • Gradual migration path

Dependencies

  • ext2 support: #227 (ext2 filesystem implementation)
  • VFS layer: #65 (already complete)
  • Partition table parsing: Need GPT/MBR parser
  • Block device: Block device layer (already complete)
  • Mount syscalls: mount/umount support

Benefits

  • Standard Linux filesystem layout
  • Proper POSIX permissions on system files
  • Bootloader files isolated in /boot
  • Symbolic link support in root filesystem
  • Better organization and security
  • Path to supporting multiple filesystems

Risks and Mitigations

  • Risk: Breaking existing boot process
    • Mitigation: Keep fallback to single FAT32
  • Risk: Partition detection failures
    • Mitigation: Robust error handling, fallback mode
  • Risk: Build system complexity
    • Mitigation: Incremental migration, dual support initially

Files to Create/Modify

  • src/kernel/fs/partition.c - Partition table parsing
  • src/kernel/fs/mount.c - Mount point management
  • src/kernel/init/boot_params.c - Kernel cmdline parsing
  • src/kernel/init/fs_init.c - Dual filesystem initialization
  • scripts/create_boot_disk.sh - Disk image creation
  • limine.cfg - Bootloader configuration
  • Makefile - Build system updates for dual partition

Deliverables

  • GPT/MBR partition detection
  • Multi-partition mount support
  • FAT32 /boot + ext2 / working
  • Binaries running from ext2 partition
  • Build system creating dual-partition images
  • Documentation for new layout
  • Migration guide

Related Issues

  • #227 - ext2 filesystem support (required)
  • #65 - VFS layer
  • #228 - Binary migration to ext2 (companion issue)

Dependencies

Required (Blocking)

  • #154 - ext2 read-only support (need to mount ext2 partition)
  • #227 - Full ext2 implementation (need write support for root filesystem)
  • #65 - VFS layer ✅ COMPLETE
  • Partition table parsing - Need GPT/MBR detection (new issue needed)
  • Mount point support - Need VFS mount point management (new issue needed)

Blocks (Downstream)

  • #229 - Migrate /bin utilities to ext2 (requires dual partition setup)

Priority

Medium - Standard Linux layout, not blocking critical milestones immediately

Justification

  • Provides proper UNIX filesystem hierarchy
  • Enables POSIX permissions on system files
  • Better separation of boot and system files
  • Not immediately needed for Doom or GCC milestones
  • FAT32 single-partition works for current development
  • Nice upgrade for production system

Implementation Phases

Phase 1: Partition Detection (1 week)

  • Implement GPT partition table reading
  • Implement MBR partition table reading
  • Partition type detection (0x0B/0x0C for FAT32, 0x83 for Linux)
  • Multi-partition enumeration

Phase 2: VFS Mount Points (1 week)

  • Mount point data structures
  • Path lookup across mount boundaries
  • Mount/unmount syscall infrastructure
  • /proc/mounts support

Phase 3: Dual Mount Setup (1 week)

  • Boot sequence changes
  • Mount FAT32 as /boot
  • Mount ext2 as /
  • Fallback to single FAT32 if ext2 missing
  • Kernel command line parsing (root=, rootfstype=)

Phase 4: Build System (1 week)

  • Disk image creation script (dual partition)
  • Partition formatting and population
  • Bootloader configuration updates
  • Install targets for both partitions

Phase 5: Testing & Migration (1 week)

  • Test dual-partition boot
  • Verify path resolution across mounts
  • Test fallback scenarios
  • Document migration procedure

Total Estimated: 5 weeks

Current Status

Blocked - Waiting for:

  1. #154 (ext2 read-only) - In progress
  2. #227 (ext2 write support) - Not started
  3. Partition table parser - Not created
  4. VFS mount point support - Not created

Recommend creating issues for partition table parsing and mount point management before starting this work.

pbalduino avatar Oct 09 '25 03:10 pbalduino