add UART console

This commit is contained in:
Lorenzo Torres 2026-01-31 15:57:54 +01:00
parent 25ec14c4a1
commit 48421fc0ef
3 changed files with 55 additions and 48 deletions

View file

@ -11,7 +11,6 @@ pub const Token = enum(u32) {
end = 0x09,
};
/// Raw FDT header as it appears in memory (big-endian)
pub const RawHeader = extern struct {
magic: u32,
totalsize: u32,
@ -25,7 +24,6 @@ pub const RawHeader = extern struct {
size_dt_struct: u32,
};
/// Memory reservation entry
pub const ReserveEntry = extern struct {
address: u64,
size: u64,
@ -38,7 +36,6 @@ pub const ReserveEntry = extern struct {
}
};
/// Parsed property data
pub const Property = struct {
name: []const u8,
data: []const u8,
@ -53,7 +50,6 @@ pub const Property = struct {
return std.mem.bigToNative(u64, @as(*const u64, @alignCast(@ptrCast(self.data.ptr))).*);
}
/// Read property as a null-terminated string
pub fn asString(self: Property) ?[]const u8 {
if (self.data.len == 0) return null;
for (self.data, 0..) |c, i| {
@ -91,7 +87,7 @@ pub const StringListIterator = struct {
self.pos += 1;
}
const end = self.pos;
self.pos += 1; // skip null terminator
self.pos += 1;
if (start == end) return null;
return self.data[start..end];
@ -130,15 +126,11 @@ pub const U64ArrayIterator = struct {
}
};
/// FDT node with its properties and children
pub const Node = struct {
/// Full path to this node (e.g., "/soc/uart@10000000")
name: []const u8,
fdt: *const Fdt,
/// Offset in structure block where this node's content starts (after name)
struct_offset: usize,
/// Get the unit address part of the node name (after '@')
pub fn unitAddress(self: Node) ?[]const u8 {
for (self.name, 0..) |c, i| {
if (c == '@') return self.name[i + 1 ..];
@ -146,7 +138,6 @@ pub const Node = struct {
return null;
}
/// Get the base name (before '@')
pub fn baseName(self: Node) []const u8 {
for (self.name, 0..) |c, i| {
if (c == '@') return self.name[0..i];
@ -154,7 +145,6 @@ pub const Node = struct {
return self.name;
}
/// Iterate over all properties of this node
pub fn properties(self: Node) PropertyIterator {
return .{
.fdt = self.fdt,
@ -162,7 +152,6 @@ pub const Node = struct {
};
}
/// Get a specific property by name
pub fn getProperty(self: Node, name: []const u8) ?Property {
var iter = self.properties();
while (iter.next()) |prop| {
@ -173,7 +162,6 @@ pub const Node = struct {
return null;
}
/// Iterate over direct children of this node
pub fn children(self: Node) ChildIterator {
// Skip to the end of properties to find children
var pos = self.struct_offset;
@ -202,7 +190,6 @@ pub const Node = struct {
};
}
/// Find a child node by name
pub fn getChild(self: Node, name: []const u8) ?Node {
var iter = self.children();
while (iter.next()) |child| {
@ -213,13 +200,11 @@ pub const Node = struct {
return null;
}
/// Get the 'compatible' property as a string list
pub fn compatible(self: Node) ?StringListIterator {
const prop = self.getProperty("compatible") orelse return null;
return prop.asStringList();
}
/// Check if node is compatible with given string
pub fn isCompatible(self: Node, compat: []const u8) bool {
var iter = self.compatible() orelse return false;
while (iter.next()) |c| {
@ -228,38 +213,31 @@ pub const Node = struct {
return false;
}
/// Get the 'reg' property - returns iterator over address/size pairs
/// Note: caller must know address-cells and size-cells from parent
pub fn reg(self: Node) ?[]const u8 {
const prop = self.getProperty("reg") orelse return null;
return prop.data;
}
/// Get the 'status' property
pub fn status(self: Node) ?[]const u8 {
const prop = self.getProperty("status") orelse return null;
return prop.asString();
}
/// Check if node is enabled (status = "okay" or "ok" or no status property)
pub fn isEnabled(self: Node) bool {
const s = self.status() orelse return true;
return std.mem.eql(u8, s, "okay") or std.mem.eql(u8, s, "ok");
}
/// Get #address-cells (defaults to 2 if not present)
pub fn addressCells(self: Node) u32 {
const prop = self.getProperty("#address-cells") orelse return 2;
return prop.asU32() orelse 2;
}
/// Get #size-cells (defaults to 1 if not present)
pub fn sizeCells(self: Node) u32 {
const prop = self.getProperty("#size-cells") orelse return 1;
return prop.asU32() orelse 1;
}
/// Get phandle of this node
pub fn phandle(self: Node) ?u32 {
// Try both 'phandle' and legacy 'linux,phandle'
if (self.getProperty("phandle")) |prop| {
@ -360,7 +338,6 @@ pub const ChildIterator = struct {
}
};
/// Iterator for all nodes in the tree (depth-first)
pub const NodeIterator = struct {
fdt: *const Fdt,
pos: usize,
@ -465,7 +442,6 @@ pub const Error = error{
InvalidStructure,
};
/// Parse an FDT from a raw pointer (as provided by OpenSBI)
pub fn parse(ptr: *const anyopaque) Error!Fdt {
const base: [*]const u8 = @ptrCast(ptr);
const header: *const RawHeader = @alignCast(@ptrCast(ptr));
@ -503,7 +479,6 @@ pub fn parse(ptr: *const anyopaque) Error!Fdt {
};
}
/// Get the root node
pub fn root(self: *const Fdt) ?Node {
if (self.struct_block.len < 4) return null;
@ -525,7 +500,6 @@ pub fn root(self: *const Fdt) ?Node {
};
}
/// Iterate over all nodes in the tree
pub fn nodes(self: *const Fdt) NodeIterator {
return .{
.fdt = self,
@ -534,7 +508,6 @@ pub fn nodes(self: *const Fdt) NodeIterator {
};
}
/// Iterate over all nodes except the root
pub fn nodesWithoutRoot(self: *const Fdt) NodeIterator {
return .{
.fdt = self,
@ -543,7 +516,6 @@ pub fn nodesWithoutRoot(self: *const Fdt) NodeIterator {
};
}
/// Find a node by path (e.g., "/soc/uart@10000000")
pub fn findNode(self: *const Fdt, path: []const u8) ?Node {
if (path.len == 0 or path[0] != '/') return null;
@ -574,7 +546,6 @@ pub fn findNode(self: *const Fdt, path: []const u8) ?Node {
return current;
}
/// Find a node by its phandle
pub fn findByPhandle(self: *const Fdt, handle: u32) ?Node {
var iter = self.nodes();
while (iter.next()) |node| {
@ -585,7 +556,6 @@ pub fn findByPhandle(self: *const Fdt, handle: u32) ?Node {
return null;
}
/// Find all nodes compatible with a given string
pub fn findCompatible(self: *const Fdt, compat: []const u8) CompatibleIterator {
return .{
.inner = self.nodesWithoutRoot(),
@ -593,13 +563,11 @@ pub fn findCompatible(self: *const Fdt, compat: []const u8) CompatibleIterator {
};
}
/// Find the first node compatible with a given string
pub fn findFirstCompatible(self: *const Fdt, compat: []const u8) ?Node {
var iter = self.findCompatible(compat);
return iter.next();
}
/// Iterate over memory reservation entries
pub fn memoryReservations(self: *const Fdt) MemoryReservationIterator {
return .{
.data = self.mem_rsv_block,
@ -607,17 +575,14 @@ pub fn memoryReservations(self: *const Fdt) MemoryReservationIterator {
};
}
/// Get the chosen node (boot parameters)
pub fn chosen(self: *const Fdt) ?Node {
return self.findNode("/chosen");
}
/// Get memory node(s)
pub fn memory(self: *const Fdt) ?Node {
return self.findNode("/memory") orelse self.findFirstCompatible("memory");
}
/// Get the CPUs node
pub fn cpus(self: *const Fdt) ?Node {
return self.findNode("/cpus");
}
@ -679,7 +644,6 @@ fn alignUp(value: anytype, alignment: @TypeOf(value)) @TypeOf(value) {
return (value + alignment - 1) & ~(alignment - 1);
}
/// Helper to parse reg property with known cell sizes
pub fn parseReg(data: []const u8, address_cells: u32, size_cells: u32) RegIterator {
return .{
.data = data,