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:
127
src/kernel.c
127
src/kernel.c
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user