diff --git a/src/drivers/dt/dt.c b/src/drivers/dt/dt.c index dcd1540b..fdb223e1 100644 --- a/src/drivers/dt/dt.c +++ b/src/drivers/dt/dt.c @@ -59,11 +59,11 @@ int dt_check(void *mem, size_t size, size_t *offp) return 0; } -int dt_parse(dt_node_t *node, int depth, size_t *offp, int (*cb_node)(void*, dt_node_t*), void *cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, size_t), void *cbp_arg) +int dt_parse(dt_node_t *node, int depth, size_t *offp, int (*cb_node)(void*, dt_node_t*, int), void *cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, size_t), void *cbp_arg) { if(cb_node) { - int r = cb_node(cbn_arg, node); + int r = cb_node(cbn_arg, node, depth); if(r != 0) return r; } if(depth >= 0 || cb_prop) @@ -198,7 +198,7 @@ typedef struct size_t size; } dt_arg_t; -static int dt_cbn(void *a, dt_node_t *node) +static int dt_cbn(void *a, dt_node_t *node, int depth) { if(a != node) { @@ -430,7 +430,7 @@ int dt_print(dt_node_t *node, int argc, const char **argv) // ========== Legacy/Compat ========== int dt_check_32(void *mem, uint32_t size, uint32_t *offp) __asm__("_dt_check$32"); -int dt_parse_32(dt_node_t *node, int depth, uint32_t *offp, int (*cb_node)(void*, dt_node_t*), void *cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void *cbp_arg) __asm__("_dt_parse$32"); +int dt_parse_32(dt_node_t *node, int depth, uint32_t *offp, int (*cb_node)(void*, dt_node_t*, int), void *cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void *cbp_arg) __asm__("_dt_parse$32"); void* dt_prop_32(dt_node_t *node, const char *key, uint32_t *lenp) __asm__("_dt_prop$32"); int dt_check_32(void *mem, uint32_t size, uint32_t *offp) @@ -453,7 +453,7 @@ static int dt_parse_32_cbp(void *a, dt_node_t *node, int depth, const char *key, return args->cb(args->arg, node, depth, key, val, (uint32_t)len); } -int dt_parse_32(dt_node_t *node, int depth, uint32_t *offp, int (*cb_node)(void*, dt_node_t*), void *cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void *cbp_arg) +int dt_parse_32(dt_node_t *node, int depth, uint32_t *offp, int (*cb_node)(void*, dt_node_t*, int), void *cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void *cbp_arg) { dt_parse_32_cbp_t cbp_arg_32 = { diff --git a/src/drivers/dt/dt.h b/src/drivers/dt/dt.h index 95585f53..0f9b09fd 100644 --- a/src/drivers/dt/dt.h +++ b/src/drivers/dt/dt.h @@ -1,7 +1,7 @@ /* * pongoOS - https://checkra.in * - * Copyright (C) 2019-2023 checkra1n team + * Copyright (C) 2019-2024 checkra1n team * * This file is part of pongoOS. * @@ -49,7 +49,7 @@ typedef struct } dt_prop_t; extern int dt_check(void *mem, size_t size, size_t *offp) __asm__("_dt_check$64"); -extern int dt_parse(dt_node_t *node, int depth, size_t *offp, int (*cb_node)(void*, dt_node_t*), void *cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, size_t), void *cbp_arg) __asm__("_dt_parse$64"); +extern int dt_parse(dt_node_t *node, int depth, size_t *offp, int (*cb_node)(void*, dt_node_t*, int), void *cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, size_t), void *cbp_arg) __asm__("_dt_parse$64"); extern dt_node_t* dt_find(dt_node_t *node, const char *name); extern void* dt_prop(dt_node_t *node, const char *key, size_t *lenp) __asm__("_dt_prop$64"); extern int dt_print(dt_node_t *node, int argc, const char **argv); @@ -65,6 +65,7 @@ struct memmap }; extern dt_node_t* dt_node(dt_node_t *node, const char *name); +extern dt_node_t* dt_node_parent(dt_node_t *node); extern dt_node_t* dt_get(const char *name); extern void* dt_node_prop(dt_node_t *node, const char *prop, size_t *size); extern void* dt_get_prop(const char *device, const char *prop, size_t *size) __asm__("_dt_get_prop$64"); diff --git a/src/drivers/dt/dt_get.c b/src/drivers/dt/dt_get.c index ba118dcc..2c76cf3d 100644 --- a/src/drivers/dt/dt_get.c +++ b/src/drivers/dt/dt_get.c @@ -1,7 +1,7 @@ /* * pongoOS - https://checkra.in * - * Copyright (C) 2019-2023 checkra1n team + * Copyright (C) 2019-2024 checkra1n team * * This file is part of pongoOS. * @@ -41,6 +41,46 @@ dt_node_t* dt_node(dt_node_t *node, const char *name) return dev; } +typedef struct +{ + dt_node_t *path[8]; + dt_node_t *target; + dt_node_t *parent; +} dt_node_parent_cb_t; + +static int dt_node_parent_cb(void *a, dt_node_t *node, int depth) +{ + dt_node_parent_cb_t *arg = a; + if(node == arg->target) + { + if(depth < 1) + { + panic("DeviceTree parent depth underflow: %d", depth); + } + arg->parent = arg->path[depth - 1]; + return 1; + } + if(depth < 0 || depth >= 8) + { + panic("DeviceTree parent depth out of bunds: %d", depth); + } + arg->path[depth] = node; + return 0; +} + +dt_node_t* dt_node_parent(dt_node_t *node) +{ + // Parsing the tree again just to find the parent node is really ugly and inefficient, but for now we're stuck with this. + // Ideally we'd parse the DeviceTree entirely into heap memory, so we can: + // a) traverse it faster and in either direction + // b) overwrite/relocate the original DeviceTree in memory (e.g. for loading a bigger kernel) + // The problem is that we currently allow clients to directly modify DeviceTree velues and we will need that + // in one form or another regardless, so we'd have to think about how to design such a writeback. + dt_node_parent_cb_t arg = { .target = node }; + dt_parse(gDeviceTree, 0, NULL, &dt_node_parent_cb, &arg, NULL, NULL); + return arg.parent; +} + dt_node_t* dt_get(const char *name) { return dt_node(gDeviceTree, name); diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index f3f83d31..fbd33099 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -36,7 +36,7 @@ struct hal_device* gRootDevice, * gDeviceTreeDevice; void hal_probe_hal_services(struct hal_device* device) ; -static int hal_load_dtree_child_node(void* arg, dt_node_t* node) { +static int hal_load_dtree_child_node(void* arg, dt_node_t* node, int depth) { struct hal_device* parentDevice = arg; if (parentDevice->node == node) return 0;