feat(microkernel): implement pure microkernel architecture with vfs_server, net_server, and procmgr

- Added vfs_server in Ring 3 (Endpoint 5) managing unified VFS tree (/, /bin, /etc, /proc, /dev, /tmp)
- Added net_server in Ring 3 (Endpoint 6) owning RTL8139 hardware NIC, DHCP, DNS, and TCP/IPv4 stack
- Refactored procmgr in Ring 3 (Endpoint 4) to handle userspace process spawning via PROC_OP_SPAWN
- Added primitive microkernel syscalls in Ring 0: SYS_TASK_CREATE (29), SYS_TASK_MAP_PAGE (30), SYS_TASK_START (31)
- Updated shell (sh) and desktop GUI (gui_server) to delegate process management and I/O to Ring 3 daemons
- Expanded boot pipeline to orchestrate 7 concurrent Ring 3 servers across dedicated SMP CPU cores
This commit is contained in:
RarDog
2026-09-03 11:03:35 +03:00
parent c18717539c
commit 5a4206acb6
15 changed files with 604 additions and 34 deletions
+14 -2
View File
@@ -35,6 +35,8 @@ KERNEL_BIN := target/x86_64-unknown-none/release/opencore_kernel
KERNEL_ELF := $(BUILD_DIR)/opencore_kernel.elf
INIT_SERVER := $(BUILD_DIR)/init_server.elf
UART_DRIVER := $(BUILD_DIR)/uart_driver.elf
VFS_SERVER := $(BUILD_DIR)/vfs_server.elf
NET_SERVER := $(BUILD_DIR)/net_server.elf
SH_SERVER := $(BUILD_DIR)/sh.elf
PROCMGR := $(BUILD_DIR)/procmgr.elf
GUI_SERVER := $(BUILD_DIR)/gui_server.elf
@@ -53,7 +55,7 @@ all: kernel libc hal servers
@echo "======================================================="
@echo " [SUCCESS] opencoreC Build Complete!"
@echo " Kernel: $(KERNEL_ELF)"
@echo " Servers: $(INIT_SERVER), $(UART_DRIVER), $(SH_SERVER), $(PROCMGR), $(GUI_SERVER)"
@echo " Servers: $(INIT_SERVER), $(UART_DRIVER), $(VFS_SERVER), $(NET_SERVER), $(PROCMGR), $(SH_SERVER), $(GUI_SERVER)"
@echo " Run: make run (Serial CLI) or make gui (LVGL Desktop Window)"
@echo "======================================================="
@@ -99,6 +101,14 @@ servers: libc hal $(LVGL_LIB)
@$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(SERVERS_DIR)/uart_driver/main.c -o $(BUILD_DIR)/uart_driver_main.o
@$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(UART_DRIVER) \
$(BUILD_DIR)/uart_driver_main.o $(BUILD_DIR)/uart.o $(LIBC_OBJS)
@# Standalone Virtual File System Server
@$(CXX) $(CXXFLAGS) -c $(SERVERS_DIR)/vfs_server/main.cpp -o $(BUILD_DIR)/vfs_server_main.o
@$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(VFS_SERVER) \
$(BUILD_DIR)/vfs_server_main.o $(BUILD_DIR)/ipc.o $(LIBC_OBJS)
@# Standalone Network Stack Server
@$(CXX) $(CXXFLAGS) -c $(SERVERS_DIR)/net_server/main.cpp -o $(BUILD_DIR)/net_server_main.o
@$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(NET_SERVER) \
$(BUILD_DIR)/net_server_main.o $(BUILD_DIR)/ipc.o $(NET_OBJS) $(LIBC_OBJS)
@# Interactive Shell with Networking & Framebuffer
@$(CXX) $(CXXFLAGS) -c $(SERVERS_DIR)/sh/main.cpp -o $(BUILD_DIR)/sh_main.o
@$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(SH_SERVER) \
@@ -137,8 +147,10 @@ image: all limine-setup
@mcopy -i $(DISK_IMG)@@1M $(KERNEL_ELF) ::/boot/
@mcopy -i $(DISK_IMG)@@1M $(INIT_SERVER) ::/boot/
@mcopy -i $(DISK_IMG)@@1M $(UART_DRIVER) ::/boot/
@mcopy -i $(DISK_IMG)@@1M $(SH_SERVER) ::/boot/
@mcopy -i $(DISK_IMG)@@1M $(VFS_SERVER) ::/boot/
@mcopy -i $(DISK_IMG)@@1M $(NET_SERVER) ::/boot/
@mcopy -i $(DISK_IMG)@@1M $(PROCMGR) ::/boot/
@mcopy -i $(DISK_IMG)@@1M $(SH_SERVER) ::/boot/
@mcopy -i $(DISK_IMG)@@1M $(GUI_SERVER) ::/boot/
@mcopy -i $(DISK_IMG)@@1M $(HELLO_APP) ::/boot/
@# Bootloader config
+6
View File
@@ -16,6 +16,12 @@ extern "C" {
#define ICMP_ECHO_REPLY 0
#define ICMP_ECHO_REQUEST 8
/* NET_ENDPOINT (6) IPC Opcodes */
#define NET_OP_GET_CONFIG 1
#define NET_OP_PING 2
#define NET_OP_DNS 3
#define NET_OP_DHCP 4
#pragma pack(push, 1)
typedef struct {
+42
View File
@@ -31,6 +31,21 @@
#define SYS_NOTIFY_RECV 26 /* Poll pending desktop notifications non-blockingly */
#define SYS_MODULE_EXEC 27 /* Find and execute boot module by name (.opc or .elf) */
#define SYS_MODULE_LIST 28 /* List available boot modules in memory */
#define SYS_TASK_CREATE 29 /* Allocate new user PML4 & thread structure: (name, name_len) -> tid */
#define SYS_TASK_MAP_PAGE 30 /* Map page into target task: (target_tid, vaddr, src_buf, flags) -> status */
#define SYS_TASK_START 31 /* Activate thread: (target_tid, entry_rip, user_rsp) -> status */
/* Standard Ring 3 Service Endpoints */
#define UART_SERVICE_ENDPOINT 2
#define PROCMGR_ENDPOINT 4
#define VFS_ENDPOINT 5
#define NET_ENDPOINT 6
/* PROCMGR_ENDPOINT (4) IPC Opcodes */
#define PROC_OP_LIST 1
#define PROC_OP_KILL 2
#define PROC_OP_SPAWN 3
#define PROC_OP_STAT 4
/* POSIX Process Signals */
#define SIGHUP 1
@@ -249,6 +264,33 @@ static inline int sys_module_list(char *out_buf, size_t max_len) {
return (int)rax;
}
static inline int64_t sys_task_create(const char *name, size_t name_len) {
register uint64_t rax __asm__("rax") = SYS_TASK_CREATE;
register uint64_t rdi __asm__("rdi") = (uint64_t)name;
register uint64_t rsi __asm__("rsi") = (uint64_t)name_len;
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi) : "rcx", "r11", "memory");
return (int64_t)rax;
}
static inline int64_t sys_task_map_page(uint64_t target_tid, uint64_t vaddr, const void *src_buf, uint64_t flags) {
register uint64_t rax __asm__("rax") = SYS_TASK_MAP_PAGE;
register uint64_t rdi __asm__("rdi") = target_tid;
register uint64_t rsi __asm__("rsi") = vaddr;
register uint64_t rdx __asm__("rdx") = (uint64_t)src_buf;
register uint64_t r8 __asm__("r8") = flags;
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi), "r"(rdx), "r"(r8) : "rcx", "r11", "memory");
return (int64_t)rax;
}
static inline int64_t sys_task_start(uint64_t target_tid, uint64_t entry_rip, uint64_t user_rsp) {
register uint64_t rax __asm__("rax") = SYS_TASK_START;
register uint64_t rdi __asm__("rdi") = target_tid;
register uint64_t rsi __asm__("rsi") = entry_rip;
register uint64_t rdx __asm__("rdx") = user_rsp;
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi), "r"(rdx) : "rcx", "r11", "memory");
return (int64_t)rax;
}
#ifdef __cplusplus
}
#endif
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include "types.h"
#include "syscalls.h"
#ifdef __cplusplus
extern "C" {
#endif
#define VFS_OP_STAT 1
#define VFS_OP_READ_FILE 2
#define VFS_OP_WRITE_FILE 3
#define VFS_OP_LIST 4
typedef struct vfs_file_stat {
uint32_t size;
uint32_t is_dir;
} vfs_file_stat_t;
#ifdef __cplusplus
}
#endif
+106
View File
@@ -433,6 +433,7 @@ pub extern "C" fn kernel_syscall_dispatcher(regs: &mut SyscallRegisters) {
entry.tid = t.id;
entry.state = match t.state {
crate::sched::thread::ThreadState::Unused => 0,
crate::sched::thread::ThreadState::Dormant => 0,
crate::sched::thread::ThreadState::Ready => 1,
crate::sched::thread::ThreadState::Running => 2,
crate::sched::thread::ThreadState::BlockedOnSend(_) |
@@ -727,6 +728,111 @@ pub extern "C" fn kernel_syscall_dispatcher(regs: &mut SyscallRegisters) {
}
regs.rax = 0;
}
// SYS_TASK_CREATE = 29: (rdi: name, rsi: name_len) -> tid
29 => unsafe {
let pfa = core::ptr::addr_of_mut!(crate::mm::pfa::PFA);
let vmm = core::ptr::addr_of_mut!(crate::mm::vmm::VMM);
let sched = core::ptr::addr_of_mut!(crate::sched::SCHEDULER);
let new_pml4 = (*vmm).create_user_address_space().unwrap_or(0);
if new_pml4 == 0 {
regs.rax = (-1i64) as u64;
return;
}
// Allocate 16 KiB (4 frames) for kernel stack
let _ = (*pfa).alloc_frame();
let _ = (*pfa).alloc_frame();
let _ = (*pfa).alloc_frame();
let kstack_frame3 = (*pfa).alloc_frame().unwrap_or(0);
if kstack_frame3 == 0 {
regs.rax = (-1i64) as u64;
return;
}
let kstack_top = (*vmm).phys_to_virt::<u8>(kstack_frame3 + 4096) as u64;
let name_ptr = regs.rdi as *const u8;
let name_len = (regs.rsi as usize).min(31);
let static_name: &'static str = if !name_ptr.is_null() && name_len > 0 {
let s = core::str::from_utf8(core::slice::from_raw_parts(name_ptr, name_len)).unwrap_or("user_proc");
if s.starts_with("hello") { "hello" }
else if s.starts_with("calc") { "calculator" }
else if s.starts_with("edit") { "editor" }
else { "user_proc" }
} else {
"user_proc"
};
match (*sched).create_dormant_task(static_name, new_pml4, kstack_top) {
Some(tid) => {
regs.rax = tid;
}
None => {
regs.rax = (-1i64) as u64;
}
}
},
// SYS_TASK_MAP_PAGE = 30: (rdi: target_tid, rsi: target_vaddr, rdx: src_buf, r8: flags) -> status
30 => unsafe {
let target_tid = regs.rdi;
let target_vaddr = regs.rsi & !0xFFF;
let src_buf = regs.rdx as *const u8;
let flags = regs.r8;
let sched = core::ptr::addr_of_mut!(crate::sched::SCHEDULER);
let vmm = core::ptr::addr_of_mut!(crate::mm::vmm::VMM);
let pfa = core::ptr::addr_of_mut!(crate::mm::pfa::PFA);
let mut target_pml4 = 0;
for t in &(*sched).threads {
if t.id == target_tid {
target_pml4 = t.pml4_paddr;
break;
}
}
if target_pml4 == 0 {
regs.rax = (-1i64) as u64;
return;
}
let frame = (*pfa).alloc_frame().unwrap_or(0);
if frame == 0 {
regs.rax = (-2i64) as u64;
return;
}
let frame_virt = (*vmm).phys_to_virt::<u8>(frame);
if !src_buf.is_null() {
core::ptr::copy_nonoverlapping(src_buf, frame_virt, 4096);
} else {
core::ptr::write_bytes(frame_virt, 0, 4096);
}
let mut page_flags = crate::mm::vmm::PAGE_USER | crate::mm::vmm::PAGE_PRESENT;
if (flags & 2) != 0 {
page_flags |= crate::mm::vmm::PAGE_WRITABLE;
}
if (*vmm).map_page(target_pml4, target_vaddr, frame, page_flags).is_ok() {
regs.rax = 0;
} else {
regs.rax = (-3i64) as u64;
}
},
// SYS_TASK_START = 31: (rdi: target_tid, rsi: entry_rip, rdx: user_rsp) -> status
31 => unsafe {
let target_tid = regs.rdi;
let entry_rip = regs.rsi;
let user_rsp = regs.rdx;
let sched = core::ptr::addr_of_mut!(crate::sched::SCHEDULER);
if (*sched).start_task(target_tid, entry_rip, user_rsp) {
regs.rax = 0;
} else {
regs.rax = (-1i64) as u64;
}
},
_ => {
regs.rax = (-1i64) as u64; // SYS_ERR_INVALID_ARG
}
+6 -4
View File
@@ -100,7 +100,7 @@ pub extern "C" fn _start() -> ! {
for i in 0..count {
let mod_file = *(*mod_resp).modules.add(i as usize);
if i >= 5 {
if i >= 7 {
let path_ptr = (*mod_file).path;
let mut path_len = 0;
while !path_ptr.is_null() && *path_ptr.add(path_len) != 0 && path_len < 64 {
@@ -119,9 +119,11 @@ pub extern "C" fn _start() -> ! {
let name = match i {
0 => "init_server",
1 => "uart_driver",
2 => "sh",
3 => "procmgr",
4 => "gui_server",
2 => "vfs_server",
3 => "net_server",
4 => "procmgr",
5 => "sh",
6 => "gui_server",
_ => "user_server",
};
+57 -1
View File
@@ -76,7 +76,7 @@ impl Scheduler {
self.threads[i].cpu_affinity = Some(1);
} else if name.starts_with("sh") {
self.threads[i].cpu_affinity = Some(2);
} else if name.starts_with("init") || name.starts_with("proc") || name.starts_with("uart") {
} else if name.starts_with("init") || name.starts_with("proc") || name.starts_with("uart") || name.starts_with("vfs") || name.starts_with("net") {
self.threads[i].cpu_affinity = Some(3);
} else {
self.threads[i].cpu_affinity = None;
@@ -105,6 +105,62 @@ impl Scheduler {
None
}
pub fn create_dormant_task(
&mut self,
name: &'static str,
pml4_paddr: u64,
kernel_stack_top: u64,
) -> Option<u64> {
for i in 1..MAX_THREADS {
if self.threads[i].state == ThreadState::Unused {
let tid = self.next_tid;
self.next_tid += 1;
self.threads[i].id = tid;
self.threads[i].name = name;
self.threads[i].state = ThreadState::Dormant; // Dormant until started
self.threads[i].pml4_paddr = pml4_paddr;
self.threads[i].kernel_stack_top = kernel_stack_top;
self.threads[i].user_rsp = 0;
self.threads[i].user_rip = 0;
self.threads[i].cpu_ticks = 0;
self.threads[i].cpu_affinity = None;
kprintln!("[SCHED] Created Dormant Task [TID {}] '{}' (PML4: {:#x})", tid, name, pml4_paddr);
return Some(tid);
}
}
None
}
pub fn start_task(&mut self, tid: u64, entry_rip: u64, user_rsp: u64) -> bool {
for i in 1..MAX_THREADS {
if self.threads[i].id == tid && self.threads[i].state == ThreadState::Dormant {
self.threads[i].user_rip = entry_rip;
self.threads[i].user_rsp = user_rsp;
unsafe {
let k = self.threads[i].kernel_stack_top as *mut u64;
*k.sub(1) = thread_entry_trampoline as *const () as u64; // ret address
*k.sub(2) = 0; // rbp
*k.sub(3) = 0; // rbx
*k.sub(4) = user_rsp; // r12 -> user_rsp
*k.sub(5) = entry_rip; // r13 -> entry_rip
*k.sub(6) = 0; // r14
*k.sub(7) = 0; // r15
self.threads[i].context.rsp = k.sub(7) as u64;
}
self.threads[i].state = ThreadState::Ready;
kprintln!("[SCHED] Activated Task [TID {}] '{}' (Entry: {:#x}, RSP: {:#x})",
tid, self.threads[i].name, entry_rip, user_rsp);
return true;
}
}
false
}
pub fn get_current_mut(&mut self) -> &mut Thread {
&mut self.threads[self.current_tid]
}
+1
View File
@@ -8,6 +8,7 @@ pub const KERNEL_STACK_SIZE: usize = 16384; // 16 KiB
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ThreadState {
Unused,
Dormant,
Ready,
Running,
BlockedOnSend(u64), // Waiting on destination endpoint ID
+3 -1
View File
@@ -9,7 +9,9 @@ interface_resolution: 1280x800
kernel_path: boot():/boot/opencore_kernel.elf
module_path: boot():/boot/init_server.elf
module_path: boot():/boot/uart_driver.elf
module_path: boot():/boot/sh.elf
module_path: boot():/boot/vfs_server.elf
module_path: boot():/boot/net_server.elf
module_path: boot():/boot/procmgr.elf
module_path: boot():/boot/sh.elf
module_path: boot():/boot/gui_server.elf
module_path: boot():/boot/hello.opc
+3 -1
View File
@@ -9,7 +9,9 @@ interface_resolution: 1280x800
kernel_path: boot():/boot/opencore_kernel.elf
module_path: boot():/boot/init_server.elf
module_path: boot():/boot/uart_driver.elf
module_path: boot():/boot/sh.elf
module_path: boot():/boot/vfs_server.elf
module_path: boot():/boot/net_server.elf
module_path: boot():/boot/procmgr.elf
module_path: boot():/boot/sh.elf
module_path: boot():/boot/gui_server.elf
module_path: boot():/boot/hello.opc
+8 -11
View File
@@ -654,20 +654,17 @@ static void execute_console_command(const char *raw_cmd) {
exec_target++;
}
int64_t tid = sys_module_exec(exec_target);
if (tid < 0 && !strstr(exec_target, ".")) {
char opc_name[70];
snprintf(opc_name, sizeof(opc_name), "%s.opc", exec_target);
tid = sys_module_exec(opc_name);
if (tid < 0) {
char elf_name[70];
snprintf(elf_name, sizeof(elf_name), "%s.elf", exec_target);
tid = sys_module_exec(elf_name);
}
uint64_t p0 = 0, p1 = 0;
memcpy(&p0, exec_target, strlen(exec_target) < 8 ? strlen(exec_target) : 8);
if (strlen(exec_target) > 8) {
memcpy(&p1, exec_target + 8, strlen(exec_target) - 8 < 8 ? strlen(exec_target) - 8 : 8);
}
uint64_t out0 = 0, out1 = 0;
sysret_t ret = sys_ipc_call_raw(PROCMGR_ENDPOINT, PROC_OP_SPAWN, p0, p1, 0, 0, &out0, &out1);
int64_t tid = (ret == 0) ? (int64_t)out0 : -1;
if (tid >= 0) {
snprintf(buf, sizeof(buf), "[osh] Process spawned with TID %ld on Ring 3\n", (long)tid);
snprintf(buf, sizeof(buf), "[procmgr] Process spawned with TID %ld on Ring 3\n", (long)tid);
lv_textarea_add_text(g_txt_term_output, buf);
} else {
snprintf(buf, sizeof(buf), "osh: %s: command not found\n", raw_cmd);
+85
View File
@@ -0,0 +1,85 @@
/**
* opencoreC - Network Stack Server (Ring 3 User Space)
* Centralized network daemon managing RTL8139 hardware NIC, ARP, DHCP, DNS, TCP/IP.
* Listens on NET_ENDPOINT (6) and handles synchronous IPC requests from sh and gui_server.
*/
#include "stdio.h"
#include "string.h"
#include "abi/syscalls.h"
#include "abi/ipc.h"
#include "abi/net.h"
extern "C" void _start(void) {
puts("[NET-SERVER] Initializing Hardware RTL8139 NIC & TCP/IP Stack in Ring 3...");
net_init();
// Acquire DHCP lease on startup
int dhcp_res = net_dhcp_discover();
char ip_str[32], gw_str[32];
format_ip(g_net_cfg.ip, ip_str);
format_ip(g_net_cfg.gateway, gw_str);
if (dhcp_res == 0) {
printf("[NET-SERVER] DHCP OK: IP %s, Gateway %s\n", ip_str, gw_str);
} else {
printf("[NET-SERVER] DHCP fallback: IP %s, Gateway %s\n", ip_str, gw_str);
}
uint64_t last_client = 0;
uint64_t reply_val0 = 0;
uint64_t reply_val1 = 0;
while (1) {
uint64_t sender_tid = 0;
uint64_t opcode = 0;
uint64_t arg0 = 0;
uint64_t arg1 = 0;
sysret_t ret = sys_ipc_reply_recv_raw(
NET_ENDPOINT,
last_client,
reply_val0,
reply_val1,
&sender_tid,
&opcode,
&arg0,
&arg1
);
if (ret == 0 && sender_tid != 0) {
last_client = sender_tid;
if (opcode == NET_OP_GET_CONFIG) {
// reply_val0 = ip (low 32 bits) | (gateway << 32)
// reply_val1 = netmask (low 32 bits) | (dns_server << 32)
reply_val0 = ((uint64_t)g_net_cfg.gateway << 32) | (uint64_t)g_net_cfg.ip;
reply_val1 = ((uint64_t)g_net_cfg.dns_server << 32) | (uint64_t)g_net_cfg.netmask;
} else if (opcode == NET_OP_PING) {
uint32_t target_ip = (uint32_t)arg0;
uint16_t seq = (uint16_t)(arg1 ? arg1 : 1);
int ping_res = net_send_icmp_ping(target_ip, seq);
reply_val0 = (ping_res == 0) ? 0 : (uint64_t)-1;
reply_val1 = 0;
} else if (opcode == NET_OP_DNS) {
// Domain string passed in arg0 (8 bytes) + arg1 (8 bytes)
char domain[20] = {0};
memcpy(domain, &arg0, 8);
memcpy(domain + 8, &arg1, 8);
uint32_t resolved_ip = 0;
int res = net_dns_resolve(domain, &resolved_ip);
reply_val0 = (res == 0) ? (uint64_t)resolved_ip : 0;
reply_val1 = (uint64_t)res;
} else if (opcode == NET_OP_DHCP) {
int res = net_dhcp_discover();
reply_val0 = (res == 0) ? (uint64_t)g_net_cfg.ip : 0;
reply_val1 = (uint64_t)g_net_cfg.gateway;
} else {
reply_val0 = (uint64_t)-1;
reply_val1 = 0;
}
} else {
last_client = 0;
sys_yield();
}
}
}
+19
View File
@@ -53,6 +53,25 @@ extern "C" void _start() {
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi) : "rcx", "r11", "memory");
reply_val0 = (rax > 0) ? rax : 0;
reply_val1 = 0;
} else if (opcode == PROC_OP_SPAWN) {
// Program name passed in arg0 (8 bytes) + arg1 (8 bytes)
char prog[20] = {0};
memcpy(prog, &arg0, 8);
memcpy(prog + 8, &arg1, 8);
int64_t tid = sys_module_exec(prog);
if (tid < 0 && !strstr(prog, ".")) {
char opc_name[28];
snprintf(opc_name, sizeof(opc_name), "%s.opc", prog);
tid = sys_module_exec(opc_name);
if (tid < 0) {
char elf_name[28];
snprintf(elf_name, sizeof(elf_name), "%s.elf", prog);
tid = sys_module_exec(elf_name);
}
}
reply_val0 = (uint64_t)tid;
reply_val1 = 0;
} else {
reply_val0 = 0;
reply_val1 = 0;
+18 -14
View File
@@ -339,10 +339,17 @@ static void cmd_run_module(const char *mod_name) {
while (*mod_name == '.' || *mod_name == '/') {
mod_name++;
}
printf("[osh] Launching native program '%s' via kernel loader...\n", mod_name);
int64_t tid = sys_module_exec(mod_name);
printf("[osh] Requesting Process Manager (procmgr) to spawn '%s'...\n", mod_name);
uint64_t p0 = 0, p1 = 0;
memcpy(&p0, mod_name, strlen(mod_name) < 8 ? strlen(mod_name) : 8);
if (strlen(mod_name) > 8) {
memcpy(&p1, mod_name + 8, strlen(mod_name) - 8 < 8 ? strlen(mod_name) - 8 : 8);
}
uint64_t out0 = 0, out1 = 0;
sysret_t ret = sys_ipc_call_raw(PROCMGR_ENDPOINT, PROC_OP_SPAWN, p0, p1, 0, 0, &out0, &out1);
int64_t tid = (ret == 0) ? (int64_t)out0 : -1;
if (tid >= 0) {
printf("[osh] Process successfully spawned with TID %ld on Ring 3!\n", (long)tid);
printf("[procmgr] Process successfully spawned with TID %ld on Ring 3!\n", (long)tid);
for (int i = 0; i < 6; i++) sys_yield();
} else {
printf("osh: failed to execute '%s' (module not found or invalid format)\n", mod_name);
@@ -965,20 +972,17 @@ static void handle_command(char *cmd) {
exec_target++;
}
int64_t tid = sys_module_exec(exec_target);
if (tid < 0 && !strstr(exec_target, ".")) {
char opc_name[70];
snprintf(opc_name, sizeof(opc_name), "%s.opc", exec_target);
tid = sys_module_exec(opc_name);
if (tid < 0) {
char elf_name[70];
snprintf(elf_name, sizeof(elf_name), "%s.elf", exec_target);
tid = sys_module_exec(elf_name);
}
uint64_t p0 = 0, p1 = 0;
memcpy(&p0, exec_target, strlen(exec_target) < 8 ? strlen(exec_target) : 8);
if (strlen(exec_target) > 8) {
memcpy(&p1, exec_target + 8, strlen(exec_target) - 8 < 8 ? strlen(exec_target) - 8 : 8);
}
uint64_t out0 = 0, out1 = 0;
sysret_t ret = sys_ipc_call_raw(PROCMGR_ENDPOINT, PROC_OP_SPAWN, p0, p1, 0, 0, &out0, &out1);
int64_t tid = (ret == 0) ? (int64_t)out0 : -1;
if (tid >= 0) {
printf("[osh] Process spawned with TID %ld on Ring 3\n", (long)tid);
printf("[procmgr] Process spawned with TID %ld on Ring 3\n", (long)tid);
for (int i = 0; i < 6; i++) sys_yield();
} else {
printf("osh: command not found: %s\n", cmd);
+214
View File
@@ -0,0 +1,214 @@
/**
* opencoreC - Virtual File System Server (Ring 3 User Space)
* Centralized file system daemon managing in-memory and virtual file hierarchy.
* Listens on VFS_ENDPOINT (5) and handles synchronous IPC requests.
*/
#include "stdio.h"
#include "string.h"
#include "abi/syscalls.h"
#include "abi/ipc.h"
#include "abi/vfs.h"
#define MAX_VFS_NODES 64
struct VfsNode {
char name[48];
bool is_dir;
uint32_t size;
char content[1024];
};
static VfsNode g_nodes[MAX_VFS_NODES];
static size_t g_node_count = 0;
static void vfs_add_dir(const char *name) {
if (g_node_count >= MAX_VFS_NODES) return;
strncpy(g_nodes[g_node_count].name, name, sizeof(g_nodes[0].name) - 1);
g_nodes[g_node_count].is_dir = true;
g_nodes[g_node_count].size = 4096;
g_nodes[g_node_count].content[0] = '\0';
g_node_count++;
}
static void vfs_add_file(const char *name, const char *content) {
if (g_node_count >= MAX_VFS_NODES) return;
strncpy(g_nodes[g_node_count].name, name, sizeof(g_nodes[0].name) - 1);
g_nodes[g_node_count].is_dir = false;
uint32_t len = (uint32_t)strlen(content);
if (len >= sizeof(g_nodes[0].content)) len = sizeof(g_nodes[0].content) - 1;
memcpy(g_nodes[g_node_count].content, content, len);
g_nodes[g_node_count].content[len] = '\0';
g_nodes[g_node_count].size = len;
g_node_count++;
}
static void vfs_init() {
g_node_count = 0;
vfs_add_dir("/");
vfs_add_dir("/bin");
vfs_add_dir("/etc");
vfs_add_dir("/proc");
vfs_add_dir("/dev");
vfs_add_dir("/tmp");
vfs_add_file("/etc/os-release",
"NAME=\"opencoreC\"\n"
"VERSION=\"0.1.0-release\"\n"
"ID=opencorec\n"
"PRETTY_NAME=\"opencoreC Microkernel x86_64\"\n");
vfs_add_file("/etc/motd",
"=======================================================\n"
" Welcome to opencoreC Pure Microkernel (x86_64)!\n"
" Servers: init, uart, vfs, net, procmgr, sh, gui\n"
"=======================================================\n");
vfs_add_file("/etc/hosts", "127.0.0.1 localhost\n");
vfs_add_file("/proc/version", "opencoreC version 0.1.0-microkernel (Rust Ring 0 + C++ Ring 3)\n");
vfs_add_file("/proc/cpuinfo", "model name: x86_64 SMP Microkernel Processor\ncores: 4\n");
vfs_add_file("/dev/null", "");
vfs_add_file("/dev/uart0", "");
vfs_add_file("/dev/net0", "");
// Dynamically discover in-memory boot modules from Limine
char mbuf[512] = {0};
int len = sys_module_list(mbuf, sizeof(mbuf) - 1);
if (len > 0) {
char *p = mbuf;
while (*p) {
char mod_name[48] = {0};
int mi = 0;
while (*p && *p != ' ' && mi < 40) {
mod_name[mi++] = *p++;
}
while (*p == ' ') p++;
if (mi > 0) {
char full_path[56];
snprintf(full_path, sizeof(full_path), "/bin/%s", mod_name);
vfs_add_file(full_path, "[Executable Binary Module]");
}
}
}
}
extern "C" void _start(void) {
vfs_init();
puts("[VFS-SERVER] Virtual File System Daemon Started (Endpoint 5, Ring 3).");
uint64_t last_client = 0;
uint64_t reply_val0 = 0;
uint64_t reply_val1 = 0;
while (1) {
uint64_t sender_tid = 0;
uint64_t opcode = 0;
uint64_t arg0 = 0;
uint64_t arg1 = 0;
sysret_t ret = sys_ipc_reply_recv_raw(
VFS_ENDPOINT,
last_client,
reply_val0,
reply_val1,
&sender_tid,
&opcode,
&arg0,
&arg1
);
if (ret == 0 && sender_tid != 0) {
last_client = sender_tid;
if (opcode == VFS_OP_STAT) {
// Path passed packed in arg0 (first 8 bytes) + arg1 (next 8 bytes)
char path[32] = {0};
memcpy(path, &arg0, 8);
memcpy(path + 8, &arg1, 8);
bool found = false;
for (size_t i = 0; i < g_node_count; i++) {
if (strcmp(g_nodes[i].name, path) == 0) {
reply_val0 = 0; // Success
reply_val1 = g_nodes[i].size | (g_nodes[i].is_dir ? 0x80000000ULL : 0ULL);
found = true;
break;
}
}
if (!found) {
reply_val0 = (uint64_t)-1; // Not found
reply_val1 = 0;
}
} else if (opcode == VFS_OP_LIST) {
// arg0 = index
size_t idx = (size_t)arg0;
if (idx < g_node_count) {
reply_val0 = 0; // Success
reply_val1 = (uint64_t)g_nodes[idx].size | (g_nodes[idx].is_dir ? 0x80000000ULL : 0ULL);
} else {
reply_val0 = (uint64_t)-1; // End of list
reply_val1 = 0;
}
} else if (opcode == VFS_OP_READ_FILE) {
// arg0: packed name (first 8 bytes), arg1: offset
char path[16] = {0};
memcpy(path, &arg0, 8);
size_t offset = (size_t)arg1;
bool found = false;
for (size_t i = 0; i < g_node_count; i++) {
if (strcmp(g_nodes[i].name, path) == 0) {
found = true;
if (offset < g_nodes[i].size) {
uint64_t chunk = 0;
size_t avail = g_nodes[i].size - offset;
if (avail > 8) avail = 8;
memcpy(&chunk, g_nodes[i].content + offset, avail);
reply_val0 = avail;
reply_val1 = chunk;
} else {
reply_val0 = 0; // EOF
reply_val1 = 0;
}
break;
}
}
if (!found) {
reply_val0 = (uint64_t)-1;
reply_val1 = 0;
}
} else if (opcode == VFS_OP_WRITE_FILE) {
// arg0: packed name (first 8 bytes), arg1: 8 bytes data
char path[16] = {0};
memcpy(path, &arg0, 8);
bool found = false;
for (size_t i = 0; i < g_node_count; i++) {
if (strcmp(g_nodes[i].name, path) == 0) {
found = true;
memcpy(g_nodes[i].content, &arg1, 8);
g_nodes[i].size = 8;
reply_val0 = 0;
reply_val1 = 8;
break;
}
}
if (!found && g_node_count < MAX_VFS_NODES) {
vfs_add_file(path, "");
memcpy(g_nodes[g_node_count - 1].content, &arg1, 8);
g_nodes[g_node_count - 1].size = 8;
reply_val0 = 0;
reply_val1 = 8;
}
} else {
reply_val0 = (uint64_t)-1;
reply_val1 = 0;
}
} else {
last_client = 0;
sys_yield();
}
}
}