Create a user-space utility that formats block devices with FAT32.
Writes all required on-disk structures sequentially:
- Boot sector (BPB) with BIOS Parameter Block at sector 0
- FSInfo sector at sector 1 with free cluster count/hint
- Backup boot sector at sector 6, backup FSInfo at sector 7
- Two FAT tables with entries 0-2 initialized (media marker,
EOC markers, root directory cluster EOC)
- Root directory cluster with volume label entry
Geometry calculation:
- Sectors per cluster chosen based on volume size (1-32)
- FAT size computed using Microsoft's formula
- Supports volumes from 128 sectors (~64K) upward
Usage: mkfs.fat32 hdd1mbr1 14336 [LABEL]
The total sector count is required since there is no stat() syscall
yet. Users can find it via 'diskpart <dev> list'.
Also checked off diskpart in README (committed previously).
Create a user-space diskpart utility that can view and modify MBR
partition tables on block devices accessible through /dev.
Features:
- list: displays all 4 partition slots with type, LBA start, size
- create <slot> <type> <start> <sectors>: creates a new partition
- delete <slot>: removes a partition entry
- activate/deactivate <slot>: sets or clears the bootable flag
The tool reads sector 0 (MBR) via VFS open/read, modifies the
partition table in memory, then writes it back via open/write.
Supports hex type codes and provides human-readable type names
for common partition types (FAT12/16/32, Linux, NTFS, etc.).
Usage: diskpart hdd1 create 1 0C 2048 14336
diskpart hdd1 list
diskpart hdd1 delete 2
- FAT32 VFS driver (fat32.h, fat32.c): reads BPB, FAT table, cluster
chains, directory entries (8.3 SFN), file read/write, mount via
fat32_mount_device()
- mount app: writes 'device mountpoint' to /sys/vfs/mount to trigger
FAT32 mount from userspace
- VFS sysfs mount namespace in kernel.c: handles mount requests via
sysfs write to /sys/vfs/mount, delegates to FAT32 driver
- Shell cd: validates target directory exists before updating CWD,
resolves relative paths (., .., components) to absolute paths
- Shell run_command: resolves ARG1 paths relative to CWD so apps
like cat and ls receive absolute paths automatically
- Fixed FAT32 root directory access: use fs->root_cluster when
VFS mount root node has inode=0
Display fixes for UTM/Mac black screen issue:
- Remove MULTIBOOT_HEADER_TAG_FRAMEBUFFER from multiboot2 header (was required,
requesting text mode depth=0 which confused GRUB on some platforms)
- Add COM1 serial port (0x3F8) output alongside debugcon for UTM serial capture
- Change VGA background from black to dark blue for diagnostics
- Add early canary write to 0xB8000 ('COS' in magenta) before subsystem init
- print_hex now outputs to both debugcon and COM1
New ls command and SYS_READDIR syscall:
- SYS_READDIR (10): reads directory entries via VFS
- VFS root listing: vfs_readdir handles '/' by iterating mount table
- apps/ls: lists CWD contents, appends '/' for directories
- apps/libc/syscalls.h: readdir() wrapper
- Created env.c/h: key=value store with ENV_MAX_VARS=32 entries per
process. Supports get, set, unset, and copy operations.
- Added env_block_t and cwd[128] fields to process_t struct.
- process_create() initializes CWD=/ by default.
- Fork inherits environment via memcpy of the entire process_t.
- Added SYS_GETENV (8) and SYS_SETENV (9) system calls.
- Created env-test user app that verifies: CWD default, set/get,
and inheritance across fork.
- Updated kernel.c to launch 'sh' as init process (for next task).
- Updated README.md to check off environment variables task.
Tested: env-test reads CWD=/, sets TEST=hello, reads it back,
forks child which inherits TEST=hello. All verified via QEMU.
- Added paging_clone_directory_from(): deep-copies user-space pages so
parent and child have independent memory. Kernel pages are shared.
- Fixed process_fork() to accept registers_t* for accurate child state,
and to clone from the parent's page directory (not the kernel's).
- Refactored process_exit() to properly context-switch to next process
using new process_switch_to_user assembly stub (loads full registers_t
and performs iret), instead of halting unconditionally.
- Fixed sys_waitpid() to use proper blocking: marks process BLOCKED,
invokes scheduler, and resumes with exit code when child dies.
- Added SYSCALL_SWITCHED mechanism to prevent syscall_handler from
clobbering the next process's EAX after a context switch.
- Created fork-test user app that validates fork + waitpid.
- Added docs/fork.md with architecture documentation.
Tested: fork-test creates child, both print messages, parent waits for
child exit (code 7), parent reaps and exits (code 0). hello-world also
verified to still work correctly after the process_exit refactor.
- Created apps/hello-world/hello-world.S: AT&T assembly user program that
calls SYS_WRITE to print 'Hello, World' then SYS_EXIT(0)
- Created apps/user.ld: linker script for user apps at 0x08048000
- Created scripts/build_apps.sh: builds each app dir into flat binary
- Updated CMakeLists.txt: added apps build target in ISO pipeline
- Updated gen_initrd.sh: packs built binaries from build/apps_bin/
- Updated kernel.c: replaced inline machine code with VFS-based loading
of hello-world from /initrd/hello-world via cpio_find()
Verified: hello-world binary (49 bytes) loads from CPIO initrd,
prints 'Hello, World', and exits with code 0.
Build system changes:
- scripts/gen_initrd.sh packs all files from apps/ into a newc-format
CPIO archive at build/isodir/boot/initrd.cpio.
- CMakeLists.txt adds 'initrd' target as ISO dependency. GRUB loads the
archive as a Multiboot2 module via 'module2 /boot/initrd.cpio'.
- apps/README added as placeholder file for initial ramdisk content.
Kernel changes:
- kernel.c scans Multiboot2 tags for MULTIBOOT_TAG_TYPE_MODULE to find
the initrd's physical address range, then passes it to cpio_init().
- cpio.c/h implements a parser for the SVR4/newc CPIO format:
- cpio_init(): lists archive contents on startup
- cpio_find(): look up a file by name (handles ./ prefix)
- cpio_next(): iterate through all entries
- cpio_count(): count files in archive
- The initrd lives in identity-mapped physical memory, so no additional
mapping is needed to access it.
Verified in QEMU: GRUB loads the module at 0x0014A000, CPIO parser
finds the README file (38 bytes). All existing functionality (Ring 3
processes, syscalls) continues to work.