mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
CHECKP: semi-stable vfs
This commit is contained in:
parent
5933483009
commit
38ed0b5ffa
6 changed files with 704 additions and 456 deletions
BIN
disk.img
BIN
disk.img
Binary file not shown.
|
|
@ -9,8 +9,11 @@
|
||||||
#include "ahci.h"
|
#include "ahci.h"
|
||||||
#include "../fs/vfs.h"
|
#include "../fs/vfs.h"
|
||||||
#include "../fs/fat32.h"
|
#include "../fs/fat32.h"
|
||||||
|
#include "../sys/spinlock.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
static spinlock_t ide_lock = SPINLOCK_INIT;
|
||||||
|
|
||||||
static Disk *disks[MAX_DISKS];
|
static Disk *disks[MAX_DISKS];
|
||||||
static int disk_count = 0;
|
static int disk_count = 0;
|
||||||
static int next_drive_letter_idx = 0; // For backward compat
|
static int next_drive_letter_idx = 0; // For backward compat
|
||||||
|
|
@ -75,12 +78,17 @@ typedef struct {
|
||||||
|
|
||||||
// === ATA PIO Driver ===
|
// === ATA PIO Driver ===
|
||||||
|
|
||||||
static void ata_wait_bsy(uint16_t port_base) {
|
static int ata_wait_bsy(uint16_t port_base) {
|
||||||
while (inb(port_base + ATA_REG_STATUS) & ATA_SR_BSY);
|
int timeout = 10000000;
|
||||||
|
while ((inb(port_base + ATA_REG_STATUS) & ATA_SR_BSY) && --timeout > 0);
|
||||||
|
return timeout <= 0 ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ata_wait_drq(uint16_t port_base) {
|
static int ata_wait_drq(uint16_t port_base) {
|
||||||
while (!(inb(port_base + ATA_REG_STATUS) & ATA_SR_DRQ));
|
int timeout = 10000000;
|
||||||
|
while (!(inb(port_base + ATA_REG_STATUS) & (ATA_SR_DRQ | ATA_SR_ERR)) && --timeout > 0);
|
||||||
|
if (timeout <= 0 || (inb(port_base + ATA_REG_STATUS) & ATA_SR_ERR)) return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ata_identify(uint16_t port_base, bool slave) {
|
static int ata_identify(uint16_t port_base, bool slave) {
|
||||||
|
|
@ -104,7 +112,7 @@ static int ata_identify(uint16_t port_base, bool slave) {
|
||||||
|
|
||||||
if (inb(port_base + ATA_REG_STATUS) & ATA_SR_ERR) return 0;
|
if (inb(port_base + ATA_REG_STATUS) & ATA_SR_ERR) return 0;
|
||||||
|
|
||||||
while (!(inb(port_base + ATA_REG_STATUS) & (ATA_SR_DRQ | ATA_SR_ERR)));
|
if (ata_wait_drq(port_base) != 0) return 0;
|
||||||
|
|
||||||
if (inb(port_base + ATA_REG_STATUS) & ATA_SR_ERR) return 0;
|
if (inb(port_base + ATA_REG_STATUS) & ATA_SR_ERR) return 0;
|
||||||
|
|
||||||
|
|
@ -132,7 +140,12 @@ static int ata_read_sector(Disk *disk, uint32_t lba, uint8_t *buffer) {
|
||||||
slave = data->slave;
|
slave = data->slave;
|
||||||
}
|
}
|
||||||
|
|
||||||
ata_wait_bsy(port_base);
|
uint64_t flags = spinlock_acquire_irqsave(&ide_lock);
|
||||||
|
|
||||||
|
if (ata_wait_bsy(port_base) != 0) {
|
||||||
|
spinlock_release_irqrestore(&ide_lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
outb(port_base + ATA_REG_HDDEVSEL, 0xE0 | (slave << 4) | ((lba >> 24) & 0x0F));
|
outb(port_base + ATA_REG_HDDEVSEL, 0xE0 | (slave << 4) | ((lba >> 24) & 0x0F));
|
||||||
outb(port_base + ATA_REG_FEATURES, 0x00);
|
outb(port_base + ATA_REG_FEATURES, 0x00);
|
||||||
|
|
@ -142,14 +155,21 @@ static int ata_read_sector(Disk *disk, uint32_t lba, uint8_t *buffer) {
|
||||||
outb(port_base + ATA_REG_LBA2, (uint8_t)(lba >> 16));
|
outb(port_base + ATA_REG_LBA2, (uint8_t)(lba >> 16));
|
||||||
outb(port_base + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
outb(port_base + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
||||||
|
|
||||||
ata_wait_bsy(port_base);
|
if (ata_wait_bsy(port_base) != 0) {
|
||||||
ata_wait_drq(port_base);
|
spinlock_release_irqrestore(&ide_lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ata_wait_drq(port_base) != 0) {
|
||||||
|
spinlock_release_irqrestore(&ide_lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t *ptr = (uint16_t*)buffer;
|
uint16_t *ptr = (uint16_t*)buffer;
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
ptr[i] = inw(port_base + ATA_REG_DATA);
|
ptr[i] = inw(port_base + ATA_REG_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spinlock_release_irqrestore(&ide_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,7 +186,12 @@ static int ata_write_sector(Disk *disk, uint32_t lba, const uint8_t *buffer) {
|
||||||
slave = data->slave;
|
slave = data->slave;
|
||||||
}
|
}
|
||||||
|
|
||||||
ata_wait_bsy(port_base);
|
uint64_t flags = spinlock_acquire_irqsave(&ide_lock);
|
||||||
|
|
||||||
|
if (ata_wait_bsy(port_base) != 0) {
|
||||||
|
spinlock_release_irqrestore(&ide_lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
outb(port_base + ATA_REG_HDDEVSEL, 0xE0 | (slave << 4) | ((lba >> 24) & 0x0F));
|
outb(port_base + ATA_REG_HDDEVSEL, 0xE0 | (slave << 4) | ((lba >> 24) & 0x0F));
|
||||||
outb(port_base + ATA_REG_FEATURES, 0x00);
|
outb(port_base + ATA_REG_FEATURES, 0x00);
|
||||||
|
|
@ -176,8 +201,14 @@ static int ata_write_sector(Disk *disk, uint32_t lba, const uint8_t *buffer) {
|
||||||
outb(port_base + ATA_REG_LBA2, (uint8_t)(lba >> 16));
|
outb(port_base + ATA_REG_LBA2, (uint8_t)(lba >> 16));
|
||||||
outb(port_base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
outb(port_base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
||||||
|
|
||||||
ata_wait_bsy(port_base);
|
if (ata_wait_bsy(port_base) != 0) {
|
||||||
ata_wait_drq(port_base);
|
spinlock_release_irqrestore(&ide_lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ata_wait_drq(port_base) != 0) {
|
||||||
|
spinlock_release_irqrestore(&ide_lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
const uint16_t *ptr = (const uint16_t*)buffer;
|
const uint16_t *ptr = (const uint16_t*)buffer;
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
|
|
@ -185,8 +216,12 @@ static int ata_write_sector(Disk *disk, uint32_t lba, const uint8_t *buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
outb(port_base + ATA_REG_COMMAND, 0xE7); // Cache Flush
|
outb(port_base + ATA_REG_COMMAND, 0xE7); // Cache Flush
|
||||||
ata_wait_bsy(port_base);
|
if (ata_wait_bsy(port_base) != 0) {
|
||||||
|
spinlock_release_irqrestore(&ide_lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_release_irqrestore(&ide_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
943
src/fs/fat32.c
943
src/fs/fat32.c
File diff suppressed because it is too large
Load diff
|
|
@ -101,6 +101,8 @@ typedef struct {
|
||||||
bool valid; // Is this handle valid?
|
bool valid; // Is this handle valid?
|
||||||
uint32_t dir_sector; // Sector containing the directory entry
|
uint32_t dir_sector; // Sector containing the directory entry
|
||||||
uint32_t dir_offset; // Offset within that sector
|
uint32_t dir_offset; // Offset within that sector
|
||||||
|
bool is_directory; // Is this a directory?
|
||||||
|
uint8_t attributes; // File attributes
|
||||||
void *volume; // Pointer to owning FAT32_Volume (or NULL for ramfs)
|
void *volume; // Pointer to owning FAT32_Volume (or NULL for ramfs)
|
||||||
} FAT32_FileHandle;
|
} FAT32_FileHandle;
|
||||||
|
|
||||||
|
|
|
||||||
42
src/fs/vfs.c
42
src/fs/vfs.c
|
|
@ -339,12 +339,14 @@ void vfs_close(vfs_file_t *file) {
|
||||||
int vfs_read(vfs_file_t *file, void *buf, int size) {
|
int vfs_read(vfs_file_t *file, void *buf, int size) {
|
||||||
if (!file || !file->valid || !file->mount) return -1;
|
if (!file || !file->valid || !file->mount) return -1;
|
||||||
if (!file->mount->ops->read) return -1;
|
if (!file->mount->ops->read) return -1;
|
||||||
|
|
||||||
return file->mount->ops->read(file->mount->fs_private, file->fs_handle, buf, size);
|
return file->mount->ops->read(file->mount->fs_private, file->fs_handle, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vfs_write(vfs_file_t *file, const void *buf, int size) {
|
int vfs_write(vfs_file_t *file, const void *buf, int size) {
|
||||||
if (!file || !file->valid || !file->mount) return -1;
|
if (!file || !file->valid || !file->mount) return -1;
|
||||||
if (!file->mount->ops->write) return -1;
|
if (!file->mount->ops->write) return -1;
|
||||||
|
|
||||||
return file->mount->ops->write(file->mount->fs_private, file->fs_handle, buf, size);
|
return file->mount->ops->write(file->mount->fs_private, file->fs_handle, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,6 +375,7 @@ uint32_t vfs_file_size(vfs_file_t *file) {
|
||||||
int vfs_list_directory(const char *path, vfs_dirent_t *entries, int max) {
|
int vfs_list_directory(const char *path, vfs_dirent_t *entries, int max) {
|
||||||
if (!path || !entries) return -1;
|
if (!path || !entries) return -1;
|
||||||
|
|
||||||
|
|
||||||
char normalized[VFS_MAX_PATH];
|
char normalized[VFS_MAX_PATH];
|
||||||
vfs_normalize_path(path, normalized);
|
vfs_normalize_path(path, normalized);
|
||||||
|
|
||||||
|
|
@ -483,10 +486,15 @@ bool vfs_mkdir(const char *path) {
|
||||||
|
|
||||||
const char *rel_path = NULL;
|
const char *rel_path = NULL;
|
||||||
vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path);
|
vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path);
|
||||||
|
|
||||||
|
// If it's in /dev/, check if it's within a mounted volume deeper than the device node
|
||||||
|
if (vfs_starts_with(normalized, "/dev/")) {
|
||||||
|
if (!mount || !rel_path || rel_path[0] == '\0') {
|
||||||
|
return false; // Protect raw device nodes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!mount || !mount->ops->mkdir) return false;
|
if (!mount || !mount->ops->mkdir) return false;
|
||||||
|
|
||||||
if (!rel_path || rel_path[0] == '\0') return false;
|
|
||||||
|
|
||||||
return mount->ops->mkdir(mount->fs_private, rel_path);
|
return mount->ops->mkdir(mount->fs_private, rel_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -496,17 +504,21 @@ bool vfs_rmdir(const char *path) {
|
||||||
char normalized[VFS_MAX_PATH];
|
char normalized[VFS_MAX_PATH];
|
||||||
vfs_normalize_path(path, normalized);
|
vfs_normalize_path(path, normalized);
|
||||||
|
|
||||||
// Protect root and virtual directories
|
// Protect root and virtual /dev directory itself
|
||||||
if (normalized[0] == '/' && normalized[1] == '\0') return false;
|
if (normalized[0] == '/' && normalized[1] == '\0') return false;
|
||||||
if (vfs_strcmp(normalized, "/dev") == 0) return false;
|
if (vfs_strcmp(normalized, "/dev") == 0) return false;
|
||||||
if (vfs_starts_with(normalized, "/dev/")) return false;
|
|
||||||
|
|
||||||
const char *rel_path = NULL;
|
const char *rel_path = NULL;
|
||||||
vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path);
|
vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path);
|
||||||
|
|
||||||
|
// If it's in /dev/, allow only if it's inside a mount beyond the device node
|
||||||
|
if (vfs_starts_with(normalized, "/dev/")) {
|
||||||
|
if (!mount || !rel_path || rel_path[0] == '\0') {
|
||||||
|
return false; // Protect raw device nodes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!mount || !mount->ops->rmdir) return false;
|
if (!mount || !mount->ops->rmdir) return false;
|
||||||
|
|
||||||
if (!rel_path || rel_path[0] == '\0') return false;
|
|
||||||
|
|
||||||
return mount->ops->rmdir(mount->fs_private, rel_path);
|
return mount->ops->rmdir(mount->fs_private, rel_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -516,17 +528,21 @@ bool vfs_delete(const char *path) {
|
||||||
char normalized[VFS_MAX_PATH];
|
char normalized[VFS_MAX_PATH];
|
||||||
vfs_normalize_path(path, normalized);
|
vfs_normalize_path(path, normalized);
|
||||||
|
|
||||||
// Protect root and virtual directories
|
// Protect root and virtual /dev directory itself
|
||||||
if (normalized[0] == '/' && normalized[1] == '\0') return false;
|
if (normalized[0] == '/' && normalized[1] == '\0') return false;
|
||||||
if (vfs_strcmp(normalized, "/dev") == 0) return false;
|
if (vfs_strcmp(normalized, "/dev") == 0) return false;
|
||||||
if (vfs_starts_with(normalized, "/dev/")) return false;
|
|
||||||
|
|
||||||
const char *rel_path = NULL;
|
const char *rel_path = NULL;
|
||||||
vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path);
|
vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path);
|
||||||
|
|
||||||
|
// If it's in /dev/, allow only if it's inside a mount beyond the device node
|
||||||
|
if (vfs_starts_with(normalized, "/dev/")) {
|
||||||
|
if (!mount || !rel_path || rel_path[0] == '\0') {
|
||||||
|
return false; // Protect raw device nodes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!mount || !mount->ops->unlink) return false;
|
if (!mount || !mount->ops->unlink) return false;
|
||||||
|
|
||||||
if (!rel_path || rel_path[0] == '\0') return false;
|
|
||||||
|
|
||||||
return mount->ops->unlink(mount->fs_private, rel_path);
|
return mount->ops->unlink(mount->fs_private, rel_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -709,7 +709,13 @@ static void explorer_load_directory(Window *win, const char *path) {
|
||||||
if (!entries) return;
|
if (!entries) return;
|
||||||
|
|
||||||
int count = vfs_list_directory(path, entries, capacity);
|
int count = vfs_list_directory(path, entries, capacity);
|
||||||
|
|
||||||
|
// Trace string to see if we reached here
|
||||||
|
extern void serial_write(const char*); extern void serial_write_num(uint32_t);
|
||||||
|
serial_write("[EXPLORER] load_directory: "); serial_write(path); serial_write(" | loop start. count: "); serial_write_num(count); serial_write("\n");
|
||||||
|
|
||||||
while (count == capacity) {
|
while (count == capacity) {
|
||||||
|
serial_write("[EXPLORER] Doubling capacity to: "); serial_write_num(capacity * 2); serial_write("\n");
|
||||||
capacity *= 2;
|
capacity *= 2;
|
||||||
vfs_dirent_t *new_entries = (vfs_dirent_t*)krealloc(entries, capacity * sizeof(vfs_dirent_t));
|
vfs_dirent_t *new_entries = (vfs_dirent_t*)krealloc(entries, capacity * sizeof(vfs_dirent_t));
|
||||||
if (!new_entries) { kfree(entries); return; }
|
if (!new_entries) { kfree(entries); return; }
|
||||||
|
|
@ -717,6 +723,8 @@ static void explorer_load_directory(Window *win, const char *path) {
|
||||||
count = vfs_list_directory(path, entries, capacity);
|
count = vfs_list_directory(path, entries, capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serial_write("[EXPLORER] load_directory loop complete.\n");
|
||||||
|
|
||||||
if (state->items_capacity < count) {
|
if (state->items_capacity < count) {
|
||||||
int new_cap = count < EXPLORER_INITIAL_CAPACITY ? EXPLORER_INITIAL_CAPACITY : count;
|
int new_cap = count < EXPLORER_INITIAL_CAPACITY ? EXPLORER_INITIAL_CAPACITY : count;
|
||||||
ExplorerItem *new_items = (ExplorerItem*)krealloc(state->items, new_cap * sizeof(ExplorerItem));
|
ExplorerItem *new_items = (ExplorerItem*)krealloc(state->items, new_cap * sizeof(ExplorerItem));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue