__attribute__((weak))
const char* ata_drive_to_name(int drive) { (void)drive; return 0; }
+
+__attribute__((weak))
+void ata_register_devfs(void) { }
return 0;
}
+/* --- Register detected ATA drives in devfs --- */
+
+#include "devfs.h"
+
+static fs_node_t ata_dev_nodes[ATA_MAX_DRIVES];
+
+static uint32_t ata_dev_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+ int drive = (int)node->inode;
+ if (!buffer || size == 0) return 0;
+
+ uint32_t lba = offset / 512;
+ uint32_t off_in_sect = offset % 512;
+ uint32_t total = 0;
+ uint8_t tmp[512];
+
+ while (total < size) {
+ if (ata_pio_read28(drive, lba, tmp) < 0) break;
+ uint32_t avail = 512 - off_in_sect;
+ uint32_t want = size - total;
+ if (want > avail) want = avail;
+ memcpy(buffer + total, tmp + off_in_sect, want);
+ total += want;
+ lba++;
+ off_in_sect = 0;
+ }
+ return total;
+}
+
+static uint32_t ata_dev_write(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) {
+ int drive = (int)node->inode;
+ if (!buffer || size == 0) return 0;
+
+ uint32_t lba = offset / 512;
+ uint32_t off_in_sect = offset % 512;
+ uint32_t total = 0;
+ uint8_t tmp[512];
+
+ while (total < size) {
+ uint32_t want = size - total;
+ if (off_in_sect != 0 || want < 512) {
+ /* Read-modify-write for partial sector */
+ if (ata_pio_read28(drive, lba, tmp) < 0) break;
+ uint32_t avail = 512 - off_in_sect;
+ if (want > avail) want = avail;
+ memcpy(tmp + off_in_sect, buffer + total, want);
+ } else {
+ want = 512;
+ memcpy(tmp, buffer + total, 512);
+ }
+ if (ata_pio_write28(drive, lba, tmp) < 0) break;
+ total += want;
+ lba++;
+ off_in_sect = 0;
+ }
+ return total;
+}
+
+static const struct file_operations ata_dev_fops = {
+ .read = ata_dev_read,
+ .write = ata_dev_write,
+};
+
+void ata_register_devfs(void) {
+ for (int i = 0; i < ATA_MAX_DRIVES; i++) {
+ if (!drive_present[i]) continue;
+ memset(&ata_dev_nodes[i], 0, sizeof(fs_node_t));
+ strcpy(ata_dev_nodes[i].name, drive_names[i]);
+ ata_dev_nodes[i].flags = FS_BLOCKDEVICE;
+ ata_dev_nodes[i].inode = (uint32_t)i;
+ ata_dev_nodes[i].f_ops = &ata_dev_fops;
+ devfs_register_device(&ata_dev_nodes[i]);
+ }
+}
+
int ata_name_to_drive(const char* name) {
if (!name) return -1;
for (int i = 0; i < ATA_MAX_DRIVES; i++) {
* (primary/secondary x master/slave). */
(void)ata_pio_init();
+ /* Register detected ATA drives as /dev/hdX block device nodes */
+ extern void ata_register_devfs(void);
+ ata_register_devfs();
+
/* If root= is specified on the kernel command line, mount that device
* as the disk root filesystem. The filesystem type is auto-detected
* by trying each supported type in order.
static fs_node_t g_proc_uptime;
static fs_node_t g_proc_meminfo;
static fs_node_t g_proc_cmdline;
+static fs_node_t g_proc_dmesg;
#define PID_NODE_POOL 8
static fs_node_t g_pid_dir[PID_NODE_POOL];
return size;
}
+extern size_t klog_read(char* out, size_t out_size);
+
+static uint32_t proc_dmesg_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+ (void)node;
+ /* Allocate from heap — too large for kernel stack */
+ char* tmp = kmalloc(16384);
+ if (!tmp) return 0;
+ size_t len = klog_read(tmp, 16384);
+ uint32_t ret = 0;
+ if (offset < (uint32_t)len) {
+ uint32_t avail = (uint32_t)len - offset;
+ if (size > avail) size = avail;
+ memcpy(buffer, tmp + offset, size);
+ ret = size;
+ }
+ kfree(tmp);
+ return ret;
+}
+
static uint32_t proc_cmdline_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
(void)node;
const char* raw = cmdline_raw();
if (strcmp(name, "uptime") == 0) return &g_proc_uptime;
if (strcmp(name, "meminfo") == 0) return &g_proc_meminfo;
if (strcmp(name, "cmdline") == 0) return &g_proc_cmdline;
+ if (strcmp(name, "dmesg") == 0) return &g_proc_dmesg;
if (is_numeric(name)) return proc_get_pid_dir(parse_uint(name));
return NULL;
}
uint32_t idx = *inout_index;
struct vfs_dirent* d = (struct vfs_dirent*)buf;
- static const char* fixed[] = { "self", "uptime", "meminfo", "cmdline" };
- if (idx < 4) {
+ static const char* fixed[] = { "self", "uptime", "meminfo", "cmdline", "dmesg" };
+ if (idx < 5) {
d->d_ino = 200 + idx;
d->d_type = (idx == 0) ? FS_DIRECTORY : FS_FILE;
d->d_reclen = sizeof(struct vfs_dirent);
}
/* After fixed entries, list numeric PIDs (under sched_lock) */
- uint32_t pi = idx - 4;
+ uint32_t pi = idx - 5;
uint32_t count = 0;
int found = 0;
{
.read = proc_cmdline_read,
};
+static const struct file_operations procfs_dmesg_fops = {
+ .read = proc_dmesg_read,
+};
+
static const struct file_operations procfs_pid_dir_fops = {0};
static const struct inode_operations procfs_pid_dir_iops = {
g_proc_cmdline.flags = FS_FILE;
g_proc_cmdline.f_ops = &procfs_cmdline_fops;
+ memset(&g_proc_dmesg, 0, sizeof(g_proc_dmesg));
+ strcpy(g_proc_dmesg.name, "dmesg");
+ g_proc_dmesg.flags = FS_FILE;
+ g_proc_dmesg.f_ops = &procfs_dmesg_fops;
+
return &g_proc_root;
}