例子1. 修改属性的值,
假设 老值: len
新值: newlen (假设newlen > len)
a. 把原属性val所占空间从len字节扩展为newlen字节:
把老值之后的所有内容向后移动(newlen - len)字节
b. 把新值写入val所占的newlen字节空间
c. 修改dtb头部信息中structure block的长度: size_dt_struct
d. 修改dtb头部信息中string block的偏移值: off_dt_strings
e. 修改dtb头部信息中的总长度: totalsize
例子2. 添加一个全新的属性
a. 如果在string block中没有这个属性的名字,
就在string block尾部添加一个新字符串: 属性的名
并且修改dtb头部信息中string block的长度: size_dt_strings
修改dtb头部信息中的总长度: totalsize
b. 找到属性所在节点, 在节点尾部扩展一块空间, 内容及长度为:
TAG // 4字节, 对应0x00000003
len // 4字节, 表示属性的val的长度
nameoff // 4字节, 表示属性名的offset
val // len字节, 用来存放val
c. 修改dtb头部信息中structure block的长度: size_dt_struct
d. 修改dtb头部信息中string block的偏移值: off_dt_strings
e. 修改dtb头部信息中的总长度: totalsize
可以从u-boot官网源码下载一个比较新的u-boot, 查看它的cmd/fdt.c
ftp://ftp.denx.de/pub/u-boot/
fdt命令调用过程:
fdt set
a. 根据path找到节点
b. 根据val确定新值长度newlen, 并把val转换为字节流
c. fdt_setprop
c.1 fdt_setprop_placeholder // 为新值在DTB中腾出位置
fdt_get_property_w // 得到老值的长度 oldlen
fdt_splice_struct_ // 腾空间
fdt_splice_ // 使用memmove移动DTB数据, 移动(newlen-oldlen)
fdt_set_size_dt_struct // 修改DTB头部, size_dt_struct
fdt_set_off_dt_strings // 修改DTB头部, off_dt_strings
c.2 memcpy(prop_data, val, len); // 在DTB中存入新值