diff options
| author | Bobby <[email protected]> | 2026-01-22 18:15:12 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-01-22 18:15:12 +0530 |
| commit | 3edd887543474bac679cc8073006bfe4ceacb2ea (patch) | |
| tree | 3a387acdd6b931f681fc360c7013b9321d4f8758 /system | |
| parent | b0375f165f3616dbb8b880b7cf602d281f1d27de (diff) | |
| download | akiba-3edd887543474bac679cc8073006bfe4ceacb2ea.tar.xz akiba-3edd887543474bac679cc8073006bfe4ceacb2ea.zip | |
feat: Implement keyboard input handling and shell functionality
- Added framebuffer initialization and retrieval functions in multiboot2.zig.
- Integrated framebuffer support into the boot sequence.
- Refactored keyboard driver to use a circular buffer for input and added blocking behavior for kata waiting on keyboard input.
- Enhanced kata management to support blocking and waking katas based on keyboard input.
- Introduced a new invocation for reading a character from the keyboard (getkeychar).
- Implemented a simple shell (ash) that reads user input and echoes it back.
- Updated syscall handling to include the new getkeychar invocation.
- Improved memory management for loading programs and handling user/kernel stacks.
- Added functionality to wake katas waiting for specific events, such as the dissolution of other katas.
Diffstat (limited to 'system')
| -rw-r--r-- | system/ash/ash.zig | 45 | ||||
| -rw-r--r-- | system/ash/ash.zon | 8 | ||||
| -rw-r--r-- | system/libraries/akiba/io.zig | 16 | ||||
| -rw-r--r-- | system/libraries/akiba/kata.zig | 12 | ||||
| -rw-r--r-- | system/libraries/akiba/sys.zig | 13 | ||||
| -rw-r--r-- | system/pulse/pulse.zig | 19 |
6 files changed, 98 insertions, 15 deletions
diff --git a/system/ash/ash.zig b/system/ash/ash.zig new file mode 100644 index 0000000..577dea3 --- /dev/null +++ b/system/ash/ash.zig @@ -0,0 +1,45 @@ +//! Ash - Akiba Shell + +const akiba = @import("akiba"); + +const MAX_INPUT = 256; +var input_buffer: [MAX_INPUT]u8 = undefined; +var input_len: usize = 0; + +export fn _start() noreturn { + while (true) { + // Print prompt + akiba.io.print("/ >>> ") catch {}; + + // Read line + input_len = 0; + while (true) { + const char = akiba.io.getchar() catch continue; + + if (char == '\n') { + akiba.io.print("\n") catch {}; + break; + } else if (char == '\x08') { + // Backspace + if (input_len > 0) { + input_len -= 1; + // Echo backspace to screen + akiba.io.print("\x08") catch {}; + } + } else if (char >= 32 and char <= 126 and input_len < MAX_INPUT - 1) { + input_buffer[input_len] = char; + input_len += 1; + // Echo character to screen + const char_str = [_]u8{char}; + akiba.io.print(&char_str) catch {}; + } + } + + // TODO: Parse and execute command + if (input_len > 0) { + akiba.io.print("Command \"") catch {}; + akiba.io.print(input_buffer[0..input_len]) catch {}; + akiba.io.print("\" not implemented yet\n") catch {}; + } + } +} diff --git a/system/ash/ash.zon b/system/ash/ash.zon new file mode 100644 index 0000000..0c72775 --- /dev/null +++ b/system/ash/ash.zon @@ -0,0 +1,8 @@ +.{ + .name = "ash", + .version = "0.1.0", + .paths = .{""}, + .dependencies = .{ + .akiba = .{ .path = "../libraries/akiba" }, + }, +} diff --git a/system/libraries/akiba/io.zig b/system/libraries/akiba/io.zig index b8f8eef..35ff739 100644 --- a/system/libraries/akiba/io.zig +++ b/system/libraries/akiba/io.zig @@ -1,6 +1,7 @@ //! File I/O operations const sys = @import("sys.zig"); +const kata = @import("kata.zig"); pub const Error = error{ NotFound, @@ -51,6 +52,21 @@ pub fn mark(fd: FileDescriptor, data: []const u8) Error!usize { return result; } +pub fn getchar() !u8 { + // Loop until character is available, yielding CPU + while (true) { + const result = sys.syscall0(.getkeychar); + if (result != @as(u64, @bitCast(@as(i64, -2)))) { + if (result != @as(u64, @bitCast(@as(i64, -1)))) { + return @truncate(result); + } + return error.ReadFailed; + } + // No input yet (-2 = EAGAIN), yield and try again + kata.yield(); + } +} + pub fn print(text: []const u8) Error!void { _ = try mark(stream, text); } diff --git a/system/libraries/akiba/kata.zig b/system/libraries/akiba/kata.zig index 2283ce8..14f2946 100644 --- a/system/libraries/akiba/kata.zig +++ b/system/libraries/akiba/kata.zig @@ -20,9 +20,13 @@ pub fn spawn(path: []const u8) !u32 { } pub fn wait(pid: u32) !u64 { - const result = sys.syscall1(.wait, pid); - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return error.WaitFailed; + // Retry loop: keep checking until the target exits + while (true) { + const result = sys.syscall1(.wait, pid); + if (result != @as(u64, @bitCast(@as(i64, -1)))) { + return result; + } + // Target still running, yield and try again + yield(); } - return result; } diff --git a/system/libraries/akiba/sys.zig b/system/libraries/akiba/sys.zig index ee74777..10329ff 100644 --- a/system/libraries/akiba/sys.zig +++ b/system/libraries/akiba/sys.zig @@ -9,6 +9,7 @@ pub const Invocation = enum(u64) { spawn = 0x06, wait = 0x07, yield = 0x08, + getkeychar = 0x09, }; pub fn syscall0(inv: Invocation) u64 { @@ -16,8 +17,7 @@ pub fn syscall0(inv: Invocation) u64 { asm volatile ("syscall" : [ret] "={rax}" (result), : [inv] "{rax}" (@intFromEnum(inv)), - : .{ .rcx = true, .r11 = true, .memory = true } - ); + : .{ .rcx = true, .r11 = true, .memory = true }); return result; } @@ -27,8 +27,7 @@ pub fn syscall1(inv: Invocation, arg1: u64) u64 { : [ret] "={rax}" (result), : [inv] "{rax}" (@intFromEnum(inv)), [arg1] "{rdi}" (arg1), - : .{ .rcx = true, .r11 = true, .memory = true } - ); + : .{ .rcx = true, .r11 = true, .memory = true }); return result; } @@ -39,8 +38,7 @@ pub fn syscall2(inv: Invocation, arg1: u64, arg2: u64) u64 { : [inv] "{rax}" (@intFromEnum(inv)), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), - : .{ .rcx = true, .r11 = true, .memory = true } - ); + : .{ .rcx = true, .r11 = true, .memory = true }); return result; } @@ -52,7 +50,6 @@ pub fn syscall3(inv: Invocation, arg1: u64, arg2: u64, arg3: u64) u64 { [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3), - : .{ .rcx = true, .r11 = true, .memory = true } - ); + : .{ .rcx = true, .r11 = true, .memory = true }); return result; } diff --git a/system/pulse/pulse.zig b/system/pulse/pulse.zig index c558eb3..2da96cf 100644 --- a/system/pulse/pulse.zig +++ b/system/pulse/pulse.zig @@ -4,9 +4,22 @@ const akiba = @import("akiba"); export fn _start() noreturn { - akiba.io.println("Pulse: System ready!") catch {}; - + // Init loop - respawn shell when it exits while (true) { - akiba.kata.yield(); + const shell_pid = akiba.kata.spawn("/system/ash/ash.akiba") catch { + akiba.io.println("Pulse: Failed to spawn shell") catch {}; + akiba.kata.yield(); + continue; + }; + + // Wait for shell to exit + _ = akiba.kata.wait(shell_pid) catch { + akiba.io.println("Pulse: Shell wait failed") catch {}; + akiba.kata.yield(); + continue; + }; + + // Shell exited, respawn + akiba.io.println("\nPulse: Shell exited, respawning...\n") catch {}; } } |
