aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-07-10 18:45:04 +0200
committerHimbeer <himbeer@disroot.org>2024-07-10 18:45:04 +0200
commitea070c02fb0894f264e815d37527ae0e9b67759c (patch)
treec54eb250825dc717cc1c6cf21519ad6d71448ab1
parent16282fe4dce325acb293b23d02d5fa4bab9481ff (diff)
kernel: Provide userinit contents at /userinit in the VFS (untested)
-rw-r--r--src/kernel.zig4
-rw-r--r--src/lib/resources.zig107
-rw-r--r--src/lib/syscall.zig1
-rw-r--r--src/lib/vfs.zig3
4 files changed, 114 insertions, 1 deletions
diff --git a/src/kernel.zig b/src/kernel.zig
index b66bef1..820ee3e 100644
--- a/src/kernel.zig
+++ b/src/kernel.zig
@@ -13,6 +13,7 @@ const paging = @import("lib/paging.zig");
const pci = @import("lib/pci.zig");
const plic = @import("lib/plic.zig");
const process = @import("lib/process.zig");
+const resources = @import("lib/resources.zig");
const userinit = @import("lib/userinit.zig");
const vfs = @import("lib/vfs.zig");
@@ -200,6 +201,9 @@ fn pagedRun() !noreturn {
try vfs.init(allocator);
try w.print("Initialize VFS\r\n", .{});
+ try resources.provideBuiltin();
+ try w.print("Provide builtin resources\r\n", .{});
+
try w.print("Start init process\r\n", .{});
var userinit_stream = std.io.fixedBufferStream(userinit.tarball);
try process.runInit(allocator, userinit_stream.reader());
diff --git a/src/lib/resources.zig b/src/lib/resources.zig
new file mode 100644
index 0000000..0dc6d9f
--- /dev/null
+++ b/src/lib/resources.zig
@@ -0,0 +1,107 @@
+// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+const std = @import("std");
+
+const sysexchange = @import("sysexchange.zig");
+const userinit = @import("userinit.zig");
+const vfs = @import("vfs.zig");
+
+const Result = sysexchange.Result;
+const io = std.io;
+const tar = std.tar;
+
+const File = tar.Iterator(io.FixedBufferStream([]const u8).Reader).File;
+
+pub const Error = error{
+ NoTarFileInitializer,
+};
+
+pub fn provideBuiltin() !void {
+ try provideUserinit();
+}
+
+fn provideUserinit() !void {
+ try addDir("/userinit");
+
+ var userinit_stream = io.fixedBufferStream(userinit.tarball);
+ const reader = userinit_stream.reader();
+
+ var file_name_buffer: [4086]u8 = undefined;
+ var link_name_buffer: [4086]u8 = undefined;
+ var path_buffer: [4096]u8 = undefined;
+
+ var it = tar.iterator(reader, .{
+ .file_name_buffer = file_name_buffer[0..],
+ .link_name_buffer = link_name_buffer[0..],
+ });
+
+ while (try it.next()) |file| {
+ const path = try std.fmt.bufPrint(path_buffer[0..], "/userinit/{s}", .{file.name});
+ switch (file.kind) {
+ .file => try addFile(path, file),
+ .directory => try addDir(path),
+ .sym_link => {},
+ }
+ }
+}
+
+fn addFile(path: []const u8, file: File) !void {
+ const allocator = vfs.treeRoot().allocator;
+
+ const initializer = try allocator.create(File);
+ initializer.* = file;
+
+ try vfs.provideResource(path, .{
+ .tag = .file,
+ .data = .{
+ .file = .{
+ .openFn = open,
+ .readFn = read,
+ .writeFn = null,
+ .closeFn = close,
+ .initializer = initializer,
+ },
+ },
+ }, 0);
+}
+
+fn addDir(path: []const u8) !void {
+ const allocator = vfs.treeRoot().allocator;
+ const tree = try allocator.create(vfs.Tree);
+ tree.* = vfs.Tree.init(allocator);
+
+ try vfs.provideResource(path, .{
+ .tag = .dir,
+ .data = .{ .dir = tree },
+ }, 0);
+}
+
+fn open(initializer: ?*anyopaque, _: u16) callconv(.C) Result(*anyopaque) {
+ const file_template: *File = @alignCast(@ptrCast(initializer orelse {
+ return Result(*anyopaque).fromAnyTypeOrError(Error.NoTarFileInitializer);
+ }));
+
+ const allocator = vfs.treeRoot().allocator;
+ const context = allocator.create(File) catch |err| {
+ return Result(*anyopaque).fromAnyTypeOrError(err);
+ };
+ context.* = file_template.*;
+
+ return Result(*anyopaque).fromAnyTypeOrError(context);
+}
+
+fn read(context: *anyopaque, ptr: [*]u8, len: usize) callconv(.C) Result(usize) {
+ const ctx: *File = @alignCast(@ptrCast(context));
+
+ const buffer = ptr[0..len];
+ return Result(usize).fromAnyTypeOrError(ctx.read(buffer));
+}
+
+fn close(context: *anyopaque) callconv(.C) void {
+ const ctx: *File = @alignCast(@ptrCast(context));
+
+ const allocator = vfs.treeRoot().allocator;
+ allocator.destroy(ctx);
+}
diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig
index 51f6ff5..661c98d 100644
--- a/src/lib/syscall.zig
+++ b/src/lib/syscall.zig
@@ -118,6 +118,7 @@ fn provideFile(proc: *const process.Info, trap_frame: *trap.Frame) void {
.readFn = readFn,
.writeFn = writeFn,
.closeFn = closeFn,
+ .initializer = null,
} },
}, proc.id));
}
diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig
index 3c3099a..a687c43 100644
--- a/src/lib/vfs.zig
+++ b/src/lib/vfs.zig
@@ -42,8 +42,9 @@ pub const File = extern struct {
readFn: ?ReadFn,
writeFn: ?WriteFn,
closeFn: ?CloseFn,
+ initializer: ?*anyopaque,
- pub const OpenFn = *allowzero const fn (pid: u16) callconv(.C) sysexchange.Result(*anyopaque);
+ pub const OpenFn = *allowzero const fn (initializer: ?*anyopaque, pid: u16) callconv(.C) sysexchange.Result(*anyopaque);
pub const ReadFn = *const fn (context: *anyopaque, ptr: [*]u8, len: usize) callconv(.C) sysexchange.Result(usize);
pub const WriteFn = *const fn (context: *anyopaque, ptr: [*]const u8, len: usize) callconv(.C) sysexchange.Result(usize);
pub const CloseFn = *const fn (context: *anyopaque) callconv(.C) void;