universalisos/kernel/dtb/fdt_reader.h

63 lines
2.3 KiB
C

/*
* UniversalisOS minimal Flattened Device Tree (FDT/DTB) reader (MP0).
*
* QEMU aarch64 virt and the STM32MP257/i.MX8MP all pass a DTB (device tree
* blob) describing the hardware: GIC base, CNTFRQ, UART, memory, etc. This
* minimal reader walks the DTB structure (not libfdt — we're freestanding) to
* extract the few fields the early boot needs: memory range, GIC distributor/
* CPU interface bases, UART base, and the timer frequency.
*
* The DTB binary format: a header (magic, totalsize, off_dt_struct, off_dt_strings,
* ...), then a structure block (tokens: FDT_BEGIN_NODE, FDT_PROP, FDT_END_NODE,
* FDT_END) and a strings block (NUL-terminated property name strings).
*/
#ifndef UOS_FDT_READER_H
#define UOS_FDT_READER_H
#include <stdint.h>
#define FDT_MAGIC 0xedfe0dd0 /* "0xd00dfeed" in little-endian word */
typedef struct {
uint32_t magic;
uint32_t totalsize;
uint32_t off_dt_struct;
uint32_t off_dt_strings;
uint32_t off_mem_rsvmap;
uint32_t version;
uint32_t last_comp_version;
uint32_t boot_cpuid_phys;
uint32_t size_dt_strings;
uint32_t size_dt_struct;
} fdt_header_t;
/* Tokens in the structure block. */
#define FDT_BEGIN_NODE 0x00000001
#define FDT_END_NODE 0x00000002
#define FDT_PROP 0x00000003
#define FDT_NOP 0x00000004
#define FDT_END 0x00000009
/* Result of an FDT lookup. */
typedef struct {
uint64_t addr; /* address of the property value in the DTB */
uint32_t len; /* length of the property value */
} fdt_prop_t;
/* Validate the DTB magic at `dtb`. Returns 0 if valid. */
int fdt_check(const void* dtb);
/* Find a property `name` under the node path "node_name" (e.g. "gic" or "uart").
* Returns 0 + fills `out` on success, -1 if not found. */
int fdt_get_prop(const void* dtb, const char* node_name, const char* prop_name, fdt_prop_t* out);
/* Convenience: read a #address-cells/<reg> pair as a 64-bit address. */
uint64_t fdt_read_addr(const void* dtb, const char* node_name);
/* Convenience: read the /memory/reg node → RAM base + size. */
void fdt_get_memory(const void* dtb, uint64_t* base, uint64_t* size);
/* Convenience: read the timer frequency from /timer or the firmware. */
uint32_t fdt_get_cntfrq(const void* dtb);
#endif /* UOS_FDT_READER_H */