diff options
author | Himbeer <himbeer@disroot.org> | 2024-05-23 13:48:01 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-05-23 13:48:01 +0200 |
commit | 3274a700daff545437f919041cbdce6938eede06 (patch) | |
tree | 60a4ec5ebb1406af20733027a2bb4a5d54e54908 /src/lib/hwinfo.zig | |
parent | 0f61d3bed969fecb35e438bfac2fe34f588834c6 (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.zig | 96 |
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 }; +} |