Files
LithosAnanake/include/starkernel/fdt.h
T
Robert Allan JamesandClaude Sonnet 5 5e46f18fd9
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run
fdt.c: node-scoped lookup extension (FABRIC-3.md SSIV.3/SSV.3 shared item)
Adds fdt_find_node_by_compatible() and fdt_find_prop_in_node() to the
minimal FDT reader -- the extension fdt.h's own header comment already
flagged as a known future need ("item 0.6 will need node-scoped reg
lookups"), now with real consumers: the Pi 5's UART/mailbox register
addresses (native boot, no ACPI) and the Milk-V Mars's real PLIC base
address (currently hardcoded to QEMU-virt's own value).

fdt_find_node_by_compatible() matches any entry in a node's
NUL-separated "compatible" list, first match in document order.
fdt_find_prop_in_node() scopes to that one node's own direct
properties only -- stops at the first child node or the node's own
end, per the DT spec's ordering guarantee that a node's properties
always precede its children. Same minimal, non-tree-building,
single-linear-scan-per-call style as the existing reader; no new
state, no allocation.

Compile-only verification -- no caller wired in yet, this is the
shared primitive both boards' own punch-list items will call once
built. Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in
the foreground).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
2026-09-04 13:05:42 -04:00

113 lines
4.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James. All rights reserved.
Licensed under the StarForth License, Version 1.0.
*/
/**
* fdt.h - Minimal flattened-devicetree reader
*
* Just enough of the Devicetree Specification v0.4 §5 to pull values out of
* the blob the UEFI firmware publishes under EFI_DTB_TABLE_GUID, or that a
* native (non-UEFI) boot entry passes directly. Read-only, no allocation, no
* tree construction — it walks the structure block each call, which is fine
* for the handful of boot-time lookups the kernel needs.
*
* Deliberately not a general devicetree library. Added for punch-list item
* 0.3 (riscv64 timebase-frequency); extended (FABRIC-3.md §IV.3/§V.3,
* 2026-09-04) with node-scoped lookup, for exactly the case this header
* originally flagged as a future need (item 0.6's aarch64 GIC) plus its
* real, concrete consumers as of this pass: the Raspberry Pi 5's UART/
* mailbox register addresses (native boot, no ACPI) and the Milk-V Mars's
* real PLIC base address (currently hardcoded to QEMU-virt's own value,
* `arch/riscv64/plic.c`'s own doc comment already warned this isn't
* assumed stable across configurations).
*/
#ifndef STARKERNEL_FDT_H
#define STARKERNEL_FDT_H
#include <stdint.h>
/**
* @brief Test whether @p fdt points at a valid flattened devicetree.
*
* Checks the 0xd00dfeed magic and that the structure and strings blocks lie
* inside totalsize. Does not validate the token stream.
*
* @param fdt Candidate blob; NULL is safe and returns 0.
* @return 1 if the header is usable, 0 otherwise.
*/
int fdt_valid(const void* fdt);
/**
* @brief Find the first property with @p name anywhere in the tree.
*
* Scans the structure block in document order and returns the first match
* regardless of which node it belongs to. That is sufficient for properties
* which are uniform across a machine (timebase-frequency being the case this
* was written for) and is *not* sufficient for anything node-scoped.
*
* @param fdt Blob, already checked with @c fdt_valid().
* @param name Property name, NUL-terminated.
* @param len_out Receives the property length in bytes; may be NULL.
* @return Pointer to the property value inside @p fdt, or NULL if not found.
* The value is big-endian as stored in the blob.
*/
const void* fdt_find_prop(const void* fdt, const char* name, uint32_t* len_out);
/**
* @brief Read a single-cell (32-bit) property by name.
*
* Convenience over @c fdt_find_prop() that also handles the big-endian
* conversion. Fails if the property is absent or not exactly 4 bytes.
*
* @param fdt Blob, already checked with @c fdt_valid().
* @param name Property name, NUL-terminated.
* @param out Receives the host-order value on success; untouched on failure.
* @return 1 on success, 0 on failure.
*/
int fdt_prop_u32(const void* fdt, const char* name, uint32_t* out);
/**
* @brief Find the first node whose "compatible" property matches @p compatible.
*
* "compatible" is a NUL-separated list of strings (DT spec §2.3.1) — matches
* if @p compatible equals any one entry in the list, not just the whole
* property verbatim. Scans the whole tree in document order; the first
* matching node wins if more than one exists.
*
* @param fdt Blob, already checked with @c fdt_valid().
* @param compatible Compatible string to match, NUL-terminated.
* @return An opaque handle to the matched node, for use with
* @c fdt_find_prop_in_node() only (not a raw offset or a pointer
* to anything else meaningful) — or NULL if no node matches.
*/
const void* fdt_find_node_by_compatible(const void* fdt, const char* compatible);
/**
* @brief Find a property by name, scoped to one node.
*
* Like @c fdt_find_prop(), but scans only @p node's own direct properties
* (as returned by @c fdt_find_node_by_compatible()) — stops at the first
* child node or the end of @p node's property list, never descends into
* children, never continues into a sibling. This is the difference that
* matters for a property name like "reg", which is not unique across the
* tree the way "timebase-frequency" (the whole reason @c fdt_find_prop()
* was originally sufficient) happens to be.
*
* @param fdt Blob, already checked with @c fdt_valid().
* @param node Handle from @c fdt_find_node_by_compatible(); NULL is
* safe and returns NULL (propagates a failed node lookup
* without a separate caller-side check).
* @param name Property name, NUL-terminated.
* @param len_out Receives the property length in bytes; may be NULL.
* @return Pointer to the property value inside @p fdt, or NULL if not
* found (or if @p node is NULL). The value is big-endian as
* stored in the blob.
*/
const void* fdt_find_prop_in_node(const void* fdt, const void* node,
const char* name, uint32_t* len_out);
#endif /* STARKERNEL_FDT_H */