Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OS
U-Boot.Mirror
提交
08cebeea
U
U-Boot.Mirror
项目概览
OS
/
U-Boot.Mirror
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
U-Boot.Mirror
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
08cebeea
编写于
9月 15, 2017
作者:
T
Tom Rini
浏览文件
操作
浏览文件
下载
差异文件
Merge
git://git.denx.de/u-boot-fdt
上级
110ba625
ea28e488
变更
42
隐藏空白更改
内联
并排
Showing
42 changed file
with
1656 addition
and
132 deletion
+1656
-132
.travis.yml
.travis.yml
+2
-3
cmd/fdt.c
cmd/fdt.c
+3
-4
common/fdt_support.c
common/fdt_support.c
+31
-0
common/image-fdt.c
common/image-fdt.c
+3
-4
common/image-fit.c
common/image-fit.c
+199
-11
configs/sandbox_defconfig
configs/sandbox_defconfig
+2
-0
doc/README.fdt-overlays
doc/README.fdt-overlays
+114
-0
doc/driver-model/of-plat.txt
doc/driver-model/of-plat.txt
+1
-1
doc/uImage.FIT/command_syntax_extensions.txt
doc/uImage.FIT/command_syntax_extensions.txt
+11
-1
doc/uImage.FIT/overlay-fdt-boot.txt
doc/uImage.FIT/overlay-fdt-boot.txt
+225
-0
doc/uImage.FIT/source_file_format.txt
doc/uImage.FIT/source_file_format.txt
+4
-2
drivers/clk/clk-uclass.c
drivers/clk/clk-uclass.c
+2
-2
drivers/clk/rockchip/clk_rk3368.c
drivers/clk/rockchip/clk_rk3368.c
+1
-1
drivers/clk/rockchip/clk_rk3399.c
drivers/clk/rockchip/clk_rk3399.c
+2
-2
drivers/core/regmap.c
drivers/core/regmap.c
+1
-1
include/clk.h
include/clk.h
+2
-2
include/dt-structs.h
include/dt-structs.h
+13
-3
include/fdt_support.h
include/fdt_support.h
+2
-0
include/fdtdec.h
include/fdtdec.h
+2
-0
include/image.h
include/image.h
+25
-0
include/regmap.h
include/regmap.h
+1
-1
include/syscon.h
include/syscon.h
+5
-1
lib/libfdt/fdt_overlay.c
lib/libfdt/fdt_overlay.c
+206
-22
lib/libfdt/fdt_rw.c
lib/libfdt/fdt_rw.c
+17
-3
lib/libfdt/fdt_wip.c
lib/libfdt/fdt_wip.c
+1
-1
lib/libfdt/libfdt.h
lib/libfdt/libfdt.h
+31
-0
lib/libfdt/pylibfdt/libfdt.i
lib/libfdt/pylibfdt/libfdt.i
+58
-0
scripts/Makefile.lib
scripts/Makefile.lib
+17
-0
scripts/Makefile.spl
scripts/Makefile.spl
+3
-2
test/overlay/Makefile
test/overlay/Makefile
+1
-0
test/overlay/cmd_ut_overlay.c
test/overlay/cmd_ut_overlay.c
+41
-9
test/overlay/test-fdt-overlay-stacked.dts
test/overlay/test-fdt-overlay-stacked.dts
+21
-0
tools/dtoc/dtb_platdata.py
tools/dtoc/dtb_platdata.py
+160
-44
tools/dtoc/dtoc_test_addr32.dts
tools/dtoc/dtoc_test_addr32.dts
+27
-0
tools/dtoc/dtoc_test_addr32_64.dts
tools/dtoc/dtoc_test_addr32_64.dts
+33
-0
tools/dtoc/dtoc_test_addr64.dts
tools/dtoc/dtoc_test_addr64.dts
+33
-0
tools/dtoc/dtoc_test_addr64_32.dts
tools/dtoc/dtoc_test_addr64_32.dts
+33
-0
tools/dtoc/dtoc_test_phandle.dts
tools/dtoc/dtoc_test_phandle.dts
+15
-1
tools/dtoc/dtoc_test_simple.dts
tools/dtoc/dtoc_test_simple.dts
+14
-0
tools/dtoc/fdt.py
tools/dtoc/fdt.py
+13
-6
tools/dtoc/fdt_util.py
tools/dtoc/fdt_util.py
+16
-0
tools/dtoc/test_dtoc.py
tools/dtoc/test_dtoc.py
+265
-5
未找到文件。
.travis.yml
浏览文件 @
08cebeea
...
...
@@ -26,12 +26,11 @@ addons:
-
grub-efi-ia32-bin
-
rpm2cpio
-
wget
-
device-tree-compiler
install
:
# install latest device tree compiler
#
- git clone --depth=1 git://git.kernel.org/pub/scm/utils/dtc/dtc.git /tmp/dtc
#
- make -j4 -C /tmp/dtc
-
git clone --depth=1 git://git.kernel.org/pub/scm/utils/dtc/dtc.git /tmp/dtc
-
make -j4 -C /tmp/dtc
# Clone uboot-test-hooks
-
git clone --depth=1 git://github.com/swarren/uboot-test-hooks.git /tmp/uboot-test-hooks
-
ln -s travis-ci /tmp/uboot-test-hooks/bin/`hostname`
...
...
cmd/fdt.c
浏览文件 @
08cebeea
...
...
@@ -667,11 +667,10 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if
(
!
fdt_valid
(
&
blob
))
return
CMD_RET_FAILURE
;
ret
=
fdt_overlay_apply
(
working_fdt
,
blob
);
if
(
ret
)
{
printf
(
"fdt_overlay_apply(): %s
\n
"
,
fdt_strerror
(
ret
));
/* apply method prints messages on error */
ret
=
fdt_overlay_apply_verbose
(
working_fdt
,
blob
);
if
(
ret
)
return
CMD_RET_FAILURE
;
}
}
#endif
/* resize the fdt */
...
...
common/fdt_support.c
浏览文件 @
08cebeea
...
...
@@ -1655,3 +1655,34 @@ int fdt_fixup_display(void *blob, const char *path, const char *display)
}
return
toff
;
}
#ifdef CONFIG_OF_LIBFDT_OVERLAY
/**
* fdt_overlay_apply_verbose - Apply an overlay with verbose error reporting
*
* @fdt: ptr to device tree
* @fdto: ptr to device tree overlay
*
* Convenience function to apply an overlay and display helpful messages
* in the case of an error
*/
int
fdt_overlay_apply_verbose
(
void
*
fdt
,
void
*
fdto
)
{
int
err
;
bool
has_symbols
;
err
=
fdt_path_offset
(
fdt
,
"/__symbols__"
);
has_symbols
=
err
>=
0
;
err
=
fdt_overlay_apply
(
fdt
,
fdto
);
if
(
err
<
0
)
{
printf
(
"failed on fdt_overlay_apply(): %s
\n
"
,
fdt_strerror
(
err
));
if
(
!
has_symbols
)
{
printf
(
"base fdt does did not have a /__symbols__ node
\n
"
);
printf
(
"make sure you've compiled with -@
\n
"
);
}
}
return
err
;
}
#endif
common/image-fdt.c
浏览文件 @
08cebeea
...
...
@@ -356,17 +356,16 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
if
(
fit_check_format
(
buf
))
{
ulong
load
,
len
;
fdt_noffset
=
fit_image_load
(
images
,
fdt_noffset
=
boot_get_fdt_fit
(
images
,
fdt_addr
,
&
fit_uname_fdt
,
&
fit_uname_config
,
arch
,
IH_TYPE_FLATDT
,
BOOTSTAGE_ID_FIT_FDT_START
,
FIT_LOAD_OPTIONAL
,
&
load
,
&
len
);
arch
,
&
load
,
&
len
);
images
->
fit_hdr_fdt
=
map_sysmem
(
fdt_addr
,
0
);
images
->
fit_uname_fdt
=
fit_uname_fdt
;
images
->
fit_noffset_fdt
=
fdt_noffset
;
fdt_addr
=
load
;
break
;
}
else
#endif
...
...
common/image-fit.c
浏览文件 @
08cebeea
...
...
@@ -19,6 +19,7 @@
#include <errno.h>
#include <mapmem.h>
#include <asm/io.h>
#include <malloc.h>
DECLARE_GLOBAL_DATA_PTR
;
#endif
/* !USE_HOSTCC*/
...
...
@@ -434,6 +435,10 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
printf
(
"0x%08lx
\n
"
,
load
);
}
/* optional load address for FDT */
if
(
type
==
IH_TYPE_FLATDT
&&
!
fit_image_get_load
(
fit
,
image_noffset
,
&
load
))
printf
(
"%s Load Address: 0x%08lx
\n
"
,
p
,
load
);
if
((
type
==
IH_TYPE_KERNEL
)
||
(
type
==
IH_TYPE_STANDALONE
)
||
(
type
==
IH_TYPE_RAMDISK
))
{
ret
=
fit_image_get_entry
(
fit
,
image_noffset
,
&
entry
);
...
...
@@ -1454,6 +1459,8 @@ int fit_conf_get_node(const void *fit, const char *conf_uname)
{
int
noffset
,
confs_noffset
;
int
len
;
const
char
*
s
;
char
*
conf_uname_copy
=
NULL
;
confs_noffset
=
fdt_path_offset
(
fit
,
FIT_CONFS_PATH
);
if
(
confs_noffset
<
0
)
{
...
...
@@ -1475,29 +1482,58 @@ int fit_conf_get_node(const void *fit, const char *conf_uname)
debug
(
"Found default configuration: '%s'
\n
"
,
conf_uname
);
}
s
=
strchr
(
conf_uname
,
'#'
);
if
(
s
)
{
len
=
s
-
conf_uname
;
conf_uname_copy
=
malloc
(
len
+
1
);
if
(
!
conf_uname_copy
)
{
debug
(
"Can't allocate uname copy: '%s'
\n
"
,
conf_uname
);
return
-
ENOMEM
;
}
memcpy
(
conf_uname_copy
,
conf_uname
,
len
);
conf_uname_copy
[
len
]
=
'\0'
;
conf_uname
=
conf_uname_copy
;
}
noffset
=
fdt_subnode_offset
(
fit
,
confs_noffset
,
conf_uname
);
if
(
noffset
<
0
)
{
debug
(
"Can't get node offset for configuration unit name: '%s' (%s)
\n
"
,
conf_uname
,
fdt_strerror
(
noffset
));
}
if
(
conf_uname_copy
)
free
(
conf_uname_copy
);
return
noffset
;
}
int
fit_conf_get_prop_node
(
const
void
*
fit
,
int
noffset
,
int
fit_conf_get_prop_node
_count
(
const
void
*
fit
,
int
noffset
,
const
char
*
prop_name
)
{
char
*
uname
;
return
fdt_stringlist_count
(
fit
,
noffset
,
prop_name
);
}
int
fit_conf_get_prop_node_index
(
const
void
*
fit
,
int
noffset
,
const
char
*
prop_name
,
int
index
)
{
const
char
*
uname
;
int
len
;
/* get kernel image unit name from configuration kernel property */
uname
=
(
char
*
)
fdt_getprop
(
fit
,
noffset
,
prop_name
,
&
len
);
uname
=
fdt_stringlist_get
(
fit
,
noffset
,
prop_name
,
index
,
&
len
);
if
(
uname
==
NULL
)
return
len
;
return
fit_image_get_node
(
fit
,
uname
);
}
int
fit_conf_get_prop_node
(
const
void
*
fit
,
int
noffset
,
const
char
*
prop_name
)
{
return
fit_conf_get_prop_node_index
(
fit
,
noffset
,
prop_name
,
0
);
}
/**
* fit_conf_print - prints out the FIT configuration details
* @fit: pointer to the FIT format image header
...
...
@@ -1515,7 +1551,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
char
*
desc
;
const
char
*
uname
;
int
ret
;
int
loadables_index
;
int
fdt_index
,
loadables_index
;
/* Mandatory properties */
ret
=
fit_get_desc
(
fit
,
noffset
,
&
desc
);
...
...
@@ -1537,9 +1573,17 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
if
(
uname
)
printf
(
"%s Init Ramdisk: %s
\n
"
,
p
,
uname
);
uname
=
fdt_getprop
(
fit
,
noffset
,
FIT_FDT_PROP
,
NULL
);
if
(
uname
)
printf
(
"%s FDT: %s
\n
"
,
p
,
uname
);
for
(
fdt_index
=
0
;
uname
=
fdt_stringlist_get
(
fit
,
noffset
,
FIT_FDT_PROP
,
fdt_index
,
NULL
),
uname
;
fdt_index
++
)
{
if
(
fdt_index
==
0
)
printf
(
"%s FDT: "
,
p
);
else
printf
(
"%s "
,
p
);
printf
(
"%s
\n
"
,
uname
);
}
uname
=
fdt_getprop
(
fit
,
noffset
,
FIT_FPGA_PROP
,
NULL
);
if
(
uname
)
...
...
@@ -1641,6 +1685,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
int
cfg_noffset
,
noffset
;
const
char
*
fit_uname
;
const
char
*
fit_uname_config
;
const
char
*
fit_base_uname_config
;
const
void
*
fit
;
const
void
*
buf
;
size_t
size
;
...
...
@@ -1656,6 +1701,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
fit
=
map_sysmem
(
addr
,
0
);
fit_uname
=
fit_unamep
?
*
fit_unamep
:
NULL
;
fit_uname_config
=
fit_uname_configp
?
*
fit_uname_configp
:
NULL
;
fit_base_uname_config
=
NULL
;
prop_name
=
fit_get_image_type_property
(
image_type
);
printf
(
"## Loading %s from FIT Image at %08lx ...
\n
"
,
prop_name
,
addr
);
...
...
@@ -1689,11 +1735,11 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
BOOTSTAGE_SUB_NO_UNIT_NAME
);
return
-
ENOENT
;
}
fit_uname_config
=
fdt_get_name
(
fit
,
cfg_noffset
,
NULL
);
printf
(
" Using '%s' configuration
\n
"
,
fit_uname_config
);
fit_
base_
uname_config
=
fdt_get_name
(
fit
,
cfg_noffset
,
NULL
);
printf
(
" Using '%s' configuration
\n
"
,
fit_
base_
uname_config
);
if
(
image_type
==
IH_TYPE_KERNEL
)
{
/* Remember (and possibly verify) this config */
images
->
fit_uname_cfg
=
fit_uname_config
;
images
->
fit_uname_cfg
=
fit_
base_
uname_config
;
if
(
IMAGE_ENABLE_VERIFY
&&
images
->
verify
)
{
puts
(
" Verifying Hash Integrity ... "
);
if
(
fit_config_verify
(
fit
,
cfg_noffset
))
{
...
...
@@ -1849,7 +1895,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
if
(
fit_unamep
)
*
fit_unamep
=
(
char
*
)
fit_uname
;
if
(
fit_uname_configp
)
*
fit_uname_configp
=
(
char
*
)
fit_uname_config
;
*
fit_uname_configp
=
(
char
*
)(
fit_uname_config
?
:
fit_base_uname_config
);
return
noffset
;
}
...
...
@@ -1873,3 +1920,144 @@ int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
return
ret
;
}
#ifndef USE_HOSTCC
int
boot_get_fdt_fit
(
bootm_headers_t
*
images
,
ulong
addr
,
const
char
**
fit_unamep
,
const
char
**
fit_uname_configp
,
int
arch
,
ulong
*
datap
,
ulong
*
lenp
)
{
int
fdt_noffset
,
cfg_noffset
,
count
;
const
void
*
fit
;
const
char
*
fit_uname
=
NULL
;
const
char
*
fit_uname_config
=
NULL
;
char
*
fit_uname_config_copy
=
NULL
;
char
*
next_config
=
NULL
;
ulong
load
,
len
;
#ifdef CONFIG_OF_LIBFDT_OVERLAY
ulong
image_start
,
image_end
;
ulong
ovload
,
ovlen
;
const
char
*
uconfig
;
const
char
*
uname
;
void
*
base
,
*
ov
;
int
i
,
err
,
noffset
,
ov_noffset
;
#endif
fit_uname
=
fit_unamep
?
*
fit_unamep
:
NULL
;
if
(
fit_uname_configp
&&
*
fit_uname_configp
)
{
fit_uname_config_copy
=
strdup
(
*
fit_uname_configp
);
if
(
!
fit_uname_config_copy
)
return
-
ENOMEM
;
next_config
=
strchr
(
fit_uname_config_copy
,
'#'
);
if
(
next_config
)
*
next_config
++
=
'\0'
;
if
(
next_config
-
1
>
fit_uname_config_copy
)
fit_uname_config
=
fit_uname_config_copy
;
}
fdt_noffset
=
fit_image_load
(
images
,
addr
,
&
fit_uname
,
&
fit_uname_config
,
arch
,
IH_TYPE_FLATDT
,
BOOTSTAGE_ID_FIT_FDT_START
,
FIT_LOAD_OPTIONAL
,
&
load
,
&
len
);
if
(
fdt_noffset
<
0
)
goto
out
;
debug
(
"fit_uname=%s, fit_uname_config=%s
\n
"
,
fit_uname
?
fit_uname
:
"<NULL>"
,
fit_uname_config
?
fit_uname_config
:
"<NULL>"
);
fit
=
map_sysmem
(
addr
,
0
);
cfg_noffset
=
fit_conf_get_node
(
fit
,
fit_uname_config
);
/* single blob, or error just return as well */
count
=
fit_conf_get_prop_node_count
(
fit
,
cfg_noffset
,
FIT_FDT_PROP
);
if
(
count
<=
1
&&
!
next_config
)
goto
out
;
/* we need to apply overlays */
#ifdef CONFIG_OF_LIBFDT_OVERLAY
image_start
=
addr
;
image_end
=
addr
+
fit_get_size
(
fit
);
/* verify that relocation took place by load address not being in fit */
if
(
load
>=
image_start
&&
load
<
image_end
)
{
/* check is simplified; fit load checks for overlaps */
printf
(
"Overlayed FDT requires relocation
\n
"
);
fdt_noffset
=
-
EBADF
;
goto
out
;
}
base
=
map_sysmem
(
load
,
len
);
/* apply extra configs in FIT first, followed by args */
for
(
i
=
1
;
;
i
++
)
{
if
(
i
<
count
)
{
noffset
=
fit_conf_get_prop_node_index
(
fit
,
cfg_noffset
,
FIT_FDT_PROP
,
i
);
uname
=
fit_get_name
(
fit
,
noffset
,
NULL
);
uconfig
=
NULL
;
}
else
{
if
(
!
next_config
)
break
;
uconfig
=
next_config
;
next_config
=
strchr
(
next_config
,
'#'
);
if
(
next_config
)
*
next_config
++
=
'\0'
;
uname
=
NULL
;
}
debug
(
"%d: using uname=%s uconfig=%s
\n
"
,
i
,
uname
,
uconfig
);
ov_noffset
=
fit_image_load
(
images
,
addr
,
&
uname
,
&
uconfig
,
arch
,
IH_TYPE_FLATDT
,
BOOTSTAGE_ID_FIT_FDT_START
,
FIT_LOAD_REQUIRED
,
&
ovload
,
&
ovlen
);
if
(
ov_noffset
<
0
)
{
printf
(
"load of %s failed
\n
"
,
uname
);
continue
;
}
debug
(
"%s loaded at 0x%08lx len=0x%08lx
\n
"
,
uname
,
ovload
,
ovlen
);
ov
=
map_sysmem
(
ovload
,
ovlen
);
base
=
map_sysmem
(
load
,
len
+
ovlen
);
err
=
fdt_open_into
(
base
,
base
,
len
+
ovlen
);
if
(
err
<
0
)
{
printf
(
"failed on fdt_open_into
\n
"
);
fdt_noffset
=
err
;
goto
out
;
}
/* the verbose method prints out messages on error */
err
=
fdt_overlay_apply_verbose
(
base
,
ov
);
if
(
err
<
0
)
{
fdt_noffset
=
err
;
goto
out
;
}
fdt_pack
(
base
);
len
=
fdt_totalsize
(
base
);
}
#else
printf
(
"config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set
\n
"
);
fdt_noffset
=
-
EBADF
;
#endif
out:
if
(
datap
)
*
datap
=
load
;
if
(
lenp
)
*
lenp
=
len
;
if
(
fit_unamep
)
*
fit_unamep
=
fit_uname
;
if
(
fit_uname_configp
)
*
fit_uname_configp
=
fit_uname_config
;
if
(
fit_uname_config_copy
)
free
(
fit_uname_config_copy
);
return
fdt_noffset
;
}
#endif
configs/sandbox_defconfig
浏览文件 @
08cebeea
...
...
@@ -190,7 +190,9 @@ CONFIG_CMD_DHRYSTONE=y
CONFIG_TPM=y
CONFIG_LZ4=y
CONFIG_ERRNO_STR=y
CONFIG_OF_LIBFDT_OVERLAY=y
CONFIG_UNIT_TEST=y
CONFIG_UT_TIME=y
CONFIG_UT_DM=y
CONFIG_UT_ENV=y
CONFIG_UT_OVERLAY=y
doc/README.fdt-overlays
0 → 100644
浏览文件 @
08cebeea
U-Boot FDT Overlay usage
=============================================
Overlays Syntax
---------------
Overlays require slightly different syntax compared to traditional overlays.
Please refer to dt-object-internal.txt in the dtc sources for information
regarding the internal format of overlays:
https://git.kernel.org/pub/scm/utils/dtc/dtc.git/tree/Documentation/dt-object-internal.txt
Building Overlays
-----------------
In a nutshell overlays provides a means to manipulate a symbol a previous dtb
or overlay has defined. It requires both the base and all the overlays
to be compiled with the -@ command line switch so that symbol information is
included.
Note support for -@ option can only be found in dtc version 1.4.4 or newer.
Only version 4.14 or higher of the Linux kernel includes a built in version
of dtc that meets this requirement.
Building an overlay follows the same process as building a traditional dtb.
For example:
base.dts
--------
/dts-v1/;
/ {
foo: foonode {
foo-property;
};
};
$ dtc -@ -I dts -O dtb -o base.dtb base.dts
bar.dts
-------
/dts-v1/;
/plugin/;
/ {
fragment@1 {
target = <&foo>;
__overlay__ {
overlay-1-property;
bar: barnode {
bar-property;
};
};
};
};
$ dtc -@ -I dts -O dtb -o bar.dtb bar.dts
Ways to Utilize Overlays in U-boot
----------------------------------
There are two ways to apply overlays in U-boot.
1. Include and define overlays within a FIT image and have overlays
automatically applied.
2. Manually load and apply overlays
The remainder of this document will discuss using overlays via the manual
approach. For information on using overlays as part of a FIT image please see:
doc/uImage.FIT/overlay-fdt-boot.txt
Manually Loading and Applying Overlays
--------------------------------------
1. Figure out where to place both the base device tree blob and the
overlay. Make sure you have enough space to grow the base tree without
overlapping anything.
=> setenv fdtaddr 0x87f00000
=> setenv fdtovaddr 0x87fc0000
2. Load the base blob and overlay blobs
=> load ${devtype} ${bootpart} ${fdtaddr} ${bootdir}/base.dtb
=> load ${devtype} ${bootpart} ${fdtovaddr} ${bootdir}/overlay.dtb
3. Set it as the working fdt tree.
=> fdtaddr $fdtaddr
4. Grow it enough so it can 'fit' all the applied overlays
=> fdt resize 8192
5. You are now ready to apply the overlay.
=> fdt apply $fdtovaddr
6. Boot system like you would do with a traditional dtb.
For bootm:
=> bootm ${kerneladdr} - ${fdtaddr}
For bootz:
=> bootz ${kerneladdr} - ${fdtaddr}
Please note that in case of an error, both the base and overlays are going
to be invalidated, so keep copies to avoid reloading.
Pantelis Antoniou
pantelis.antoniou@konsulko.com
11/7/2017
doc/driver-model/of-plat.txt
浏览文件 @
08cebeea
...
...
@@ -111,7 +111,7 @@ struct dtd_rockchip_rk3288_dw_mshc {
bool cap_sd_highspeed;
fdt32_t card_detect_delay;
fdt32_t clock_freq_min_max[2];
struct phandle_
2_cell
clocks[4];
struct phandle_
1_arg
clocks[4];
bool disable_wp;
fdt32_t fifo_depth;
fdt32_t interrupts[3];
...
...
doc/uImage.FIT/command_syntax_extensions.txt
浏览文件 @
08cebeea
...
...
@@ -36,7 +36,7 @@ Old uImage:
New uImage:
8. bootm <addr1>
9. bootm [<addr1>]:<subimg1>
10. bootm [<addr1>]#<conf>
10. bootm [<addr1>]#<conf>
[#<extra-conf[#...]]
11. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2>
12. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> [<addr3>]:<subimg3>
13. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> <addr3>
...
...
@@ -129,6 +129,12 @@ following syntax:
- new uImage configuration specification
<addr>#<configuration unit_name>
- new uImage configuration specification with extra configuration components
<addr>#<configuration unit_name>[#<extra configuration unit_name>[#..]]
The extra configuration currently is supported only for additional device tree
overlays to apply on the base device tree supplied by the first configuration
unit.
Examples:
...
...
@@ -138,6 +144,10 @@ bootm 200000:kernel@1
- boot configuration "cfg@1" from a new uImage located at 200000:
bootm 200000#cfg@1
- boot configuration "cfg@1" with extra "cfg@2" from a new uImage located
at 200000:
bootm 200000#cfg@1#cfg@2
- boot "kernel@1" from a new uImage at 200000 with initrd "ramdisk@2" found in
some other new uImage stored at address 800000:
bootm 200000:kernel@1 800000:ramdisk@2
...
...
doc/uImage.FIT/overlay-fdt-boot.txt
0 → 100644
浏览文件 @
08cebeea
U-Boot FDT Overlay FIT usage
============================
Introduction
------------
In many cases it is desirable to have a single FIT image support a multitude
of similar boards and their expansion options. The same kernel on DT enabled
platforms can support this easily enough by providing a DT blob upon boot
that matches the desired configuration.
This document focuses on specifically using overlays as part of a FIT image.
General information regarding overlays including its syntax and building it
can be found in doc/README.fdt-overlays
Configuration without overlays
------------------------------
Take a hypothetical board named 'foo' where there are different supported
revisions, reva and revb. Assume that both board revisions can use add a bar
add-on board, while only the revb board can use a baz add-on board.
Without using overlays the configuration would be as follows for every case.
/dts-v1/;
/ {
images {
kernel@1 {
data = /incbin/("./zImage");
type = "kernel";
arch = "arm";
os = "linux";
load = <0x82000000>;
entry = <0x82000000>;
};
fdt@1 {
data = /incbin/("./foo-reva.dtb");
type = "flat_dt";
arch = "arm";
};
fdt@2 {
data = /incbin/("./foo-revb.dtb");
type = "flat_dt";
arch = "arm";
};
fdt@3 {
data = /incbin/("./foo-reva-bar.dtb");
type = "flat_dt";
arch = "arm";
};
fdt@4 {
data = /incbin/("./foo-revb-bar.dtb");
type = "flat_dt";
arch = "arm";
};
fdt@5 {
data = /incbin/("./foo-revb-baz.dtb");
type = "flat_dt";
arch = "arm";
};
fdt@6 {
data = /incbin/("./foo-revb-bar-baz.dtb");
type = "flat_dt";
arch = "arm";
};
};
configurations {
default = "foo-reva.dtb;
foo-reva.dtb {
kernel = "kernel@1";
fdt = "fdt@1";
};
foo-revb.dtb {
kernel = "kernel@1";
fdt = "fdt@2";
};
foo-reva-bar.dtb {
kernel = "kernel@1";
fdt = "fdt@3";
};
foo-revb-bar.dtb {
kernel = "kernel@1";
fdt = "fdt@4";
};
foo-revb-baz.dtb {
kernel = "kernel@1";
fdt = "fdt@5";
};
foo-revb-bar-baz.dtb {
kernel = "kernel@1";
fdt = "fdt@6";
};
};
};
Note the blob needs to be compiled for each case and the combinatorial explosion of
configurations. A typical device tree blob is in the low hunderds of kbytes so a
multitude of configuration grows the image quite a bit.
Booting this image is done by using
# bootm <addr>#<config>
Where config is one of:
foo-reva.dtb, foo-revb.dtb, foo-reva-bar.dtb, foo-revb-bar.dtb,
foo-revb-baz.dtb, foo-revb-bar-baz.dtb
This selects the DTB to use when booting.
Configuration using overlays
----------------------------
Device tree overlays can be applied to a base DT and result in the same blob
being passed to the booting kernel. This saves on space and avoid the combinatorial
explosion problem.
/dts-v1/;
/ {
images {
kernel@1 {
data = /incbin/("./zImage");
type = "kernel";
arch = "arm";
os = "linux";
load = <0x82000000>;
entry = <0x82000000>;
};
fdt@1 {
data = /incbin/("./foo.dtb");
type = "flat_dt";
arch = "arm";
load = <0x87f00000>;
};
fdt@2 {
data = /incbin/("./reva.dtbo");
type = "flat_dt";
arch = "arm";
load = <0x87fc0000>;
};
fdt@3 {
data = /incbin/("./revb.dtbo");
type = "flat_dt";
arch = "arm";
load = <0x87fc0000>;
};
fdt@4 {
data = /incbin/("./bar.dtbo");
type = "flat_dt";
arch = "arm";
load = <0x87fc0000>;
};
fdt@5 {
data = /incbin/("./baz.dtbo");
type = "flat_dt";
arch = "arm";
load = <0x87fc0000>;
};
};
configurations {
default = "foo-reva.dtb;
foo-reva.dtb {
kernel = "kernel@1";
fdt = "fdt@1", "fdt@2";
};
foo-revb.dtb {
kernel = "kernel@1";
fdt = "fdt@1", "fdt@3";
};
foo-reva-bar.dtb {
kernel = "kernel@1";
fdt = "fdt@1", "fdt@2", "fdt@4";
};
foo-revb-bar.dtb {
kernel = "kernel@1";
fdt = "fdt@1", "fdt@3", "fdt@4";
};
foo-revb-baz.dtb {
kernel = "kernel@1";
fdt = "fdt@1", "fdt@3", "fdt@5";
};
foo-revb-bar-baz.dtb {
kernel = "kernel@1";
fdt = "fdt@1", "fdt@3", "fdt@4", "fdt@5";
};
bar {
fdt = "fdt@4";
};
baz {
fdt = "fdt@5";
};
};
};
Booting this image is exactly the same as the non-overlay example.
u-boot will retrieve the base blob and apply the overlays in sequence as
they are declared in the configuration.
Note the minimum amount of different DT blobs, as well as the requirement for
the DT blobs to have a load address; the overlay application requires the blobs
to be writeable.
Configuration using overlays and feature selection
--------------------------------------------------
Although the configuration in the previous section works is a bit inflexible
since it requires all possible configuration options to be laid out before
hand in the FIT image. For the add-on boards the extra config selection method
might make sense.
Note the two bar & baz configuration nodes. To boot a reva board with
the bar add-on board enabled simply use:
# bootm <addr>#foo-reva.dtb#bar
While booting a revb with bar and baz is as follows:
# bootm <addr>#foo-revb.dtb#bar#baz
The limitation for a feature selection configuration node is that a single
fdt option is currently supported.
Pantelis Antoniou
pantelis.antoniou@konsulko.com
12/6/2017
doc/uImage.FIT/source_file_format.txt
浏览文件 @
08cebeea
...
...
@@ -235,7 +235,7 @@ o config@1
|- description = "configuration description"
|- kernel = "kernel sub-node unit name"
|- ramdisk = "ramdisk sub-node unit name"
|- fdt = "fdt sub-node unit-name"
|- fdt = "fdt sub-node unit-name"
[, "fdt overlay sub-node unit-name", ...]
|- fpga = "fpga sub-node unit-name"
|- loadables = "loadables sub-node unit-name"
...
...
@@ -249,7 +249,9 @@ o config@1
- ramdisk : Unit name of the corresponding ramdisk image (component image
node of a "ramdisk" type).
- fdt : Unit name of the corresponding fdt blob (component image node of a
"fdt type").
"fdt type"). Additional fdt overlay nodes can be supplied which signify
that the resulting device tree blob is generated by the first base fdt
blob with all subsequent overlays applied.
- setup : Unit name of the corresponding setup binary (used for booting
an x86 kernel). This contains the setup.bin file built by the kernel.
- fpga : Unit name of the corresponding fpga bitstream blob
...
...
drivers/clk/clk-uclass.c
浏览文件 @
08cebeea
...
...
@@ -23,7 +23,7 @@ static inline struct clk_ops *clk_dev_ops(struct udevice *dev)
#if CONFIG_IS_ENABLED(OF_CONTROL)
# if CONFIG_IS_ENABLED(OF_PLATDATA)
int
clk_get_by_index_platdata
(
struct
udevice
*
dev
,
int
index
,
struct
phandle_
2_cell
*
cells
,
struct
clk
*
clk
)
struct
phandle_
1_arg
*
cells
,
struct
clk
*
clk
)
{
int
ret
;
...
...
@@ -32,7 +32,7 @@ int clk_get_by_index_platdata(struct udevice *dev, int index,
ret
=
uclass_get_device
(
UCLASS_CLK
,
0
,
&
clk
->
dev
);
if
(
ret
)
return
ret
;
clk
->
id
=
cells
[
0
].
id
;
clk
->
id
=
cells
[
0
].
arg
[
0
]
;
return
0
;
}
...
...
drivers/clk/rockchip/clk_rk3368.c
浏览文件 @
08cebeea
...
...
@@ -471,7 +471,7 @@ static int rk3368_clk_probe(struct udevice *dev)
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct
rk3368_clk_plat
*
plat
=
dev_get_platdata
(
dev
);
priv
->
cru
=
map_sysmem
(
plat
->
dtd
.
reg
[
1
],
plat
->
dtd
.
reg
[
3
]);
priv
->
cru
=
map_sysmem
(
plat
->
dtd
.
reg
[
0
],
plat
->
dtd
.
reg
[
1
]);
#endif
#if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD)
rkclk_init
(
priv
->
cru
);
...
...
drivers/clk/rockchip/clk_rk3399.c
浏览文件 @
08cebeea
...
...
@@ -963,7 +963,7 @@ static int rk3399_clk_probe(struct udevice *dev)
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct
rk3399_clk_plat
*
plat
=
dev_get_platdata
(
dev
);
priv
->
cru
=
map_sysmem
(
plat
->
dtd
.
reg
[
1
],
plat
->
dtd
.
reg
[
3
]);
priv
->
cru
=
map_sysmem
(
plat
->
dtd
.
reg
[
0
],
plat
->
dtd
.
reg
[
1
]);
#endif
rkclk_init
(
priv
->
cru
);
#endif
...
...
@@ -1145,7 +1145,7 @@ static int rk3399_pmuclk_probe(struct udevice *dev)
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct
rk3399_pmuclk_plat
*
plat
=
dev_get_platdata
(
dev
);
priv
->
pmucru
=
map_sysmem
(
plat
->
dtd
.
reg
[
1
],
plat
->
dtd
.
reg
[
3
]);
priv
->
pmucru
=
map_sysmem
(
plat
->
dtd
.
reg
[
0
],
plat
->
dtd
.
reg
[
1
]);
#endif
#ifndef CONFIG_SPL_BUILD
...
...
drivers/core/regmap.c
浏览文件 @
08cebeea
...
...
@@ -40,7 +40,7 @@ static struct regmap *regmap_alloc_count(int count)
}
#if CONFIG_IS_ENABLED(OF_PLATDATA)
int
regmap_init_mem_platdata
(
struct
udevice
*
dev
,
u32
*
reg
,
int
count
,
int
regmap_init_mem_platdata
(
struct
udevice
*
dev
,
fdt_val_t
*
reg
,
int
count
,
struct
regmap
**
mapp
)
{
struct
regmap_range
*
range
;
...
...
include/clk.h
浏览文件 @
08cebeea
...
...
@@ -61,9 +61,9 @@ struct clk {
};
#if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(CLK)
struct
phandle_
2_cell
;
struct
phandle_
1_arg
;
int
clk_get_by_index_platdata
(
struct
udevice
*
dev
,
int
index
,
struct
phandle_
2_cell
*
cells
,
struct
clk
*
clk
);
struct
phandle_
1_arg
*
cells
,
struct
clk
*
clk
);
/**
* clock_get_by_index - Get/request a clock by integer index.
...
...
include/dt-structs.h
浏览文件 @
08cebeea
...
...
@@ -9,11 +9,21 @@
/* These structures may only be used in SPL */
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct
phandle_
2_cell
{
struct
phandle_
0_arg
{
const
void
*
node
;
int
id
;
int
arg
[
0
]
;
};
#include <generated/dt-structs.h>
struct
phandle_1_arg
{
const
void
*
node
;
int
arg
[
1
];
};
struct
phandle_2_arg
{
const
void
*
node
;
int
arg
[
2
];
};
#include <generated/dt-structs-gen.h>
#endif
#endif
include/fdt_support.h
浏览文件 @
08cebeea
...
...
@@ -264,6 +264,8 @@ int arch_fixup_memory_node(void *blob);
int
fdt_setup_simplefb_node
(
void
*
fdt
,
int
node
,
u64
base_address
,
u32
width
,
u32
height
,
u32
stride
,
const
char
*
format
);
int
fdt_overlay_apply_verbose
(
void
*
fdt
,
void
*
fdto
);
#endif
/* ifdef CONFIG_OF_LIBFDT */
#ifdef USE_HOSTCC
...
...
include/fdtdec.h
浏览文件 @
08cebeea
...
...
@@ -27,10 +27,12 @@ typedef phys_size_t fdt_size_t;
#define FDT_ADDR_T_NONE (-1ULL)
#define fdt_addr_to_cpu(reg) be64_to_cpu(reg)
#define fdt_size_to_cpu(reg) be64_to_cpu(reg)
typedef
fdt64_t
fdt_val_t
;
#else
#define FDT_ADDR_T_NONE (-1U)
#define fdt_addr_to_cpu(reg) be32_to_cpu(reg)
#define fdt_size_to_cpu(reg) be32_to_cpu(reg)
typedef
fdt32_t
fdt_val_t
;
#endif
/* Information obtained about memory from the FDT */
...
...
include/image.h
浏览文件 @
08cebeea
...
...
@@ -593,6 +593,31 @@ int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
int
boot_get_setup_fit
(
bootm_headers_t
*
images
,
uint8_t
arch
,
ulong
*
setup_start
,
ulong
*
setup_len
);
/**
* boot_get_fdt_fit() - load a DTB from a FIT file (applying overlays)
*
* This deals with all aspects of loading an DTB from a FIT.
* The correct base image based on configuration will be selected, and
* then any overlays specified will be applied (as present in fit_uname_configp).
*
* @param images Boot images structure
* @param addr Address of FIT in memory
* @param fit_unamep On entry this is the requested image name
* (e.g. "kernel@1") or NULL to use the default. On exit
* points to the selected image name
* @param fit_uname_configp On entry this is the requested configuration
* name (e.g. "conf@1") or NULL to use the default. On
* exit points to the selected configuration name.
* @param arch Expected architecture (IH_ARCH_...)
* @param datap Returns address of loaded image
* @param lenp Returns length of loaded image
*
* @return node offset of base image, or -ve error code on error
*/
int
boot_get_fdt_fit
(
bootm_headers_t
*
images
,
ulong
addr
,
const
char
**
fit_unamep
,
const
char
**
fit_uname_configp
,
int
arch
,
ulong
*
datap
,
ulong
*
lenp
);
/**
* fit_image_load() - load an image from a FIT
*
...
...
include/regmap.h
浏览文件 @
08cebeea
...
...
@@ -69,7 +69,7 @@ int regmap_init_mem(struct udevice *dev, struct regmap **mapp);
* @count: Number of pairs (e.g. 1 if the regmap has a single entry)
* @mapp: Returns allocated map
*/
int
regmap_init_mem_platdata
(
struct
udevice
*
dev
,
u32
*
reg
,
int
count
,
int
regmap_init_mem_platdata
(
struct
udevice
*
dev
,
fdt_val_t
*
reg
,
int
count
,
struct
regmap
**
mapp
);
/**
...
...
include/syscon.h
浏览文件 @
08cebeea
...
...
@@ -8,6 +8,8 @@
#ifndef __SYSCON_H
#define __SYSCON_H
#include <fdtdec.h>
/**
* struct syscon_uc_info - Information stored by the syscon UCLASS_UCLASS
*
...
...
@@ -28,9 +30,11 @@ struct syscon_ops {
* We don't support 64-bit machines. If they are so resource-contrained that
* they need to use OF_PLATDATA, something is horribly wrong with the
* education of our hardware engineers.
*
* Update: 64-bit is now supported and we have an education crisis.
*/
struct
syscon_base_platdata
{
u32
reg
[
2
];
fdt_val_t
reg
[
2
];
};
#endif
...
...
lib/libfdt/fdt_overlay.c
浏览文件 @
08cebeea
...
...
@@ -39,6 +39,7 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
* @fdt: Base device tree blob
* @fdto: Device tree overlay blob
* @fragment: node offset of the fragment in the overlay
* @pathp: pointer which receives the path of the target (or NULL)
*
* overlay_get_target() retrieves the target offset in the base
* device tree of a fragment, no matter how the actual targetting is
...
...
@@ -49,37 +50,47 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
* Negative error code on error
*/
static
int
overlay_get_target
(
const
void
*
fdt
,
const
void
*
fdto
,
int
fragment
)
int
fragment
,
char
const
**
pathp
)
{
uint32_t
phandle
;
const
char
*
path
;
int
path_len
;
const
char
*
path
=
NULL
;
int
path_len
=
0
,
ret
;
/* Try first to do a phandle based lookup */
phandle
=
overlay_get_target_phandle
(
fdto
,
fragment
);
if
(
phandle
==
(
uint32_t
)
-
1
)
return
-
FDT_ERR_BADPHANDLE
;
if
(
phandle
)
return
fdt_node_offset_by_phandle
(
fdt
,
phandle
);
/* no phandle, try path */
if
(
!
phandle
)
{
/* And then a path based lookup */
path
=
fdt_getprop
(
fdto
,
fragment
,
"target-path"
,
&
path_len
);
if
(
path
)
ret
=
fdt_path_offset
(
fdt
,
path
);
else
ret
=
path_len
;
}
else
ret
=
fdt_node_offset_by_phandle
(
fdt
,
phandle
);
/* And then a path based lookup */
path
=
fdt_getprop
(
fdto
,
fragment
,
"target-path"
,
&
path_len
);
if
(
!
path
)
{
/*
* If we haven't found either a target or a
* target-path property in a node that contains a
* __overlay__ subnode (we wouldn't be called
* otherwise), consider it a improperly written
* overlay
*/
if
(
path_len
==
-
FDT_ERR_NOTFOUND
)
return
-
FDT_ERR_BADOVERLAY
;
/*
* If we haven't found either a target or a
* target-path property in a node that contains a
* __overlay__ subnode (we wouldn't be called
* otherwise), consider it a improperly written
* overlay
*/
if
(
ret
<
0
&&
path_len
==
-
FDT_ERR_NOTFOUND
)
ret
=
-
FDT_ERR_BADOVERLAY
;
/* return on error */
if
(
ret
<
0
)
return
ret
;
return
path_len
;
}
/* return pointer to path (if available) */
if
(
pathp
)
*
pathp
=
path
?
path
:
NULL
;
return
fdt_path_offset
(
fdt
,
path
)
;
return
ret
;
}
/**
...
...
@@ -590,7 +601,7 @@ static int overlay_apply_node(void *fdt, int target,
*
* overlay_merge() merges an overlay into its base device tree.
*
* This is the
final
step in the device tree overlay application
* This is the
next to last
step in the device tree overlay application
* process, when all the phandles have been adjusted and resolved and
* you just have to merge overlay into the base device tree.
*
...
...
@@ -618,7 +629,7 @@ static int overlay_merge(void *fdt, void *fdto)
if
(
overlay
<
0
)
return
overlay
;
target
=
overlay_get_target
(
fdt
,
fdto
,
fragment
);
target
=
overlay_get_target
(
fdt
,
fdto
,
fragment
,
NULL
);
if
(
target
<
0
)
return
target
;
...
...
@@ -630,6 +641,175 @@ static int overlay_merge(void *fdt, void *fdto)
return
0
;
}
static
int
get_path_len
(
const
void
*
fdt
,
int
nodeoffset
)
{
int
len
=
0
,
namelen
;
const
char
*
name
;
FDT_CHECK_HEADER
(
fdt
);
for
(;;)
{
name
=
fdt_get_name
(
fdt
,
nodeoffset
,
&
namelen
);
if
(
!
name
)
return
namelen
;
/* root? we're done */
if
(
namelen
==
0
)
break
;
nodeoffset
=
fdt_parent_offset
(
fdt
,
nodeoffset
);
if
(
nodeoffset
<
0
)
return
nodeoffset
;
len
+=
namelen
+
1
;
}
/* in case of root pretend it's "/" */
if
(
len
==
0
)
len
++
;
return
len
;
}
/**
* overlay_symbol_update - Update the symbols of base tree after a merge
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
*
* overlay_symbol_update() updates the symbols of the base tree with the
* symbols of the applied overlay
*
* This is the last step in the device tree overlay application
* process, allowing the reference of overlay symbols by subsequent
* overlay operations.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_symbol_update
(
void
*
fdt
,
void
*
fdto
)
{
int
root_sym
,
ov_sym
,
prop
,
path_len
,
fragment
,
target
;
int
len
,
frag_name_len
,
ret
,
rel_path_len
;
const
char
*
s
,
*
e
;
const
char
*
path
;
const
char
*
name
;
const
char
*
frag_name
;
const
char
*
rel_path
;
const
char
*
target_path
;
char
*
buf
;
void
*
p
;
ov_sym
=
fdt_subnode_offset
(
fdto
,
0
,
"__symbols__"
);
/* if no overlay symbols exist no problem */
if
(
ov_sym
<
0
)
return
0
;
root_sym
=
fdt_subnode_offset
(
fdt
,
0
,
"__symbols__"
);
/* it no root symbols exist we should create them */
if
(
root_sym
==
-
FDT_ERR_NOTFOUND
)
root_sym
=
fdt_add_subnode
(
fdt
,
0
,
"__symbols__"
);
/* any error is fatal now */
if
(
root_sym
<
0
)
return
root_sym
;
/* iterate over each overlay symbol */
fdt_for_each_property_offset
(
prop
,
fdto
,
ov_sym
)
{
path
=
fdt_getprop_by_offset
(
fdto
,
prop
,
&
name
,
&
path_len
);
if
(
!
path
)
return
path_len
;
/* verify it's a string property (terminated by a single \0) */
if
(
path_len
<
1
||
memchr
(
path
,
'\0'
,
path_len
)
!=
&
path
[
path_len
-
1
])
return
-
FDT_ERR_BADVALUE
;
/* keep end marker to avoid strlen() */
e
=
path
+
path_len
;
/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
if
(
*
path
!=
'/'
)
return
-
FDT_ERR_BADVALUE
;
/* get fragment name first */
s
=
strchr
(
path
+
1
,
'/'
);
if
(
!
s
)
return
-
FDT_ERR_BADOVERLAY
;
frag_name
=
path
+
1
;
frag_name_len
=
s
-
path
-
1
;
/* verify format; safe since "s" lies in \0 terminated prop */
len
=
sizeof
(
"/__overlay__/"
)
-
1
;
if
((
e
-
s
)
<
len
||
memcmp
(
s
,
"/__overlay__/"
,
len
))
return
-
FDT_ERR_BADOVERLAY
;
rel_path
=
s
+
len
;
rel_path_len
=
e
-
rel_path
;
/* find the fragment index in which the symbol lies */
ret
=
fdt_subnode_offset_namelen
(
fdto
,
0
,
frag_name
,
frag_name_len
);
/* not found? */
if
(
ret
<
0
)
return
-
FDT_ERR_BADOVERLAY
;
fragment
=
ret
;
/* an __overlay__ subnode must exist */
ret
=
fdt_subnode_offset
(
fdto
,
fragment
,
"__overlay__"
);
if
(
ret
<
0
)
return
-
FDT_ERR_BADOVERLAY
;
/* get the target of the fragment */
ret
=
overlay_get_target
(
fdt
,
fdto
,
fragment
,
&
target_path
);
if
(
ret
<
0
)
return
ret
;
target
=
ret
;
/* if we have a target path use */
if
(
!
target_path
)
{
ret
=
get_path_len
(
fdt
,
target
);
if
(
ret
<
0
)
return
ret
;
len
=
ret
;
}
else
{
len
=
strlen
(
target_path
);
}
ret
=
fdt_setprop_placeholder
(
fdt
,
root_sym
,
name
,
len
+
(
len
>
1
)
+
rel_path_len
+
1
,
&
p
);
if
(
ret
<
0
)
return
ret
;
if
(
!
target_path
)
{
/* again in case setprop_placeholder changed it */
ret
=
overlay_get_target
(
fdt
,
fdto
,
fragment
,
&
target_path
);
if
(
ret
<
0
)
return
ret
;
target
=
ret
;
}
buf
=
p
;
if
(
len
>
1
)
{
/* target is not root */
if
(
!
target_path
)
{
ret
=
fdt_get_path
(
fdt
,
target
,
buf
,
len
+
1
);
if
(
ret
<
0
)
return
ret
;
}
else
memcpy
(
buf
,
target_path
,
len
+
1
);
}
else
len
--
;
buf
[
len
]
=
'/'
;
memcpy
(
buf
+
len
+
1
,
rel_path
,
rel_path_len
);
buf
[
len
+
1
+
rel_path_len
]
=
'\0'
;
}
return
0
;
}
int
fdt_overlay_apply
(
void
*
fdt
,
void
*
fdto
)
{
uint32_t
delta
=
fdt_get_max_phandle
(
fdt
);
...
...
@@ -654,6 +834,10 @@ int fdt_overlay_apply(void *fdt, void *fdto)
if
(
ret
)
goto
err
;
ret
=
overlay_symbol_update
(
fdt
,
fdto
);
if
(
ret
)
goto
err
;
/*
* The overlay has been damaged, erase its magic.
*/
...
...
lib/libfdt/fdt_rw.c
浏览文件 @
08cebeea
...
...
@@ -228,8 +228,8 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
return
0
;
}
int
fdt_setprop
(
void
*
fdt
,
int
nodeoffset
,
const
char
*
name
,
const
void
*
val
,
int
len
)
int
fdt_setprop
_placeholder
(
void
*
fdt
,
int
nodeoffset
,
const
char
*
name
,
int
len
,
void
**
prop_data
)
{
struct
fdt_property
*
prop
;
int
err
;
...
...
@@ -242,8 +242,22 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
if
(
err
)
return
err
;
*
prop_data
=
prop
->
data
;
return
0
;
}
int
fdt_setprop
(
void
*
fdt
,
int
nodeoffset
,
const
char
*
name
,
const
void
*
val
,
int
len
)
{
void
*
prop_data
;
int
err
;
err
=
fdt_setprop_placeholder
(
fdt
,
nodeoffset
,
name
,
len
,
&
prop_data
);
if
(
err
)
return
err
;
if
(
len
)
memcpy
(
prop
->
data
,
val
,
len
);
memcpy
(
prop
_
data
,
val
,
len
);
return
0
;
}
...
...
lib/libfdt/fdt_wip.c
浏览文件 @
08cebeea
...
...
@@ -115,7 +115,7 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
struct
fdt_region
region
[],
int
max_regions
,
char
*
path
,
int
path_len
,
int
add_string_tab
)
{
int
stack
[
FDT_MAX_DEPTH
];
int
stack
[
FDT_MAX_DEPTH
]
=
{
0
}
;
char
*
end
;
int
nextoffset
=
0
;
uint32_t
tag
;
...
...
lib/libfdt/libfdt.h
浏览文件 @
08cebeea
...
...
@@ -1404,6 +1404,37 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name);
int
fdt_setprop
(
void
*
fdt
,
int
nodeoffset
,
const
char
*
name
,
const
void
*
val
,
int
len
);
/**
* fdt_setprop _placeholder - allocate space for 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
* @len: length of the property value
* @prop_data: return pointer to property data
*
* fdt_setprop_placeholer() allocates the named property in the given node.
* If the property exists it is resized. In either case a pointer to the
* property data is returned.
*
* 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_placeholder
(
void
*
fdt
,
int
nodeoffset
,
const
char
*
name
,
int
len
,
void
**
prop_data
);
/**
* fdt_setprop_u32 - set a property to a 32-bit integer
* @fdt: pointer to the device tree blob
...
...
lib/libfdt/pylibfdt/libfdt.i
浏览文件 @
08cebeea
...
...
@@ -130,6 +130,23 @@ class Fdt:
self
.
_fdt
=
bytearray
(
data
)
check_err
(
fdt_check_header
(
self
.
_fdt
))
;
def
subnode_offset
(
self
,
parentoffset
,
name
,
quiet
=
())
:
"""Get the offset of a named subnode
Args:
parentoffset: Offset of the parent node to check
name: Name of the required subnode, e.g. 'subnode@1'
quiet: Errors to ignore (empty to raise on all errors)
Returns:
The node offset of the found node, if any
Raises
FdtException if there is no node with that name, or other error
"""
return
check_err
(
fdt_subnode_offset
(
self
.
_fdt
,
parentoffset
,
name
),
quiet
)
def
path_offset
(
self
,
path
,
quiet
=
())
:
"""Get the offset for a given path
...
...
@@ -304,6 +321,47 @@ class Fdt:
return
pdata
return
bytearray
(
pdata
[
0
])
def
get_phandle
(
self
,
nodeoffset
)
:
"""Get the phandle of a node
Args:
nodeoffset: Node offset to check
Returns:
phandle of node, or 0 if the node has no phandle or another error
occurs
"""
return
fdt_get_phandle
(
self
.
_fdt
,
nodeoffset
)
def
parent_offset
(
self
,
nodeoffset
,
quiet
=
())
:
"""Get the offset of a node's parent
Args:
nodeoffset: Node offset to check
quiet: Errors to ignore (empty to raise on all errors)
Returns:
The offset of the parent node, if any
Raises:
FdtException if no parent found or other error occurs
"""
return
check_err
(
fdt_parent_offset
(
self
.
_fdt
,
nodeoffset
),
quiet
)
def
node_offset_by_phandle
(
self
,
phandle
,
quiet
=
())
:
"""Get the offset of a node with the given phandle
Args:
phandle: Phandle to search for
quiet: Errors to ignore (empty to raise on all errors)
Returns:
The offset of node with that phandle, if any
Raises:
FdtException if no node found or other error occurs
"""
return
check_err
(
fdt_node_offset_by_phandle
(
self
.
_fdt
,
phandle
),
quiet
)
class
Property
:
"""Holds a device tree property name and value.
...
...
scripts/Makefile.lib
浏览文件 @
08cebeea
...
...
@@ -321,6 +321,23 @@ $(obj)/%.dtb: $(src)/%.dts FORCE
dtc-tmp
=
$(
subst
$(comma)
,_,
$
(
dot-target
)
.dts.tmp
)
# DTCO
# ---------------------------------------------------------------------------
quiet_cmd_dtco
=
DTCO
$@
# Rule for objects only; does not put specific u-boot include at the end
# No generation of assembly file either
# Modified for U-Boot
cmd_dtco
=
mkdir
-p
$(
dir
${
dtc
-tmp
}
) ; \
$(CPP)
$(dtc_cpp_flags)
-x assembler-with-cpp -o
$
(dtc-tmp) - ; \
$(DTC)
-@ -O dtb -o
$@
-b 0 \
-i
$(
dir
$<
)
$(DTC_FLAGS)
\
-d
$(depfile)
.dtc.tmp
$
(dtc-tmp) ; \
cat
$(depfile)
.pre.tmp
$(depfile)
.dtc.tmp >
$(depfile)
$(obj)/%.dtbo
:
$(src)/%.dts FORCE
$(
call
if_changed_dep
,dtco
)
# Fonts
# ---------------------------------------------------------------------------
...
...
scripts/Makefile.spl
浏览文件 @
08cebeea
...
...
@@ -257,14 +257,15 @@ cmd_dtoch = $(pythonpath) $(srctree)/tools/dtoc/dtoc -d $(obj)/$(SPL_BIN).dtb -o
quiet_cmd_plat
=
PLAT
$@
cmd_plat
=
$(CC)
$(c_flags)
-c
$<
-o
$@
$(obj)/dts/dt-platdata.o
:
$(obj)/dts/dt-platdata.c include/generated/dt-structs.h
$(obj)/dts/dt-platdata.o
:
$(obj)/dts/dt-platdata.c
\
include/generated/dt-structs-gen.h
$(
call
if_changed,plat
)
PHONY
+=
dts_dir
dts_dir
:
$(
shell
[
-d
$(obj)
/dts
]
||
mkdir
-p
$(obj)
/dts
)
include/generated/dt-structs.h
:
$(obj)/$(SPL_BIN).dtb dts_dir checkdtoc
include/generated/dt-structs
-gen
.h
:
$(obj)/$(SPL_BIN).dtb dts_dir checkdtoc
$(
call
if_changed,dtoch
)
$(obj)/dts/dt-platdata.c
:
$(obj)/$(SPL_BIN).dtb dts_dir checkdtoc
...
...
test/overlay/Makefile
浏览文件 @
08cebeea
...
...
@@ -13,3 +13,4 @@ DTC_FLAGS += -@
# DT overlays
obj-y
+=
test-fdt-base.dtb.o
obj-y
+=
test-fdt-overlay.dtb.o
obj-y
+=
test-fdt-overlay-stacked.dtb.o
test/overlay/cmd_ut_overlay.c
浏览文件 @
08cebeea
...
...
@@ -20,8 +20,9 @@
extern
u32
__dtb_test_fdt_base_begin
;
extern
u32
__dtb_test_fdt_overlay_begin
;
extern
u32
__dtb_test_fdt_overlay_stacked_begin
;
static
int
fdt_getprop_u32_by_index
(
void
*
fdt
,
const
char
*
path
,
static
int
ut_
fdt_getprop_u32_by_index
(
void
*
fdt
,
const
char
*
path
,
const
char
*
name
,
int
index
,
u32
*
out
)
{
...
...
@@ -42,10 +43,10 @@ static int fdt_getprop_u32_by_index(void *fdt, const char *path,
return
0
;
}
static
int
fdt_getprop_u32
(
void
*
fdt
,
const
char
*
path
,
const
char
*
name
,
static
int
ut_
fdt_getprop_u32
(
void
*
fdt
,
const
char
*
path
,
const
char
*
name
,
u32
*
out
)
{
return
fdt_getprop_u32_by_index
(
fdt
,
path
,
name
,
0
,
out
);
return
ut_
fdt_getprop_u32_by_index
(
fdt
,
path
,
name
,
0
,
out
);
}
static
int
fdt_getprop_str
(
void
*
fdt
,
const
char
*
path
,
const
char
*
name
,
...
...
@@ -68,7 +69,7 @@ static int fdt_overlay_change_int_property(struct unit_test_state *uts)
void
*
fdt
=
uts
->
priv
;
u32
val
=
0
;
ut_assertok
(
fdt_getprop_u32
(
fdt
,
"/test-node"
,
"test-int-property"
,
ut_assertok
(
ut_
fdt_getprop_u32
(
fdt
,
"/test-node"
,
"test-int-property"
,
&
val
));
ut_asserteq
(
43
,
val
);
...
...
@@ -158,11 +159,11 @@ static int fdt_overlay_local_phandle(struct unit_test_state *uts)
local_phandle
=
fdt_get_phandle
(
fdt
,
off
);
ut_assert
(
local_phandle
);
ut_assertok
(
fdt_getprop_u32_by_index
(
fdt
,
"/"
,
"test-several-phandle"
,
ut_assertok
(
ut_
fdt_getprop_u32_by_index
(
fdt
,
"/"
,
"test-several-phandle"
,
0
,
&
val
));
ut_asserteq
(
local_phandle
,
val
);
ut_assertok
(
fdt_getprop_u32_by_index
(
fdt
,
"/"
,
"test-several-phandle"
,
ut_assertok
(
ut_
fdt_getprop_u32_by_index
(
fdt
,
"/"
,
"test-several-phandle"
,
1
,
&
val
));
ut_asserteq
(
local_phandle
,
val
);
...
...
@@ -189,11 +190,11 @@ static int fdt_overlay_local_phandles(struct unit_test_state *uts)
test_phandle
=
fdt_get_phandle
(
fdt
,
off
);
ut_assert
(
test_phandle
);
ut_assertok
(
fdt_getprop_u32_by_index
(
fdt
,
"/"
,
"test-phandle"
,
0
,
ut_assertok
(
ut_
fdt_getprop_u32_by_index
(
fdt
,
"/"
,
"test-phandle"
,
0
,
&
val
));
ut_asserteq
(
test_phandle
,
val
);
ut_assertok
(
fdt_getprop_u32_by_index
(
fdt
,
"/"
,
"test-phandle"
,
1
,
ut_assertok
(
ut_
fdt_getprop_u32_by_index
(
fdt
,
"/"
,
"test-phandle"
,
1
,
&
val
));
ut_asserteq
(
local_phandle
,
val
);
...
...
@@ -201,6 +202,19 @@ static int fdt_overlay_local_phandles(struct unit_test_state *uts)
}
OVERLAY_TEST
(
fdt_overlay_local_phandles
,
0
);
static
int
fdt_overlay_stacked
(
struct
unit_test_state
*
uts
)
{
void
*
fdt
=
uts
->
priv
;
u32
val
=
0
;
ut_assertok
(
ut_fdt_getprop_u32
(
fdt
,
"/new-local-node"
,
"stacked-test-int-property"
,
&
val
));
ut_asserteq
(
43
,
val
);
return
CMD_RET_SUCCESS
;
}
OVERLAY_TEST
(
fdt_overlay_stacked
,
0
);
int
do_ut_overlay
(
cmd_tbl_t
*
cmdtp
,
int
flag
,
int
argc
,
char
*
const
argv
[])
{
struct
unit_test
*
tests
=
ll_entry_start
(
struct
unit_test
,
...
...
@@ -210,7 +224,8 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
struct
unit_test
*
test
;
void
*
fdt_base
=
&
__dtb_test_fdt_base_begin
;
void
*
fdt_overlay
=
&
__dtb_test_fdt_overlay_begin
;
void
*
fdt_base_copy
,
*
fdt_overlay_copy
;
void
*
fdt_overlay_stacked
=
&
__dtb_test_fdt_overlay_stacked_begin
;
void
*
fdt_base_copy
,
*
fdt_overlay_copy
,
*
fdt_overlay_stacked_copy
;
uts
=
calloc
(
1
,
sizeof
(
*
uts
));
if
(
!
uts
)
...
...
@@ -228,6 +243,10 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if
(
!
fdt_overlay_copy
)
return
-
ENOMEM
;
fdt_overlay_stacked_copy
=
malloc
(
FDT_COPY_SIZE
);
if
(
!
fdt_overlay_stacked_copy
)
return
-
ENOMEM
;
/*
* Resize the FDT to 4k so that we have room to operate on
*
...
...
@@ -245,9 +264,21 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
ut_assertok
(
fdt_open_into
(
fdt_overlay
,
fdt_overlay_copy
,
FDT_COPY_SIZE
));
/*
* Resize the stacked overlay to 4k so that we have room to operate on
*
* (and relocate it since the memory might be mapped
* read-only)
*/
ut_assertok
(
fdt_open_into
(
fdt_overlay_stacked
,
fdt_overlay_stacked_copy
,
FDT_COPY_SIZE
));
/* Apply the overlay */
ut_assertok
(
fdt_overlay_apply
(
fdt_base_copy
,
fdt_overlay_copy
));
/* Apply the stacked overlay */
ut_assertok
(
fdt_overlay_apply
(
fdt_base_copy
,
fdt_overlay_stacked_copy
));
if
(
argc
==
1
)
printf
(
"Running %d environment tests
\n
"
,
n_ents
);
...
...
@@ -263,6 +294,7 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf
(
"Failures: %d
\n
"
,
uts
->
fail_count
);
free
(
fdt_overlay_stacked_copy
);
free
(
fdt_overlay_copy
);
free
(
fdt_base_copy
);
free
(
uts
);
...
...
test/overlay/test-fdt-overlay-stacked.dts
0 → 100644
浏览文件 @
08cebeea
/*
* Copyright (c) 2016 NextThing Co
* Copyright (c) 2016 Free Electrons
* Copyright (c) 2018 Konsulko Group
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/plugin/;
/ {
/* Test that we can reference an overlay symbol */
fragment@0 {
target = <&local>;
__overlay__ {
stacked-test-int-property = <43>;
};
};
};
tools/dtoc/dtb_platdata.py
浏览文件 @
08cebeea
...
...
@@ -12,6 +12,7 @@ This supports converting device tree data to C structures definitions and
static data.
"""
import
collections
import
copy
import
sys
...
...
@@ -38,11 +39,20 @@ TYPE_NAMES = {
fdt
.
TYPE_BYTE
:
'unsigned char'
,
fdt
.
TYPE_STRING
:
'const char *'
,
fdt
.
TYPE_BOOL
:
'bool'
,
fdt
.
TYPE_INT64
:
'fdt64_t'
,
}
STRUCT_PREFIX
=
'dtd_'
VAL_PREFIX
=
'dtv_'
# This holds information about a property which includes phandles.
#
# max_args: integer: Maximum number or arguments that any phandle uses (int).
# args: Number of args for each phandle in the property. The total number of
# phandles is len(args). This is a list of integers.
PhandleInfo
=
collections
.
namedtuple
(
'PhandleInfo'
,
[
'max_args'
,
'args'
])
def
conv_name_to_c
(
name
):
"""Convert a device-tree name to a C identifier
...
...
@@ -95,6 +105,8 @@ def get_value(ftype, value):
return
'"%s"'
%
value
elif
ftype
==
fdt
.
TYPE_BOOL
:
return
'true'
elif
ftype
==
fdt
.
TYPE_INT64
:
return
'%#x'
%
value
def
get_compat_name
(
node
):
"""Get a node's first compatible string as a C identifier
...
...
@@ -113,21 +125,6 @@ def get_compat_name(node):
compat
,
aliases
=
compat
[
0
],
compat
[
1
:]
return
conv_name_to_c
(
compat
),
[
conv_name_to_c
(
a
)
for
a
in
aliases
]
def
is_phandle
(
prop
):
"""Check if a node contains phandles
We have no reliable way of detecting whether a node uses a phandle
or not. As an interim measure, use a list of known property names.
Args:
prop: Prop object to check
Return:
True if the object value contains phandles, else False
"""
if
prop
.
name
in
[
'clocks'
]:
return
True
return
False
class
DtbPlatdata
(
object
):
"""Provide a means to convert device tree binary data to platform data
...
...
@@ -141,17 +138,14 @@ class DtbPlatdata(object):
_dtb_fname: Filename of the input device tree binary file
_valid_nodes: A list of Node object with compatible strings
_include_disabled: true to include nodes marked status = "disabled"
_phandle_nodes: A dict of nodes indexed by phandle number (1, 2...)
_outfile: The current output file (sys.stdout or a real file)
_lines: Stashed list of output lines for outputting in the future
_phandle_nodes: A dict of Nodes indexed by phandle (an integer)
"""
def
__init__
(
self
,
dtb_fname
,
include_disabled
):
self
.
_fdt
=
None
self
.
_dtb_fname
=
dtb_fname
self
.
_valid_nodes
=
None
self
.
_include_disabled
=
include_disabled
self
.
_phandle_nodes
=
{}
self
.
_outfile
=
None
self
.
_lines
=
[]
self
.
_aliases
=
{}
...
...
@@ -196,6 +190,53 @@ class DtbPlatdata(object):
self
.
_lines
=
[]
return
lines
def
out_header
(
self
):
"""Output a message indicating that this is an auto-generated file"""
self
.
out
(
'''/*
* DO NOT MODIFY
*
* This file was generated by dtoc from a .dtb (device tree binary) file.
*/
'''
)
def
get_phandle_argc
(
self
,
prop
,
node_name
):
"""Check if a node contains phandles
We have no reliable way of detecting whether a node uses a phandle
or not. As an interim measure, use a list of known property names.
Args:
prop: Prop object to check
Return:
Number of argument cells is this is a phandle, else None
"""
if
prop
.
name
in
[
'clocks'
]:
val
=
prop
.
value
if
not
isinstance
(
val
,
list
):
val
=
[
val
]
i
=
0
max_args
=
0
args
=
[]
while
i
<
len
(
val
):
phandle
=
fdt_util
.
fdt32_to_cpu
(
val
[
i
])
target
=
self
.
_fdt
.
phandle_to_node
.
get
(
phandle
)
if
not
target
:
raise
ValueError
(
"Cannot parse '%s' in node '%s'"
%
(
prop
.
name
,
node_name
))
prop_name
=
'#clock-cells'
cells
=
target
.
props
.
get
(
prop_name
)
if
not
cells
:
raise
ValueError
(
"Node '%s' has no '%s' property"
%
(
target
.
name
,
prop_name
))
num_args
=
fdt_util
.
fdt32_to_cpu
(
cells
.
value
)
max_args
=
max
(
max_args
,
num_args
)
args
.
append
(
num_args
)
i
+=
1
+
num_args
return
PhandleInfo
(
max_args
,
args
)
return
None
def
scan_dtb
(
self
):
"""Scan the device tree to obtain a tree of nodes and properties
...
...
@@ -207,8 +248,7 @@ class DtbPlatdata(object):
def
scan_node
(
self
,
root
):
"""Scan a node and subnodes to build a tree of node and phandle info
This adds each node to self._valid_nodes and each phandle to
self._phandle_nodes.
This adds each node to self._valid_nodes.
Args:
root: Root node for scan
...
...
@@ -219,10 +259,6 @@ class DtbPlatdata(object):
if
(
not
self
.
_include_disabled
and
not
status
or
status
.
value
!=
'disabled'
):
self
.
_valid_nodes
.
append
(
node
)
phandle_prop
=
node
.
props
.
get
(
'phandle'
)
if
phandle_prop
:
phandle
=
phandle_prop
.
GetPhandle
()
self
.
_phandle_nodes
[
phandle
]
=
node
# recurse to handle any subnodes
self
.
scan_node
(
node
)
...
...
@@ -231,14 +267,72 @@ class DtbPlatdata(object):
"""Scan the device tree for useful information
This fills in the following properties:
_phandle_nodes: A dict of Nodes indexed by phandle (an integer)
_valid_nodes: A list of nodes we wish to consider include in the
platform data
"""
self
.
_phandle_nodes
=
{}
self
.
_valid_nodes
=
[]
return
self
.
scan_node
(
self
.
_fdt
.
GetRoot
())
@
staticmethod
def
get_num_cells
(
node
):
"""Get the number of cells in addresses and sizes for this node
Args:
node: Node to check
Returns:
Tuple:
Number of address cells for this node
Number of size cells for this node
"""
parent
=
node
.
parent
na
,
ns
=
2
,
2
if
parent
:
na_prop
=
parent
.
props
.
get
(
'#address-cells'
)
ns_prop
=
parent
.
props
.
get
(
'#size-cells'
)
if
na_prop
:
na
=
fdt_util
.
fdt32_to_cpu
(
na_prop
.
value
)
if
ns_prop
:
ns
=
fdt_util
.
fdt32_to_cpu
(
ns_prop
.
value
)
return
na
,
ns
def
scan_reg_sizes
(
self
):
"""Scan for 64-bit 'reg' properties and update the values
This finds 'reg' properties with 64-bit data and converts the value to
an array of 64-values. This allows it to be output in a way that the
C code can read.
"""
for
node
in
self
.
_valid_nodes
:
reg
=
node
.
props
.
get
(
'reg'
)
if
not
reg
:
continue
na
,
ns
=
self
.
get_num_cells
(
node
)
total
=
na
+
ns
if
reg
.
type
!=
fdt
.
TYPE_INT
:
raise
ValueError
(
"Node '%s' reg property is not an int"
)
if
len
(
reg
.
value
)
%
total
:
raise
ValueError
(
"Node '%s' reg property has %d cells "
'which is not a multiple of na + ns = %d + %d)'
%
(
node
.
name
,
len
(
reg
.
value
),
na
,
ns
))
reg
.
na
=
na
reg
.
ns
=
ns
if
na
!=
1
or
ns
!=
1
:
reg
.
type
=
fdt
.
TYPE_INT64
i
=
0
new_value
=
[]
val
=
reg
.
value
if
not
isinstance
(
val
,
list
):
val
=
[
val
]
while
i
<
len
(
val
):
addr
=
fdt_util
.
fdt_cells_to_cpu
(
val
[
i
:],
reg
.
na
)
i
+=
na
size
=
fdt_util
.
fdt_cells_to_cpu
(
val
[
i
:],
reg
.
ns
)
i
+=
ns
new_value
+=
[
addr
,
size
]
reg
.
value
=
new_value
def
scan_structs
(
self
):
"""Scan the device tree building up the C structures we will use.
...
...
@@ -305,14 +399,18 @@ class DtbPlatdata(object):
for
pname
,
prop
in
node
.
props
.
items
():
if
pname
in
PROP_IGNORE_LIST
or
pname
[
0
]
==
'#'
:
continue
if
isinstance
(
prop
.
value
,
list
):
if
is_phandle
(
prop
):
# Process the list as pairs of (phandle, id)
value_it
=
iter
(
prop
.
value
)
for
phandle_cell
,
_
in
zip
(
value_it
,
value_it
):
phandle
=
fdt_util
.
fdt32_to_cpu
(
phandle_cell
)
target_node
=
self
.
_phandle_nodes
[
phandle
]
node
.
phandles
.
add
(
target_node
)
info
=
self
.
get_phandle_argc
(
prop
,
node
.
name
)
if
info
:
if
not
isinstance
(
prop
.
value
,
list
):
prop
.
value
=
[
prop
.
value
]
# Process the list as pairs of (phandle, id)
pos
=
0
for
args
in
info
.
args
:
phandle_cell
=
prop
.
value
[
pos
]
phandle
=
fdt_util
.
fdt32_to_cpu
(
phandle_cell
)
target_node
=
self
.
_fdt
.
phandle_to_node
[
phandle
]
node
.
phandles
.
add
(
target_node
)
pos
+=
1
+
args
def
generate_structs
(
self
,
structs
):
...
...
@@ -322,6 +420,7 @@ class DtbPlatdata(object):
definitions for node in self._valid_nodes. See the documentation in
README.of-plat for more information.
"""
self
.
out_header
()
self
.
out
(
'#include <stdbool.h>
\n
'
)
self
.
out
(
'#include <libfdt.h>
\n
'
)
...
...
@@ -330,11 +429,13 @@ class DtbPlatdata(object):
self
.
out
(
'struct %s%s {
\n
'
%
(
STRUCT_PREFIX
,
name
))
for
pname
in
sorted
(
structs
[
name
]):
prop
=
structs
[
name
][
pname
]
if
is_phandle
(
prop
):
info
=
self
.
get_phandle_argc
(
prop
,
structs
[
name
])
if
info
:
# For phandles, include a reference to the target
self
.
out
(
'
\t
%s%s[%d]'
%
(
tab_to
(
2
,
'struct phandle_2_cell'
),
struct_name
=
'struct phandle_%d_arg'
%
info
.
max_args
self
.
out
(
'
\t
%s%s[%d]'
%
(
tab_to
(
2
,
struct_name
),
conv_name_to_c
(
prop
.
name
),
len
(
prop
.
value
)
/
2
))
len
(
info
.
args
)
))
else
:
ptype
=
TYPE_NAMES
[
prop
.
type
]
self
.
out
(
'
\t
%s%s'
%
(
tab_to
(
2
,
ptype
),
...
...
@@ -370,19 +471,32 @@ class DtbPlatdata(object):
vals
=
[]
# For phandles, output a reference to the platform data
# of the target node.
if
is_phandle
(
prop
):
info
=
self
.
get_phandle_argc
(
prop
,
node
.
name
)
if
info
:
# Process the list as pairs of (phandle, id)
value_it
=
iter
(
prop
.
value
)
for
phandle_cell
,
id_cell
in
zip
(
value_it
,
value_it
):
pos
=
0
for
args
in
info
.
args
:
phandle_cell
=
prop
.
value
[
pos
]
phandle
=
fdt_util
.
fdt32_to_cpu
(
phandle_cell
)
id_num
=
fdt_util
.
fdt32_to_cpu
(
id_cell
)
target_node
=
self
.
_phandle_nodes
[
phandle
]
target_node
=
self
.
_fdt
.
phandle_to_node
[
phandle
]
name
=
conv_name_to_c
(
target_node
.
name
)
vals
.
append
(
'{&%s%s, %d}'
%
(
VAL_PREFIX
,
name
,
id_num
))
arg_values
=
[]
for
i
in
range
(
args
):
arg_values
.
append
(
str
(
fdt_util
.
fdt32_to_cpu
(
prop
.
value
[
pos
+
1
+
i
])))
pos
+=
1
+
args
vals
.
append
(
'
\t
{&%s%s, {%s}}'
%
(
VAL_PREFIX
,
name
,
', '
.
join
(
arg_values
)))
for
val
in
vals
:
self
.
buf
(
'
\n\t\t
%s,'
%
val
)
else
:
for
val
in
prop
.
value
:
vals
.
append
(
get_value
(
prop
.
type
,
val
))
self
.
buf
(
', '
.
join
(
vals
))
# Put 8 values per line to avoid very long lines.
for
i
in
xrange
(
0
,
len
(
vals
),
8
):
if
i
:
self
.
buf
(
',
\n\t\t
'
)
self
.
buf
(
', '
.
join
(
vals
[
i
:
i
+
8
]))
self
.
buf
(
'}'
)
else
:
self
.
buf
(
get_value
(
prop
.
type
,
prop
.
value
))
...
...
@@ -409,6 +523,7 @@ class DtbPlatdata(object):
See the documentation in doc/driver-model/of-plat.txt for more
information.
"""
self
.
out_header
()
self
.
out
(
'#include <common.h>
\n
'
)
self
.
out
(
'#include <dm.h>
\n
'
)
self
.
out
(
'#include <dt-structs.h>
\n
'
)
...
...
@@ -442,6 +557,7 @@ def run_steps(args, dtb_file, include_disabled, output):
plat
=
DtbPlatdata
(
dtb_file
,
include_disabled
)
plat
.
scan_dtb
()
plat
.
scan_tree
()
plat
.
scan_reg_sizes
()
plat
.
setup_output
(
output
)
structs
=
plat
.
scan_structs
()
plat
.
scan_phandles
()
...
...
tools/dtoc/dtoc_test_addr32.dts
0 → 100644
浏览文件 @
08cebeea
/*
* Test device tree file for dtoc
*
* Copyright 2017 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
test1 {
u-boot,dm-pre-reloc;
compatible = "test1";
reg = <0x1234 0x5678>;
};
test2 {
u-boot,dm-pre-reloc;
compatible = "test2";
reg = <0x12345678 0x98765432 2 3>;
};
};
tools/dtoc/dtoc_test_addr32_64.dts
0 → 100644
浏览文件 @
08cebeea
/*
* Test device tree file for dtoc
*
* Copyright 2017 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <2>;
test1 {
u-boot,dm-pre-reloc;
compatible = "test1";
reg = <0x1234 0x5678 0x0>;
};
test2 {
u-boot,dm-pre-reloc;
compatible = "test2";
reg = <0x12345678 0x98765432 0x10987654>;
};
test3 {
u-boot,dm-pre-reloc;
compatible = "test3";
reg = <0x12345678 0x98765432 0x10987654 2 0 3>;
};
};
tools/dtoc/dtoc_test_addr64.dts
0 → 100644
浏览文件 @
08cebeea
/*
* Test device tree file for dtoc
*
* Copyright 2017 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/ {
#address-cells = <2>;
#size-cells = <2>;
test1 {
u-boot,dm-pre-reloc;
compatible = "test1";
reg = /bits/ 64 <0x1234 0x5678>;
};
test2 {
u-boot,dm-pre-reloc;
compatible = "test2";
reg = /bits/ 64 <0x1234567890123456 0x9876543210987654>;
};
test3 {
u-boot,dm-pre-reloc;
compatible = "test3";
reg = /bits/ 64 <0x1234567890123456 0x9876543210987654 2 3>;
};
};
tools/dtoc/dtoc_test_addr64_32.dts
0 → 100644
浏览文件 @
08cebeea
/*
* Test device tree file for dtoc
*
* Copyright 2017 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/ {
#address-cells = <2>;
#size-cells = <1>;
test1 {
u-boot,dm-pre-reloc;
compatible = "test1";
reg = <0x1234 0x0 0x5678>;
};
test2 {
u-boot,dm-pre-reloc;
compatible = "test2";
reg = <0x12345678 0x90123456 0x98765432>;
};
test3 {
u-boot,dm-pre-reloc;
compatible = "test3";
reg = <0x12345678 0x90123456 0x98765432 0 2 3>;
};
};
tools/dtoc/dtoc_test_phandle.dts
浏览文件 @
08cebeea
...
...
@@ -10,14 +10,28 @@
/ {
phandle: phandle-target {
u-boot,dm-pre-reloc;
compatible = "target";
intval = <0>;
#clock-cells = <0>;
};
phandle_1: phandle2-target {
u-boot,dm-pre-reloc;
compatible = "target";
intval = <1>;
#clock-cells = <1>;
};
phandle_2: phandle3-target {
u-boot,dm-pre-reloc;
compatible = "target";
intval = <2>;
#clock-cells = <2>;
};
phandle-source {
u-boot,dm-pre-reloc;
compatible = "source";
clocks = <&phandle
1
>;
clocks = <&phandle
&phandle_1 11 &phandle_2 12 13 &phandle
>;
};
};
tools/dtoc/dtoc_test_simple.dts
浏览文件 @
08cebeea
...
...
@@ -9,6 +9,8 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
spl-test {
u-boot,dm-pre-reloc;
compatible = "sandbox,spl-test";
...
...
@@ -45,4 +47,16 @@
compatible = "sandbox,spl-test.2";
};
i2c@0 {
compatible = "sandbox,i2c-test";
u-boot,dm-pre-reloc;
#address-cells = <1>;
#size-cells = <0>;
pmic@9 {
compatible = "sandbox,pmic-test";
u-boot,dm-pre-reloc;
reg = <9>;
low-power;
};
};
};
tools/dtoc/fdt.py
浏览文件 @
08cebeea
...
...
@@ -21,7 +21,7 @@ import libfdt
# so it is fairly efficient.
# A list of types we support
(
TYPE_BYTE
,
TYPE_INT
,
TYPE_STRING
,
TYPE_BOOL
)
=
range
(
4
)
(
TYPE_BYTE
,
TYPE_INT
,
TYPE_STRING
,
TYPE_BOOL
,
TYPE_INT64
)
=
range
(
5
)
def
CheckErr
(
errnum
,
msg
):
if
errnum
:
...
...
@@ -174,8 +174,9 @@ class Node:
props: A dict of properties for this node, each a Prop object.
Keyed by property name
"""
def
__init__
(
self
,
fdt
,
offset
,
name
,
path
):
def
__init__
(
self
,
fdt
,
parent
,
offset
,
name
,
path
):
self
.
_fdt
=
fdt
self
.
parent
=
parent
self
.
_offset
=
offset
self
.
name
=
name
self
.
path
=
path
...
...
@@ -211,13 +212,17 @@ class Node:
searching into subnodes so that the entire tree is built.
"""
self
.
props
=
self
.
_fdt
.
GetProps
(
self
)
phandle
=
self
.
props
.
get
(
'phandle'
)
if
phandle
:
val
=
fdt_util
.
fdt32_to_cpu
(
phandle
.
value
)
self
.
_fdt
.
phandle_to_node
[
val
]
=
self
offset
=
libfdt
.
fdt_first_subnode
(
self
.
_fdt
.
GetFdt
(),
self
.
Offset
())
while
offset
>=
0
:
sep
=
''
if
self
.
path
[
-
1
]
==
'/'
else
'/'
name
=
self
.
_fdt
.
_fdt_obj
.
get_name
(
offset
)
path
=
self
.
path
+
sep
+
name
node
=
Node
(
self
.
_fdt
,
offset
,
name
,
path
)
node
=
Node
(
self
.
_fdt
,
self
,
offset
,
name
,
path
)
self
.
subnodes
.
append
(
node
)
node
.
Scan
()
...
...
@@ -262,6 +267,7 @@ class Fdt:
def
__init__
(
self
,
fname
):
self
.
_fname
=
fname
self
.
_cached_offsets
=
False
self
.
phandle_to_node
=
{}
if
self
.
_fname
:
self
.
_fname
=
fdt_util
.
EnsureCompiled
(
self
.
_fname
)
...
...
@@ -279,7 +285,7 @@ class Fdt:
TODO(sjg@chromium.org): Implement the 'root' parameter
"""
self
.
_root
=
self
.
Node
(
self
,
0
,
'/'
,
'/'
)
self
.
_root
=
self
.
Node
(
self
,
None
,
0
,
'/'
,
'/'
)
self
.
_root
.
Scan
()
def
GetRoot
(
self
):
...
...
@@ -386,7 +392,7 @@ class Fdt:
return
libfdt
.
fdt_off_dt_struct
(
self
.
_fdt
)
+
offset
@
classmethod
def
Node
(
self
,
fdt
,
offset
,
name
,
path
):
def
Node
(
self
,
fdt
,
parent
,
offset
,
name
,
path
):
"""Create a new node
This is used by Fdt.Scan() to create a new node using the correct
...
...
@@ -394,11 +400,12 @@ class Fdt:
Args:
fdt: Fdt object
parent: Parent node, or None if this is the root node
offset: Offset of node
name: Node name
path: Full path to node
"""
node
=
Node
(
fdt
,
offset
,
name
,
path
)
node
=
Node
(
fdt
,
parent
,
offset
,
name
,
path
)
return
node
def
FdtScan
(
fname
):
...
...
tools/dtoc/fdt_util.py
浏览文件 @
08cebeea
...
...
@@ -29,6 +29,22 @@ def fdt32_to_cpu(val):
val
=
val
.
encode
(
'raw_unicode_escape'
)
return
struct
.
unpack
(
'>I'
,
val
)[
0
]
def
fdt_cells_to_cpu
(
val
,
cells
):
"""Convert one or two cells to a long integer
Args:
Value to convert (array of one or more 4-character strings)
Return:
A native-endian long value
"""
if
not
cells
:
return
0
out
=
long
(
fdt32_to_cpu
(
val
[
0
]))
if
cells
==
2
:
out
=
out
<<
32
|
fdt32_to_cpu
(
val
[
1
])
return
out
def
EnsureCompiled
(
fname
):
"""Compile an fdt .dts source file into a .dtb binary blob if needed.
...
...
tools/dtoc/test_dtoc.py
浏览文件 @
08cebeea
...
...
@@ -121,6 +121,12 @@ class TestDtoc(unittest.TestCase):
data
=
infile
.
read
()
self
.
assertEqual
(
'''#include <stdbool.h>
#include <libfdt.h>
struct dtd_sandbox_i2c_test {
};
struct dtd_sandbox_pmic_test {
\t
bool
\t\t
low_power;
\t
fdt64_t
\t\t
reg[2];
};
struct dtd_sandbox_spl_test {
\t
bool
\t\t
boolval;
\t
unsigned char
\t
bytearray[3];
...
...
@@ -146,7 +152,8 @@ static struct dtd_sandbox_spl_test dtv_spl_test = {
\t
.bytearray
\t\t
= {0x6, 0x0, 0x0},
\t
.byteval
\t\t
= 0x5,
\t
.intval
\t\t\t
= 0x1,
\t
.longbytearray
\t\t
= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11},
\t
.longbytearray
\t\t
= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
\t\t
0x11},
\t
.stringval
\t\t
= "message",
\t
.boolval
\t\t
= true,
\t
.intarray
\t\t
= {0x2, 0x3, 0x4, 0x0},
...
...
@@ -162,7 +169,8 @@ static struct dtd_sandbox_spl_test dtv_spl_test2 = {
\t
.bytearray
\t\t
= {0x1, 0x23, 0x34},
\t
.byteval
\t\t
= 0x8,
\t
.intval
\t\t\t
= 0x3,
\t
.longbytearray
\t\t
= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
\t
.longbytearray
\t\t
= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
\t\t
0x0},
\t
.stringval
\t\t
= "message2",
\t
.intarray
\t\t
= {0x5, 0x0, 0x0, 0x0},
\t
.stringarray
\t\t
= {"another", "multi-word", "message"},
...
...
@@ -190,6 +198,24 @@ U_BOOT_DEVICE(spl_test4) = {
\t
.platdata_size
\t
= sizeof(dtv_spl_test4),
};
static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
};
U_BOOT_DEVICE(i2c_at_0) = {
\t
.name
\t\t
= "sandbox_i2c_test",
\t
.platdata
\t
= &dtv_i2c_at_0,
\t
.platdata_size
\t
= sizeof(dtv_i2c_at_0),
};
static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
\t
.low_power
\t\t
= true,
\t
.reg
\t\t\t
= {0x9, 0x0},
};
U_BOOT_DEVICE(pmic_at_9) = {
\t
.name
\t\t
= "sandbox_pmic_test",
\t
.platdata
\t
= &dtv_pmic_at_9,
\t
.platdata_size
\t
= sizeof(dtv_pmic_at_9),
};
'''
,
data
)
def
test_phandle
(
self
):
...
...
@@ -202,7 +228,7 @@ U_BOOT_DEVICE(spl_test4) = {
self
.
assertEqual
(
'''#include <stdbool.h>
#include <libfdt.h>
struct dtd_source {
\t
struct phandle_2_
cell clocks[1
];
\t
struct phandle_2_
arg clocks[4
];
};
struct dtd_target {
\t
fdt32_t
\t\t
intval;
...
...
@@ -217,7 +243,7 @@ struct dtd_target {
#include <dt-structs.h>
static struct dtd_target dtv_phandle_target = {
\t
.intval
\t\t\t
= 0x
1
,
\t
.intval
\t\t\t
= 0x
0
,
};
U_BOOT_DEVICE(phandle_target) = {
\t
.name
\t\t
= "target",
...
...
@@ -225,8 +251,30 @@ U_BOOT_DEVICE(phandle_target) = {
\t
.platdata_size
\t
= sizeof(dtv_phandle_target),
};
static struct dtd_target dtv_phandle2_target = {
\t
.intval
\t\t\t
= 0x1,
};
U_BOOT_DEVICE(phandle2_target) = {
\t
.name
\t\t
= "target",
\t
.platdata
\t
= &dtv_phandle2_target,
\t
.platdata_size
\t
= sizeof(dtv_phandle2_target),
};
static struct dtd_target dtv_phandle3_target = {
\t
.intval
\t\t\t
= 0x2,
};
U_BOOT_DEVICE(phandle3_target) = {
\t
.name
\t\t
= "target",
\t
.platdata
\t
= &dtv_phandle3_target,
\t
.platdata_size
\t
= sizeof(dtv_phandle3_target),
};
static struct dtd_source dtv_phandle_source = {
\t
.clocks
\t\t\t
= {{&dtv_phandle_target, 1}},
\t
.clocks
\t\t\t
= {
\t\t\t
{&dtv_phandle_target, {}},
\t\t\t
{&dtv_phandle2_target, {11}},
\t\t\t
{&dtv_phandle3_target, {12, 13}},
\t\t\t
{&dtv_phandle_target, {}},},
};
U_BOOT_DEVICE(phandle_source) = {
\t
.name
\t\t
= "source",
...
...
@@ -268,4 +316,216 @@ U_BOOT_DEVICE(spl_test) = {
\t
.platdata_size
\t
= sizeof(dtv_spl_test),
};
'''
,
data
)
def
test_addresses64
(
self
):
"""Test output from a node with a 'reg' property with na=2, ns=2"""
dtb_file
=
get_dtb_file
(
'dtoc_test_addr64.dts'
)
output
=
tools
.
GetOutputFilename
(
'output'
)
dtb_platdata
.
run_steps
([
'struct'
],
dtb_file
,
False
,
output
)
with
open
(
output
)
as
infile
:
data
=
infile
.
read
()
self
.
assertEqual
(
'''#include <stdbool.h>
#include <libfdt.h>
struct dtd_test1 {
\t
fdt64_t
\t\t
reg[2];
};
struct dtd_test2 {
\t
fdt64_t
\t\t
reg[2];
};
struct dtd_test3 {
\t
fdt64_t
\t\t
reg[4];
};
'''
,
data
)
dtb_platdata
.
run_steps
([
'platdata'
],
dtb_file
,
False
,
output
)
with
open
(
output
)
as
infile
:
data
=
infile
.
read
()
self
.
assertEqual
(
'''#include <common.h>
#include <dm.h>
#include <dt-structs.h>
static struct dtd_test1 dtv_test1 = {
\t
.reg
\t\t\t
= {0x1234, 0x5678},
};
U_BOOT_DEVICE(test1) = {
\t
.name
\t\t
= "test1",
\t
.platdata
\t
= &dtv_test1,
\t
.platdata_size
\t
= sizeof(dtv_test1),
};
static struct dtd_test2 dtv_test2 = {
\t
.reg
\t\t\t
= {0x1234567890123456, 0x9876543210987654},
};
U_BOOT_DEVICE(test2) = {
\t
.name
\t\t
= "test2",
\t
.platdata
\t
= &dtv_test2,
\t
.platdata_size
\t
= sizeof(dtv_test2),
};
static struct dtd_test3 dtv_test3 = {
\t
.reg
\t\t\t
= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3},
};
U_BOOT_DEVICE(test3) = {
\t
.name
\t\t
= "test3",
\t
.platdata
\t
= &dtv_test3,
\t
.platdata_size
\t
= sizeof(dtv_test3),
};
'''
,
data
)
def
test_addresses32
(
self
):
"""Test output from a node with a 'reg' property with na=1, ns=1"""
dtb_file
=
get_dtb_file
(
'dtoc_test_addr32.dts'
)
output
=
tools
.
GetOutputFilename
(
'output'
)
dtb_platdata
.
run_steps
([
'struct'
],
dtb_file
,
False
,
output
)
with
open
(
output
)
as
infile
:
data
=
infile
.
read
()
self
.
assertEqual
(
'''#include <stdbool.h>
#include <libfdt.h>
struct dtd_test1 {
\t
fdt32_t
\t\t
reg[2];
};
struct dtd_test2 {
\t
fdt32_t
\t\t
reg[4];
};
'''
,
data
)
dtb_platdata
.
run_steps
([
'platdata'
],
dtb_file
,
False
,
output
)
with
open
(
output
)
as
infile
:
data
=
infile
.
read
()
self
.
assertEqual
(
'''#include <common.h>
#include <dm.h>
#include <dt-structs.h>
static struct dtd_test1 dtv_test1 = {
\t
.reg
\t\t\t
= {0x1234, 0x5678},
};
U_BOOT_DEVICE(test1) = {
\t
.name
\t\t
= "test1",
\t
.platdata
\t
= &dtv_test1,
\t
.platdata_size
\t
= sizeof(dtv_test1),
};
static struct dtd_test2 dtv_test2 = {
\t
.reg
\t\t\t
= {0x12345678, 0x98765432, 0x2, 0x3},
};
U_BOOT_DEVICE(test2) = {
\t
.name
\t\t
= "test2",
\t
.platdata
\t
= &dtv_test2,
\t
.platdata_size
\t
= sizeof(dtv_test2),
};
'''
,
data
)
def
test_addresses64_32
(
self
):
"""Test output from a node with a 'reg' property with na=2, ns=1"""
dtb_file
=
get_dtb_file
(
'dtoc_test_addr64_32.dts'
)
output
=
tools
.
GetOutputFilename
(
'output'
)
dtb_platdata
.
run_steps
([
'struct'
],
dtb_file
,
False
,
output
)
with
open
(
output
)
as
infile
:
data
=
infile
.
read
()
self
.
assertEqual
(
'''#include <stdbool.h>
#include <libfdt.h>
struct dtd_test1 {
\t
fdt64_t
\t\t
reg[2];
};
struct dtd_test2 {
\t
fdt64_t
\t\t
reg[2];
};
struct dtd_test3 {
\t
fdt64_t
\t\t
reg[4];
};
'''
,
data
)
dtb_platdata
.
run_steps
([
'platdata'
],
dtb_file
,
False
,
output
)
with
open
(
output
)
as
infile
:
data
=
infile
.
read
()
self
.
assertEqual
(
'''#include <common.h>
#include <dm.h>
#include <dt-structs.h>
static struct dtd_test1 dtv_test1 = {
\t
.reg
\t\t\t
= {0x123400000000, 0x5678},
};
U_BOOT_DEVICE(test1) = {
\t
.name
\t\t
= "test1",
\t
.platdata
\t
= &dtv_test1,
\t
.platdata_size
\t
= sizeof(dtv_test1),
};
static struct dtd_test2 dtv_test2 = {
\t
.reg
\t\t\t
= {0x1234567890123456, 0x98765432},
};
U_BOOT_DEVICE(test2) = {
\t
.name
\t\t
= "test2",
\t
.platdata
\t
= &dtv_test2,
\t
.platdata_size
\t
= sizeof(dtv_test2),
};
static struct dtd_test3 dtv_test3 = {
\t
.reg
\t\t\t
= {0x1234567890123456, 0x98765432, 0x2, 0x3},
};
U_BOOT_DEVICE(test3) = {
\t
.name
\t\t
= "test3",
\t
.platdata
\t
= &dtv_test3,
\t
.platdata_size
\t
= sizeof(dtv_test3),
};
'''
,
data
)
def
test_addresses32_64
(
self
):
"""Test output from a node with a 'reg' property with na=1, ns=2"""
dtb_file
=
get_dtb_file
(
'dtoc_test_addr32_64.dts'
)
output
=
tools
.
GetOutputFilename
(
'output'
)
dtb_platdata
.
run_steps
([
'struct'
],
dtb_file
,
False
,
output
)
with
open
(
output
)
as
infile
:
data
=
infile
.
read
()
self
.
assertEqual
(
'''#include <stdbool.h>
#include <libfdt.h>
struct dtd_test1 {
\t
fdt64_t
\t\t
reg[2];
};
struct dtd_test2 {
\t
fdt64_t
\t\t
reg[2];
};
struct dtd_test3 {
\t
fdt64_t
\t\t
reg[4];
};
'''
,
data
)
dtb_platdata
.
run_steps
([
'platdata'
],
dtb_file
,
False
,
output
)
with
open
(
output
)
as
infile
:
data
=
infile
.
read
()
self
.
assertEqual
(
'''#include <common.h>
#include <dm.h>
#include <dt-structs.h>
static struct dtd_test1 dtv_test1 = {
\t
.reg
\t\t\t
= {0x1234, 0x567800000000},
};
U_BOOT_DEVICE(test1) = {
\t
.name
\t\t
= "test1",
\t
.platdata
\t
= &dtv_test1,
\t
.platdata_size
\t
= sizeof(dtv_test1),
};
static struct dtd_test2 dtv_test2 = {
\t
.reg
\t\t\t
= {0x12345678, 0x9876543210987654},
};
U_BOOT_DEVICE(test2) = {
\t
.name
\t\t
= "test2",
\t
.platdata
\t
= &dtv_test2,
\t
.platdata_size
\t
= sizeof(dtv_test2),
};
static struct dtd_test3 dtv_test3 = {
\t
.reg
\t\t\t
= {0x12345678, 0x9876543210987654, 0x2, 0x3},
};
U_BOOT_DEVICE(test3) = {
\t
.name
\t\t
= "test3",
\t
.platdata
\t
= &dtv_test3,
\t
.platdata_size
\t
= sizeof(dtv_test3),
};
'''
,
data
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录