Skip to content
13 changes: 13 additions & 0 deletions include/dt/dt.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,19 @@ error_t dt_get_prop_buffer(const fdt_t* fdt, dt_prop_t prop, buffer_t* bufOUT);
[[gnu::nonnull(3)]]
error_t dt_get_rsv_mem_entry(const fdt_t* fdt, u32 index, fdt_rsv_entry* entryOUT);

/**
* @brief Get #address-cells and #size-cells properties from a node.
* @param fdt Pointer to the fdt object.
* @param node The node to read cell counts from.
* @param[out] address_cellsOUT Number of address cells (default 2).
* @param[out] size_cellsOUT Number of size cells (default 1).
* @retval ERR_NONE on success
* @retval ERR_BAD_ARG on nullptr args
* @retval ERR_NOT_VALID if the FDT is invalid or cell counts exceed 2
*/
[[gnu::nonnull(3, 4)]]
error_t dt_get_reg_cell_counts(const fdt_t* fdt, dt_node_t node, u32* address_cellsOUT, u32* size_cellsOUT);

/// @}

#endif // !DT_DT
4 changes: 2 additions & 2 deletions include/hal/memory_regions.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* Fields of this struct should not be modified directly.
* */
typedef struct {
alignas(16) u8 data[16];
alignas(16) u8 data[32];
} hal_reserved_memory_iterator_t;

/**
Expand All @@ -26,7 +26,7 @@ error_t hal_get_next_reserved_region(hal_reserved_memory_iterator_t* iter, memor
* Fields of this struct should not be modified directly.
* */
typedef struct {
alignas(16) u8 data[16];
alignas(16) u8 data[32];
} hal_memory_iterator_t;

/**
Expand Down
38 changes: 38 additions & 0 deletions src/lib/dt/dt_access.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,41 @@ error_t dt_get_rsv_mem_entry(const fdt_t* fdt, u32 index, fdt_rsv_entry* entryOU

return ERR_NOT_VALID;
}

error_t dt_get_reg_cell_counts(const fdt_t* fdt, dt_node_t node, u32* address_cellsOUT, u32* size_cellsOUT) {
*address_cellsOUT = 2;
*size_cellsOUT = 1;

dt_prop_t address_cells_prop;
error_t err = dt_get_prop_by_name(fdt, node, "#address-cells", &address_cells_prop);
if (err == ERR_NONE) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer maintaining a logic flow where errors are handled first, and normal execution continues afterward, like other dt_ functions

buffer_t buf;
err = dt_get_prop_buffer(fdt, address_cells_prop, &buf);
if (err)
return err;

if (!buffer_read_u32_be(buf, 0, address_cellsOUT) || *address_cellsOUT == 0)
return ERR_NOT_VALID;
} else if (err != ERR_NOT_FOUND) {
return err;
}

dt_prop_t size_cells_prop;
err = dt_get_prop_by_name(fdt, node, "#size-cells", &size_cells_prop);
if (err == ERR_NONE) {
buffer_t buf;
err = dt_get_prop_buffer(fdt, size_cells_prop, &buf);
if (err)
return err;

if (!buffer_read_u32_be(buf, 0, size_cellsOUT) || *size_cellsOUT == 0)
return ERR_NOT_VALID;
} else if (err != ERR_NOT_FOUND) {
return err;
}

if (*address_cellsOUT > 2 || *size_cellsOUT > 2)
return ERR_NOT_VALID;

return ERR_NONE;
}
Loading
Loading