Add FAT32 driver, mount app, fix shell cd/path resolution

- 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
This commit is contained in:
AI
2026-02-23 14:52:41 +00:00
parent d1bf69ce0d
commit 5229758092
6 changed files with 1198 additions and 8 deletions

View File

@@ -20,6 +20,7 @@
#include "devicefs.h"
#include "sysfs.h"
#include "mbr.h"
#include "fat32.h"
#include "keyboard.h"
#include "framebuffer.h"
@@ -68,6 +69,128 @@ void print_hex(uint32_t val)
outb(0xE9, '\n'); serial_putc('\n');
}
/* ================================================================
* VFS sysfs namespace — handles mount/umount via /sys/vfs
* ================================================================
*
* /sys/vfs/mount — write "device mountpoint" to mount a FAT32 device
* /sys/vfs/mounts — read to list active mounts
*/
/** Last mount status message for reading back. */
static char vfs_sysfs_status[256] = "no mounts\n";
static int vfs_sysfs_list(void *ctx, const char *path, uint32_t idx,
sysfs_entry_t *out) {
(void)ctx;
if (path[0] != '\0') return -1; /* No subdirectories */
static const char *entries[] = { "mount", "mounts" };
if (idx >= 2) return -1;
memset(out, 0, sizeof(sysfs_entry_t));
strncpy(out->name, entries[idx], SYSFS_MAX_NAME - 1);
out->is_dir = 0;
return 0;
}
static int vfs_sysfs_read(void *ctx, const char *path, char *buf,
uint32_t buf_size) {
(void)ctx;
if (strcmp(path, "mount") == 0 || strcmp(path, "mounts") == 0) {
uint32_t len = strlen(vfs_sysfs_status);
if (len + 1 > buf_size) len = buf_size - 1;
memcpy(buf, vfs_sysfs_status, len);
buf[len] = '\0';
return (int)len;
}
return -1;
}
static int vfs_sysfs_write(void *ctx, const char *path, const char *buf,
uint32_t size) {
(void)ctx;
if (strcmp(path, "mount") != 0) return -1;
/* Parse: "device_name mount_path\n" */
char device[64];
char mount_path[128];
int di = 0, mi = 0;
uint32_t i = 0;
/* Parse device name */
while (i < size && buf[i] != ' ' && buf[i] != '\n' && di < 63) {
device[di++] = buf[i++];
}
device[di] = '\0';
/* Skip spaces */
while (i < size && buf[i] == ' ') i++;
/* Parse mount path */
while (i < size && buf[i] != ' ' && buf[i] != '\n' && mi < 127) {
mount_path[mi++] = buf[i++];
}
mount_path[mi] = '\0';
if (di == 0 || mi == 0) {
strncpy(vfs_sysfs_status, "error: usage: device mountpoint\n",
sizeof(vfs_sysfs_status) - 1);
return -1;
}
offset_print(" VFS mount request: ");
offset_print(device);
offset_print(" -> ");
offset_print(mount_path);
offset_print("\n");
/* Find the device */
devicefs_device_t *dev = devicefs_find(device);
if (!dev) {
strncpy(vfs_sysfs_status, "error: device not found\n",
sizeof(vfs_sysfs_status) - 1);
offset_print(" VFS mount: device not found\n");
return -1;
}
/* Mount as FAT32 */
int ret = fat32_mount_device(dev, mount_path);
if (ret != 0) {
strncpy(vfs_sysfs_status, "error: FAT32 mount failed\n",
sizeof(vfs_sysfs_status) - 1);
offset_print(" VFS mount: FAT32 mount failed\n");
return -1;
}
/* Build success message */
strncpy(vfs_sysfs_status, "mounted ", sizeof(vfs_sysfs_status) - 1);
uint32_t slen = strlen(vfs_sysfs_status);
strncpy(vfs_sysfs_status + slen, device,
sizeof(vfs_sysfs_status) - 1 - slen);
slen = strlen(vfs_sysfs_status);
strncpy(vfs_sysfs_status + slen, " at ",
sizeof(vfs_sysfs_status) - 1 - slen);
slen = strlen(vfs_sysfs_status);
strncpy(vfs_sysfs_status + slen, mount_path,
sizeof(vfs_sysfs_status) - 1 - slen);
slen = strlen(vfs_sysfs_status);
if (slen < sizeof(vfs_sysfs_status) - 1) {
vfs_sysfs_status[slen] = '\n';
vfs_sysfs_status[slen + 1] = '\0';
}
return (int)size;
}
static sysfs_ops_t vfs_sysfs_ops = {
.list = vfs_sysfs_list,
.read = vfs_sysfs_read,
.write = vfs_sysfs_write,
};
void kernel_main(uint32_t magic, uint32_t addr) {
/* Initialize serial port first so all debug output goes to COM1 too */
serial_init();
@@ -258,6 +381,10 @@ void kernel_main(uint32_t magic, uint32_t addr) {
EARLY_PRINT("SYS ");
offset_print("Sysfs initialized\n");
/* Register VFS mount namespace in sysfs */
sysfs_register("vfs", &vfs_sysfs_ops, NULL);
offset_print("VFS sysfs namespace registered\n");
init_tss();
EARLY_PRINT("TSS ");
offset_print("TSS initialized\n");