#include "vfs.h" #include "../sys/process.h" #include "../sys/syscall.h" #include "../dev/disk.h" #include "memory_manager.h" #include "core/kutils.h" #include "core/platform.h" typedef struct { uint32_t pid; char type[32]; int offset; bool is_root; } procfs_handle_t; void* procfs_open(void *fs_private, const char *path, const char *mode) { if (path[0] == '/') path++; procfs_handle_t *h = (procfs_handle_t*)kmalloc(sizeof(procfs_handle_t)); memset(h, 0, sizeof(procfs_handle_t)); h->offset = 0; if (path[0] == '\0') { h->is_root = true; return h; } if (path[0] >= '0' && path[0] <= '9') { char pid_str[16]; int i = 0; while (path[i] && path[i] != '/' && i < 15) { pid_str[i] = path[i]; i++; } pid_str[i] = 0; h->pid = atoi(pid_str); if (path[i] == '/') { strcpy(h->type, path + i + 1); } else { h->type[0] = 0; } return h; } h->pid = 0xFFFFFFFF; strcpy(h->type, path); return h; } void procfs_close(void *fs_private, void *handle) { if (handle) kfree(handle); } int procfs_read(void *fs_private, void *handle, void *buf, int size) { procfs_handle_t *h = (procfs_handle_t*)handle; if (!h) return -1; char *out = (char*)kmalloc(16384); if (!out) return -1; out[0] = 0; if (h->pid == 0xFFFFFFFF) { if (strcmp(h->type, "version") == 0) { extern void get_os_info(os_info_t *info); os_info_t info; get_os_info(&info); strcpy(out, info.os_name); strcpy(out + strlen(out), " ["); strcpy(out + strlen(out), info.os_codename); strcpy(out + strlen(out), "] Version "); strcpy(out + strlen(out), info.os_version); strcpy(out + strlen(out), "\nKernel: "); strcpy(out + strlen(out), info.kernel_name); strcpy(out + strlen(out), " "); strcpy(out + strlen(out), info.kernel_version); strcpy(out + strlen(out), "\nBuild: "); strcpy(out + strlen(out), info.build_date); strcpy(out + strlen(out), " "); strcpy(out + strlen(out), info.build_time); strcpy(out + strlen(out), "\n"); } else if (strcmp(h->type, "uptime") == 0) { extern uint32_t wm_get_ticks(void); uint32_t ticks = wm_get_ticks(); itoa(ticks / 60, out); strcpy(out + strlen(out), " seconds\nRaw_Ticks:"); char t_s[16]; itoa(ticks, t_s); strcpy(out + strlen(out), t_s); strcpy(out + strlen(out), "\n"); } else if (strcmp(h->type, "cpuinfo") == 0) { extern uint32_t smp_cpu_count(void); extern void platform_get_cpu_model(char *model); extern void platform_get_cpu_vendor(char *vendor); extern void platform_get_cpu_info(cpu_info_t *info); extern void platform_get_cpu_flags(char *flags_str); char model[64]; char vendor[16]; char flags[1024]; cpu_info_t info; platform_get_cpu_model(model); platform_get_cpu_vendor(vendor); platform_get_cpu_info(&info); platform_get_cpu_flags(flags); uint32_t cpu_count = smp_cpu_count(); out[0] = '\0'; // Output info for each processor for (uint32_t i = 0; i < cpu_count; i++) { char buf[32]; strcpy(out + strlen(out), "processor\t: "); itoa(i, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "vendor_id\t: "); strcpy(out + strlen(out), vendor); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "cpu family\t: "); itoa(info.family, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "model\t\t: "); itoa(info.model, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "model name\t: "); strcpy(out + strlen(out), model); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "stepping\t: "); itoa(info.stepping, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "microcode\t: 0x"); char hex[16]; int temp = info.microcode; int hex_pos = 0; for (int j = 7; j >= 0; j--) { int digit = (temp >> (j * 4)) & 0xF; hex[hex_pos++] = digit < 10 ? '0' + digit : 'a' + (digit - 10); } hex[hex_pos] = '\0'; strcpy(out + strlen(out), hex); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "cache size\t: "); itoa(info.cache_size, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), " KB\n"); strcpy(out + strlen(out), "physical id\t: 0\n"); strcpy(out + strlen(out), "siblings\t: "); itoa(cpu_count, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "core id\t\t: "); itoa(i, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "cpu cores\t: "); itoa(cpu_count, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "apicid\t\t: "); itoa(i, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "initial apicid\t: "); itoa(i, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "fpu\t\t: yes\n"); strcpy(out + strlen(out), "fpu_exception\t: yes\n"); strcpy(out + strlen(out), "cpuid level\t: 13\n"); strcpy(out + strlen(out), "wp\t\t: yes\n"); strcpy(out + strlen(out), "flags\t\t: "); strcpy(out + strlen(out), flags); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "bugs\t\t: \n"); strcpy(out + strlen(out), "bogomips\t: 4800.00\n"); if (i < cpu_count - 1) { strcpy(out + strlen(out), "\n"); } } } else if (strcmp(h->type, "datetime") == 0) { extern void rtc_get_datetime(int *year, int *month, int *day, int *hour, int *minute, int *second); int y, m, d, h_val, min, s; rtc_get_datetime(&y, &m, &d, &h_val, &min, &s); char buf[16]; itoa(y, buf); strcpy(out, buf); strcpy(out + strlen(out), "-"); if (m < 10) strcpy(out + strlen(out), "0"); itoa(m, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "-"); if (d < 10) strcpy(out + strlen(out), "0"); itoa(d, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), " "); if (h_val < 10) strcpy(out + strlen(out), "0"); itoa(h_val, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), ":"); if (min < 10) strcpy(out + strlen(out), "0"); itoa(min, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), ":"); if (s < 10) strcpy(out + strlen(out), "0"); itoa(s, buf); strcpy(out + strlen(out), buf); strcpy(out + strlen(out), "\n"); } else if (strcmp(h->type, "meminfo") == 0) { extern MemStats memory_get_stats(void); MemStats stats = memory_get_stats(); char m_s[32]; strcpy(out, "MemTotal:\t"); itoa(stats.total_memory / 1024, m_s); strcpy(out + strlen(out), m_s); strcpy(out + strlen(out), " kB\n"); strcpy(out + strlen(out), "MemFree:\t"); itoa(stats.available_memory / 1024, m_s); strcpy(out + strlen(out), m_s); strcpy(out + strlen(out), " kB\n"); strcpy(out + strlen(out), "MemAvailable:\t"); itoa(stats.available_memory / 1024, m_s); strcpy(out + strlen(out), m_s); strcpy(out + strlen(out), " kB\n"); strcpy(out + strlen(out), "Buffers:\t0 kB\n"); strcpy(out + strlen(out), "Cached:\t\t0 kB\n"); strcpy(out + strlen(out), "MemUsed:\t"); itoa(stats.used_memory / 1024, m_s); strcpy(out + strlen(out), m_s); strcpy(out + strlen(out), " kB\n"); strcpy(out + strlen(out), "MemPeak:\t"); itoa(stats.peak_memory_used / 1024, m_s); strcpy(out + strlen(out), m_s); strcpy(out + strlen(out), " kB\n"); strcpy(out + strlen(out), "SwapTotal:\t0 kB\n"); strcpy(out + strlen(out), "SwapFree:\t0 kB\n"); strcpy(out + strlen(out), "Dirty:\t\t0 kB\n"); strcpy(out + strlen(out), "Writeback:\t0 kB\n"); strcpy(out + strlen(out), "AnonPages:\t"); itoa(stats.used_memory / 1024, m_s); strcpy(out + strlen(out), m_s); strcpy(out + strlen(out), " kB\n"); strcpy(out + strlen(out), "Mapped:\t\t0 kB\n"); strcpy(out + strlen(out), "Shmem:\t\t0 kB\n"); strcpy(out + strlen(out), "Blocks:\t\t"); itoa(stats.allocated_blocks, m_s); strcpy(out + strlen(out), m_s); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "FreeBlocks:\t"); itoa(stats.free_blocks, m_s); strcpy(out + strlen(out), m_s); strcpy(out + strlen(out), "\n"); strcpy(out + strlen(out), "Fragmentation:\t"); itoa(stats.fragmentation_percent, m_s); strcpy(out + strlen(out), m_s); strcpy(out + strlen(out), "%\n"); } else if (strcmp(h->type, "devices") == 0) { extern int disk_get_count(void); extern Disk* disk_get_by_index(int index); int dcount = disk_get_count(); out[0] = '\0'; strcpy(out, "Character devices:\n"); strcpy(out + strlen(out), " 1 mem\n"); strcpy(out + strlen(out), " 4 tty\n"); strcpy(out + strlen(out), " 5 cua\n"); strcpy(out + strlen(out), " 7 vcs\n"); strcpy(out + strlen(out), " 8 stdin\n"); strcpy(out + strlen(out), " 13 input\n"); strcpy(out + strlen(out), " 14 sound\n"); strcpy(out + strlen(out), " 29 fb\n"); strcpy(out + strlen(out), "189 usb\n\n"); strcpy(out + strlen(out), "Block devices:\n"); for (int i = 0; i < dcount; i++) { Disk *d = disk_get_by_index(i); if (d && !d->is_partition) { strcpy(out + strlen(out), " 8 "); strcpy(out + strlen(out), d->devname); strcpy(out + strlen(out), "\n"); } } strcpy(out + strlen(out), " 11 sr\n"); strcpy(out + strlen(out), "253 virtblk\n"); } } else { process_t *proc = process_get_by_pid(h->pid); if (!proc) { kfree(out); return -1; } if (strcmp(h->type, "name") == 0 || strcmp(h->type, "cmdline") == 0) { strcpy(out, proc->name); strcpy(out + strlen(out), "\n"); } else if (strcmp(h->type, "cwd") == 0) { strcpy(out, proc->cwd); strcpy(out + strlen(out), "\n"); } else if (strcmp(h->type, "status") == 0) { strcpy(out, "Name: "); strcpy(out + strlen(out), proc->name); strcpy(out + strlen(out), "\nPID: "); char pid_s[16]; itoa(proc->pid, pid_s); strcpy(out + strlen(out), pid_s); strcpy(out + strlen(out), "\nState: RUNNING\nMemory: "); uint64_t mem_val = proc->used_memory; if (h->pid == 0) { extern MemStats memory_get_stats(void); mem_val = memory_get_stats().used_memory; } char mem_s[32]; itoa(mem_val / 1024, mem_s); strcpy(out + strlen(out), mem_s); strcpy(out + strlen(out), " KB\nTicks: "); char tick_s[32]; itoa(proc->ticks, tick_s); strcpy(out + strlen(out), tick_s); strcpy(out + strlen(out), "\nIdle: "); strcpy(out + strlen(out), proc->is_idle ? "1" : "0"); strcpy(out + strlen(out), "\n"); } } int len = strlen(out); if (h->offset >= len) { kfree(out); return 0; } int to_copy = len - h->offset; if (to_copy > size) to_copy = size; memcpy(buf, out + h->offset, to_copy); h->offset += to_copy; kfree(out); return to_copy; } int procfs_write(void *fs_private, void *handle, const void *buf, int size) { procfs_handle_t *h = (procfs_handle_t*)handle; if (!h || h->pid == 0xFFFFFFFF) return -1; if (strcmp(h->type, "signal") == 0) { char cmd[16]; int to_copy = size < 15 ? size : 15; memcpy(cmd, buf, to_copy); cmd[to_copy] = 0; if (strcmp(cmd, "9") == 0 || strcmp(cmd, "kill") == 0) { process_t *proc = process_get_by_pid(h->pid); if (proc && proc->pid != 0) { process_terminate(proc); return size; } } } return -1; } int procfs_readdir(void *fs_private, const char *path, vfs_dirent_t *entries, int max) { if (path[0] == '/') path++; if (path[0] == '\0') { int out = 0; strcpy(entries[out++].name, "version"); entries[out-1].is_directory = 0; strcpy(entries[out++].name, "uptime"); entries[out-1].is_directory = 0; strcpy(entries[out++].name, "cpuinfo"); entries[out-1].is_directory = 0; strcpy(entries[out++].name, "meminfo"); entries[out-1].is_directory = 0; strcpy(entries[out++].name, "datetime"); entries[out-1].is_directory = 0; strcpy(entries[out++].name, "devices"); entries[out-1].is_directory = 0; extern process_t processes[]; for (int i = 0; i < 16 && out < max; i++) { if (processes[i].pid != 0xFFFFFFFF) { itoa(processes[i].pid, entries[out].name); entries[out].is_directory = 1; entries[out].size = 0; out++; } } return out; } if (path[0] >= '0' && path[0] <= '9') { int out = 0; strcpy(entries[out++].name, "name"); strcpy(entries[out++].name, "status"); strcpy(entries[out++].name, "cmdline"); strcpy(entries[out++].name, "cwd"); strcpy(entries[out++].name, "signal"); for(int i=0; i= '0' && path[0] <= '9') { char pid_str[16]; int i = 0; while (path[i] && path[i] != '/' && i < 15) { pid_str[i] = path[i]; i++; } pid_str[i] = 0; uint32_t pid = atoi(pid_str); if (process_get_by_pid(pid)) return true; } if (strcmp(path, "version") == 0 || strcmp(path, "uptime") == 0) return true; if (strcmp(path, "cpuinfo") == 0 || strcmp(path, "meminfo") == 0) return true; if (strcmp(path, "datetime") == 0 || strcmp(path, "devices") == 0) return true; return false; } bool procfs_is_dir(void *fs_private, const char *path) { if (path[0] == '/') path++; if (path[0] == '\0') return true; if (path[0] >= '0' && path[0] <= '9') { int i = 0; while (path[i] && path[i] != '/') i++; if (path[i] == '\0') return true; return false; } return false; } static int procfs_statfs(void *fs_private, vfs_statfs_t *stat) { (void)fs_private; stat->total_blocks = 0; stat->free_blocks = 0; stat->block_size = 512; return 0; } vfs_fs_ops_t procfs_ops = { .open = procfs_open, .close = procfs_close, .read = procfs_read, .write = procfs_write, .readdir = procfs_readdir, .exists = procfs_exists, .is_dir = procfs_is_dir, .statfs = procfs_statfs }; vfs_fs_ops_t* procfs_get_ops(void) { return &procfs_ops; }