aboutsummaryrefslogtreecommitdiff
path: root/src/lib/hwinfo.zig
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-05-23 13:48:01 +0200
committerHimbeer <himbeer@disroot.org>2024-05-23 13:48:01 +0200
commit3274a700daff545437f919041cbdce6938eede06 (patch)
tree60a4ec5ebb1406af20733027a2bb4a5d54e54908 /src/lib/hwinfo.zig
parent0f61d3bed969fecb35e438bfac2fe34f588834c6 (diff)
Drop FDT support in favor of custom HWI format
Fixes numerous parsing bugs and increases efficiency. The kernel now runs successfully on the Lichee Pi 4A.
Diffstat (limited to 'src/lib/hwinfo.zig')
-rw-r--r--src/lib/hwinfo.zig96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/lib/hwinfo.zig b/src/lib/hwinfo.zig
new file mode 100644
index 0000000..a2d6a5e
--- /dev/null
+++ b/src/lib/hwinfo.zig
@@ -0,0 +1,96 @@
+// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+const config = @import("config");
+const std = @import("std");
+
+const hw_info = @embedFile("cfg/platform/" ++ config.platform ++ ".hwi");
+//const devices: *[hw_info.len / @sizeOf(Dev)]Dev = @ptrCast(hw_info);
+const devices = std.io.FixedBufferStream([]const u8){ .buffer = hw_info, .pos = 0 };
+
+pub const ParseError = error{
+ MissingKind,
+ MissingRegAddr,
+ MissingRegLen,
+
+ UnknownDevKind,
+};
+
+pub const DevKind = enum(u32) {
+ cpus,
+ plic,
+ pcie,
+ pci,
+
+ pub fn parse(buf: []const u8) !DevKind {
+ if (std.mem.eql(u8, buf, "cpus")) {
+ return .cpus;
+ } else if (std.mem.eql(u8, buf, "plic")) {
+ return .plic;
+ } else if (std.mem.eql(u8, buf, "pcie")) {
+ return .pcie;
+ } else if (std.mem.eql(u8, buf, "pci")) {
+ return .pci;
+ }
+
+ return ParseError.UnknownDevKind;
+ }
+};
+
+pub const Dev = extern struct {
+ kind: DevKind,
+ reg: Reg,
+ value: u64,
+
+ pub fn parse(buf: []const u8) !Dev {
+ var columns = std.mem.tokenizeScalar(u8, buf, ' ');
+ const kind_buf = columns.next() orelse return ParseError.MissingKind;
+ const reg_addr_buf = columns.next() orelse return ParseError.MissingRegAddr;
+ const reg_len_buf = columns.next() orelse return ParseError.MissingRegLen;
+ const value_buf = columns.next() orelse "0";
+
+ return .{
+ .kind = try DevKind.parse(kind_buf),
+ .reg = .{
+ .addr = try std.fmt.parseUnsigned(u64, reg_addr_buf, 0),
+ .len = try std.fmt.parseUnsigned(u64, reg_len_buf, 0),
+ },
+ .value = try std.fmt.parseUnsigned(u64, value_buf, 0),
+ };
+ }
+};
+
+pub const Reg = extern struct {
+ addr: u64,
+ len: u64,
+
+ pub fn slice(self: Reg, comptime T: type) []volatile T {
+ const ptr: [*]volatile T = @ptrFromInt(self.addr);
+ return ptr[0 .. self.len / @sizeOf(T)];
+ }
+};
+
+pub const ByKind = struct {
+ kind: DevKind,
+ fbs: std.io.FixedBufferStream([]const u8),
+
+ pub fn next(it: *ByKind) !?Dev {
+ const reader = it.fbs.reader();
+ while (reader.readStruct(Dev)) |device| {
+ if (device.kind == it.kind) {
+ return device;
+ }
+ } else |_| {}
+
+ return null;
+ }
+
+ pub fn reset(it: *ByKind) !void {
+ try it.fbs.seekTo(0);
+ }
+};
+
+pub fn byKind(kind: DevKind) ByKind {
+ return .{ .kind = kind, .fbs = devices };
+}