diff options
author | Himbeer <himbeer@disroot.org> | 2024-07-01 23:30:51 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-07-01 23:30:51 +0200 |
commit | 64aab3ba1e8f6120f59e2923a8bbae02e16693d9 (patch) | |
tree | 7c35e93bba91e7d0fda5c74a16b70de09e02020e /src/lib | |
parent | ae2418ccaebdfcede0a79ce7b1e1e574ff468c72 (diff) |
syscall: Implement opening resources
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/process.zig | 22 | ||||
-rw-r--r-- | src/lib/syscall.zig | 33 | ||||
-rw-r--r-- | src/lib/vfs.zig | 18 |
3 files changed, 60 insertions, 13 deletions
diff --git a/src/lib/process.zig b/src/lib/process.zig index 0ab11ae..6f8ffce 100644 --- a/src/lib/process.zig +++ b/src/lib/process.zig @@ -9,6 +9,7 @@ const instructions = @import("instructions.zig"); const paging = @import("paging.zig"); const time = @import("sbi/time.zig"); const trap = @import("trap.zig"); +const vfs = @import("vfs.zig"); const elf = std.elf; @@ -25,6 +26,10 @@ pub const Error = error{ NoInit, }; +pub const ProcessError = error{ + TooManyResourceDescriptors, +}; + pub const ExeError = error{ BadEndian, BadArch, @@ -42,23 +47,37 @@ pub const State = enum(u8) { terminated, }; -pub const Info = extern struct { +pub const Info = struct { id: u16, trap_frame: trap.Frame, stack: *[num_stack_pages * paging.page_size]u8, pc: usize, page_table: *paging.Table, state: State, + rds: std.AutoArrayHashMap(usize, vfs.ResourceDescriptor), pub fn destroy(self: *Info) !void { try paging.free(self.stack); try self.page_table.unmap(); try paging.free(self.page_table); + self.rds.deinit(); } pub fn satp(self: *const Info) paging.Satp { return self.page_table.satp(self.id); } + + pub fn makeRdHandle(self: *Info, rd: vfs.ResourceDescriptor) !usize { + if (self.rds.count() == std.math.maxInt(usize)) { + return ProcessError.TooManyResourceDescriptors; + } + + var handle = self.rds.count() + 1; + while (self.rds.contains(handle)) : (handle +%= 1) {} + + try self.rds.put(handle, rd); + return handle; + } }; pub fn next() ?*Info { @@ -195,6 +214,7 @@ pub fn create(allocator: std.mem.Allocator, elf_buf: []align(@alignOf(elf.Elf64_ .pc = hdr.entry, .page_table = procmem, .state = .waiting, + .rds = std.AutoArrayHashMap(usize, vfs.ResourceDescriptor).init(allocator), }; proc.trap_frame.general_purpose_registers[2] = stack_top; diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig index eece736..c2457c6 100644 --- a/src/lib/syscall.zig +++ b/src/lib/syscall.zig @@ -4,6 +4,7 @@ const instructions = @import("instructions.zig"); const paging = @import("paging.zig"); +const process = @import("process.zig"); const sysexchange = @import("sysexchange.zig"); const trap = @import("trap.zig"); const vfs = @import("vfs.zig"); @@ -12,10 +13,10 @@ pub const Error = error{ UnknownSyscall, }; -pub fn handle(trap_frame: *trap.Frame) !void { +pub fn handle(proc: *process.Info, trap_frame: *trap.Frame) !void { switch (trap_frame.general_purpose_registers[17]) { 100000 => uprint(trap_frame), - 100001 => open(trap_frame), + 100001 => open(proc, trap_frame), 100002 => close(trap_frame), 100003 => provideStream(trap_frame), 100004 => provideFile(trap_frame), @@ -40,12 +41,22 @@ fn uprint(trap_frame: *const trap.Frame) void { w.print("User message: {s}\r\n", .{str}) catch unreachable; } -// open(path: [*:0]const u8) Result(usize) // fixme: Kernel panic if null pointer -fn open(trap_frame: *const trap.Frame) void { +// open(path: [*:0]const u8, data: usize) Result(usize) // fixme: Kernel panic if null pointer +fn open(proc: *process.Info, trap_frame: *trap.Frame) void { const path: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]); - - _ = path; - unreachable; + const data = trap_frame.general_purpose_registers[11]; + + const user_info = vfs.openZ(path, proc.id, data) catch |err| { + sysexchange.frameReturn(usize, trap_frame, err); + return; + }; + switch (user_info) { + .rd => |resource_descriptor| { + const maybe_handle = proc.makeRdHandle(resource_descriptor); + sysexchange.frameReturn(null, trap_frame, maybe_handle); + }, + .value => |value| sysexchange.frameReturnResult(usize, trap_frame, value), + } } // close(rd: usize) void @@ -66,7 +77,7 @@ fn provideStream(trap_frame: *trap.Frame) void { const readFn: ?vfs.Stream.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[11]); const writeFn: ?vfs.Stream.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[12]); - sysexchange.frameReturn(trap_frame, vfs.provideResourceZ(path, .{ + sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path, .{ .stream = .{ .readFn = readFn, .writeFn = writeFn, @@ -88,7 +99,7 @@ fn provideFile(trap_frame: *trap.Frame) void { const writeFn: ?vfs.File.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[13]); const closeFn: ?vfs.File.CloseFn = @ptrFromInt(trap_frame.general_purpose_registers[14]); - sysexchange.frameReturn(trap_frame, vfs.provideResourceZ(path, .{ + sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path, .{ .file = .{ .openFn = openFn, .readFn = readFn, @@ -106,7 +117,7 @@ fn provideHook(trap_frame: *trap.Frame) void { const path: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]); const callback: vfs.Hook.Callback = @ptrFromInt(trap_frame.general_purpose_registers[11]); - sysexchange.frameReturn(trap_frame, vfs.provideResourceZ(path, .{ + sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path, .{ .hook = .{ .callback = callback, }, @@ -138,7 +149,7 @@ fn provideDirHook(trap_frame: *trap.Frame) void { const findFn: vfs.DirHook.FindFn = @ptrFromInt(trap_frame.general_purpose_registers[12]); const removeFn: vfs.DirHook.RemoveFn = @ptrFromInt(trap_frame.general_purpose_registers[13]); - sysexchange.frameReturn(trap_frame, vfs.provideResourceZ(path, .{ + sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path, .{ .dir_hook = .{ .provideFn = provideFn, .findFn = findFn, diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig index 0eb57a6..56834d6 100644 --- a/src/lib/vfs.zig +++ b/src/lib/vfs.zig @@ -116,7 +116,6 @@ pub const Tree = struct { pub const ResourceDescriptor = struct { inode: *Inode, - pos: usize = 0, pub fn init(inode: *Inode) !ResourceDescriptor { inode.refs = std.math.add(usize, inode.refs, 1) catch return Error.TooManyReferences; @@ -130,6 +129,11 @@ pub const ResourceDescriptor = struct { } }; +pub const UserInfo = union(enum) { + rd: ResourceDescriptor, + value: sysexchange.Result(usize), +}; + pub fn init(allocator: mem.Allocator) void { root = Tree.init(allocator); } @@ -174,3 +178,15 @@ pub fn provideResource(path: []const u8, resource: Resource) !void { pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource) !void { return provideResource(mem.sliceTo(path_c, 0), resource); } + +pub fn open(path: []const u8, pid: u16, data: usize) !UserInfo { + const node = find(path) orelse return Error.NotFound; + return switch (node.data.resource) { + .hook => |hook| .{ .value = hook.callback(pid, data) }, + else => .{ .rd = try ResourceDescriptor.init(&node.data) }, + }; +} + +pub fn openZ(path_c: [*:0]const u8, pid: u16, data: usize) !UserInfo { + return open(mem.sliceTo(path_c, 0), pid, data); +} |