aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/os.zig105
-rw-r--r--src/root.zig102
2 files changed, 106 insertions, 101 deletions
diff --git a/src/os.zig b/src/os.zig
new file mode 100644
index 0000000..42ef2d0
--- /dev/null
+++ b/src/os.zig
@@ -0,0 +1,105 @@
+// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+const std = @import("std");
+pub const hwinfo = @import("hwinfo.zig");
+
+pub const max_args = 6;
+
+const Result = struct {
+ value: usize,
+ error_code: usize,
+};
+
+const SyscallError = error{Kernel};
+
+fn autoCast(value: anytype) usize {
+ return switch (@typeInfo(@TypeOf(value))) {
+ .Type => @compileError("cannot pass type to system call"),
+ .Void => @compileError("cannot pass void to system call"),
+ .NoReturn => @compileError("cannot pass noreturn to system call"),
+ .Pointer => @intFromPtr(value),
+ else => value,
+ };
+}
+
+fn ecall(number: usize, args: anytype) Result {
+ var registers = [_]usize{0} ** max_args;
+ inline for (args, 0..) |arg, i| {
+ if (i >= max_args) @compileError("too many arguments to system call");
+ registers[i] = autoCast(arg);
+ }
+
+ var result: Result = undefined;
+ asm volatile (
+ \\ ecall
+ \\ sd a0, 0(%[value])
+ \\ sd a1, 0(%[error_code])
+ :
+ : [value] "r" (&result.value),
+ [error_code] "r" (&result.error_code),
+ [a0] "{a0}" (registers[0]),
+ [a1] "{a1}" (registers[1]),
+ [a2] "{a2}" (registers[2]),
+ [a3] "{a3}" (registers[3]),
+ [a4] "{a4}" (registers[4]),
+ [a5] "{a5}" (registers[5]),
+ [number] "{a7}" (number),
+ );
+ return result;
+}
+
+pub fn errorName(code: u16, buffer: []u8) !usize {
+ const result = ecall(100000, .{
+ code,
+ buffer.ptr,
+ buffer.len,
+ });
+ if (result.error_code != 0) return SyscallError.Kernel;
+ return result.value;
+}
+
+pub fn consoleWrite(bytes: []const u8) !usize {
+ const result = ecall(100001, .{ bytes.ptr, bytes.len });
+ if (result.error_code != 0) return SyscallError.Kernel;
+ return result.value;
+}
+
+pub fn launch(bytes: []align(@alignOf(std.elf.Elf64_Ehdr)) const u8) !usize {
+ const result = ecall(100002, .{ bytes.ptr, bytes.len });
+ if (result.error_code != 0) return SyscallError.Kernel;
+ return result.value;
+}
+
+pub fn end() noreturn {
+ _ = ecall(100003, .{});
+ unreachable;
+}
+
+pub fn terminate(pid: u16, thread: usize) !void {
+ const result = ecall(100004, .{ pid, thread });
+ if (result.error_code != 0) return SyscallError.Kernel;
+}
+
+pub fn processId() u16 {
+ const result = ecall(100005, .{});
+ return result.value;
+}
+
+pub fn threadId() usize {
+ const result = ecall(100006, .{});
+ return result.value;
+}
+
+pub fn rawUserinit() []const u8 {
+ var ptr: [*]const u8 = undefined;
+ const result = ecall(100007, .{&ptr});
+ return ptr[0..result.value];
+}
+
+pub fn devicesByKind(kind: hwinfo.DevKind, devices: []hwinfo.Dev) !usize {
+ const result = ecall(100008, .{ kind, devices.ptr, devices.len });
+ if (result.error_code != 0) return SyscallError.Kernel;
+ return result.value;
+}
diff --git a/src/root.zig b/src/root.zig
index 6f6c9cb..d6362e6 100644
--- a/src/root.zig
+++ b/src/root.zig
@@ -4,17 +4,7 @@
const builtin = @import("builtin");
const root = @import("root");
-const std = @import("std");
-pub const hwinfo = @import("hwinfo.zig");
-
-pub const max_args = 6;
-
-const Result = struct {
- value: usize,
- error_code: usize,
-};
-
-const SyscallError = error{Kernel};
+pub const os = @import("os.zig");
fn _start() callconv(.C) noreturn {
if (!@hasDecl(root, "main")) @compileError("no main function");
@@ -25,93 +15,3 @@ fn _start() callconv(.C) noreturn {
comptime {
if (!builtin.is_test) @export(_start, .{ .name = "_start" });
}
-
-fn autoCast(value: anytype) usize {
- return switch (@typeInfo(@TypeOf(value))) {
- .Type => @compileError("cannot pass type to system call"),
- .Void => @compileError("cannot pass void to system call"),
- .NoReturn => @compileError("cannot pass noreturn to system call"),
- .Pointer => @intFromPtr(value),
- else => value,
- };
-}
-
-fn ecall(number: usize, args: anytype) Result {
- var registers = [_]usize{0} ** max_args;
- inline for (args, 0..) |arg, i| {
- if (i >= max_args) @compileError("too many arguments to system call");
- registers[i] = autoCast(arg);
- }
-
- var result: Result = undefined;
- asm volatile (
- \\ ecall
- \\ sd a0, 0(%[value])
- \\ sd a1, 0(%[error_code])
- :
- : [value] "r" (&result.value),
- [error_code] "r" (&result.error_code),
- [a0] "{a0}" (registers[0]),
- [a1] "{a1}" (registers[1]),
- [a2] "{a2}" (registers[2]),
- [a3] "{a3}" (registers[3]),
- [a4] "{a4}" (registers[4]),
- [a5] "{a5}" (registers[5]),
- [number] "{a7}" (number),
- );
- return result;
-}
-
-pub fn errorName(code: u16, buffer: []u8) !usize {
- const result = ecall(100000, .{
- code,
- buffer.ptr,
- buffer.len,
- });
- if (result.error_code != 0) return SyscallError.Kernel;
- return result.value;
-}
-
-pub fn consoleWrite(bytes: []const u8) !usize {
- const result = ecall(100001, .{ bytes.ptr, bytes.len });
- if (result.error_code != 0) return SyscallError.Kernel;
- return result.value;
-}
-
-pub fn launch(bytes: []align(@alignOf(std.elf.Elf64_Ehdr)) const u8) !usize {
- const result = ecall(100002, .{ bytes.ptr, bytes.len });
- if (result.error_code != 0) return SyscallError.Kernel;
- return result.value;
-}
-
-pub fn end() noreturn {
- _ = ecall(100003, .{});
- unreachable;
-}
-
-pub fn terminate(pid: u16, thread: usize) !void {
- const result = ecall(100004, .{ pid, thread });
- if (result.error_code != 0) return SyscallError.Kernel;
-}
-
-pub fn processId() u16 {
- const result = ecall(100005, .{});
- return result.value;
-}
-
-pub fn threadId() usize {
- const result = ecall(100006, .{});
- return result.value;
-}
-
-pub fn rawUserinit() []const u8 {
- var ptr: [*]const u8 = undefined;
- const result = ecall(100007, .{&ptr});
- return ptr[0..result.value];
-}
-
-pub fn devicesByKind(kind: hwinfo.DevKind, devices: []hwinfo.Dev) !usize {
- const result = ecall(100008, .{ kind, devices.ptr, devices.len });
- if (result.error_code != 0) return SyscallError.Kernel;
- return result.value;
-}