From 3b1ce1e4b68699616cc8395fbae6ee81140f1882 Mon Sep 17 00:00:00 2001 From: zms123456 <85141075+zmshahaha@users.noreply.github.com> Date: Wed, 19 Jun 2024 19:48:35 +0800 Subject: [components][drivers]legacy fdt (#9062) * legacy fdt * update fdt --- components/drivers/Kconfig | 1 - components/drivers/fdt/Kconfig | 0 components/drivers/fdt/README.md | 41 - components/drivers/fdt/SConscript | 16 - components/drivers/fdt/docs/README.md | 13 - components/drivers/fdt/docs/api.md | 434 ------ components/drivers/fdt/docs/examples.md | 81 - components/drivers/fdt/docs/version.md | 7 - components/drivers/fdt/examples/SConscript | 10 - components/drivers/fdt/examples/fdt_test.c | 143 -- components/drivers/fdt/inc/dtb_node.h | 385 ----- components/drivers/fdt/libfdt/SConscript | 10 - components/drivers/fdt/libfdt/fdt.c | 249 --- components/drivers/fdt/libfdt/fdt.h | 125 -- components/drivers/fdt/libfdt/fdt_addresses.c | 99 -- components/drivers/fdt/libfdt/fdt_empty_tree.c | 84 - components/drivers/fdt/libfdt/fdt_ro.c | 701 --------- components/drivers/fdt/libfdt/fdt_rw.c | 491 ------ components/drivers/fdt/libfdt/fdt_strerror.c | 100 -- components/drivers/fdt/libfdt/fdt_sw.c | 286 ---- components/drivers/fdt/libfdt/fdt_wip.c | 137 -- components/drivers/fdt/libfdt/libfdt.h | 1883 ----------------------- components/drivers/fdt/libfdt/libfdt_env.h | 113 -- components/drivers/fdt/libfdt/libfdt_internal.h | 95 -- components/drivers/fdt/src/SConscript | 17 - components/drivers/fdt/src/dtb_access.c | 648 -------- components/drivers/fdt/src/dtb_addr.c | 57 - components/drivers/fdt/src/dtb_base.c | 574 ------- components/drivers/fdt/src/dtb_get.c | 823 ---------- components/drivers/fdt/src/dtb_head.c | 41 - components/drivers/fdt/src/dtb_load.c | 107 -- components/drivers/fdt/src/dtb_set.c | 166 -- components/legacy/Kconfig | 202 +-- components/legacy/fdt/Kconfig | 15 + components/legacy/fdt/README.md | 41 + components/legacy/fdt/SConscript | 16 + components/legacy/fdt/docs/README.md | 13 + components/legacy/fdt/docs/api.md | 434 ++++++ components/legacy/fdt/docs/examples.md | 81 + components/legacy/fdt/docs/version.md | 7 + components/legacy/fdt/examples/SConscript | 10 + components/legacy/fdt/examples/fdt_test.c | 143 ++ components/legacy/fdt/inc/dtb_fwnode.h | 125 ++ components/legacy/fdt/inc/dtb_node.h | 400 +++++ components/legacy/fdt/libfdt/SConscript | 10 + components/legacy/fdt/libfdt/fdt.c | 249 +++ components/legacy/fdt/libfdt/fdt.h | 125 ++ components/legacy/fdt/libfdt/fdt_addresses.c | 99 ++ components/legacy/fdt/libfdt/fdt_empty_tree.c | 84 + components/legacy/fdt/libfdt/fdt_ro.c | 701 +++++++++ components/legacy/fdt/libfdt/fdt_rw.c | 491 ++++++ components/legacy/fdt/libfdt/fdt_strerror.c | 100 ++ components/legacy/fdt/libfdt/fdt_sw.c | 286 ++++ components/legacy/fdt/libfdt/fdt_wip.c | 137 ++ components/legacy/fdt/libfdt/libfdt.h | 1883 +++++++++++++++++++++++ components/legacy/fdt/libfdt/libfdt_env.h | 113 ++ components/legacy/fdt/libfdt/libfdt_internal.h | 95 ++ components/legacy/fdt/src/SConscript | 17 + components/legacy/fdt/src/dtb_access.c | 648 ++++++++ components/legacy/fdt/src/dtb_addr.c | 57 + components/legacy/fdt/src/dtb_base.c | 574 +++++++ components/legacy/fdt/src/dtb_get.c | 829 ++++++++++ components/legacy/fdt/src/dtb_head.c | 41 + components/legacy/fdt/src/dtb_load.c | 107 ++ components/legacy/fdt/src/dtb_set.c | 166 ++ components/legacy/usb/Kconfig | 200 +++ 66 files changed, 8299 insertions(+), 8137 deletions(-) delete mode 100644 components/drivers/fdt/Kconfig delete mode 100644 components/drivers/fdt/README.md delete mode 100644 components/drivers/fdt/SConscript delete mode 100644 components/drivers/fdt/docs/README.md delete mode 100644 components/drivers/fdt/docs/api.md delete mode 100644 components/drivers/fdt/docs/examples.md delete mode 100644 components/drivers/fdt/docs/version.md delete mode 100644 components/drivers/fdt/examples/SConscript delete mode 100644 components/drivers/fdt/examples/fdt_test.c delete mode 100644 components/drivers/fdt/inc/dtb_node.h delete mode 100644 components/drivers/fdt/libfdt/SConscript delete mode 100644 components/drivers/fdt/libfdt/fdt.c delete mode 100644 components/drivers/fdt/libfdt/fdt.h delete mode 100644 components/drivers/fdt/libfdt/fdt_addresses.c delete mode 100644 components/drivers/fdt/libfdt/fdt_empty_tree.c delete mode 100644 components/drivers/fdt/libfdt/fdt_ro.c delete mode 100644 components/drivers/fdt/libfdt/fdt_rw.c delete mode 100644 components/drivers/fdt/libfdt/fdt_strerror.c delete mode 100644 components/drivers/fdt/libfdt/fdt_sw.c delete mode 100644 components/drivers/fdt/libfdt/fdt_wip.c delete mode 100644 components/drivers/fdt/libfdt/libfdt.h delete mode 100644 components/drivers/fdt/libfdt/libfdt_env.h delete mode 100644 components/drivers/fdt/libfdt/libfdt_internal.h delete mode 100644 components/drivers/fdt/src/SConscript delete mode 100644 components/drivers/fdt/src/dtb_access.c delete mode 100644 components/drivers/fdt/src/dtb_addr.c delete mode 100644 components/drivers/fdt/src/dtb_base.c delete mode 100644 components/drivers/fdt/src/dtb_get.c delete mode 100644 components/drivers/fdt/src/dtb_head.c delete mode 100644 components/drivers/fdt/src/dtb_load.c delete mode 100644 components/drivers/fdt/src/dtb_set.c create mode 100644 components/legacy/fdt/Kconfig create mode 100644 components/legacy/fdt/README.md create mode 100644 components/legacy/fdt/SConscript create mode 100644 components/legacy/fdt/docs/README.md create mode 100644 components/legacy/fdt/docs/api.md create mode 100644 components/legacy/fdt/docs/examples.md create mode 100644 components/legacy/fdt/docs/version.md create mode 100644 components/legacy/fdt/examples/SConscript create mode 100644 components/legacy/fdt/examples/fdt_test.c create mode 100644 components/legacy/fdt/inc/dtb_fwnode.h create mode 100644 components/legacy/fdt/inc/dtb_node.h create mode 100644 components/legacy/fdt/libfdt/SConscript create mode 100644 components/legacy/fdt/libfdt/fdt.c create mode 100644 components/legacy/fdt/libfdt/fdt.h create mode 100644 components/legacy/fdt/libfdt/fdt_addresses.c create mode 100644 components/legacy/fdt/libfdt/fdt_empty_tree.c create mode 100644 components/legacy/fdt/libfdt/fdt_ro.c create mode 100644 components/legacy/fdt/libfdt/fdt_rw.c create mode 100644 components/legacy/fdt/libfdt/fdt_strerror.c create mode 100644 components/legacy/fdt/libfdt/fdt_sw.c create mode 100644 components/legacy/fdt/libfdt/fdt_wip.c create mode 100644 components/legacy/fdt/libfdt/libfdt.h create mode 100644 components/legacy/fdt/libfdt/libfdt_env.h create mode 100644 components/legacy/fdt/libfdt/libfdt_internal.h create mode 100644 components/legacy/fdt/src/SConscript create mode 100644 components/legacy/fdt/src/dtb_access.c create mode 100644 components/legacy/fdt/src/dtb_addr.c create mode 100644 components/legacy/fdt/src/dtb_base.c create mode 100644 components/legacy/fdt/src/dtb_get.c create mode 100644 components/legacy/fdt/src/dtb_head.c create mode 100644 components/legacy/fdt/src/dtb_load.c create mode 100644 components/legacy/fdt/src/dtb_set.c create mode 100644 components/legacy/usb/Kconfig (limited to 'components') diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index b7112d9ea6..24856d5cc8 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -30,6 +30,5 @@ rsource "ktime/Kconfig" rsource "clk/Kconfig" rsource "hwtimer/Kconfig" rsource "usb/Kconfig" -rsource "fdt/Kconfig" endmenu diff --git a/components/drivers/fdt/Kconfig b/components/drivers/fdt/Kconfig deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/components/drivers/fdt/README.md b/components/drivers/fdt/README.md deleted file mode 100644 index d8a049c8fc..0000000000 --- a/components/drivers/fdt/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# fdt - -## 1、介绍 -fdt基于libfdt进行封装,可实现在内存或文件系统中加载dtb设备树,对内存中的设备树修改、解析,并转换为设备节点树,通过该节点树开发者可通过设备树信息开发驱动。 - -### 1.1 目录结构 -| 名称 | 说明 | -| ---- | ---- | -| docs | 文档目录 | -| examples | 例子目录,并有相应的一些说明 | -| inc | 头文件目录 | -| src | 源代码目录 | - -### 1.2 许可证 -fdt package 遵循 GPL-3.0 许可,详见 LICENSE 文件。 - -### 1.3 依赖 -- RT-Thread 3.0+ - -## 2、如何打开 fdt -使用 fdt package 需要在 RT-Thread 的包管理器中选择它,具体路径如下: - -``` -RT-Thread online packages - tools packages ---> - [*] Device Tree package in RT-Thread -``` - -## 3、使用 fdt -在打开 fdt package 后,当进行 bsp 编译时,它会被加入到 bsp 工程中进行编译。 - -* 完整的 API 手册可以访问这个[链接](docs/api.md) -* 更多文档位于 [`/docs`](/docs) 下,使用前 **务必查看** - -## 4、注意事项 -如果发生`libfdt`库冲突,在package管理菜单中取消选择`Enable libfdt` - -## 5、联系方式 - -* 维护:GuEe-GUI -* 主页:https://github.com/GuEe-GUI/fdt \ No newline at end of file diff --git a/components/drivers/fdt/SConscript b/components/drivers/fdt/SConscript deleted file mode 100644 index d916b2dfbc..0000000000 --- a/components/drivers/fdt/SConscript +++ /dev/null @@ -1,16 +0,0 @@ -# RT-Thread building script for bridge - -import os -from building import * - -cwd = GetCurrentDir() -objs = [] -list = os.listdir(cwd) - -if GetDepend('RT_USING_FDT'): - for d in list: - path = os.path.join(cwd, d) - if os.path.isfile(os.path.join(path, 'SConscript')): - objs = objs + SConscript(os.path.join(d, 'SConscript')) - -Return('objs') diff --git a/components/drivers/fdt/docs/README.md b/components/drivers/fdt/docs/README.md deleted file mode 100644 index f57e0a8e75..0000000000 --- a/components/drivers/fdt/docs/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# 文档 - -## 软件包地址 - -- https://gitee.com/GuEe_GUI/fdt - -## 文档列表 - -|文件名 |描述| -|:----- |:----| -|[examples.md](examples.md) |示例程序| -|[version.md](version.md) |版本信息| -|[api.md](api.md) |API 说明| diff --git a/components/drivers/fdt/docs/api.md b/components/drivers/fdt/docs/api.md deleted file mode 100644 index 13471de06f..0000000000 --- a/components/drivers/fdt/docs/api.md +++ /dev/null @@ -1,434 +0,0 @@ -# fdt load API - -## 从文件系统上读取设备树 -```c -void *fdt_load_from_fs(char *dtb_filename) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_filename | 设备树文件名 | -| **返回** | **描述** | -|void* | 设备树在内存上的地址 | - -## 从内存上读取设备树 -```c -void *fdt_load_from_memory(void *dtb_ptr, rt_bool_t is_clone) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_ptr | 设备树在内存上的内存地址 | -|is_clone | 是否克隆到新的内存区域 | -| **返回** | **描述** | -|void* | 设备树在内存上的地址 | - -# fdt set API - -## 设置Linux启动参数 -```c -rt_size_t fdt_set_linux_cmdline(void *fdt, char *cmdline) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|fdt | 设备树指针 | -|cmdline | 启动参数 | -| **返回** | **描述** | -|rt_size_t | 修改设备树后设备树的大小 | - -## 设置Linux init ramdisk -```c -rt_size_t fdt_set_linux_initrd(void *fdt, rt_uint64_t initrd_addr, rt_size_t initrd_size) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|fdt | 设备树指针 | -|initrd_addr | init ramdisk 内存地址 | -|initrd_size | init 大小 | -| **返回** | **描述** | -|rt_size_t | 修改设备树后设备树的大小 | - -## 设置节点属性值 -```c -rt_size_t fdt_set_dtb_property(void *fdt, char *pathname, char *property_name, rt_uint32_t *cells, rt_size_t cells_size); -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|fdt | 设备树指针 | -|pathname | 节点路径 | -|property_name | 属性名称 | -|cells | 属性值地址 | -|cells_size | 属性值长度 | -| **返回** | **描述** | -|rt_size_t | 修改设备树后设备树的大小 | - -## 添加保留内存 -```c -rt_size_t fdt_add_dtb_memreserve(void *fdt, rt_uint64_t address, rt_uint64_t size) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|fdt | 设备树指针 | -|address | 保留内存起始地址 | -|size | 保留内存大小 | -| **返回** | **描述** | -|rt_size_t | 修改设备树后设备树的大小 | - -## 删除保留内存 -```c -rt_size_t fdt_del_dtb_memreserve(void *fdt, rt_uint64_t address) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|fdt | 设备树指针 | -|address | 保留内存起始地址 | -| **返回** | **描述** | -|rt_size_t | 修改设备树后设备树的大小 | - -# fdt get API - -## 获取设备树软件包执行状态 -```c -rt_err_t fdt_get_exec_status() -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|无 | 无参数 | -| **返回** | **描述** | -|FDT_RET_NO_MEMORY | 内存不足 | -|FDT_RET_NO_LOADED | 设备树还未加载进内存 | -|FDT_RET_GET_OK | 执行成功 | -|FDT_RET_GET_EMPTY | 读取数据为空 | - -## 将原始设备树转换为设备节点树 -```c -struct dtb_node *fdt_get_dtb_list(void *fdt) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|fdt | 设备树在内存上的地址 | -| **返回** | **描述** | -|struct dtb_node * | 设备节点树头指针 | -## 释放设备节点树内存 -```c -void fdt_free_dtb_list(struct dtb_node *dtb_node_head) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node_head | 设备节点树头节点 | -| **返回** | **描述** | -|无返回值 | 无描述 | - -示例:加载设备树 - -```c -#include -#include - -int main() -{ - void *fdt = fdt_load_from_fs("sample.dtb"); - if (fdt != RT_NULL) - { - struct dtb_node *dtb_node_list = fdt_get_dtb_list(fdt); - - if (dtb_node_list != RT_NULL) - { - /* load dtb node list OK */ - - /* free dtb_node_list here */ - fdt_free_dtb_list(dtb_node_list); - } - - rt_free(fdt); - } - - return 0; -} -``` - -## 打印设备树信息 -```c -void fdt_get_dts_dump(struct dtb_node *dtb_node_head) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node_head | 设备节点树头节点 | -| **返回** | **描述** | -|无返回值 | 无描述 | - -## 遍历设备节点树并使用程序定义的回调函数 -```c -void fdt_get_enum_dtb_node(struct dtb_node *dtb_node_head, void (*callback(struct dtb_node *dtb_node))) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node_head | 设备节点树头节点 | -|callback | 程序定义的回调函数 | -| **返回** | **描述** | -|无返回值 | 无描述 | - -示例:遍历设备树节点,并打印每个节点名称 - -```c -#include -#include - -void callback(struct dtb_node *node) -{ - rt_kprintf("this node's name is %s\n", node->name); -} - -int main() -{ - /* loaded dtb_node */ - extern struct dtb_node *dtb_node_list; - - if (dtb_node_list != RT_NULL) - { - fdt_get_enum_dtb_node(dtb_node_list, callback); - } - - return 0; -} -``` - -## 通过节点名称查找节点 -```c -struct dtb_node *fdt_get_dtb_node_by_name_DFS(struct dtb_node *dtb_node, const char *nodename) -``` -```c -struct dtb_node *fdt_get_dtb_node_by_name_BFS(struct dtb_node *dtb_node, const char *nodename) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node | 设备节点树节点 | -|nodename | 查找节点的名称 | -| **返回** | **描述** | -|struct dtb_node * | 返回查找的节点 | -|RT_NULL | 未找到为RT_NULL | - -## 通过节点路径查找节点 -```c -struct dtb_node *fdt_get_dtb_node_by_path(struct dtb_node *dtb_node, const char *pathname) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node | 设备节点树节点 | -|pathname | 查找节点的路径 | -| **返回** | **描述** | -|struct dtb_node * | 返回查找的节点 | -|RT_NULL | 未找到为RT_NULL | - -## 通过节点phandle值查找节点 -```c -struct dtb_node *fdt_get_dtb_node_by_phandle_DFS(struct dtb_node *dtb_node, phandle handle) -``` -```c -struct dtb_node *fdt_get_dtb_node_by_phandle_BFS(struct dtb_node *dtb_node, phandle handle) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node | 设备节点树节点 | -|handle | 查找节点的phandle值 | -| **返回** | **描述** | -|struct dtb_node * | 返回查找的节点 | -|RT_NULL | 未找到为RT_NULL | - -DFS和BFS是用于区分不同深度节点的搜索方法,时间复杂度和空间复杂度都较高,建议使用路径查找。 - -## 读取节点属性值的单位 -```c -void fdt_get_dtb_node_cells(struct dtb_node *dtb_node, int *addr_cells, int *size_cells) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node | 设备节点树节点 | -|addr_cells | 返回的地址块的单位(u32)大小 | -|size_cells | 返回的尺寸块的单位(u32)大小 | -| **返回** | **描述** | -|无返回值 | 无描述 | - - -## 读取节点属性值 -```c -void *fdt_get_dtb_node_property(struct dtb_node *dtb_node, const char *property_name, rt_size_t *property_size) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node | 设备节点树节点 | -|property_name | 属性名称 | -|property_size | 属性大小 | -| **返回** | **描述** | -|void * | 无描述 | -|RT_NULL | 该设备树没有该属性 | - -读取的值为在设备树中存储的值,CPU小端模式下可能需要使用其他API进行转换才是正确的值 - -## 读取预留内存信息 -```c -struct dtb_memreserve *fdt_get_dtb_memreserve(struct dtb_node *dtb_node, int *memreserve_size) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node | 设备节点树节点 | -|memreserve_size | 返回的内存信息数组长度 | -| **返回** | **描述** | -|struct dtb_memreserve *| 内存预留信息数组的内存地址 | -|RT_NULL | 该设备树没有预留内存信息 | - -## 读取节点的状态 -```c -rt_bool_t fdt_get_dtb_node_status(struct dtb_node *dtb_node) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node | 设备节点树节点 | -| **返回** | **描述** | -|RT_FALSE | 状态为禁用 | -|RT_TRUE | 状态为使用 | - -## 用于参数为字符串列表的函数 -```c -fdt_string_list(string, ...) -``` -| 参数 | 描述 | -|:------------------|:------------------------------------| -|string | 字符串集合 | - -## 读取节点compatible标志匹配 -```c -rt_bool_t fdt_get_dtb_node_compatible_match(struct dtb_node *dtb_node, char **compatibles) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|dtb_node | 设备节点树节点 | -|compatibles | 所有要匹配的字符串列表 | -| **返回** | **描述** | -|RT_FALSE | 匹配失败 | -|RT_TRUE | 匹配成功 | - -## 读取属性值中的字符串 -```c -char *fdt_get_dtb_string_list_value(void *value, int size, int index) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|value | 节点属性的内存地址 | -|size | 节点属性的尺寸 | -|index | 要读取字符串的索引 | -| **返回** | **描述** | -|char * | 字符串的内存地址 | -|RT_NULL | 该索引没有字符串 | - -## 读取值为字符串属性下一个字符串 -```c -char *fdt_get_dtb_string_list_value_next(void *value, void *end) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|value | 节点属性的内存地址 | -|end | 节点属性的结束地址 | -| **返回** | **描述** | -|char * | 字符串的内存地址 | -|RT_NULL | 没有下一个字符串 | - -## 读取值为u32属性的值 -```c -rt_uint32_t fdt_get_dtb_cell_value(void *value) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|value | 节点属性的内存地址 | -| **返回** | **描述** | -|rt_uint32_t | 该值小端的值 | - -## 读取值为u8属性的值 -```c -rt_uint8_t fdt_get_dtb_byte_value(void *value) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|value | 节点属性的内存地址 | -| **返回** | **描述** | -|rt_uint8_t | 该值小端的值 | - -# fdt foreach API - -## 遍历属性中字符串宏 -```c -for_each_property_string(node_ptr, property_name, str, size) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|node_ptr | 设备节点树节点 | -|property_name | 节点属性名称 | -|str | 每次遍历到的字符串 | -|size | 用于保存节点属性的尺寸 | - -## 遍历属性中u32宏 -```c -for_each_property_cell(node_ptr, property_name, value, list, size) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|node_ptr | 设备节点树节点 | -|property_name | 节点属性名称 | -|value | 每次遍历到的值 | -|list | 用于保存节点属性的值内存地址 | -|size | 用于保存节点属性的尺寸 | - -## 遍历属性中u8宏 -```c -for_each_property_byte(node_ptr, property_name, value, list, size) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|node_ptr | 设备节点树节点 | -|property_name | 节点属性名称 | -|value | 每次遍历到的值 | -|list | 用于保存节点属性的值内存地址 | -|size | 用于保存节点属性的尺寸 | - -## 遍历子节点宏 -```c -for_each_node_child(node_ptr) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|node_ptr | 设备节点树节点 | - -## 遍历兄弟节点宏 -```c -for_each_node_sibling(node_ptr) -``` - -| 参数 | 描述 | -|:------------------|:------------------------------------| -|node_ptr | 设备节点树节点 | diff --git a/components/drivers/fdt/docs/examples.md b/components/drivers/fdt/docs/examples.md deleted file mode 100644 index aa3e655987..0000000000 --- a/components/drivers/fdt/docs/examples.md +++ /dev/null @@ -1,81 +0,0 @@ -# fdt示例 # - -在`examples`文件夹中存放`bcm2711-rpi-4-b.dtb`和`vexpress-v2p-ca9.dtb`可供测试,如果系统可以从bootloader或其他方式获取到bsp本身的dtb,也可以通过修改示例程序进行测试 - -## fdt_dump -```bash -fdt_dump vexpress-v2p-ca9.dtb -``` - -#### 示例结果 #### -```bash -/dts-v1/; - -/ { - model = "V2P-CA9"; - arm,hbi = <0x191>; - arm,vexpress,site = <0xf>; - compatible = "arm,vexpress,v2p-ca9", "arm,vexpress"; - interrupt-parent = <0x1>; - #address-cells = <0x1>; - #size-cells = <0x1>; - - chosen { - }; - - aliases { - serial0 = "/smb@4000000/motherboard/iofpga@7,00000000/uart@9000"; - serial1 = "/smb@4000000/motherboard/iofpga@7,00000000/uart@a000"; - serial2 = "/smb@4000000/motherboard/iofpga@7,00000000/uart@b000"; - serial3 = "/smb@4000000/motherboard/iofpga@7,00000000/uart@c000"; - i2c0 = "/smb@4000000/motherboard/iofpga@7,00000000/i2c@16000"; - i2c1 = "/smb@4000000/motherboard/iofpga@7,00000000/i2c@2000"; - }; - -...... 省略 - - hsb@e0000000 { - compatible = "simple-bus"; - #address-cells = <0x1>; - #size-cells = <0x1>; - ranges = <0x0 0xe0000000 0x20000000>; - #interrupt-cells = <0x1>; - interrupt-map-mask = <0x0 0x3>; - interrupt-map = <0x0 0x0 0x1 0x0 0x24 0x4 0x0 0x1 0x1 0x0 0x25 0x4 0x0 0x2 0x1 0x0 0x26 0x4 0x0 0x3 0x1 0x0 0x27 0x4>; - }; -}; -``` - -## fdt_test -```bash -fdt_test -``` - -#### 示例结果 #### -```bash -name = uart@9000 -reg = <0x9000,0x1000>; -compatible = "arm,pl011","arm,primecell"; - -name = cpus -path = /cpus/cpu@0/ -path = /cpus/cpu@1/ -path = /cpus/cpu@2/ -path = /cpus/cpu@3/ - -name = user1, lable = v2m:green:user1 -name = user2, lable = v2m:green:user2 -name = user3, lable = v2m:green:user3 -name = user4, lable = v2m:green:user4 -name = user5, lable = v2m:green:user5 -name = user6, lable = v2m:green:user6 -name = user7, lable = v2m:green:user7 -name = user8, lable = v2m:green:user8 - -/memreserve/ 0x0000000000000000 0x0000000000001000; - -phandle = <0x9> -name = bt_pins -path = /soc/gpio@7e200000/bt_pins/ -brcm,pins = [2d 00] -``` \ No newline at end of file diff --git a/components/drivers/fdt/docs/version.md b/components/drivers/fdt/docs/version.md deleted file mode 100644 index 3c3499d91a..0000000000 --- a/components/drivers/fdt/docs/version.md +++ /dev/null @@ -1,7 +0,0 @@ -# 版本和修订 # - -| Date | Version | Author | Note | -| -------- | :-----: | :---- | :---- | -| 2021-9-1 | v0.0.1 | GuEe-GUI | 初始版本 | -| 2021-11-11 | v1.0.0 | GuEe-GUI | API确定版本 | -| | | | | \ No newline at end of file diff --git a/components/drivers/fdt/examples/SConscript b/components/drivers/fdt/examples/SConscript deleted file mode 100644 index 463c4814cc..0000000000 --- a/components/drivers/fdt/examples/SConscript +++ /dev/null @@ -1,10 +0,0 @@ - -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd] - -group = DefineGroup('FDT', src, depend = ['FDT_USING_DEBUG'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/drivers/fdt/examples/fdt_test.c b/components/drivers/fdt/examples/fdt_test.c deleted file mode 100644 index 4bf2879256..0000000000 --- a/components/drivers/fdt/examples/fdt_test.c +++ /dev/null @@ -1,143 +0,0 @@ -#include -#include "dtb_node.h" - -int dtb_test() -{ - void *fdt; - - if ((fdt = dtb_node_load_from_fs("vexpress-v2p-ca9.dtb")) != RT_NULL) - { - struct dtb_node *dtb_node_list = dtb_node_get_dtb_list(fdt); - if (dtb_node_list != RT_NULL) - { - struct dtb_node *serial0 = dtb_node_get_dtb_node_by_path(dtb_node_list, "/smb@4000000/motherboard/iofpga@7,00000000/uart@9000"); - struct dtb_node *cpu = dtb_node_get_dtb_node_by_path(dtb_node_list, "/cpus"); - struct dtb_node *user1 = dtb_node_get_dtb_node_by_path(dtb_node_list, "/smb@4000000/motherboard/leds/user1"); - - if (serial0 != RT_NULL) - { - int property_size; - rt_uint32_t u32_value; - rt_uint32_t *u32_ptr; - char *str_ptr; - - rt_kprintf("name = %s\n", serial0->name); - - rt_kputs("reg = <"); - for_each_property_cell(serial0, "reg", u32_value, u32_ptr, property_size) - { - rt_kprintf("0x%x,", u32_value); - } - rt_kputs("\b>;\n"); - - rt_kputs("compatible = "); - for_each_property_string(serial0, "compatible", str_ptr, property_size) - { - rt_kprintf("\"%s\",", str_ptr); - } - rt_kputs("\b;\n"); - } - - if (cpu != RT_NULL) - { - struct dtb_node *cpu_child = cpu; - - rt_kprintf("\nname = %s\n", cpu->name); - - for_each_node_child(cpu_child) - { - rt_kprintf("path = %s\n", cpu_child->path); - } - } - - if (user1 != RT_NULL) - { - struct dtb_node *user = user1; - - rt_kprintf("\nname = %s, lable = %s\n", user1->name, dtb_node_get_dtb_node_property(user1, "label", RT_NULL)); - - for_each_node_sibling(user) - { - rt_kprintf("name = %s, lable = %s\n", user->name, dtb_node_get_dtb_node_property(user, "label", RT_NULL)); - } - } - } - dtb_node_free_dtb_list(dtb_node_list); - } - - if ((fdt = dtb_node_load_from_fs("bcm2711-rpi-4-b.dtb")) != RT_NULL) - { - struct dtb_node *dtb_node_list = dtb_node_get_dtb_list(fdt); - if (dtb_node_list != RT_NULL) - { - struct dtb_node *bt_pins; - int memreserve_size; - struct dtb_memreserve *memreserve; - - bt_pins = dtb_node_get_dtb_node_by_name_DFS(dtb_node_list, "bt_pins"); - bt_pins = dtb_node_get_dtb_node_by_name_BFS(dtb_node_list, bt_pins->name); - bt_pins = dtb_node_get_dtb_node_by_phandle_DFS(dtb_node_list, bt_pins->handle); - bt_pins = dtb_node_get_dtb_node_by_phandle_BFS(dtb_node_list, bt_pins->handle); - - memreserve = dtb_node_get_dtb_memreserve(bt_pins, &memreserve_size); - if (memreserve_size > 0) - { - int i; - for (i = 0; i < memreserve_size; ++i) - { - rt_kputs("\n/memreserve/\t"); - if (IN_64BITS_MODE) - { - rt_kprintf("0x%016x 0x%016x;", memreserve[i].address, memreserve[i].size); - } - else - { - rt_kprintf("0x%08x%08x 0x%08x%08x;", memreserve[i].address, memreserve[i].size); - } - } - } - - if (bt_pins != RT_NULL) - { - int property_size; - rt_uint8_t u8_value; - rt_uint8_t *u8_ptr; - - rt_kprintf("\n\nphandle = <0x%x>\n", bt_pins->handle); - rt_kprintf("name = %s\n", bt_pins->name); - rt_kprintf("path = %s\n", bt_pins->path); - - rt_kputs("brcm,pins = ["); - for_each_property_byte(bt_pins, "brcm,pins", u8_value, u8_ptr, property_size) - { - rt_kprintf("%02x ", u8_value); - } - rt_kputs("\b]\n"); - } - } - dtb_node_free_dtb_list(dtb_node_list); - } - return 0; -} -MSH_CMD_EXPORT(dtb_test, dtb API test); - -int dtb_dump(int argc, char** argv) -{ - struct dtb_node *dtb_root_node = get_dtb_node_head(); - if(argc == 1) - { - if (dtb_root_node != RT_NULL) - { - dtb_node_get_dts_dump(dtb_root_node); - } - } - else - { - rt_kprintf("invailed parameter\n"); - } - - return 0; -} -MSH_CMD_EXPORT(dtb_dump, dtb dump from mem); - - diff --git a/components/drivers/fdt/inc/dtb_node.h b/components/drivers/fdt/inc/dtb_node.h deleted file mode 100644 index 7d780e9948..0000000000 --- a/components/drivers/fdt/inc/dtb_node.h +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef _DTB_NODE_H__ -#define _DTB_NODE_H__ - -#include "libfdt_env.h" -#include -#include - -//#define RT_DTB_DEBUG -#ifdef RT_DTB_DEBUG -#define debug(fmt, args...) rt_kprintf(fmt, ##args) -#else -#define debug(fmt, args...) -#endif - -#define ERR_PTR(err) ((void *)((long)(err))) -#define PTR_ERR(ptr) ((long)(ptr)) -#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) - -#define DEV_ROOT_NODE_ADDR_CELLS_DEFAULT 2 -#define DEV_ROOT_NODE_SIZE_CELLS_DEFAULT 1 -/* will be optimized to only u64 or u32 by gcc */ -#define IN_64BITS_MODE (sizeof(void *) == 8) - -#define FDT_ROOT_ADDR_CELLS_DEFAULT 1 -#define FDT_ROOT_SIZE_CELLS_DEFAULT 1 - -#define FDT_DTB_ALL_NODES_PATH_SIZE (32 * 1024) -#define FDT_DTB_PAD_SIZE 1024 - -#define FDT_RET_NO_MEMORY 2 -#define FDT_RET_NO_LOADED 1 -#define FDT_RET_GET_OK 0 -#define FDT_RET_GET_EMPTY (-1) - -typedef uint32_t phandle; - -struct dtb_memreserve -{ - uintptr_t address; - size_t size; -}; - -struct dtb_header -{ - char root, zero; /* "/" */ - struct dtb_memreserve *memreserve; - size_t memreserve_sz; -}; - -struct dtb_property -{ - const char *name; - int size; - void *value; - - struct dtb_property *next; -}; - -struct dtb_node -{ - union - { - const char *name; - const struct dtb_header *header; - }; - const char *path; - phandle handle; - int level; - - struct dtb_property *properties; - struct dtb_node *parent; - struct dtb_node *child; - struct dtb_node *sibling; -}; - -#define FDT_MAX_PHANDLE_ARGS 16 - -/** - * struct dtb_node_phandle_args - structure to hold phandle and arguments - * - * This is used when decoding a phandle in a device tree property. Typically - * these look like this: - * - * wibble { - * phandle = <5>; - * }; - * - * ... - * some-prop = <&wibble 1 2 3> - * - * Here &node is the phandle of the node 'wibble', i.e. 5. There are three - * arguments: 1, 2, 3. - * - * So when decoding the phandle in some-prop, np will point to wibble, - * args_count will be 3 and the three arguments will be in args. - * - * @np: Node that the phandle refers to - * @args_count: Number of arguments - * @args: Argument values - */ -struct fdt_phandle_args -{ - struct dtb_node *np; - int args_count; - uint32_t args[FDT_MAX_PHANDLE_ARGS]; -}; - -/* - * A single signal can be specified via a range of minimal and maximal values - * with a typical value, that lies somewhere inbetween. - */ -struct timing_entry -{ - uint32_t min; - uint32_t typ; - uint32_t max; -}; - -void *get_fdt_blob(void); -struct dtb_node *get_dtb_node_head(void); -rt_bool_t dtb_node_active(void); -int device_tree_setup(void *mem_addr); - -void *dtb_node_load_from_fs(char *dtb_filename); -void *dtb_node_load_from_memory(void *dtb_ptr, rt_bool_t is_clone); - -size_t dtb_node_set_linux_cmdline(void *fdt, char *cmdline); -size_t dtb_node_set_linux_initrd(void *fdt, uint64_t initrd_addr, size_t initrd_size); - -size_t dtb_node_set_dtb_property(void *fdt, char *pathname, char *property_name, uint32_t *cells, size_t cells_size); -size_t dtb_node_add_dtb_memreserve(void *fdt, uint64_t address, uint64_t size); -size_t dtb_node_del_dtb_memreserve(void *fdt, uint64_t address); - -int dtb_node_get_exec_status(); -struct dtb_node *dtb_node_get_dtb_list(void *fdt); -void dtb_node_free_dtb_list(struct dtb_node *dtb_node_head); -void dtb_node_get_dts_dump(struct dtb_node *dtb_node_head); -void dtb_node_get_enum_dtb_node(struct dtb_node *dtb_node_head, void(callback(struct dtb_node *dtb_node))); - -struct dtb_node *dtb_node_get_dtb_node_by_name_DFS(struct dtb_node *dtb_node, const char *nodename); -struct dtb_node *dtb_node_get_dtb_node_by_name_BFS(struct dtb_node *dtb_node, const char *nodename); -struct dtb_node *dtb_node_get_dtb_node_by_path(struct dtb_node *dtb_node, const char *pathname); -struct dtb_node *dtb_node_get_dtb_node_by_phandle_DFS(struct dtb_node *dtb_node, phandle handle); -struct dtb_node *dtb_node_get_dtb_node_by_phandle_BFS(struct dtb_node *dtb_node, phandle handle); -void dtb_node_get_dtb_node_cells(struct dtb_node *dtb_node, int *addr_cells, int *size_cells); -struct dtb_memreserve *dtb_node_get_dtb_memreserve(struct dtb_node *dtb_node, int *memreserve_size); -uint8_t dtb_node_get_dtb_byte_value(void *value); - -char *dtb_node_get_dtb_string_list_value(void *value, int size, int index); -char *dtb_node_get_dtb_string_list_value_next(void *value, void *end); -uint32_t dtb_node_get_dtb_cell_value(void *value); - -rt_bool_t dtb_node_get_dtb_node_status(const struct dtb_node *dtb_node); -rt_bool_t dtb_node_get_dtb_node_compatible_match(const struct dtb_node *dtb_node, const char *compatibles); - -/*dtb_node_access.c */ -int dtb_node_read_u32(const struct dtb_node *dn, const char *propname, uint32_t *outp); -uint32_t dtb_node_read_u32_default(const struct dtb_node *node, const char *propname, uint32_t def); -int dtb_node_read_u32_index(const struct dtb_node *node, const char *propname, int index, - uint32_t *outp); -uint32_t dtb_node_read_u32_index_default(const struct dtb_node *node, const char *propname, int index, - uint32_t def); -int dtb_node_read_u32_array(const struct dtb_node *dn, const char *propname, - uint32_t *out_values, size_t sz); -int dtb_node_read_u32_index(const struct dtb_node *dn, const char *propname, - int index, uint32_t *outp); -int dtb_node_read_s32_default(const struct dtb_node *node, const char *propname, int32_t def); -int dtb_node_read_u64(const struct dtb_node *dn, const char *propname, uint64_t *outp); -uint64_t dtb_node_read_u64_default(const struct dtb_node *node, const char *propname, uint64_t def); - -int dtb_node_n_addr_cells(const struct dtb_node *dn); -int dtb_node_n_size_cells(const struct dtb_node *dn); -int dtb_node_simple_addr_cells(const struct dtb_node *np); -int dtb_node_simple_size_cells(const struct dtb_node *np); - -struct dtb_node *dtb_node_find_all_nodes(const struct dtb_node *prev); -struct dtb_node *dtb_node_find_node_by_phandle(phandle handle); -struct dtb_node *dtb_node_find_compatible_node(struct dtb_node *from, const char *compatible); -void *dtb_node_get_dtb_node_property_value(const struct dtb_node *dtb_node, const char *property_name, int *property_size); -struct dtb_property *dtb_node_get_dtb_node_property(const struct dtb_node *dtb_node, const char *property_name, int *property_size); -const struct dtb_node *dtb_node_find_node_by_prop_value(struct dtb_node *from, const char *propname, const void *propval, int proplen); -struct dtb_node *dtb_node_find_node_opts_by_path(const char *path, - const char **opts); - -static inline struct dtb_node *dtb_node_find_node_by_path(const char *path) -{ - return dtb_node_find_node_opts_by_path(path, NULL); -} - -rt_bool_t dtb_node_device_is_available(const struct dtb_node *device); -struct dtb_node *dtb_node_get_parent(const struct dtb_node *node); -int dtb_node_property_match_string(const struct dtb_node *dn, const char *propname, - const char *string); -int dtb_node_property_read_string_helper(const struct dtb_node *dn, - const char *propname, const char **out_strs, - size_t sz, int skip); -/** - * of_property_read_string_index() - Find and read a string from a multiple - * strings property. - * @np: device node from which the property value is to be read. - * @propname: name of the property to be searched. - * @index: index of the string in the list of strings - * @out_string: pointer to null terminated return string, modified only if - * return value is 0. - * - * Search for a property in a device tree node and retrieve a null - * terminated string value (pointer to data, not a copy) in the list of strings - * contained in that property. - * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if - * property does not have a value, and -EILSEQ if the string is not - * null-terminated within the length of the property data. - * - * The out_string pointer is modified only if a valid string can be decoded. - */ -static inline int dtb_node_property_read_string_index(const struct dtb_node *dn, - const char *propname, - int index, const char **output) -{ - int rc = dtb_node_property_read_string_helper(dn, propname, output, 1, index); - return rc < 0 ? rc : 0; -} - -/** - * of_property_count_strings() - Find and return the number of strings from a - * multiple strings property. - * @np: device node from which the property value is to be read. - * @propname: name of the property to be searched. - * - * Search for a property in a device tree node and retrieve the number of null - * terminated string contain in it. Returns the number of strings on - * success, -EINVAL if the property does not exist, -ENODATA if property - * does not have a value, and -EILSEQ if the string is not null-terminated - * within the length of the property data. - */ -static inline int dtb_node_property_count_strings(const struct dtb_node *dn, - const char *propname) -{ - return dtb_node_property_read_string_helper(dn, propname, NULL, 0, 0); -} - -struct dtb_node *dtb_node_parse_phandle(const struct dtb_node *dn, - const char *phandle_name, int index); -int dtb_node_parse_phandle_with_args(const struct dtb_node *dn, - const char *list_name, const char *cells_name, - int index, struct fdt_phandle_args *out_args); -int dtb_node_count_phandle_with_args(const struct dtb_node *dn, - const char *list_name, const char *cells_name); - -/* dtb_node_addr.c */ -const uint32_t *dtb_node_get_address(const struct dtb_node *dev, int index, - uint64_t *size, unsigned int *flags); - -#define dtb_node_string_list(string, ...) ((char *[]){string, ##__VA_ARGS__, NULL}) - -#define for_each_property_string(node_ptr, property_name, str, size) \ - for (str = dtb_node_get_dtb_node_property_value(node_ptr, property_name, &size), \ - size += (typeof(size))(size_t)str; \ - str && *str; \ - str = dtb_node_get_dtb_string_list_value_next((void *)str, (void *)(size_t)size)) - -#define for_each_property_cell(node_ptr, property_name, value, list, size) \ - for (list = dtb_node_get_dtb_node_property_value(node_ptr, property_name, &size), \ - value = dtb_node_get_dtb_cell_value(list), \ - size /= sizeof(uint32_t); \ - size > 0; \ - value = dtb_node_get_dtb_cell_value(++list), --size) - -#define for_each_property_byte(node_ptr, property_name, value, list, size) \ - for (list = dtb_node_get_dtb_node_property_value(node_ptr, property_name, &size), \ - value = dtb_node_get_dtb_byte_value(list); \ - size > 0; \ - value = dtb_node_get_dtb_byte_value(++list), --size) - -#define for_each_node_child(node_ptr) \ - for (node_ptr = (node_ptr ? node_ptr->child : NULL); \ - node_ptr != NULL; \ - node_ptr = node_ptr->sibling) - -#define for_each_node_sibling(node_ptr) \ - for (node_ptr = (node_ptr ? node_ptr->sibling : NULL); \ - node_ptr != NULL; \ - node_ptr = node_ptr->sibling) - -#define for_each_of_allnodes_from(from, dn) \ - for (dn = dtb_node_find_all_nodes(from); dn; dn = dtb_node_find_all_nodes(dn)) - -#define for_each_of_all_child_nodes_from(from, dn) \ - for (dn = dtb_node_find_all_nodes(from); dn && (dn->level > from->level); dn = dtb_node_find_all_nodes(dn)) - -#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn) - -#define dtb_node_get(x) (x) -static inline void dtb_node_put(const struct dtb_node *np) -{ -} - -/* Helper to read a big number; size is in cells (not bytes) */ -static inline uint64_t dtb_node_read_number(const uint32_t *cell, int size) -{ - uint64_t r = 0; - while (size--) - r = (r << 32) | fdt32_to_cpu(*(cell++)); - return r; -} - -/** - * ofnode_valid() - check if an ofnode is valid - * - * @return true if the reference contains a valid ofnode, RT_FALSE if it is NULL - */ -static inline rt_bool_t dtb_node_valid(const struct dtb_node *node) -{ - if (dtb_node_active()) - return node != NULL; - return RT_FALSE; -} - -/*dtb_base.c */ -rt_bool_t dtb_node_read_bool(const struct dtb_node *node, const char *propname); -const void *dtb_node_read_prop(const struct dtb_node *node, const char *propname, int *sizep); -const char *dtb_node_read_string(const struct dtb_node *node, const char *propname); -const struct dtb_node *dtb_node_find_subnode(const struct dtb_node *node, const char *subnode_name); -int dtb_node_read_u32_array(const struct dtb_node *node, const char *propname, - uint32_t *out_values, size_t sz); -struct dtb_node *dtb_node_first_subnode(const struct dtb_node *node); -struct dtb_node *dtb_node_next_subnode(const struct dtb_node *node); -struct dtb_node *dtb_node_get_parent(const struct dtb_node *node); -const char *dtb_node_get_name(const struct dtb_node *node); -struct dtb_node *dtb_node_get_by_phandle(uint32_t phandle); -int dtb_node_read_size(const struct dtb_node *node, const char *propname); -int dtb_node_get_addr_and_size_by_index(const struct dtb_node *node, int index, size_t *addr, size_t *size); -size_t dtb_node_get_addr_index(const struct dtb_node *node, int index); -size_t dtb_node_get_addr(const struct dtb_node *node); -int dtb_node_stringlist_search(const struct dtb_node *node, const char *property, - const char *string); -int dtb_node_read_string_index(const struct dtb_node *node, const char *property, int index, - const char **outp); -int dtb_node_read_string_count(const struct dtb_node *node, const char *property); -struct dtb_node *dtb_node_path(const char *path); -const char *dtb_node_get_chosen_prop(const char *name); -struct dtb_node *dtb_node_get_chosen_node(const char *name); -const void *dtb_node_get_property(const struct dtb_node *node, const char *propname, int *lenp); -rt_bool_t dtb_node_is_available(const struct dtb_node *node); -size_t dtb_node_get_addr_size(const struct dtb_node *node, const char *property, - size_t *sizep); -const uint8_t *dtb_node_read_u8_array_ptr(const struct dtb_node *node, const char *propname, size_t sz); -int dtb_node_find_all_compatible_node(const struct dtb_node *from, const char *compatible, struct dtb_node **node_table, int max_num, int *node_num); -int dtb_node_write_prop(const struct dtb_node *node, const char *propname, int len, - const void *value); -int dtb_node_write_string(const struct dtb_node *node, const char *propname, const char *value); -int dtb_node_set_enabled(const struct dtb_node *node, rt_bool_t value); -int dtb_node_irq_get(struct dtb_node *dev, int index); -int dtb_node_irq_get_byname(struct dtb_node *dev, const char *name); -int dtb_node_irq_count(struct dtb_node *dev); - -/** - * dtb_node_for_each_subnode() - iterate over all subnodes of a parent - * - * @node: child node (ofnode, lvalue) - * @parent: parent node (ofnode) - * - * This is a wrapper around a for loop and is used like so: - * - * ofnode node; - * - * dtb_node_for_each_subnode(node, parent) { - * Use node - * ... - * } - * - * Note that this is implemented as a macro and @node is used as - * iterator in the loop. The parent variable can be a constant or even a - * literal. - */ -#define dtb_node_for_each_subnode(node, parent) \ - for (node = dtb_node_first_subnode(parent); \ - dtb_node_valid(node); \ - node = dtb_node_next_subnode(node)) - -#endif /* RT_FDT_H__ */ diff --git a/components/drivers/fdt/libfdt/SConscript b/components/drivers/fdt/libfdt/SConscript deleted file mode 100644 index 9efdd16c0a..0000000000 --- a/components/drivers/fdt/libfdt/SConscript +++ /dev/null @@ -1,10 +0,0 @@ -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') - -CPPPATH = [cwd] - -group = DefineGroup('FDT', src, depend = ['RT_USING_FDTLIB'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/drivers/fdt/libfdt/fdt.c b/components/drivers/fdt/libfdt/fdt.c deleted file mode 100644 index ecc7e8abee..0000000000 --- a/components/drivers/fdt/libfdt/fdt.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" -#include "fdt.h" -#include "libfdt.h" -#include "libfdt_internal.h" - -int fdt_check_header(const void *fdt) -{ - if (fdt_magic(fdt) == FDT_MAGIC) { - /* Complete tree */ - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { - /* Unfinished sequential-write blob */ - if (fdt_size_dt_struct(fdt) == 0) - return -FDT_ERR_BADSTATE; - } else { - return -FDT_ERR_BADMAGIC; - } - - return 0; -} - -const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) -{ - unsigned absoffset = offset + fdt_off_dt_struct(fdt); - - if ((absoffset < offset) - || ((absoffset + len) < absoffset) - || (absoffset + len) > fdt_totalsize(fdt)) - return NULL; - - if (fdt_version(fdt) >= 0x11) - if (((offset + len) < offset) - || ((offset + len) > fdt_size_dt_struct(fdt))) - return NULL; - - return _fdt_offset_ptr(fdt, offset); -} - -uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) -{ - const fdt32_t *tagp, *lenp; - uint32_t tag; - int offset = startoffset; - const char *p; - - *nextoffset = -FDT_ERR_TRUNCATED; - tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); - if (!tagp) - return FDT_END; /* premature end */ - tag = fdt32_to_cpu(*tagp); - offset += FDT_TAGSIZE; - - *nextoffset = -FDT_ERR_BADSTRUCTURE; - switch (tag) { - case FDT_BEGIN_NODE: - /* skip name */ - do { - p = fdt_offset_ptr(fdt, offset++, 1); - } while (p && (*p != '\0')); - if (!p) - return FDT_END; /* premature end */ - break; - - case FDT_PROP: - lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); - if (!lenp) - return FDT_END; /* premature end */ - /* skip-name offset, length and value */ - offset += sizeof(struct fdt_property) - FDT_TAGSIZE - + fdt32_to_cpu(*lenp); - break; - - case FDT_END: - case FDT_END_NODE: - case FDT_NOP: - break; - - default: - return FDT_END; - } - - if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) - return FDT_END; /* premature end */ - - *nextoffset = FDT_TAGALIGN(offset); - return tag; -} - -int _fdt_check_node_offset(const void *fdt, int offset) -{ - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) - return -FDT_ERR_BADOFFSET; - - return offset; -} - -int _fdt_check_prop_offset(const void *fdt, int offset) -{ - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) - return -FDT_ERR_BADOFFSET; - - return offset; -} - -int fdt_next_node(const void *fdt, int offset, int *depth) -{ - int nextoffset = 0; - uint32_t tag; - - if (offset >= 0) - if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) - return nextoffset; - - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_PROP: - case FDT_NOP: - break; - - case FDT_BEGIN_NODE: - if (depth) - (*depth)++; - break; - - case FDT_END_NODE: - if (depth && ((--(*depth)) < 0)) - return nextoffset; - break; - - case FDT_END: - if ((nextoffset >= 0) - || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) - return -FDT_ERR_NOTFOUND; - else - return nextoffset; - } - } while (tag != FDT_BEGIN_NODE); - - return offset; -} - -int fdt_first_subnode(const void *fdt, int offset) -{ - int depth = 0; - - offset = fdt_next_node(fdt, offset, &depth); - if (offset < 0 || depth != 1) - return -FDT_ERR_NOTFOUND; - - return offset; -} - -int fdt_next_subnode(const void *fdt, int offset) -{ - int depth = 1; - - /* - * With respect to the parent, the depth of the next subnode will be - * the same as the last. - */ - do { - offset = fdt_next_node(fdt, offset, &depth); - if (offset < 0 || depth < 1) - return -FDT_ERR_NOTFOUND; - } while (depth > 1); - - return offset; -} - -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) -{ - int len = strlen(s) + 1; - const char *last = strtab + tabsize - len; - const char *p; - - for (p = strtab; p <= last; p++) - if (memcmp(p, s, len) == 0) - return p; - return NULL; -} - -int fdt_move(const void *fdt, void *buf, int bufsize) -{ - FDT_CHECK_HEADER(fdt); - - if (fdt_totalsize(fdt) > bufsize) - return -FDT_ERR_NOSPACE; - - memmove(buf, fdt, fdt_totalsize(fdt)); - return 0; -} diff --git a/components/drivers/fdt/libfdt/fdt.h b/components/drivers/fdt/libfdt/fdt.h deleted file mode 100644 index a00161cced..0000000000 --- a/components/drivers/fdt/libfdt/fdt.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-12-20 RT-Thread the first version - */ - -#ifndef _FDT_H -#define _FDT_H -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * Copyright 2012 Kim Phillips, Freescale Semiconductor. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __ASSEMBLY__ - -#include -#include -#include - -struct fdt_header { - fdt32_t magic; /* magic word FDT_MAGIC */ - fdt32_t totalsize; /* total size of DT block */ - fdt32_t off_dt_struct; /* offset to structure */ - fdt32_t off_dt_strings; /* offset to strings */ - fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ - fdt32_t version; /* format version */ - fdt32_t last_comp_version; /* last compatible version */ - - /* version 2 fields below */ - fdt32_t boot_cpuid_phys; /* Which physical CPU id we're - booting on */ - /* version 3 fields below */ - fdt32_t size_dt_strings; /* size of the strings block */ - - /* version 17 fields below */ - fdt32_t size_dt_struct; /* size of the structure block */ -}; - -struct fdt_reserve_entry { - fdt64_t address; - fdt64_t size; -}; - -struct fdt_node_header { - fdt32_t tag; - char name[0]; -}; - -struct fdt_property { - fdt32_t tag; - fdt32_t len; - fdt32_t nameoff; - char data[0]; -}; - -#endif /* !__ASSEMBLY */ - -#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ -#define FDT_TAGSIZE sizeof(fdt32_t) - -#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ -#define FDT_END_NODE 0x2 /* End node */ -#define FDT_PROP 0x3 /* Property: name off, - size, content */ -#define FDT_NOP 0x4 /* nop */ -#define FDT_END 0x9 - -#define FDT_V1_SIZE (7*sizeof(fdt32_t)) -#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) -#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) -#define FDT_V16_SIZE FDT_V3_SIZE -#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) - -#endif /* _FDT_H */ diff --git a/components/drivers/fdt/libfdt/fdt_addresses.c b/components/drivers/fdt/libfdt/fdt_addresses.c deleted file mode 100644 index a8f2ad5ebc..0000000000 --- a/components/drivers/fdt/libfdt/fdt_addresses.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2014 David Gibson - * Copyright (C) 2018 embedded brains GmbH - */ -#include "libfdt_env.h" -#include -#include -#include "libfdt_internal.h" - -static int fdt_cells(const void *fdt, int nodeoffset, const char *name) -{ - const fdt32_t *c; - uint32_t val; - int len; - - c = fdt_getprop(fdt, nodeoffset, name, &len); - if (!c) - return len; - - if (len != sizeof(*c)) - return -FDT_ERR_BADNCELLS; - - val = fdt32_to_cpu(*c); - if (val > FDT_MAX_NCELLS) - return -FDT_ERR_BADNCELLS; - - return (int)val; -} - -int fdt_address_cells(const void *fdt, int nodeoffset) -{ - int val; - - val = fdt_cells(fdt, nodeoffset, "#address-cells"); - if (val == 0) - return -FDT_ERR_BADNCELLS; - if (val == -FDT_ERR_NOTFOUND) - return 2; - return val; -} - -int fdt_size_cells(const void *fdt, int nodeoffset) -{ - int val; - - val = fdt_cells(fdt, nodeoffset, "#size-cells"); - if (val == -FDT_ERR_NOTFOUND) - return 1; - return val; -} - -/* This function assumes that [address|size]_cells is 1 or 2 */ -int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, - const char *name, uint64_t addr, uint64_t size) -{ - int addr_cells, size_cells, ret; - uint8_t data[sizeof(fdt64_t) * 2], *prop; - - ret = fdt_address_cells(fdt, parent); - if (ret < 0) - return ret; - addr_cells = ret; - - ret = fdt_size_cells(fdt, parent); - if (ret < 0) - return ret; - size_cells = ret; - - /* check validity of address */ - prop = data; - if (addr_cells == 1) { - if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) - return -FDT_ERR_BADVALUE; - - fdt32_st(prop, (uint32_t)addr); - } else if (addr_cells == 2) { - fdt64_st(prop, addr); - } else { - return -FDT_ERR_BADNCELLS; - } - - /* check validity of size */ - prop += addr_cells * sizeof(fdt32_t); - if (size_cells == 1) { - if (size > UINT32_MAX) - return -FDT_ERR_BADVALUE; - - fdt32_st(prop, (uint32_t)size); - } else if (size_cells == 2) { - fdt64_st(prop, size); - } else { - return -FDT_ERR_BADNCELLS; - } - - return fdt_appendprop(fdt, nodeoffset, name, data, - (addr_cells + size_cells) * sizeof(fdt32_t)); -} diff --git a/components/drivers/fdt/libfdt/fdt_empty_tree.c b/components/drivers/fdt/libfdt/fdt_empty_tree.c deleted file mode 100644 index 0f317a4726..0000000000 --- a/components/drivers/fdt/libfdt/fdt_empty_tree.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2012 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include "fdt.h" -#include "libfdt.h" - -#include "libfdt_internal.h" - -int fdt_create_empty_tree(void *buf, int bufsize) -{ - int err; - - err = fdt_create(buf, bufsize); - if (err) - return err; - - err = fdt_finish_reservemap(buf); - if (err) - return err; - - err = fdt_begin_node(buf, ""); - if (err) - return err; - - err = fdt_end_node(buf); - if (err) - return err; - - err = fdt_finish(buf); - if (err) - return err; - - return fdt_open_into(buf, buf, bufsize); -} - diff --git a/components/drivers/fdt/libfdt/fdt_ro.c b/components/drivers/fdt/libfdt/fdt_ro.c deleted file mode 100644 index ff8b7fbdc0..0000000000 --- a/components/drivers/fdt/libfdt/fdt_ro.c +++ /dev/null @@ -1,701 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" -#include "fdt.h" -#include "libfdt.h" -#include "libfdt_internal.h" - -static int _fdt_nodename_eq(const void *fdt, int offset, - const char *s, int len) -{ - const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); - - if (! p) - /* short match */ - return 0; - - if (memcmp(p, s, len) != 0) - return 0; - - if (p[len] == '\0') - return 1; - else if (!memchr(s, '@', len) && (p[len] == '@')) - return 1; - else - return 0; -} - -const char *fdt_string(const void *fdt, int stroffset) -{ - return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; -} - -static int _fdt_string_eq(const void *fdt, int stroffset, - const char *s, int len) -{ - const char *p = fdt_string(fdt, stroffset); - - return (strlen(p) == len) && (memcmp(p, s, len) == 0); -} - -uint32_t fdt_get_max_phandle(const void *fdt) -{ - uint32_t max_phandle = 0; - int offset; - - for (offset = fdt_next_node(fdt, -1, NULL);; - offset = fdt_next_node(fdt, offset, NULL)) { - uint32_t phandle; - - if (offset == -FDT_ERR_NOTFOUND) - return max_phandle; - - if (offset < 0) - return (uint32_t)-1; - - phandle = fdt_get_phandle(fdt, offset); - if (phandle == (uint32_t)-1) - continue; - - if (phandle > max_phandle) - max_phandle = phandle; - } - - return 0; -} - -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) -{ - FDT_CHECK_HEADER(fdt); - *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); - *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); - return 0; -} - -int fdt_num_mem_rsv(const void *fdt) -{ - int i = 0; - - while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) - i++; - return i; -} - -static int _nextprop(const void *fdt, int offset) -{ - uint32_t tag; - int nextoffset; - - do { - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_END: - if (nextoffset >= 0) - return -FDT_ERR_BADSTRUCTURE; - else - return nextoffset; - - case FDT_PROP: - return offset; - } - offset = nextoffset; - } while (tag == FDT_NOP); - - return -FDT_ERR_NOTFOUND; -} - -int fdt_subnode_offset_namelen(const void *fdt, int offset, - const char *name, int namelen) -{ - int depth; - - FDT_CHECK_HEADER(fdt); - - for (depth = 0; - (offset >= 0) && (depth >= 0); - offset = fdt_next_node(fdt, offset, &depth)) - if ((depth == 1) - && _fdt_nodename_eq(fdt, offset, name, namelen)) - return offset; - - if (depth < 0) - return -FDT_ERR_NOTFOUND; - return offset; /* error */ -} - -int fdt_subnode_offset(const void *fdt, int parentoffset, - const char *name) -{ - return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); -} - -int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) -{ - const char *end = path + namelen; - const char *p = path; - int offset = 0; - - FDT_CHECK_HEADER(fdt); - - /* see if we have an alias */ - if (*path != '/') { - const char *q = memchr(path, '/', end - p); - - if (!q) - q = end; - - p = fdt_get_alias_namelen(fdt, p, q - p); - if (!p) - return -FDT_ERR_BADPATH; - offset = fdt_path_offset(fdt, p); - - p = q; - } - - while (p < end) { - const char *q; - - while (*p == '/') { - p++; - if (p == end) - return offset; - } - q = memchr(p, '/', end - p); - if (! q) - q = end; - - offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); - if (offset < 0) - return offset; - - p = q; - } - - return offset; -} - -int fdt_path_offset(const void *fdt, const char *path) -{ - return fdt_path_offset_namelen(fdt, path, strlen(path)); -} - -const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) -{ - const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); - int err; - - if (((err = fdt_check_header(fdt)) != 0) - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) - goto fail; - - if (len) - *len = strlen(nh->name); - - return nh->name; - - fail: - if (len) - *len = err; - return NULL; -} - -int fdt_first_property_offset(const void *fdt, int nodeoffset) -{ - int offset; - - if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) - return offset; - - return _nextprop(fdt, offset); -} - -int fdt_next_property_offset(const void *fdt, int offset) -{ - if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) - return offset; - - return _nextprop(fdt, offset); -} - -const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - int offset, - int *lenp) -{ - int err; - const struct fdt_property *prop; - - if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { - if (lenp) - *lenp = err; - return NULL; - } - - prop = _fdt_offset_ptr(fdt, offset); - - if (lenp) - *lenp = fdt32_to_cpu(prop->len); - - return prop; -} - -const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int offset, - const char *name, - int namelen, int *lenp) -{ - for (offset = fdt_first_property_offset(fdt, offset); - (offset >= 0); - (offset = fdt_next_property_offset(fdt, offset))) { - const struct fdt_property *prop; - - if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { - offset = -FDT_ERR_INTERNAL; - break; - } - if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), - name, namelen)) - return prop; - } - - if (lenp) - *lenp = offset; - return NULL; -} - -const struct fdt_property *fdt_get_property(const void *fdt, - int nodeoffset, - const char *name, int *lenp) -{ - return fdt_get_property_namelen(fdt, nodeoffset, name, - strlen(name), lenp); -} - -const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, - const char *name, int namelen, int *lenp) -{ - const struct fdt_property *prop; - - prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); - if (! prop) - return NULL; - - return prop->data; -} - -const void *fdt_getprop_by_offset(const void *fdt, int offset, - const char **namep, int *lenp) -{ - const struct fdt_property *prop; - - prop = fdt_get_property_by_offset(fdt, offset, lenp); - if (!prop) - return NULL; - if (namep) - *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - return prop->data; -} - -const void *fdt_getprop(const void *fdt, int nodeoffset, - const char *name, int *lenp) -{ - return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); -} - -uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) -{ - const fdt32_t *php; - int len; - - /* FIXME: This is a bit sub-optimal, since we potentially scan - * over all the properties twice. */ - php = fdt_getprop(fdt, nodeoffset, "phandle", &len); - if (!php || (len != sizeof(*php))) { - php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); - if (!php || (len != sizeof(*php))) - return 0; - } - - return fdt32_to_cpu(*php); -} - -const char *fdt_get_alias_namelen(const void *fdt, - const char *name, int namelen) -{ - int aliasoffset; - - aliasoffset = fdt_path_offset(fdt, "/aliases"); - if (aliasoffset < 0) - return NULL; - - return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); -} - -const char *fdt_get_alias(const void *fdt, const char *name) -{ - return fdt_get_alias_namelen(fdt, name, strlen(name)); -} - -int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) -{ - int pdepth = 0, p = 0; - int offset, depth, namelen; - const char *name; - - FDT_CHECK_HEADER(fdt); - - if (buflen < 2) - return -FDT_ERR_NOSPACE; - - for (offset = 0, depth = 0; - (offset >= 0) && (offset <= nodeoffset); - offset = fdt_next_node(fdt, offset, &depth)) { - while (pdepth > depth) { - do { - p--; - } while (buf[p-1] != '/'); - pdepth--; - } - - if (pdepth >= depth) { - name = fdt_get_name(fdt, offset, &namelen); - if (!name) - return namelen; - if ((p + namelen + 1) <= buflen) { - memcpy(buf + p, name, namelen); - p += namelen; - buf[p++] = '/'; - pdepth++; - } - } - - if (offset == nodeoffset) { - if (pdepth < (depth + 1)) - return -FDT_ERR_NOSPACE; - - if (p > 1) /* special case so that root path is "/", not "" */ - p--; - buf[p] = '\0'; - return 0; - } - } - - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; - - return offset; /* error from fdt_next_node() */ -} - -int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, - int supernodedepth, int *nodedepth) -{ - int offset, depth; - int supernodeoffset = -FDT_ERR_INTERNAL; - - FDT_CHECK_HEADER(fdt); - - if (supernodedepth < 0) - return -FDT_ERR_NOTFOUND; - - for (offset = 0, depth = 0; - (offset >= 0) && (offset <= nodeoffset); - offset = fdt_next_node(fdt, offset, &depth)) { - if (depth == supernodedepth) - supernodeoffset = offset; - - if (offset == nodeoffset) { - if (nodedepth) - *nodedepth = depth; - - if (supernodedepth > depth) - return -FDT_ERR_NOTFOUND; - else - return supernodeoffset; - } - } - - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; - - return offset; /* error from fdt_next_node() */ -} - -int fdt_node_depth(const void *fdt, int nodeoffset) -{ - int nodedepth; - int err; - - err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); - if (err) - return (err < 0) ? err : -FDT_ERR_INTERNAL; - return nodedepth; -} - -int fdt_parent_offset(const void *fdt, int nodeoffset) -{ - int nodedepth = fdt_node_depth(fdt, nodeoffset); - - if (nodedepth < 0) - return nodedepth; - return fdt_supernode_atdepth_offset(fdt, nodeoffset, - nodedepth - 1, NULL); -} - -int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, - const char *propname, - const void *propval, int proplen) -{ - int offset; - const void *val; - int len; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we scan each - * property of a node in fdt_getprop(), then if that didn't - * find what we want, we scan over them again making our way - * to the next node. Still it's the easiest to implement - * approach; performance can come later. */ - for (offset = fdt_next_node(fdt, startoffset, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - val = fdt_getprop(fdt, offset, propname, &len); - if (val && (len == proplen) - && (memcmp(val, propval, len) == 0)) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} - -int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) -{ - int offset; - - if ((phandle == 0) || (phandle == -1)) - return -FDT_ERR_BADPHANDLE; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we - * potentially scan each property of a node in - * fdt_get_phandle(), then if that didn't find what - * we want, we scan over them again making our way to the next - * node. Still it's the easiest to implement approach; - * performance can come later. */ - for (offset = fdt_next_node(fdt, -1, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - if (fdt_get_phandle(fdt, offset) == phandle) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} - -int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) -{ - int len = strlen(str); - const char *p; - - while (listlen >= len) { - if (memcmp(str, strlist, len+1) == 0) - return 1; - p = memchr(strlist, '\0', listlen); - if (!p) - return 0; /* malformed strlist.. */ - listlen -= (p-strlist) + 1; - strlist = p + 1; - } - return 0; -} - -int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) -{ - const char *list, *end; - int length, count = 0; - - list = fdt_getprop(fdt, nodeoffset, property, &length); - if (!list) - return length; - - end = list + length; - - while (list < end) { - length = strnlen(list, end - list) + 1; - - /* Abort if the last string isn't properly NUL-terminated. */ - if (list + length > end) - return -FDT_ERR_BADVALUE; - - list += length; - count++; - } - - return count; -} - -int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, - const char *string) -{ - int length, len, idx = 0; - const char *list, *end; - - list = fdt_getprop(fdt, nodeoffset, property, &length); - if (!list) - return length; - - len = strlen(string) + 1; - end = list + length; - - while (list < end) { - length = strnlen(list, end - list) + 1; - - /* Abort if the last string isn't properly NUL-terminated. */ - if (list + length > end) - return -FDT_ERR_BADVALUE; - - if (length == len && memcmp(list, string, length) == 0) - return idx; - - list += length; - idx++; - } - - return -FDT_ERR_NOTFOUND; -} - -const char *fdt_stringlist_get(const void *fdt, int nodeoffset, - const char *property, int idx, - int *lenp) -{ - const char *list, *end; - int length; - - list = fdt_getprop(fdt, nodeoffset, property, &length); - if (!list) { - if (lenp) - *lenp = length; - - return NULL; - } - - end = list + length; - - while (list < end) { - length = strnlen(list, end - list) + 1; - - /* Abort if the last string isn't properly NUL-terminated. */ - if (list + length > end) { - if (lenp) - *lenp = -FDT_ERR_BADVALUE; - - return NULL; - } - - if (idx == 0) { - if (lenp) - *lenp = length - 1; - - return list; - } - - list += length; - idx--; - } - - if (lenp) - *lenp = -FDT_ERR_NOTFOUND; - - return NULL; -} - -int fdt_node_check_compatible(const void *fdt, int nodeoffset, - const char *compatible) -{ - const void *prop; - int len; - - prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); - if (!prop) - return len; - - return !fdt_stringlist_contains(prop, len, compatible); -} - -int fdt_node_offset_by_compatible(const void *fdt, int startoffset, - const char *compatible) -{ - int offset, err; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we scan each - * property of a node in fdt_node_check_compatible(), then if - * that didn't find what we want, we scan over them again - * making our way to the next node. Still it's the easiest to - * implement approach; performance can come later. */ - for (offset = fdt_next_node(fdt, startoffset, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - err = fdt_node_check_compatible(fdt, offset, compatible); - if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) - return err; - else if (err == 0) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} diff --git a/components/drivers/fdt/libfdt/fdt_rw.c b/components/drivers/fdt/libfdt/fdt_rw.c deleted file mode 100644 index 58827ef898..0000000000 --- a/components/drivers/fdt/libfdt/fdt_rw.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" -#include "fdt.h" -#include "libfdt.h" -#include "libfdt_internal.h" - -static int _fdt_blocks_misordered(const void *fdt, - int mem_rsv_size, int struct_size) -{ - return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) - || (fdt_off_dt_struct(fdt) < - (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) - || (fdt_off_dt_strings(fdt) < - (fdt_off_dt_struct(fdt) + struct_size)) - || (fdt_totalsize(fdt) < - (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); -} - -static int _fdt_rw_check_header(void *fdt) -{ - FDT_CHECK_HEADER(fdt); - - if (fdt_version(fdt) < 17) - return -FDT_ERR_BADVERSION; - if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), - fdt_size_dt_struct(fdt))) - return -FDT_ERR_BADLAYOUT; - if (fdt_version(fdt) > 17) - fdt_set_version(fdt, 17); - - return 0; -} - -#define FDT_RW_CHECK_HEADER(fdt) \ - { \ - int __err; \ - if ((__err = _fdt_rw_check_header(fdt)) != 0) \ - return __err; \ - } - -static inline int _fdt_data_size(void *fdt) -{ - return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); -} - -static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) -{ - char *p = splicepoint; - char *end = (char *)fdt + _fdt_data_size(fdt); - - if (oldlen <= 0) - return -FDT_ERR_BADOFFSET; - if (((p + oldlen) < p) || ((p + oldlen) > end)) - return -FDT_ERR_BADOFFSET; - if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) - return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) - return -FDT_ERR_NOSPACE; - memmove(p + newlen, p + oldlen, end - p - oldlen); - return 0; -} - -static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, - int oldn, int newn) -{ - int delta = (newn - oldn) * sizeof(*p); - int err; - err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); - if (err) - return err; - fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); - return 0; -} - -static int _fdt_splice_struct(void *fdt, void *p, - int oldlen, int newlen) -{ - int delta = newlen - oldlen; - int err; - - if ((err = _fdt_splice(fdt, p, oldlen, newlen))) - return err; - - fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); - return 0; -} - -static int _fdt_splice_string(void *fdt, int newlen) -{ - void *p = (char *)fdt - + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); - int err; - - if ((err = _fdt_splice(fdt, p, 0, newlen))) - return err; - - fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); - return 0; -} - -static int _fdt_find_add_string(void *fdt, const char *s) -{ - char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); - const char *p; - char *new; - int len = strlen(s) + 1; - int err; - - p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); - if (p) - /* found it */ - return (p - strtab); - - new = strtab + fdt_size_dt_strings(fdt); - err = _fdt_splice_string(fdt, len); - if (err) - return err; - - memcpy(new, s, len); - return (new - strtab); -} - -int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) -{ - struct fdt_reserve_entry *re; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); - err = _fdt_splice_mem_rsv(fdt, re, 0, 1); - if (err) - return err; - - re->address = cpu_to_fdt64(address); - re->size = cpu_to_fdt64(size); - return 0; -} - -int fdt_del_mem_rsv(void *fdt, int n) -{ - struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); - - FDT_RW_CHECK_HEADER(fdt); - - if (n >= fdt_num_mem_rsv(fdt)) - return -FDT_ERR_NOTFOUND; - - return _fdt_splice_mem_rsv(fdt, re, 1, 0); -} - -static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, - int len, struct fdt_property **prop) -{ - int oldlen; - int err; - - *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); - if (! (*prop)) - return oldlen; - - if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), - FDT_TAGALIGN(len)))) - return err; - - (*prop)->len = cpu_to_fdt32(len); - return 0; -} - -static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, - int len, struct fdt_property **prop) -{ - int proplen; - int nextoffset; - int namestroff; - int err; - - if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) - return nextoffset; - - namestroff = _fdt_find_add_string(fdt, name); - if (namestroff < 0) - return namestroff; - - *prop = _fdt_offset_ptr_w(fdt, nextoffset); - proplen = sizeof(**prop) + FDT_TAGALIGN(len); - - err = _fdt_splice_struct(fdt, *prop, 0, proplen); - if (err) - return err; - - (*prop)->tag = cpu_to_fdt32(FDT_PROP); - (*prop)->nameoff = cpu_to_fdt32(namestroff); - (*prop)->len = cpu_to_fdt32(len); - return 0; -} - -int fdt_set_name(void *fdt, int nodeoffset, const char *name) -{ - char *namep; - int oldlen, newlen; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); - if (!namep) - return oldlen; - - newlen = strlen(name); - - err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), - FDT_TAGALIGN(newlen+1)); - if (err) - return err; - - memcpy(namep, name, newlen+1); - return 0; -} - -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - struct fdt_property *prop; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); - if (err == -FDT_ERR_NOTFOUND) - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); - if (err) - return err; - - if (len) - memcpy(prop->data, val, len); - return 0; -} - -int fdt_appendprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - struct fdt_property *prop; - int err, oldlen, newlen; - - FDT_RW_CHECK_HEADER(fdt); - - prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); - if (prop) { - newlen = len + oldlen; - err = _fdt_splice_struct(fdt, prop->data, - FDT_TAGALIGN(oldlen), - FDT_TAGALIGN(newlen)); - if (err) - return err; - prop->len = cpu_to_fdt32(newlen); - memcpy(prop->data + oldlen, val, len); - } else { - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); - if (err) - return err; - memcpy(prop->data, val, len); - } - return 0; -} - -int fdt_delprop(void *fdt, int nodeoffset, const char *name) -{ - struct fdt_property *prop; - int len, proplen; - - FDT_RW_CHECK_HEADER(fdt); - - prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) - return len; - - proplen = sizeof(*prop) + FDT_TAGALIGN(len); - return _fdt_splice_struct(fdt, prop, proplen, 0); -} - -int fdt_add_subnode_namelen(void *fdt, int parentoffset, - const char *name, int namelen) -{ - struct fdt_node_header *nh; - int offset, nextoffset; - int nodelen; - int err; - uint32_t tag; - fdt32_t *endtag; - - FDT_RW_CHECK_HEADER(fdt); - - offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); - if (offset >= 0) - return -FDT_ERR_EXISTS; - else if (offset != -FDT_ERR_NOTFOUND) - return offset; - - /* Try to place the new node after the parent's properties */ - fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - } while ((tag == FDT_PROP) || (tag == FDT_NOP)); - - nh = _fdt_offset_ptr_w(fdt, offset); - nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; - - err = _fdt_splice_struct(fdt, nh, 0, nodelen); - if (err) - return err; - - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); - memcpy(nh->name, name, namelen); - endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); - *endtag = cpu_to_fdt32(FDT_END_NODE); - - return offset; -} - -int fdt_add_subnode(void *fdt, int parentoffset, const char *name) -{ - return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); -} - -int fdt_del_node(void *fdt, int nodeoffset) -{ - int endoffset; - - FDT_RW_CHECK_HEADER(fdt); - - endoffset = _fdt_node_end_offset(fdt, nodeoffset); - if (endoffset < 0) - return endoffset; - - return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), - endoffset - nodeoffset, 0); -} - -static void _fdt_packblocks(const char *old, char *new, - int mem_rsv_size, int struct_size) -{ - int mem_rsv_off, struct_off, strings_off; - - mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); - struct_off = mem_rsv_off + mem_rsv_size; - strings_off = struct_off + struct_size; - - memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); - fdt_set_off_mem_rsvmap(new, mem_rsv_off); - - memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); - fdt_set_off_dt_struct(new, struct_off); - fdt_set_size_dt_struct(new, struct_size); - - memmove(new + strings_off, old + fdt_off_dt_strings(old), - fdt_size_dt_strings(old)); - fdt_set_off_dt_strings(new, strings_off); - fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); -} - -int fdt_open_into(const void *fdt, void *buf, int bufsize) -{ - int err; - int mem_rsv_size, struct_size; - int newsize; - const char *fdtstart = fdt; - const char *fdtend = fdtstart + fdt_totalsize(fdt); - char *tmp; - - FDT_CHECK_HEADER(fdt); - - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) - * sizeof(struct fdt_reserve_entry); - - if (fdt_version(fdt) >= 17) { - struct_size = fdt_size_dt_struct(fdt); - } else { - struct_size = 0; - while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) - ; - if (struct_size < 0) - return struct_size; - } - - if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { - /* no further work necessary */ - err = fdt_move(fdt, buf, bufsize); - if (err) - return err; - fdt_set_version(buf, 17); - fdt_set_size_dt_struct(buf, struct_size); - fdt_set_totalsize(buf, bufsize); - return 0; - } - - /* Need to reorder */ - newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size - + struct_size + fdt_size_dt_strings(fdt); - - if (bufsize < newsize) - return -FDT_ERR_NOSPACE; - - /* First attempt to build converted tree at beginning of buffer */ - tmp = buf; - /* But if that overlaps with the old tree... */ - if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { - /* Try right after the old tree instead */ - tmp = (char *)(uintptr_t)fdtend; - if ((tmp + newsize) > ((char *)buf + bufsize)) - return -FDT_ERR_NOSPACE; - } - - _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); - memmove(buf, tmp, newsize); - - fdt_set_magic(buf, FDT_MAGIC); - fdt_set_totalsize(buf, bufsize); - fdt_set_version(buf, 17); - fdt_set_last_comp_version(buf, 16); - fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); - - return 0; -} - -int fdt_pack(void *fdt) -{ - int mem_rsv_size; - - FDT_RW_CHECK_HEADER(fdt); - - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) - * sizeof(struct fdt_reserve_entry); - _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); - fdt_set_totalsize(fdt, _fdt_data_size(fdt)); - - return 0; -} diff --git a/components/drivers/fdt/libfdt/fdt_strerror.c b/components/drivers/fdt/libfdt/fdt_strerror.c deleted file mode 100644 index a62aad11ed..0000000000 --- a/components/drivers/fdt/libfdt/fdt_strerror.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" -#include "fdt.h" -#include "libfdt.h" -#include "libfdt_internal.h" - -struct fdt_errtabent { - const char *str; -}; - -#define FDT_ERRTABENT(val) \ - [(val)] = { .str = #val, } - -static struct fdt_errtabent fdt_errtable[] = { - FDT_ERRTABENT(FDT_ERR_NOTFOUND), - FDT_ERRTABENT(FDT_ERR_EXISTS), - FDT_ERRTABENT(FDT_ERR_NOSPACE), - - FDT_ERRTABENT(FDT_ERR_BADOFFSET), - FDT_ERRTABENT(FDT_ERR_BADPATH), - FDT_ERRTABENT(FDT_ERR_BADPHANDLE), - FDT_ERRTABENT(FDT_ERR_BADSTATE), - - FDT_ERRTABENT(FDT_ERR_TRUNCATED), - FDT_ERRTABENT(FDT_ERR_BADMAGIC), - FDT_ERRTABENT(FDT_ERR_BADVERSION), - FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), - FDT_ERRTABENT(FDT_ERR_BADLAYOUT), - FDT_ERRTABENT(FDT_ERR_INTERNAL), - FDT_ERRTABENT(FDT_ERR_BADNCELLS), - FDT_ERRTABENT(FDT_ERR_BADVALUE), - FDT_ERRTABENT(FDT_ERR_BADOVERLAY), - FDT_ERRTABENT(FDT_ERR_NOPHANDLES), -}; -#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) - -const char *fdt_strerror(int errval) -{ - if (errval > 0) - return ""; - else if (errval == 0) - return ""; - else if (errval > -FDT_ERRTABSIZE) { - const char *s = fdt_errtable[-errval].str; - - if (s) - return s; - } - - return ""; -} diff --git a/components/drivers/fdt/libfdt/fdt_sw.c b/components/drivers/fdt/libfdt/fdt_sw.c deleted file mode 100644 index 4834d01b48..0000000000 --- a/components/drivers/fdt/libfdt/fdt_sw.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" -#include "fdt.h" -#include "libfdt.h" -#include "libfdt_internal.h" - -static int _fdt_sw_check_header(void *fdt) -{ - if (fdt_magic(fdt) != FDT_SW_MAGIC) - return -FDT_ERR_BADMAGIC; - /* FIXME: should check more details about the header state */ - return 0; -} - -#define FDT_SW_CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = _fdt_sw_check_header(fdt)) != 0) \ - return err; \ - } - -static void *_fdt_grab_space(void *fdt, size_t len) -{ - int offset = fdt_size_dt_struct(fdt); - int spaceleft; - - spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - - fdt_size_dt_strings(fdt); - - if ((offset + len < offset) || (offset + len > spaceleft)) - return NULL; - - fdt_set_size_dt_struct(fdt, offset + len); - return _fdt_offset_ptr_w(fdt, offset); -} - -int fdt_create(void *buf, int bufsize) -{ - void *fdt = buf; - - if (bufsize < sizeof(struct fdt_header)) - return -FDT_ERR_NOSPACE; - - memset(buf, 0, bufsize); - - fdt_set_magic(fdt, FDT_SW_MAGIC); - fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); - fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); - fdt_set_totalsize(fdt, bufsize); - - fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry))); - fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); - fdt_set_off_dt_strings(fdt, bufsize); - - return 0; -} - -int fdt_resize(void *fdt, void *buf, int bufsize) -{ - size_t headsize, tailsize; - char *oldtail, *newtail; - - FDT_SW_CHECK_HEADER(fdt); - - headsize = fdt_off_dt_struct(fdt); - tailsize = fdt_size_dt_strings(fdt); - - if ((headsize + tailsize) > bufsize) - return -FDT_ERR_NOSPACE; - - oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; - newtail = (char *)buf + bufsize - tailsize; - - /* Two cases to avoid clobbering data if the old and new - * buffers partially overlap */ - if (buf <= fdt) { - memmove(buf, fdt, headsize); - memmove(newtail, oldtail, tailsize); - } else { - memmove(newtail, oldtail, tailsize); - memmove(buf, fdt, headsize); - } - - fdt_set_off_dt_strings(buf, bufsize); - fdt_set_totalsize(buf, bufsize); - - return 0; -} - -int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) -{ - struct fdt_reserve_entry *re; - int offset; - - FDT_SW_CHECK_HEADER(fdt); - - if (fdt_size_dt_struct(fdt)) - return -FDT_ERR_BADSTATE; - - offset = fdt_off_dt_struct(fdt); - if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) - return -FDT_ERR_NOSPACE; - - re = (struct fdt_reserve_entry *)((char *)fdt + offset); - re->address = cpu_to_fdt64(addr); - re->size = cpu_to_fdt64(size); - - fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); - - return 0; -} - -int fdt_finish_reservemap(void *fdt) -{ - return fdt_add_reservemap_entry(fdt, 0, 0); -} - -int fdt_begin_node(void *fdt, const char *name) -{ - struct fdt_node_header *nh; - int namelen = strlen(name) + 1; - - FDT_SW_CHECK_HEADER(fdt); - - nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); - if (! nh) - return -FDT_ERR_NOSPACE; - - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - memcpy(nh->name, name, namelen); - return 0; -} - -int fdt_end_node(void *fdt) -{ - fdt32_t *en; - - FDT_SW_CHECK_HEADER(fdt); - - en = _fdt_grab_space(fdt, FDT_TAGSIZE); - if (! en) - return -FDT_ERR_NOSPACE; - - *en = cpu_to_fdt32(FDT_END_NODE); - return 0; -} - -static int _fdt_find_add_string(void *fdt, const char *s) -{ - char *strtab = (char *)fdt + fdt_totalsize(fdt); - const char *p; - int strtabsize = fdt_size_dt_strings(fdt); - int len = strlen(s) + 1; - int struct_top, offset; - - p = _fdt_find_string(strtab - strtabsize, strtabsize, s); - if (p) - return p - strtab; - - /* Add it */ - offset = -strtabsize - len; - struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - if (fdt_totalsize(fdt) + offset < struct_top) - return 0; /* no more room :( */ - - memcpy(strtab + offset, s, len); - fdt_set_size_dt_strings(fdt, strtabsize + len); - return offset; -} - -int fdt_property(void *fdt, const char *name, const void *val, int len) -{ - struct fdt_property *prop; - int nameoff; - - FDT_SW_CHECK_HEADER(fdt); - - nameoff = _fdt_find_add_string(fdt, name); - if (nameoff == 0) - return -FDT_ERR_NOSPACE; - - prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); - if (! prop) - return -FDT_ERR_NOSPACE; - - prop->tag = cpu_to_fdt32(FDT_PROP); - prop->nameoff = cpu_to_fdt32(nameoff); - prop->len = cpu_to_fdt32(len); - memcpy(prop->data, val, len); - return 0; -} - -int fdt_finish(void *fdt) -{ - char *p = (char *)fdt; - fdt32_t *end; - int oldstroffset, newstroffset; - uint32_t tag; - int offset, nextoffset; - - FDT_SW_CHECK_HEADER(fdt); - - /* Add terminator */ - end = _fdt_grab_space(fdt, sizeof(*end)); - if (! end) - return -FDT_ERR_NOSPACE; - *end = cpu_to_fdt32(FDT_END); - - /* Relocate the string table */ - oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); - newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); - fdt_set_off_dt_strings(fdt, newstroffset); - - /* Walk the structure, correcting string offsets */ - offset = 0; - while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { - if (tag == FDT_PROP) { - struct fdt_property *prop = - _fdt_offset_ptr_w(fdt, offset); - int nameoff; - - nameoff = fdt32_to_cpu(prop->nameoff); - nameoff += fdt_size_dt_strings(fdt); - prop->nameoff = cpu_to_fdt32(nameoff); - } - offset = nextoffset; - } - if (nextoffset < 0) - return nextoffset; - - /* Finally, adjust the header */ - fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); - fdt_set_magic(fdt, FDT_MAGIC); - return 0; -} diff --git a/components/drivers/fdt/libfdt/fdt_wip.c b/components/drivers/fdt/libfdt/fdt_wip.c deleted file mode 100644 index a817fefdbe..0000000000 --- a/components/drivers/fdt/libfdt/fdt_wip.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" -#include "fdt.h" -#include "libfdt.h" -#include "libfdt_internal.h" - -int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, - const char *name, int namelen, - uint32_t idx, const void *val, - int len) -{ - void *propval; - int proplen; - - propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, - &proplen); - if (!propval) - return proplen; - - if (proplen < (len + idx)) - return -FDT_ERR_NOSPACE; - - memcpy((char *)propval + idx, val, len); - return 0; -} - -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - const void *propval; - int proplen; - - propval = fdt_getprop(fdt, nodeoffset, name, &proplen); - if (! propval) - return proplen; - - if (proplen != len) - return -FDT_ERR_NOSPACE; - - return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, - strlen(name), 0, - val, len); -} - -static void _fdt_nop_region(void *start, int len) -{ - fdt32_t *p; - - for (p = start; (char *)p < ((char *)start + len); p++) - *p = cpu_to_fdt32(FDT_NOP); -} - -int fdt_nop_property(void *fdt, int nodeoffset, const char *name) -{ - struct fdt_property *prop; - int len; - - prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) - return len; - - _fdt_nop_region(prop, len + sizeof(*prop)); - - return 0; -} - -int _fdt_node_end_offset(void *fdt, int offset) -{ - int depth = 0; - - while ((offset >= 0) && (depth >= 0)) - offset = fdt_next_node(fdt, offset, &depth); - - return offset; -} - -int fdt_nop_node(void *fdt, int nodeoffset) -{ - int endoffset; - - endoffset = _fdt_node_end_offset(fdt, nodeoffset); - if (endoffset < 0) - return endoffset; - - _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), - endoffset - nodeoffset); - return 0; -} diff --git a/components/drivers/fdt/libfdt/libfdt.h b/components/drivers/fdt/libfdt/libfdt.h deleted file mode 100644 index 8593f10ae8..0000000000 --- a/components/drivers/fdt/libfdt/libfdt.h +++ /dev/null @@ -1,1883 +0,0 @@ -#ifndef _LIBFDT_H -#define _LIBFDT_H -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libfdt_env.h" -#include "fdt.h" - -#define FDT_FIRST_SUPPORTED_VERSION 0x10 -#define FDT_LAST_SUPPORTED_VERSION 0x11 - -/* Error codes: informative error codes */ -#define FDT_ERR_NOTFOUND 1 - /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ -#define FDT_ERR_EXISTS 2 - /* FDT_ERR_EXISTS: Attempted to create a node or property which - * already exists */ -#define FDT_ERR_NOSPACE 3 - /* FDT_ERR_NOSPACE: Operation needed to expand the device - * tree, but its buffer did not have sufficient space to - * contain the expanded tree. Use fdt_open_into() to move the - * device tree to a buffer with more space. */ - -/* Error codes: codes for bad parameters */ -#define FDT_ERR_BADOFFSET 4 - /* FDT_ERR_BADOFFSET: Function was passed a structure block - * offset which is out-of-bounds, or which points to an - * unsuitable part of the structure for the operation. */ -#define FDT_ERR_BADPATH 5 - /* FDT_ERR_BADPATH: Function was passed a badly formatted path - * (e.g. missing a leading / for a function which requires an - * absolute path) */ -#define FDT_ERR_BADPHANDLE 6 - /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. - * This can be caused either by an invalid phandle property - * length, or the phandle value was either 0 or -1, which are - * not permitted. */ -#define FDT_ERR_BADSTATE 7 - /* FDT_ERR_BADSTATE: Function was passed an incomplete device - * tree created by the sequential-write functions, which is - * not sufficiently complete for the requested operation. */ - -/* Error codes: codes for bad device tree blobs */ -#define FDT_ERR_TRUNCATED 8 - /* FDT_ERR_TRUNCATED: Structure block of the given device tree - * ends without an FDT_END tag. */ -#define FDT_ERR_BADMAGIC 9 - /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a - * device tree at all - it is missing the flattened device - * tree magic number. */ -#define FDT_ERR_BADVERSION 10 - /* FDT_ERR_BADVERSION: Given device tree has a version which - * can't be handled by the requested operation. For - * read-write functions, this may mean that fdt_open_into() is - * required to convert the tree to the expected version. */ -#define FDT_ERR_BADSTRUCTURE 11 - /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt - * structure block or other serious error (e.g. misnested - * nodes, or subnodes preceding properties). */ -#define FDT_ERR_BADLAYOUT 12 - /* FDT_ERR_BADLAYOUT: For read-write functions, the given - * device tree has it's sub-blocks in an order that the - * function can't handle (memory reserve map, then structure, - * then strings). Use fdt_open_into() to reorganize the tree - * into a form suitable for the read-write operations. */ - -/* "Can't happen" error indicating a bug in libfdt */ -#define FDT_ERR_INTERNAL 13 - /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. - * Should never be returned, if it is, it indicates a bug in - * libfdt itself. */ - -/* Errors in device tree content */ -#define FDT_ERR_BADNCELLS 14 - /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells - * or similar property with a bad format or value */ - -#define FDT_ERR_BADVALUE 15 - /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected - * value. For example: a property expected to contain a string list - * is not NUL-terminated within the length of its value. */ - -#define FDT_ERR_BADOVERLAY 16 - /* FDT_ERR_BADOVERLAY: The device tree overlay, while - * correctly structured, cannot be applied due to some - * unexpected or missing value, property or node. */ - -#define FDT_ERR_NOPHANDLES 17 - /* FDT_ERR_NOPHANDLES: The device tree doesn't have any - * phandle available anymore without causing an overflow */ - -#define FDT_ERR_MAX 17 - -/* string.h for POSIX compatibility */ -#include -typedef unsigned int uint; -size_t strnlen (const char *, size_t); -char *strdup (const char *); -char *strchrnul (const char *, int); - -/**********************************************************************/ -/* Low-level functions (you probably don't need these) */ -/**********************************************************************/ - -#ifndef SWIG /* This function is not useful in Python */ -const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); -#endif -static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) -{ - return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); -} - -uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); - -static inline void fdt32_st(void *property, uint32_t value) -{ - uint8_t *bp = (uint8_t *)property; - - bp[0] = value >> 24; - bp[1] = (value >> 16) & 0xff; - bp[2] = (value >> 8) & 0xff; - bp[3] = value & 0xff; -} - -static inline void fdt64_st(void *property, uint64_t value) -{ - uint8_t *bp = (uint8_t *)property; - - bp[0] = value >> 56; - bp[1] = (value >> 48) & 0xff; - bp[2] = (value >> 40) & 0xff; - bp[3] = (value >> 32) & 0xff; - bp[4] = (value >> 24) & 0xff; - bp[5] = (value >> 16) & 0xff; - bp[6] = (value >> 8) & 0xff; - bp[7] = value & 0xff; -} - -/**********************************************************************/ -/* Traversal functions */ -/**********************************************************************/ - -int fdt_next_node(const void *fdt, int offset, int *depth); - -/** - * fdt_first_subnode() - get offset of first direct subnode - * - * @fdt: FDT blob - * @offset: Offset of node to check - * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none - */ -int fdt_first_subnode(const void *fdt, int offset); - -/** - * fdt_next_subnode() - get offset of next direct subnode - * - * After first calling fdt_first_subnode(), call this function repeatedly to - * get direct subnodes of a parent node. - * - * @fdt: FDT blob - * @offset: Offset of previous subnode - * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more - * subnodes - */ -int fdt_next_subnode(const void *fdt, int offset); - -/** - * fdt_for_each_subnode - iterate over all subnodes of a parent - * - * @node: child node (int, lvalue) - * @fdt: FDT blob (const void *) - * @parent: parent node (int) - * - * This is actually a wrapper around a for loop and would be used like so: - * - * fdt_for_each_subnode(node, fdt, parent) { - * Use node - * ... - * } - * - * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { - * Error handling - * } - * - * Note that this is implemented as a macro and @node is used as - * iterator in the loop. The parent variable be constant or even a - * literal. - * - */ -#define fdt_for_each_subnode(node, fdt, parent) \ - for (node = fdt_first_subnode(fdt, parent); \ - node >= 0; \ - node = fdt_next_subnode(fdt, node)) - -/**********************************************************************/ -/* General functions */ -/**********************************************************************/ -#define fdt_get_header(fdt, field) \ - (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) -#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) -#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) -#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) -#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) -#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) -#define fdt_version(fdt) (fdt_get_header(fdt, version)) -#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) -#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) -#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) -#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) - -#define __fdt_set_hdr(name) \ - static inline void fdt_set_##name(void *fdt, uint32_t val) \ - { \ - struct fdt_header *fdth = (struct fdt_header *)fdt; \ - fdth->name = cpu_to_fdt32(val); \ - } -__fdt_set_hdr(magic); -__fdt_set_hdr(totalsize); -__fdt_set_hdr(off_dt_struct); -__fdt_set_hdr(off_dt_strings); -__fdt_set_hdr(off_mem_rsvmap); -__fdt_set_hdr(version); -__fdt_set_hdr(last_comp_version); -__fdt_set_hdr(boot_cpuid_phys); -__fdt_set_hdr(size_dt_strings); -__fdt_set_hdr(size_dt_struct); -#undef __fdt_set_hdr - -/** - * fdt_check_header - sanity check a device tree or possible device tree - * @fdt: pointer to data which might be a flattened device tree - * - * fdt_check_header() checks that the given buffer contains what - * appears to be a flattened device tree with sane information in its - * header. - * - * returns: - * 0, if the buffer appears to contain a valid device tree - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings, as above - */ -int fdt_check_header(const void *fdt); - -/** - * fdt_move - move a device tree around in memory - * @fdt: pointer to the device tree to move - * @buf: pointer to memory where the device is to be moved - * @bufsize: size of the memory space at buf - * - * fdt_move() relocates, if possible, the device tree blob located at - * fdt to the buffer at buf of size bufsize. The buffer may overlap - * with the existing device tree blob at fdt. Therefore, - * fdt_move(fdt, fdt, fdt_totalsize(fdt)) - * should always succeed. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_move(const void *fdt, void *buf, int bufsize); - -/**********************************************************************/ -/* Read-only functions */ -/**********************************************************************/ - -/** - * fdt_string - retrieve a string from the strings block of a device tree - * @fdt: pointer to the device tree blob - * @stroffset: offset of the string within the strings block (native endian) - * - * fdt_string() retrieves a pointer to a single string from the - * strings block of the device tree blob at fdt. - * - * returns: - * a pointer to the string, on success - * NULL, if stroffset is out of bounds - */ -const char *fdt_string(const void *fdt, int stroffset); - -/** - * fdt_get_max_phandle - retrieves the highest phandle in a tree - * @fdt: pointer to the device tree blob - * - * fdt_get_max_phandle retrieves the highest phandle in the given - * device tree. This will ignore badly formatted phandles, or phandles - * with a value of 0 or -1. - * - * returns: - * the highest phandle on success - * 0, if no phandle was found in the device tree - * -1, if an error occurred - */ -uint32_t fdt_get_max_phandle(const void *fdt); - -/** - * fdt_num_mem_rsv - retrieve the number of memory reserve map entries - * @fdt: pointer to the device tree blob - * - * Returns the number of entries in the device tree blob's memory - * reservation map. This does not include the terminating 0,0 entry - * or any other (0,0) entries reserved for expansion. - * - * returns: - * the number of entries - */ -int fdt_num_mem_rsv(const void *fdt); - -/** - * fdt_get_mem_rsv - retrieve one memory reserve map entry - * @fdt: pointer to the device tree blob - * @address, @size: pointers to 64-bit variables - * - * On success, *address and *size will contain the address and size of - * the n-th reserve map entry from the device tree blob, in - * native-endian format. - * - * returns: - * 0, on success - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); - -/** - * fdt_subnode_offset_namelen - find a subnode based on substring - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * @namelen: number of characters of name to consider - * - * Identical to fdt_subnode_offset(), but only examine the first - * namelen characters of name for matching the subnode name. This is - * useful for finding subnodes based on a portion of a larger string, - * such as a full path. - */ -#ifndef SWIG /* Not available in Python */ -int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, - const char *name, int namelen); -#endif -/** - * fdt_subnode_offset - find a subnode of a given node - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * - * fdt_subnode_offset() finds a subnode of the node at structure block - * offset parentoffset with the given name. name may include a unit - * address, in which case fdt_subnode_offset() will find the subnode - * with that unit address, or the unit address may be omitted, in - * which case fdt_subnode_offset() will find an arbitrary subnode - * whose name excluding unit address matches the given name. - * - * returns: - * structure block offset of the requested subnode (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist - * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE - * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); - -/** - * fdt_path_offset_namelen - find a tree node by its full path - * @fdt: pointer to the device tree blob - * @path: full path of the node to locate - * @namelen: number of characters of path to consider - * - * Identical to fdt_path_offset(), but only consider the first namelen - * characters of path as the path name. - */ -#ifndef SWIG /* Not available in Python */ -int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); -#endif - -/** - * fdt_path_offset - find a tree node by its full path - * @fdt: pointer to the device tree blob - * @path: full path of the node to locate - * - * fdt_path_offset() finds a node of a given path in the device tree. - * Each path component may omit the unit address portion, but the - * results of this are undefined if any such path component is - * ambiguous (that is if there are multiple nodes at the relevant - * level matching the given component, differentiated only by unit - * address). - * - * returns: - * structure block offset of the node with the requested path (>=0), on - * success - * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid - * -FDT_ERR_NOTFOUND, if the requested node does not exist - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_path_offset(const void *fdt, const char *path); - -/** - * fdt_get_name - retrieve the name of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of the starting node - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_name() retrieves the name (including unit address) of the - * device tree node at structure block offset nodeoffset. If lenp is - * non-NULL, the length of this name is also returned, in the integer - * pointed to by lenp. - * - * returns: - * pointer to the node's name, on success - * If lenp is non-NULL, *lenp contains the length of that name - * (>=0) - * NULL, on error - * if lenp is non-NULL *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE - * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); - -/** - * fdt_first_property_offset - find the offset of a node's first property - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of a node - * - * fdt_first_property_offset() finds the first property of the node at - * the given structure block offset. - * - * returns: - * structure block offset of the property (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested node has no properties - * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_first_property_offset(const void *fdt, int nodeoffset); - -/** - * fdt_next_property_offset - step through a node's properties - * @fdt: pointer to the device tree blob - * @offset: structure block offset of a property - * - * fdt_next_property_offset() finds the property immediately after the - * one at the given structure block offset. This will be a property - * of the same node as the given property. - * - * returns: - * structure block offset of the next property (>=0), on success - * -FDT_ERR_NOTFOUND, if the given property is the last in its node - * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_next_property_offset(const void *fdt, int offset); - -/** - * fdt_for_each_property_offset - iterate over all properties of a node - * - * @property_offset: property offset (int, lvalue) - * @fdt: FDT blob (const void *) - * @node: node offset (int) - * - * This is actually a wrapper around a for loop and would be used like so: - * - * fdt_for_each_property_offset(property, fdt, node) { - * Use property - * ... - * } - * - * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { - * Error handling - * } - * - * Note that this is implemented as a macro and property is used as - * iterator in the loop. The node variable can be constant or even a - * literal. - */ -#define fdt_for_each_property_offset(property, fdt, node) \ - for (property = fdt_first_property_offset(fdt, node); \ - property >= 0; \ - property = fdt_next_property_offset(fdt, property)) - -/** - * fdt_get_property_by_offset - retrieve the property at a given offset - * @fdt: pointer to the device tree blob - * @offset: offset of the property to retrieve - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_property_by_offset() retrieves a pointer to the - * fdt_property structure within the device tree blob at the given - * offset. If lenp is non-NULL, the length of the property value is - * also returned, in the integer pointed to by lenp. - * - * returns: - * pointer to the structure representing the property - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - int offset, - int *lenp); - -/** - * fdt_get_property_namelen - find a property based on substring - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @namelen: number of characters of name to consider - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * Identical to fdt_get_property(), but only examine the first namelen - * characters of name for matching the property name. - */ -#ifndef SWIG /* Not available in Python */ -const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int nodeoffset, - const char *name, - int namelen, int *lenp); -#endif - -/** - * fdt_get_property - find a given property in a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_property() retrieves a pointer to the fdt_property - * structure within the device tree blob corresponding to the property - * named 'name' of the node at offset nodeoffset. If lenp is - * non-NULL, the length of the property value is also returned, in the - * integer pointed to by lenp. - * - * returns: - * pointer to the structure representing the property - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE - * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, - const char *name, int *lenp); -static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, - const char *name, - int *lenp) -{ - return (struct fdt_property *)(uintptr_t) - fdt_get_property(fdt, nodeoffset, name, lenp); -} - -/** - * fdt_getprop_by_offset - retrieve the value of a property at a given offset - * @fdt: pointer to the device tree blob - * @ffset: offset of the property to read - * @namep: pointer to a string variable (will be overwritten) or NULL - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_getprop_by_offset() retrieves a pointer to the value of the - * property at structure block offset 'offset' (this will be a pointer - * to within the device blob itself, not a copy of the value). If - * lenp is non-NULL, the length of the property value is also - * returned, in the integer pointed to by lenp. If namep is non-NULL, - * the property's namne will also be returned in the char * pointed to - * by namep (this will be a pointer to within the device tree's string - * block, not a new copy of the name). - * - * returns: - * pointer to the property's value - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * if namep is non-NULL *namep contiains a pointer to the property - * name. - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#ifndef SWIG /* This function is not useful in Python */ -const void *fdt_getprop_by_offset(const void *fdt, int offset, - const char **namep, int *lenp); -#endif - -/** - * fdt_getprop_namelen - get property value based on substring - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @namelen: number of characters of name to consider - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * Identical to fdt_getprop(), but only examine the first namelen - * characters of name for matching the property name. - */ -#ifndef SWIG /* Not available in Python */ -const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, - const char *name, int namelen, int *lenp); -static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, - const char *name, int namelen, - int *lenp) -{ - return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, - namelen, lenp); -} -#endif - -/** - * fdt_getprop - retrieve the value of a given property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_getprop() retrieves a pointer to the value of the property - * named 'name' of the node at offset nodeoffset (this will be a - * pointer to within the device blob itself, not a copy of the value). - * If lenp is non-NULL, the length of the property value is also - * returned, in the integer pointed to by lenp. - * - * returns: - * pointer to the property's value - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE - * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const void *fdt_getprop(const void *fdt, int nodeoffset, - const char *name, int *lenp); -static inline void *fdt_getprop_w(void *fdt, int nodeoffset, - const char *name, int *lenp) -{ - return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); -} - -/** - * fdt_get_phandle - retrieve the phandle of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of the node - * - * fdt_get_phandle() retrieves the phandle of the device tree node at - * structure block offset nodeoffset. - * - * returns: - * the phandle of the node at nodeoffset, on success (!= 0, != -1) - * 0, if the node has no phandle, or another error occurs - */ -uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); - -/** - * fdt_get_alias_namelen - get alias based on substring - * @fdt: pointer to the device tree blob - * @name: name of the alias th look up - * @namelen: number of characters of name to consider - * - * Identical to fdt_get_alias(), but only examine the first namelen - * characters of name for matching the alias name. - */ -#ifndef SWIG /* Not available in Python */ -const char *fdt_get_alias_namelen(const void *fdt, - const char *name, int namelen); -#endif - -/** - * fdt_get_alias - retrieve the path referenced by a given alias - * @fdt: pointer to the device tree blob - * @name: name of the alias th look up - * - * fdt_get_alias() retrieves the value of a given alias. That is, the - * value of the property named 'name' in the node /aliases. - * - * returns: - * a pointer to the expansion of the alias named 'name', if it exists - * NULL, if the given alias or the /aliases node does not exist - */ -const char *fdt_get_alias(const void *fdt, const char *name); - -/** - * fdt_get_path - determine the full path of a node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose path to find - * @buf: character buffer to contain the returned path (will be overwritten) - * @buflen: size of the character buffer at buf - * - * fdt_get_path() computes the full path of the node at offset - * nodeoffset, and records that path in the buffer at buf. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * 0, on success - * buf contains the absolute path of the node at - * nodeoffset, as a NUL-terminated string. - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) - * characters and will not fit in the given buffer. - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); - -/** - * fdt_supernode_atdepth_offset - find a specific ancestor of a node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * @supernodedepth: depth of the ancestor to find - * @nodedepth: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_supernode_atdepth_offset() finds an ancestor of the given node - * at a specific depth from the root (where the root itself has depth - * 0, its immediate subnodes depth 1 and so forth). So - * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); - * will always return 0, the offset of the root node. If the node at - * nodeoffset has depth D, then: - * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); - * will return nodeoffset itself. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * structure block offset of the node at node offset's ancestor - * of depth supernodedepth (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of - * nodeoffset - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, - int supernodedepth, int *nodedepth); - -/** - * fdt_node_depth - find the depth of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * - * fdt_node_depth() finds the depth of a given node. The root node - * has depth 0, its immediate subnodes depth 1 and so forth. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * depth of the node at nodeoffset (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_depth(const void *fdt, int nodeoffset); - -/** - * fdt_parent_offset - find the parent of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * - * fdt_parent_offset() locates the parent node of a given node (that - * is, it finds the offset of the node which contains the node at - * nodeoffset as a subnode). - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset, *twice*. - * - * returns: - * structure block offset of the parent of the node at nodeoffset - * (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_parent_offset(const void *fdt, int nodeoffset); - -/** - * fdt_node_offset_by_prop_value - find nodes with a given property value - * @fdt: pointer to the device tree blob - * @startoffset: only find nodes after this offset - * @propname: property name to check - * @propval: property value to search for - * @proplen: length of the value in propval - * - * fdt_node_offset_by_prop_value() returns the offset of the first - * node after startoffset, which has a property named propname whose - * value is of length proplen and has value equal to propval; or if - * startoffset is -1, the very first such node in the tree. - * - * To iterate through all nodes matching the criterion, the following - * idiom can be used: - * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, - * propval, proplen); - * while (offset != -FDT_ERR_NOTFOUND) { - * // other code here - * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, - * propval, proplen); - * } - * - * Note the -1 in the first call to the function, if 0 is used here - * instead, the function will never locate the root node, even if it - * matches the criterion. - * - * returns: - * structure block offset of the located node (>= 0, >startoffset), - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, - const char *propname, - const void *propval, int proplen); - -/** - * fdt_node_offset_by_phandle - find the node with a given phandle - * @fdt: pointer to the device tree blob - * @phandle: phandle value - * - * fdt_node_offset_by_phandle() returns the offset of the node - * which has the given phandle value. If there is more than one node - * in the tree with the given phandle (an invalid tree), results are - * undefined. - * - * returns: - * structure block offset of the located node (>= 0), on success - * -FDT_ERR_NOTFOUND, no node with that phandle exists - * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); - -/** - * fdt_node_check_compatible: check a node's compatible property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @compatible: string to match against - * - * - * fdt_node_check_compatible() returns 0 if the given node contains a - * 'compatible' property with the given string as one of its elements, - * it returns non-zero otherwise, or on error. - * - * returns: - * 0, if the node has a 'compatible' property listing the given string - * 1, if the node has a 'compatible' property, but it does not list - * the given string - * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property - * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_check_compatible(const void *fdt, int nodeoffset, - const char *compatible); - -/** - * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value - * @fdt: pointer to the device tree blob - * @startoffset: only find nodes after this offset - * @compatible: 'compatible' string to match against - * - * fdt_node_offset_by_compatible() returns the offset of the first - * node after startoffset, which has a 'compatible' property which - * lists the given compatible string; or if startoffset is -1, the - * very first such node in the tree. - * - * To iterate through all nodes matching the criterion, the following - * idiom can be used: - * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); - * while (offset != -FDT_ERR_NOTFOUND) { - * // other code here - * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); - * } - * - * Note the -1 in the first call to the function, if 0 is used here - * instead, the function will never locate the root node, even if it - * matches the criterion. - * - * returns: - * structure block offset of the located node (>= 0, >startoffset), - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_compatible(const void *fdt, int startoffset, - const char *compatible); - -/** - * fdt_stringlist_contains - check a string list property for a string - * @strlist: Property containing a list of strings to check - * @listlen: Length of property - * @str: String to search for - * - * This is a utility function provided for convenience. The list contains - * one or more strings, each terminated by \0, as is found in a device tree - * "compatible" property. - * - * @return: 1 if the string is found in the list, 0 not found, or invalid list - */ -int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); - -/** - * fdt_stringlist_count - count the number of strings in a string list - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @property: name of the property containing the string list - * @return: - * the number of strings in the given property - * -FDT_ERR_BADVALUE if the property value is not NUL-terminated - * -FDT_ERR_NOTFOUND if the property does not exist - */ -int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); - -/** - * fdt_stringlist_search - find a string in a string list and return its index - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @property: name of the property containing the string list - * @string: string to look up in the string list - * - * Note that it is possible for this function to succeed on property values - * that are not NUL-terminated. That's because the function will stop after - * finding the first occurrence of @string. This can for example happen with - * small-valued cell properties, such as #address-cells, when searching for - * the empty string. - * - * @return: - * the index of the string in the list of strings - * -FDT_ERR_BADVALUE if the property value is not NUL-terminated - * -FDT_ERR_NOTFOUND if the property does not exist or does not contain - * the given string - */ -int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, - const char *string); - -/** - * fdt_stringlist_get() - obtain the string at a given index in a string list - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @property: name of the property containing the string list - * @index: index of the string to return - * @lenp: return location for the string length or an error code on failure - * - * Note that this will successfully extract strings from properties with - * non-NUL-terminated values. For example on small-valued cell properties - * this function will return the empty string. - * - * If non-NULL, the length of the string (on success) or a negative error-code - * (on failure) will be stored in the integer pointer to by lenp. - * - * @return: - * A pointer to the string at the given index in the string list or NULL on - * failure. On success the length of the string will be stored in the memory - * location pointed to by the lenp parameter, if non-NULL. On failure one of - * the following negative error codes will be returned in the lenp parameter - * (if non-NULL): - * -FDT_ERR_BADVALUE if the property value is not NUL-terminated - * -FDT_ERR_NOTFOUND if the property does not exist - */ -const char *fdt_stringlist_get(const void *fdt, int nodeoffset, - const char *property, int index, - int *lenp); - -/**********************************************************************/ -/* Read-only functions (addressing related) */ -/**********************************************************************/ - -/** - * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells - * - * This is the maximum value for #address-cells, #size-cells and - * similar properties that will be processed by libfdt. IEE1275 - * requires that OF implementations handle values up to 4. - * Implementations may support larger values, but in practice higher - * values aren't used. - */ -#define FDT_MAX_NCELLS 4 - -/** - * fdt_address_cells - retrieve address size for a bus represented in the tree - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to find the address size for - * - * When the node has a valid #address-cells property, returns its value. - * - * returns: - * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property - * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid - * #address-cells property - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_address_cells(const void *fdt, int nodeoffset); - -/** - * fdt_size_cells - retrieve address range size for a bus represented in the - * tree - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to find the address range size for - * - * When the node has a valid #size-cells property, returns its value. - * - * returns: - * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property - * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid - * #size-cells property - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_size_cells(const void *fdt, int nodeoffset); - - -/**********************************************************************/ -/* Write-in-place functions */ -/**********************************************************************/ - -/** - * fdt_setprop_inplace_namelen_partial - change a property's value, - * but not its size - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @namelen: number of characters of name to consider - * @idx: index of the property to change in the array - * @val: pointer to data to replace the property value with - * @len: length of the property value - * - * Identical to fdt_setprop_inplace(), but modifies the given property - * starting from the given index, and using only the first characters - * of the name. It is useful when you want to manipulate only one value of - * an array and you have a string that doesn't end with \0. - */ -#ifndef SWIG /* Not available in Python */ -int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, - const char *name, int namelen, - uint32_t idx, const void *val, - int len); -#endif - -/** - * fdt_setprop_inplace - change a property's value, but not its size - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: pointer to data to replace the property value with - * @len: length of the property value - * - * fdt_setprop_inplace() replaces the value of a given property with - * the data in val, of length len. This function cannot change the - * size of a property, and so will only work if len is equal to the - * current length of the property. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if len is not equal to the property's current length - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#ifndef SWIG /* Not available in Python */ -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, - const void *val, int len); -#endif - -/** - * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value to replace the property with - * - * fdt_setprop_inplace_u32() replaces the value of a given property - * with the 32-bit integer value in val, converting val to big-endian - * if necessary. This function cannot change the size of a property, - * and so will only work if the property already exists and has length - * 4. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - fdt32_t tmp = cpu_to_fdt32(val); - return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 64-bit integer value to replace the property with - * - * fdt_setprop_inplace_u64() replaces the value of a given property - * with the 64-bit integer value in val, converting val to big-endian - * if necessary. This function cannot change the size of a property, - * and so will only work if the property already exists and has length - * 8. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, - const char *name, uint64_t val) -{ - fdt64_t tmp = cpu_to_fdt64(val); - return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_setprop_inplace_cell - change the value of a single-cell property - * - * This is an alternative name for fdt_setprop_inplace_u32() - */ -static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); -} - -/** - * fdt_nop_property - replace a property with nop tags - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to nop - * @name: name of the property to nop - * - * fdt_nop_property() will replace a given property's representation - * in the blob with FDT_NOP tags, effectively removing it from the - * tree. - * - * This function will alter only the bytes in the blob which contain - * the property, and will not alter or move any other part of the - * tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_nop_property(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_nop_node - replace a node (subtree) with nop tags - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to nop - * - * fdt_nop_node() will replace a given node's representation in the - * blob, including all its subnodes, if any, with FDT_NOP tags, - * effectively removing it from the tree. - * - * This function will alter only the bytes in the blob which contain - * the node and its properties and subnodes, and will not alter or - * move any other part of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_nop_node(void *fdt, int nodeoffset); - -/**********************************************************************/ -/* Sequential write functions */ -/**********************************************************************/ - -int fdt_create(void *buf, int bufsize); -int fdt_resize(void *fdt, void *buf, int bufsize); -int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); -int fdt_finish_reservemap(void *fdt); -int fdt_begin_node(void *fdt, const char *name); -int fdt_property(void *fdt, const char *name, const void *val, int len); -static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) -{ - fdt32_t tmp = cpu_to_fdt32(val); - return fdt_property(fdt, name, &tmp, sizeof(tmp)); -} -static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) -{ - fdt64_t tmp = cpu_to_fdt64(val); - return fdt_property(fdt, name, &tmp, sizeof(tmp)); -} -static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) -{ - return fdt_property_u32(fdt, name, val); -} -#define fdt_property_string(fdt, name, str) \ - fdt_property(fdt, name, str, strlen(str)+1) -int fdt_end_node(void *fdt); -int fdt_finish(void *fdt); - -/**********************************************************************/ -/* Read-write functions */ -/**********************************************************************/ - -int fdt_create_empty_tree(void *buf, int bufsize); -int fdt_open_into(const void *fdt, void *buf, int bufsize); -int fdt_pack(void *fdt); - -/** - * fdt_add_mem_rsv - add one memory reserve map entry - * @fdt: pointer to the device tree blob - * @address, @size: 64-bit values (native endian) - * - * Adds a reserve map entry to the given blob reserving a region at - * address address of length size. - * - * This function will insert data into the reserve map and will - * therefore change the indexes of some entries in the table. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new reservation entry - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); - -/** - * fdt_del_mem_rsv - remove a memory reserve map entry - * @fdt: pointer to the device tree blob - * @n: entry to remove - * - * fdt_del_mem_rsv() removes the n-th memory reserve map entry from - * the blob. - * - * This function will delete data from the reservation table and will - * therefore change the indexes of some entries in the table. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there - * are less than n+1 reserve map entries) - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_del_mem_rsv(void *fdt, int n); - -/** - * fdt_set_name - change the name of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of a node - * @name: name to give the node - * - * fdt_set_name() replaces the name (including unit address, if any) - * of the given node with the given string. NOTE: this function can't - * efficiently check if the new name is unique amongst the given - * node's siblings; results are undefined if this function is invoked - * with a name equal to one of the given node's siblings. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob - * to contain the new name - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_set_name(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_setprop - create or change a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: pointer to data to set the property value to - * @len: length of the property value - * - * fdt_setprop() sets the value of the named property in the given - * node to the given value and length, creating the property if it - * does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len); - -/** - * fdt_setprop_u32 - set a property to a 32-bit integer - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value for the property (native endian) - * - * fdt_setprop_u32() sets the value of the named property in the given - * node to the given 32-bit integer value (converting to big-endian if - * necessary), or creates a new property with that value if it does - * not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, - uint32_t val) -{ - fdt32_t tmp = cpu_to_fdt32(val); - return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_setprop_u64 - set a property to a 64-bit integer - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 64-bit integer value for the property (native endian) - * - * fdt_setprop_u64() sets the value of the named property in the given - * node to the given 64-bit integer value (converting to big-endian if - * necessary), or creates a new property with that value if it does - * not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, - uint64_t val) -{ - fdt64_t tmp = cpu_to_fdt64(val); - return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_setprop_cell - set a property to a single cell value - * - * This is an alternative name for fdt_setprop_u32() - */ -static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, - uint32_t val) -{ - return fdt_setprop_u32(fdt, nodeoffset, name, val); -} - -/** - * fdt_setprop_string - set a property to a string value - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @str: string value for the property - * - * fdt_setprop_string() sets the value of the named property in the - * given node to the given string value (using the length of the - * string to determine the new length of the property), or creates a - * new property with that value if it does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#define fdt_setprop_string(fdt, nodeoffset, name, str) \ - fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) - - -/** - * fdt_setprop_empty - set a property to an empty value - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * - * fdt_setprop_empty() sets the value of the named property in the - * given node to an empty (zero length) value, or creates a new empty - * property if it does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#define fdt_setprop_empty(fdt, nodeoffset, name) \ - fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) - -/** - * fdt_appendprop - append to or create a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to append to - * @val: pointer to data to append to the property value - * @len: length of the data to append to the property value - * - * fdt_appendprop() appends the value to the named property in the - * given node, creating the property if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_appendprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len); - -/** - * fdt_appendprop_u32 - append a 32-bit integer value to a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value to append to the property (native endian) - * - * fdt_appendprop_u32() appends the given 32-bit integer value - * (converting to big-endian if necessary) to the value of the named - * property in the given node, or creates a new property with that - * value if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - fdt32_t tmp = cpu_to_fdt32(val); - return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_appendprop_u64 - append a 64-bit integer value to a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 64-bit integer value to append to the property (native endian) - * - * fdt_appendprop_u64() appends the given 64-bit integer value - * (converting to big-endian if necessary) to the value of the named - * property in the given node, or creates a new property with that - * value if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, - const char *name, uint64_t val) -{ - fdt64_t tmp = cpu_to_fdt64(val); - return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_appendprop_cell - append a single cell value to a property - * - * This is an alternative name for fdt_appendprop_u32() - */ -static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - return fdt_appendprop_u32(fdt, nodeoffset, name, val); -} - -/** - * fdt_appendprop_string - append a string to a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @str: string value to append to the property - * - * fdt_appendprop_string() appends the given string to the value of - * the named property in the given node, or creates a new property - * with that value if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ - fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) - -/** - * fdt_delprop - delete a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to nop - * @name: name of the property to nop - * - * fdt_del_property() will delete the given property. - * - * This function will delete data from the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_delprop(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_add_subnode_namelen - creates a new node based on substring - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * @namelen: number of characters of name to consider - * - * Identical to fdt_add_subnode(), but use only the first namelen - * characters of name as the name of the new node. This is useful for - * creating subnodes based on a portion of a larger string, such as a - * full path. - */ -#ifndef SWIG /* Not available in Python */ -int fdt_add_subnode_namelen(void *fdt, int parentoffset, - const char *name, int namelen); -#endif - -/** - * fdt_add_subnode - creates a new node - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * - * fdt_add_subnode() creates a new node as a subnode of the node at - * structure block offset parentoffset, with the given name (which - * should include the unit address, if any). - * - * This function will insert data into the blob, and will therefore - * change the offsets of some existing nodes. - - * returns: - * structure block offset of the created nodeequested subnode (>=0), on - * success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist - * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE - * tag - * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of - * the given name - * -FDT_ERR_NOSPACE, if there is insufficient free space in the - * blob to contain the new node - * -FDT_ERR_NOSPACE - * -FDT_ERR_BADLAYOUT - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_add_subnode(void *fdt, int parentoffset, const char *name); - -/** - * fdt_del_node - delete a node (subtree) - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to nop - * - * fdt_del_node() will remove the given node, including all its - * subnodes if any, from the blob. - * - * This function will delete data from the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_del_node(void *fdt, int nodeoffset); - -/** - * fdt_overlay_apply - Applies a DT overlay on a base DT - * @fdt: pointer to the base device tree blob - * @fdto: pointer to the device tree overlay blob - * - * fdt_overlay_apply() will apply the given device tree overlay on the - * given base device tree. - * - * Expect the base device tree to be modified, even if the function - * returns an error. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there's not enough space in the base device tree - * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or - * properties in the base DT - * -FDT_ERR_BADPHANDLE, - * -FDT_ERR_BADOVERLAY, - * -FDT_ERR_NOPHANDLES, - * -FDT_ERR_INTERNAL, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADOFFSET, - * -FDT_ERR_BADPATH, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_overlay_apply(void *fdt, void *fdto); - -/**********************************************************************/ -/* Debugging / informational functions */ -/**********************************************************************/ - -const char *fdt_strerror(int errval); - -#endif /* _LIBFDT_H */ diff --git a/components/drivers/fdt/libfdt/libfdt_env.h b/components/drivers/fdt/libfdt/libfdt_env.h deleted file mode 100644 index 3acc87f2bb..0000000000 --- a/components/drivers/fdt/libfdt/libfdt_env.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef _LIBFDT_ENV_H -#define _LIBFDT_ENV_H -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * Copyright 2012 Kim Phillips, Freescale Semiconductor. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#ifdef __CHECKER__ -#define FDT_FORCE __attribute__((force)) -#define FDT_BITWISE __attribute__((bitwise)) -#else -#define FDT_FORCE -#define FDT_BITWISE -#endif - -typedef uint16_t FDT_BITWISE fdt16_t; -typedef uint32_t FDT_BITWISE fdt32_t; -typedef uint64_t FDT_BITWISE fdt64_t; -typedef uint64_t unaligned_fdt64_t __attribute__((aligned(4))); - -#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) -#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) -#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ - (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) -#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ - (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ - (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ - (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) - -static inline uint16_t fdt16_to_cpu(fdt16_t x) -{ - return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); -} -static inline fdt16_t cpu_to_fdt16(uint16_t x) -{ - return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); -} - -static inline uint32_t fdt32_to_cpu(fdt32_t x) -{ - return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); -} -static inline fdt32_t cpu_to_fdt32(uint32_t x) -{ - return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); -} - -static inline uint64_t fdt64_to_cpu(fdt64_t x) -{ - return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); -} -static inline fdt64_t cpu_to_fdt64(uint64_t x) -{ - return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); -} -#undef CPU_TO_FDT64 -#undef CPU_TO_FDT32 -#undef CPU_TO_FDT16 -#undef EXTRACT_BYTE - -#endif /* _LIBFDT_ENV_H */ diff --git a/components/drivers/fdt/libfdt/libfdt_internal.h b/components/drivers/fdt/libfdt/libfdt_internal.h deleted file mode 100644 index b813e58167..0000000000 --- a/components/drivers/fdt/libfdt/libfdt_internal.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _LIBFDT_INTERNAL_H -#define _LIBFDT_INTERNAL_H -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "fdt.h" - -#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) - -#define FDT_CHECK_HEADER(fdt) \ - { \ - int __err; \ - if ((__err = fdt_check_header(fdt)) != 0) \ - return __err; \ - } - -int _fdt_check_node_offset(const void *fdt, int offset); -int _fdt_check_prop_offset(const void *fdt, int offset); -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); -int _fdt_node_end_offset(void *fdt, int nodeoffset); - -static inline const void *_fdt_offset_ptr(const void *fdt, int offset) -{ - return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; -} - -static inline void *_fdt_offset_ptr_w(void *fdt, int offset) -{ - return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); -} - -static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) -{ - const struct fdt_reserve_entry *rsv_table = - (const struct fdt_reserve_entry *) - ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); - - return rsv_table + n; -} -static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) -{ - return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); -} - -#define FDT_SW_MAGIC (~FDT_MAGIC) - -#endif /* _LIBFDT_INTERNAL_H */ diff --git a/components/drivers/fdt/src/SConscript b/components/drivers/fdt/src/SConscript deleted file mode 100644 index 23f4af644e..0000000000 --- a/components/drivers/fdt/src/SConscript +++ /dev/null @@ -1,17 +0,0 @@ -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -list = os.listdir(cwd) -CPPPATH = [cwd + '/../inc' , cwd + '/libfdt'] -objs = [] - -group = DefineGroup('FDT', src, depend = ['RT_USING_FDT'], CPPPATH = CPPPATH) - -for d in list: - path = os.path.join(cwd, d) - if os.path.isfile(os.path.join(path, 'SConscript')): - objs = objs + SConscript(os.path.join(d, 'SConscript')) -objs = objs + group - -Return('objs') diff --git a/components/drivers/fdt/src/dtb_access.c b/components/drivers/fdt/src/dtb_access.c deleted file mode 100644 index e80192e7b4..0000000000 --- a/components/drivers/fdt/src/dtb_access.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "libfdt.h" -#include "dtb_node.h" - -/* "/aliaes" node */ -static struct dtb_node *fdt_aliases; - -/** - * of_find_property_value_of_size() - find property of given size - * - * Search for a property in a device node and validate the requested size. - * - * @np: device node from which the property value is to be read. - * @propname: name of the property to be searched. - * @len: requested length of property value - * - * @return the property value on success, -EINVAL if the property does not - * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the - * property data isn't large enough. - */ -static void *dtb_node_find_property_value_of_size(const struct dtb_node *dn, - const char *propname, uint32_t len) -{ - struct dtb_property *prop = dtb_node_get_dtb_node_property(dn, propname, NULL); - - if (!prop) - return ERR_PTR(-EINVAL); - if (!prop->value) - return ERR_PTR(-ENODATA); - if (len > prop->size) - return ERR_PTR(-EOVERFLOW); - return prop->value; -} - -int dtb_node_read_u32(const struct dtb_node *dn, const char *propname, uint32_t *outp) -{ - const uint32_t *val; - - debug("%s: %s: \n", __func__, propname); - if (!dn) - return -EINVAL; - val = dtb_node_find_property_value_of_size(dn, propname, sizeof(*outp)); - if (IS_ERR(val)) - { - debug("(not found)\n"); - return PTR_ERR(val); - } - - *outp = fdt32_to_cpu(*val); - debug("%#x (%d)\n", *outp, *outp); - - return 0; -} - -uint32_t dtb_node_read_u32_default(const struct dtb_node *node, const char *propname, uint32_t def) -{ - dtb_node_read_u32(node, propname, &def); - - return def; -} - -int dtb_node_read_u32_array(const struct dtb_node *dn, const char *propname, - uint32_t *out_values, size_t sz) -{ - const uint32_t *val; - - debug("%s: %s: ", __func__, propname); - val = dtb_node_find_property_value_of_size(dn, propname, - sz * sizeof(*out_values)); - - if (IS_ERR(val)) - return PTR_ERR(val); - - debug("size %zd, val:%d\n", sz, *val); - while (sz--) - *out_values++ = fdt32_to_cpu(*val++); - - return 0; -} - -uint32_t dtb_node_read_u32_index_default(const struct dtb_node *node, const char *propname, int index, - uint32_t def) -{ - RT_ASSERT(dtb_node_valid(node)); - dtb_node_read_u32_index(node, propname, index, &def); - - return def; -} - -int dtb_node_read_s32_default(const struct dtb_node *node, const char *propname, int32_t def) -{ - RT_ASSERT(dtb_node_valid(node)); - dtb_node_read_u32(node, propname, (uint32_t *)&def); - - return def; -} - -int dtb_node_read_u32_index(const struct dtb_node *dn, const char *propname, - int index, uint32_t *outp) -{ - const uint32_t *val; - - debug("%s: %s: ", __func__, propname); - if (!dn) - return -EINVAL; - - val = dtb_node_find_property_value_of_size(dn, propname, - sizeof(*outp) * (index + 1)); - if (IS_ERR(val)) - { - debug("(not found)\n"); - return PTR_ERR(val); - } - - *outp = fdt32_to_cpu(val[index]); - debug("%#x (%d)\n", *outp, *outp); - - return 0; -} - -int dtb_node_read_u64(const struct dtb_node *dn, const char *propname, uint64_t *outp) -{ - const uint64_t *val; - - debug("%s: %s: ", __func__, propname); - if (!dn) - return -EINVAL; - val = dtb_node_find_property_value_of_size(dn, propname, sizeof(*outp)); - if (IS_ERR(val)) - { - debug("(not found)\n"); - return PTR_ERR(val); - } - - *outp = fdt64_to_cpu(*val); - debug("%#llx (%lld)\n", (unsigned long long)*outp, - (unsigned long long)*outp); - - return 0; -} - -uint64_t dtb_node_read_u64_default(const struct dtb_node *node, const char *propname, uint64_t def) -{ - RT_ASSERT(dtb_node_valid(node)); - dtb_node_read_u64(node, propname, &def); - - return def; -} - -int dtb_node_n_addr_cells(const struct dtb_node *dn) -{ - const uint32_t *ip; - - do - { - if (dn->parent) - dn = dn->parent; - ip = dtb_node_get_dtb_node_property_value(dn, "#address-cells", NULL); - if (ip) - return fdt32_to_cpu(*ip); - } while (dn->parent); - - /* No #address-cells property for the root node */ - return DEV_ROOT_NODE_ADDR_CELLS_DEFAULT; -} - -int dtb_node_n_size_cells(const struct dtb_node *dn) -{ - const uint32_t *ip; - - do - { - if (dn->parent) - dn = dn->parent; - ip = dtb_node_get_dtb_node_property_value(dn, "#size-cells", NULL); - if (ip) - return fdt32_to_cpu(*ip); - } while (dn->parent); - - /* No #size-cells property for the root node */ - return DEV_ROOT_NODE_SIZE_CELLS_DEFAULT; -} - -int dtb_node_simple_addr_cells(const struct dtb_node *dn) -{ - const uint32_t *ip; - - ip = dtb_node_get_dtb_node_property_value(dn, "#address-cells", NULL); - if (ip) - return fdt32_to_cpu(*ip); - - /* Return a default of 2 to match fdt_address_cells()*/ - return 2; -} - -int dtb_node_simple_size_cells(const struct dtb_node *dn) -{ - const uint32_t *ip; - - ip = dtb_node_get_dtb_node_property_value(dn, "#size-cells", NULL); - if (ip) - return fdt32_to_cpu(*ip); - - /* Return a default of 2 to match fdt_size_cells()*/ - return 2; -} - -struct dtb_property *dtb_node_get_dtb_node_property(const struct dtb_node *dtb_node, const char *property_name, int *property_size) -{ - struct dtb_property *dtb_property = NULL; - - if (dtb_node != NULL && property_name != NULL) - { - dtb_property = dtb_node->properties; - - while (dtb_property != NULL) - { - if (!strcmp(dtb_property->name, property_name)) - { - if (property_size != NULL) - { - *property_size = dtb_property->size; - } - return dtb_property; - } - dtb_property = dtb_property->next; - } - } - - return dtb_property; -} - -#define for_each_property_of_node(dn, pp) \ - for (pp = dn->properties; pp != NULL; pp = pp->next) - -struct dtb_node *dtb_node_find_node_opts_by_path(const char *path, - const char **opts) -{ - struct dtb_node *np = NULL; - struct dtb_property *pp; - const char *separator = strchr(path, ':'); - - if (opts) - *opts = separator ? separator + 1 : NULL; - - if (strcmp(path, "/") == 0) - return dtb_node_get(get_dtb_node_head()); - - /* The path could begin with an alias */ - if (*path != '/') - { - int len; - const char *p = separator; - - if (!p) - p = strchrnul(path, '/'); - len = p - path; - - /* of_aliases must not be NULL */ - if (!fdt_aliases) - return NULL; - - for_each_property_of_node(fdt_aliases, pp) - { - if (strlen(pp->name) == len && !strncmp(pp->name, path, - len)) - { - np = dtb_node_find_node_by_path(pp->value); - break; - } - } - if (!np) - return NULL; - path = p; - } - - /* Step down the tree matching path components */ - if (!np) - np = dtb_node_get(get_dtb_node_head()); - while (np && *path == '/') - { - struct dtb_node *tmp = np; - - path++; /* Increment past '/' delimiter */ - np = dtb_node_get_dtb_node_by_path(np, path); - dtb_node_put(tmp); - path = strchrnul(path, '/'); - if (separator && separator < path) - break; - } - - return np; -} - -struct dtb_node *dtb_node_find_compatible_node(struct dtb_node *from, const char *compatible) -{ - struct dtb_node *dn; - - for_each_of_allnodes_from(from, dn) - { - if (dtb_node_get_dtb_node_compatible_match(dn, compatible) && - dtb_node_get(dn)) - break; - } - dtb_node_put(from); - - return dn; -} - -void *dtb_node_get_dtb_node_property_value(const struct dtb_node *dtb_node, const char *property_name, int *property_size) -{ - struct dtb_property *dtb_property = dtb_node_get_dtb_node_property(dtb_node, property_name, NULL); - - if (!dtb_property || !dtb_property->value || !dtb_property->size) - { - return NULL; - } - - if (property_size != NULL) - { - *property_size = dtb_property->size; - } - - return dtb_property->value; -} - -const struct dtb_node *dtb_node_find_node_by_prop_value(struct dtb_node *from, - const char *propname, - const void *propval, int proplen) -{ - struct dtb_node *np; - void *value; - for_each_of_allnodes_from(from, np) - { - value = dtb_node_get_dtb_node_property_value(np, propname, &proplen); - if (!memcmp(value, propval, proplen) && dtb_node_get(np)) - break; - } - dtb_node_put(from); - - return np; -} - -struct dtb_node *dtb_node_find_all_nodes(const struct dtb_node *prev) -{ - const struct dtb_node *dn; - - if (!prev) - { - dn = get_dtb_node_head(); - } - else if (prev->child) - { - dn = prev->child; - } - else - { - /* - * Walk back up looking for a sibling, or the end of the - * structure - */ - dn = prev; - while (dn->parent && !dn->sibling) - dn = dn->parent; - dn = dn->sibling; /* Might be null at the end of the tree */ - } - - return (struct dtb_node *)dn; -} - -rt_bool_t dtb_node_device_is_available(const struct dtb_node *device) -{ - const char *status; - int statlen; - - if (!device) - return RT_FALSE; - - status = dtb_node_get_dtb_node_property_value(device, "status", &statlen); - if (status == NULL) - return RT_TRUE; - - if (statlen > 0) - { - if (!strcmp(status, "okay")) - return RT_TRUE; - } - - return RT_FALSE; -} - -struct dtb_node *dtb_node_get_parent(const struct dtb_node *node) -{ - const struct dtb_node *dn; - - if (!node) - return NULL; - - dn = dtb_node_get(node->parent); - - return (struct dtb_node *)dn; -} - -struct dtb_node *dtb_node_find_node_by_phandle(phandle handle) -{ - struct dtb_node *dn; - - if (!handle) - return NULL; - - for_each_of_allnodes(dn) if (dn->handle == handle) break; - (void)dtb_node_get(dn); - - return dn; -} - -int dtb_node_property_match_string(const struct dtb_node *dn, const char *propname, - const char *string) -{ - const struct dtb_property *prop = dtb_node_get_dtb_node_property(dn, propname, NULL); - size_t l; - int i; - const char *p, *end; - - if (!prop) - return -EINVAL; - if (!prop->value) - return -ENODATA; - - p = prop->value; - end = p + prop->size; - - for (i = 0; p < end; i++, p += l) - { - l = strnlen(p, end - p) + 1; - if (p + l > end) - return -EILSEQ; - debug("comparing %s with %s\n", string, p); - if (strcmp(string, p) == 0) - return i; /* Found it; return index */ - } - return -ENODATA; -} - -/** - * of_property_read_string_helper() - Utility helper for parsing string properties - * @np: device node from which the property value is to be read. - * @propname: name of the property to be searched. - * @out_strs: output array of string pointers. - * @sz: number of array elements to read. - * @skip: Number of strings to skip over at beginning of list. - * - * Don't call this function directly. It is a utility helper for the - * of_property_read_string*() family of functions. - */ -int dtb_node_property_read_string_helper(const struct dtb_node *dn, - const char *propname, const char **out_strs, - size_t sz, int skip) -{ - const struct dtb_property *prop = dtb_node_get_dtb_node_property(dn, propname, NULL); - int l = 0, i = 0; - const char *p, *end; - - if (!prop) - return -EINVAL; - if (!prop->value) - return -ENODATA; - p = prop->value; - end = p + prop->size; - - for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) - { - l = strnlen(p, end - p) + 1; - if (p + l > end) - return -EILSEQ; - if (out_strs && i >= skip) - *out_strs++ = p; - } - i -= skip; - return i <= 0 ? -ENODATA : i; -} - -static int __dtb_node_parse_phandle_with_args(const struct dtb_node *dn, - const char *list_name, - const char *cells_name, - int cell_count, int index, - struct fdt_phandle_args *out_args) -{ - const uint32_t *list, *list_end; - int rc = 0, cur_index = 0; - uint32_t count = 0; - struct dtb_node *node = NULL; - phandle phandle; - int size; - - /* Retrieve the phandle list property */ - list = dtb_node_get_dtb_node_property_value(dn, list_name, &size); - if (!list) - return -ENOENT; - list_end = list + size / sizeof(*list); - - /* Loop over the phandles until all the requested entry is found */ - while (list < list_end) - { - rc = -EINVAL; - count = 0; - - /* - * If phandle is 0, then it is an empty entry with no - * arguments. Skip forward to the next entry. - */ - phandle = fdt32_to_cpu(*(list++)); - if (phandle) - { - /* - * Find the provider node and parse the #*-cells - * property to determine the argument length. - * - * This is not needed if the cell count is hard-coded - * (i.e. cells_name not set, but cell_count is set), - * except when we're going to return the found node - * below. - */ - if (cells_name || cur_index == index) - { - node = dtb_node_find_node_by_phandle(phandle); - if (!node) - { - debug("%s: could not find phandle\n", - dn->path); - goto err; - } - } - - if (cells_name) - { - if (dtb_node_read_u32(node, cells_name, &count)) - { - debug("%s: could not get %s for %s\n", - dn->path, cells_name, - node->path); - goto err; - } - } - else - { - count = cell_count; - } - - /* - * Make sure that the arguments actually fit in the - * remaining property data length - */ - if (list + count > list_end) - { - debug("%s: arguments longer than property\n", - dn->path); - goto err; - } - } - - /* - * All of the error cases above bail out of the loop, so at - * this point, the parsing is successful. If the requested - * index matches, then fill the out_args structure and return, - * or return -ENOENT for an empty entry. - */ - rc = -ENOENT; - if (cur_index == index) - { - if (!phandle) - goto err; - - if (out_args) - { - int i; - if (count > FDT_MAX_PHANDLE_ARGS) - count = FDT_MAX_PHANDLE_ARGS; - out_args->np = node; - out_args->args_count = count; - for (i = 0; i < count; i++) - out_args->args[i] = - fdt32_to_cpu(*(list++)); - } - else - { - dtb_node_put(node); - } - - /* Found it! return success */ - return 0; - } - - dtb_node_put(node); - node = NULL; - list += count; - cur_index++; - } - - /* - * Unlock node before returning result; will be one of: - * -ENOENT : index is for empty phandle - * -EINVAL : parsing error on data - * [1..n] : Number of phandle (count mode; when index = -1) - */ - rc = index < 0 ? cur_index : -ENOENT; -err: - if (node) - dtb_node_put(node); - return rc; -} - -struct dtb_node *dtb_node_parse_phandle(const struct dtb_node *dn, - const char *phandle_name, int index) -{ - struct fdt_phandle_args args; - - if (index < 0) - return NULL; - - if (__dtb_node_parse_phandle_with_args(dn, phandle_name, NULL, 0, index, - &args)) - return NULL; - - return args.np; -} - -int dtb_node_parse_phandle_with_args(const struct dtb_node *dn, - const char *list_name, const char *cells_name, - int index, struct fdt_phandle_args *out_args) -{ - if (index < 0) - return -EINVAL; - - return __dtb_node_parse_phandle_with_args(dn, list_name, cells_name, 0, - index, out_args); -} - -int dtb_node_count_phandle_with_args(const struct dtb_node *dn, - const char *list_name, const char *cells_name) -{ - return __dtb_node_parse_phandle_with_args(dn, list_name, cells_name, 0, - -1, NULL); -} diff --git a/components/drivers/fdt/src/dtb_addr.c b/components/drivers/fdt/src/dtb_addr.c deleted file mode 100644 index 5516ff1e6c..0000000000 --- a/components/drivers/fdt/src/dtb_addr.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "libfdt.h" -#include "dtb_node.h" - -/* Max address size we deal with */ -#define FDT_MAX_ADDR_CELLS 4 -#define FDT_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= FDT_MAX_ADDR_CELLS) -#define FDT_CHECK_COUNTS(na, ns) (FDT_CHECK_ADDR_COUNT(na) && (ns) > 0) - -static void dtb_node_default_count_cells(const struct dtb_node *dn, - int *addrc, int *sizec) -{ - if (addrc) - *addrc = dtb_node_n_addr_cells(dn); - if (sizec) - *sizec = dtb_node_n_size_cells(dn); -} - -const uint32_t *dtb_node_get_address(const struct dtb_node *dev, int index, - uint64_t *size, unsigned int *flags) -{ - const uint32_t *prop; - int psize; - struct dtb_node *parent; - int onesize, i, na, ns; - - /* Get parent */ - parent = dtb_node_get_parent(dev); - if (parent == NULL) - return NULL; - - dtb_node_default_count_cells(dev, &na, &ns); - if (!FDT_CHECK_ADDR_COUNT(na)) - return NULL; - - /* Get "reg" or "assigned-addresses" property */ - prop = dtb_node_get_dtb_node_property_value(dev, "reg", &psize); - if (prop == NULL) - return NULL; - psize /= 4; - - onesize = na + ns; - for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) - if (i == index) - { - if (size) - *size = dtb_node_read_number(prop + na, ns); - if (flags) - *flags = 0x200; - return prop; - } - return NULL; -} diff --git a/components/drivers/fdt/src/dtb_base.c b/components/drivers/fdt/src/dtb_base.c deleted file mode 100644 index eb71de429a..0000000000 --- a/components/drivers/fdt/src/dtb_base.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "dtb_node.h" -#include "libfdt.h" -#include "libfdt_env.h" -#include - -static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) -{ - if (*base == 0) - { - if (s[0] == '0') - { - if (tolower(s[1]) == 'x' && isxdigit((int)s[2])) - *base = 16; - else - *base = 8; - } - else - *base = 10; - } - if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x') - s += 2; - return s; -} - -unsigned long simple_strtoul(const char *cp, char **endp, - unsigned int base) -{ - unsigned long result = 0; - unsigned long value; - - cp = _parse_integer_fixup_radix(cp, &base); - - while (isxdigit((int)*cp) && (value = isdigit((int)*cp) ? *cp-'0' : (islower((int)*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) - { - result = result*base + value; - cp++; - } - - if (endp) - *endp = (char *)cp; - - return result; -} - -int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) -{ - char *tail; - unsigned long val; - size_t len; - - *res = 0; - len = strlen(cp); - if (len == 0) - return -EINVAL; - - val = simple_strtoul(cp, &tail, base); - if (tail == cp) - return -EINVAL; - - if ((*tail == '\0') || - ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) - { - *res = val; - return 0; - } - - return -EINVAL; -} - -long simple_strtol(const char *cp, char **endp, unsigned int base) -{ - if (*cp == '-') - return -simple_strtoul(cp + 1, endp, base); - - return simple_strtoul(cp, endp, base); -} - -rt_bool_t dtb_node_read_bool(const struct dtb_node *node, const char *propname) -{ - const void *prop; - - RT_ASSERT(dtb_node_valid(node)); - debug("%s: %s: ", __func__, propname); - - prop = dtb_node_get_property(node, propname, NULL); - - debug("%s\n", prop ? "true" : "false"); - - return prop ? RT_TRUE : RT_FALSE; -} - -const void *dtb_node_read_prop(const struct dtb_node *node, const char *propname, int *sizep) -{ - const char *val = NULL; - int len; - - RT_ASSERT(dtb_node_valid(node)); - debug("%s: %s: ", __func__, propname); - - struct dtb_property *prop = dtb_node_get_dtb_node_property(node, propname, &len); - - if (prop) - { - val = prop->value; - len = prop->size; - } - - if (!val) - { - debug("\n"); - if (sizep) - *sizep = -FDT_ERR_NOTFOUND; - return NULL; - } - if (sizep) - *sizep = len; - - return val; -} - -const char *dtb_node_read_string(const struct dtb_node *node, const char *propname) -{ - const char *str; - int len; - - str = dtb_node_read_prop(node, propname, &len); - if (!str) - return NULL; - - if (strnlen(str, len) >= len) - { - debug("\n"); - return NULL; - } - debug("%s\n", str); - - return str; -} - -const struct dtb_node *dtb_node_find_subnode(const struct dtb_node *node, const char *subnode_name) -{ - const struct dtb_node *subnode; - - RT_ASSERT(dtb_node_valid(node)); - debug("%s: %s: ", __func__, subnode_name); - - for (node = node->child; node; node = node->sibling) - { - if (!strcmp(subnode_name, node->name)) - break; - } - subnode = node; - - debug("%s\n", dtb_node_valid(subnode) ?\ - dtb_node_get_name(subnode) : ""); - - return subnode; -} - -struct dtb_node *dtb_node_first_subnode(const struct dtb_node *node) -{ - RT_ASSERT(dtb_node_valid(node)); - - return node->child; -} - -struct dtb_node *dtb_node_next_subnode(const struct dtb_node *node) -{ - RT_ASSERT(dtb_node_valid(node)); - - return node->sibling; -} - -const char *dtb_node_get_name(const struct dtb_node *node) -{ - if (!dtb_node_valid(node)) - { - debug("%s node not valid\n", __func__); - return NULL; - } - - return strrchr(node->path, '/') + 1; - -} - -struct dtb_node *dtb_node_get_by_phandle(uint32_t phandle) -{ - if (dtb_node_active()) - return dtb_node_find_node_by_phandle(phandle); - return NULL; -} - -int dtb_node_read_size(const struct dtb_node *node, const char *propname) -{ - struct dtb_property *prop = dtb_node_get_dtb_node_property( node, propname, NULL); - - if (prop) - return prop->size; - - return -EINVAL; -} - -int dtb_node_get_addr_and_size_by_index(const struct dtb_node *node, int index, size_t *addr, size_t *size) -{ - const uint32_t *prop; - int psize; - int onesize, na, ns; - - na = dtb_node_n_addr_cells(node); - ns = dtb_node_n_size_cells(node); - - prop = dtb_node_get_dtb_node_property_value(node, "reg", &psize); - if (prop == NULL) - { - return -1; - } - - psize /= 4; - onesize = na + ns; - - if (psize >= (index + 1) * onesize) - { - prop += index * onesize; - - if (addr) - { - *addr = dtb_node_read_number(prop, na); - } - if (size) - { - *size = dtb_node_read_number(prop + na, ns); - } - - return 0; - } - - return -1; -} - -size_t dtb_node_get_addr_index(const struct dtb_node *node, int index) -{ - int na; - size_t size; - - const uint32_t *prop_val; - uint flags; - - prop_val = dtb_node_get_address(node, index, - (uint64_t *)&size, &flags); - if (!prop_val) - return -1; - - na = dtb_node_n_addr_cells(node); - - return dtb_node_read_number(prop_val, na); -} - -size_t dtb_node_get_addr(const struct dtb_node *node) -{ - return dtb_node_get_addr_index(node, 0); -} - -int dtb_node_stringlist_search(const struct dtb_node *node, const char *property, - const char *string) -{ - return dtb_node_property_match_string(node, property, string); -} - -int dtb_node_read_string_index(const struct dtb_node *node, const char *property, int index, - const char **outp) -{ - return dtb_node_property_read_string_index(node, property, index, outp); -} - -int dtb_node_read_string_count(const struct dtb_node *node, const char *property) -{ - return dtb_node_property_count_strings(node, property); -} - -struct dtb_node *dtb_node_path(const char *path) -{ - if (dtb_node_active()) - return dtb_node_find_node_by_path(path); - return NULL; -} - -const char *dtb_node_get_chosen_prop(const char *name) -{ - const struct dtb_node *chosen_node; - - chosen_node = (const struct dtb_node *)dtb_node_path("/chosen"); - - return dtb_node_read_string(chosen_node, name); -} - -struct dtb_node *dtb_node_get_chosen_node(const char *name) -{ - const char *prop; - - prop = dtb_node_get_chosen_prop(name); - if (!prop) - return NULL; - - return dtb_node_path(prop); -} - -const void *dtb_node_get_property(const struct dtb_node *node, const char *propname, int *lenp) -{ - return dtb_node_get_dtb_node_property_value(node, propname, lenp); -} - -rt_bool_t dtb_node_is_available(const struct dtb_node *node) -{ - return dtb_node_device_is_available(node); -} - -size_t dtb_node_get_addr_size(const struct dtb_node *node, const char *property, - size_t *sizep) -{ - int na, ns; - int psize; - const uint32_t *prop = dtb_node_get_dtb_node_property_value(node, property, &psize); - - if (!prop) - return -1; - na = dtb_node_n_addr_cells(node); - ns = dtb_node_n_size_cells(node); - *sizep = dtb_node_read_number(prop + na, ns); - - return dtb_node_read_number(prop, na); -} - -const uint8_t *dtb_node_read_u8_array_ptr(const struct dtb_node *node, const char *propname, - size_t sz) -{ - int psize; - const uint32_t *prop = dtb_node_get_dtb_node_property_value(node, propname, &psize); - - if (!prop || sz != psize) - return NULL; - return (uint8_t *)prop; -} - -int dtb_node_find_all_compatible_node(const struct dtb_node *from, const char *compatible, struct dtb_node **node_table, int max_num, int *node_num) -{ - const struct dtb_node *dn; - int num = 0; - for_each_of_allnodes_from(from, dn) - { - if (dtb_node_get_dtb_node_compatible_match(dn, compatible) && - dtb_node_get(dn)) - { - - num++; - *node_table = (struct dtb_node *)dn; - node_table++; - if (num >= max_num) - { - break; - } - } - } - *node_num = num; - dtb_node_put(from); - - return 0; -} - -int dtb_node_write_prop(const struct dtb_node *node, const char *propname, int len, - const void *value) -{ - struct dtb_property *pp; - struct dtb_property *pp_last = NULL; - struct dtb_property *new; - - if (!dtb_node_active()) - return -ENOSYS; - - if (!node) - return -EINVAL; - - for (pp = node->properties; pp; pp = pp->next) - { - if (strcmp(pp->name, propname) == 0) - { - /* Property exists -> change value */ - pp->value = (void *)value; - pp->size = len; - return 0; - } - pp_last = pp; - } - - if (!pp_last) - return -ENOENT; - - /* Property does not exist -> append new property */ - new = (struct dtb_property *)malloc(sizeof(struct dtb_property)); - if (!new) - return -ENOMEM; - - new->name = strdup(propname); - if (!new->name) - { - free(new); - return -ENOMEM; - } - - new->value = (void *)value; - new->size = len; - new->next = NULL; - - pp_last->next = new; - - return 0; -} - -int dtb_node_write_string(const struct dtb_node *node, const char *propname, const char *value) -{ - if (!dtb_node_active()) - return -ENOSYS; - - RT_ASSERT(dtb_node_valid(node)); - - debug("%s: %s = %s", __func__, propname, value); - - return dtb_node_write_prop(node, propname, strlen(value) + 1, value); -} - -int dtb_node_set_enabled(const struct dtb_node *node, rt_bool_t value) -{ - if (!dtb_node_active()) - return -ENOSYS; - - RT_ASSERT(dtb_node_valid(node)); - - if (value) - return dtb_node_write_string(node, "status", "okay"); - else - return dtb_node_write_string(node, "status", "disable"); -} - -/** - * dtb_node_irq_find_parent - Given a device node, find its interrupt parent node - * @child: pointer to device node - * - * Returns a pointer to the interrupt parent node, or NULL if the interrupt - * parent could not be determined. - */ -static struct dtb_node *dtb_node_irq_find_parent(struct dtb_node *child) -{ - struct dtb_node *p; - phandle parent; - - if (!dtb_node_get(child)) - return NULL; - do - { - if (dtb_node_read_u32_array(child, "interrupt-parent", &parent, 1)) - { - p = dtb_node_get_parent(child); - } - else - { - p = dtb_node_get_by_phandle(parent); - } - dtb_node_put(child); - child = p; - } while (p && dtb_node_get_property(p, "#interrupt-cells", NULL) == NULL); - - return p; -} - -int dtb_node_irq_get(struct dtb_node *dev, int index) -{ - int rc = 0; - struct fdt_phandle_args out_irq; - struct dtb_node *p; - uint32_t intsize; - int res, i; - - p = dtb_node_irq_find_parent(dev); - if (p == NULL) - return -EINVAL; - /* Get size of interrupt specifier */ - if (dtb_node_read_u32_array(p, "#interrupt-cells", &intsize, 1)) - { - res = -EINVAL; - goto out; - } - - debug(" path:%s, parent=%pOF, intsize=%d\n", p->path,p, intsize); - - /* Copy intspec into irq structure */ - out_irq.np = p; - out_irq.args_count = intsize; - for (i = 0; i < intsize; i++) - { - res = dtb_node_read_u32_index(dev, "interrupts", - (index * 3 + i), - out_irq.args + i); - if (res) - goto out; - } - rc = out_irq.args[1]; - out: - dtb_node_put(p); - return rc; - -} - -/** - * dtb_node_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number - * @dev: pointer to device tree node - * @name: IRQ name - * - * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or - * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case - * of any other failure. - */ -int dtb_node_irq_get_byname(struct dtb_node *dev, const char *name) -{ - int index; - - if (!name) - return -EINVAL; - - index = dtb_node_stringlist_search(dev, "interrupt-names", name); - if (index < 0) - return index; - - return dtb_node_irq_get(dev, index); -} - -/** - * dtb_node_irq_count - Count the number of IRQs a node uses - * @dev: pointer to device tree node - */ -int dtb_node_irq_count(struct dtb_node *device) -{ - struct dtb_node *p; - uint32_t intsize; - int nr = 0, res = 0; - - p = dtb_node_irq_find_parent(device); - if (p == NULL) - return -EINVAL; - - /* Get size of interrupt specifier */ - if (dtb_node_read_u32_array(p, "#interrupt-cells", &intsize, 1)) - { - res = -EINVAL; - goto out; - } - - debug(" path:%s, parent=%pOF, intsize=%d\n", p->path,p, intsize); - - res = dtb_node_read_size(device, "interrupts"); - if (res < 0) - { - goto out; - } - nr = res / (intsize * 4); - out: - dtb_node_put(p); - - return nr; -} diff --git a/components/drivers/fdt/src/dtb_get.c b/components/drivers/fdt/src/dtb_get.c deleted file mode 100644 index 51c3f5ee1d..0000000000 --- a/components/drivers/fdt/src/dtb_get.c +++ /dev/null @@ -1,823 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "libfdt.h" -#include "dtb_node.h" - -static struct -{ - const char *ptr; - const char *end; - char *cur; -} paths_buf = {NULL, NULL}; -static void *current_fdt; - -int fdt_exec_status = FDT_RET_GET_OK; - -int dtb_node_get_exec_status() -{ - return fdt_exec_status; -} - -static int _dtb_node_get_dtb_properties_list(struct dtb_property *dtb_property, off_t node_off) -{ - /* caller alrealy checked current_fdt */ - off_t property_off = fdt_first_property_offset(current_fdt, node_off); - struct fdt_property *fdt_property; - - if (property_off < 0) - { - return FDT_RET_GET_EMPTY; - } - - for (;;) - { - fdt_property = (struct fdt_property *)fdt_get_property_by_offset(current_fdt, property_off, &dtb_property->size); - if (fdt_property != NULL) - { - dtb_property->name = fdt_string(current_fdt, fdt32_to_cpu(fdt_property->nameoff)); - dtb_property->value = fdt_property->data; - dtb_property->size = fdt32_to_cpu(fdt_property->len); - } - - property_off = fdt_next_property_offset(current_fdt, property_off); - if (property_off >= 0) - { - dtb_property->next = (struct dtb_property *)malloc(sizeof(struct dtb_property)); - if (dtb_property->next == NULL) - { - return FDT_RET_NO_MEMORY; - } - dtb_property = dtb_property->next; - } - else - { - dtb_property->next = NULL; - break; - } - } - - return FDT_RET_GET_OK; -} - -static int _dtb_node_get_dtb_nodes_list(struct dtb_node *dtb_node_head, struct dtb_node *dtb_node, const char *pathname) -{ - off_t root_off; - off_t node_off; - int pathname_sz; - int node_name_sz; - - /* caller alrealy checked current_fdt */ - if ((root_off = fdt_path_offset(current_fdt, pathname)) >= 0) - { - pathname_sz = strlen(pathname); - node_off = fdt_first_subnode(current_fdt, root_off); - - if (node_off < 0) - { - return FDT_RET_GET_EMPTY; - } - - for (;;) - { - dtb_node->parent = dtb_node_head; - dtb_node->sibling = NULL; - dtb_node->name = fdt_get_name(current_fdt, node_off, &node_name_sz); - - /* parent_path + name + '/' + '\0' */ - if (paths_buf.cur + pathname_sz + node_name_sz + 2 < paths_buf.end) - { - dtb_node->path = (const char *)paths_buf.cur; - strncpy(paths_buf.cur, pathname, pathname_sz); - paths_buf.cur += pathname_sz; - strncpy(paths_buf.cur, (char *)dtb_node->name, node_name_sz); - paths_buf.cur += node_name_sz; - *paths_buf.cur++ = '/'; - *paths_buf.cur++ = '\0'; - dtb_node->level = dtb_node_head->level + 1; - } - else - { - dtb_node->path = NULL; - rt_kprintf("\033[31m\rERROR: `FDT_DTB_ALL_NODES_PATH_SIZE' = %d bytes is configured too low.\033[0m\n", FDT_DTB_ALL_NODES_PATH_SIZE); - return FDT_RET_NO_MEMORY; - } - - dtb_node->handle = fdt_get_phandle(current_fdt, node_off); - dtb_node->properties = (struct dtb_property *)malloc(sizeof(struct dtb_property)); - dtb_node->child = (struct dtb_node *)malloc(sizeof(struct dtb_node)); - - if (dtb_node->properties == NULL || dtb_node->child == NULL) - { - return FDT_RET_NO_MEMORY; - } - - fdt_exec_status = _dtb_node_get_dtb_properties_list(dtb_node->properties, node_off); - if (fdt_exec_status == FDT_RET_GET_EMPTY) - { - free(dtb_node->properties); - dtb_node->properties = NULL; - } - else if (fdt_exec_status != FDT_RET_GET_OK) - { - return fdt_exec_status; - } - - fdt_exec_status = _dtb_node_get_dtb_nodes_list(dtb_node, dtb_node->child, dtb_node->path); - if (fdt_exec_status == FDT_RET_GET_EMPTY) - { - free(dtb_node->child); - dtb_node->child = NULL; - } - else if (fdt_exec_status != FDT_RET_GET_OK) - { - return fdt_exec_status; - } - - node_off = fdt_next_subnode(current_fdt, node_off); - if (node_off >= 0) - { - dtb_node->sibling = (struct dtb_node *)malloc(sizeof(struct dtb_node)); - if (dtb_node->sibling == NULL) - { - return FDT_RET_NO_MEMORY; - } - dtb_node = dtb_node->sibling; - dtb_node->level--; - } - else - { - break; - } - } - } - - return FDT_RET_GET_OK; -} - -struct dtb_node *dtb_node_get_dtb_list(void *fdt) -{ - int root_off; - struct dtb_node *dtb_node_head = NULL; - - if (fdt == NULL) - { - fdt_exec_status = FDT_RET_NO_LOADED; - goto fail; - } - - current_fdt = fdt; - - if ((dtb_node_head = (struct dtb_node *)malloc(sizeof(struct dtb_node))) == NULL) - { - fdt_exec_status = FDT_RET_NO_MEMORY; - goto fail; - } - - if (paths_buf.ptr == NULL) - { - paths_buf.ptr = (char *)malloc(FDT_DTB_ALL_NODES_PATH_SIZE); - - if (paths_buf.ptr == NULL) - { - fdt_exec_status = FDT_RET_NO_MEMORY; - goto fail; - } - paths_buf.cur = (char *)paths_buf.ptr; - paths_buf.end = (char *)(paths_buf.ptr + FDT_DTB_ALL_NODES_PATH_SIZE); - } - - root_off = fdt_path_offset(fdt, "/"); - - if ((dtb_node_head->header = (struct dtb_header *)malloc(sizeof(struct dtb_header))) == NULL) - - { - fdt_exec_status = FDT_RET_NO_MEMORY; - goto fail; - } - else - { - ((struct dtb_header *)dtb_node_head->header)->root = '/'; - ((struct dtb_header *)dtb_node_head->header)->zero = '\0'; - ((struct dtb_header *)dtb_node_head->header)->memreserve_sz = fdt_num_mem_rsv(fdt); - - if (dtb_node_head->header->memreserve_sz > 0) - { - int i; - int memreserve_sz = dtb_node_head->header->memreserve_sz; - uint32_t off_mem_rsvmap = fdt_off_mem_rsvmap(fdt); - struct fdt_reserve_entry *rsvmap = (struct fdt_reserve_entry *)((char *)fdt + off_mem_rsvmap); - - ((struct dtb_header *)dtb_node_head->header)->memreserve = (struct dtb_memreserve *)malloc(sizeof(struct dtb_memreserve) * memreserve_sz); - if (dtb_node_head->header->memreserve == NULL) - { - fdt_exec_status = FDT_RET_NO_MEMORY; - goto fail; - } - for (i = 0; i < memreserve_sz; ++i) - { - ((struct dtb_header *)dtb_node_head->header)->memreserve[i].address = fdt64_to_cpu(rsvmap[i].address); - ((struct dtb_header *)dtb_node_head->header)->memreserve[i].size = fdt64_to_cpu(rsvmap[i].size); - } - } - else - { - ((struct dtb_header *)dtb_node_head->header)->memreserve = NULL; - } - } - - dtb_node_head->path = paths_buf.ptr; - *paths_buf.cur++ = '/'; - *paths_buf.cur++ = '\0'; - dtb_node_head->parent = NULL; - dtb_node_head->sibling = NULL; - - dtb_node_head->handle = fdt_get_phandle(fdt, root_off); - dtb_node_head->properties = (struct dtb_property *)malloc(sizeof(struct dtb_property)); - dtb_node_head->child = (struct dtb_node *)malloc(sizeof(struct dtb_node)); - dtb_node_head->level = 0; - - if (dtb_node_head->properties == NULL || dtb_node_head->child == NULL) - { - fdt_exec_status = FDT_RET_NO_MEMORY; - goto fail; - } - - if ((fdt_exec_status = _dtb_node_get_dtb_properties_list(dtb_node_head->properties, root_off)) != FDT_RET_GET_OK) - { - goto fail; - } - - if ((fdt_exec_status = _dtb_node_get_dtb_nodes_list(dtb_node_head, dtb_node_head->child, dtb_node_head->path)) != FDT_RET_GET_OK) - { - goto fail; - } - - /* paths_buf.ptr addr save in the dtb_node_head's path */ - paths_buf.ptr = NULL; - paths_buf.cur = NULL; - - return dtb_node_head; - -fail: - if (dtb_node_head != NULL) - { - dtb_node_free_dtb_list(dtb_node_head); - } - - return NULL; -} - -static void _dtb_node_free_dtb_node(struct dtb_node *dtb_node) -{ - struct dtb_node *dtb_node_last; - struct dtb_property *dtb_property; - struct dtb_property *dtb_property_last; - - while (dtb_node != NULL) - { - dtb_property = dtb_node->properties; - while (dtb_property != NULL) - { - dtb_property_last = dtb_property; - dtb_property = dtb_property->next; - free(dtb_property_last); - } - - _dtb_node_free_dtb_node(dtb_node->child); - - dtb_node_last = dtb_node; - dtb_node = dtb_node->sibling; - free(dtb_node_last); - } -} - -void dtb_node_free_dtb_list(struct dtb_node *dtb_node_head) -{ - if (dtb_node_head == NULL) - { - return; - } - - /* only root node can free all path buffer */ - if (dtb_node_head->parent == NULL || (dtb_node_head->path != NULL && !strcmp(dtb_node_head->path, "/"))) - { - if (dtb_node_head->path != NULL) - { - free((void *)dtb_node_head->path); - } - if (dtb_node_head->header != NULL) - { - if (dtb_node_head->header->memreserve != NULL) - { - free((void *)dtb_node_head->header->memreserve); - } - free((void *)dtb_node_head->header); - } - } - - _dtb_node_free_dtb_node(dtb_node_head); -} - -static void _dtb_node_printf_depth(int depth) -{ - int i = depth; - while (i --> 0) - { - rt_kputs("\t"); - } -} - -rt_bool_t _dtb_node_test_string_list(const void *value, int size) -{ - const char *str = value; - const char *str_start, *str_end; - - if (size == 0) - { - return RT_FALSE; - } - - /* string end with '\0' */ - if (str[size - 1] != '\0') - { - return RT_FALSE; - } - - /* get string list end */ - str_end = str + size; - - while (str < str_end) - { - str_start = str; - /* before string list end, not '\0' and a printable characters */ - while (str < str_end && *str && ((unsigned char)*str >= ' ' && (unsigned char)*str <= '~')) - { - ++str; - } - - /* not zero, or not increased */ - if (*str != '\0' || str == str_start) - { - return RT_FALSE; - } - - /* next string */ - ++str; - } - - return RT_TRUE; -} - -static void _dtb_node_printf_dtb_node_info(struct dtb_node *dtb_node) -{ - static int depth = 0; - struct dtb_property *dtb_property; - - while (dtb_node != NULL) - { - rt_kputs("\n"); - _dtb_node_printf_depth(depth); - rt_kputs(dtb_node->name); - rt_kputs(" {\n"); - ++depth; - - dtb_property = dtb_node->properties; - while (dtb_property != NULL) - { - _dtb_node_printf_depth(depth); - - rt_kputs(dtb_property->name); - - if (dtb_property->size > 0) - { - int size = dtb_property->size; - char *value = dtb_property->value; - - rt_kputs(" = "); - if (_dtb_node_test_string_list(value, size) == RT_TRUE) - { - /* print string list */ - char *str = value; - do - { - rt_kprintf("\"%s\"", str); - str += strlen(str) + 1; - rt_kputs(", "); - } while (str < value + size); - rt_kputs("\b\b"); - } - else if ((size % 4) == 0) - { - /* print addr and size cell */ - int i; - fdt32_t *cell = (fdt32_t *)value; - - rt_kputs("<"); - for (i = 0, size /= 4; i < size; ++i) - { - rt_kprintf("0x%x ", fdt32_to_cpu(cell[i])); - } - rt_kputs("\b>"); - } - else - { - /* print bytes array */ - int i; - uint8_t *byte = (uint8_t *)value; - - rt_kputs("["); - for (i = 0; i < size; ++i) - { - rt_kprintf("%02x ", *byte++); - } - rt_kputs("\b]"); - } - } - rt_kputs(";\n"); - dtb_property = dtb_property->next; - } - - _dtb_node_printf_dtb_node_info(dtb_node->child); - dtb_node = dtb_node->sibling; - - --depth; - _dtb_node_printf_depth(depth); - rt_kputs("};\n"); - } -} - -void dtb_node_get_dts_dump(struct dtb_node *dtb_node_head) -{ - if (dtb_node_head != NULL) - { - int i = dtb_node_head->header->memreserve_sz; - - rt_kputs("/dts-v1/;\n"); - while (i --> 0) - { - rt_kprintf("\n/memreserve/\t0x%lx 0x%zx;", dtb_node_head->header->memreserve[i].address, dtb_node_head->header->memreserve[i].size); - } - - _dtb_node_printf_dtb_node_info(dtb_node_head); - } -} - -static void _dtb_node_get_enum_dtb_node(struct dtb_node *dtb_node, void (callback(struct dtb_node *dtb_node))) -{ - while (dtb_node != NULL) - { - callback(dtb_node); - _dtb_node_get_enum_dtb_node(dtb_node->child, callback); - dtb_node = dtb_node->sibling; - } -} - -void dtb_node_get_enum_dtb_node(struct dtb_node *dtb_node_head, void (callback(struct dtb_node *dtb_node))) -{ - if (dtb_node_head == NULL || callback == NULL) - { - return; - } - - _dtb_node_get_enum_dtb_node(dtb_node_head, callback); -} - -struct dtb_node *dtb_node_get_dtb_node_by_name_DFS(struct dtb_node *dtb_node, const char *nodename) -{ - struct dtb_node *dtb_node_child; - - while (dtb_node != NULL) - { - if (!strcmp(nodename, dtb_node->name)) - { - return dtb_node; - } - - dtb_node_child = dtb_node_get_dtb_node_by_name_DFS(dtb_node->child, nodename); - - if (dtb_node_child != NULL) - { - return dtb_node_child; - } - dtb_node = dtb_node->sibling; - } - - return NULL; -} - -struct dtb_node *dtb_node_get_dtb_node_by_name_BFS(struct dtb_node *dtb_node, const char *nodename) -{ - if (dtb_node != NULL) - { - struct dtb_node *dtb_node_child, *dtb_node_head = dtb_node; - - while (dtb_node != NULL) - { - if (!strcmp(nodename, dtb_node->name)) - { - return dtb_node; - } - dtb_node = dtb_node->sibling; - } - - dtb_node = dtb_node_head; - - while (dtb_node != NULL) - { - dtb_node_child = dtb_node_get_dtb_node_by_name_BFS(dtb_node->child, nodename); - - if (dtb_node_child != NULL) - { - return dtb_node_child; - } - dtb_node = dtb_node->sibling; - } - } - - return NULL; -} - -struct dtb_node *dtb_node_get_dtb_node_by_path(struct dtb_node *dtb_node, const char *pathname) -{ - int i = 0; - char *node_name; - char *pathname_clone; - int pathname_sz; - - if (pathname == NULL || dtb_node == NULL) - { - return NULL; - } - - /* skip '/' */ - if (*pathname == '/') - { - ++pathname; - } - - /* root not have sibling, so skip */ - if (dtb_node->parent == NULL || !strcmp(dtb_node->path, "/")) - { - dtb_node = dtb_node->child; - } - - pathname_sz = strlen(pathname) + 1; - pathname_clone = (char *)malloc(pathname_sz); - if (pathname_clone == NULL) - { - return NULL; - } - strncpy(pathname_clone, pathname, pathname_sz); - node_name = pathname_clone; - - while (pathname_clone[i]) - { - if (pathname_clone[i] == '/') - { - /* set an end of name that can used to strcmp */ - pathname_clone[i] = '\0'; - - while (dtb_node != NULL) - { - if (!strcmp(dtb_node->name, node_name)) - { - break; - } - dtb_node = dtb_node->sibling; - } - if (dtb_node == NULL) - { - free(pathname_clone); - return NULL; - } - dtb_node = dtb_node->child; - node_name = &pathname_clone[i + 1]; - } - ++i; - } - - /* - * found the end node and it's name: - * (pathname[pathname_sz - 1]) is '\0' - * (&pathname_clone[i] - node_name) is the node_name's length - */ - node_name = &((char *)pathname)[(pathname_sz - 1) - (&pathname_clone[i] - node_name)]; - free(pathname_clone); - - while (dtb_node != NULL) - { - if (!strcmp(dtb_node->name, node_name)) - { - return dtb_node; - } - dtb_node = dtb_node->sibling; - } - - return NULL; -} - -struct dtb_node *dtb_node_get_dtb_node_by_phandle_DFS(struct dtb_node *dtb_node, phandle handle) -{ - struct dtb_node *dtb_node_child; - - while (dtb_node != NULL) - { - if (dtb_node->handle == handle) - { - return dtb_node; - } - - dtb_node_child = dtb_node_get_dtb_node_by_phandle_DFS(dtb_node->child, handle); - - if (dtb_node_child != NULL) - { - return dtb_node_child; - } - dtb_node = dtb_node->sibling; - } - - return NULL; -} - -struct dtb_node *dtb_node_get_dtb_node_by_phandle_BFS(struct dtb_node *dtb_node, phandle handle) -{ - if (dtb_node != NULL) - { - struct dtb_node *dtb_node_child, *dtb_node_head = dtb_node; - - while (dtb_node != NULL) - { - if (dtb_node->handle == handle) - { - return dtb_node; - } - dtb_node = dtb_node->sibling; - } - - dtb_node = dtb_node_head; - - while (dtb_node != NULL) - { - dtb_node_child = dtb_node_get_dtb_node_by_phandle_BFS(dtb_node->child, handle); - - if (dtb_node_child != NULL) - { - return dtb_node_child; - } - dtb_node = dtb_node->sibling; - } - } - - return NULL; -} - -void dtb_node_get_dtb_node_cells(struct dtb_node *dtb_node, int *addr_cells, int *size_cells) -{ - if (dtb_node != NULL && addr_cells != NULL && size_cells != NULL) - { - struct dtb_property *dtb_property; - *addr_cells = -1; - *size_cells = -1; - - /* if couldn't found, check parent */ - while ((dtb_node = dtb_node->parent) != NULL) - { - dtb_property = dtb_node->properties; - while (dtb_property != NULL) - { - if (!strcmp(dtb_property->name, "#address-cells")) - { - *addr_cells = fdt32_to_cpu(*(int *)dtb_property->value); - } - else if (!strcmp(dtb_property->name, "#size-cells")) - { - *size_cells = fdt32_to_cpu(*(int *)dtb_property->value); - } - if (*addr_cells != -1 && *size_cells != -1) - { - return; - } - dtb_property = dtb_property->next; - } - } - - if (*addr_cells == -1) - { - *addr_cells = FDT_ROOT_ADDR_CELLS_DEFAULT; - } - if (*size_cells == -1) - { - *size_cells = FDT_ROOT_SIZE_CELLS_DEFAULT; - } - } -} - -struct dtb_memreserve *dtb_node_get_dtb_memreserve(struct dtb_node *dtb_node, int *memreserve_size) -{ - if (dtb_node != NULL && memreserve_size != NULL) - { - struct dtb_node *dtb_node_root = dtb_node; - - while (dtb_node_root != NULL) - { - if (!strcmp(dtb_node_root->path, "/")) - { - break; - } - dtb_node_root = dtb_node_root->parent; - } - if(dtb_node_root == NULL) return NULL; - - *memreserve_size = dtb_node_root->header->memreserve_sz; - - return dtb_node_root->header->memreserve; - } - return NULL; -} - -rt_bool_t dtb_node_get_dtb_node_status(const struct dtb_node *dtb_node) -{ - if (dtb_node != NULL) - { - char *status = dtb_node_get_dtb_node_property_value(dtb_node, "status", NULL); - if (status != NULL) - { - return (!strcmp(status, "okay") || !strcmp(status, "ok")) ? RT_TRUE : RT_FALSE; - } - - return RT_TRUE; - } - - return RT_FALSE; -} - -rt_bool_t dtb_node_get_dtb_node_compatible_match(const struct dtb_node *dtb_node, const char *compatibles) -{ - if (dtb_node != NULL) - { - if (compatibles != NULL) - { - char *str_ptr; - int prop_sz; - - for_each_property_string(dtb_node, "compatible", str_ptr, prop_sz) - { - if (!strcmp(compatibles, str_ptr)) - { - return RT_TRUE; - } - } - } - } - - return RT_FALSE; -} - -char *dtb_node_get_dtb_string_list_value(void *value, int size, int index) -{ - int i = 0; - char *str = value; - - if (str != NULL) - { - do - { - if (i++ == index) - { - return str; - } - str += strlen(str) + 1; - } while (str < (char *)value + size); - } - - return NULL; -} - -char *dtb_node_get_dtb_string_list_value_next(void *value, void *end) -{ - char *str = value; - - if (str != NULL) - { - str += strlen(str) + 1; - if (str < (char *)end) - { - return str; - } - } - - return NULL; -} - -uint32_t dtb_node_get_dtb_cell_value(void *value) -{ - return fdt32_to_cpu(*(fdt32_t *)value); -} - -uint8_t dtb_node_get_dtb_byte_value(void *value) -{ - return *(uint8_t *)value; -} diff --git a/components/drivers/fdt/src/dtb_head.c b/components/drivers/fdt/src/dtb_head.c deleted file mode 100644 index 6142673393..0000000000 --- a/components/drivers/fdt/src/dtb_head.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "dtb_node.h" - -static void *dtb_root = NULL; -static struct dtb_node *dtb_node_list = NULL; -void *get_fdt_blob(void) -{ - return dtb_root; -} - -struct dtb_node *get_dtb_node_head(void) -{ - return dtb_node_list; -} - -rt_bool_t dtb_node_active(void) -{ - return dtb_node_list != NULL; -} - -int device_tree_setup(void *mem_addr) -{ - if(mem_addr) - { - if ((dtb_root = dtb_node_load_from_memory(mem_addr,1)) != NULL) - { - dtb_node_list = dtb_node_get_dtb_list(dtb_root); - if (dtb_node_list != NULL) - { - return -1; - } - } - return 0; - } - - return -1; -} diff --git a/components/drivers/fdt/src/dtb_load.c b/components/drivers/fdt/src/dtb_load.c deleted file mode 100644 index c4ac535fdf..0000000000 --- a/components/drivers/fdt/src/dtb_load.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "libfdt.h" -#include -#include -#include "dtb_node.h" - -extern int fdt_exec_status; - -rt_bool_t dtb_node_check(void *fdt) -{ - return fdt_check_header(fdt) == 0 ? RT_TRUE : RT_FALSE; -} - -void *dtb_node_load_from_fs(char *dtb_filename) -{ - void *fdt = NULL; - size_t dtb_sz; - int fd = -1; - - if (dtb_filename == NULL) - { - fdt_exec_status = FDT_RET_GET_EMPTY; - goto end; - } - - fd = open(dtb_filename, O_RDONLY, 0); - - if (fd == -1) - { - rt_kprintf("File `%s' not found.\n", dtb_filename); - fdt_exec_status = FDT_RET_GET_EMPTY; - goto end; - } - - dtb_sz = lseek(fd, 0, SEEK_END); - - if (dtb_sz > 0) - { - if ((fdt = (struct fdt_header *)malloc(sizeof(uint8_t) * dtb_sz)) == NULL) - { - fdt_exec_status = FDT_RET_NO_MEMORY; - goto end; - } - - lseek(fd, 0, SEEK_SET); - read(fd, fdt, sizeof(uint8_t) * dtb_sz); - - if (dtb_node_check(fdt) == RT_FALSE) - { - free(fdt); - fdt=NULL; - } - } - -end: - if (fd != -1) - { - close(fd); - } - - return fdt; -} - -void *dtb_node_load_from_memory(void *dtb_ptr, rt_bool_t is_clone) -{ - void *fdt = NULL; - - if (dtb_ptr == NULL) - { - fdt_exec_status = FDT_RET_GET_EMPTY; - goto end; - } - - if (dtb_node_check(dtb_ptr) == RT_FALSE) - { - fdt_exec_status = FDT_RET_GET_EMPTY; - fdt = NULL; - goto end; - } - - if (is_clone) - { - size_t dtb_sz = fdt_totalsize(dtb_ptr); - if (dtb_sz > 0) - { - if ((fdt = (size_t *)malloc(dtb_sz)) != NULL) - { - memcpy(fdt, dtb_ptr, dtb_sz); - } - else - { - fdt_exec_status = FDT_RET_NO_MEMORY; - } - } - } - else - { - fdt = dtb_ptr; - } - -end: - return fdt; -} diff --git a/components/drivers/fdt/src/dtb_set.c b/components/drivers/fdt/src/dtb_set.c deleted file mode 100644 index f0e11b6b4f..0000000000 --- a/components/drivers/fdt/src/dtb_set.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "libfdt.h" -#include "dtb_node.h" - -static off_t dtb_node_find_and_add_subnode(void *fdt, char* name) -{ - off_t chosen_offset = 0; - - chosen_offset = fdt_subnode_offset(fdt, 0, name); - - if (chosen_offset == -FDT_ERR_NOTFOUND) - { - chosen_offset = fdt_add_subnode(fdt, 0, name); - } - - return chosen_offset; -} - -size_t dtb_node_set_linux_cmdline(void *fdt, char *cmdline) -{ - off_t chosen_offset; - size_t cmdline_size; - - if (cmdline == NULL || fdt == NULL) - { - goto end; - } - - chosen_offset = dtb_node_find_and_add_subnode(fdt, "chosen"); - cmdline_size = strlen(cmdline); - - /* install bootargs */ - if (chosen_offset >= 0 || chosen_offset == -FDT_ERR_EXISTS) - { - if (fdt_setprop(fdt, chosen_offset, "bootargs", cmdline, cmdline_size) < 0) - { - fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_DTB_PAD_SIZE); - fdt_setprop(fdt, chosen_offset, "bootargs", cmdline, cmdline_size); - } - } - -end: - return fdt_totalsize(fdt); -} - -size_t dtb_node_set_linux_initrd(void *fdt, uint64_t initrd_addr, size_t initrd_size) -{ - uint64_t addr, size_ptr; - off_t chosen_offset; - int i; - - if (fdt == NULL) - { - goto end; - } - - chosen_offset = dtb_node_find_and_add_subnode(fdt, "chosen"); - - /* update the entry */ - for (i = fdt_num_mem_rsv(fdt) - 1; i >= 0; --i) - { - fdt_get_mem_rsv(fdt, i, &addr, &size_ptr); - if (addr == initrd_addr) - { - fdt_del_mem_rsv(fdt, i); - break; - } - } - - /* add the memory */ - if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0) - { - /* move the memory */ - fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_DTB_PAD_SIZE); - if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0) - { - goto end; - } - } - - /* install initrd */ - if (chosen_offset >= 0 || chosen_offset == -FDT_ERR_EXISTS) - { - chosen_offset = fdt_path_offset(fdt, "/chosen"); - - if (IN_64BITS_MODE) - { - fdt_setprop_u64(fdt, chosen_offset, "linux,initrd-start", initrd_addr); - fdt_setprop_u64(fdt, chosen_offset, "linux,initrd-end", initrd_addr + initrd_size); - } - else - { - fdt_setprop_u32(fdt, chosen_offset, "linux,initrd-start", initrd_addr); - fdt_setprop_u32(fdt, chosen_offset, "linux,initrd-end", initrd_addr + initrd_size); - } - } - -end: - return fdt_totalsize(fdt); -} - -size_t dtb_node_set_dtb_property(void *fdt, char *pathname, char *property_name, uint32_t *cells, size_t cells_size) -{ - int node_off; - - if (fdt == NULL) - { - goto end; - } - - node_off = fdt_path_offset(fdt, pathname); - - if (node_off >= 0 && cells_size != 0) - { - fdt_setprop(fdt, node_off, property_name, cells, cells_size); - } - -end: - return fdt_totalsize(fdt); -} - -size_t dtb_node_add_dtb_memreserve(void *fdt, uint64_t address, uint64_t size) -{ - if (fdt == NULL) - { - goto end; - } - - fdt_add_mem_rsv(fdt, address, size); - -end: - return fdt_totalsize(fdt); -} - -size_t dtb_node_del_dtb_memreserve(void *fdt, uint64_t address) -{ - int i; - int num_mem_rsvmap; - uint32_t off_mem_rsvmap; - struct fdt_reserve_entry *rsvmap; - - if (fdt == NULL) - { - goto end; - } - - num_mem_rsvmap = fdt_num_mem_rsv(fdt); - off_mem_rsvmap = fdt_off_mem_rsvmap(fdt); - rsvmap = (struct fdt_reserve_entry *)((char *)fdt + off_mem_rsvmap); - - for (i = 0; i < num_mem_rsvmap; ++i) - { - if (address == fdt64_to_cpu(rsvmap[i].address)) - { - fdt_del_mem_rsv(fdt, i); - break; - } - } - -end: - return fdt_totalsize(fdt); -} diff --git a/components/legacy/Kconfig b/components/legacy/Kconfig index d20c0f92f9..67d397949c 100644 --- a/components/legacy/Kconfig +++ b/components/legacy/Kconfig @@ -1,200 +1,2 @@ -menu "Using USB legacy version" - config RT_USING_USB - bool - default n - - config RT_USING_USB_HOST - bool "Using USB host" - default n - select RT_USING_USB - - if RT_USING_USB_HOST - config RT_USBH_MSTORAGE - bool "Enable Udisk Drivers" - default n - if RT_USBH_MSTORAGE - config UDISK_MOUNTPOINT - string "Udisk mount dir" - default "/" - endif - config RT_USBH_HID - bool "Enable HID Drivers" - default n - if RT_USBH_HID - config RT_USBH_HID_MOUSE - bool "Enable HID mouse protocol" - default n - config RT_USBH_HID_KEYBOARD - bool "Enable HID keyboard protocol" - default n - endif - endif - config RT_USING_USB_DEVICE - bool "Using USB device" - default n - select RT_USING_USB - - if RT_USING_USB_DEVICE || RT_USING_USB_HOST - config RT_USBD_THREAD_STACK_SZ - int "usb thread stack size" - default 4096 - endif - if RT_USING_USB_DEVICE - config USB_VENDOR_ID - hex "USB Vendor ID" - default 0x0FFE - config USB_PRODUCT_ID - hex "USB Product ID" - default 0x0001 - - config RT_USB_DEVICE_COMPOSITE - bool "Enable composite device" - default n - choice - prompt "Device type" - default _RT_USB_DEVICE_NONE - depends on !RT_USB_DEVICE_COMPOSITE - config _RT_USB_DEVICE_NONE - bool "Using custom class by register interface" - select RT_USB_DEVICE_NONE - config _RT_USB_DEVICE_CDC - bool "Enable to use device as CDC device" - select RT_USB_DEVICE_CDC - config _RT_USB_DEVICE_MSTORAGE - bool "Enable to use device as Mass Storage device" - select RT_USB_DEVICE_MSTORAGE - config _RT_USB_DEVICE_HID - bool "Enable to use device as HID device" - select RT_USB_DEVICE_HID - config _RT_USB_DEVICE_RNDIS - bool "Enable to use device as rndis device" - select RT_USB_DEVICE_RNDIS - depends on RT_USING_LWIP - config _RT_USB_DEVICE_ECM - bool "Enable to use device as ecm device" - select RT_USB_DEVICE_ECM - depends on RT_USING_LWIP - config _RT_USB_DEVICE_WINUSB - bool "Enable to use device as winusb device" - select RT_USB_DEVICE_WINUSB - config _RT_USB_DEVICE_AUDIO - bool "Enable to use device as audio device" - select RT_USB_DEVICE_AUDIO - endchoice - if RT_USB_DEVICE_COMPOSITE - config RT_USB_DEVICE_CDC - bool "Enable to use device as CDC device" - default n - config RT_USB_DEVICE_NONE - bool - default y - config RT_USB_DEVICE_MSTORAGE - bool "Enable to use device as Mass Storage device" - default n - config RT_USB_DEVICE_HID - bool "Enable to use device as HID device" - default n - config RT_USB_DEVICE_RNDIS - bool "Enable to use device as rndis device" - default n - depends on RT_USING_LWIP - config RT_USB_DEVICE_ECM - bool "Enable to use device as ecm device" - default n - depends on RT_USING_LWIP - config RT_USB_DEVICE_WINUSB - bool "Enable to use device as winusb device" - default n - config RT_USB_DEVICE_AUDIO - bool "Enable to use device as audio device" - default n - endif - if RT_USB_DEVICE_CDC - config RT_VCOM_TASK_STK_SIZE - int "virtual com thread stack size" - default 512 - config RT_CDC_RX_BUFSIZE - int "virtual com rx buffer size" - default 128 - config RT_VCOM_TX_USE_DMA - bool "Enable to use dma for vcom tx" - default n - config RT_VCOM_SERNO - string "serial number of virtual com" - default "32021919830108" - config RT_VCOM_SER_LEN - int "serial number length of virtual com" - default 14 - config RT_VCOM_TX_TIMEOUT - int "tx timeout(ticks) of virtual com" - default 1000 - endif - if RT_USB_DEVICE_WINUSB - config RT_WINUSB_GUID - string "Guid for winusb" - default "{6860DC3C-C05F-4807-8807-1CA861CC1D66}" - endif - if RT_USB_DEVICE_MSTORAGE - config RT_USB_MSTORAGE_DISK_NAME - string "msc class disk name" - default "flash0" - endif - - if RT_USB_DEVICE_RNDIS - config RNDIS_DELAY_LINK_UP - bool "Delay linkup media connection" - select RT_USING_TIMER_SOFT - default n - endif - - if RT_USB_DEVICE_HID - config RT_USB_DEVICE_HID_KEYBOARD - bool "Use to HID device as Keyboard" - default n - if RT_USB_DEVICE_HID_KEYBOARD - config RT_USB_DEVICE_HID_KEYBOARD_NUMBER - int "Number of Keyboard(max 3)" - default 1 - range 1 3 - endif - config RT_USB_DEVICE_HID_MOUSE - bool "Use to HID device as Mouse" - default n - config RT_USB_DEVICE_HID_GENERAL - bool "Use to HID device as General HID device" - default y - if RT_USB_DEVICE_HID_GENERAL - config RT_USB_DEVICE_HID_GENERAL_OUT_REPORT_LENGTH - int "General HID device out report length" - default 63 - range 0 63 - - config RT_USB_DEVICE_HID_GENERAL_IN_REPORT_LENGTH - int "General HID device in report length" - default 63 - range 0 63 - endif - config RT_USB_DEVICE_HID_MEDIA - bool "Use to HID device as media keyboard" - default y - endif - if RT_USB_DEVICE_AUDIO - config RT_USB_DEVICE_AUDIO_MIC - bool "Use usb mic device as audio device" - default n - if RT_USB_DEVICE_AUDIO_MIC - config RT_USBD_MIC_DEVICE_NAME - string "audio mic device name" - default "mic0" - endif - config RT_USB_DEVICE_AUDIO_SPEAKER - bool "Use usb speaker device as audio device" - default n - if RT_USB_DEVICE_AUDIO_SPEAKER - config RT_USBD_SPEAKER_DEVICE_NAME - string "audio speaker device name" - default "sound0" - endif - endif - endif -endmenu +rsource "usb/Kconfig" +rsource "fdt/Kconfig" diff --git a/components/legacy/fdt/Kconfig b/components/legacy/fdt/Kconfig new file mode 100644 index 0000000000..af3c4efd1a --- /dev/null +++ b/components/legacy/fdt/Kconfig @@ -0,0 +1,15 @@ +config RT_USING_FDT + bool "Using fdt legacy version" + default n + if RT_USING_FDT + config RT_USING_FDTLIB + bool "Using fdt lib for device drivers" + default y + config RT_USING_FDT_FWNODE + bool "Using fdt fwnode for device drivers" + default n + config FDT_USING_DEBUG + bool "Using fdt debug function " + default n + + endif diff --git a/components/legacy/fdt/README.md b/components/legacy/fdt/README.md new file mode 100644 index 0000000000..d8a049c8fc --- /dev/null +++ b/components/legacy/fdt/README.md @@ -0,0 +1,41 @@ +# fdt + +## 1、介绍 +fdt基于libfdt进行封装,可实现在内存或文件系统中加载dtb设备树,对内存中的设备树修改、解析,并转换为设备节点树,通过该节点树开发者可通过设备树信息开发驱动。 + +### 1.1 目录结构 +| 名称 | 说明 | +| ---- | ---- | +| docs | 文档目录 | +| examples | 例子目录,并有相应的一些说明 | +| inc | 头文件目录 | +| src | 源代码目录 | + +### 1.2 许可证 +fdt package 遵循 GPL-3.0 许可,详见 LICENSE 文件。 + +### 1.3 依赖 +- RT-Thread 3.0+ + +## 2、如何打开 fdt +使用 fdt package 需要在 RT-Thread 的包管理器中选择它,具体路径如下: + +``` +RT-Thread online packages + tools packages ---> + [*] Device Tree package in RT-Thread +``` + +## 3、使用 fdt +在打开 fdt package 后,当进行 bsp 编译时,它会被加入到 bsp 工程中进行编译。 + +* 完整的 API 手册可以访问这个[链接](docs/api.md) +* 更多文档位于 [`/docs`](/docs) 下,使用前 **务必查看** + +## 4、注意事项 +如果发生`libfdt`库冲突,在package管理菜单中取消选择`Enable libfdt` + +## 5、联系方式 + +* 维护:GuEe-GUI +* 主页:https://github.com/GuEe-GUI/fdt \ No newline at end of file diff --git a/components/legacy/fdt/SConscript b/components/legacy/fdt/SConscript new file mode 100644 index 0000000000..d916b2dfbc --- /dev/null +++ b/components/legacy/fdt/SConscript @@ -0,0 +1,16 @@ +# RT-Thread building script for bridge + +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +if GetDepend('RT_USING_FDT'): + for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/components/legacy/fdt/docs/README.md b/components/legacy/fdt/docs/README.md new file mode 100644 index 0000000000..f57e0a8e75 --- /dev/null +++ b/components/legacy/fdt/docs/README.md @@ -0,0 +1,13 @@ +# 文档 + +## 软件包地址 + +- https://gitee.com/GuEe_GUI/fdt + +## 文档列表 + +|文件名 |描述| +|:----- |:----| +|[examples.md](examples.md) |示例程序| +|[version.md](version.md) |版本信息| +|[api.md](api.md) |API 说明| diff --git a/components/legacy/fdt/docs/api.md b/components/legacy/fdt/docs/api.md new file mode 100644 index 0000000000..13471de06f --- /dev/null +++ b/components/legacy/fdt/docs/api.md @@ -0,0 +1,434 @@ +# fdt load API + +## 从文件系统上读取设备树 +```c +void *fdt_load_from_fs(char *dtb_filename) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_filename | 设备树文件名 | +| **返回** | **描述** | +|void* | 设备树在内存上的地址 | + +## 从内存上读取设备树 +```c +void *fdt_load_from_memory(void *dtb_ptr, rt_bool_t is_clone) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_ptr | 设备树在内存上的内存地址 | +|is_clone | 是否克隆到新的内存区域 | +| **返回** | **描述** | +|void* | 设备树在内存上的地址 | + +# fdt set API + +## 设置Linux启动参数 +```c +rt_size_t fdt_set_linux_cmdline(void *fdt, char *cmdline) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|fdt | 设备树指针 | +|cmdline | 启动参数 | +| **返回** | **描述** | +|rt_size_t | 修改设备树后设备树的大小 | + +## 设置Linux init ramdisk +```c +rt_size_t fdt_set_linux_initrd(void *fdt, rt_uint64_t initrd_addr, rt_size_t initrd_size) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|fdt | 设备树指针 | +|initrd_addr | init ramdisk 内存地址 | +|initrd_size | init 大小 | +| **返回** | **描述** | +|rt_size_t | 修改设备树后设备树的大小 | + +## 设置节点属性值 +```c +rt_size_t fdt_set_dtb_property(void *fdt, char *pathname, char *property_name, rt_uint32_t *cells, rt_size_t cells_size); +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|fdt | 设备树指针 | +|pathname | 节点路径 | +|property_name | 属性名称 | +|cells | 属性值地址 | +|cells_size | 属性值长度 | +| **返回** | **描述** | +|rt_size_t | 修改设备树后设备树的大小 | + +## 添加保留内存 +```c +rt_size_t fdt_add_dtb_memreserve(void *fdt, rt_uint64_t address, rt_uint64_t size) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|fdt | 设备树指针 | +|address | 保留内存起始地址 | +|size | 保留内存大小 | +| **返回** | **描述** | +|rt_size_t | 修改设备树后设备树的大小 | + +## 删除保留内存 +```c +rt_size_t fdt_del_dtb_memreserve(void *fdt, rt_uint64_t address) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|fdt | 设备树指针 | +|address | 保留内存起始地址 | +| **返回** | **描述** | +|rt_size_t | 修改设备树后设备树的大小 | + +# fdt get API + +## 获取设备树软件包执行状态 +```c +rt_err_t fdt_get_exec_status() +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|无 | 无参数 | +| **返回** | **描述** | +|FDT_RET_NO_MEMORY | 内存不足 | +|FDT_RET_NO_LOADED | 设备树还未加载进内存 | +|FDT_RET_GET_OK | 执行成功 | +|FDT_RET_GET_EMPTY | 读取数据为空 | + +## 将原始设备树转换为设备节点树 +```c +struct dtb_node *fdt_get_dtb_list(void *fdt) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|fdt | 设备树在内存上的地址 | +| **返回** | **描述** | +|struct dtb_node * | 设备节点树头指针 | +## 释放设备节点树内存 +```c +void fdt_free_dtb_list(struct dtb_node *dtb_node_head) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node_head | 设备节点树头节点 | +| **返回** | **描述** | +|无返回值 | 无描述 | + +示例:加载设备树 + +```c +#include +#include + +int main() +{ + void *fdt = fdt_load_from_fs("sample.dtb"); + if (fdt != RT_NULL) + { + struct dtb_node *dtb_node_list = fdt_get_dtb_list(fdt); + + if (dtb_node_list != RT_NULL) + { + /* load dtb node list OK */ + + /* free dtb_node_list here */ + fdt_free_dtb_list(dtb_node_list); + } + + rt_free(fdt); + } + + return 0; +} +``` + +## 打印设备树信息 +```c +void fdt_get_dts_dump(struct dtb_node *dtb_node_head) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node_head | 设备节点树头节点 | +| **返回** | **描述** | +|无返回值 | 无描述 | + +## 遍历设备节点树并使用程序定义的回调函数 +```c +void fdt_get_enum_dtb_node(struct dtb_node *dtb_node_head, void (*callback(struct dtb_node *dtb_node))) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node_head | 设备节点树头节点 | +|callback | 程序定义的回调函数 | +| **返回** | **描述** | +|无返回值 | 无描述 | + +示例:遍历设备树节点,并打印每个节点名称 + +```c +#include +#include + +void callback(struct dtb_node *node) +{ + rt_kprintf("this node's name is %s\n", node->name); +} + +int main() +{ + /* loaded dtb_node */ + extern struct dtb_node *dtb_node_list; + + if (dtb_node_list != RT_NULL) + { + fdt_get_enum_dtb_node(dtb_node_list, callback); + } + + return 0; +} +``` + +## 通过节点名称查找节点 +```c +struct dtb_node *fdt_get_dtb_node_by_name_DFS(struct dtb_node *dtb_node, const char *nodename) +``` +```c +struct dtb_node *fdt_get_dtb_node_by_name_BFS(struct dtb_node *dtb_node, const char *nodename) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node | 设备节点树节点 | +|nodename | 查找节点的名称 | +| **返回** | **描述** | +|struct dtb_node * | 返回查找的节点 | +|RT_NULL | 未找到为RT_NULL | + +## 通过节点路径查找节点 +```c +struct dtb_node *fdt_get_dtb_node_by_path(struct dtb_node *dtb_node, const char *pathname) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node | 设备节点树节点 | +|pathname | 查找节点的路径 | +| **返回** | **描述** | +|struct dtb_node * | 返回查找的节点 | +|RT_NULL | 未找到为RT_NULL | + +## 通过节点phandle值查找节点 +```c +struct dtb_node *fdt_get_dtb_node_by_phandle_DFS(struct dtb_node *dtb_node, phandle handle) +``` +```c +struct dtb_node *fdt_get_dtb_node_by_phandle_BFS(struct dtb_node *dtb_node, phandle handle) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node | 设备节点树节点 | +|handle | 查找节点的phandle值 | +| **返回** | **描述** | +|struct dtb_node * | 返回查找的节点 | +|RT_NULL | 未找到为RT_NULL | + +DFS和BFS是用于区分不同深度节点的搜索方法,时间复杂度和空间复杂度都较高,建议使用路径查找。 + +## 读取节点属性值的单位 +```c +void fdt_get_dtb_node_cells(struct dtb_node *dtb_node, int *addr_cells, int *size_cells) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node | 设备节点树节点 | +|addr_cells | 返回的地址块的单位(u32)大小 | +|size_cells | 返回的尺寸块的单位(u32)大小 | +| **返回** | **描述** | +|无返回值 | 无描述 | + + +## 读取节点属性值 +```c +void *fdt_get_dtb_node_property(struct dtb_node *dtb_node, const char *property_name, rt_size_t *property_size) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node | 设备节点树节点 | +|property_name | 属性名称 | +|property_size | 属性大小 | +| **返回** | **描述** | +|void * | 无描述 | +|RT_NULL | 该设备树没有该属性 | + +读取的值为在设备树中存储的值,CPU小端模式下可能需要使用其他API进行转换才是正确的值 + +## 读取预留内存信息 +```c +struct dtb_memreserve *fdt_get_dtb_memreserve(struct dtb_node *dtb_node, int *memreserve_size) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node | 设备节点树节点 | +|memreserve_size | 返回的内存信息数组长度 | +| **返回** | **描述** | +|struct dtb_memreserve *| 内存预留信息数组的内存地址 | +|RT_NULL | 该设备树没有预留内存信息 | + +## 读取节点的状态 +```c +rt_bool_t fdt_get_dtb_node_status(struct dtb_node *dtb_node) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node | 设备节点树节点 | +| **返回** | **描述** | +|RT_FALSE | 状态为禁用 | +|RT_TRUE | 状态为使用 | + +## 用于参数为字符串列表的函数 +```c +fdt_string_list(string, ...) +``` +| 参数 | 描述 | +|:------------------|:------------------------------------| +|string | 字符串集合 | + +## 读取节点compatible标志匹配 +```c +rt_bool_t fdt_get_dtb_node_compatible_match(struct dtb_node *dtb_node, char **compatibles) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|dtb_node | 设备节点树节点 | +|compatibles | 所有要匹配的字符串列表 | +| **返回** | **描述** | +|RT_FALSE | 匹配失败 | +|RT_TRUE | 匹配成功 | + +## 读取属性值中的字符串 +```c +char *fdt_get_dtb_string_list_value(void *value, int size, int index) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|value | 节点属性的内存地址 | +|size | 节点属性的尺寸 | +|index | 要读取字符串的索引 | +| **返回** | **描述** | +|char * | 字符串的内存地址 | +|RT_NULL | 该索引没有字符串 | + +## 读取值为字符串属性下一个字符串 +```c +char *fdt_get_dtb_string_list_value_next(void *value, void *end) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|value | 节点属性的内存地址 | +|end | 节点属性的结束地址 | +| **返回** | **描述** | +|char * | 字符串的内存地址 | +|RT_NULL | 没有下一个字符串 | + +## 读取值为u32属性的值 +```c +rt_uint32_t fdt_get_dtb_cell_value(void *value) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|value | 节点属性的内存地址 | +| **返回** | **描述** | +|rt_uint32_t | 该值小端的值 | + +## 读取值为u8属性的值 +```c +rt_uint8_t fdt_get_dtb_byte_value(void *value) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|value | 节点属性的内存地址 | +| **返回** | **描述** | +|rt_uint8_t | 该值小端的值 | + +# fdt foreach API + +## 遍历属性中字符串宏 +```c +for_each_property_string(node_ptr, property_name, str, size) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|node_ptr | 设备节点树节点 | +|property_name | 节点属性名称 | +|str | 每次遍历到的字符串 | +|size | 用于保存节点属性的尺寸 | + +## 遍历属性中u32宏 +```c +for_each_property_cell(node_ptr, property_name, value, list, size) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|node_ptr | 设备节点树节点 | +|property_name | 节点属性名称 | +|value | 每次遍历到的值 | +|list | 用于保存节点属性的值内存地址 | +|size | 用于保存节点属性的尺寸 | + +## 遍历属性中u8宏 +```c +for_each_property_byte(node_ptr, property_name, value, list, size) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|node_ptr | 设备节点树节点 | +|property_name | 节点属性名称 | +|value | 每次遍历到的值 | +|list | 用于保存节点属性的值内存地址 | +|size | 用于保存节点属性的尺寸 | + +## 遍历子节点宏 +```c +for_each_node_child(node_ptr) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|node_ptr | 设备节点树节点 | + +## 遍历兄弟节点宏 +```c +for_each_node_sibling(node_ptr) +``` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +|node_ptr | 设备节点树节点 | diff --git a/components/legacy/fdt/docs/examples.md b/components/legacy/fdt/docs/examples.md new file mode 100644 index 0000000000..aa3e655987 --- /dev/null +++ b/components/legacy/fdt/docs/examples.md @@ -0,0 +1,81 @@ +# fdt示例 # + +在`examples`文件夹中存放`bcm2711-rpi-4-b.dtb`和`vexpress-v2p-ca9.dtb`可供测试,如果系统可以从bootloader或其他方式获取到bsp本身的dtb,也可以通过修改示例程序进行测试 + +## fdt_dump +```bash +fdt_dump vexpress-v2p-ca9.dtb +``` + +#### 示例结果 #### +```bash +/dts-v1/; + +/ { + model = "V2P-CA9"; + arm,hbi = <0x191>; + arm,vexpress,site = <0xf>; + compatible = "arm,vexpress,v2p-ca9", "arm,vexpress"; + interrupt-parent = <0x1>; + #address-cells = <0x1>; + #size-cells = <0x1>; + + chosen { + }; + + aliases { + serial0 = "/smb@4000000/motherboard/iofpga@7,00000000/uart@9000"; + serial1 = "/smb@4000000/motherboard/iofpga@7,00000000/uart@a000"; + serial2 = "/smb@4000000/motherboard/iofpga@7,00000000/uart@b000"; + serial3 = "/smb@4000000/motherboard/iofpga@7,00000000/uart@c000"; + i2c0 = "/smb@4000000/motherboard/iofpga@7,00000000/i2c@16000"; + i2c1 = "/smb@4000000/motherboard/iofpga@7,00000000/i2c@2000"; + }; + +...... 省略 + + hsb@e0000000 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges = <0x0 0xe0000000 0x20000000>; + #interrupt-cells = <0x1>; + interrupt-map-mask = <0x0 0x3>; + interrupt-map = <0x0 0x0 0x1 0x0 0x24 0x4 0x0 0x1 0x1 0x0 0x25 0x4 0x0 0x2 0x1 0x0 0x26 0x4 0x0 0x3 0x1 0x0 0x27 0x4>; + }; +}; +``` + +## fdt_test +```bash +fdt_test +``` + +#### 示例结果 #### +```bash +name = uart@9000 +reg = <0x9000,0x1000>; +compatible = "arm,pl011","arm,primecell"; + +name = cpus +path = /cpus/cpu@0/ +path = /cpus/cpu@1/ +path = /cpus/cpu@2/ +path = /cpus/cpu@3/ + +name = user1, lable = v2m:green:user1 +name = user2, lable = v2m:green:user2 +name = user3, lable = v2m:green:user3 +name = user4, lable = v2m:green:user4 +name = user5, lable = v2m:green:user5 +name = user6, lable = v2m:green:user6 +name = user7, lable = v2m:green:user7 +name = user8, lable = v2m:green:user8 + +/memreserve/ 0x0000000000000000 0x0000000000001000; + +phandle = <0x9> +name = bt_pins +path = /soc/gpio@7e200000/bt_pins/ +brcm,pins = [2d 00] +``` \ No newline at end of file diff --git a/components/legacy/fdt/docs/version.md b/components/legacy/fdt/docs/version.md new file mode 100644 index 0000000000..3c3499d91a --- /dev/null +++ b/components/legacy/fdt/docs/version.md @@ -0,0 +1,7 @@ +# 版本和修订 # + +| Date | Version | Author | Note | +| -------- | :-----: | :---- | :---- | +| 2021-9-1 | v0.0.1 | GuEe-GUI | 初始版本 | +| 2021-11-11 | v1.0.0 | GuEe-GUI | API确定版本 | +| | | | | \ No newline at end of file diff --git a/components/legacy/fdt/examples/SConscript b/components/legacy/fdt/examples/SConscript new file mode 100644 index 0000000000..463c4814cc --- /dev/null +++ b/components/legacy/fdt/examples/SConscript @@ -0,0 +1,10 @@ + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('FDT', src, depend = ['FDT_USING_DEBUG'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/legacy/fdt/examples/fdt_test.c b/components/legacy/fdt/examples/fdt_test.c new file mode 100644 index 0000000000..4bf2879256 --- /dev/null +++ b/components/legacy/fdt/examples/fdt_test.c @@ -0,0 +1,143 @@ +#include +#include "dtb_node.h" + +int dtb_test() +{ + void *fdt; + + if ((fdt = dtb_node_load_from_fs("vexpress-v2p-ca9.dtb")) != RT_NULL) + { + struct dtb_node *dtb_node_list = dtb_node_get_dtb_list(fdt); + if (dtb_node_list != RT_NULL) + { + struct dtb_node *serial0 = dtb_node_get_dtb_node_by_path(dtb_node_list, "/smb@4000000/motherboard/iofpga@7,00000000/uart@9000"); + struct dtb_node *cpu = dtb_node_get_dtb_node_by_path(dtb_node_list, "/cpus"); + struct dtb_node *user1 = dtb_node_get_dtb_node_by_path(dtb_node_list, "/smb@4000000/motherboard/leds/user1"); + + if (serial0 != RT_NULL) + { + int property_size; + rt_uint32_t u32_value; + rt_uint32_t *u32_ptr; + char *str_ptr; + + rt_kprintf("name = %s\n", serial0->name); + + rt_kputs("reg = <"); + for_each_property_cell(serial0, "reg", u32_value, u32_ptr, property_size) + { + rt_kprintf("0x%x,", u32_value); + } + rt_kputs("\b>;\n"); + + rt_kputs("compatible = "); + for_each_property_string(serial0, "compatible", str_ptr, property_size) + { + rt_kprintf("\"%s\",", str_ptr); + } + rt_kputs("\b;\n"); + } + + if (cpu != RT_NULL) + { + struct dtb_node *cpu_child = cpu; + + rt_kprintf("\nname = %s\n", cpu->name); + + for_each_node_child(cpu_child) + { + rt_kprintf("path = %s\n", cpu_child->path); + } + } + + if (user1 != RT_NULL) + { + struct dtb_node *user = user1; + + rt_kprintf("\nname = %s, lable = %s\n", user1->name, dtb_node_get_dtb_node_property(user1, "label", RT_NULL)); + + for_each_node_sibling(user) + { + rt_kprintf("name = %s, lable = %s\n", user->name, dtb_node_get_dtb_node_property(user, "label", RT_NULL)); + } + } + } + dtb_node_free_dtb_list(dtb_node_list); + } + + if ((fdt = dtb_node_load_from_fs("bcm2711-rpi-4-b.dtb")) != RT_NULL) + { + struct dtb_node *dtb_node_list = dtb_node_get_dtb_list(fdt); + if (dtb_node_list != RT_NULL) + { + struct dtb_node *bt_pins; + int memreserve_size; + struct dtb_memreserve *memreserve; + + bt_pins = dtb_node_get_dtb_node_by_name_DFS(dtb_node_list, "bt_pins"); + bt_pins = dtb_node_get_dtb_node_by_name_BFS(dtb_node_list, bt_pins->name); + bt_pins = dtb_node_get_dtb_node_by_phandle_DFS(dtb_node_list, bt_pins->handle); + bt_pins = dtb_node_get_dtb_node_by_phandle_BFS(dtb_node_list, bt_pins->handle); + + memreserve = dtb_node_get_dtb_memreserve(bt_pins, &memreserve_size); + if (memreserve_size > 0) + { + int i; + for (i = 0; i < memreserve_size; ++i) + { + rt_kputs("\n/memreserve/\t"); + if (IN_64BITS_MODE) + { + rt_kprintf("0x%016x 0x%016x;", memreserve[i].address, memreserve[i].size); + } + else + { + rt_kprintf("0x%08x%08x 0x%08x%08x;", memreserve[i].address, memreserve[i].size); + } + } + } + + if (bt_pins != RT_NULL) + { + int property_size; + rt_uint8_t u8_value; + rt_uint8_t *u8_ptr; + + rt_kprintf("\n\nphandle = <0x%x>\n", bt_pins->handle); + rt_kprintf("name = %s\n", bt_pins->name); + rt_kprintf("path = %s\n", bt_pins->path); + + rt_kputs("brcm,pins = ["); + for_each_property_byte(bt_pins, "brcm,pins", u8_value, u8_ptr, property_size) + { + rt_kprintf("%02x ", u8_value); + } + rt_kputs("\b]\n"); + } + } + dtb_node_free_dtb_list(dtb_node_list); + } + return 0; +} +MSH_CMD_EXPORT(dtb_test, dtb API test); + +int dtb_dump(int argc, char** argv) +{ + struct dtb_node *dtb_root_node = get_dtb_node_head(); + if(argc == 1) + { + if (dtb_root_node != RT_NULL) + { + dtb_node_get_dts_dump(dtb_root_node); + } + } + else + { + rt_kprintf("invailed parameter\n"); + } + + return 0; +} +MSH_CMD_EXPORT(dtb_dump, dtb dump from mem); + + diff --git a/components/legacy/fdt/inc/dtb_fwnode.h b/components/legacy/fdt/inc/dtb_fwnode.h new file mode 100644 index 0000000000..e8d303e37d --- /dev/null +++ b/components/legacy/fdt/inc/dtb_fwnode.h @@ -0,0 +1,125 @@ +#ifndef __DTB_FWNODE_H__ +#define __DTB_FWNODE_H__ + +#include "libfdt_env.h" +#include +#include +#include + +struct fwnode_operations; +struct rt_device; + +#define FWNODE_FLAG_LINKS_ADDED 0x01 +#define FWNODE_FLAG_NOT_DEVICE 0x02 +#define FWNODE_FLAG_INITIALIZED 0x04 + +#define NR_FWNODE_REFERENCE_ARGS 8 + +struct fwnode_handle +{ + struct fwnode_handle *secondary; + const struct fwnode_operations *ops; + struct rt_device *dev; + struct rt_list_node suppliers; + struct rt_list_node consumers; + uint8_t flags; +}; + +struct fwnode_link +{ + struct fwnode_handle *supplier; + struct rt_list_node s_hook; + struct fwnode_handle *consumer; + struct rt_list_node c_hook; +}; + +struct fwnode_endpoint +{ + unsigned int port; + unsigned int id; + const struct fwnode_handle *local_fwnode; +}; + +struct fwnode_reference_args +{ + struct fwnode_handle *fwnode; + unsigned int nargs; + uint64_t args[NR_FWNODE_REFERENCE_ARGS]; +}; + +struct fwnode_operations +{ + struct fwnode_handle *(*get)(struct fwnode_handle *fwnode); + void (*put)(struct fwnode_handle *fwnode); + bool (*device_is_available)(const struct fwnode_handle *fwnode); + const void *(*device_get_match_data)(const struct fwnode_handle *fwnode, + const struct rt_device *dev); + bool (*property_present)(const struct fwnode_handle *fwnode, + const char *propname); + int (*property_read_int_array)(const struct fwnode_handle *fwnode, + const char *propname, + unsigned int elem_size, void *val, + size_t nval); + int (*property_read_string_array)(const struct fwnode_handle *fwnode_handle, + const char *propname, const char **val, + size_t nval); + const char *(*get_name)(const struct fwnode_handle *fwnode); + const char *(*get_name_prefix)(const struct fwnode_handle *fwnode); + struct fwnode_handle *(*get_parent)(const struct fwnode_handle *fwnode); + struct fwnode_handle *(*get_next_child_node)(const struct fwnode_handle *fwnode, + struct fwnode_handle *child); + struct fwnode_handle *(*get_named_child_node)(const struct fwnode_handle *fwnode, + const char *name); + int (*get_reference_args)(const struct fwnode_handle *fwnode, + const char *prop, const char *nargs_prop, + unsigned int nargs, unsigned int index, + struct fwnode_reference_args *args); + struct fwnode_handle *(*graph_get_next_endpoint)(const struct fwnode_handle *fwnode, + struct fwnode_handle *prev); + struct fwnode_handle *(*graph_get_remote_endpoint)(const struct fwnode_handle *fwnode); + struct fwnode_handle *(*graph_get_port_parent)(struct fwnode_handle *fwnode); + int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode, + struct fwnode_endpoint *endpoint); + int (*add_links)(struct fwnode_handle *fwnode); +}; + +#define fwnode_has_op(fwnode, op) \ + ((fwnode) && (fwnode)->ops && (fwnode)->ops->op) +#define fwnode_call_int_op(fwnode, op, ...) \ + (fwnode ? (fwnode_has_op(fwnode, op) ? (fwnode)->ops->op(fwnode, ##__VA_ARGS__) : -ENXIO) : -EINVAL) + +#define fwnode_call_bool_op(fwnode, op, ...) \ + (fwnode_has_op(fwnode, op) ? (fwnode)->ops->op(fwnode, ##__VA_ARGS__) : false) + +#define fwnode_call_ptr_op(fwnode, op, ...) \ + (fwnode_has_op(fwnode, op) ? (fwnode)->ops->op(fwnode, ##__VA_ARGS__) : NULL) +#define fwnode_call_void_op(fwnode, op, ...) \ + do \ + { \ + if (fwnode_has_op(fwnode, op)) \ + (fwnode)->ops->op(fwnode, ##__VA_ARGS__); \ + } while (false) + +#define get_dev_from_fwnode(fwnode) ((fwnode)->dev) + +static inline void fwnode_init(struct fwnode_handle *fwnode, + const struct fwnode_operations *ops) +{ + fwnode->ops = ops; + rt_list_init(&fwnode->consumers); + rt_list_init(&fwnode->suppliers); +} + +static inline void fwnode_dev_initialized(struct fwnode_handle *fwnode, + bool initialized) +{ + if (!fwnode) + return; + + if (initialized) + fwnode->flags |= FWNODE_FLAG_INITIALIZED; + else + fwnode->flags &= ~FWNODE_FLAG_INITIALIZED; +} + +#endif //__DTB_FWNODE_H__ diff --git a/components/legacy/fdt/inc/dtb_node.h b/components/legacy/fdt/inc/dtb_node.h new file mode 100644 index 0000000000..716d4a3082 --- /dev/null +++ b/components/legacy/fdt/inc/dtb_node.h @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _DTB_NODE_H__ +#define _DTB_NODE_H__ + +#include "libfdt_env.h" +#include +#include + +#ifdef RT_USING_FDT_FWNODE +#include "dtb_fwnode.h" +#endif + +//#define RT_DTB_DEBUG +#ifdef RT_DTB_DEBUG +#define debug(fmt, args...) rt_kprintf(fmt, ##args) +#else +#define debug(fmt, args...) +#endif + +#define DTB_ERR_PTR(err) ((void *)((long)(err))) +#define DTB_PTR_ERR(ptr) ((long)(ptr)) +#define DTB_IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) + +#define DEV_ROOT_NODE_ADDR_CELLS_DEFAULT 2 +#define DEV_ROOT_NODE_SIZE_CELLS_DEFAULT 1 +/* will be optimized to only u64 or u32 by gcc */ +#define IN_64BITS_MODE (sizeof(void *) == 8) + +#define FDT_ROOT_ADDR_CELLS_DEFAULT 1 +#define FDT_ROOT_SIZE_CELLS_DEFAULT 1 + +#define FDT_DTB_ALL_NODES_PATH_SIZE (32 * 1024) +#define FDT_DTB_PAD_SIZE 1024 + +#define FDT_RET_NO_MEMORY 2 +#define FDT_RET_NO_LOADED 1 +#define FDT_RET_GET_OK 0 +#define FDT_RET_GET_EMPTY (-1) + +typedef uint32_t phandle; + +struct dtb_memreserve +{ + uintptr_t address; + size_t size; +}; + +struct dtb_header +{ + char root, zero; /* "/" */ + struct dtb_memreserve *memreserve; + size_t memreserve_sz; +}; + +struct dtb_property +{ + const char *name; + int size; + void *value; + + struct dtb_property *next; +}; + +struct dtb_node +{ + union + { + const char *name; + const struct dtb_header *header; + }; + const char *path; + phandle handle; + int level; +#ifdef RT_USING_FDT_FWNODE + struct fwnode_handle fwnode; + unsigned long _flags; +#endif + struct dtb_property *properties; + struct dtb_node *parent; + struct dtb_node *child; + struct dtb_node *sibling; +}; + +#define FDT_MAX_PHANDLE_ARGS 16 + +/** + * struct dtb_node_phandle_args - structure to hold phandle and arguments + * + * This is used when decoding a phandle in a device tree property. Typically + * these look like this: + * + * wibble { + * phandle = <5>; + * }; + * + * ... + * some-prop = <&wibble 1 2 3> + * + * Here &node is the phandle of the node 'wibble', i.e. 5. There are three + * arguments: 1, 2, 3. + * + * So when decoding the phandle in some-prop, np will point to wibble, + * args_count will be 3 and the three arguments will be in args. + * + * @np: Node that the phandle refers to + * @args_count: Number of arguments + * @args: Argument values + */ +struct fdt_phandle_args +{ + struct dtb_node *np; + int args_count; + uint32_t args[FDT_MAX_PHANDLE_ARGS]; +}; + +/* + * A single signal can be specified via a range of minimal and maximal values + * with a typical value, that lies somewhere inbetween. + */ +struct timing_entry +{ + uint32_t min; + uint32_t typ; + uint32_t max; +}; + +void *get_fdt_blob(void); +struct dtb_node *get_dtb_node_head(void); +rt_bool_t dtb_node_active(void); +int device_tree_setup(void *mem_addr); + +void *dtb_node_load_from_fs(char *dtb_filename); +void *dtb_node_load_from_memory(void *dtb_ptr, rt_bool_t is_clone); + +size_t dtb_node_set_linux_cmdline(void *fdt, char *cmdline); +size_t dtb_node_set_linux_initrd(void *fdt, uint64_t initrd_addr, size_t initrd_size); + +size_t dtb_node_set_dtb_property(void *fdt, char *pathname, char *property_name, uint32_t *cells, size_t cells_size); +size_t dtb_node_add_dtb_memreserve(void *fdt, uint64_t address, uint64_t size); +size_t dtb_node_del_dtb_memreserve(void *fdt, uint64_t address); + +int dtb_node_get_exec_status(); +struct dtb_node *dtb_node_get_dtb_list(void *fdt); +void dtb_node_free_dtb_list(struct dtb_node *dtb_node_head); +void dtb_node_get_dts_dump(struct dtb_node *dtb_node_head); +void dtb_node_get_enum_dtb_node(struct dtb_node *dtb_node_head, void(callback(struct dtb_node *dtb_node))); + +struct dtb_node *dtb_node_get_dtb_node_by_name_DFS(struct dtb_node *dtb_node, const char *nodename); +struct dtb_node *dtb_node_get_dtb_node_by_name_BFS(struct dtb_node *dtb_node, const char *nodename); +struct dtb_node *dtb_node_get_dtb_node_by_path(struct dtb_node *dtb_node, const char *pathname); +struct dtb_node *dtb_node_get_dtb_node_by_phandle_DFS(struct dtb_node *dtb_node, phandle handle); +struct dtb_node *dtb_node_get_dtb_node_by_phandle_BFS(struct dtb_node *dtb_node, phandle handle); +void dtb_node_get_dtb_node_cells(struct dtb_node *dtb_node, int *addr_cells, int *size_cells); +struct dtb_memreserve *dtb_node_get_dtb_memreserve(struct dtb_node *dtb_node, int *memreserve_size); +uint8_t dtb_node_get_dtb_byte_value(void *value); + +char *dtb_node_get_dtb_string_list_value(void *value, int size, int index); +char *dtb_node_get_dtb_string_list_value_next(void *value, void *end); +uint32_t dtb_node_get_dtb_cell_value(void *value); + +rt_bool_t dtb_node_get_dtb_node_status(const struct dtb_node *dtb_node); +rt_bool_t dtb_node_get_dtb_node_compatible_match(const struct dtb_node *dtb_node, const char *compatibles); + +/*dtb_node_access.c */ +int dtb_node_read_u32(const struct dtb_node *dn, const char *propname, uint32_t *outp); +uint32_t dtb_node_read_u32_default(const struct dtb_node *node, const char *propname, uint32_t def); +int dtb_node_read_u32_index(const struct dtb_node *node, const char *propname, int index, + uint32_t *outp); +uint32_t dtb_node_read_u32_index_default(const struct dtb_node *node, const char *propname, int index, + uint32_t def); +int dtb_node_read_u32_array(const struct dtb_node *dn, const char *propname, + uint32_t *out_values, size_t sz); +int dtb_node_read_u32_index(const struct dtb_node *dn, const char *propname, + int index, uint32_t *outp); +int dtb_node_read_s32_default(const struct dtb_node *node, const char *propname, int32_t def); +int dtb_node_read_u64(const struct dtb_node *dn, const char *propname, uint64_t *outp); +uint64_t dtb_node_read_u64_default(const struct dtb_node *node, const char *propname, uint64_t def); + +int dtb_node_n_addr_cells(const struct dtb_node *dn); +int dtb_node_n_size_cells(const struct dtb_node *dn); +int dtb_node_simple_addr_cells(const struct dtb_node *np); +int dtb_node_simple_size_cells(const struct dtb_node *np); + +struct dtb_node *dtb_node_find_all_nodes(const struct dtb_node *prev); +struct dtb_node *dtb_node_find_node_by_phandle(phandle handle); +struct dtb_node *dtb_node_find_compatible_node(struct dtb_node *from, const char *compatible); +void *dtb_node_get_dtb_node_property_value(const struct dtb_node *dtb_node, const char *property_name, int *property_size); +struct dtb_property *dtb_node_get_dtb_node_property(const struct dtb_node *dtb_node, const char *property_name, int *property_size); +const struct dtb_node *dtb_node_find_node_by_prop_value(struct dtb_node *from, const char *propname, const void *propval, int proplen); +struct dtb_node *dtb_node_find_node_opts_by_path(const char *path, + const char **opts); + +static inline struct dtb_node *dtb_node_find_node_by_path(const char *path) +{ + return dtb_node_find_node_opts_by_path(path, NULL); +} + +rt_bool_t dtb_node_device_is_available(const struct dtb_node *device); +struct dtb_node *dtb_node_get_parent(const struct dtb_node *node); +int dtb_node_property_match_string(const struct dtb_node *dn, const char *propname, + const char *string); +int dtb_node_property_read_string_helper(const struct dtb_node *dn, + const char *propname, const char **out_strs, + size_t sz, int skip); +/** + * of_property_read_string_index() - Find and read a string from a multiple + * strings property. + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @index: index of the string in the list of strings + * @out_string: pointer to null terminated return string, modified only if + * return value is 0. + * + * Search for a property in a device tree node and retrieve a null + * terminated string value (pointer to data, not a copy) in the list of strings + * contained in that property. + * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if + * property does not have a value, and -EILSEQ if the string is not + * null-terminated within the length of the property data. + * + * The out_string pointer is modified only if a valid string can be decoded. + */ +static inline int dtb_node_property_read_string_index(const struct dtb_node *dn, + const char *propname, + int index, const char **output) +{ + int rc = dtb_node_property_read_string_helper(dn, propname, output, 1, index); + return rc < 0 ? rc : 0; +} + +/** + * of_property_count_strings() - Find and return the number of strings from a + * multiple strings property. + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device tree node and retrieve the number of null + * terminated string contain in it. Returns the number of strings on + * success, -EINVAL if the property does not exist, -ENODATA if property + * does not have a value, and -EILSEQ if the string is not null-terminated + * within the length of the property data. + */ +static inline int dtb_node_property_count_strings(const struct dtb_node *dn, + const char *propname) +{ + return dtb_node_property_read_string_helper(dn, propname, NULL, 0, 0); +} + +struct dtb_node *dtb_node_parse_phandle(const struct dtb_node *dn, + const char *phandle_name, int index); +int dtb_node_parse_phandle_with_args(const struct dtb_node *dn, + const char *list_name, const char *cells_name, + int index, struct fdt_phandle_args *out_args); +int dtb_node_count_phandle_with_args(const struct dtb_node *dn, + const char *list_name, const char *cells_name); + +/* dtb_node_addr.c */ +const uint32_t *dtb_node_get_address(const struct dtb_node *dev, int index, + uint64_t *size, unsigned int *flags); + +#define dtb_node_string_list(string, ...) ((char *[]){string, ##__VA_ARGS__, NULL}) + +#define for_each_property_string(node_ptr, property_name, str, size) \ + for (str = dtb_node_get_dtb_node_property_value(node_ptr, property_name, &size), \ + size += (typeof(size))(size_t)str; \ + str && *str; \ + str = dtb_node_get_dtb_string_list_value_next((void *)str, (void *)(size_t)size)) + +#define for_each_property_cell(node_ptr, property_name, value, list, size) \ + for (list = dtb_node_get_dtb_node_property_value(node_ptr, property_name, &size), \ + value = dtb_node_get_dtb_cell_value(list), \ + size /= sizeof(uint32_t); \ + size > 0; \ + value = dtb_node_get_dtb_cell_value(++list), --size) + +#define for_each_property_byte(node_ptr, property_name, value, list, size) \ + for (list = dtb_node_get_dtb_node_property_value(node_ptr, property_name, &size), \ + value = dtb_node_get_dtb_byte_value(list); \ + size > 0; \ + value = dtb_node_get_dtb_byte_value(++list), --size) + +#define for_each_node_child(node_ptr) \ + for (node_ptr = (node_ptr ? node_ptr->child : NULL); \ + node_ptr != NULL; \ + node_ptr = node_ptr->sibling) + +#define for_each_node_sibling(node_ptr) \ + for (node_ptr = (node_ptr ? node_ptr->sibling : NULL); \ + node_ptr != NULL; \ + node_ptr = node_ptr->sibling) + +#define for_each_of_allnodes_from(from, dn) \ + for (dn = dtb_node_find_all_nodes(from); dn; dn = dtb_node_find_all_nodes(dn)) + +#define for_each_of_all_child_nodes_from(from, dn) \ + for (dn = dtb_node_find_all_nodes(from); dn && (dn->level > from->level); dn = dtb_node_find_all_nodes(dn)) + +#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn) + +#define dtb_node_get(x) (x) +static inline void dtb_node_put(const struct dtb_node *np) +{ +} + +/* Helper to read a big number; size is in cells (not bytes) */ +static inline uint64_t dtb_node_read_number(const uint32_t *cell, int size) +{ + uint64_t r = 0; + while (size--) + r = (r << 32) | fdt32_to_cpu(*(cell++)); + return r; +} + +/** + * ofnode_valid() - check if an ofnode is valid + * + * @return true if the reference contains a valid ofnode, RT_FALSE if it is NULL + */ +static inline rt_bool_t dtb_node_valid(const struct dtb_node *node) +{ + if (dtb_node_active()) + return node != NULL; + return RT_FALSE; +} + +/*dtb_base.c */ +rt_bool_t dtb_node_read_bool(const struct dtb_node *node, const char *propname); +const void *dtb_node_read_prop(const struct dtb_node *node, const char *propname, int *sizep); +const char *dtb_node_read_string(const struct dtb_node *node, const char *propname); +const struct dtb_node *dtb_node_find_subnode(const struct dtb_node *node, const char *subnode_name); +int dtb_node_read_u32_array(const struct dtb_node *node, const char *propname, + uint32_t *out_values, size_t sz); +struct dtb_node *dtb_node_first_subnode(const struct dtb_node *node); +struct dtb_node *dtb_node_next_subnode(const struct dtb_node *node); +struct dtb_node *dtb_node_get_parent(const struct dtb_node *node); +const char *dtb_node_get_name(const struct dtb_node *node); +struct dtb_node *dtb_node_get_by_phandle(uint32_t phandle); +int dtb_node_read_size(const struct dtb_node *node, const char *propname); +int dtb_node_get_addr_and_size_by_index(const struct dtb_node *node, int index, size_t *addr, size_t *size); +size_t dtb_node_get_addr_index(const struct dtb_node *node, int index); +size_t dtb_node_get_addr(const struct dtb_node *node); +int dtb_node_stringlist_search(const struct dtb_node *node, const char *property, + const char *string); +int dtb_node_read_string_index(const struct dtb_node *node, const char *property, int index, + const char **outp); +int dtb_node_read_string_count(const struct dtb_node *node, const char *property); +struct dtb_node *dtb_node_path(const char *path); +const char *dtb_node_get_chosen_prop(const char *name); +struct dtb_node *dtb_node_get_chosen_node(const char *name); +const void *dtb_node_get_property(const struct dtb_node *node, const char *propname, int *lenp); +rt_bool_t dtb_node_is_available(const struct dtb_node *node); +size_t dtb_node_get_addr_size(const struct dtb_node *node, const char *property, + size_t *sizep); +const uint8_t *dtb_node_read_u8_array_ptr(const struct dtb_node *node, const char *propname, size_t sz); +int dtb_node_find_all_compatible_node(const struct dtb_node *from, const char *compatible, struct dtb_node **node_table, int max_num, int *node_num); +int dtb_node_write_prop(const struct dtb_node *node, const char *propname, int len, + const void *value); +int dtb_node_write_string(const struct dtb_node *node, const char *propname, const char *value); +int dtb_node_set_enabled(const struct dtb_node *node, rt_bool_t value); +int dtb_node_irq_get(struct dtb_node *dev, int index); +int dtb_node_irq_get_byname(struct dtb_node *dev, const char *name); +int dtb_node_irq_count(struct dtb_node *dev); + +/** + * dtb_node_for_each_subnode() - iterate over all subnodes of a parent + * + * @node: child node (ofnode, lvalue) + * @parent: parent node (ofnode) + * + * This is a wrapper around a for loop and is used like so: + * + * ofnode node; + * + * dtb_node_for_each_subnode(node, parent) { + * Use node + * ... + * } + * + * Note that this is implemented as a macro and @node is used as + * iterator in the loop. The parent variable can be a constant or even a + * literal. + */ +#define dtb_node_for_each_subnode(node, parent) \ + for (node = dtb_node_first_subnode(parent); \ + dtb_node_valid(node); \ + node = dtb_node_next_subnode(node)) + +#ifdef RT_USING_FDT_FWNODE +extern const struct fwnode_operations of_fwnode_ops; +static inline void dtb_fwnode_init(struct dtb_node *node) +{ + fwnode_init(&node->fwnode, &of_fwnode_ops); +} +#endif + +#endif /* RT_FDT_H__ */ diff --git a/components/legacy/fdt/libfdt/SConscript b/components/legacy/fdt/libfdt/SConscript new file mode 100644 index 0000000000..9efdd16c0a --- /dev/null +++ b/components/legacy/fdt/libfdt/SConscript @@ -0,0 +1,10 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +CPPPATH = [cwd] + +group = DefineGroup('FDT', src, depend = ['RT_USING_FDTLIB'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/legacy/fdt/libfdt/fdt.c b/components/legacy/fdt/libfdt/fdt.c new file mode 100644 index 0000000000..ecc7e8abee --- /dev/null +++ b/components/legacy/fdt/libfdt/fdt.c @@ -0,0 +1,249 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" +#include "fdt.h" +#include "libfdt.h" +#include "libfdt_internal.h" + +int fdt_check_header(const void *fdt) +{ + if (fdt_magic(fdt) == FDT_MAGIC) { + /* Complete tree */ + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + /* Unfinished sequential-write blob */ + if (fdt_size_dt_struct(fdt) == 0) + return -FDT_ERR_BADSTATE; + } else { + return -FDT_ERR_BADMAGIC; + } + + return 0; +} + +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) +{ + unsigned absoffset = offset + fdt_off_dt_struct(fdt); + + if ((absoffset < offset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; + + if (fdt_version(fdt) >= 0x11) + if (((offset + len) < offset) + || ((offset + len) > fdt_size_dt_struct(fdt))) + return NULL; + + return _fdt_offset_ptr(fdt, offset); +} + +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) +{ + const fdt32_t *tagp, *lenp; + uint32_t tag; + int offset = startoffset; + const char *p; + + *nextoffset = -FDT_ERR_TRUNCATED; + tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); + if (!tagp) + return FDT_END; /* premature end */ + tag = fdt32_to_cpu(*tagp); + offset += FDT_TAGSIZE; + + *nextoffset = -FDT_ERR_BADSTRUCTURE; + switch (tag) { + case FDT_BEGIN_NODE: + /* skip name */ + do { + p = fdt_offset_ptr(fdt, offset++, 1); + } while (p && (*p != '\0')); + if (!p) + return FDT_END; /* premature end */ + break; + + case FDT_PROP: + lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); + if (!lenp) + return FDT_END; /* premature end */ + /* skip-name offset, length and value */ + offset += sizeof(struct fdt_property) - FDT_TAGSIZE + + fdt32_to_cpu(*lenp); + break; + + case FDT_END: + case FDT_END_NODE: + case FDT_NOP: + break; + + default: + return FDT_END; + } + + if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) + return FDT_END; /* premature end */ + + *nextoffset = FDT_TAGALIGN(offset); + return tag; +} + +int _fdt_check_node_offset(const void *fdt, int offset) +{ + if ((offset < 0) || (offset % FDT_TAGSIZE) + || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int _fdt_check_prop_offset(const void *fdt, int offset) +{ + if ((offset < 0) || (offset % FDT_TAGSIZE) + || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int fdt_next_node(const void *fdt, int offset, int *depth) +{ + int nextoffset = 0; + uint32_t tag; + + if (offset >= 0) + if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) + return nextoffset; + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_PROP: + case FDT_NOP: + break; + + case FDT_BEGIN_NODE: + if (depth) + (*depth)++; + break; + + case FDT_END_NODE: + if (depth && ((--(*depth)) < 0)) + return nextoffset; + break; + + case FDT_END: + if ((nextoffset >= 0) + || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) + return -FDT_ERR_NOTFOUND; + else + return nextoffset; + } + } while (tag != FDT_BEGIN_NODE); + + return offset; +} + +int fdt_first_subnode(const void *fdt, int offset) +{ + int depth = 0; + + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth != 1) + return -FDT_ERR_NOTFOUND; + + return offset; +} + +int fdt_next_subnode(const void *fdt, int offset) +{ + int depth = 1; + + /* + * With respect to the parent, the depth of the next subnode will be + * the same as the last. + */ + do { + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth < 1) + return -FDT_ERR_NOTFOUND; + } while (depth > 1); + + return offset; +} + +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) +{ + int len = strlen(s) + 1; + const char *last = strtab + tabsize - len; + const char *p; + + for (p = strtab; p <= last; p++) + if (memcmp(p, s, len) == 0) + return p; + return NULL; +} + +int fdt_move(const void *fdt, void *buf, int bufsize) +{ + FDT_CHECK_HEADER(fdt); + + if (fdt_totalsize(fdt) > bufsize) + return -FDT_ERR_NOSPACE; + + memmove(buf, fdt, fdt_totalsize(fdt)); + return 0; +} diff --git a/components/legacy/fdt/libfdt/fdt.h b/components/legacy/fdt/libfdt/fdt.h new file mode 100644 index 0000000000..a00161cced --- /dev/null +++ b/components/legacy/fdt/libfdt/fdt.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-20 RT-Thread the first version + */ + +#ifndef _FDT_H +#define _FDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __ASSEMBLY__ + +#include +#include +#include + +struct fdt_header { + fdt32_t magic; /* magic word FDT_MAGIC */ + fdt32_t totalsize; /* total size of DT block */ + fdt32_t off_dt_struct; /* offset to structure */ + fdt32_t off_dt_strings; /* offset to strings */ + fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ + fdt32_t version; /* format version */ + fdt32_t last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + fdt32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + fdt32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + fdt32_t size_dt_struct; /* size of the structure block */ +}; + +struct fdt_reserve_entry { + fdt64_t address; + fdt64_t size; +}; + +struct fdt_node_header { + fdt32_t tag; + char name[0]; +}; + +struct fdt_property { + fdt32_t tag; + fdt32_t len; + fdt32_t nameoff; + char data[0]; +}; + +#endif /* !__ASSEMBLY */ + +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_TAGSIZE sizeof(fdt32_t) + +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, + size, content */ +#define FDT_NOP 0x4 /* nop */ +#define FDT_END 0x9 + +#define FDT_V1_SIZE (7*sizeof(fdt32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) +#define FDT_V16_SIZE FDT_V3_SIZE +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) + +#endif /* _FDT_H */ diff --git a/components/legacy/fdt/libfdt/fdt_addresses.c b/components/legacy/fdt/libfdt/fdt_addresses.c new file mode 100644 index 0000000000..a8f2ad5ebc --- /dev/null +++ b/components/legacy/fdt/libfdt/fdt_addresses.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2014 David Gibson + * Copyright (C) 2018 embedded brains GmbH + */ +#include "libfdt_env.h" +#include +#include +#include "libfdt_internal.h" + +static int fdt_cells(const void *fdt, int nodeoffset, const char *name) +{ + const fdt32_t *c; + uint32_t val; + int len; + + c = fdt_getprop(fdt, nodeoffset, name, &len); + if (!c) + return len; + + if (len != sizeof(*c)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*c); + if (val > FDT_MAX_NCELLS) + return -FDT_ERR_BADNCELLS; + + return (int)val; +} + +int fdt_address_cells(const void *fdt, int nodeoffset) +{ + int val; + + val = fdt_cells(fdt, nodeoffset, "#address-cells"); + if (val == 0) + return -FDT_ERR_BADNCELLS; + if (val == -FDT_ERR_NOTFOUND) + return 2; + return val; +} + +int fdt_size_cells(const void *fdt, int nodeoffset) +{ + int val; + + val = fdt_cells(fdt, nodeoffset, "#size-cells"); + if (val == -FDT_ERR_NOTFOUND) + return 1; + return val; +} + +/* This function assumes that [address|size]_cells is 1 or 2 */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size) +{ + int addr_cells, size_cells, ret; + uint8_t data[sizeof(fdt64_t) * 2], *prop; + + ret = fdt_address_cells(fdt, parent); + if (ret < 0) + return ret; + addr_cells = ret; + + ret = fdt_size_cells(fdt, parent); + if (ret < 0) + return ret; + size_cells = ret; + + /* check validity of address */ + prop = data; + if (addr_cells == 1) { + if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)addr); + } else if (addr_cells == 2) { + fdt64_st(prop, addr); + } else { + return -FDT_ERR_BADNCELLS; + } + + /* check validity of size */ + prop += addr_cells * sizeof(fdt32_t); + if (size_cells == 1) { + if (size > UINT32_MAX) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)size); + } else if (size_cells == 2) { + fdt64_st(prop, size); + } else { + return -FDT_ERR_BADNCELLS; + } + + return fdt_appendprop(fdt, nodeoffset, name, data, + (addr_cells + size_cells) * sizeof(fdt32_t)); +} diff --git a/components/legacy/fdt/libfdt/fdt_empty_tree.c b/components/legacy/fdt/libfdt/fdt_empty_tree.c new file mode 100644 index 0000000000..0f317a4726 --- /dev/null +++ b/components/legacy/fdt/libfdt/fdt_empty_tree.c @@ -0,0 +1,84 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2012 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include "fdt.h" +#include "libfdt.h" + +#include "libfdt_internal.h" + +int fdt_create_empty_tree(void *buf, int bufsize) +{ + int err; + + err = fdt_create(buf, bufsize); + if (err) + return err; + + err = fdt_finish_reservemap(buf); + if (err) + return err; + + err = fdt_begin_node(buf, ""); + if (err) + return err; + + err = fdt_end_node(buf); + if (err) + return err; + + err = fdt_finish(buf); + if (err) + return err; + + return fdt_open_into(buf, buf, bufsize); +} + diff --git a/components/legacy/fdt/libfdt/fdt_ro.c b/components/legacy/fdt/libfdt/fdt_ro.c new file mode 100644 index 0000000000..ff8b7fbdc0 --- /dev/null +++ b/components/legacy/fdt/libfdt/fdt_ro.c @@ -0,0 +1,701 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" +#include "fdt.h" +#include "libfdt.h" +#include "libfdt_internal.h" + +static int _fdt_nodename_eq(const void *fdt, int offset, + const char *s, int len) +{ + const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); + + if (! p) + /* short match */ + return 0; + + if (memcmp(p, s, len) != 0) + return 0; + + if (p[len] == '\0') + return 1; + else if (!memchr(s, '@', len) && (p[len] == '@')) + return 1; + else + return 0; +} + +const char *fdt_string(const void *fdt, int stroffset) +{ + return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; +} + +static int _fdt_string_eq(const void *fdt, int stroffset, + const char *s, int len) +{ + const char *p = fdt_string(fdt, stroffset); + + return (strlen(p) == len) && (memcmp(p, s, len) == 0); +} + +uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t max_phandle = 0; + int offset; + + for (offset = fdt_next_node(fdt, -1, NULL);; + offset = fdt_next_node(fdt, offset, NULL)) { + uint32_t phandle; + + if (offset == -FDT_ERR_NOTFOUND) + return max_phandle; + + if (offset < 0) + return (uint32_t)-1; + + phandle = fdt_get_phandle(fdt, offset); + if (phandle == (uint32_t)-1) + continue; + + if (phandle > max_phandle) + max_phandle = phandle; + } + + return 0; +} + +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) +{ + FDT_CHECK_HEADER(fdt); + *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); + *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); + return 0; +} + +int fdt_num_mem_rsv(const void *fdt) +{ + int i = 0; + + while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) + i++; + return i; +} + +static int _nextprop(const void *fdt, int offset) +{ + uint32_t tag; + int nextoffset; + + do { + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_END: + if (nextoffset >= 0) + return -FDT_ERR_BADSTRUCTURE; + else + return nextoffset; + + case FDT_PROP: + return offset; + } + offset = nextoffset; + } while (tag == FDT_NOP); + + return -FDT_ERR_NOTFOUND; +} + +int fdt_subnode_offset_namelen(const void *fdt, int offset, + const char *name, int namelen) +{ + int depth; + + FDT_CHECK_HEADER(fdt); + + for (depth = 0; + (offset >= 0) && (depth >= 0); + offset = fdt_next_node(fdt, offset, &depth)) + if ((depth == 1) + && _fdt_nodename_eq(fdt, offset, name, namelen)) + return offset; + + if (depth < 0) + return -FDT_ERR_NOTFOUND; + return offset; /* error */ +} + +int fdt_subnode_offset(const void *fdt, int parentoffset, + const char *name) +{ + return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) +{ + const char *end = path + namelen; + const char *p = path; + int offset = 0; + + FDT_CHECK_HEADER(fdt); + + /* see if we have an alias */ + if (*path != '/') { + const char *q = memchr(path, '/', end - p); + + if (!q) + q = end; + + p = fdt_get_alias_namelen(fdt, p, q - p); + if (!p) + return -FDT_ERR_BADPATH; + offset = fdt_path_offset(fdt, p); + + p = q; + } + + while (p < end) { + const char *q; + + while (*p == '/') { + p++; + if (p == end) + return offset; + } + q = memchr(p, '/', end - p); + if (! q) + q = end; + + offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); + if (offset < 0) + return offset; + + p = q; + } + + return offset; +} + +int fdt_path_offset(const void *fdt, const char *path) +{ + return fdt_path_offset_namelen(fdt, path, strlen(path)); +} + +const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) +{ + const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); + int err; + + if (((err = fdt_check_header(fdt)) != 0) + || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) + goto fail; + + if (len) + *len = strlen(nh->name); + + return nh->name; + + fail: + if (len) + *len = err; + return NULL; +} + +int fdt_first_property_offset(const void *fdt, int nodeoffset) +{ + int offset; + + if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + return offset; + + return _nextprop(fdt, offset); +} + +int fdt_next_property_offset(const void *fdt, int offset) +{ + if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) + return offset; + + return _nextprop(fdt, offset); +} + +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp) +{ + int err; + const struct fdt_property *prop; + + if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { + if (lenp) + *lenp = err; + return NULL; + } + + prop = _fdt_offset_ptr(fdt, offset); + + if (lenp) + *lenp = fdt32_to_cpu(prop->len); + + return prop; +} + +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int offset, + const char *name, + int namelen, int *lenp) +{ + for (offset = fdt_first_property_offset(fdt, offset); + (offset >= 0); + (offset = fdt_next_property_offset(fdt, offset))) { + const struct fdt_property *prop; + + if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { + offset = -FDT_ERR_INTERNAL; + break; + } + if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), + name, namelen)) + return prop; + } + + if (lenp) + *lenp = offset; + return NULL; +} + +const struct fdt_property *fdt_get_property(const void *fdt, + int nodeoffset, + const char *name, int *lenp) +{ + return fdt_get_property_namelen(fdt, nodeoffset, name, + strlen(name), lenp); +} + +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp) +{ + const struct fdt_property *prop; + + prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); + if (! prop) + return NULL; + + return prop->data; +} + +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp) +{ + const struct fdt_property *prop; + + prop = fdt_get_property_by_offset(fdt, offset, lenp); + if (!prop) + return NULL; + if (namep) + *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + return prop->data; +} + +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); +} + +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) +{ + const fdt32_t *php; + int len; + + /* FIXME: This is a bit sub-optimal, since we potentially scan + * over all the properties twice. */ + php = fdt_getprop(fdt, nodeoffset, "phandle", &len); + if (!php || (len != sizeof(*php))) { + php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); + if (!php || (len != sizeof(*php))) + return 0; + } + + return fdt32_to_cpu(*php); +} + +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen) +{ + int aliasoffset; + + aliasoffset = fdt_path_offset(fdt, "/aliases"); + if (aliasoffset < 0) + return NULL; + + return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); +} + +const char *fdt_get_alias(const void *fdt, const char *name) +{ + return fdt_get_alias_namelen(fdt, name, strlen(name)); +} + +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) +{ + int pdepth = 0, p = 0; + int offset, depth, namelen; + const char *name; + + FDT_CHECK_HEADER(fdt); + + if (buflen < 2) + return -FDT_ERR_NOSPACE; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + while (pdepth > depth) { + do { + p--; + } while (buf[p-1] != '/'); + pdepth--; + } + + if (pdepth >= depth) { + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if ((p + namelen + 1) <= buflen) { + memcpy(buf + p, name, namelen); + p += namelen; + buf[p++] = '/'; + pdepth++; + } + } + + if (offset == nodeoffset) { + if (pdepth < (depth + 1)) + return -FDT_ERR_NOSPACE; + + if (p > 1) /* special case so that root path is "/", not "" */ + p--; + buf[p] = '\0'; + return 0; + } + } + + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + + return offset; /* error from fdt_next_node() */ +} + +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth) +{ + int offset, depth; + int supernodeoffset = -FDT_ERR_INTERNAL; + + FDT_CHECK_HEADER(fdt); + + if (supernodedepth < 0) + return -FDT_ERR_NOTFOUND; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + if (depth == supernodedepth) + supernodeoffset = offset; + + if (offset == nodeoffset) { + if (nodedepth) + *nodedepth = depth; + + if (supernodedepth > depth) + return -FDT_ERR_NOTFOUND; + else + return supernodeoffset; + } + } + + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_depth(const void *fdt, int nodeoffset) +{ + int nodedepth; + int err; + + err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); + if (err) + return (err < 0) ? err : -FDT_ERR_INTERNAL; + return nodedepth; +} + +int fdt_parent_offset(const void *fdt, int nodeoffset) +{ + int nodedepth = fdt_node_depth(fdt, nodeoffset); + + if (nodedepth < 0) + return nodedepth; + return fdt_supernode_atdepth_offset(fdt, nodeoffset, + nodedepth - 1, NULL); +} + +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen) +{ + int offset; + const void *val; + int len; + + FDT_CHECK_HEADER(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_getprop(), then if that didn't + * find what we want, we scan over them again making our way + * to the next node. Still it's the easiest to implement + * approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + val = fdt_getprop(fdt, offset, propname, &len); + if (val && (len == proplen) + && (memcmp(val, propval, len) == 0)) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) +{ + int offset; + + if ((phandle == 0) || (phandle == -1)) + return -FDT_ERR_BADPHANDLE; + + FDT_CHECK_HEADER(fdt); + + /* FIXME: The algorithm here is pretty horrible: we + * potentially scan each property of a node in + * fdt_get_phandle(), then if that didn't find what + * we want, we scan over them again making our way to the next + * node. Still it's the easiest to implement approach; + * performance can come later. */ + for (offset = fdt_next_node(fdt, -1, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + if (fdt_get_phandle(fdt, offset) == phandle) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) +{ + int len = strlen(str); + const char *p; + + while (listlen >= len) { + if (memcmp(str, strlist, len+1) == 0) + return 1; + p = memchr(strlist, '\0', listlen); + if (!p) + return 0; /* malformed strlist.. */ + listlen -= (p-strlist) + 1; + strlist = p + 1; + } + return 0; +} + +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) +{ + const char *list, *end; + int length, count = 0; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + list += length; + count++; + } + + return count; +} + +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string) +{ + int length, len, idx = 0; + const char *list, *end; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + len = strlen(string) + 1; + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + if (length == len && memcmp(list, string, length) == 0) + return idx; + + list += length; + idx++; + } + + return -FDT_ERR_NOTFOUND; +} + +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int idx, + int *lenp) +{ + const char *list, *end; + int length; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) { + if (lenp) + *lenp = length; + + return NULL; + } + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) { + if (lenp) + *lenp = -FDT_ERR_BADVALUE; + + return NULL; + } + + if (idx == 0) { + if (lenp) + *lenp = length - 1; + + return list; + } + + list += length; + idx--; + } + + if (lenp) + *lenp = -FDT_ERR_NOTFOUND; + + return NULL; +} + +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible) +{ + const void *prop; + int len; + + prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); + if (!prop) + return len; + + return !fdt_stringlist_contains(prop, len, compatible); +} + +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible) +{ + int offset, err; + + FDT_CHECK_HEADER(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_node_check_compatible(), then if + * that didn't find what we want, we scan over them again + * making our way to the next node. Still it's the easiest to + * implement approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + err = fdt_node_check_compatible(fdt, offset, compatible); + if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) + return err; + else if (err == 0) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} diff --git a/components/legacy/fdt/libfdt/fdt_rw.c b/components/legacy/fdt/libfdt/fdt_rw.c new file mode 100644 index 0000000000..58827ef898 --- /dev/null +++ b/components/legacy/fdt/libfdt/fdt_rw.c @@ -0,0 +1,491 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" +#include "fdt.h" +#include "libfdt.h" +#include "libfdt_internal.h" + +static int _fdt_blocks_misordered(const void *fdt, + int mem_rsv_size, int struct_size) +{ + return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) + || (fdt_off_dt_struct(fdt) < + (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) + || (fdt_off_dt_strings(fdt) < + (fdt_off_dt_struct(fdt) + struct_size)) + || (fdt_totalsize(fdt) < + (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); +} + +static int _fdt_rw_check_header(void *fdt) +{ + FDT_CHECK_HEADER(fdt); + + if (fdt_version(fdt) < 17) + return -FDT_ERR_BADVERSION; + if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_BADLAYOUT; + if (fdt_version(fdt) > 17) + fdt_set_version(fdt, 17); + + return 0; +} + +#define FDT_RW_CHECK_HEADER(fdt) \ + { \ + int __err; \ + if ((__err = _fdt_rw_check_header(fdt)) != 0) \ + return __err; \ + } + +static inline int _fdt_data_size(void *fdt) +{ + return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); +} + +static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) +{ + char *p = splicepoint; + char *end = (char *)fdt + _fdt_data_size(fdt); + + if (oldlen <= 0) + return -FDT_ERR_BADOFFSET; + if (((p + oldlen) < p) || ((p + oldlen) > end)) + return -FDT_ERR_BADOFFSET; + if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) + return -FDT_ERR_BADOFFSET; + if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) + return -FDT_ERR_NOSPACE; + memmove(p + newlen, p + oldlen, end - p - oldlen); + return 0; +} + +static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, + int oldn, int newn) +{ + int delta = (newn - oldn) * sizeof(*p); + int err; + err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); + if (err) + return err; + fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +static int _fdt_splice_struct(void *fdt, void *p, + int oldlen, int newlen) +{ + int delta = newlen - oldlen; + int err; + + if ((err = _fdt_splice(fdt, p, oldlen, newlen))) + return err; + + fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +static int _fdt_splice_string(void *fdt, int newlen) +{ + void *p = (char *)fdt + + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + int err; + + if ((err = _fdt_splice(fdt, p, 0, newlen))) + return err; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); + return 0; +} + +static int _fdt_find_add_string(void *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); + const char *p; + char *new; + int len = strlen(s) + 1; + int err; + + p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); + if (p) + /* found it */ + return (p - strtab); + + new = strtab + fdt_size_dt_strings(fdt); + err = _fdt_splice_string(fdt, len); + if (err) + return err; + + memcpy(new, s, len); + return (new - strtab); +} + +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) +{ + struct fdt_reserve_entry *re; + int err; + + FDT_RW_CHECK_HEADER(fdt); + + re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); + err = _fdt_splice_mem_rsv(fdt, re, 0, 1); + if (err) + return err; + + re->address = cpu_to_fdt64(address); + re->size = cpu_to_fdt64(size); + return 0; +} + +int fdt_del_mem_rsv(void *fdt, int n) +{ + struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); + + FDT_RW_CHECK_HEADER(fdt); + + if (n >= fdt_num_mem_rsv(fdt)) + return -FDT_ERR_NOTFOUND; + + return _fdt_splice_mem_rsv(fdt, re, 1, 0); +} + +static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int oldlen; + int err; + + *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (! (*prop)) + return oldlen; + + if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(len)))) + return err; + + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int proplen; + int nextoffset; + int namestroff; + int err; + + if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + return nextoffset; + + namestroff = _fdt_find_add_string(fdt, name); + if (namestroff < 0) + return namestroff; + + *prop = _fdt_offset_ptr_w(fdt, nextoffset); + proplen = sizeof(**prop) + FDT_TAGALIGN(len); + + err = _fdt_splice_struct(fdt, *prop, 0, proplen); + if (err) + return err; + + (*prop)->tag = cpu_to_fdt32(FDT_PROP); + (*prop)->nameoff = cpu_to_fdt32(namestroff); + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +int fdt_set_name(void *fdt, int nodeoffset, const char *name) +{ + char *namep; + int oldlen, newlen; + int err; + + FDT_RW_CHECK_HEADER(fdt); + + namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); + if (!namep) + return oldlen; + + newlen = strlen(name); + + err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), + FDT_TAGALIGN(newlen+1)); + if (err) + return err; + + memcpy(namep, name, newlen+1); + return 0; +} + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err; + + FDT_RW_CHECK_HEADER(fdt); + + err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); + if (err == -FDT_ERR_NOTFOUND) + err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + + if (len) + memcpy(prop->data, val, len); + return 0; +} + +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err, oldlen, newlen; + + FDT_RW_CHECK_HEADER(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (prop) { + newlen = len + oldlen; + err = _fdt_splice_struct(fdt, prop->data, + FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(newlen)); + if (err) + return err; + prop->len = cpu_to_fdt32(newlen); + memcpy(prop->data + oldlen, val, len); + } else { + err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + memcpy(prop->data, val, len); + } + return 0; +} + +int fdt_delprop(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len, proplen; + + FDT_RW_CHECK_HEADER(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (! prop) + return len; + + proplen = sizeof(*prop) + FDT_TAGALIGN(len); + return _fdt_splice_struct(fdt, prop, proplen, 0); +} + +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen) +{ + struct fdt_node_header *nh; + int offset, nextoffset; + int nodelen; + int err; + uint32_t tag; + fdt32_t *endtag; + + FDT_RW_CHECK_HEADER(fdt); + + offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); + if (offset >= 0) + return -FDT_ERR_EXISTS; + else if (offset != -FDT_ERR_NOTFOUND) + return offset; + + /* Try to place the new node after the parent's properties */ + fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); + + nh = _fdt_offset_ptr_w(fdt, offset); + nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; + + err = _fdt_splice_struct(fdt, nh, 0, nodelen); + if (err) + return err; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); + memcpy(nh->name, name, namelen); + endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); + *endtag = cpu_to_fdt32(FDT_END_NODE); + + return offset; +} + +int fdt_add_subnode(void *fdt, int parentoffset, const char *name) +{ + return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_del_node(void *fdt, int nodeoffset) +{ + int endoffset; + + FDT_RW_CHECK_HEADER(fdt); + + endoffset = _fdt_node_end_offset(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), + endoffset - nodeoffset, 0); +} + +static void _fdt_packblocks(const char *old, char *new, + int mem_rsv_size, int struct_size) +{ + int mem_rsv_off, struct_off, strings_off; + + mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); + struct_off = mem_rsv_off + mem_rsv_size; + strings_off = struct_off + struct_size; + + memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); + fdt_set_off_mem_rsvmap(new, mem_rsv_off); + + memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); + fdt_set_off_dt_struct(new, struct_off); + fdt_set_size_dt_struct(new, struct_size); + + memmove(new + strings_off, old + fdt_off_dt_strings(old), + fdt_size_dt_strings(old)); + fdt_set_off_dt_strings(new, strings_off); + fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); +} + +int fdt_open_into(const void *fdt, void *buf, int bufsize) +{ + int err; + int mem_rsv_size, struct_size; + int newsize; + const char *fdtstart = fdt; + const char *fdtend = fdtstart + fdt_totalsize(fdt); + char *tmp; + + FDT_CHECK_HEADER(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + + if (fdt_version(fdt) >= 17) { + struct_size = fdt_size_dt_struct(fdt); + } else { + struct_size = 0; + while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) + ; + if (struct_size < 0) + return struct_size; + } + + if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { + /* no further work necessary */ + err = fdt_move(fdt, buf, bufsize); + if (err) + return err; + fdt_set_version(buf, 17); + fdt_set_size_dt_struct(buf, struct_size); + fdt_set_totalsize(buf, bufsize); + return 0; + } + + /* Need to reorder */ + newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + + struct_size + fdt_size_dt_strings(fdt); + + if (bufsize < newsize) + return -FDT_ERR_NOSPACE; + + /* First attempt to build converted tree at beginning of buffer */ + tmp = buf; + /* But if that overlaps with the old tree... */ + if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { + /* Try right after the old tree instead */ + tmp = (char *)(uintptr_t)fdtend; + if ((tmp + newsize) > ((char *)buf + bufsize)) + return -FDT_ERR_NOSPACE; + } + + _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); + memmove(buf, tmp, newsize); + + fdt_set_magic(buf, FDT_MAGIC); + fdt_set_totalsize(buf, bufsize); + fdt_set_version(buf, 17); + fdt_set_last_comp_version(buf, 16); + fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); + + return 0; +} + +int fdt_pack(void *fdt) +{ + int mem_rsv_size; + + FDT_RW_CHECK_HEADER(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); + fdt_set_totalsize(fdt, _fdt_data_size(fdt)); + + return 0; +} diff --git a/components/legacy/fdt/libfdt/fdt_strerror.c b/components/legacy/fdt/libfdt/fdt_strerror.c new file mode 100644 index 0000000000..a62aad11ed --- /dev/null +++ b/components/legacy/fdt/libfdt/fdt_strerror.c @@ -0,0 +1,100 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" +#include "fdt.h" +#include "libfdt.h" +#include "libfdt_internal.h" + +struct fdt_errtabent { + const char *str; +}; + +#define FDT_ERRTABENT(val) \ + [(val)] = { .str = #val, } + +static struct fdt_errtabent fdt_errtable[] = { + FDT_ERRTABENT(FDT_ERR_NOTFOUND), + FDT_ERRTABENT(FDT_ERR_EXISTS), + FDT_ERRTABENT(FDT_ERR_NOSPACE), + + FDT_ERRTABENT(FDT_ERR_BADOFFSET), + FDT_ERRTABENT(FDT_ERR_BADPATH), + FDT_ERRTABENT(FDT_ERR_BADPHANDLE), + FDT_ERRTABENT(FDT_ERR_BADSTATE), + + FDT_ERRTABENT(FDT_ERR_TRUNCATED), + FDT_ERRTABENT(FDT_ERR_BADMAGIC), + FDT_ERRTABENT(FDT_ERR_BADVERSION), + FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), + FDT_ERRTABENT(FDT_ERR_BADLAYOUT), + FDT_ERRTABENT(FDT_ERR_INTERNAL), + FDT_ERRTABENT(FDT_ERR_BADNCELLS), + FDT_ERRTABENT(FDT_ERR_BADVALUE), + FDT_ERRTABENT(FDT_ERR_BADOVERLAY), + FDT_ERRTABENT(FDT_ERR_NOPHANDLES), +}; +#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) + +const char *fdt_strerror(int errval) +{ + if (errval > 0) + return ""; + else if (errval == 0) + return ""; + else if (errval > -FDT_ERRTABSIZE) { + const char *s = fdt_errtable[-errval].str; + + if (s) + return s; + } + + return ""; +} diff --git a/components/legacy/fdt/libfdt/fdt_sw.c b/components/legacy/fdt/libfdt/fdt_sw.c new file mode 100644 index 0000000000..4834d01b48 --- /dev/null +++ b/components/legacy/fdt/libfdt/fdt_sw.c @@ -0,0 +1,286 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" +#include "fdt.h" +#include "libfdt.h" +#include "libfdt_internal.h" + +static int _fdt_sw_check_header(void *fdt) +{ + if (fdt_magic(fdt) != FDT_SW_MAGIC) + return -FDT_ERR_BADMAGIC; + /* FIXME: should check more details about the header state */ + return 0; +} + +#define FDT_SW_CHECK_HEADER(fdt) \ + { \ + int err; \ + if ((err = _fdt_sw_check_header(fdt)) != 0) \ + return err; \ + } + +static void *_fdt_grab_space(void *fdt, size_t len) +{ + int offset = fdt_size_dt_struct(fdt); + int spaceleft; + + spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) + - fdt_size_dt_strings(fdt); + + if ((offset + len < offset) || (offset + len > spaceleft)) + return NULL; + + fdt_set_size_dt_struct(fdt, offset + len); + return _fdt_offset_ptr_w(fdt, offset); +} + +int fdt_create(void *buf, int bufsize) +{ + void *fdt = buf; + + if (bufsize < sizeof(struct fdt_header)) + return -FDT_ERR_NOSPACE; + + memset(buf, 0, bufsize); + + fdt_set_magic(fdt, FDT_SW_MAGIC); + fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_totalsize(fdt, bufsize); + + fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry))); + fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); + fdt_set_off_dt_strings(fdt, bufsize); + + return 0; +} + +int fdt_resize(void *fdt, void *buf, int bufsize) +{ + size_t headsize, tailsize; + char *oldtail, *newtail; + + FDT_SW_CHECK_HEADER(fdt); + + headsize = fdt_off_dt_struct(fdt); + tailsize = fdt_size_dt_strings(fdt); + + if ((headsize + tailsize) > bufsize) + return -FDT_ERR_NOSPACE; + + oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; + newtail = (char *)buf + bufsize - tailsize; + + /* Two cases to avoid clobbering data if the old and new + * buffers partially overlap */ + if (buf <= fdt) { + memmove(buf, fdt, headsize); + memmove(newtail, oldtail, tailsize); + } else { + memmove(newtail, oldtail, tailsize); + memmove(buf, fdt, headsize); + } + + fdt_set_off_dt_strings(buf, bufsize); + fdt_set_totalsize(buf, bufsize); + + return 0; +} + +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) +{ + struct fdt_reserve_entry *re; + int offset; + + FDT_SW_CHECK_HEADER(fdt); + + if (fdt_size_dt_struct(fdt)) + return -FDT_ERR_BADSTATE; + + offset = fdt_off_dt_struct(fdt); + if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) + return -FDT_ERR_NOSPACE; + + re = (struct fdt_reserve_entry *)((char *)fdt + offset); + re->address = cpu_to_fdt64(addr); + re->size = cpu_to_fdt64(size); + + fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); + + return 0; +} + +int fdt_finish_reservemap(void *fdt) +{ + return fdt_add_reservemap_entry(fdt, 0, 0); +} + +int fdt_begin_node(void *fdt, const char *name) +{ + struct fdt_node_header *nh; + int namelen = strlen(name) + 1; + + FDT_SW_CHECK_HEADER(fdt); + + nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); + if (! nh) + return -FDT_ERR_NOSPACE; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memcpy(nh->name, name, namelen); + return 0; +} + +int fdt_end_node(void *fdt) +{ + fdt32_t *en; + + FDT_SW_CHECK_HEADER(fdt); + + en = _fdt_grab_space(fdt, FDT_TAGSIZE); + if (! en) + return -FDT_ERR_NOSPACE; + + *en = cpu_to_fdt32(FDT_END_NODE); + return 0; +} + +static int _fdt_find_add_string(void *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + const char *p; + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + int struct_top, offset; + + p = _fdt_find_string(strtab - strtabsize, strtabsize, s); + if (p) + return p - strtab; + + /* Add it */ + offset = -strtabsize - len; + struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + if (fdt_totalsize(fdt) + offset < struct_top) + return 0; /* no more room :( */ + + memcpy(strtab + offset, s, len); + fdt_set_size_dt_strings(fdt, strtabsize + len); + return offset; +} + +int fdt_property(void *fdt, const char *name, const void *val, int len) +{ + struct fdt_property *prop; + int nameoff; + + FDT_SW_CHECK_HEADER(fdt); + + nameoff = _fdt_find_add_string(fdt, name); + if (nameoff == 0) + return -FDT_ERR_NOSPACE; + + prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); + if (! prop) + return -FDT_ERR_NOSPACE; + + prop->tag = cpu_to_fdt32(FDT_PROP); + prop->nameoff = cpu_to_fdt32(nameoff); + prop->len = cpu_to_fdt32(len); + memcpy(prop->data, val, len); + return 0; +} + +int fdt_finish(void *fdt) +{ + char *p = (char *)fdt; + fdt32_t *end; + int oldstroffset, newstroffset; + uint32_t tag; + int offset, nextoffset; + + FDT_SW_CHECK_HEADER(fdt); + + /* Add terminator */ + end = _fdt_grab_space(fdt, sizeof(*end)); + if (! end) + return -FDT_ERR_NOSPACE; + *end = cpu_to_fdt32(FDT_END); + + /* Relocate the string table */ + oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); + newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); + fdt_set_off_dt_strings(fdt, newstroffset); + + /* Walk the structure, correcting string offsets */ + offset = 0; + while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { + if (tag == FDT_PROP) { + struct fdt_property *prop = + _fdt_offset_ptr_w(fdt, offset); + int nameoff; + + nameoff = fdt32_to_cpu(prop->nameoff); + nameoff += fdt_size_dt_strings(fdt); + prop->nameoff = cpu_to_fdt32(nameoff); + } + offset = nextoffset; + } + if (nextoffset < 0) + return nextoffset; + + /* Finally, adjust the header */ + fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); + fdt_set_magic(fdt, FDT_MAGIC); + return 0; +} diff --git a/components/legacy/fdt/libfdt/fdt_wip.c b/components/legacy/fdt/libfdt/fdt_wip.c new file mode 100644 index 0000000000..a817fefdbe --- /dev/null +++ b/components/legacy/fdt/libfdt/fdt_wip.c @@ -0,0 +1,137 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" +#include "fdt.h" +#include "libfdt.h" +#include "libfdt_internal.h" + +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len) +{ + void *propval; + int proplen; + + propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, + &proplen); + if (!propval) + return proplen; + + if (proplen < (len + idx)) + return -FDT_ERR_NOSPACE; + + memcpy((char *)propval + idx, val, len); + return 0; +} + +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + const void *propval; + int proplen; + + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); + if (! propval) + return proplen; + + if (proplen != len) + return -FDT_ERR_NOSPACE; + + return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, + strlen(name), 0, + val, len); +} + +static void _fdt_nop_region(void *start, int len) +{ + fdt32_t *p; + + for (p = start; (char *)p < ((char *)start + len); p++) + *p = cpu_to_fdt32(FDT_NOP); +} + +int fdt_nop_property(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len; + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (! prop) + return len; + + _fdt_nop_region(prop, len + sizeof(*prop)); + + return 0; +} + +int _fdt_node_end_offset(void *fdt, int offset) +{ + int depth = 0; + + while ((offset >= 0) && (depth >= 0)) + offset = fdt_next_node(fdt, offset, &depth); + + return offset; +} + +int fdt_nop_node(void *fdt, int nodeoffset) +{ + int endoffset; + + endoffset = _fdt_node_end_offset(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), + endoffset - nodeoffset); + return 0; +} diff --git a/components/legacy/fdt/libfdt/libfdt.h b/components/legacy/fdt/libfdt/libfdt.h new file mode 100644 index 0000000000..8593f10ae8 --- /dev/null +++ b/components/legacy/fdt/libfdt/libfdt.h @@ -0,0 +1,1883 @@ +#ifndef _LIBFDT_H +#define _LIBFDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libfdt_env.h" +#include "fdt.h" + +#define FDT_FIRST_SUPPORTED_VERSION 0x10 +#define FDT_LAST_SUPPORTED_VERSION 0x11 + +/* Error codes: informative error codes */ +#define FDT_ERR_NOTFOUND 1 + /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ +#define FDT_ERR_EXISTS 2 + /* FDT_ERR_EXISTS: Attempted to create a node or property which + * already exists */ +#define FDT_ERR_NOSPACE 3 + /* FDT_ERR_NOSPACE: Operation needed to expand the device + * tree, but its buffer did not have sufficient space to + * contain the expanded tree. Use fdt_open_into() to move the + * device tree to a buffer with more space. */ + +/* Error codes: codes for bad parameters */ +#define FDT_ERR_BADOFFSET 4 + /* FDT_ERR_BADOFFSET: Function was passed a structure block + * offset which is out-of-bounds, or which points to an + * unsuitable part of the structure for the operation. */ +#define FDT_ERR_BADPATH 5 + /* FDT_ERR_BADPATH: Function was passed a badly formatted path + * (e.g. missing a leading / for a function which requires an + * absolute path) */ +#define FDT_ERR_BADPHANDLE 6 + /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. + * This can be caused either by an invalid phandle property + * length, or the phandle value was either 0 or -1, which are + * not permitted. */ +#define FDT_ERR_BADSTATE 7 + /* FDT_ERR_BADSTATE: Function was passed an incomplete device + * tree created by the sequential-write functions, which is + * not sufficiently complete for the requested operation. */ + +/* Error codes: codes for bad device tree blobs */ +#define FDT_ERR_TRUNCATED 8 + /* FDT_ERR_TRUNCATED: Structure block of the given device tree + * ends without an FDT_END tag. */ +#define FDT_ERR_BADMAGIC 9 + /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a + * device tree at all - it is missing the flattened device + * tree magic number. */ +#define FDT_ERR_BADVERSION 10 + /* FDT_ERR_BADVERSION: Given device tree has a version which + * can't be handled by the requested operation. For + * read-write functions, this may mean that fdt_open_into() is + * required to convert the tree to the expected version. */ +#define FDT_ERR_BADSTRUCTURE 11 + /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt + * structure block or other serious error (e.g. misnested + * nodes, or subnodes preceding properties). */ +#define FDT_ERR_BADLAYOUT 12 + /* FDT_ERR_BADLAYOUT: For read-write functions, the given + * device tree has it's sub-blocks in an order that the + * function can't handle (memory reserve map, then structure, + * then strings). Use fdt_open_into() to reorganize the tree + * into a form suitable for the read-write operations. */ + +/* "Can't happen" error indicating a bug in libfdt */ +#define FDT_ERR_INTERNAL 13 + /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. + * Should never be returned, if it is, it indicates a bug in + * libfdt itself. */ + +/* Errors in device tree content */ +#define FDT_ERR_BADNCELLS 14 + /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells + * or similar property with a bad format or value */ + +#define FDT_ERR_BADVALUE 15 + /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected + * value. For example: a property expected to contain a string list + * is not NUL-terminated within the length of its value. */ + +#define FDT_ERR_BADOVERLAY 16 + /* FDT_ERR_BADOVERLAY: The device tree overlay, while + * correctly structured, cannot be applied due to some + * unexpected or missing value, property or node. */ + +#define FDT_ERR_NOPHANDLES 17 + /* FDT_ERR_NOPHANDLES: The device tree doesn't have any + * phandle available anymore without causing an overflow */ + +#define FDT_ERR_MAX 17 + +/* string.h for POSIX compatibility */ +#include +typedef unsigned int uint; +size_t strnlen (const char *, size_t); +char *strdup (const char *); +char *strchrnul (const char *, int); + +/**********************************************************************/ +/* Low-level functions (you probably don't need these) */ +/**********************************************************************/ + +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); +#endif +static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) +{ + return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); +} + +uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); + +static inline void fdt32_st(void *property, uint32_t value) +{ + uint8_t *bp = (uint8_t *)property; + + bp[0] = value >> 24; + bp[1] = (value >> 16) & 0xff; + bp[2] = (value >> 8) & 0xff; + bp[3] = value & 0xff; +} + +static inline void fdt64_st(void *property, uint64_t value) +{ + uint8_t *bp = (uint8_t *)property; + + bp[0] = value >> 56; + bp[1] = (value >> 48) & 0xff; + bp[2] = (value >> 40) & 0xff; + bp[3] = (value >> 32) & 0xff; + bp[4] = (value >> 24) & 0xff; + bp[5] = (value >> 16) & 0xff; + bp[6] = (value >> 8) & 0xff; + bp[7] = value & 0xff; +} + +/**********************************************************************/ +/* Traversal functions */ +/**********************************************************************/ + +int fdt_next_node(const void *fdt, int offset, int *depth); + +/** + * fdt_first_subnode() - get offset of first direct subnode + * + * @fdt: FDT blob + * @offset: Offset of node to check + * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none + */ +int fdt_first_subnode(const void *fdt, int offset); + +/** + * fdt_next_subnode() - get offset of next direct subnode + * + * After first calling fdt_first_subnode(), call this function repeatedly to + * get direct subnodes of a parent node. + * + * @fdt: FDT blob + * @offset: Offset of previous subnode + * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more + * subnodes + */ +int fdt_next_subnode(const void *fdt, int offset); + +/** + * fdt_for_each_subnode - iterate over all subnodes of a parent + * + * @node: child node (int, lvalue) + * @fdt: FDT blob (const void *) + * @parent: parent node (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_subnode(node, fdt, parent) { + * Use node + * ... + * } + * + * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and @node is used as + * iterator in the loop. The parent variable be constant or even a + * literal. + * + */ +#define fdt_for_each_subnode(node, fdt, parent) \ + for (node = fdt_first_subnode(fdt, parent); \ + node >= 0; \ + node = fdt_next_subnode(fdt, node)) + +/**********************************************************************/ +/* General functions */ +/**********************************************************************/ +#define fdt_get_header(fdt, field) \ + (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) +#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) +#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) +#define fdt_version(fdt) (fdt_get_header(fdt, version)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) + +#define __fdt_set_hdr(name) \ + static inline void fdt_set_##name(void *fdt, uint32_t val) \ + { \ + struct fdt_header *fdth = (struct fdt_header *)fdt; \ + fdth->name = cpu_to_fdt32(val); \ + } +__fdt_set_hdr(magic); +__fdt_set_hdr(totalsize); +__fdt_set_hdr(off_dt_struct); +__fdt_set_hdr(off_dt_strings); +__fdt_set_hdr(off_mem_rsvmap); +__fdt_set_hdr(version); +__fdt_set_hdr(last_comp_version); +__fdt_set_hdr(boot_cpuid_phys); +__fdt_set_hdr(size_dt_strings); +__fdt_set_hdr(size_dt_struct); +#undef __fdt_set_hdr + +/** + * fdt_check_header - sanity check a device tree or possible device tree + * @fdt: pointer to data which might be a flattened device tree + * + * fdt_check_header() checks that the given buffer contains what + * appears to be a flattened device tree with sane information in its + * header. + * + * returns: + * 0, if the buffer appears to contain a valid device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings, as above + */ +int fdt_check_header(const void *fdt); + +/** + * fdt_move - move a device tree around in memory + * @fdt: pointer to the device tree to move + * @buf: pointer to memory where the device is to be moved + * @bufsize: size of the memory space at buf + * + * fdt_move() relocates, if possible, the device tree blob located at + * fdt to the buffer at buf of size bufsize. The buffer may overlap + * with the existing device tree blob at fdt. Therefore, + * fdt_move(fdt, fdt, fdt_totalsize(fdt)) + * should always succeed. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_move(const void *fdt, void *buf, int bufsize); + +/**********************************************************************/ +/* Read-only functions */ +/**********************************************************************/ + +/** + * fdt_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * + * fdt_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds + */ +const char *fdt_string(const void *fdt, int stroffset); + +/** + * fdt_get_max_phandle - retrieves the highest phandle in a tree + * @fdt: pointer to the device tree blob + * + * fdt_get_max_phandle retrieves the highest phandle in the given + * device tree. This will ignore badly formatted phandles, or phandles + * with a value of 0 or -1. + * + * returns: + * the highest phandle on success + * 0, if no phandle was found in the device tree + * -1, if an error occurred + */ +uint32_t fdt_get_max_phandle(const void *fdt); + +/** + * fdt_num_mem_rsv - retrieve the number of memory reserve map entries + * @fdt: pointer to the device tree blob + * + * Returns the number of entries in the device tree blob's memory + * reservation map. This does not include the terminating 0,0 entry + * or any other (0,0) entries reserved for expansion. + * + * returns: + * the number of entries + */ +int fdt_num_mem_rsv(const void *fdt); + +/** + * fdt_get_mem_rsv - retrieve one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: pointers to 64-bit variables + * + * On success, *address and *size will contain the address and size of + * the n-th reserve map entry from the device tree blob, in + * native-endian format. + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); + +/** + * fdt_subnode_offset_namelen - find a subnode based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_subnode_offset(), but only examine the first + * namelen characters of name for matching the subnode name. This is + * useful for finding subnodes based on a portion of a larger string, + * such as a full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, + const char *name, int namelen); +#endif +/** + * fdt_subnode_offset - find a subnode of a given node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_subnode_offset() finds a subnode of the node at structure block + * offset parentoffset with the given name. name may include a unit + * address, in which case fdt_subnode_offset() will find the subnode + * with that unit address, or the unit address may be omitted, in + * which case fdt_subnode_offset() will find an arbitrary subnode + * whose name excluding unit address matches the given name. + * + * returns: + * structure block offset of the requested subnode (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); + +/** + * fdt_path_offset_namelen - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * @namelen: number of characters of path to consider + * + * Identical to fdt_path_offset(), but only consider the first namelen + * characters of path as the path name. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); +#endif + +/** + * fdt_path_offset - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * + * fdt_path_offset() finds a node of a given path in the device tree. + * Each path component may omit the unit address portion, but the + * results of this are undefined if any such path component is + * ambiguous (that is if there are multiple nodes at the relevant + * level matching the given component, differentiated only by unit + * address). + * + * returns: + * structure block offset of the node with the requested path (>=0), on + * success + * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid + * -FDT_ERR_NOTFOUND, if the requested node does not exist + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_path_offset(const void *fdt, const char *path); + +/** + * fdt_get_name - retrieve the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the starting node + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_name() retrieves the name (including unit address) of the + * device tree node at structure block offset nodeoffset. If lenp is + * non-NULL, the length of this name is also returned, in the integer + * pointed to by lenp. + * + * returns: + * pointer to the node's name, on success + * If lenp is non-NULL, *lenp contains the length of that name + * (>=0) + * NULL, on error + * if lenp is non-NULL *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); + +/** + * fdt_first_property_offset - find the offset of a node's first property + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * + * fdt_first_property_offset() finds the first property of the node at + * the given structure block offset. + * + * returns: + * structure block offset of the property (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested node has no properties + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_first_property_offset(const void *fdt, int nodeoffset); + +/** + * fdt_next_property_offset - step through a node's properties + * @fdt: pointer to the device tree blob + * @offset: structure block offset of a property + * + * fdt_next_property_offset() finds the property immediately after the + * one at the given structure block offset. This will be a property + * of the same node as the given property. + * + * returns: + * structure block offset of the next property (>=0), on success + * -FDT_ERR_NOTFOUND, if the given property is the last in its node + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_next_property_offset(const void *fdt, int offset); + +/** + * fdt_for_each_property_offset - iterate over all properties of a node + * + * @property_offset: property offset (int, lvalue) + * @fdt: FDT blob (const void *) + * @node: node offset (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_property_offset(property, fdt, node) { + * Use property + * ... + * } + * + * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and property is used as + * iterator in the loop. The node variable can be constant or even a + * literal. + */ +#define fdt_for_each_property_offset(property, fdt, node) \ + for (property = fdt_first_property_offset(fdt, node); \ + property >= 0; \ + property = fdt_next_property_offset(fdt, property)) + +/** + * fdt_get_property_by_offset - retrieve the property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to retrieve + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property_by_offset() retrieves a pointer to the + * fdt_property structure within the device tree blob at the given + * offset. If lenp is non-NULL, the length of the property value is + * also returned, in the integer pointed to by lenp. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp); + +/** + * fdt_get_property_namelen - find a property based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_get_property(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int nodeoffset, + const char *name, + int namelen, int *lenp); +#endif + +/** + * fdt_get_property - find a given property in a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property() retrieves a pointer to the fdt_property + * structure within the device tree blob corresponding to the property + * named 'name' of the node at offset nodeoffset. If lenp is + * non-NULL, the length of the property value is also returned, in the + * integer pointed to by lenp. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, + const char *name, + int *lenp) +{ + return (struct fdt_property *)(uintptr_t) + fdt_get_property(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_getprop_by_offset - retrieve the value of a property at a given offset + * @fdt: pointer to the device tree blob + * @ffset: offset of the property to read + * @namep: pointer to a string variable (will be overwritten) or NULL + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop_by_offset() retrieves a pointer to the value of the + * property at structure block offset 'offset' (this will be a pointer + * to within the device blob itself, not a copy of the value). If + * lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. If namep is non-NULL, + * the property's namne will also be returned in the char * pointed to + * by namep (this will be a pointer to within the device tree's string + * block, not a new copy of the name). + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * if namep is non-NULL *namep contiains a pointer to the property + * name. + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp); +#endif + +/** + * fdt_getprop_namelen - get property value based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_getprop(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp); +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, + const char *name, int namelen, + int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, + namelen, lenp); +} +#endif + +/** + * fdt_getprop - retrieve the value of a given property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop() retrieves a pointer to the value of the property + * named 'name' of the node at offset nodeoffset (this will be a + * pointer to within the device blob itself, not a copy of the value). + * If lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline void *fdt_getprop_w(void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_get_phandle - retrieve the phandle of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the node + * + * fdt_get_phandle() retrieves the phandle of the device tree node at + * structure block offset nodeoffset. + * + * returns: + * the phandle of the node at nodeoffset, on success (!= 0, != -1) + * 0, if the node has no phandle, or another error occurs + */ +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); + +/** + * fdt_get_alias_namelen - get alias based on substring + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * @namelen: number of characters of name to consider + * + * Identical to fdt_get_alias(), but only examine the first namelen + * characters of name for matching the alias name. + */ +#ifndef SWIG /* Not available in Python */ +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen); +#endif + +/** + * fdt_get_alias - retrieve the path referenced by a given alias + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * + * fdt_get_alias() retrieves the value of a given alias. That is, the + * value of the property named 'name' in the node /aliases. + * + * returns: + * a pointer to the expansion of the alias named 'name', if it exists + * NULL, if the given alias or the /aliases node does not exist + */ +const char *fdt_get_alias(const void *fdt, const char *name); + +/** + * fdt_get_path - determine the full path of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose path to find + * @buf: character buffer to contain the returned path (will be overwritten) + * @buflen: size of the character buffer at buf + * + * fdt_get_path() computes the full path of the node at offset + * nodeoffset, and records that path in the buffer at buf. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * 0, on success + * buf contains the absolute path of the node at + * nodeoffset, as a NUL-terminated string. + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) + * characters and will not fit in the given buffer. + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); + +/** + * fdt_supernode_atdepth_offset - find a specific ancestor of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * @supernodedepth: depth of the ancestor to find + * @nodedepth: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_supernode_atdepth_offset() finds an ancestor of the given node + * at a specific depth from the root (where the root itself has depth + * 0, its immediate subnodes depth 1 and so forth). So + * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); + * will always return 0, the offset of the root node. If the node at + * nodeoffset has depth D, then: + * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); + * will return nodeoffset itself. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * structure block offset of the node at node offset's ancestor + * of depth supernodedepth (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of + * nodeoffset + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth); + +/** + * fdt_node_depth - find the depth of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_node_depth() finds the depth of a given node. The root node + * has depth 0, its immediate subnodes depth 1 and so forth. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * depth of the node at nodeoffset (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_depth(const void *fdt, int nodeoffset); + +/** + * fdt_parent_offset - find the parent of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_parent_offset() locates the parent node of a given node (that + * is, it finds the offset of the node which contains the node at + * nodeoffset as a subnode). + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset, *twice*. + * + * returns: + * structure block offset of the parent of the node at nodeoffset + * (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_parent_offset(const void *fdt, int nodeoffset); + +/** + * fdt_node_offset_by_prop_value - find nodes with a given property value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @propname: property name to check + * @propval: property value to search for + * @proplen: length of the value in propval + * + * fdt_node_offset_by_prop_value() returns the offset of the first + * node after startoffset, which has a property named propname whose + * value is of length proplen and has value equal to propval; or if + * startoffset is -1, the very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, + * propval, proplen); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, + * propval, proplen); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen); + +/** + * fdt_node_offset_by_phandle - find the node with a given phandle + * @fdt: pointer to the device tree blob + * @phandle: phandle value + * + * fdt_node_offset_by_phandle() returns the offset of the node + * which has the given phandle value. If there is more than one node + * in the tree with the given phandle (an invalid tree), results are + * undefined. + * + * returns: + * structure block offset of the located node (>= 0), on success + * -FDT_ERR_NOTFOUND, no node with that phandle exists + * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); + +/** + * fdt_node_check_compatible: check a node's compatible property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @compatible: string to match against + * + * + * fdt_node_check_compatible() returns 0 if the given node contains a + * 'compatible' property with the given string as one of its elements, + * it returns non-zero otherwise, or on error. + * + * returns: + * 0, if the node has a 'compatible' property listing the given string + * 1, if the node has a 'compatible' property, but it does not list + * the given string + * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property + * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible); + +/** + * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @compatible: 'compatible' string to match against + * + * fdt_node_offset_by_compatible() returns the offset of the first + * node after startoffset, which has a 'compatible' property which + * lists the given compatible string; or if startoffset is -1, the + * very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible); + +/** + * fdt_stringlist_contains - check a string list property for a string + * @strlist: Property containing a list of strings to check + * @listlen: Length of property + * @str: String to search for + * + * This is a utility function provided for convenience. The list contains + * one or more strings, each terminated by \0, as is found in a device tree + * "compatible" property. + * + * @return: 1 if the string is found in the list, 0 not found, or invalid list + */ +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); + +/** + * fdt_stringlist_count - count the number of strings in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @return: + * the number of strings in the given property + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); + +/** + * fdt_stringlist_search - find a string in a string list and return its index + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @string: string to look up in the string list + * + * Note that it is possible for this function to succeed on property values + * that are not NUL-terminated. That's because the function will stop after + * finding the first occurrence of @string. This can for example happen with + * small-valued cell properties, such as #address-cells, when searching for + * the empty string. + * + * @return: + * the index of the string in the list of strings + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist or does not contain + * the given string + */ +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string); + +/** + * fdt_stringlist_get() - obtain the string at a given index in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @index: index of the string to return + * @lenp: return location for the string length or an error code on failure + * + * Note that this will successfully extract strings from properties with + * non-NUL-terminated values. For example on small-valued cell properties + * this function will return the empty string. + * + * If non-NULL, the length of the string (on success) or a negative error-code + * (on failure) will be stored in the integer pointer to by lenp. + * + * @return: + * A pointer to the string at the given index in the string list or NULL on + * failure. On success the length of the string will be stored in the memory + * location pointed to by the lenp parameter, if non-NULL. On failure one of + * the following negative error codes will be returned in the lenp parameter + * (if non-NULL): + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int index, + int *lenp); + +/**********************************************************************/ +/* Read-only functions (addressing related) */ +/**********************************************************************/ + +/** + * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells + * + * This is the maximum value for #address-cells, #size-cells and + * similar properties that will be processed by libfdt. IEE1275 + * requires that OF implementations handle values up to 4. + * Implementations may support larger values, but in practice higher + * values aren't used. + */ +#define FDT_MAX_NCELLS 4 + +/** + * fdt_address_cells - retrieve address size for a bus represented in the tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address size for + * + * When the node has a valid #address-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_address_cells(const void *fdt, int nodeoffset); + +/** + * fdt_size_cells - retrieve address range size for a bus represented in the + * tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address range size for + * + * When the node has a valid #size-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #size-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_size_cells(const void *fdt, int nodeoffset); + + +/**********************************************************************/ +/* Write-in-place functions */ +/**********************************************************************/ + +/** + * fdt_setprop_inplace_namelen_partial - change a property's value, + * but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @namelen: number of characters of name to consider + * @idx: index of the property to change in the array + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * Identical to fdt_setprop_inplace(), but modifies the given property + * starting from the given index, and using only the first characters + * of the name. It is useful when you want to manipulate only one value of + * an array and you have a string that doesn't end with \0. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len); +#endif + +/** + * fdt_setprop_inplace - change a property's value, but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * fdt_setprop_inplace() replaces the value of a given property with + * the data in val, of length len. This function cannot change the + * size of a property, and so will only work if len is equal to the + * current length of the property. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if len is not equal to the property's current length + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len); +#endif + +/** + * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to replace the property with + * + * fdt_setprop_inplace_u32() replaces the value of a given property + * with the 32-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 4. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to replace the property with + * + * fdt_setprop_inplace_u64() replaces the value of a given property + * with the 64-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 8. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_cell - change the value of a single-cell property + * + * This is an alternative name for fdt_setprop_inplace_u32() + */ +static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_nop_property - replace a property with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_nop_property() will replace a given property's representation + * in the blob with FDT_NOP tags, effectively removing it from the + * tree. + * + * This function will alter only the bytes in the blob which contain + * the property, and will not alter or move any other part of the + * tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_property(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_nop_node - replace a node (subtree) with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_nop_node() will replace a given node's representation in the + * blob, including all its subnodes, if any, with FDT_NOP tags, + * effectively removing it from the tree. + * + * This function will alter only the bytes in the blob which contain + * the node and its properties and subnodes, and will not alter or + * move any other part of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_node(void *fdt, int nodeoffset); + +/**********************************************************************/ +/* Sequential write functions */ +/**********************************************************************/ + +int fdt_create(void *buf, int bufsize); +int fdt_resize(void *fdt, void *buf, int bufsize); +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); +int fdt_finish_reservemap(void *fdt); +int fdt_begin_node(void *fdt, const char *name); +int fdt_property(void *fdt, const char *name, const void *val, int len); +static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} +static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} +static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +{ + return fdt_property_u32(fdt, name, val); +} +#define fdt_property_string(fdt, name, str) \ + fdt_property(fdt, name, str, strlen(str)+1) +int fdt_end_node(void *fdt); +int fdt_finish(void *fdt); + +/**********************************************************************/ +/* Read-write functions */ +/**********************************************************************/ + +int fdt_create_empty_tree(void *buf, int bufsize); +int fdt_open_into(const void *fdt, void *buf, int bufsize); +int fdt_pack(void *fdt); + +/** + * fdt_add_mem_rsv - add one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: 64-bit values (native endian) + * + * Adds a reserve map entry to the given blob reserving a region at + * address address of length size. + * + * This function will insert data into the reserve map and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new reservation entry + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); + +/** + * fdt_del_mem_rsv - remove a memory reserve map entry + * @fdt: pointer to the device tree blob + * @n: entry to remove + * + * fdt_del_mem_rsv() removes the n-th memory reserve map entry from + * the blob. + * + * This function will delete data from the reservation table and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there + * are less than n+1 reserve map entries) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_mem_rsv(void *fdt, int n); + +/** + * fdt_set_name - change the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * @name: name to give the node + * + * fdt_set_name() replaces the name (including unit address, if any) + * of the given node with the given string. NOTE: this function can't + * efficiently check if the new name is unique amongst the given + * node's siblings; results are undefined if this function is invoked + * with a name equal to one of the given node's siblings. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob + * to contain the new name + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_set_name(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_setprop - create or change a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to set the property value to + * @len: length of the property value + * + * fdt_setprop() sets the value of the named property in the given + * node to the given value and length, creating the property if it + * does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_setprop_u32 - set a property to a 32-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value for the property (native endian) + * + * fdt_setprop_u32() sets the value of the named property in the given + * node to the given 32-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_u64 - set a property to a 64-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value for the property (native endian) + * + * fdt_setprop_u64() sets the value of the named property in the given + * node to the given 64-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, + uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_cell - set a property to a single cell value + * + * This is an alternative name for fdt_setprop_u32() + */ +static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + return fdt_setprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_setprop_string - set a property to a string value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value for the property + * + * fdt_setprop_string() sets the value of the named property in the + * given node to the given string value (using the length of the + * string to determine the new length of the property), or creates a + * new property with that value if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_string(fdt, nodeoffset, name, str) \ + fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + + +/** + * fdt_setprop_empty - set a property to an empty value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * + * fdt_setprop_empty() sets the value of the named property in the + * given node to an empty (zero length) value, or creates a new empty + * property if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_empty(fdt, nodeoffset, name) \ + fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) + +/** + * fdt_appendprop - append to or create a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to append to + * @val: pointer to data to append to the property value + * @len: length of the data to append to the property value + * + * fdt_appendprop() appends the value to the named property in the + * given node, creating the property if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_appendprop_u32 - append a 32-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u32() appends the given 32-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_u64 - append a 64-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u64() appends the given 64-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_cell - append a single cell value to a property + * + * This is an alternative name for fdt_appendprop_u32() + */ +static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_appendprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_appendprop_string - append a string to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value to append to the property + * + * fdt_appendprop_string() appends the given string to the value of + * the named property in the given node, or creates a new property + * with that value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ + fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + +/** + * fdt_delprop - delete a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_del_property() will delete the given property. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_delprop(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_add_subnode_namelen - creates a new node based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_add_subnode(), but use only the first namelen + * characters of name as the name of the new node. This is useful for + * creating subnodes based on a portion of a larger string, such as a + * full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen); +#endif + +/** + * fdt_add_subnode - creates a new node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_add_subnode() creates a new node as a subnode of the node at + * structure block offset parentoffset, with the given name (which + * should include the unit address, if any). + * + * This function will insert data into the blob, and will therefore + * change the offsets of some existing nodes. + + * returns: + * structure block offset of the created nodeequested subnode (>=0), on + * success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of + * the given name + * -FDT_ERR_NOSPACE, if there is insufficient free space in the + * blob to contain the new node + * -FDT_ERR_NOSPACE + * -FDT_ERR_BADLAYOUT + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_add_subnode(void *fdt, int parentoffset, const char *name); + +/** + * fdt_del_node - delete a node (subtree) + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_del_node() will remove the given node, including all its + * subnodes if any, from the blob. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_node(void *fdt, int nodeoffset); + +/** + * fdt_overlay_apply - Applies a DT overlay on a base DT + * @fdt: pointer to the base device tree blob + * @fdto: pointer to the device tree overlay blob + * + * fdt_overlay_apply() will apply the given device tree overlay on the + * given base device tree. + * + * Expect the base device tree to be modified, even if the function + * returns an error. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there's not enough space in the base device tree + * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or + * properties in the base DT + * -FDT_ERR_BADPHANDLE, + * -FDT_ERR_BADOVERLAY, + * -FDT_ERR_NOPHANDLES, + * -FDT_ERR_INTERNAL, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADOFFSET, + * -FDT_ERR_BADPATH, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_overlay_apply(void *fdt, void *fdto); + +/**********************************************************************/ +/* Debugging / informational functions */ +/**********************************************************************/ + +const char *fdt_strerror(int errval); + +#endif /* _LIBFDT_H */ diff --git a/components/legacy/fdt/libfdt/libfdt_env.h b/components/legacy/fdt/libfdt/libfdt_env.h new file mode 100644 index 0000000000..3acc87f2bb --- /dev/null +++ b/components/legacy/fdt/libfdt/libfdt_env.h @@ -0,0 +1,113 @@ +#ifndef _LIBFDT_ENV_H +#define _LIBFDT_ENV_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#ifdef __CHECKER__ +#define FDT_FORCE __attribute__((force)) +#define FDT_BITWISE __attribute__((bitwise)) +#else +#define FDT_FORCE +#define FDT_BITWISE +#endif + +typedef uint16_t FDT_BITWISE fdt16_t; +typedef uint32_t FDT_BITWISE fdt32_t; +typedef uint64_t FDT_BITWISE fdt64_t; +typedef uint64_t unaligned_fdt64_t __attribute__((aligned(4))); + +#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) +#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) +#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ + (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) +#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ + (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ + (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ + (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) + +static inline uint16_t fdt16_to_cpu(fdt16_t x) +{ + return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); +} +static inline fdt16_t cpu_to_fdt16(uint16_t x) +{ + return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); +} + +static inline uint32_t fdt32_to_cpu(fdt32_t x) +{ + return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); +} +static inline fdt32_t cpu_to_fdt32(uint32_t x) +{ + return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); +} + +static inline uint64_t fdt64_to_cpu(fdt64_t x) +{ + return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); +} +static inline fdt64_t cpu_to_fdt64(uint64_t x) +{ + return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); +} +#undef CPU_TO_FDT64 +#undef CPU_TO_FDT32 +#undef CPU_TO_FDT16 +#undef EXTRACT_BYTE + +#endif /* _LIBFDT_ENV_H */ diff --git a/components/legacy/fdt/libfdt/libfdt_internal.h b/components/legacy/fdt/libfdt/libfdt_internal.h new file mode 100644 index 0000000000..b813e58167 --- /dev/null +++ b/components/legacy/fdt/libfdt/libfdt_internal.h @@ -0,0 +1,95 @@ +#ifndef _LIBFDT_INTERNAL_H +#define _LIBFDT_INTERNAL_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "fdt.h" + +#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) + +#define FDT_CHECK_HEADER(fdt) \ + { \ + int __err; \ + if ((__err = fdt_check_header(fdt)) != 0) \ + return __err; \ + } + +int _fdt_check_node_offset(const void *fdt, int offset); +int _fdt_check_prop_offset(const void *fdt, int offset); +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); +int _fdt_node_end_offset(void *fdt, int nodeoffset); + +static inline const void *_fdt_offset_ptr(const void *fdt, int offset) +{ + return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; +} + +static inline void *_fdt_offset_ptr_w(void *fdt, int offset) +{ + return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); +} + +static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) +{ + const struct fdt_reserve_entry *rsv_table = + (const struct fdt_reserve_entry *) + ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); + + return rsv_table + n; +} +static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) +{ + return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); +} + +#define FDT_SW_MAGIC (~FDT_MAGIC) + +#endif /* _LIBFDT_INTERNAL_H */ diff --git a/components/legacy/fdt/src/SConscript b/components/legacy/fdt/src/SConscript new file mode 100644 index 0000000000..23f4af644e --- /dev/null +++ b/components/legacy/fdt/src/SConscript @@ -0,0 +1,17 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +list = os.listdir(cwd) +CPPPATH = [cwd + '/../inc' , cwd + '/libfdt'] +objs = [] + +group = DefineGroup('FDT', src, depend = ['RT_USING_FDT'], CPPPATH = CPPPATH) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) +objs = objs + group + +Return('objs') diff --git a/components/legacy/fdt/src/dtb_access.c b/components/legacy/fdt/src/dtb_access.c new file mode 100644 index 0000000000..dbc5191f7d --- /dev/null +++ b/components/legacy/fdt/src/dtb_access.c @@ -0,0 +1,648 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "libfdt.h" +#include "dtb_node.h" + +/* "/aliaes" node */ +static struct dtb_node *fdt_aliases; + +/** + * of_find_property_value_of_size() - find property of given size + * + * Search for a property in a device node and validate the requested size. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @len: requested length of property value + * + * @return the property value on success, -EINVAL if the property does not + * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + */ +static void *dtb_node_find_property_value_of_size(const struct dtb_node *dn, + const char *propname, uint32_t len) +{ + struct dtb_property *prop = dtb_node_get_dtb_node_property(dn, propname, NULL); + + if (!prop) + return DTB_ERR_PTR(-EINVAL); + if (!prop->value) + return DTB_ERR_PTR(-ENODATA); + if (len > prop->size) + return DTB_ERR_PTR(-EOVERFLOW); + return prop->value; +} + +int dtb_node_read_u32(const struct dtb_node *dn, const char *propname, uint32_t *outp) +{ + const uint32_t *val; + + debug("%s: %s: \n", __func__, propname); + if (!dn) + return -EINVAL; + val = dtb_node_find_property_value_of_size(dn, propname, sizeof(*outp)); + if (DTB_IS_ERR(val)) + { + debug("(not found)\n"); + return DTB_PTR_ERR(val); + } + + *outp = fdt32_to_cpu(*val); + debug("%#x (%d)\n", *outp, *outp); + + return 0; +} + +uint32_t dtb_node_read_u32_default(const struct dtb_node *node, const char *propname, uint32_t def) +{ + dtb_node_read_u32(node, propname, &def); + + return def; +} + +int dtb_node_read_u32_array(const struct dtb_node *dn, const char *propname, + uint32_t *out_values, size_t sz) +{ + const uint32_t *val; + + debug("%s: %s: ", __func__, propname); + val = dtb_node_find_property_value_of_size(dn, propname, + sz * sizeof(*out_values)); + + if (DTB_IS_ERR(val)) + return DTB_PTR_ERR(val); + + debug("size %zd, val:%d\n", sz, *val); + while (sz--) + *out_values++ = fdt32_to_cpu(*val++); + + return 0; +} + +uint32_t dtb_node_read_u32_index_default(const struct dtb_node *node, const char *propname, int index, + uint32_t def) +{ + RT_ASSERT(dtb_node_valid(node)); + dtb_node_read_u32_index(node, propname, index, &def); + + return def; +} + +int dtb_node_read_s32_default(const struct dtb_node *node, const char *propname, int32_t def) +{ + RT_ASSERT(dtb_node_valid(node)); + dtb_node_read_u32(node, propname, (uint32_t *)&def); + + return def; +} + +int dtb_node_read_u32_index(const struct dtb_node *dn, const char *propname, + int index, uint32_t *outp) +{ + const uint32_t *val; + + debug("%s: %s: ", __func__, propname); + if (!dn) + return -EINVAL; + + val = dtb_node_find_property_value_of_size(dn, propname, + sizeof(*outp) * (index + 1)); + if (DTB_IS_ERR(val)) + { + debug("(not found)\n"); + return DTB_PTR_ERR(val); + } + + *outp = fdt32_to_cpu(val[index]); + debug("%#x (%d)\n", *outp, *outp); + + return 0; +} + +int dtb_node_read_u64(const struct dtb_node *dn, const char *propname, uint64_t *outp) +{ + const uint64_t *val; + + debug("%s: %s: ", __func__, propname); + if (!dn) + return -EINVAL; + val = dtb_node_find_property_value_of_size(dn, propname, sizeof(*outp)); + if (DTB_IS_ERR(val)) + { + debug("(not found)\n"); + return DTB_PTR_ERR(val); + } + + *outp = fdt64_to_cpu(*val); + debug("%#llx (%lld)\n", (unsigned long long)*outp, + (unsigned long long)*outp); + + return 0; +} + +uint64_t dtb_node_read_u64_default(const struct dtb_node *node, const char *propname, uint64_t def) +{ + RT_ASSERT(dtb_node_valid(node)); + dtb_node_read_u64(node, propname, &def); + + return def; +} + +int dtb_node_n_addr_cells(const struct dtb_node *dn) +{ + const uint32_t *ip; + + do + { + if (dn->parent) + dn = dn->parent; + ip = dtb_node_get_dtb_node_property_value(dn, "#address-cells", NULL); + if (ip) + return fdt32_to_cpu(*ip); + } while (dn->parent); + + /* No #address-cells property for the root node */ + return DEV_ROOT_NODE_ADDR_CELLS_DEFAULT; +} + +int dtb_node_n_size_cells(const struct dtb_node *dn) +{ + const uint32_t *ip; + + do + { + if (dn->parent) + dn = dn->parent; + ip = dtb_node_get_dtb_node_property_value(dn, "#size-cells", NULL); + if (ip) + return fdt32_to_cpu(*ip); + } while (dn->parent); + + /* No #size-cells property for the root node */ + return DEV_ROOT_NODE_SIZE_CELLS_DEFAULT; +} + +int dtb_node_simple_addr_cells(const struct dtb_node *dn) +{ + const uint32_t *ip; + + ip = dtb_node_get_dtb_node_property_value(dn, "#address-cells", NULL); + if (ip) + return fdt32_to_cpu(*ip); + + /* Return a default of 2 to match fdt_address_cells()*/ + return 2; +} + +int dtb_node_simple_size_cells(const struct dtb_node *dn) +{ + const uint32_t *ip; + + ip = dtb_node_get_dtb_node_property_value(dn, "#size-cells", NULL); + if (ip) + return fdt32_to_cpu(*ip); + + /* Return a default of 2 to match fdt_size_cells()*/ + return 2; +} + +struct dtb_property *dtb_node_get_dtb_node_property(const struct dtb_node *dtb_node, const char *property_name, int *property_size) +{ + struct dtb_property *dtb_property = NULL; + + if (dtb_node != NULL && property_name != NULL) + { + dtb_property = dtb_node->properties; + + while (dtb_property != NULL) + { + if (!strcmp(dtb_property->name, property_name)) + { + if (property_size != NULL) + { + *property_size = dtb_property->size; + } + return dtb_property; + } + dtb_property = dtb_property->next; + } + } + + return dtb_property; +} + +#define for_each_property_of_node(dn, pp) \ + for (pp = dn->properties; pp != NULL; pp = pp->next) + +struct dtb_node *dtb_node_find_node_opts_by_path(const char *path, + const char **opts) +{ + struct dtb_node *np = NULL; + struct dtb_property *pp; + const char *separator = strchr(path, ':'); + + if (opts) + *opts = separator ? separator + 1 : NULL; + + if (strcmp(path, "/") == 0) + return dtb_node_get(get_dtb_node_head()); + + /* The path could begin with an alias */ + if (*path != '/') + { + int len; + const char *p = separator; + + if (!p) + p = strchrnul(path, '/'); + len = p - path; + + /* of_aliases must not be NULL */ + if (!fdt_aliases) + return NULL; + + for_each_property_of_node(fdt_aliases, pp) + { + if (strlen(pp->name) == len && !strncmp(pp->name, path, + len)) + { + np = dtb_node_find_node_by_path(pp->value); + break; + } + } + if (!np) + return NULL; + path = p; + } + + /* Step down the tree matching path components */ + if (!np) + np = dtb_node_get(get_dtb_node_head()); + while (np && *path == '/') + { + struct dtb_node *tmp = np; + + path++; /* Increment past '/' delimiter */ + np = dtb_node_get_dtb_node_by_path(np, path); + dtb_node_put(tmp); + path = strchrnul(path, '/'); + if (separator && separator < path) + break; + } + + return np; +} + +struct dtb_node *dtb_node_find_compatible_node(struct dtb_node *from, const char *compatible) +{ + struct dtb_node *dn; + + for_each_of_allnodes_from(from, dn) + { + if (dtb_node_get_dtb_node_compatible_match(dn, compatible) && + dtb_node_get(dn)) + break; + } + dtb_node_put(from); + + return dn; +} + +void *dtb_node_get_dtb_node_property_value(const struct dtb_node *dtb_node, const char *property_name, int *property_size) +{ + struct dtb_property *dtb_property = dtb_node_get_dtb_node_property(dtb_node, property_name, NULL); + + if (!dtb_property || !dtb_property->value || !dtb_property->size) + { + return NULL; + } + + if (property_size != NULL) + { + *property_size = dtb_property->size; + } + + return dtb_property->value; +} + +const struct dtb_node *dtb_node_find_node_by_prop_value(struct dtb_node *from, + const char *propname, + const void *propval, int proplen) +{ + struct dtb_node *np; + void *value; + for_each_of_allnodes_from(from, np) + { + value = dtb_node_get_dtb_node_property_value(np, propname, &proplen); + if (!memcmp(value, propval, proplen) && dtb_node_get(np)) + break; + } + dtb_node_put(from); + + return np; +} + +struct dtb_node *dtb_node_find_all_nodes(const struct dtb_node *prev) +{ + const struct dtb_node *dn; + + if (!prev) + { + dn = get_dtb_node_head(); + } + else if (prev->child) + { + dn = prev->child; + } + else + { + /* + * Walk back up looking for a sibling, or the end of the + * structure + */ + dn = prev; + while (dn->parent && !dn->sibling) + dn = dn->parent; + dn = dn->sibling; /* Might be null at the end of the tree */ + } + + return (struct dtb_node *)dn; +} + +rt_bool_t dtb_node_device_is_available(const struct dtb_node *device) +{ + const char *status; + int statlen; + + if (!device) + return RT_FALSE; + + status = dtb_node_get_dtb_node_property_value(device, "status", &statlen); + if (status == NULL) + return RT_TRUE; + + if (statlen > 0) + { + if (!strcmp(status, "okay")) + return RT_TRUE; + } + + return RT_FALSE; +} + +struct dtb_node *dtb_node_get_parent(const struct dtb_node *node) +{ + const struct dtb_node *dn; + + if (!node) + return NULL; + + dn = dtb_node_get(node->parent); + + return (struct dtb_node *)dn; +} + +struct dtb_node *dtb_node_find_node_by_phandle(phandle handle) +{ + struct dtb_node *dn; + + if (!handle) + return NULL; + + for_each_of_allnodes(dn) if (dn->handle == handle) break; + (void)dtb_node_get(dn); + + return dn; +} + +int dtb_node_property_match_string(const struct dtb_node *dn, const char *propname, + const char *string) +{ + const struct dtb_property *prop = dtb_node_get_dtb_node_property(dn, propname, NULL); + size_t l; + int i; + const char *p, *end; + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + p = prop->value; + end = p + prop->size; + + for (i = 0; p < end; i++, p += l) + { + l = strnlen(p, end - p) + 1; + if (p + l > end) + return -EILSEQ; + debug("comparing %s with %s\n", string, p); + if (strcmp(string, p) == 0) + return i; /* Found it; return index */ + } + return -ENODATA; +} + +/** + * of_property_read_string_helper() - Utility helper for parsing string properties + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_strs: output array of string pointers. + * @sz: number of array elements to read. + * @skip: Number of strings to skip over at beginning of list. + * + * Don't call this function directly. It is a utility helper for the + * of_property_read_string*() family of functions. + */ +int dtb_node_property_read_string_helper(const struct dtb_node *dn, + const char *propname, const char **out_strs, + size_t sz, int skip) +{ + const struct dtb_property *prop = dtb_node_get_dtb_node_property(dn, propname, NULL); + int l = 0, i = 0; + const char *p, *end; + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + p = prop->value; + end = p + prop->size; + + for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) + { + l = strnlen(p, end - p) + 1; + if (p + l > end) + return -EILSEQ; + if (out_strs && i >= skip) + *out_strs++ = p; + } + i -= skip; + return i <= 0 ? -ENODATA : i; +} + +static int __dtb_node_parse_phandle_with_args(const struct dtb_node *dn, + const char *list_name, + const char *cells_name, + int cell_count, int index, + struct fdt_phandle_args *out_args) +{ + const uint32_t *list, *list_end; + int rc = 0, cur_index = 0; + uint32_t count = 0; + struct dtb_node *node = NULL; + phandle phandle; + int size; + + /* Retrieve the phandle list property */ + list = dtb_node_get_dtb_node_property_value(dn, list_name, &size); + if (!list) + return -ENOENT; + list_end = list + size / sizeof(*list); + + /* Loop over the phandles until all the requested entry is found */ + while (list < list_end) + { + rc = -EINVAL; + count = 0; + + /* + * If phandle is 0, then it is an empty entry with no + * arguments. Skip forward to the next entry. + */ + phandle = fdt32_to_cpu(*(list++)); + if (phandle) + { + /* + * Find the provider node and parse the #*-cells + * property to determine the argument length. + * + * This is not needed if the cell count is hard-coded + * (i.e. cells_name not set, but cell_count is set), + * except when we're going to return the found node + * below. + */ + if (cells_name || cur_index == index) + { + node = dtb_node_find_node_by_phandle(phandle); + if (!node) + { + debug("%s: could not find phandle\n", + dn->path); + goto err; + } + } + + if (cells_name) + { + if (dtb_node_read_u32(node, cells_name, &count)) + { + debug("%s: could not get %s for %s\n", + dn->path, cells_name, + node->path); + goto err; + } + } + else + { + count = cell_count; + } + + /* + * Make sure that the arguments actually fit in the + * remaining property data length + */ + if (list + count > list_end) + { + debug("%s: arguments longer than property\n", + dn->path); + goto err; + } + } + + /* + * All of the error cases above bail out of the loop, so at + * this point, the parsing is successful. If the requested + * index matches, then fill the out_args structure and return, + * or return -ENOENT for an empty entry. + */ + rc = -ENOENT; + if (cur_index == index) + { + if (!phandle) + goto err; + + if (out_args) + { + int i; + if (count > FDT_MAX_PHANDLE_ARGS) + count = FDT_MAX_PHANDLE_ARGS; + out_args->np = node; + out_args->args_count = count; + for (i = 0; i < count; i++) + out_args->args[i] = + fdt32_to_cpu(*(list++)); + } + else + { + dtb_node_put(node); + } + + /* Found it! return success */ + return 0; + } + + dtb_node_put(node); + node = NULL; + list += count; + cur_index++; + } + + /* + * Unlock node before returning result; will be one of: + * -ENOENT : index is for empty phandle + * -EINVAL : parsing error on data + * [1..n] : Number of phandle (count mode; when index = -1) + */ + rc = index < 0 ? cur_index : -ENOENT; +err: + if (node) + dtb_node_put(node); + return rc; +} + +struct dtb_node *dtb_node_parse_phandle(const struct dtb_node *dn, + const char *phandle_name, int index) +{ + struct fdt_phandle_args args; + + if (index < 0) + return NULL; + + if (__dtb_node_parse_phandle_with_args(dn, phandle_name, NULL, 0, index, + &args)) + return NULL; + + return args.np; +} + +int dtb_node_parse_phandle_with_args(const struct dtb_node *dn, + const char *list_name, const char *cells_name, + int index, struct fdt_phandle_args *out_args) +{ + if (index < 0) + return -EINVAL; + + return __dtb_node_parse_phandle_with_args(dn, list_name, cells_name, 0, + index, out_args); +} + +int dtb_node_count_phandle_with_args(const struct dtb_node *dn, + const char *list_name, const char *cells_name) +{ + return __dtb_node_parse_phandle_with_args(dn, list_name, cells_name, 0, + -1, NULL); +} diff --git a/components/legacy/fdt/src/dtb_addr.c b/components/legacy/fdt/src/dtb_addr.c new file mode 100644 index 0000000000..5516ff1e6c --- /dev/null +++ b/components/legacy/fdt/src/dtb_addr.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "libfdt.h" +#include "dtb_node.h" + +/* Max address size we deal with */ +#define FDT_MAX_ADDR_CELLS 4 +#define FDT_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= FDT_MAX_ADDR_CELLS) +#define FDT_CHECK_COUNTS(na, ns) (FDT_CHECK_ADDR_COUNT(na) && (ns) > 0) + +static void dtb_node_default_count_cells(const struct dtb_node *dn, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = dtb_node_n_addr_cells(dn); + if (sizec) + *sizec = dtb_node_n_size_cells(dn); +} + +const uint32_t *dtb_node_get_address(const struct dtb_node *dev, int index, + uint64_t *size, unsigned int *flags) +{ + const uint32_t *prop; + int psize; + struct dtb_node *parent; + int onesize, i, na, ns; + + /* Get parent */ + parent = dtb_node_get_parent(dev); + if (parent == NULL) + return NULL; + + dtb_node_default_count_cells(dev, &na, &ns); + if (!FDT_CHECK_ADDR_COUNT(na)) + return NULL; + + /* Get "reg" or "assigned-addresses" property */ + prop = dtb_node_get_dtb_node_property_value(dev, "reg", &psize); + if (prop == NULL) + return NULL; + psize /= 4; + + onesize = na + ns; + for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) + if (i == index) + { + if (size) + *size = dtb_node_read_number(prop + na, ns); + if (flags) + *flags = 0x200; + return prop; + } + return NULL; +} diff --git a/components/legacy/fdt/src/dtb_base.c b/components/legacy/fdt/src/dtb_base.c new file mode 100644 index 0000000000..eb71de429a --- /dev/null +++ b/components/legacy/fdt/src/dtb_base.c @@ -0,0 +1,574 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "dtb_node.h" +#include "libfdt.h" +#include "libfdt_env.h" +#include + +static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) +{ + if (*base == 0) + { + if (s[0] == '0') + { + if (tolower(s[1]) == 'x' && isxdigit((int)s[2])) + *base = 16; + else + *base = 8; + } + else + *base = 10; + } + if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x') + s += 2; + return s; +} + +unsigned long simple_strtoul(const char *cp, char **endp, + unsigned int base) +{ + unsigned long result = 0; + unsigned long value; + + cp = _parse_integer_fixup_radix(cp, &base); + + while (isxdigit((int)*cp) && (value = isdigit((int)*cp) ? *cp-'0' : (islower((int)*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) + { + result = result*base + value; + cp++; + } + + if (endp) + *endp = (char *)cp; + + return result; +} + +int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) +{ + char *tail; + unsigned long val; + size_t len; + + *res = 0; + len = strlen(cp); + if (len == 0) + return -EINVAL; + + val = simple_strtoul(cp, &tail, base); + if (tail == cp) + return -EINVAL; + + if ((*tail == '\0') || + ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) + { + *res = val; + return 0; + } + + return -EINVAL; +} + +long simple_strtol(const char *cp, char **endp, unsigned int base) +{ + if (*cp == '-') + return -simple_strtoul(cp + 1, endp, base); + + return simple_strtoul(cp, endp, base); +} + +rt_bool_t dtb_node_read_bool(const struct dtb_node *node, const char *propname) +{ + const void *prop; + + RT_ASSERT(dtb_node_valid(node)); + debug("%s: %s: ", __func__, propname); + + prop = dtb_node_get_property(node, propname, NULL); + + debug("%s\n", prop ? "true" : "false"); + + return prop ? RT_TRUE : RT_FALSE; +} + +const void *dtb_node_read_prop(const struct dtb_node *node, const char *propname, int *sizep) +{ + const char *val = NULL; + int len; + + RT_ASSERT(dtb_node_valid(node)); + debug("%s: %s: ", __func__, propname); + + struct dtb_property *prop = dtb_node_get_dtb_node_property(node, propname, &len); + + if (prop) + { + val = prop->value; + len = prop->size; + } + + if (!val) + { + debug("\n"); + if (sizep) + *sizep = -FDT_ERR_NOTFOUND; + return NULL; + } + if (sizep) + *sizep = len; + + return val; +} + +const char *dtb_node_read_string(const struct dtb_node *node, const char *propname) +{ + const char *str; + int len; + + str = dtb_node_read_prop(node, propname, &len); + if (!str) + return NULL; + + if (strnlen(str, len) >= len) + { + debug("\n"); + return NULL; + } + debug("%s\n", str); + + return str; +} + +const struct dtb_node *dtb_node_find_subnode(const struct dtb_node *node, const char *subnode_name) +{ + const struct dtb_node *subnode; + + RT_ASSERT(dtb_node_valid(node)); + debug("%s: %s: ", __func__, subnode_name); + + for (node = node->child; node; node = node->sibling) + { + if (!strcmp(subnode_name, node->name)) + break; + } + subnode = node; + + debug("%s\n", dtb_node_valid(subnode) ?\ + dtb_node_get_name(subnode) : ""); + + return subnode; +} + +struct dtb_node *dtb_node_first_subnode(const struct dtb_node *node) +{ + RT_ASSERT(dtb_node_valid(node)); + + return node->child; +} + +struct dtb_node *dtb_node_next_subnode(const struct dtb_node *node) +{ + RT_ASSERT(dtb_node_valid(node)); + + return node->sibling; +} + +const char *dtb_node_get_name(const struct dtb_node *node) +{ + if (!dtb_node_valid(node)) + { + debug("%s node not valid\n", __func__); + return NULL; + } + + return strrchr(node->path, '/') + 1; + +} + +struct dtb_node *dtb_node_get_by_phandle(uint32_t phandle) +{ + if (dtb_node_active()) + return dtb_node_find_node_by_phandle(phandle); + return NULL; +} + +int dtb_node_read_size(const struct dtb_node *node, const char *propname) +{ + struct dtb_property *prop = dtb_node_get_dtb_node_property( node, propname, NULL); + + if (prop) + return prop->size; + + return -EINVAL; +} + +int dtb_node_get_addr_and_size_by_index(const struct dtb_node *node, int index, size_t *addr, size_t *size) +{ + const uint32_t *prop; + int psize; + int onesize, na, ns; + + na = dtb_node_n_addr_cells(node); + ns = dtb_node_n_size_cells(node); + + prop = dtb_node_get_dtb_node_property_value(node, "reg", &psize); + if (prop == NULL) + { + return -1; + } + + psize /= 4; + onesize = na + ns; + + if (psize >= (index + 1) * onesize) + { + prop += index * onesize; + + if (addr) + { + *addr = dtb_node_read_number(prop, na); + } + if (size) + { + *size = dtb_node_read_number(prop + na, ns); + } + + return 0; + } + + return -1; +} + +size_t dtb_node_get_addr_index(const struct dtb_node *node, int index) +{ + int na; + size_t size; + + const uint32_t *prop_val; + uint flags; + + prop_val = dtb_node_get_address(node, index, + (uint64_t *)&size, &flags); + if (!prop_val) + return -1; + + na = dtb_node_n_addr_cells(node); + + return dtb_node_read_number(prop_val, na); +} + +size_t dtb_node_get_addr(const struct dtb_node *node) +{ + return dtb_node_get_addr_index(node, 0); +} + +int dtb_node_stringlist_search(const struct dtb_node *node, const char *property, + const char *string) +{ + return dtb_node_property_match_string(node, property, string); +} + +int dtb_node_read_string_index(const struct dtb_node *node, const char *property, int index, + const char **outp) +{ + return dtb_node_property_read_string_index(node, property, index, outp); +} + +int dtb_node_read_string_count(const struct dtb_node *node, const char *property) +{ + return dtb_node_property_count_strings(node, property); +} + +struct dtb_node *dtb_node_path(const char *path) +{ + if (dtb_node_active()) + return dtb_node_find_node_by_path(path); + return NULL; +} + +const char *dtb_node_get_chosen_prop(const char *name) +{ + const struct dtb_node *chosen_node; + + chosen_node = (const struct dtb_node *)dtb_node_path("/chosen"); + + return dtb_node_read_string(chosen_node, name); +} + +struct dtb_node *dtb_node_get_chosen_node(const char *name) +{ + const char *prop; + + prop = dtb_node_get_chosen_prop(name); + if (!prop) + return NULL; + + return dtb_node_path(prop); +} + +const void *dtb_node_get_property(const struct dtb_node *node, const char *propname, int *lenp) +{ + return dtb_node_get_dtb_node_property_value(node, propname, lenp); +} + +rt_bool_t dtb_node_is_available(const struct dtb_node *node) +{ + return dtb_node_device_is_available(node); +} + +size_t dtb_node_get_addr_size(const struct dtb_node *node, const char *property, + size_t *sizep) +{ + int na, ns; + int psize; + const uint32_t *prop = dtb_node_get_dtb_node_property_value(node, property, &psize); + + if (!prop) + return -1; + na = dtb_node_n_addr_cells(node); + ns = dtb_node_n_size_cells(node); + *sizep = dtb_node_read_number(prop + na, ns); + + return dtb_node_read_number(prop, na); +} + +const uint8_t *dtb_node_read_u8_array_ptr(const struct dtb_node *node, const char *propname, + size_t sz) +{ + int psize; + const uint32_t *prop = dtb_node_get_dtb_node_property_value(node, propname, &psize); + + if (!prop || sz != psize) + return NULL; + return (uint8_t *)prop; +} + +int dtb_node_find_all_compatible_node(const struct dtb_node *from, const char *compatible, struct dtb_node **node_table, int max_num, int *node_num) +{ + const struct dtb_node *dn; + int num = 0; + for_each_of_allnodes_from(from, dn) + { + if (dtb_node_get_dtb_node_compatible_match(dn, compatible) && + dtb_node_get(dn)) + { + + num++; + *node_table = (struct dtb_node *)dn; + node_table++; + if (num >= max_num) + { + break; + } + } + } + *node_num = num; + dtb_node_put(from); + + return 0; +} + +int dtb_node_write_prop(const struct dtb_node *node, const char *propname, int len, + const void *value) +{ + struct dtb_property *pp; + struct dtb_property *pp_last = NULL; + struct dtb_property *new; + + if (!dtb_node_active()) + return -ENOSYS; + + if (!node) + return -EINVAL; + + for (pp = node->properties; pp; pp = pp->next) + { + if (strcmp(pp->name, propname) == 0) + { + /* Property exists -> change value */ + pp->value = (void *)value; + pp->size = len; + return 0; + } + pp_last = pp; + } + + if (!pp_last) + return -ENOENT; + + /* Property does not exist -> append new property */ + new = (struct dtb_property *)malloc(sizeof(struct dtb_property)); + if (!new) + return -ENOMEM; + + new->name = strdup(propname); + if (!new->name) + { + free(new); + return -ENOMEM; + } + + new->value = (void *)value; + new->size = len; + new->next = NULL; + + pp_last->next = new; + + return 0; +} + +int dtb_node_write_string(const struct dtb_node *node, const char *propname, const char *value) +{ + if (!dtb_node_active()) + return -ENOSYS; + + RT_ASSERT(dtb_node_valid(node)); + + debug("%s: %s = %s", __func__, propname, value); + + return dtb_node_write_prop(node, propname, strlen(value) + 1, value); +} + +int dtb_node_set_enabled(const struct dtb_node *node, rt_bool_t value) +{ + if (!dtb_node_active()) + return -ENOSYS; + + RT_ASSERT(dtb_node_valid(node)); + + if (value) + return dtb_node_write_string(node, "status", "okay"); + else + return dtb_node_write_string(node, "status", "disable"); +} + +/** + * dtb_node_irq_find_parent - Given a device node, find its interrupt parent node + * @child: pointer to device node + * + * Returns a pointer to the interrupt parent node, or NULL if the interrupt + * parent could not be determined. + */ +static struct dtb_node *dtb_node_irq_find_parent(struct dtb_node *child) +{ + struct dtb_node *p; + phandle parent; + + if (!dtb_node_get(child)) + return NULL; + do + { + if (dtb_node_read_u32_array(child, "interrupt-parent", &parent, 1)) + { + p = dtb_node_get_parent(child); + } + else + { + p = dtb_node_get_by_phandle(parent); + } + dtb_node_put(child); + child = p; + } while (p && dtb_node_get_property(p, "#interrupt-cells", NULL) == NULL); + + return p; +} + +int dtb_node_irq_get(struct dtb_node *dev, int index) +{ + int rc = 0; + struct fdt_phandle_args out_irq; + struct dtb_node *p; + uint32_t intsize; + int res, i; + + p = dtb_node_irq_find_parent(dev); + if (p == NULL) + return -EINVAL; + /* Get size of interrupt specifier */ + if (dtb_node_read_u32_array(p, "#interrupt-cells", &intsize, 1)) + { + res = -EINVAL; + goto out; + } + + debug(" path:%s, parent=%pOF, intsize=%d\n", p->path,p, intsize); + + /* Copy intspec into irq structure */ + out_irq.np = p; + out_irq.args_count = intsize; + for (i = 0; i < intsize; i++) + { + res = dtb_node_read_u32_index(dev, "interrupts", + (index * 3 + i), + out_irq.args + i); + if (res) + goto out; + } + rc = out_irq.args[1]; + out: + dtb_node_put(p); + return rc; + +} + +/** + * dtb_node_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number + * @dev: pointer to device tree node + * @name: IRQ name + * + * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or + * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case + * of any other failure. + */ +int dtb_node_irq_get_byname(struct dtb_node *dev, const char *name) +{ + int index; + + if (!name) + return -EINVAL; + + index = dtb_node_stringlist_search(dev, "interrupt-names", name); + if (index < 0) + return index; + + return dtb_node_irq_get(dev, index); +} + +/** + * dtb_node_irq_count - Count the number of IRQs a node uses + * @dev: pointer to device tree node + */ +int dtb_node_irq_count(struct dtb_node *device) +{ + struct dtb_node *p; + uint32_t intsize; + int nr = 0, res = 0; + + p = dtb_node_irq_find_parent(device); + if (p == NULL) + return -EINVAL; + + /* Get size of interrupt specifier */ + if (dtb_node_read_u32_array(p, "#interrupt-cells", &intsize, 1)) + { + res = -EINVAL; + goto out; + } + + debug(" path:%s, parent=%pOF, intsize=%d\n", p->path,p, intsize); + + res = dtb_node_read_size(device, "interrupts"); + if (res < 0) + { + goto out; + } + nr = res / (intsize * 4); + out: + dtb_node_put(p); + + return nr; +} diff --git a/components/legacy/fdt/src/dtb_get.c b/components/legacy/fdt/src/dtb_get.c new file mode 100644 index 0000000000..e4e700114f --- /dev/null +++ b/components/legacy/fdt/src/dtb_get.c @@ -0,0 +1,829 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "libfdt.h" +#include "dtb_node.h" + +static struct +{ + const char *ptr; + const char *end; + char *cur; +} paths_buf = {NULL, NULL}; +static void *current_fdt; + +int fdt_exec_status = FDT_RET_GET_OK; + +int dtb_node_get_exec_status() +{ + return fdt_exec_status; +} + +static int _dtb_node_get_dtb_properties_list(struct dtb_property *dtb_property, off_t node_off) +{ + /* caller alrealy checked current_fdt */ + off_t property_off = fdt_first_property_offset(current_fdt, node_off); + struct fdt_property *fdt_property; + + if (property_off < 0) + { + return FDT_RET_GET_EMPTY; + } + + for (;;) + { + fdt_property = (struct fdt_property *)fdt_get_property_by_offset(current_fdt, property_off, &dtb_property->size); + if (fdt_property != NULL) + { + dtb_property->name = fdt_string(current_fdt, fdt32_to_cpu(fdt_property->nameoff)); + dtb_property->value = fdt_property->data; + dtb_property->size = fdt32_to_cpu(fdt_property->len); + } + + property_off = fdt_next_property_offset(current_fdt, property_off); + if (property_off >= 0) + { + dtb_property->next = (struct dtb_property *)malloc(sizeof(struct dtb_property)); + if (dtb_property->next == NULL) + { + return FDT_RET_NO_MEMORY; + } + dtb_property = dtb_property->next; + } + else + { + dtb_property->next = NULL; + break; + } + } + + return FDT_RET_GET_OK; +} + +static int _dtb_node_get_dtb_nodes_list(struct dtb_node *dtb_node_head, struct dtb_node *dtb_node, const char *pathname) +{ + off_t root_off; + off_t node_off; + int pathname_sz; + int node_name_sz; + +#ifdef RT_USING_FDT_FWNODE + dtb_fwnode_init(dtb_node_head); +#endif + + /* caller alrealy checked current_fdt */ + if ((root_off = fdt_path_offset(current_fdt, pathname)) >= 0) + { + pathname_sz = strlen(pathname); + node_off = fdt_first_subnode(current_fdt, root_off); + + if (node_off < 0) + { + return FDT_RET_GET_EMPTY; + } + + for (;;) + { + dtb_node->parent = dtb_node_head; + dtb_node->sibling = NULL; + dtb_node->name = fdt_get_name(current_fdt, node_off, &node_name_sz); + + /* parent_path + name + '/' + '\0' */ + if (paths_buf.cur + pathname_sz + node_name_sz + 2 < paths_buf.end) + { + dtb_node->path = (const char *)paths_buf.cur; + strncpy(paths_buf.cur, pathname, pathname_sz); + paths_buf.cur += pathname_sz; + strncpy(paths_buf.cur, (char *)dtb_node->name, node_name_sz); + paths_buf.cur += node_name_sz; + *paths_buf.cur++ = '/'; + *paths_buf.cur++ = '\0'; + dtb_node->level = dtb_node_head->level + 1; + } + else + { + dtb_node->path = NULL; + rt_kprintf("\033[31m\rERROR: `FDT_DTB_ALL_NODES_PATH_SIZE' = %d bytes is configured too low.\033[0m\n", FDT_DTB_ALL_NODES_PATH_SIZE); + return FDT_RET_NO_MEMORY; + } + + dtb_node->handle = fdt_get_phandle(current_fdt, node_off); + dtb_node->properties = (struct dtb_property *)malloc(sizeof(struct dtb_property)); + dtb_node->child = (struct dtb_node *)malloc(sizeof(struct dtb_node)); + + if (dtb_node->properties == NULL || dtb_node->child == NULL) + { + return FDT_RET_NO_MEMORY; + } +#ifdef RT_USING_FDT_FWNODE + dtb_fwnode_init(dtb_node); +#endif + fdt_exec_status = _dtb_node_get_dtb_properties_list(dtb_node->properties, node_off); + if (fdt_exec_status == FDT_RET_GET_EMPTY) + { + free(dtb_node->properties); + dtb_node->properties = NULL; + } + else if (fdt_exec_status != FDT_RET_GET_OK) + { + return fdt_exec_status; + } + + fdt_exec_status = _dtb_node_get_dtb_nodes_list(dtb_node, dtb_node->child, dtb_node->path); + if (fdt_exec_status == FDT_RET_GET_EMPTY) + { + free(dtb_node->child); + dtb_node->child = NULL; + } + else if (fdt_exec_status != FDT_RET_GET_OK) + { + return fdt_exec_status; + } + + node_off = fdt_next_subnode(current_fdt, node_off); + if (node_off >= 0) + { + dtb_node->sibling = (struct dtb_node *)malloc(sizeof(struct dtb_node)); + if (dtb_node->sibling == NULL) + { + return FDT_RET_NO_MEMORY; + } + dtb_node = dtb_node->sibling; + dtb_node->level--; + } + else + { + break; + } + } + } + + return FDT_RET_GET_OK; +} + +struct dtb_node *dtb_node_get_dtb_list(void *fdt) +{ + int root_off; + struct dtb_node *dtb_node_head = NULL; + + if (fdt == NULL) + { + fdt_exec_status = FDT_RET_NO_LOADED; + goto fail; + } + + current_fdt = fdt; + + if ((dtb_node_head = (struct dtb_node *)malloc(sizeof(struct dtb_node))) == NULL) + { + fdt_exec_status = FDT_RET_NO_MEMORY; + goto fail; + } + + if (paths_buf.ptr == NULL) + { + paths_buf.ptr = (char *)malloc(FDT_DTB_ALL_NODES_PATH_SIZE); + + if (paths_buf.ptr == NULL) + { + fdt_exec_status = FDT_RET_NO_MEMORY; + goto fail; + } + paths_buf.cur = (char *)paths_buf.ptr; + paths_buf.end = (char *)(paths_buf.ptr + FDT_DTB_ALL_NODES_PATH_SIZE); + } + + root_off = fdt_path_offset(fdt, "/"); + + if ((dtb_node_head->header = (struct dtb_header *)malloc(sizeof(struct dtb_header))) == NULL) + + { + fdt_exec_status = FDT_RET_NO_MEMORY; + goto fail; + } + else + { + ((struct dtb_header *)dtb_node_head->header)->root = '/'; + ((struct dtb_header *)dtb_node_head->header)->zero = '\0'; + ((struct dtb_header *)dtb_node_head->header)->memreserve_sz = fdt_num_mem_rsv(fdt); + + if (dtb_node_head->header->memreserve_sz > 0) + { + int i; + int memreserve_sz = dtb_node_head->header->memreserve_sz; + uint32_t off_mem_rsvmap = fdt_off_mem_rsvmap(fdt); + struct fdt_reserve_entry *rsvmap = (struct fdt_reserve_entry *)((char *)fdt + off_mem_rsvmap); + + ((struct dtb_header *)dtb_node_head->header)->memreserve = (struct dtb_memreserve *)malloc(sizeof(struct dtb_memreserve) * memreserve_sz); + if (dtb_node_head->header->memreserve == NULL) + { + fdt_exec_status = FDT_RET_NO_MEMORY; + goto fail; + } + for (i = 0; i < memreserve_sz; ++i) + { + ((struct dtb_header *)dtb_node_head->header)->memreserve[i].address = fdt64_to_cpu(rsvmap[i].address); + ((struct dtb_header *)dtb_node_head->header)->memreserve[i].size = fdt64_to_cpu(rsvmap[i].size); + } + } + else + { + ((struct dtb_header *)dtb_node_head->header)->memreserve = NULL; + } + } + + dtb_node_head->path = paths_buf.ptr; + *paths_buf.cur++ = '/'; + *paths_buf.cur++ = '\0'; + dtb_node_head->parent = NULL; + dtb_node_head->sibling = NULL; + + dtb_node_head->handle = fdt_get_phandle(fdt, root_off); + dtb_node_head->properties = (struct dtb_property *)malloc(sizeof(struct dtb_property)); + dtb_node_head->child = (struct dtb_node *)malloc(sizeof(struct dtb_node)); + dtb_node_head->level = 0; + + if (dtb_node_head->properties == NULL || dtb_node_head->child == NULL) + { + fdt_exec_status = FDT_RET_NO_MEMORY; + goto fail; + } + + if ((fdt_exec_status = _dtb_node_get_dtb_properties_list(dtb_node_head->properties, root_off)) != FDT_RET_GET_OK) + { + goto fail; + } + + if ((fdt_exec_status = _dtb_node_get_dtb_nodes_list(dtb_node_head, dtb_node_head->child, dtb_node_head->path)) != FDT_RET_GET_OK) + { + goto fail; + } + + /* paths_buf.ptr addr save in the dtb_node_head's path */ + paths_buf.ptr = NULL; + paths_buf.cur = NULL; + + return dtb_node_head; + +fail: + if (dtb_node_head != NULL) + { + dtb_node_free_dtb_list(dtb_node_head); + } + + return NULL; +} + +static void _dtb_node_free_dtb_node(struct dtb_node *dtb_node) +{ + struct dtb_node *dtb_node_last; + struct dtb_property *dtb_property; + struct dtb_property *dtb_property_last; + + while (dtb_node != NULL) + { + dtb_property = dtb_node->properties; + while (dtb_property != NULL) + { + dtb_property_last = dtb_property; + dtb_property = dtb_property->next; + free(dtb_property_last); + } + + _dtb_node_free_dtb_node(dtb_node->child); + + dtb_node_last = dtb_node; + dtb_node = dtb_node->sibling; + free(dtb_node_last); + } +} + +void dtb_node_free_dtb_list(struct dtb_node *dtb_node_head) +{ + if (dtb_node_head == NULL) + { + return; + } + + /* only root node can free all path buffer */ + if (dtb_node_head->parent == NULL || (dtb_node_head->path != NULL && !strcmp(dtb_node_head->path, "/"))) + { + if (dtb_node_head->path != NULL) + { + free((void *)dtb_node_head->path); + } + if (dtb_node_head->header != NULL) + { + if (dtb_node_head->header->memreserve != NULL) + { + free((void *)dtb_node_head->header->memreserve); + } + free((void *)dtb_node_head->header); + } + } + + _dtb_node_free_dtb_node(dtb_node_head); +} + +static void _dtb_node_printf_depth(int depth) +{ + int i = depth; + while (i --> 0) + { + rt_kputs("\t"); + } +} + +rt_bool_t _dtb_node_test_string_list(const void *value, int size) +{ + const char *str = value; + const char *str_start, *str_end; + + if (size == 0) + { + return RT_FALSE; + } + + /* string end with '\0' */ + if (str[size - 1] != '\0') + { + return RT_FALSE; + } + + /* get string list end */ + str_end = str + size; + + while (str < str_end) + { + str_start = str; + /* before string list end, not '\0' and a printable characters */ + while (str < str_end && *str && ((unsigned char)*str >= ' ' && (unsigned char)*str <= '~')) + { + ++str; + } + + /* not zero, or not increased */ + if (*str != '\0' || str == str_start) + { + return RT_FALSE; + } + + /* next string */ + ++str; + } + + return RT_TRUE; +} + +static void _dtb_node_printf_dtb_node_info(struct dtb_node *dtb_node) +{ + static int depth = 0; + struct dtb_property *dtb_property; + + while (dtb_node != NULL) + { + rt_kputs("\n"); + _dtb_node_printf_depth(depth); + rt_kputs(dtb_node->name); + rt_kputs(" {\n"); + ++depth; + + dtb_property = dtb_node->properties; + while (dtb_property != NULL) + { + _dtb_node_printf_depth(depth); + + rt_kputs(dtb_property->name); + + if (dtb_property->size > 0) + { + int size = dtb_property->size; + char *value = dtb_property->value; + + rt_kputs(" = "); + if (_dtb_node_test_string_list(value, size) == RT_TRUE) + { + /* print string list */ + char *str = value; + do + { + rt_kprintf("\"%s\"", str); + str += strlen(str) + 1; + rt_kputs(", "); + } while (str < value + size); + rt_kputs("\b\b"); + } + else if ((size % 4) == 0) + { + /* print addr and size cell */ + int i; + fdt32_t *cell = (fdt32_t *)value; + + rt_kputs("<"); + for (i = 0, size /= 4; i < size; ++i) + { + rt_kprintf("0x%x ", fdt32_to_cpu(cell[i])); + } + rt_kputs("\b>"); + } + else + { + /* print bytes array */ + int i; + uint8_t *byte = (uint8_t *)value; + + rt_kputs("["); + for (i = 0; i < size; ++i) + { + rt_kprintf("%02x ", *byte++); + } + rt_kputs("\b]"); + } + } + rt_kputs(";\n"); + dtb_property = dtb_property->next; + } + + _dtb_node_printf_dtb_node_info(dtb_node->child); + dtb_node = dtb_node->sibling; + + --depth; + _dtb_node_printf_depth(depth); + rt_kputs("};\n"); + } +} + +void dtb_node_get_dts_dump(struct dtb_node *dtb_node_head) +{ + if (dtb_node_head != NULL) + { + int i = dtb_node_head->header->memreserve_sz; + + rt_kputs("/dts-v1/;\n"); + while (i --> 0) + { + rt_kprintf("\n/memreserve/\t0x%lx 0x%zx;", dtb_node_head->header->memreserve[i].address, dtb_node_head->header->memreserve[i].size); + } + + _dtb_node_printf_dtb_node_info(dtb_node_head); + } +} + +static void _dtb_node_get_enum_dtb_node(struct dtb_node *dtb_node, void (callback(struct dtb_node *dtb_node))) +{ + while (dtb_node != NULL) + { + callback(dtb_node); + _dtb_node_get_enum_dtb_node(dtb_node->child, callback); + dtb_node = dtb_node->sibling; + } +} + +void dtb_node_get_enum_dtb_node(struct dtb_node *dtb_node_head, void (callback(struct dtb_node *dtb_node))) +{ + if (dtb_node_head == NULL || callback == NULL) + { + return; + } + + _dtb_node_get_enum_dtb_node(dtb_node_head, callback); +} + +struct dtb_node *dtb_node_get_dtb_node_by_name_DFS(struct dtb_node *dtb_node, const char *nodename) +{ + struct dtb_node *dtb_node_child; + + while (dtb_node != NULL) + { + if (!strcmp(nodename, dtb_node->name)) + { + return dtb_node; + } + + dtb_node_child = dtb_node_get_dtb_node_by_name_DFS(dtb_node->child, nodename); + + if (dtb_node_child != NULL) + { + return dtb_node_child; + } + dtb_node = dtb_node->sibling; + } + + return NULL; +} + +struct dtb_node *dtb_node_get_dtb_node_by_name_BFS(struct dtb_node *dtb_node, const char *nodename) +{ + if (dtb_node != NULL) + { + struct dtb_node *dtb_node_child, *dtb_node_head = dtb_node; + + while (dtb_node != NULL) + { + if (!strcmp(nodename, dtb_node->name)) + { + return dtb_node; + } + dtb_node = dtb_node->sibling; + } + + dtb_node = dtb_node_head; + + while (dtb_node != NULL) + { + dtb_node_child = dtb_node_get_dtb_node_by_name_BFS(dtb_node->child, nodename); + + if (dtb_node_child != NULL) + { + return dtb_node_child; + } + dtb_node = dtb_node->sibling; + } + } + + return NULL; +} + +struct dtb_node *dtb_node_get_dtb_node_by_path(struct dtb_node *dtb_node, const char *pathname) +{ + int i = 0; + char *node_name; + char *pathname_clone; + int pathname_sz; + + if (pathname == NULL || dtb_node == NULL) + { + return NULL; + } + + /* skip '/' */ + if (*pathname == '/') + { + ++pathname; + } + + /* root not have sibling, so skip */ + if (dtb_node->parent == NULL || !strcmp(dtb_node->path, "/")) + { + dtb_node = dtb_node->child; + } + + pathname_sz = strlen(pathname) + 1; + pathname_clone = (char *)malloc(pathname_sz); + if (pathname_clone == NULL) + { + return NULL; + } + strncpy(pathname_clone, pathname, pathname_sz); + node_name = pathname_clone; + + while (pathname_clone[i]) + { + if (pathname_clone[i] == '/') + { + /* set an end of name that can used to strcmp */ + pathname_clone[i] = '\0'; + + while (dtb_node != NULL) + { + if (!strcmp(dtb_node->name, node_name)) + { + break; + } + dtb_node = dtb_node->sibling; + } + if (dtb_node == NULL) + { + free(pathname_clone); + return NULL; + } + dtb_node = dtb_node->child; + node_name = &pathname_clone[i + 1]; + } + ++i; + } + + /* + * found the end node and it's name: + * (pathname[pathname_sz - 1]) is '\0' + * (&pathname_clone[i] - node_name) is the node_name's length + */ + node_name = &((char *)pathname)[(pathname_sz - 1) - (&pathname_clone[i] - node_name)]; + free(pathname_clone); + + while (dtb_node != NULL) + { + if (!strcmp(dtb_node->name, node_name)) + { + return dtb_node; + } + dtb_node = dtb_node->sibling; + } + + return NULL; +} + +struct dtb_node *dtb_node_get_dtb_node_by_phandle_DFS(struct dtb_node *dtb_node, phandle handle) +{ + struct dtb_node *dtb_node_child; + + while (dtb_node != NULL) + { + if (dtb_node->handle == handle) + { + return dtb_node; + } + + dtb_node_child = dtb_node_get_dtb_node_by_phandle_DFS(dtb_node->child, handle); + + if (dtb_node_child != NULL) + { + return dtb_node_child; + } + dtb_node = dtb_node->sibling; + } + + return NULL; +} + +struct dtb_node *dtb_node_get_dtb_node_by_phandle_BFS(struct dtb_node *dtb_node, phandle handle) +{ + if (dtb_node != NULL) + { + struct dtb_node *dtb_node_child, *dtb_node_head = dtb_node; + + while (dtb_node != NULL) + { + if (dtb_node->handle == handle) + { + return dtb_node; + } + dtb_node = dtb_node->sibling; + } + + dtb_node = dtb_node_head; + + while (dtb_node != NULL) + { + dtb_node_child = dtb_node_get_dtb_node_by_phandle_BFS(dtb_node->child, handle); + + if (dtb_node_child != NULL) + { + return dtb_node_child; + } + dtb_node = dtb_node->sibling; + } + } + + return NULL; +} + +void dtb_node_get_dtb_node_cells(struct dtb_node *dtb_node, int *addr_cells, int *size_cells) +{ + if (dtb_node != NULL && addr_cells != NULL && size_cells != NULL) + { + struct dtb_property *dtb_property; + *addr_cells = -1; + *size_cells = -1; + + /* if couldn't found, check parent */ + while ((dtb_node = dtb_node->parent) != NULL) + { + dtb_property = dtb_node->properties; + while (dtb_property != NULL) + { + if (!strcmp(dtb_property->name, "#address-cells")) + { + *addr_cells = fdt32_to_cpu(*(int *)dtb_property->value); + } + else if (!strcmp(dtb_property->name, "#size-cells")) + { + *size_cells = fdt32_to_cpu(*(int *)dtb_property->value); + } + if (*addr_cells != -1 && *size_cells != -1) + { + return; + } + dtb_property = dtb_property->next; + } + } + + if (*addr_cells == -1) + { + *addr_cells = FDT_ROOT_ADDR_CELLS_DEFAULT; + } + if (*size_cells == -1) + { + *size_cells = FDT_ROOT_SIZE_CELLS_DEFAULT; + } + } +} + +struct dtb_memreserve *dtb_node_get_dtb_memreserve(struct dtb_node *dtb_node, int *memreserve_size) +{ + if (dtb_node != NULL && memreserve_size != NULL) + { + struct dtb_node *dtb_node_root = dtb_node; + + while (dtb_node_root != NULL) + { + if (!strcmp(dtb_node_root->path, "/")) + { + break; + } + dtb_node_root = dtb_node_root->parent; + } + if(dtb_node_root == NULL) return NULL; + + *memreserve_size = dtb_node_root->header->memreserve_sz; + + return dtb_node_root->header->memreserve; + } + return NULL; +} + +rt_bool_t dtb_node_get_dtb_node_status(const struct dtb_node *dtb_node) +{ + if (dtb_node != NULL) + { + char *status = dtb_node_get_dtb_node_property_value(dtb_node, "status", NULL); + if (status != NULL) + { + return (!strcmp(status, "okay") || !strcmp(status, "ok")) ? RT_TRUE : RT_FALSE; + } + + return RT_TRUE; + } + + return RT_FALSE; +} + +rt_bool_t dtb_node_get_dtb_node_compatible_match(const struct dtb_node *dtb_node, const char *compatibles) +{ + if (dtb_node != NULL) + { + if (compatibles != NULL) + { + char *str_ptr; + int prop_sz; + + for_each_property_string(dtb_node, "compatible", str_ptr, prop_sz) + { + if (!strcmp(compatibles, str_ptr)) + { + return RT_TRUE; + } + } + } + } + + return RT_FALSE; +} + +char *dtb_node_get_dtb_string_list_value(void *value, int size, int index) +{ + int i = 0; + char *str = value; + + if (str != NULL) + { + do + { + if (i++ == index) + { + return str; + } + str += strlen(str) + 1; + } while (str < (char *)value + size); + } + + return NULL; +} + +char *dtb_node_get_dtb_string_list_value_next(void *value, void *end) +{ + char *str = value; + + if (str != NULL) + { + str += strlen(str) + 1; + if (str < (char *)end) + { + return str; + } + } + + return NULL; +} + +uint32_t dtb_node_get_dtb_cell_value(void *value) +{ + return fdt32_to_cpu(*(fdt32_t *)value); +} + +uint8_t dtb_node_get_dtb_byte_value(void *value) +{ + return *(uint8_t *)value; +} diff --git a/components/legacy/fdt/src/dtb_head.c b/components/legacy/fdt/src/dtb_head.c new file mode 100644 index 0000000000..6142673393 --- /dev/null +++ b/components/legacy/fdt/src/dtb_head.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "dtb_node.h" + +static void *dtb_root = NULL; +static struct dtb_node *dtb_node_list = NULL; +void *get_fdt_blob(void) +{ + return dtb_root; +} + +struct dtb_node *get_dtb_node_head(void) +{ + return dtb_node_list; +} + +rt_bool_t dtb_node_active(void) +{ + return dtb_node_list != NULL; +} + +int device_tree_setup(void *mem_addr) +{ + if(mem_addr) + { + if ((dtb_root = dtb_node_load_from_memory(mem_addr,1)) != NULL) + { + dtb_node_list = dtb_node_get_dtb_list(dtb_root); + if (dtb_node_list != NULL) + { + return -1; + } + } + return 0; + } + + return -1; +} diff --git a/components/legacy/fdt/src/dtb_load.c b/components/legacy/fdt/src/dtb_load.c new file mode 100644 index 0000000000..c4ac535fdf --- /dev/null +++ b/components/legacy/fdt/src/dtb_load.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "libfdt.h" +#include +#include +#include "dtb_node.h" + +extern int fdt_exec_status; + +rt_bool_t dtb_node_check(void *fdt) +{ + return fdt_check_header(fdt) == 0 ? RT_TRUE : RT_FALSE; +} + +void *dtb_node_load_from_fs(char *dtb_filename) +{ + void *fdt = NULL; + size_t dtb_sz; + int fd = -1; + + if (dtb_filename == NULL) + { + fdt_exec_status = FDT_RET_GET_EMPTY; + goto end; + } + + fd = open(dtb_filename, O_RDONLY, 0); + + if (fd == -1) + { + rt_kprintf("File `%s' not found.\n", dtb_filename); + fdt_exec_status = FDT_RET_GET_EMPTY; + goto end; + } + + dtb_sz = lseek(fd, 0, SEEK_END); + + if (dtb_sz > 0) + { + if ((fdt = (struct fdt_header *)malloc(sizeof(uint8_t) * dtb_sz)) == NULL) + { + fdt_exec_status = FDT_RET_NO_MEMORY; + goto end; + } + + lseek(fd, 0, SEEK_SET); + read(fd, fdt, sizeof(uint8_t) * dtb_sz); + + if (dtb_node_check(fdt) == RT_FALSE) + { + free(fdt); + fdt=NULL; + } + } + +end: + if (fd != -1) + { + close(fd); + } + + return fdt; +} + +void *dtb_node_load_from_memory(void *dtb_ptr, rt_bool_t is_clone) +{ + void *fdt = NULL; + + if (dtb_ptr == NULL) + { + fdt_exec_status = FDT_RET_GET_EMPTY; + goto end; + } + + if (dtb_node_check(dtb_ptr) == RT_FALSE) + { + fdt_exec_status = FDT_RET_GET_EMPTY; + fdt = NULL; + goto end; + } + + if (is_clone) + { + size_t dtb_sz = fdt_totalsize(dtb_ptr); + if (dtb_sz > 0) + { + if ((fdt = (size_t *)malloc(dtb_sz)) != NULL) + { + memcpy(fdt, dtb_ptr, dtb_sz); + } + else + { + fdt_exec_status = FDT_RET_NO_MEMORY; + } + } + } + else + { + fdt = dtb_ptr; + } + +end: + return fdt; +} diff --git a/components/legacy/fdt/src/dtb_set.c b/components/legacy/fdt/src/dtb_set.c new file mode 100644 index 0000000000..f0e11b6b4f --- /dev/null +++ b/components/legacy/fdt/src/dtb_set.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "libfdt.h" +#include "dtb_node.h" + +static off_t dtb_node_find_and_add_subnode(void *fdt, char* name) +{ + off_t chosen_offset = 0; + + chosen_offset = fdt_subnode_offset(fdt, 0, name); + + if (chosen_offset == -FDT_ERR_NOTFOUND) + { + chosen_offset = fdt_add_subnode(fdt, 0, name); + } + + return chosen_offset; +} + +size_t dtb_node_set_linux_cmdline(void *fdt, char *cmdline) +{ + off_t chosen_offset; + size_t cmdline_size; + + if (cmdline == NULL || fdt == NULL) + { + goto end; + } + + chosen_offset = dtb_node_find_and_add_subnode(fdt, "chosen"); + cmdline_size = strlen(cmdline); + + /* install bootargs */ + if (chosen_offset >= 0 || chosen_offset == -FDT_ERR_EXISTS) + { + if (fdt_setprop(fdt, chosen_offset, "bootargs", cmdline, cmdline_size) < 0) + { + fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_DTB_PAD_SIZE); + fdt_setprop(fdt, chosen_offset, "bootargs", cmdline, cmdline_size); + } + } + +end: + return fdt_totalsize(fdt); +} + +size_t dtb_node_set_linux_initrd(void *fdt, uint64_t initrd_addr, size_t initrd_size) +{ + uint64_t addr, size_ptr; + off_t chosen_offset; + int i; + + if (fdt == NULL) + { + goto end; + } + + chosen_offset = dtb_node_find_and_add_subnode(fdt, "chosen"); + + /* update the entry */ + for (i = fdt_num_mem_rsv(fdt) - 1; i >= 0; --i) + { + fdt_get_mem_rsv(fdt, i, &addr, &size_ptr); + if (addr == initrd_addr) + { + fdt_del_mem_rsv(fdt, i); + break; + } + } + + /* add the memory */ + if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0) + { + /* move the memory */ + fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_DTB_PAD_SIZE); + if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0) + { + goto end; + } + } + + /* install initrd */ + if (chosen_offset >= 0 || chosen_offset == -FDT_ERR_EXISTS) + { + chosen_offset = fdt_path_offset(fdt, "/chosen"); + + if (IN_64BITS_MODE) + { + fdt_setprop_u64(fdt, chosen_offset, "linux,initrd-start", initrd_addr); + fdt_setprop_u64(fdt, chosen_offset, "linux,initrd-end", initrd_addr + initrd_size); + } + else + { + fdt_setprop_u32(fdt, chosen_offset, "linux,initrd-start", initrd_addr); + fdt_setprop_u32(fdt, chosen_offset, "linux,initrd-end", initrd_addr + initrd_size); + } + } + +end: + return fdt_totalsize(fdt); +} + +size_t dtb_node_set_dtb_property(void *fdt, char *pathname, char *property_name, uint32_t *cells, size_t cells_size) +{ + int node_off; + + if (fdt == NULL) + { + goto end; + } + + node_off = fdt_path_offset(fdt, pathname); + + if (node_off >= 0 && cells_size != 0) + { + fdt_setprop(fdt, node_off, property_name, cells, cells_size); + } + +end: + return fdt_totalsize(fdt); +} + +size_t dtb_node_add_dtb_memreserve(void *fdt, uint64_t address, uint64_t size) +{ + if (fdt == NULL) + { + goto end; + } + + fdt_add_mem_rsv(fdt, address, size); + +end: + return fdt_totalsize(fdt); +} + +size_t dtb_node_del_dtb_memreserve(void *fdt, uint64_t address) +{ + int i; + int num_mem_rsvmap; + uint32_t off_mem_rsvmap; + struct fdt_reserve_entry *rsvmap; + + if (fdt == NULL) + { + goto end; + } + + num_mem_rsvmap = fdt_num_mem_rsv(fdt); + off_mem_rsvmap = fdt_off_mem_rsvmap(fdt); + rsvmap = (struct fdt_reserve_entry *)((char *)fdt + off_mem_rsvmap); + + for (i = 0; i < num_mem_rsvmap; ++i) + { + if (address == fdt64_to_cpu(rsvmap[i].address)) + { + fdt_del_mem_rsv(fdt, i); + break; + } + } + +end: + return fdt_totalsize(fdt); +} diff --git a/components/legacy/usb/Kconfig b/components/legacy/usb/Kconfig new file mode 100644 index 0000000000..d20c0f92f9 --- /dev/null +++ b/components/legacy/usb/Kconfig @@ -0,0 +1,200 @@ +menu "Using USB legacy version" + config RT_USING_USB + bool + default n + + config RT_USING_USB_HOST + bool "Using USB host" + default n + select RT_USING_USB + + if RT_USING_USB_HOST + config RT_USBH_MSTORAGE + bool "Enable Udisk Drivers" + default n + if RT_USBH_MSTORAGE + config UDISK_MOUNTPOINT + string "Udisk mount dir" + default "/" + endif + config RT_USBH_HID + bool "Enable HID Drivers" + default n + if RT_USBH_HID + config RT_USBH_HID_MOUSE + bool "Enable HID mouse protocol" + default n + config RT_USBH_HID_KEYBOARD + bool "Enable HID keyboard protocol" + default n + endif + endif + config RT_USING_USB_DEVICE + bool "Using USB device" + default n + select RT_USING_USB + + if RT_USING_USB_DEVICE || RT_USING_USB_HOST + config RT_USBD_THREAD_STACK_SZ + int "usb thread stack size" + default 4096 + endif + if RT_USING_USB_DEVICE + config USB_VENDOR_ID + hex "USB Vendor ID" + default 0x0FFE + config USB_PRODUCT_ID + hex "USB Product ID" + default 0x0001 + + config RT_USB_DEVICE_COMPOSITE + bool "Enable composite device" + default n + choice + prompt "Device type" + default _RT_USB_DEVICE_NONE + depends on !RT_USB_DEVICE_COMPOSITE + config _RT_USB_DEVICE_NONE + bool "Using custom class by register interface" + select RT_USB_DEVICE_NONE + config _RT_USB_DEVICE_CDC + bool "Enable to use device as CDC device" + select RT_USB_DEVICE_CDC + config _RT_USB_DEVICE_MSTORAGE + bool "Enable to use device as Mass Storage device" + select RT_USB_DEVICE_MSTORAGE + config _RT_USB_DEVICE_HID + bool "Enable to use device as HID device" + select RT_USB_DEVICE_HID + config _RT_USB_DEVICE_RNDIS + bool "Enable to use device as rndis device" + select RT_USB_DEVICE_RNDIS + depends on RT_USING_LWIP + config _RT_USB_DEVICE_ECM + bool "Enable to use device as ecm device" + select RT_USB_DEVICE_ECM + depends on RT_USING_LWIP + config _RT_USB_DEVICE_WINUSB + bool "Enable to use device as winusb device" + select RT_USB_DEVICE_WINUSB + config _RT_USB_DEVICE_AUDIO + bool "Enable to use device as audio device" + select RT_USB_DEVICE_AUDIO + endchoice + if RT_USB_DEVICE_COMPOSITE + config RT_USB_DEVICE_CDC + bool "Enable to use device as CDC device" + default n + config RT_USB_DEVICE_NONE + bool + default y + config RT_USB_DEVICE_MSTORAGE + bool "Enable to use device as Mass Storage device" + default n + config RT_USB_DEVICE_HID + bool "Enable to use device as HID device" + default n + config RT_USB_DEVICE_RNDIS + bool "Enable to use device as rndis device" + default n + depends on RT_USING_LWIP + config RT_USB_DEVICE_ECM + bool "Enable to use device as ecm device" + default n + depends on RT_USING_LWIP + config RT_USB_DEVICE_WINUSB + bool "Enable to use device as winusb device" + default n + config RT_USB_DEVICE_AUDIO + bool "Enable to use device as audio device" + default n + endif + if RT_USB_DEVICE_CDC + config RT_VCOM_TASK_STK_SIZE + int "virtual com thread stack size" + default 512 + config RT_CDC_RX_BUFSIZE + int "virtual com rx buffer size" + default 128 + config RT_VCOM_TX_USE_DMA + bool "Enable to use dma for vcom tx" + default n + config RT_VCOM_SERNO + string "serial number of virtual com" + default "32021919830108" + config RT_VCOM_SER_LEN + int "serial number length of virtual com" + default 14 + config RT_VCOM_TX_TIMEOUT + int "tx timeout(ticks) of virtual com" + default 1000 + endif + if RT_USB_DEVICE_WINUSB + config RT_WINUSB_GUID + string "Guid for winusb" + default "{6860DC3C-C05F-4807-8807-1CA861CC1D66}" + endif + if RT_USB_DEVICE_MSTORAGE + config RT_USB_MSTORAGE_DISK_NAME + string "msc class disk name" + default "flash0" + endif + + if RT_USB_DEVICE_RNDIS + config RNDIS_DELAY_LINK_UP + bool "Delay linkup media connection" + select RT_USING_TIMER_SOFT + default n + endif + + if RT_USB_DEVICE_HID + config RT_USB_DEVICE_HID_KEYBOARD + bool "Use to HID device as Keyboard" + default n + if RT_USB_DEVICE_HID_KEYBOARD + config RT_USB_DEVICE_HID_KEYBOARD_NUMBER + int "Number of Keyboard(max 3)" + default 1 + range 1 3 + endif + config RT_USB_DEVICE_HID_MOUSE + bool "Use to HID device as Mouse" + default n + config RT_USB_DEVICE_HID_GENERAL + bool "Use to HID device as General HID device" + default y + if RT_USB_DEVICE_HID_GENERAL + config RT_USB_DEVICE_HID_GENERAL_OUT_REPORT_LENGTH + int "General HID device out report length" + default 63 + range 0 63 + + config RT_USB_DEVICE_HID_GENERAL_IN_REPORT_LENGTH + int "General HID device in report length" + default 63 + range 0 63 + endif + config RT_USB_DEVICE_HID_MEDIA + bool "Use to HID device as media keyboard" + default y + endif + if RT_USB_DEVICE_AUDIO + config RT_USB_DEVICE_AUDIO_MIC + bool "Use usb mic device as audio device" + default n + if RT_USB_DEVICE_AUDIO_MIC + config RT_USBD_MIC_DEVICE_NAME + string "audio mic device name" + default "mic0" + endif + config RT_USB_DEVICE_AUDIO_SPEAKER + bool "Use usb speaker device as audio device" + default n + if RT_USB_DEVICE_AUDIO_SPEAKER + config RT_USBD_SPEAKER_DEVICE_NAME + string "audio speaker device name" + default "sound0" + endif + endif + endif +endmenu -- cgit v1.3.1