hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/bridge
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-10-06 12:49:46 +0200
committerhachem <im@hachem.wtf>2026-10-06 12:49:46 +0200
commit5d4a723a5f157c0ed38a348099a600d1d21c3c2b (patch)
tree70e5fdf560a64cd0eb3a13d88ce046ddd29fd077 /bridge
parent52dab7fc85d877e80e3032f0afabae906adebad8 (diff)
feat: gils core utils and other shit
Diffstat (limited to 'bridge')
-rw-r--r--bridge/bridge.zig35
-rw-r--r--bridge/hosts.zig83
-rw-r--r--bridge/serial.zig4
3 files changed, 108 insertions, 14 deletions
diff --git a/bridge/bridge.zig b/bridge/bridge.zig
index 71f7023..87548eb 100644
--- a/bridge/bridge.zig
+++ b/bridge/bridge.zig
@@ -15,16 +15,25 @@ pub const KernelOps = hosts.KernelOps;
// the vm outlives boot() now, so we juts make this hoe static
var g_vm: ?*revo.VM = null;
-const init_program = @embedFile("k_font") ++ "\n" ++
- @embedFile("k_console") ++ "\n" ++
- @embedFile("k_vmm") ++ "\n" ++
- @embedFile("k_fs") ++ "\n" ++
- @embedFile("k_vfs") ++ "\n" ++
- @embedFile("k_seed") ++ "\n" ++
- @embedFile("k_proc") ++ "\n" ++
- @embedFile("k_shell") ++ "\n" ++
- @embedFile("k_input") ++ "\n" ++
- @embedFile("k_main");
+// NOTE: ORDER MATTERS
+const init_program = blk: {
+ var s: []const u8 = @embedFile("k_font") ++ "\n" ++
+ @embedFile("k_console") ++ "\n" ++
+ @embedFile("k_vmm") ++ "\n" ++
+ @embedFile("k_fs") ++ "\n" ++
+ @embedFile("k_vfs") ++ "\n" ++
+ @embedFile("k_seed") ++ "\n";
+
+ // gils shit
+ const gils_embedded = .{ "gils", "ed" };
+ for (gils_embedded) |g| s = s ++ @embedFile("k_gils_" ++ g) ++ "\n";
+
+ s = s ++ @embedFile("k_proc") ++ "\n" ++
+ @embedFile("k_shell") ++ "\n" ++
+ @embedFile("k_input") ++ "\n" ++
+ @embedFile("k_main");
+ break :blk s;
+};
pub fn boot(alloc: std.mem.Allocator, out: Sink, fb: ?Fb, ops: ?KernelOps) void {
serial.setSink(out);
@@ -50,7 +59,7 @@ pub fn boot(alloc: std.mem.Allocator, out: Sink, fb: ?Fb, ops: ?KernelOps) void
};
out("bridge: revo VM up\r\n");
- hosts.registerPrimitives(vm) catch {
+ hosts.passShitToRevo(vm) catch {
out("bridge: registering primitives failed\r\n");
return;
};
@@ -64,7 +73,7 @@ pub fn boot(alloc: std.mem.Allocator, out: Sink, fb: ?Fb, ops: ?KernelOps) void
.err => |failure| {
out("bridge: compile error: ");
var sw = serial.SinkWriter.init();
- revo.lang.renderError(alloc, &sw.interface, .{ .name = "kernel", .text = init_program }, failure) catch {};
+ revo.lang.renderError(alloc, &sw.interface, .{ .name = "kernel", .text = init_program }, failure, .{}) catch {};
out("\r\n");
return;
},
@@ -86,7 +95,7 @@ pub fn boot(alloc: std.mem.Allocator, out: Sink, fb: ?Fb, ops: ?KernelOps) void
.err => |failure| {
out("\r\nbridge: runtime error: ");
var sw = serial.SinkWriter.init();
- failure.render(alloc, &sw.interface, init_program) catch {};
+ failure.render(alloc, &sw.interface, init_program, false) catch {};
out("\r\n");
},
}
diff --git a/bridge/hosts.zig b/bridge/hosts.zig
index e329316..51362dc 100644
--- a/bridge/hosts.zig
+++ b/bridge/hosts.zig
@@ -8,6 +8,22 @@ const Data = convert.Data;
const argInt = convert.argInt;
const emit = serial.emit;
+// gils shit
+const Script = struct { name: []const u8, src: []const u8 };
+const scripts = [_]Script{
+ .{ .name = "ls", .src = @embedFile("k_gils_ls") },
+ .{ .name = "tree", .src = @embedFile("k_gils_tree") },
+ .{ .name = "cat", .src = @embedFile("k_gils_cat") },
+ .{ .name = "rm", .src = @embedFile("k_gils_rm") },
+ .{ .name = "mkdir", .src = @embedFile("k_gils_mkdir") },
+ .{ .name = "touch", .src = @embedFile("k_gils_touch") },
+ .{ .name = "cp", .src = @embedFile("k_gils_cp") },
+ .{ .name = "mv", .src = @embedFile("k_gils_mv") },
+ .{ .name = "wc", .src = @embedFile("k_gils_wc") },
+ .{ .name = "head", .src = @embedFile("k_gils_head") },
+ .{ .name = "tail", .src = @embedFile("k_gils_tail") },
+};
+
// the actual framebuffer, the data layout feels pretty self explanatory
pub const Fb = struct {
ptr: [*]u8,
@@ -50,6 +66,7 @@ pub const KernelOps = struct {
disk_sectors: *const fn () u64,
disk_read: *const fn (u64, u64) u64, // lba, phys buf -> 1 ok / 0 fail
disk_write: *const fn (u64, u64) u64, // lba, phys buf -> 1 ok / 0 fail
+ alloc_contig: *const fn (u64) u64, // n contiguous pages -> phys base, 0 on fail
};
var g_kops: ?KernelOps = null;
@@ -337,7 +354,63 @@ fn hostDiskWrite(args: []const revo.Value, _: *revo.VM) anyerror!HostResult {
}
// pass shit to revo
-pub fn registerPrimitives(vm: *revo.VM) !void {
+fn hostAllocContig(args: []const revo.Value, _: *revo.VM) anyerror!HostResult {
+ const n = argInt(u64, args, 0) orelse return HostResult.other("alloc_contig: bad count");
+ return HostResult.data(Data.new.num(kops().alloc_contig(n)));
+}
+
+// pass shit to revo
+fn hostBlitStr(args: []const revo.Value, vm: *revo.VM) anyerror!HostResult {
+ const phys = argInt(u64, args, 0) orelse return HostResult.other("blit_str: bad addr");
+ const sid = args[1].asString() orelse return HostResult.other("blit_str: not a string");
+ const bytes = vm.stringValue(sid);
+ const dst: [*]u8 = @ptrFromInt(kops().phys_to_virt(phys));
+ @memcpy(dst[0..bytes.len], bytes);
+ return HostResult.data(Data.new.num(bytes.len));
+}
+
+// pass shit to revo
+fn hostPhysToStr(args: []const revo.Value, vm: *revo.VM) anyerror!HostResult {
+ const phys = argInt(u64, args, 0) orelse return HostResult.other("phys_to_str: bad addr");
+ const len = argInt(usize, args, 1) orelse return HostResult.other("phys_to_str: bad len");
+ const src: [*]const u8 = @ptrFromInt(kops().phys_to_virt(phys));
+ return HostResult.data(try vm.ownValueString(src[0..len]));
+}
+
+// pass shit to revo
+fn hostScriptCount(_: []const revo.Value, _: *revo.VM) anyerror!HostResult {
+ return HostResult.data(Data.new.num(scripts.len));
+}
+
+// pass shit to revo
+fn hostScriptName(args: []const revo.Value, vm: *revo.VM) anyerror!HostResult {
+ const i = argInt(usize, args, 0) orelse return HostResult.other("script_name: bad index");
+ if (i >= scripts.len) return HostResult.other("script_name: out of range");
+ return HostResult.data(try vm.ownValueString(scripts[i].name));
+}
+
+// pass shit to revo
+fn hostScriptSrc(args: []const revo.Value, vm: *revo.VM) anyerror!HostResult {
+ const i = argInt(usize, args, 0) orelse return HostResult.other("script_src: bad index");
+ if (i >= scripts.len) return HostResult.other("script_src: out of range");
+ return HostResult.data(try vm.ownValueString(scripts[i].src));
+}
+
+// pass shit to revo
+fn hostEvalScript(args: []const revo.Value, vm: *revo.VM) anyerror!HostResult {
+ const sid = args[0].asString() orelse return HostResult.other("eval_script: not a string");
+ const src = vm.stringValue(sid);
+ const res = revo.run.runModule(vm, "<script>", src, false) catch |e| {
+ return HostResult.data(try vm.ownValueString(@errorName(e)));
+ };
+ return switch (res) {
+ .ok => HostResult.data(Data.new.nil()),
+ .err => HostResult.data(try vm.ownValueString("script runtime error")),
+ };
+}
+
+// pass shit to revo
+pub fn passShitToRevo(vm: *revo.VM) !void {
const define = revo.baselib.host.define;
const T = revo.baselib.host.ParamType;
try vm.registerGlobal("outb", try vm.installHost("outb", define(&[_]T{ .number, .number }, hostOutb)));
@@ -377,4 +450,12 @@ pub fn registerPrimitives(vm: *revo.VM) !void {
try vm.registerGlobal("disk_sectors", try vm.installHost("disk_sectors", define(&[_]T{}, hostDiskSectors)));
try vm.registerGlobal("disk_read", try vm.installHost("disk_read", define(&[_]T{ .number, .number }, hostDiskRead)));
try vm.registerGlobal("disk_write", try vm.installHost("disk_write", define(&[_]T{ .number, .number }, hostDiskWrite)));
+
+ try vm.registerGlobal("eval_script", try vm.installHost("eval_script", define(&[_]T{.string}, hostEvalScript)));
+ try vm.registerGlobal("script_count", try vm.installHost("script_count", define(&[_]T{}, hostScriptCount)));
+ try vm.registerGlobal("script_name", try vm.installHost("script_name", define(&[_]T{.number}, hostScriptName)));
+ try vm.registerGlobal("script_src", try vm.installHost("script_src", define(&[_]T{.number}, hostScriptSrc)));
+ try vm.registerGlobal("alloc_contig", try vm.installHost("alloc_contig", define(&[_]T{.number}, hostAllocContig)));
+ try vm.registerGlobal("blit_str", try vm.installHost("blit_str", define(&[_]T{ .number, .string }, hostBlitStr)));
+ try vm.registerGlobal("phys_to_str", try vm.installHost("phys_to_str", define(&[_]T{ .number, .number }, hostPhysToStr)));
}
diff --git a/bridge/serial.zig b/bridge/serial.zig
index ec0bdb9..f765efe 100644
--- a/bridge/serial.zig
+++ b/bridge/serial.zig
@@ -43,6 +43,10 @@ fn ioOperate(_: ?*anyopaque, operation: std.Io.Operation) std.Io.Cancelable!std.
.file_read_streaming => .{ .file_read_streaming = error.InputOutput },
.device_io_control => .{ .device_io_control = -1 },
.net_receive => .{ .net_receive = .{ error.NetworkDown, 0 } },
+ // no networking on bare metal (yet)
+ .net_send => .{ .net_send = .{ null, 0 } },
+ .net_read => .{ .net_read = error.Unexpected },
+ .net_write => .{ .net_write = error.Unexpected },
};
}