Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
ezynq
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
ezynq
Commits
47fad1d4
Commit
47fad1d4
authored
Dec 26, 2018
by
Oleg Dzhimiev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added wrong libfdt?
parent
3e304607
Changes
45
Show whitespace changes
Inline
Side-by-side
Showing
45 changed files
with
49 additions
and
12148 deletions
+49
-12148
.gitignore
u-boot-tree/scripts/dtc/.gitignore
+0
-1
Makefile
u-boot-tree/scripts/dtc/Makefile
+0
-32
Makefile.dtc
u-boot-tree/scripts/dtc/Makefile.dtc
+0
-18
checks.c
u-boot-tree/scripts/dtc/checks.c
+0
-1506
data.c
u-boot-tree/scripts/dtc/data.c
+0
-269
dtc-lexer.l
u-boot-tree/scripts/dtc/dtc-lexer.l
+0
-306
dtc-parser.y
u-boot-tree/scripts/dtc/dtc-parser.y
+0
-538
dtc.c
u-boot-tree/scripts/dtc/dtc.c
+0
-364
dtc.h
u-boot-tree/scripts/dtc/dtc.h
+0
-293
flattree.c
u-boot-tree/scripts/dtc/flattree.c
+0
-940
fstree.c
u-boot-tree/scripts/dtc/fstree.c
+0
-90
Makefile.libfdt
u-boot-tree/scripts/dtc/libfdt/Makefile.libfdt
+0
-11
fdt.c
u-boot-tree/scripts/dtc/libfdt/fdt.c
+0
-254
fdt_addresses.c
u-boot-tree/scripts/dtc/libfdt/fdt_addresses.c
+0
-96
fdt_empty_tree.c
u-boot-tree/scripts/dtc/libfdt/fdt_empty_tree.c
+0
-83
fdt_overlay.c
u-boot-tree/scripts/dtc/libfdt/fdt_overlay.c
+0
-912
fdt_ro.c
u-boot-tree/scripts/dtc/libfdt/fdt_ro.c
+0
-773
fdt_rw.c
u-boot-tree/scripts/dtc/libfdt/fdt_rw.c
+0
-505
fdt_strerror.c
u-boot-tree/scripts/dtc/libfdt/fdt_strerror.c
+0
-102
fdt_sw.c
u-boot-tree/scripts/dtc/libfdt/fdt_sw.c
+0
-300
fdt_wip.c
u-boot-tree/scripts/dtc/libfdt/fdt_wip.c
+0
-139
livetree.c
u-boot-tree/scripts/dtc/livetree.c
+0
-1013
.gitignore
u-boot-tree/scripts/dtc/pylibfdt/.gitignore
+0
-4
Makefile
u-boot-tree/scripts/dtc/pylibfdt/Makefile
+0
-31
libfdt.i_shipped
u-boot-tree/scripts/dtc/pylibfdt/libfdt.i_shipped
+0
-1097
setup.py
u-boot-tree/scripts/dtc/pylibfdt/setup.py
+0
-123
srcpos.c
u-boot-tree/scripts/dtc/srcpos.c
+0
-297
srcpos.h
u-boot-tree/scripts/dtc/srcpos.h
+0
-117
treesource.c
u-boot-tree/scripts/dtc/treesource.c
+0
-284
update-dtc-source.sh
u-boot-tree/scripts/dtc/update-dtc-source.sh
+0
-79
util.c
u-boot-tree/scripts/dtc/util.c
+0
-474
util.h
u-boot-tree/scripts/dtc/util.h
+0
-266
version_gen.h
u-boot-tree/scripts/dtc/version_gen.h
+0
-1
aisimage.c
u-boot-tree/tools/aisimage.c
+0
-429
aisimage.h
u-boot-tree/tools/aisimage.h
+0
-81
fdt_host.h
u-boot-tree/tools/fdt_host.h
+0
-33
imagetool.h
u-boot-tree/tools/imagetool.h
+0
-287
fdt.c
u-boot-tree/tools/libfdt/fdt.c
+2
-0
fdt_addresses.c
u-boot-tree/tools/libfdt/fdt_addresses.c
+2
-0
fdt_empty_tree.c
u-boot-tree/tools/libfdt/fdt_empty_tree.c
+2
-0
fdt_overlay.c
u-boot-tree/tools/libfdt/fdt_overlay.c
+2
-0
fdt_rw.c
u-boot-tree/tools/libfdt/fdt_rw.c
+35
-0
fdt_strerror.c
u-boot-tree/tools/libfdt/fdt_strerror.c
+2
-0
fdt_sw.c
u-boot-tree/tools/libfdt/fdt_sw.c
+2
-0
fdt_wip.c
u-boot-tree/tools/libfdt/fdt_wip.c
+2
-0
No files found.
u-boot-tree/scripts/dtc/.gitignore
deleted
100644 → 0
View file @
3e304607
/dtc
u-boot-tree/scripts/dtc/Makefile
deleted
100644 → 0
View file @
3e304607
# SPDX-License-Identifier: GPL-2.0
# scripts/dtc makefile
hostprogs-y
:=
dtc
always
:=
$
(
hostprogs-y
)
dtc-objs
:=
dtc.o flattree.o fstree.o data.o livetree.o treesource.o
\
srcpos.o checks.o util.o
dtc-objs
+=
dtc-lexer.lex.o dtc-parser.tab.o
# Source files need to get at the userspace version of libfdt_env.h to compile
HOSTCFLAGS_DTC
:=
-I
$(src)
-I
$(src)
/libfdt
HOSTCFLAGS_checks.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_data.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_flattree.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_fstree.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_livetree.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_srcpos.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_treesource.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_util.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc-lexer.lex.o
:=
$(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc-parser.tab.o
:=
$(HOSTCFLAGS_DTC)
# dependencies on generated files need to be listed explicitly
$(obj)/dtc-lexer.lex.o
:
$(obj)/dtc-parser.tab.h
# Added for U-Boot
subdir-$(CONFIG_PYLIBFDT)
+=
pylibfdt
u-boot-tree/scripts/dtc/Makefile.dtc
deleted
100644 → 0
View file @
3e304607
# Makefile.dtc
#
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
DTC_SRCS
=
\
checks.c
\
data.c
\
dtc.c
\
flattree.c
\
fstree.c
\
livetree.c
\
srcpos.c
\
treesource.c
\
util.c
DTC_GEN_SRCS
=
dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS
=
$
(
DTC_SRCS:%.c
=
%.o
)
$
(
DTC_GEN_SRCS:%.c
=
%.o
)
u-boot-tree/scripts/dtc/checks.c
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "dtc.h"
#ifdef TRACE_CHECKS
#define TRACE(c, ...) \
do { \
fprintf(stderr, "=== %s: ", (c)->name); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while (0)
#else
#define TRACE(c, fmt, ...) do { } while (0)
#endif
enum
checkstatus
{
UNCHECKED
=
0
,
PREREQ
,
PASSED
,
FAILED
,
};
struct
check
;
typedef
void
(
*
check_fn
)(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
);
struct
check
{
const
char
*
name
;
check_fn
fn
;
void
*
data
;
bool
warn
,
error
;
enum
checkstatus
status
;
bool
inprogress
;
int
num_prereqs
;
struct
check
**
prereq
;
};
#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...) \
static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \
static struct check nm_ = { \
.name = #nm_, \
.fn = (fn_), \
.data = (d_), \
.warn = (w_), \
.error = (e_), \
.status = UNCHECKED, \
.num_prereqs = ARRAY_SIZE(nm_##_prereqs), \
.prereq = nm_##_prereqs, \
};
#define WARNING(nm_, fn_, d_, ...) \
CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__)
#define ERROR(nm_, fn_, d_, ...) \
CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__)
#define CHECK(nm_, fn_, d_, ...) \
CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__)
static
inline
void
PRINTF
(
5
,
6
)
check_msg
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
,
struct
property
*
prop
,
const
char
*
fmt
,
...)
{
va_list
ap
;
va_start
(
ap
,
fmt
);
if
((
c
->
warn
&&
(
quiet
<
1
))
||
(
c
->
error
&&
(
quiet
<
2
)))
{
fprintf
(
stderr
,
"%s: %s (%s): "
,
strcmp
(
dti
->
outname
,
"-"
)
?
dti
->
outname
:
"<stdout>"
,
(
c
->
error
)
?
"ERROR"
:
"Warning"
,
c
->
name
);
if
(
node
)
{
fprintf
(
stderr
,
"%s"
,
node
->
fullpath
);
if
(
prop
)
fprintf
(
stderr
,
":%s"
,
prop
->
name
);
fputs
(
": "
,
stderr
);
}
vfprintf
(
stderr
,
fmt
,
ap
);
fprintf
(
stderr
,
"
\n
"
);
}
va_end
(
ap
);
}
#define FAIL(c, dti, node, ...) \
do { \
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
(c)->status = FAILED; \
check_msg((c), dti, node, NULL, __VA_ARGS__); \
} while (0)
#define FAIL_PROP(c, dti, node, prop, ...) \
do { \
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
(c)->status = FAILED; \
check_msg((c), dti, node, prop, __VA_ARGS__); \
} while (0)
static
void
check_nodes_props
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
child
;
TRACE
(
c
,
"%s"
,
node
->
fullpath
);
if
(
c
->
fn
)
c
->
fn
(
c
,
dti
,
node
);
for_each_child
(
node
,
child
)
check_nodes_props
(
c
,
dti
,
child
);
}
static
bool
run_check
(
struct
check
*
c
,
struct
dt_info
*
dti
)
{
struct
node
*
dt
=
dti
->
dt
;
bool
error
=
false
;
int
i
;
assert
(
!
c
->
inprogress
);
if
(
c
->
status
!=
UNCHECKED
)
goto
out
;
c
->
inprogress
=
true
;
for
(
i
=
0
;
i
<
c
->
num_prereqs
;
i
++
)
{
struct
check
*
prq
=
c
->
prereq
[
i
];
error
=
error
||
run_check
(
prq
,
dti
);
if
(
prq
->
status
!=
PASSED
)
{
c
->
status
=
PREREQ
;
check_msg
(
c
,
dti
,
NULL
,
NULL
,
"Failed prerequisite '%s'"
,
c
->
prereq
[
i
]
->
name
);
}
}
if
(
c
->
status
!=
UNCHECKED
)
goto
out
;
check_nodes_props
(
c
,
dti
,
dt
);
if
(
c
->
status
==
UNCHECKED
)
c
->
status
=
PASSED
;
TRACE
(
c
,
"
\t
Completed, status %d"
,
c
->
status
);
out:
c
->
inprogress
=
false
;
if
((
c
->
status
!=
PASSED
)
&&
(
c
->
error
))
error
=
true
;
return
error
;
}
/*
* Utility check functions
*/
/* A check which always fails, for testing purposes only */
static
inline
void
check_always_fail
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
FAIL
(
c
,
dti
,
node
,
"always_fail check"
);
}
CHECK
(
always_fail
,
check_always_fail
,
NULL
);
static
void
check_is_string
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
char
*
propname
=
c
->
data
;
prop
=
get_property
(
node
,
propname
);
if
(
!
prop
)
return
;
/* Not present, assumed ok */
if
(
!
data_is_one_string
(
prop
->
val
))
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"property is not a string"
);
}
#define WARNING_IF_NOT_STRING(nm, propname) \
WARNING(nm, check_is_string, (propname))
#define ERROR_IF_NOT_STRING(nm, propname) \
ERROR(nm, check_is_string, (propname))
static
void
check_is_string_list
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
int
rem
,
l
;
struct
property
*
prop
;
char
*
propname
=
c
->
data
;
char
*
str
;
prop
=
get_property
(
node
,
propname
);
if
(
!
prop
)
return
;
/* Not present, assumed ok */
str
=
prop
->
val
.
val
;
rem
=
prop
->
val
.
len
;
while
(
rem
>
0
)
{
l
=
strnlen
(
str
,
rem
);
if
(
l
==
rem
)
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"property is not a string list"
);
break
;
}
rem
-=
l
+
1
;
str
+=
l
+
1
;
}
}
#define WARNING_IF_NOT_STRING_LIST(nm, propname) \
WARNING(nm, check_is_string_list, (propname))
#define ERROR_IF_NOT_STRING_LIST(nm, propname) \
ERROR(nm, check_is_string_list, (propname))
static
void
check_is_cell
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
char
*
propname
=
c
->
data
;
prop
=
get_property
(
node
,
propname
);
if
(
!
prop
)
return
;
/* Not present, assumed ok */
if
(
prop
->
val
.
len
!=
sizeof
(
cell_t
))
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"property is not a single cell"
);
}
#define WARNING_IF_NOT_CELL(nm, propname) \
WARNING(nm, check_is_cell, (propname))
#define ERROR_IF_NOT_CELL(nm, propname) \
ERROR(nm, check_is_cell, (propname))
/*
* Structural check functions
*/
static
void
check_duplicate_node_names
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
child
,
*
child2
;
for_each_child
(
node
,
child
)
for
(
child2
=
child
->
next_sibling
;
child2
;
child2
=
child2
->
next_sibling
)
if
(
streq
(
child
->
name
,
child2
->
name
))
FAIL
(
c
,
dti
,
node
,
"Duplicate node name"
);
}
ERROR
(
duplicate_node_names
,
check_duplicate_node_names
,
NULL
);
static
void
check_duplicate_property_names
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
,
*
prop2
;
for_each_property
(
node
,
prop
)
{
for
(
prop2
=
prop
->
next
;
prop2
;
prop2
=
prop2
->
next
)
{
if
(
prop2
->
deleted
)
continue
;
if
(
streq
(
prop
->
name
,
prop2
->
name
))
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"Duplicate property name"
);
}
}
}
ERROR
(
duplicate_property_names
,
check_duplicate_property_names
,
NULL
);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
static
void
check_node_name_chars
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
int
n
=
strspn
(
node
->
name
,
c
->
data
);
if
(
n
<
strlen
(
node
->
name
))
FAIL
(
c
,
dti
,
node
,
"Bad character '%c' in node name"
,
node
->
name
[
n
]);
}
ERROR
(
node_name_chars
,
check_node_name_chars
,
PROPNODECHARS
"@"
);
static
void
check_node_name_chars_strict
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
int
n
=
strspn
(
node
->
name
,
c
->
data
);
if
(
n
<
node
->
basenamelen
)
FAIL
(
c
,
dti
,
node
,
"Character '%c' not recommended in node name"
,
node
->
name
[
n
]);
}
CHECK
(
node_name_chars_strict
,
check_node_name_chars_strict
,
PROPNODECHARSSTRICT
);
static
void
check_node_name_format
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
if
(
strchr
(
get_unitname
(
node
),
'@'
))
FAIL
(
c
,
dti
,
node
,
"multiple '@' characters in node name"
);
}
ERROR
(
node_name_format
,
check_node_name_format
,
NULL
,
&
node_name_chars
);
static
void
check_unit_address_vs_reg
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
const
char
*
unitname
=
get_unitname
(
node
);
struct
property
*
prop
=
get_property
(
node
,
"reg"
);
if
(
!
prop
)
{
prop
=
get_property
(
node
,
"ranges"
);
if
(
prop
&&
!
prop
->
val
.
len
)
prop
=
NULL
;
}
if
(
prop
)
{
if
(
!
unitname
[
0
])
FAIL
(
c
,
dti
,
node
,
"node has a reg or ranges property, but no unit name"
);
}
else
{
if
(
unitname
[
0
])
FAIL
(
c
,
dti
,
node
,
"node has a unit name, but no reg property"
);
}
}
WARNING
(
unit_address_vs_reg
,
check_unit_address_vs_reg
,
NULL
);
static
void
check_property_name_chars
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
for_each_property
(
node
,
prop
)
{
int
n
=
strspn
(
prop
->
name
,
c
->
data
);
if
(
n
<
strlen
(
prop
->
name
))
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"Bad character '%c' in property name"
,
prop
->
name
[
n
]);
}
}
ERROR
(
property_name_chars
,
check_property_name_chars
,
PROPNODECHARS
);
static
void
check_property_name_chars_strict
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
for_each_property
(
node
,
prop
)
{
const
char
*
name
=
prop
->
name
;
int
n
=
strspn
(
name
,
c
->
data
);
if
(
n
==
strlen
(
prop
->
name
))
continue
;
/* Certain names are whitelisted */
if
(
streq
(
name
,
"device_type"
))
continue
;
/*
* # is only allowed at the beginning of property names not counting
* the vendor prefix.
*/
if
(
name
[
n
]
==
'#'
&&
((
n
==
0
)
||
(
name
[
n
-
1
]
==
','
)))
{
name
+=
n
+
1
;
n
=
strspn
(
name
,
c
->
data
);
}
if
(
n
<
strlen
(
name
))
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"Character '%c' not recommended in property name"
,
name
[
n
]);
}
}
CHECK
(
property_name_chars_strict
,
check_property_name_chars_strict
,
PROPNODECHARSSTRICT
);
#define DESCLABEL_FMT "%s%s%s%s%s"
#define DESCLABEL_ARGS(node,prop,mark) \
((mark) ? "value of " : ""), \
((prop) ? "'" : ""), \
((prop) ? (prop)->name : ""), \
((prop) ? "' in " : ""), (node)->fullpath
static
void
check_duplicate_label
(
struct
check
*
c
,
struct
dt_info
*
dti
,
const
char
*
label
,
struct
node
*
node
,
struct
property
*
prop
,
struct
marker
*
mark
)
{
struct
node
*
dt
=
dti
->
dt
;
struct
node
*
othernode
=
NULL
;
struct
property
*
otherprop
=
NULL
;
struct
marker
*
othermark
=
NULL
;
othernode
=
get_node_by_label
(
dt
,
label
);
if
(
!
othernode
)
otherprop
=
get_property_by_label
(
dt
,
label
,
&
othernode
);
if
(
!
othernode
)
othermark
=
get_marker_label
(
dt
,
label
,
&
othernode
,
&
otherprop
);
if
(
!
othernode
)
return
;
if
((
othernode
!=
node
)
||
(
otherprop
!=
prop
)
||
(
othermark
!=
mark
))
FAIL
(
c
,
dti
,
node
,
"Duplicate label '%s' on "
DESCLABEL_FMT
" and "
DESCLABEL_FMT
,
label
,
DESCLABEL_ARGS
(
node
,
prop
,
mark
),
DESCLABEL_ARGS
(
othernode
,
otherprop
,
othermark
));
}
static
void
check_duplicate_label_node
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
label
*
l
;
struct
property
*
prop
;
for_each_label
(
node
->
labels
,
l
)
check_duplicate_label
(
c
,
dti
,
l
->
label
,
node
,
NULL
,
NULL
);
for_each_property
(
node
,
prop
)
{
struct
marker
*
m
=
prop
->
val
.
markers
;
for_each_label
(
prop
->
labels
,
l
)
check_duplicate_label
(
c
,
dti
,
l
->
label
,
node
,
prop
,
NULL
);
for_each_marker_of_type
(
m
,
LABEL
)
check_duplicate_label
(
c
,
dti
,
m
->
ref
,
node
,
prop
,
m
);
}
}
ERROR
(
duplicate_label
,
check_duplicate_label_node
,
NULL
);
static
cell_t
check_phandle_prop
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
,
const
char
*
propname
)
{
struct
node
*
root
=
dti
->
dt
;
struct
property
*
prop
;
struct
marker
*
m
;
cell_t
phandle
;
prop
=
get_property
(
node
,
propname
);
if
(
!
prop
)
return
0
;
if
(
prop
->
val
.
len
!=
sizeof
(
cell_t
))
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"bad length (%d) %s property"
,
prop
->
val
.
len
,
prop
->
name
);
return
0
;
}
m
=
prop
->
val
.
markers
;
for_each_marker_of_type
(
m
,
REF_PHANDLE
)
{
assert
(
m
->
offset
==
0
);
if
(
node
!=
get_node_by_ref
(
root
,
m
->
ref
))
/* "Set this node's phandle equal to some
* other node's phandle". That's nonsensical
* by construction. */
{
FAIL
(
c
,
dti
,
node
,
"%s is a reference to another node"
,
prop
->
name
);
}
/* But setting this node's phandle equal to its own
* phandle is allowed - that means allocate a unique
* phandle for this node, even if it's not otherwise
* referenced. The value will be filled in later, so
* we treat it as having no phandle data for now. */
return
0
;
}
phandle
=
propval_cell
(
prop
);
if
((
phandle
==
0
)
||
(
phandle
==
-
1
))
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"bad value (0x%x) in %s property"
,
phandle
,
prop
->
name
);
return
0
;
}
return
phandle
;
}
static
void
check_explicit_phandles
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
root
=
dti
->
dt
;
struct
node
*
other
;
cell_t
phandle
,
linux_phandle
;
/* Nothing should have assigned phandles yet */
assert
(
!
node
->
phandle
);
phandle
=
check_phandle_prop
(
c
,
dti
,
node
,
"phandle"
);
linux_phandle
=
check_phandle_prop
(
c
,
dti
,
node
,
"linux,phandle"
);
if
(
!
phandle
&&
!
linux_phandle
)
/* No valid phandles; nothing further to check */
return
;
if
(
linux_phandle
&&
phandle
&&
(
phandle
!=
linux_phandle
))
FAIL
(
c
,
dti
,
node
,
"mismatching 'phandle' and 'linux,phandle'"
" properties"
);
if
(
linux_phandle
&&
!
phandle
)
phandle
=
linux_phandle
;
other
=
get_node_by_phandle
(
root
,
phandle
);
if
(
other
&&
(
other
!=
node
))
{
FAIL
(
c
,
dti
,
node
,
"duplicated phandle 0x%x (seen before at %s)"
,
phandle
,
other
->
fullpath
);
return
;
}
node
->
phandle
=
phandle
;
}
ERROR
(
explicit_phandles
,
check_explicit_phandles
,
NULL
);
static
void
check_name_properties
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
**
pp
,
*
prop
=
NULL
;
for
(
pp
=
&
node
->
proplist
;
*
pp
;
pp
=
&
((
*
pp
)
->
next
))
if
(
streq
((
*
pp
)
->
name
,
"name"
))
{
prop
=
*
pp
;
break
;
}
if
(
!
prop
)
return
;
/* No name property, that's fine */
if
((
prop
->
val
.
len
!=
node
->
basenamelen
+
1
)
||
(
memcmp
(
prop
->
val
.
val
,
node
->
name
,
node
->
basenamelen
)
!=
0
))
{
FAIL
(
c
,
dti
,
node
,
"
\"
name
\"
property is incorrect (
\"
%s
\"
instead"
" of base node name)"
,
prop
->
val
.
val
);
}
else
{
/* The name property is correct, and therefore redundant.
* Delete it */
*
pp
=
prop
->
next
;
free
(
prop
->
name
);
data_free
(
prop
->
val
);
free
(
prop
);
}
}
ERROR_IF_NOT_STRING
(
name_is_string
,
"name"
);
ERROR
(
name_properties
,
check_name_properties
,
NULL
,
&
name_is_string
);
/*
* Reference fixup functions
*/
static
void
fixup_phandle_references
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
dt
=
dti
->
dt
;
struct
property
*
prop
;
for_each_property
(
node
,
prop
)
{
struct
marker
*
m
=
prop
->
val
.
markers
;
struct
node
*
refnode
;
cell_t
phandle
;
for_each_marker_of_type
(
m
,
REF_PHANDLE
)
{
assert
(
m
->
offset
+
sizeof
(
cell_t
)
<=
prop
->
val
.
len
);
refnode
=
get_node_by_ref
(
dt
,
m
->
ref
);
if
(
!
refnode
)
{
if
(
!
(
dti
->
dtsflags
&
DTSF_PLUGIN
))
FAIL
(
c
,
dti
,
node
,
"Reference to non-existent node or "
"label
\"
%s
\"\n
"
,
m
->
ref
);
else
/* mark the entry as unresolved */
*
((
fdt32_t
*
)(
prop
->
val
.
val
+
m
->
offset
))
=
cpu_to_fdt32
(
0xffffffff
);
continue
;
}
phandle
=
get_node_phandle
(
dt
,
refnode
);
*
((
fdt32_t
*
)(
prop
->
val
.
val
+
m
->
offset
))
=
cpu_to_fdt32
(
phandle
);
}
}
}
ERROR
(
phandle_references
,
fixup_phandle_references
,
NULL
,
&
duplicate_node_names
,
&
explicit_phandles
);
static
void
fixup_path_references
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
dt
=
dti
->
dt
;
struct
property
*
prop
;
for_each_property
(
node
,
prop
)
{
struct
marker
*
m
=
prop
->
val
.
markers
;
struct
node
*
refnode
;
char
*
path
;
for_each_marker_of_type
(
m
,
REF_PATH
)
{
assert
(
m
->
offset
<=
prop
->
val
.
len
);
refnode
=
get_node_by_ref
(
dt
,
m
->
ref
);
if
(
!
refnode
)
{
FAIL
(
c
,
dti
,
node
,
"Reference to non-existent node or label
\"
%s
\"\n
"
,
m
->
ref
);
continue
;
}
path
=
refnode
->
fullpath
;
prop
->
val
=
data_insert_at_marker
(
prop
->
val
,
m
,
path
,
strlen
(
path
)
+
1
);
}
}
}
ERROR
(
path_references
,
fixup_path_references
,
NULL
,
&
duplicate_node_names
);
/*
* Semantic checks
*/
WARNING_IF_NOT_CELL
(
address_cells_is_cell
,
"#address-cells"
);
WARNING_IF_NOT_CELL
(
size_cells_is_cell
,
"#size-cells"
);
WARNING_IF_NOT_CELL
(
interrupt_cells_is_cell
,
"#interrupt-cells"
);
WARNING_IF_NOT_STRING
(
device_type_is_string
,
"device_type"
);
WARNING_IF_NOT_STRING
(
model_is_string
,
"model"
);
WARNING_IF_NOT_STRING
(
status_is_string
,
"status"
);
WARNING_IF_NOT_STRING
(
label_is_string
,
"label"
);
WARNING_IF_NOT_STRING_LIST
(
compatible_is_string_list
,
"compatible"
);
static
void
check_names_is_string_list
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
for_each_property
(
node
,
prop
)
{
const
char
*
s
=
strrchr
(
prop
->
name
,
'-'
);
if
(
!
s
||
!
streq
(
s
,
"-names"
))
continue
;
c
->
data
=
prop
->
name
;
check_is_string_list
(
c
,
dti
,
node
);
}
}
WARNING
(
names_is_string_list
,
check_names_is_string_list
,
NULL
);
static
void
check_alias_paths
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
if
(
!
streq
(
node
->
name
,
"aliases"
))
return
;
for_each_property
(
node
,
prop
)
{
if
(
!
prop
->
val
.
val
||
!
get_node_by_path
(
dti
->
dt
,
prop
->
val
.
val
))
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"aliases property is not a valid node (%s)"
,
prop
->
val
.
val
);
continue
;
}
if
(
strspn
(
prop
->
name
,
LOWERCASE
DIGITS
"-"
)
!=
strlen
(
prop
->
name
))
FAIL
(
c
,
dti
,
node
,
"aliases property name must include only lowercase and '-'"
);
}
}
WARNING
(
alias_paths
,
check_alias_paths
,
NULL
);
static
void
fixup_addr_size_cells
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
node
->
addr_cells
=
-
1
;
node
->
size_cells
=
-
1
;
prop
=
get_property
(
node
,
"#address-cells"
);
if
(
prop
)
node
->
addr_cells
=
propval_cell
(
prop
);
prop
=
get_property
(
node
,
"#size-cells"
);
if
(
prop
)
node
->
size_cells
=
propval_cell
(
prop
);
}
WARNING
(
addr_size_cells
,
fixup_addr_size_cells
,
NULL
,
&
address_cells_is_cell
,
&
size_cells_is_cell
);
#define node_addr_cells(n) \
(((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
#define node_size_cells(n) \
(((n)->size_cells == -1) ? 1 : (n)->size_cells)
static
void
check_reg_format
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
int
addr_cells
,
size_cells
,
entrylen
;
prop
=
get_property
(
node
,
"reg"
);
if
(
!
prop
)
return
;
/* No "reg", that's fine */
if
(
!
node
->
parent
)
{
FAIL
(
c
,
dti
,
node
,
"Root node has a
\"
reg
\"
property"
);
return
;
}
if
(
prop
->
val
.
len
==
0
)
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"property is empty"
);
addr_cells
=
node_addr_cells
(
node
->
parent
);
size_cells
=
node_size_cells
(
node
->
parent
);
entrylen
=
(
addr_cells
+
size_cells
)
*
sizeof
(
cell_t
);
if
(
!
entrylen
||
(
prop
->
val
.
len
%
entrylen
)
!=
0
)
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"property has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)"
,
prop
->
val
.
len
,
addr_cells
,
size_cells
);
}
WARNING
(
reg_format
,
check_reg_format
,
NULL
,
&
addr_size_cells
);
static
void
check_ranges_format
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
int
c_addr_cells
,
p_addr_cells
,
c_size_cells
,
p_size_cells
,
entrylen
;
prop
=
get_property
(
node
,
"ranges"
);
if
(
!
prop
)
return
;
if
(
!
node
->
parent
)
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"Root node has a
\"
ranges
\"
property"
);
return
;
}
p_addr_cells
=
node_addr_cells
(
node
->
parent
);
p_size_cells
=
node_size_cells
(
node
->
parent
);
c_addr_cells
=
node_addr_cells
(
node
);
c_size_cells
=
node_size_cells
(
node
);
entrylen
=
(
p_addr_cells
+
c_addr_cells
+
c_size_cells
)
*
sizeof
(
cell_t
);
if
(
prop
->
val
.
len
==
0
)
{
if
(
p_addr_cells
!=
c_addr_cells
)
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"empty
\"
ranges
\"
property but its "
"#address-cells (%d) differs from %s (%d)"
,
c_addr_cells
,
node
->
parent
->
fullpath
,
p_addr_cells
);
if
(
p_size_cells
!=
c_size_cells
)
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"empty
\"
ranges
\"
property but its "
"#size-cells (%d) differs from %s (%d)"
,
c_size_cells
,
node
->
parent
->
fullpath
,
p_size_cells
);
}
else
if
((
prop
->
val
.
len
%
entrylen
)
!=
0
)
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"
\"
ranges
\"
property has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)"
,
prop
->
val
.
len
,
p_addr_cells
,
c_addr_cells
,
c_size_cells
);
}
}
WARNING
(
ranges_format
,
check_ranges_format
,
NULL
,
&
addr_size_cells
);
static
const
struct
bus_type
pci_bus
=
{
.
name
=
"PCI"
,
};
static
void
check_pci_bridge
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
cell_t
*
cells
;
prop
=
get_property
(
node
,
"device_type"
);
if
(
!
prop
||
!
streq
(
prop
->
val
.
val
,
"pci"
))
return
;
node
->
bus
=
&
pci_bus
;
if
(
!
strprefixeq
(
node
->
name
,
node
->
basenamelen
,
"pci"
)
&&
!
strprefixeq
(
node
->
name
,
node
->
basenamelen
,
"pcie"
))
FAIL
(
c
,
dti
,
node
,
"node name is not
\"
pci
\"
or
\"
pcie
\"
"
);
prop
=
get_property
(
node
,
"ranges"
);
if
(
!
prop
)
FAIL
(
c
,
dti
,
node
,
"missing ranges for PCI bridge (or not a bridge)"
);
if
(
node_addr_cells
(
node
)
!=
3
)
FAIL
(
c
,
dti
,
node
,
"incorrect #address-cells for PCI bridge"
);
if
(
node_size_cells
(
node
)
!=
2
)
FAIL
(
c
,
dti
,
node
,
"incorrect #size-cells for PCI bridge"
);
prop
=
get_property
(
node
,
"bus-range"
);
if
(
!
prop
)
{
FAIL
(
c
,
dti
,
node
,
"missing bus-range for PCI bridge"
);
return
;
}
if
(
prop
->
val
.
len
!=
(
sizeof
(
cell_t
)
*
2
))
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"value must be 2 cells"
);
return
;
}
cells
=
(
cell_t
*
)
prop
->
val
.
val
;
if
(
fdt32_to_cpu
(
cells
[
0
])
>
fdt32_to_cpu
(
cells
[
1
]))
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"1st cell must be less than or equal to 2nd cell"
);
if
(
fdt32_to_cpu
(
cells
[
1
])
>
0xff
)
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"maximum bus number must be less than 256"
);
}
WARNING
(
pci_bridge
,
check_pci_bridge
,
NULL
,
&
device_type_is_string
,
&
addr_size_cells
);
static
void
check_pci_device_bus_num
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
unsigned
int
bus_num
,
min_bus
,
max_bus
;
cell_t
*
cells
;
if
(
!
node
->
parent
||
(
node
->
parent
->
bus
!=
&
pci_bus
))
return
;
prop
=
get_property
(
node
,
"reg"
);
if
(
!
prop
)
return
;
cells
=
(
cell_t
*
)
prop
->
val
.
val
;
bus_num
=
(
fdt32_to_cpu
(
cells
[
0
])
&
0x00ff0000
)
>>
16
;
prop
=
get_property
(
node
->
parent
,
"bus-range"
);
if
(
!
prop
)
{
min_bus
=
max_bus
=
0
;
}
else
{
cells
=
(
cell_t
*
)
prop
->
val
.
val
;
min_bus
=
fdt32_to_cpu
(
cells
[
0
]);
max_bus
=
fdt32_to_cpu
(
cells
[
0
]);
}
if
((
bus_num
<
min_bus
)
||
(
bus_num
>
max_bus
))
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"PCI bus number %d out of range, expected (%d - %d)"
,
bus_num
,
min_bus
,
max_bus
);
}
WARNING
(
pci_device_bus_num
,
check_pci_device_bus_num
,
NULL
,
&
reg_format
,
&
pci_bridge
);
static
void
check_pci_device_reg
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
const
char
*
unitname
=
get_unitname
(
node
);
char
unit_addr
[
5
];
unsigned
int
dev
,
func
,
reg
;
cell_t
*
cells
;
if
(
!
node
->
parent
||
(
node
->
parent
->
bus
!=
&
pci_bus
))
return
;
prop
=
get_property
(
node
,
"reg"
);
if
(
!
prop
)
{
FAIL
(
c
,
dti
,
node
,
"missing PCI reg property"
);
return
;
}
cells
=
(
cell_t
*
)
prop
->
val
.
val
;
if
(
cells
[
1
]
||
cells
[
2
])
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"PCI reg config space address cells 2 and 3 must be 0"
);
reg
=
fdt32_to_cpu
(
cells
[
0
]);
dev
=
(
reg
&
0xf800
)
>>
11
;
func
=
(
reg
&
0x700
)
>>
8
;
if
(
reg
&
0xff000000
)
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"PCI reg address is not configuration space"
);
if
(
reg
&
0x000000ff
)
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"PCI reg config space address register number must be 0"
);
if
(
func
==
0
)
{
snprintf
(
unit_addr
,
sizeof
(
unit_addr
),
"%x"
,
dev
);
if
(
streq
(
unitname
,
unit_addr
))
return
;
}
snprintf
(
unit_addr
,
sizeof
(
unit_addr
),
"%x,%x"
,
dev
,
func
);
if
(
streq
(
unitname
,
unit_addr
))
return
;
FAIL
(
c
,
dti
,
node
,
"PCI unit address format error, expected
\"
%s
\"
"
,
unit_addr
);
}
WARNING
(
pci_device_reg
,
check_pci_device_reg
,
NULL
,
&
reg_format
,
&
pci_bridge
);
static
const
struct
bus_type
simple_bus
=
{
.
name
=
"simple-bus"
,
};
static
bool
node_is_compatible
(
struct
node
*
node
,
const
char
*
compat
)
{
struct
property
*
prop
;
const
char
*
str
,
*
end
;
prop
=
get_property
(
node
,
"compatible"
);
if
(
!
prop
)
return
false
;
for
(
str
=
prop
->
val
.
val
,
end
=
str
+
prop
->
val
.
len
;
str
<
end
;
str
+=
strnlen
(
str
,
end
-
str
)
+
1
)
{
if
(
strprefixeq
(
str
,
end
-
str
,
compat
))
return
true
;
}
return
false
;
}
static
void
check_simple_bus_bridge
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
if
(
node_is_compatible
(
node
,
"simple-bus"
))
node
->
bus
=
&
simple_bus
;
}
WARNING
(
simple_bus_bridge
,
check_simple_bus_bridge
,
NULL
,
&
addr_size_cells
);
static
void
check_simple_bus_reg
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
const
char
*
unitname
=
get_unitname
(
node
);
char
unit_addr
[
17
];
unsigned
int
size
;
uint64_t
reg
=
0
;
cell_t
*
cells
=
NULL
;
if
(
!
node
->
parent
||
(
node
->
parent
->
bus
!=
&
simple_bus
))
return
;
prop
=
get_property
(
node
,
"reg"
);
if
(
prop
)
cells
=
(
cell_t
*
)
prop
->
val
.
val
;
else
{
prop
=
get_property
(
node
,
"ranges"
);
if
(
prop
&&
prop
->
val
.
len
)
/* skip of child address */
cells
=
((
cell_t
*
)
prop
->
val
.
val
)
+
node_addr_cells
(
node
);
}
if
(
!
cells
)
{
if
(
node
->
parent
->
parent
&&
!
(
node
->
bus
==
&
simple_bus
))
FAIL
(
c
,
dti
,
node
,
"missing or empty reg/ranges property"
);
return
;
}
size
=
node_addr_cells
(
node
->
parent
);
while
(
size
--
)
reg
=
(
reg
<<
32
)
|
fdt32_to_cpu
(
*
(
cells
++
));
snprintf
(
unit_addr
,
sizeof
(
unit_addr
),
"%"
PRIx64
,
reg
);
if
(
!
streq
(
unitname
,
unit_addr
))
FAIL
(
c
,
dti
,
node
,
"simple-bus unit address format error, expected
\"
%s
\"
"
,
unit_addr
);
}
WARNING
(
simple_bus_reg
,
check_simple_bus_reg
,
NULL
,
&
reg_format
,
&
simple_bus_bridge
);
static
void
check_unit_address_format
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
const
char
*
unitname
=
get_unitname
(
node
);
if
(
node
->
parent
&&
node
->
parent
->
bus
)
return
;
if
(
!
unitname
[
0
])
return
;
if
(
!
strncmp
(
unitname
,
"0x"
,
2
))
{
FAIL
(
c
,
dti
,
node
,
"unit name should not have leading
\"
0x
\"
"
);
/* skip over 0x for next test */
unitname
+=
2
;
}
if
(
unitname
[
0
]
==
'0'
&&
isxdigit
(
unitname
[
1
]))
FAIL
(
c
,
dti
,
node
,
"unit name should not have leading 0s"
);
}
WARNING
(
unit_address_format
,
check_unit_address_format
,
NULL
,
&
node_name_format
,
&
pci_bridge
,
&
simple_bus_bridge
);
/*
* Style checks
*/
static
void
check_avoid_default_addr_size
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
reg
,
*
ranges
;
if
(
!
node
->
parent
)
return
;
/* Ignore root node */
reg
=
get_property
(
node
,
"reg"
);
ranges
=
get_property
(
node
,
"ranges"
);
if
(
!
reg
&&
!
ranges
)
return
;
if
(
node
->
parent
->
addr_cells
==
-
1
)
FAIL
(
c
,
dti
,
node
,
"Relying on default #address-cells value"
);
if
(
node
->
parent
->
size_cells
==
-
1
)
FAIL
(
c
,
dti
,
node
,
"Relying on default #size-cells value"
);
}
WARNING
(
avoid_default_addr_size
,
check_avoid_default_addr_size
,
NULL
,
&
addr_size_cells
);
static
void
check_avoid_unnecessary_addr_size
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
struct
node
*
child
;
bool
has_reg
=
false
;
if
(
!
node
->
parent
||
node
->
addr_cells
<
0
||
node
->
size_cells
<
0
)
return
;
if
(
get_property
(
node
,
"ranges"
)
||
!
node
->
children
)
return
;
for_each_child
(
node
,
child
)
{
prop
=
get_property
(
child
,
"reg"
);
if
(
prop
)
has_reg
=
true
;
}
if
(
!
has_reg
)
FAIL
(
c
,
dti
,
node
,
"unnecessary #address-cells/#size-cells without
\"
ranges
\"
or child
\"
reg
\"
property"
);
}
WARNING
(
avoid_unnecessary_addr_size
,
check_avoid_unnecessary_addr_size
,
NULL
,
&
avoid_default_addr_size
);
static
void
check_obsolete_chosen_interrupt_controller
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
dt
=
dti
->
dt
;
struct
node
*
chosen
;
struct
property
*
prop
;
if
(
node
!=
dt
)
return
;
chosen
=
get_node_by_path
(
dt
,
"/chosen"
);
if
(
!
chosen
)
return
;
prop
=
get_property
(
chosen
,
"interrupt-controller"
);
if
(
prop
)
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"/chosen has obsolete
\"
interrupt-controller
\"
property"
);
}
WARNING
(
obsolete_chosen_interrupt_controller
,
check_obsolete_chosen_interrupt_controller
,
NULL
);
static
void
check_chosen_node_is_root
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
if
(
!
streq
(
node
->
name
,
"chosen"
))
return
;
if
(
node
->
parent
!=
dti
->
dt
)
FAIL
(
c
,
dti
,
node
,
"chosen node must be at root node"
);
}
WARNING
(
chosen_node_is_root
,
check_chosen_node_is_root
,
NULL
);
static
void
check_chosen_node_bootargs
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
if
(
!
streq
(
node
->
name
,
"chosen"
))
return
;
prop
=
get_property
(
node
,
"bootargs"
);
if
(
!
prop
)
return
;
c
->
data
=
prop
->
name
;
check_is_string
(
c
,
dti
,
node
);
}
WARNING
(
chosen_node_bootargs
,
check_chosen_node_bootargs
,
NULL
);
static
void
check_chosen_node_stdout_path
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
if
(
!
streq
(
node
->
name
,
"chosen"
))
return
;
prop
=
get_property
(
node
,
"stdout-path"
);
if
(
!
prop
)
{
prop
=
get_property
(
node
,
"linux,stdout-path"
);
if
(
!
prop
)
return
;
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"Use 'stdout-path' instead"
);
}
c
->
data
=
prop
->
name
;
check_is_string
(
c
,
dti
,
node
);
}
WARNING
(
chosen_node_stdout_path
,
check_chosen_node_stdout_path
,
NULL
);
struct
provider
{
const
char
*
prop_name
;
const
char
*
cell_name
;
bool
optional
;
};
static
void
check_property_phandle_args
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
,
struct
property
*
prop
,
const
struct
provider
*
provider
)
{
struct
node
*
root
=
dti
->
dt
;
int
cell
,
cellsize
=
0
;
if
(
prop
->
val
.
len
%
sizeof
(
cell_t
))
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"property size (%d) is invalid, expected multiple of %zu"
,
prop
->
val
.
len
,
sizeof
(
cell_t
));
return
;
}
for
(
cell
=
0
;
cell
<
prop
->
val
.
len
/
sizeof
(
cell_t
);
cell
+=
cellsize
+
1
)
{
struct
node
*
provider_node
;
struct
property
*
cellprop
;
int
phandle
;
phandle
=
propval_cell_n
(
prop
,
cell
);
/*
* Some bindings use a cell value 0 or -1 to skip over optional
* entries when each index position has a specific definition.
*/
if
(
phandle
==
0
||
phandle
==
-
1
)
{
/* Give up if this is an overlay with external references */
if
(
dti
->
dtsflags
&
DTSF_PLUGIN
)
break
;
cellsize
=
0
;
continue
;
}
/* If we have markers, verify the current cell is a phandle */
if
(
prop
->
val
.
markers
)
{
struct
marker
*
m
=
prop
->
val
.
markers
;
for_each_marker_of_type
(
m
,
REF_PHANDLE
)
{
if
(
m
->
offset
==
(
cell
*
sizeof
(
cell_t
)))
break
;
}
if
(
!
m
)
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"cell %d is not a phandle reference"
,
cell
);
}
provider_node
=
get_node_by_phandle
(
root
,
phandle
);
if
(
!
provider_node
)
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"Could not get phandle node for (cell %d)"
,
cell
);
break
;
}
cellprop
=
get_property
(
provider_node
,
provider
->
cell_name
);
if
(
cellprop
)
{
cellsize
=
propval_cell
(
cellprop
);
}
else
if
(
provider
->
optional
)
{
cellsize
=
0
;
}
else
{
FAIL
(
c
,
dti
,
node
,
"Missing property '%s' in node %s or bad phandle (referred from %s[%d])"
,
provider
->
cell_name
,
provider_node
->
fullpath
,
prop
->
name
,
cell
);
break
;
}
if
(
prop
->
val
.
len
<
((
cell
+
cellsize
+
1
)
*
sizeof
(
cell_t
)))
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"property size (%d) too small for cell size %d"
,
prop
->
val
.
len
,
cellsize
);
}
}
}
static
void
check_provider_cells_property
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
provider
*
provider
=
c
->
data
;
struct
property
*
prop
;
prop
=
get_property
(
node
,
provider
->
prop_name
);
if
(
!
prop
)
return
;
check_property_phandle_args
(
c
,
dti
,
node
,
prop
,
provider
);
}
#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
WARNING_PROPERTY_PHANDLE_CELLS
(
clocks
,
"clocks"
,
"#clock-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
cooling_device
,
"cooling-device"
,
"#cooling-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
dmas
,
"dmas"
,
"#dma-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
hwlocks
,
"hwlocks"
,
"#hwlock-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
interrupts_extended
,
"interrupts-extended"
,
"#interrupt-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
io_channels
,
"io-channels"
,
"#io-channel-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
iommus
,
"iommus"
,
"#iommu-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
mboxes
,
"mboxes"
,
"#mbox-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
msi_parent
,
"msi-parent"
,
"#msi-cells"
,
true
);
WARNING_PROPERTY_PHANDLE_CELLS
(
mux_controls
,
"mux-controls"
,
"#mux-control-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
phys
,
"phys"
,
"#phy-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
power_domains
,
"power-domains"
,
"#power-domain-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
pwms
,
"pwms"
,
"#pwm-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
resets
,
"resets"
,
"#reset-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
sound_dai
,
"sound-dai"
,
"#sound-dai-cells"
);
WARNING_PROPERTY_PHANDLE_CELLS
(
thermal_sensors
,
"thermal-sensors"
,
"#thermal-sensor-cells"
);
static
bool
prop_is_gpio
(
struct
property
*
prop
)
{
char
*
str
;
/*
* *-gpios and *-gpio can appear in property names,
* so skip over any false matches (only one known ATM)
*/
if
(
strstr
(
prop
->
name
,
"nr-gpio"
))
return
false
;
str
=
strrchr
(
prop
->
name
,
'-'
);
if
(
str
)
str
++
;
else
str
=
prop
->
name
;
if
(
!
(
streq
(
str
,
"gpios"
)
||
streq
(
str
,
"gpio"
)))
return
false
;
return
true
;
}
static
void
check_gpios_property
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
/* Skip GPIO hog nodes which have 'gpios' property */
if
(
get_property
(
node
,
"gpio-hog"
))
return
;
for_each_property
(
node
,
prop
)
{
struct
provider
provider
;
if
(
!
prop_is_gpio
(
prop
))
continue
;
provider
.
prop_name
=
prop
->
name
;
provider
.
cell_name
=
"#gpio-cells"
;
provider
.
optional
=
false
;
check_property_phandle_args
(
c
,
dti
,
node
,
prop
,
&
provider
);
}
}
WARNING
(
gpios_property
,
check_gpios_property
,
NULL
,
&
phandle_references
);
static
void
check_deprecated_gpio_property
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
property
*
prop
;
for_each_property
(
node
,
prop
)
{
char
*
str
;
if
(
!
prop_is_gpio
(
prop
))
continue
;
str
=
strstr
(
prop
->
name
,
"gpio"
);
if
(
!
streq
(
str
,
"gpio"
))
continue
;
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"'[*-]gpio' is deprecated, use '[*-]gpios' instead"
);
}
}
CHECK
(
deprecated_gpio_property
,
check_deprecated_gpio_property
,
NULL
);
static
bool
node_is_interrupt_provider
(
struct
node
*
node
)
{
struct
property
*
prop
;
prop
=
get_property
(
node
,
"interrupt-controller"
);
if
(
prop
)
return
true
;
prop
=
get_property
(
node
,
"interrupt-map"
);
if
(
prop
)
return
true
;
return
false
;
}
static
void
check_interrupts_property
(
struct
check
*
c
,
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
root
=
dti
->
dt
;
struct
node
*
irq_node
=
NULL
,
*
parent
=
node
;
struct
property
*
irq_prop
,
*
prop
=
NULL
;
int
irq_cells
,
phandle
;
irq_prop
=
get_property
(
node
,
"interrupts"
);
if
(
!
irq_prop
)
return
;
if
(
irq_prop
->
val
.
len
%
sizeof
(
cell_t
))
FAIL_PROP
(
c
,
dti
,
node
,
irq_prop
,
"size (%d) is invalid, expected multiple of %zu"
,
irq_prop
->
val
.
len
,
sizeof
(
cell_t
));
while
(
parent
&&
!
prop
)
{
if
(
parent
!=
node
&&
node_is_interrupt_provider
(
parent
))
{
irq_node
=
parent
;
break
;
}
prop
=
get_property
(
parent
,
"interrupt-parent"
);
if
(
prop
)
{
phandle
=
propval_cell
(
prop
);
/* Give up if this is an overlay with external references */
if
((
phandle
==
0
||
phandle
==
-
1
)
&&
(
dti
->
dtsflags
&
DTSF_PLUGIN
))
return
;
irq_node
=
get_node_by_phandle
(
root
,
phandle
);
if
(
!
irq_node
)
{
FAIL_PROP
(
c
,
dti
,
parent
,
prop
,
"Bad phandle"
);
return
;
}
if
(
!
node_is_interrupt_provider
(
irq_node
))
FAIL
(
c
,
dti
,
irq_node
,
"Missing interrupt-controller or interrupt-map property"
);
break
;
}
parent
=
parent
->
parent
;
}
if
(
!
irq_node
)
{
FAIL
(
c
,
dti
,
node
,
"Missing interrupt-parent"
);
return
;
}
prop
=
get_property
(
irq_node
,
"#interrupt-cells"
);
if
(
!
prop
)
{
FAIL
(
c
,
dti
,
irq_node
,
"Missing #interrupt-cells in interrupt-parent"
);
return
;
}
irq_cells
=
propval_cell
(
prop
);
if
(
irq_prop
->
val
.
len
%
(
irq_cells
*
sizeof
(
cell_t
)))
{
FAIL_PROP
(
c
,
dti
,
node
,
prop
,
"size is (%d), expected multiple of %d"
,
irq_prop
->
val
.
len
,
(
int
)(
irq_cells
*
sizeof
(
cell_t
)));
}
}
WARNING
(
interrupts_property
,
check_interrupts_property
,
&
phandle_references
);
static
struct
check
*
check_table
[]
=
{
&
duplicate_node_names
,
&
duplicate_property_names
,
&
node_name_chars
,
&
node_name_format
,
&
property_name_chars
,
&
name_is_string
,
&
name_properties
,
&
duplicate_label
,
&
explicit_phandles
,
&
phandle_references
,
&
path_references
,
&
address_cells_is_cell
,
&
size_cells_is_cell
,
&
interrupt_cells_is_cell
,
&
device_type_is_string
,
&
model_is_string
,
&
status_is_string
,
&
label_is_string
,
&
compatible_is_string_list
,
&
names_is_string_list
,
&
property_name_chars_strict
,
&
node_name_chars_strict
,
&
addr_size_cells
,
&
reg_format
,
&
ranges_format
,
&
unit_address_vs_reg
,
&
unit_address_format
,
&
pci_bridge
,
&
pci_device_reg
,
&
pci_device_bus_num
,
&
simple_bus_bridge
,
&
simple_bus_reg
,
&
avoid_default_addr_size
,
&
avoid_unnecessary_addr_size
,
&
obsolete_chosen_interrupt_controller
,
&
chosen_node_is_root
,
&
chosen_node_bootargs
,
&
chosen_node_stdout_path
,
&
clocks_property
,
&
cooling_device_property
,
&
dmas_property
,
&
hwlocks_property
,
&
interrupts_extended_property
,
&
io_channels_property
,
&
iommus_property
,
&
mboxes_property
,
&
msi_parent_property
,
&
mux_controls_property
,
&
phys_property
,
&
power_domains_property
,
&
pwms_property
,
&
resets_property
,
&
sound_dai_property
,
&
thermal_sensors_property
,
&
deprecated_gpio_property
,
&
gpios_property
,
&
interrupts_property
,
&
alias_paths
,
&
always_fail
,
};
static
void
enable_warning_error
(
struct
check
*
c
,
bool
warn
,
bool
error
)
{
int
i
;
/* Raising level, also raise it for prereqs */
if
((
warn
&&
!
c
->
warn
)
||
(
error
&&
!
c
->
error
))
for
(
i
=
0
;
i
<
c
->
num_prereqs
;
i
++
)
enable_warning_error
(
c
->
prereq
[
i
],
warn
,
error
);
c
->
warn
=
c
->
warn
||
warn
;
c
->
error
=
c
->
error
||
error
;
}
static
void
disable_warning_error
(
struct
check
*
c
,
bool
warn
,
bool
error
)
{
int
i
;
/* Lowering level, also lower it for things this is the prereq
* for */
if
((
warn
&&
c
->
warn
)
||
(
error
&&
c
->
error
))
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
check_table
);
i
++
)
{
struct
check
*
cc
=
check_table
[
i
];
int
j
;
for
(
j
=
0
;
j
<
cc
->
num_prereqs
;
j
++
)
if
(
cc
->
prereq
[
j
]
==
c
)
disable_warning_error
(
cc
,
warn
,
error
);
}
}
c
->
warn
=
c
->
warn
&&
!
warn
;
c
->
error
=
c
->
error
&&
!
error
;
}
void
parse_checks_option
(
bool
warn
,
bool
error
,
const
char
*
arg
)
{
int
i
;
const
char
*
name
=
arg
;
bool
enable
=
true
;
if
((
strncmp
(
arg
,
"no-"
,
3
)
==
0
)
||
(
strncmp
(
arg
,
"no_"
,
3
)
==
0
))
{
name
=
arg
+
3
;
enable
=
false
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
check_table
);
i
++
)
{
struct
check
*
c
=
check_table
[
i
];
if
(
streq
(
c
->
name
,
name
))
{
if
(
enable
)
enable_warning_error
(
c
,
warn
,
error
);
else
disable_warning_error
(
c
,
warn
,
error
);
return
;
}
}
die
(
"Unrecognized check name
\"
%s
\"\n
"
,
name
);
}
void
process_checks
(
bool
force
,
struct
dt_info
*
dti
)
{
int
i
;
int
error
=
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
check_table
);
i
++
)
{
struct
check
*
c
=
check_table
[
i
];
if
(
c
->
warn
||
c
->
error
)
error
=
error
||
run_check
(
c
,
dti
);
}
if
(
error
)
{
if
(
!
force
)
{
fprintf
(
stderr
,
"ERROR: Input tree has errors, aborting "
"(use -f to force output)
\n
"
);
exit
(
2
);
}
else
if
(
quiet
<
3
)
{
fprintf
(
stderr
,
"Warning: Input tree has errors, "
"output forced
\n
"
);
}
}
}
u-boot-tree/scripts/dtc/data.c
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "dtc.h"
void
data_free
(
struct
data
d
)
{
struct
marker
*
m
,
*
nm
;
m
=
d
.
markers
;
while
(
m
)
{
nm
=
m
->
next
;
free
(
m
->
ref
);
free
(
m
);
m
=
nm
;
}
if
(
d
.
val
)
free
(
d
.
val
);
}
struct
data
data_grow_for
(
struct
data
d
,
int
xlen
)
{
struct
data
nd
;
int
newsize
;
if
(
xlen
==
0
)
return
d
;
nd
=
d
;
newsize
=
xlen
;
while
((
d
.
len
+
xlen
)
>
newsize
)
newsize
*=
2
;
nd
.
val
=
xrealloc
(
d
.
val
,
newsize
);
return
nd
;
}
struct
data
data_copy_mem
(
const
char
*
mem
,
int
len
)
{
struct
data
d
;
d
=
data_grow_for
(
empty_data
,
len
);
d
.
len
=
len
;
memcpy
(
d
.
val
,
mem
,
len
);
return
d
;
}
struct
data
data_copy_escape_string
(
const
char
*
s
,
int
len
)
{
int
i
=
0
;
struct
data
d
;
char
*
q
;
d
=
data_grow_for
(
empty_data
,
len
+
1
);
q
=
d
.
val
;
while
(
i
<
len
)
{
char
c
=
s
[
i
++
];
if
(
c
==
'\\'
)
c
=
get_escape_char
(
s
,
&
i
);
q
[
d
.
len
++
]
=
c
;
}
q
[
d
.
len
++
]
=
'\0'
;
return
d
;
}
struct
data
data_copy_file
(
FILE
*
f
,
size_t
maxlen
)
{
struct
data
d
=
empty_data
;
while
(
!
feof
(
f
)
&&
(
d
.
len
<
maxlen
))
{
size_t
chunksize
,
ret
;
if
(
maxlen
==
-
1
)
chunksize
=
4096
;
else
chunksize
=
maxlen
-
d
.
len
;
d
=
data_grow_for
(
d
,
chunksize
);
ret
=
fread
(
d
.
val
+
d
.
len
,
1
,
chunksize
,
f
);
if
(
ferror
(
f
))
die
(
"Error reading file into data: %s"
,
strerror
(
errno
));
if
(
d
.
len
+
ret
<
d
.
len
)
die
(
"Overflow reading file into data
\n
"
);
d
.
len
+=
ret
;
}
return
d
;
}
struct
data
data_append_data
(
struct
data
d
,
const
void
*
p
,
int
len
)
{
d
=
data_grow_for
(
d
,
len
);
memcpy
(
d
.
val
+
d
.
len
,
p
,
len
);
d
.
len
+=
len
;
return
d
;
}
struct
data
data_insert_at_marker
(
struct
data
d
,
struct
marker
*
m
,
const
void
*
p
,
int
len
)
{
d
=
data_grow_for
(
d
,
len
);
memmove
(
d
.
val
+
m
->
offset
+
len
,
d
.
val
+
m
->
offset
,
d
.
len
-
m
->
offset
);
memcpy
(
d
.
val
+
m
->
offset
,
p
,
len
);
d
.
len
+=
len
;
/* Adjust all markers after the one we're inserting at */
m
=
m
->
next
;
for_each_marker
(
m
)
m
->
offset
+=
len
;
return
d
;
}
static
struct
data
data_append_markers
(
struct
data
d
,
struct
marker
*
m
)
{
struct
marker
**
mp
=
&
d
.
markers
;
/* Find the end of the markerlist */
while
(
*
mp
)
mp
=
&
((
*
mp
)
->
next
);
*
mp
=
m
;
return
d
;
}
struct
data
data_merge
(
struct
data
d1
,
struct
data
d2
)
{
struct
data
d
;
struct
marker
*
m2
=
d2
.
markers
;
d
=
data_append_markers
(
data_append_data
(
d1
,
d2
.
val
,
d2
.
len
),
m2
);
/* Adjust for the length of d1 */
for_each_marker
(
m2
)
m2
->
offset
+=
d1
.
len
;
d2
.
markers
=
NULL
;
/* So data_free() doesn't clobber them */
data_free
(
d2
);
return
d
;
}
struct
data
data_append_integer
(
struct
data
d
,
uint64_t
value
,
int
bits
)
{
uint8_t
value_8
;
fdt16_t
value_16
;
fdt32_t
value_32
;
fdt64_t
value_64
;
switch
(
bits
)
{
case
8
:
value_8
=
value
;
return
data_append_data
(
d
,
&
value_8
,
1
);
case
16
:
value_16
=
cpu_to_fdt16
(
value
);
return
data_append_data
(
d
,
&
value_16
,
2
);
case
32
:
value_32
=
cpu_to_fdt32
(
value
);
return
data_append_data
(
d
,
&
value_32
,
4
);
case
64
:
value_64
=
cpu_to_fdt64
(
value
);
return
data_append_data
(
d
,
&
value_64
,
8
);
default:
die
(
"Invalid literal size (%d)
\n
"
,
bits
);
}
}
struct
data
data_append_re
(
struct
data
d
,
uint64_t
address
,
uint64_t
size
)
{
struct
fdt_reserve_entry
re
;
re
.
address
=
cpu_to_fdt64
(
address
);
re
.
size
=
cpu_to_fdt64
(
size
);
return
data_append_data
(
d
,
&
re
,
sizeof
(
re
));
}
struct
data
data_append_cell
(
struct
data
d
,
cell_t
word
)
{
return
data_append_integer
(
d
,
word
,
sizeof
(
word
)
*
8
);
}
struct
data
data_append_addr
(
struct
data
d
,
uint64_t
addr
)
{
return
data_append_integer
(
d
,
addr
,
sizeof
(
addr
)
*
8
);
}
struct
data
data_append_byte
(
struct
data
d
,
uint8_t
byte
)
{
return
data_append_data
(
d
,
&
byte
,
1
);
}
struct
data
data_append_zeroes
(
struct
data
d
,
int
len
)
{
d
=
data_grow_for
(
d
,
len
);
memset
(
d
.
val
+
d
.
len
,
0
,
len
);
d
.
len
+=
len
;
return
d
;
}
struct
data
data_append_align
(
struct
data
d
,
int
align
)
{
int
newlen
=
ALIGN
(
d
.
len
,
align
);
return
data_append_zeroes
(
d
,
newlen
-
d
.
len
);
}
struct
data
data_add_marker
(
struct
data
d
,
enum
markertype
type
,
char
*
ref
)
{
struct
marker
*
m
;
m
=
xmalloc
(
sizeof
(
*
m
));
m
->
offset
=
d
.
len
;
m
->
type
=
type
;
m
->
ref
=
ref
;
m
->
next
=
NULL
;
return
data_append_markers
(
d
,
m
);
}
bool
data_is_one_string
(
struct
data
d
)
{
int
i
;
int
len
=
d
.
len
;
if
(
len
==
0
)
return
false
;
for
(
i
=
0
;
i
<
len
-
1
;
i
++
)
if
(
d
.
val
[
i
]
==
'\0'
)
return
false
;
if
(
d
.
val
[
len
-
1
]
!=
'\0'
)
return
false
;
return
true
;
}
u-boot-tree/scripts/dtc/dtc-lexer.l
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
%option noyywrap nounput noinput never-interactive
%x BYTESTRING
%x PROPNODENAME
%s V1
PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
PATHCHAR ({PROPNODECHAR}|[/])
LABEL [a-zA-Z_][a-zA-Z0-9_]*
STRING \"([^\\"]|\\.)*\"
CHAR_LITERAL '([^']|\\')*'
WS [[:space:]]
COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
LINECOMMENT "//".*\n
%{
#include "dtc.h"
#include "srcpos.h"
#include "dtc-parser.tab.h"
YYLTYPE yylloc;
extern bool treesource_error;
/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
#define YY_USER_ACTION \
{ \
srcpos_update(&yylloc, yytext, yyleng); \
}
/*#define LEXDEBUG 1*/
#ifdef LEXDEBUG
#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
#else
#define DPRINT(fmt, ...) do { } while (0)
#endif
static int dts_version = 1;
#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \
BEGIN(V1); \
static void push_input_file(const char *filename);
static bool pop_input_file(void);
static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
%}
%%
<*>"/include/"{WS}*{STRING} {
char *name = strchr(yytext, '\"') + 1;
yytext[yyleng-1] = '\0';
push_input_file(name);
}
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
line = yytext;
while (!isdigit((unsigned char)*line))
line++;
/* regexp ensures that first and list "
* in the whole yytext are those at
* beginning and end of the filename string */
fnstart = memchr(yytext, '"', yyleng);
for (fnend = yytext + yyleng - 1;
*fnend != '"'; fnend--)
;
assert(fnstart && fnend && (fnend > fnstart));
fn = data_copy_escape_string(fnstart + 1,
fnend - fnstart - 1);
/* Don't allow nuls in filenames */
if (memchr(fn.val, '\0', fn.len - 1))
lexical_error("nul in line number directive");
/* -1 since #line is the number of the next line */
srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
data_free(fn);
}
<*><<EOF>> {
if (!pop_input_file()) {
yyterminate();
}
}
<*>{STRING} {
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
yyleng-2);
return DT_STRING;
}
<*>"/dts-v1/" {
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
BEGIN_DEFAULT();
return DT_V1;
}
<*>"/plugin/" {
DPRINT("Keyword: /plugin/\n");
return DT_PLUGIN;
}
<*>"/memreserve/" {
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
return DT_MEMRESERVE;
}
<*>"/bits/" {
DPRINT("Keyword: /bits/\n");
BEGIN_DEFAULT();
return DT_BITS;
}
<*>"/delete-property/" {
DPRINT("Keyword: /delete-property/\n");
DPRINT("<PROPNODENAME>\n");
BEGIN(PROPNODENAME);
return DT_DEL_PROP;
}
<*>"/delete-node/" {
DPRINT("Keyword: /delete-node/\n");
DPRINT("<PROPNODENAME>\n");
BEGIN(PROPNODENAME);
return DT_DEL_NODE;
}
<*>{LABEL}: {
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
yylval.labelref[yyleng-1] = '\0';
return DT_LABEL;
}
<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
char *e;
DPRINT("Integer Literal: '%s'\n", yytext);
errno = 0;
yylval.integer = strtoull(yytext, &e, 0);
if (*e && e[strspn(e, "UL")]) {
lexical_error("Bad integer literal '%s'",
yytext);
}
if (errno == ERANGE)
lexical_error("Integer literal '%s' out of range",
yytext);
else
/* ERANGE is the only strtoull error triggerable
* by strings matching the pattern */
assert(errno == 0);
return DT_LITERAL;
}
<*>{CHAR_LITERAL} {
struct data d;
DPRINT("Character literal: %s\n", yytext);
d = data_copy_escape_string(yytext+1, yyleng-2);
if (d.len == 1) {
lexical_error("Empty character literal");
yylval.integer = 0;
} else {
yylval.integer = (unsigned char)d.val[0];
if (d.len > 2)
lexical_error("Character literal has %d"
" characters instead of 1",
d.len - 1);
}
data_free(d);
return DT_CHAR_LITERAL;
}
<*>\&{LABEL} { /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
return DT_REF;
}
<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = xstrdup(yytext+2);
return DT_REF;
}
<BYTESTRING>[0-9a-fA-F]{2} {
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
return DT_BYTE;
}
<BYTESTRING>"]" {
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
return ']';
}
<PROPNODENAME>\\?{PROPNODECHAR}+ {
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = xstrdup((yytext[0] == '\\') ?
yytext + 1 : yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
"/incbin/" {
DPRINT("Binary Include\n");
return DT_INCBIN;
}
<*>{WS}+ /* eat whitespace */
<*>{COMMENT}+ /* eat C-style comments */
<*>{LINECOMMENT}+ /* eat C++-style comments */
<*>"<<" { return DT_LSHIFT; };
<*>">>" { return DT_RSHIFT; };
<*>"<=" { return DT_LE; };
<*>">=" { return DT_GE; };
<*>"==" { return DT_EQ; };
<*>"!=" { return DT_NE; };
<*>"&&" { return DT_AND; };
<*>"||" { return DT_OR; };
<*>. {
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
if (yytext[0] == '[') {
DPRINT("<BYTESTRING>\n");
BEGIN(BYTESTRING);
}
if ((yytext[0] == '{')
|| (yytext[0] == ';')) {
DPRINT("<PROPNODENAME>\n");
BEGIN(PROPNODENAME);
}
return yytext[0];
}
%%
static void push_input_file(const char *filename)
{
assert(filename);
srcfile_push(filename);
yyin = current_srcfile->f;
yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
}
static bool pop_input_file(void)
{
if (srcfile_pop() == 0)
return false;
yypop_buffer_state();
yyin = current_srcfile->f;
return true;
}
static void lexical_error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
srcpos_verror(&yylloc, "Lexical error", fmt, ap);
va_end(ap);
treesource_error = true;
}
u-boot-tree/scripts/dtc/dtc-parser.y
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
%{
#include <stdio.h>
#include <inttypes.h>
#include "dtc.h"
#include "srcpos.h"
extern int yylex(void);
extern void yyerror(char const *s);
#define ERROR(loc, ...) \
do { \
srcpos_error((loc), "Error", __VA_ARGS__); \
treesource_error = true; \
} while (0)
extern struct dt_info *parser_output;
extern bool treesource_error;
%}
%union {
char *propnodename;
char *labelref;
uint8_t byte;
struct data data;
struct {
struct data data;
int bits;
} array;
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
uint64_t integer;
unsigned int flags;
}
%token DT_V1
%token DT_PLUGIN
%token DT_MEMRESERVE
%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
%token DT_BITS
%token DT_DEL_PROP
%token DT_DEL_NODE
%token <propnodename> DT_PROPNODENAME
%token <integer> DT_LITERAL
%token <integer> DT_CHAR_LITERAL
%token <byte> DT_BYTE
%token <data> DT_STRING
%token <labelref> DT_LABEL
%token <labelref> DT_REF
%token DT_INCBIN
%type <data> propdata
%type <data> propdataprefix
%type <flags> header
%type <flags> headers
%type <re> memreserve
%type <re> memreserves
%type <array> arrayprefix
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist
%type <node> devicetree
%type <node> nodedef
%type <node> subnode
%type <nodelist> subnodes
%type <integer> integer_prim
%type <integer> integer_unary
%type <integer> integer_mul
%type <integer> integer_add
%type <integer> integer_shift
%type <integer> integer_rela
%type <integer> integer_eq
%type <integer> integer_bitand
%type <integer> integer_bitxor
%type <integer> integer_bitor
%type <integer> integer_and
%type <integer> integer_or
%type <integer> integer_trinary
%type <integer> integer_expr
%%
sourcefile:
headers memreserves devicetree
{
parser_output = build_dt_info($1, $2, $3,
guess_boot_cpuid($3));
}
;
header:
DT_V1 ';'
{
$$ = DTSF_V1;
}
| DT_V1 ';' DT_PLUGIN ';'
{
$$ = DTSF_V1 | DTSF_PLUGIN;
}
;
headers:
header
| header headers
{
if ($2 != $1)
ERROR(&@2, "Header flags don't match earlier ones");
$$ = $1;
}
;
memreserves:
/* empty */
{
$$ = NULL;
}
| memreserve memreserves
{
$$ = chain_reserve_entry($1, $2);
}
;
memreserve:
DT_MEMRESERVE integer_prim integer_prim ';'
{
$$ = build_reserve_entry($2, $3);
}
| DT_LABEL memreserve
{
add_label(&$2->labels, $1);
$$ = $2;
}
;
devicetree:
'/' nodedef
{
$$ = name_node($2, "");
}
| devicetree '/' nodedef
{
$$ = merge_nodes($1, $3);
}
| DT_REF nodedef
{
/*
* We rely on the rule being always:
* versioninfo plugindecl memreserves devicetree
* so $-1 is what we want (plugindecl)
*/
if (!($<flags>-1 & DTSF_PLUGIN))
ERROR(&@2, "Label or path %s not found", $1);
$$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1);
}
| devicetree DT_LABEL DT_REF nodedef
{
struct node *target = get_node_by_ref($1, $3);
if (target) {
add_label(&target->labels, $2);
merge_nodes(target, $4);
} else
ERROR(&@3, "Label or path %s not found", $3);
$$ = $1;
}
| devicetree DT_REF nodedef
{
struct node *target = get_node_by_ref($1, $2);
if (target) {
merge_nodes(target, $3);
} else {
/*
* We rely on the rule being always:
* versioninfo plugindecl memreserves devicetree
* so $-1 is what we want (plugindecl)
*/
if ($<flags>-1 & DTSF_PLUGIN)
add_orphan_node($1, $3, $2);
else
ERROR(&@2, "Label or path %s not found", $2);
}
$$ = $1;
}
| devicetree DT_DEL_NODE DT_REF ';'
{
struct node *target = get_node_by_ref($1, $3);
if (target)
delete_node(target);
else
ERROR(&@3, "Label or path %s not found", $3);
$$ = $1;
}
;
nodedef:
'{' proplist subnodes '}' ';'
{
$$ = build_node($2, $3);
}
;
proplist:
/* empty */
{
$$ = NULL;
}
| proplist propdef
{
$$ = chain_property($2, $1);
}
;
propdef:
DT_PROPNODENAME '=' propdata ';'
{
$$ = build_property($1, $3);
}
| DT_PROPNODENAME ';'
{
$$ = build_property($1, empty_data);
}
| DT_DEL_PROP DT_PROPNODENAME ';'
{
$$ = build_property_delete($2);
}
| DT_LABEL propdef
{
add_label(&$2->labels, $1);
$$ = $2;
}
;
propdata:
propdataprefix DT_STRING
{
$$ = data_merge($1, $2);
}
| propdataprefix arrayprefix '>'
{
$$ = data_merge($1, $2.data);
}
| propdataprefix '[' bytestring ']'
{
$$ = data_merge($1, $3);
}
| propdataprefix DT_REF
{
$$ = data_add_marker($1, REF_PATH, $2);
}
| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
{
FILE *f = srcfile_relative_open($4.val, NULL);
struct data d;
if ($6 != 0)
if (fseek(f, $6, SEEK_SET) != 0)
die("Couldn't seek to offset %llu in \"%s\": %s",
(unsigned long long)$6, $4.val,
strerror(errno));
d = data_copy_file(f, $8);
$$ = data_merge($1, d);
fclose(f);
}
| propdataprefix DT_INCBIN '(' DT_STRING ')'
{
FILE *f = srcfile_relative_open($4.val, NULL);
struct data d = empty_data;
d = data_copy_file(f, -1);
$$ = data_merge($1, d);
fclose(f);
}
| propdata DT_LABEL
{
$$ = data_add_marker($1, LABEL, $2);
}
;
propdataprefix:
/* empty */
{
$$ = empty_data;
}
| propdata ','
{
$$ = $1;
}
| propdataprefix DT_LABEL
{
$$ = data_add_marker($1, LABEL, $2);
}
;
arrayprefix:
DT_BITS DT_LITERAL '<'
{
unsigned long long bits;
bits = $2;
if ((bits != 8) && (bits != 16) &&
(bits != 32) && (bits != 64)) {
ERROR(&@2, "Array elements must be"
" 8, 16, 32 or 64-bits");
bits = 32;
}
$$.data = empty_data;
$$.bits = bits;
}
| '<'
{
$$.data = empty_data;
$$.bits = 32;
}
| arrayprefix integer_prim
{
if ($1.bits < 64) {
uint64_t mask = (1ULL << $1.bits) - 1;
/*
* Bits above mask must either be all zero
* (positive within range of mask) or all one
* (negative and sign-extended). The second
* condition is true if when we set all bits
* within the mask to one (i.e. | in the
* mask), all bits are one.
*/
if (($2 > mask) && (($2 | mask) != -1ULL))
ERROR(&@2, "Value out of range for"
" %d-bit array element", $1.bits);
}
$$.data = data_append_integer($1.data, $2, $1.bits);
}
| arrayprefix DT_REF
{
uint64_t val = ~0ULL >> (64 - $1.bits);
if ($1.bits == 32)
$1.data = data_add_marker($1.data,
REF_PHANDLE,
$2);
else
ERROR(&@2, "References are only allowed in "
"arrays with 32-bit elements.");
$$.data = data_append_integer($1.data, val, $1.bits);
}
| arrayprefix DT_LABEL
{
$$.data = data_add_marker($1.data, LABEL, $2);
}
;
integer_prim:
DT_LITERAL
| DT_CHAR_LITERAL
| '(' integer_expr ')'
{
$$ = $2;
}
;
integer_expr:
integer_trinary
;
integer_trinary:
integer_or
| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
;
integer_or:
integer_and
| integer_or DT_OR integer_and { $$ = $1 || $3; }
;
integer_and:
integer_bitor
| integer_and DT_AND integer_bitor { $$ = $1 && $3; }
;
integer_bitor:
integer_bitxor
| integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
;
integer_bitxor:
integer_bitand
| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
;
integer_bitand:
integer_eq
| integer_bitand '&' integer_eq { $$ = $1 & $3; }
;
integer_eq:
integer_rela
| integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
| integer_eq DT_NE integer_rela { $$ = $1 != $3; }
;
integer_rela:
integer_shift
| integer_rela '<' integer_shift { $$ = $1 < $3; }
| integer_rela '>' integer_shift { $$ = $1 > $3; }
| integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
| integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
;
integer_shift:
integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
| integer_add
;
integer_add:
integer_add '+' integer_mul { $$ = $1 + $3; }
| integer_add '-' integer_mul { $$ = $1 - $3; }
| integer_mul
;
integer_mul:
integer_mul '*' integer_unary { $$ = $1 * $3; }
| integer_mul '/' integer_unary
{
if ($3 != 0) {
$$ = $1 / $3;
} else {
ERROR(&@$, "Division by zero");
$$ = 0;
}
}
| integer_mul '%' integer_unary
{
if ($3 != 0) {
$$ = $1 % $3;
} else {
ERROR(&@$, "Division by zero");
$$ = 0;
}
}
| integer_unary
;
integer_unary:
integer_prim
| '-' integer_unary { $$ = -$2; }
| '~' integer_unary { $$ = ~$2; }
| '!' integer_unary { $$ = !$2; }
;
bytestring:
/* empty */
{
$$ = empty_data;
}
| bytestring DT_BYTE
{
$$ = data_append_byte($1, $2);
}
| bytestring DT_LABEL
{
$$ = data_add_marker($1, LABEL, $2);
}
;
subnodes:
/* empty */
{
$$ = NULL;
}
| subnode subnodes
{
$$ = chain_node($1, $2);
}
| subnode propdef
{
ERROR(&@2, "Properties must precede subnodes");
YYERROR;
}
;
subnode:
DT_PROPNODENAME nodedef
{
$$ = name_node($2, $1);
}
| DT_DEL_NODE DT_PROPNODENAME ';'
{
$$ = name_node(build_node_delete(), $2);
}
| DT_LABEL subnode
{
add_label(&$2->labels, $1);
$$ = $2;
}
;
%%
void yyerror(char const *s)
{
ERROR(&yylloc, "%s", s);
}
u-boot-tree/scripts/dtc/dtc.c
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <sys/stat.h>
#include "dtc.h"
#include "srcpos.h"
/*
* Command line options
*/
int
quiet
;
/* Level of quietness */
int
reservenum
;
/* Number of memory reservation slots */
int
minsize
;
/* Minimum blob size */
int
padsize
;
/* Additional padding to blob */
int
alignsize
;
/* Additional padding to blob accroding to the alignsize */
int
phandle_format
=
PHANDLE_EPAPR
;
/* Use linux,phandle or phandle properties */
int
generate_symbols
;
/* enable symbols & fixup support */
int
generate_fixups
;
/* suppress generation of fixups on symbol support */
int
auto_label_aliases
;
/* auto generate labels -> aliases */
static
int
is_power_of_2
(
int
x
)
{
return
(
x
>
0
)
&&
((
x
&
(
x
-
1
))
==
0
);
}
static
void
fill_fullpaths
(
struct
node
*
tree
,
const
char
*
prefix
)
{
struct
node
*
child
;
const
char
*
unit
;
tree
->
fullpath
=
join_path
(
prefix
,
tree
->
name
);
unit
=
strchr
(
tree
->
name
,
'@'
);
if
(
unit
)
tree
->
basenamelen
=
unit
-
tree
->
name
;
else
tree
->
basenamelen
=
strlen
(
tree
->
name
);
for_each_child
(
tree
,
child
)
fill_fullpaths
(
child
,
tree
->
fullpath
);
}
/* Usage related data. */
static
const
char
usage_synopsis
[]
=
"dtc [options] <input file>"
;
static
const
char
usage_short_opts
[]
=
"qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv"
;
static
struct
option
const
usage_long_opts
[]
=
{
{
"quiet"
,
no_argument
,
NULL
,
'q'
},
{
"in-format"
,
a_argument
,
NULL
,
'I'
},
{
"out"
,
a_argument
,
NULL
,
'o'
},
{
"out-format"
,
a_argument
,
NULL
,
'O'
},
{
"out-version"
,
a_argument
,
NULL
,
'V'
},
{
"out-dependency"
,
a_argument
,
NULL
,
'd'
},
{
"reserve"
,
a_argument
,
NULL
,
'R'
},
{
"space"
,
a_argument
,
NULL
,
'S'
},
{
"pad"
,
a_argument
,
NULL
,
'p'
},
{
"align"
,
a_argument
,
NULL
,
'a'
},
{
"boot-cpu"
,
a_argument
,
NULL
,
'b'
},
{
"force"
,
no_argument
,
NULL
,
'f'
},
{
"include"
,
a_argument
,
NULL
,
'i'
},
{
"sort"
,
no_argument
,
NULL
,
's'
},
{
"phandle"
,
a_argument
,
NULL
,
'H'
},
{
"warning"
,
a_argument
,
NULL
,
'W'
},
{
"error"
,
a_argument
,
NULL
,
'E'
},
{
"symbols"
,
no_argument
,
NULL
,
'@'
},
{
"auto-alias"
,
no_argument
,
NULL
,
'A'
},
{
"help"
,
no_argument
,
NULL
,
'h'
},
{
"version"
,
no_argument
,
NULL
,
'v'
},
{
NULL
,
no_argument
,
NULL
,
0x0
},
};
static
const
char
*
const
usage_opts_help
[]
=
{
"
\n\t
Quiet: -q suppress warnings, -qq errors, -qqq all"
,
"
\n\t
Input formats are:
\n
"
"
\t\t
dts - device tree source text
\n
"
"
\t\t
dtb - device tree blob
\n
"
"
\t\t
fs - /proc/device-tree style directory"
,
"
\n\t
Output file"
,
"
\n\t
Output formats are:
\n
"
"
\t\t
dts - device tree source text
\n
"
"
\t\t
dtb - device tree blob
\n
"
"
\t\t
asm - assembler source"
,
"
\n\t
Blob version to produce, defaults to "
stringify
(
DEFAULT_FDT_VERSION
)
" (for dtb and asm output)"
,
"
\n\t
Output dependency file"
,
"
\n\t
Make space for <number> reserve map entries (for dtb and asm output)"
,
"
\n\t
Make the blob at least <bytes> long (extra space)"
,
"
\n\t
Add padding to the blob of <bytes> long (extra space)"
,
"
\n\t
Make the blob align to the <bytes> (extra space)"
,
"
\n\t
Set the physical boot cpu"
,
"
\n\t
Try to produce output even if the input tree has errors"
,
"
\n\t
Add a path to search for include files"
,
"
\n\t
Sort nodes and properties before outputting (useful for comparing trees)"
,
"
\n\t
Valid phandle formats are:
\n
"
"
\t\t
legacy -
\"
linux,phandle
\"
properties only
\n
"
"
\t\t
epapr -
\"
phandle
\"
properties only
\n
"
"
\t\t
both - Both
\"
linux,phandle
\"
and
\"
phandle
\"
properties"
,
"
\n\t
Enable/disable warnings (prefix with
\"
no-
\"
)"
,
"
\n\t
Enable/disable errors (prefix with
\"
no-
\"
)"
,
"
\n\t
Enable generation of symbols"
,
"
\n\t
Enable auto-alias of labels"
,
"
\n\t
Print this help and exit"
,
"
\n\t
Print version and exit"
,
NULL
,
};
static
const
char
*
guess_type_by_name
(
const
char
*
fname
,
const
char
*
fallback
)
{
const
char
*
s
;
s
=
strrchr
(
fname
,
'.'
);
if
(
s
==
NULL
)
return
fallback
;
if
(
!
strcasecmp
(
s
,
".dts"
))
return
"dts"
;
if
(
!
strcasecmp
(
s
,
".dtb"
))
return
"dtb"
;
return
fallback
;
}
static
const
char
*
guess_input_format
(
const
char
*
fname
,
const
char
*
fallback
)
{
struct
stat
statbuf
;
fdt32_t
magic
;
FILE
*
f
;
if
(
stat
(
fname
,
&
statbuf
)
!=
0
)
return
fallback
;
if
(
S_ISDIR
(
statbuf
.
st_mode
))
return
"fs"
;
if
(
!
S_ISREG
(
statbuf
.
st_mode
))
return
fallback
;
f
=
fopen
(
fname
,
"r"
);
if
(
f
==
NULL
)
return
fallback
;
if
(
fread
(
&
magic
,
4
,
1
,
f
)
!=
1
)
{
fclose
(
f
);
return
fallback
;
}
fclose
(
f
);
if
(
fdt32_to_cpu
(
magic
)
==
FDT_MAGIC
)
return
"dtb"
;
return
guess_type_by_name
(
fname
,
fallback
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
struct
dt_info
*
dti
;
const
char
*
inform
=
NULL
;
const
char
*
outform
=
NULL
;
const
char
*
outname
=
"-"
;
const
char
*
depname
=
NULL
;
bool
force
=
false
,
sort
=
false
;
const
char
*
arg
;
int
opt
;
FILE
*
outf
=
NULL
;
int
outversion
=
DEFAULT_FDT_VERSION
;
long
long
cmdline_boot_cpuid
=
-
1
;
quiet
=
0
;
reservenum
=
0
;
minsize
=
0
;
padsize
=
0
;
alignsize
=
0
;
while
((
opt
=
util_getopt_long
())
!=
EOF
)
{
switch
(
opt
)
{
case
'I'
:
inform
=
optarg
;
break
;
case
'O'
:
outform
=
optarg
;
break
;
case
'o'
:
outname
=
optarg
;
break
;
case
'V'
:
outversion
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
'd'
:
depname
=
optarg
;
break
;
case
'R'
:
reservenum
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
'S'
:
minsize
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
'p'
:
padsize
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
'a'
:
alignsize
=
strtol
(
optarg
,
NULL
,
0
);
if
(
!
is_power_of_2
(
alignsize
))
die
(
"Invalid argument
\"
%d
\"
to -a option
\n
"
,
alignsize
);
break
;
case
'f'
:
force
=
true
;
break
;
case
'q'
:
quiet
++
;
break
;
case
'b'
:
cmdline_boot_cpuid
=
strtoll
(
optarg
,
NULL
,
0
);
break
;
case
'i'
:
srcfile_add_search_path
(
optarg
);
break
;
case
'v'
:
util_version
();
case
'H'
:
if
(
streq
(
optarg
,
"legacy"
))
phandle_format
=
PHANDLE_LEGACY
;
else
if
(
streq
(
optarg
,
"epapr"
))
phandle_format
=
PHANDLE_EPAPR
;
else
if
(
streq
(
optarg
,
"both"
))
phandle_format
=
PHANDLE_BOTH
;
else
die
(
"Invalid argument
\"
%s
\"
to -H option
\n
"
,
optarg
);
break
;
case
's'
:
sort
=
true
;
break
;
case
'W'
:
parse_checks_option
(
true
,
false
,
optarg
);
break
;
case
'E'
:
parse_checks_option
(
false
,
true
,
optarg
);
break
;
case
'@'
:
generate_symbols
=
1
;
break
;
case
'A'
:
auto_label_aliases
=
1
;
break
;
case
'h'
:
usage
(
NULL
);
default:
usage
(
"unknown option"
);
}
}
if
(
argc
>
(
optind
+
1
))
usage
(
"missing files"
);
else
if
(
argc
<
(
optind
+
1
))
arg
=
"-"
;
else
arg
=
argv
[
optind
];
/* minsize and padsize are mutually exclusive */
if
(
minsize
&&
padsize
)
die
(
"Can't set both -p and -S
\n
"
);
if
(
depname
)
{
depfile
=
fopen
(
depname
,
"w"
);
if
(
!
depfile
)
die
(
"Couldn't open dependency file %s: %s
\n
"
,
depname
,
strerror
(
errno
));
fprintf
(
depfile
,
"%s:"
,
outname
);
}
if
(
inform
==
NULL
)
inform
=
guess_input_format
(
arg
,
"dts"
);
if
(
outform
==
NULL
)
{
outform
=
guess_type_by_name
(
outname
,
NULL
);
if
(
outform
==
NULL
)
{
if
(
streq
(
inform
,
"dts"
))
outform
=
"dtb"
;
else
outform
=
"dts"
;
}
}
if
(
streq
(
inform
,
"dts"
))
dti
=
dt_from_source
(
arg
);
else
if
(
streq
(
inform
,
"fs"
))
dti
=
dt_from_fs
(
arg
);
else
if
(
streq
(
inform
,
"dtb"
))
dti
=
dt_from_blob
(
arg
);
else
die
(
"Unknown input format
\"
%s
\"\n
"
,
inform
);
dti
->
outname
=
outname
;
if
(
depfile
)
{
fputc
(
'\n'
,
depfile
);
fclose
(
depfile
);
}
if
(
cmdline_boot_cpuid
!=
-
1
)
dti
->
boot_cpuid_phys
=
cmdline_boot_cpuid
;
fill_fullpaths
(
dti
->
dt
,
""
);
/* on a plugin, generate by default */
if
(
dti
->
dtsflags
&
DTSF_PLUGIN
)
{
generate_fixups
=
1
;
}
process_checks
(
force
,
dti
);
if
(
auto_label_aliases
)
generate_label_tree
(
dti
,
"aliases"
,
false
);
if
(
generate_symbols
)
generate_label_tree
(
dti
,
"__symbols__"
,
true
);
if
(
generate_fixups
)
{
generate_fixups_tree
(
dti
,
"__fixups__"
);
generate_local_fixups_tree
(
dti
,
"__local_fixups__"
);
}
if
(
sort
)
sort_tree
(
dti
);
if
(
streq
(
outname
,
"-"
))
{
outf
=
stdout
;
}
else
{
outf
=
fopen
(
outname
,
"wb"
);
if
(
!
outf
)
die
(
"Couldn't open output file %s: %s
\n
"
,
outname
,
strerror
(
errno
));
}
if
(
streq
(
outform
,
"dts"
))
{
dt_to_source
(
outf
,
dti
);
}
else
if
(
streq
(
outform
,
"dtb"
))
{
dt_to_blob
(
outf
,
dti
,
outversion
);
}
else
if
(
streq
(
outform
,
"asm"
))
{
dt_to_asm
(
outf
,
dti
,
outversion
);
}
else
if
(
streq
(
outform
,
"null"
))
{
/* do nothing */
}
else
{
die
(
"Unknown output format
\"
%s
\"\n
"
,
outform
);
}
exit
(
0
);
}
u-boot-tree/scripts/dtc/dtc.h
deleted
100644 → 0
View file @
3e304607
#ifndef DTC_H
#define DTC_H
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <inttypes.h>
#include <libfdt_env.h>
#include <fdt.h>
#include "util.h"
#ifdef DEBUG
#define debug(...) printf(__VA_ARGS__)
#else
#define debug(...)
#endif
#define DEFAULT_FDT_VERSION 17
/*
* Command line options
*/
extern
int
quiet
;
/* Level of quietness */
extern
int
reservenum
;
/* Number of memory reservation slots */
extern
int
minsize
;
/* Minimum blob size */
extern
int
padsize
;
/* Additional padding to blob */
extern
int
alignsize
;
/* Additional padding to blob accroding to the alignsize */
extern
int
phandle_format
;
/* Use linux,phandle or phandle properties */
extern
int
generate_symbols
;
/* generate symbols for nodes with labels */
extern
int
generate_fixups
;
/* generate fixups */
extern
int
auto_label_aliases
;
/* auto generate labels -> aliases */
#define PHANDLE_LEGACY 0x1
#define PHANDLE_EPAPR 0x2
#define PHANDLE_BOTH 0x3
typedef
uint32_t
cell_t
;
#define streq(a, b) (strcmp((a), (b)) == 0)
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
/* Data blobs */
enum
markertype
{
REF_PHANDLE
,
REF_PATH
,
LABEL
,
};
struct
marker
{
enum
markertype
type
;
int
offset
;
char
*
ref
;
struct
marker
*
next
;
};
struct
data
{
int
len
;
char
*
val
;
struct
marker
*
markers
;
};
#define empty_data ((struct data){ 0
/* all .members = 0 or NULL */
})
#define for_each_marker(m) \
for (; (m); (m) = (m)->next)
#define for_each_marker_of_type(m, t) \
for_each_marker(m) \
if ((m)->type == (t))
void
data_free
(
struct
data
d
);
struct
data
data_grow_for
(
struct
data
d
,
int
xlen
);
struct
data
data_copy_mem
(
const
char
*
mem
,
int
len
);
struct
data
data_copy_escape_string
(
const
char
*
s
,
int
len
);
struct
data
data_copy_file
(
FILE
*
f
,
size_t
len
);
struct
data
data_append_data
(
struct
data
d
,
const
void
*
p
,
int
len
);
struct
data
data_insert_at_marker
(
struct
data
d
,
struct
marker
*
m
,
const
void
*
p
,
int
len
);
struct
data
data_merge
(
struct
data
d1
,
struct
data
d2
);
struct
data
data_append_cell
(
struct
data
d
,
cell_t
word
);
struct
data
data_append_integer
(
struct
data
d
,
uint64_t
word
,
int
bits
);
struct
data
data_append_re
(
struct
data
d
,
uint64_t
address
,
uint64_t
size
);
struct
data
data_append_addr
(
struct
data
d
,
uint64_t
addr
);
struct
data
data_append_byte
(
struct
data
d
,
uint8_t
byte
);
struct
data
data_append_zeroes
(
struct
data
d
,
int
len
);
struct
data
data_append_align
(
struct
data
d
,
int
align
);
struct
data
data_add_marker
(
struct
data
d
,
enum
markertype
type
,
char
*
ref
);
bool
data_is_one_string
(
struct
data
d
);
/* DT constraints */
#define MAX_PROPNAME_LEN 31
#define MAX_NODENAME_LEN 31
/* Live trees */
struct
label
{
bool
deleted
;
char
*
label
;
struct
label
*
next
;
};
struct
bus_type
{
const
char
*
name
;
};
struct
property
{
bool
deleted
;
char
*
name
;
struct
data
val
;
struct
property
*
next
;
struct
label
*
labels
;
};
struct
node
{
bool
deleted
;
char
*
name
;
struct
property
*
proplist
;
struct
node
*
children
;
struct
node
*
parent
;
struct
node
*
next_sibling
;
char
*
fullpath
;
int
basenamelen
;
cell_t
phandle
;
int
addr_cells
,
size_cells
;
struct
label
*
labels
;
const
struct
bus_type
*
bus
;
};
#define for_each_label_withdel(l0, l) \
for ((l) = (l0); (l); (l) = (l)->next)
#define for_each_label(l0, l) \
for_each_label_withdel(l0, l) \
if (!(l)->deleted)
#define for_each_property_withdel(n, p) \
for ((p) = (n)->proplist; (p); (p) = (p)->next)
#define for_each_property(n, p) \
for_each_property_withdel(n, p) \
if (!(p)->deleted)
#define for_each_child_withdel(n, c) \
for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
#define for_each_child(n, c) \
for_each_child_withdel(n, c) \
if (!(c)->deleted)
void
add_label
(
struct
label
**
labels
,
char
*
label
);
void
delete_labels
(
struct
label
**
labels
);
struct
property
*
build_property
(
char
*
name
,
struct
data
val
);
struct
property
*
build_property_delete
(
char
*
name
);
struct
property
*
chain_property
(
struct
property
*
first
,
struct
property
*
list
);
struct
property
*
reverse_properties
(
struct
property
*
first
);
struct
node
*
build_node
(
struct
property
*
proplist
,
struct
node
*
children
);
struct
node
*
build_node_delete
(
void
);
struct
node
*
name_node
(
struct
node
*
node
,
char
*
name
);
struct
node
*
chain_node
(
struct
node
*
first
,
struct
node
*
list
);
struct
node
*
merge_nodes
(
struct
node
*
old_node
,
struct
node
*
new_node
);
struct
node
*
add_orphan_node
(
struct
node
*
old_node
,
struct
node
*
new_node
,
char
*
ref
);
void
add_property
(
struct
node
*
node
,
struct
property
*
prop
);
void
delete_property_by_name
(
struct
node
*
node
,
char
*
name
);
void
delete_property
(
struct
property
*
prop
);
void
add_child
(
struct
node
*
parent
,
struct
node
*
child
);
void
delete_node_by_name
(
struct
node
*
parent
,
char
*
name
);
void
delete_node
(
struct
node
*
node
);
void
append_to_property
(
struct
node
*
node
,
char
*
name
,
const
void
*
data
,
int
len
);
const
char
*
get_unitname
(
struct
node
*
node
);
struct
property
*
get_property
(
struct
node
*
node
,
const
char
*
propname
);
cell_t
propval_cell
(
struct
property
*
prop
);
cell_t
propval_cell_n
(
struct
property
*
prop
,
int
n
);
struct
property
*
get_property_by_label
(
struct
node
*
tree
,
const
char
*
label
,
struct
node
**
node
);
struct
marker
*
get_marker_label
(
struct
node
*
tree
,
const
char
*
label
,
struct
node
**
node
,
struct
property
**
prop
);
struct
node
*
get_subnode
(
struct
node
*
node
,
const
char
*
nodename
);
struct
node
*
get_node_by_path
(
struct
node
*
tree
,
const
char
*
path
);
struct
node
*
get_node_by_label
(
struct
node
*
tree
,
const
char
*
label
);
struct
node
*
get_node_by_phandle
(
struct
node
*
tree
,
cell_t
phandle
);
struct
node
*
get_node_by_ref
(
struct
node
*
tree
,
const
char
*
ref
);
cell_t
get_node_phandle
(
struct
node
*
root
,
struct
node
*
node
);
uint32_t
guess_boot_cpuid
(
struct
node
*
tree
);
/* Boot info (tree plus memreserve information */
struct
reserve_info
{
uint64_t
address
,
size
;
struct
reserve_info
*
next
;
struct
label
*
labels
;
};
struct
reserve_info
*
build_reserve_entry
(
uint64_t
start
,
uint64_t
len
);
struct
reserve_info
*
chain_reserve_entry
(
struct
reserve_info
*
first
,
struct
reserve_info
*
list
);
struct
reserve_info
*
add_reserve_entry
(
struct
reserve_info
*
list
,
struct
reserve_info
*
new
);
struct
dt_info
{
unsigned
int
dtsflags
;
struct
reserve_info
*
reservelist
;
uint32_t
boot_cpuid_phys
;
struct
node
*
dt
;
/* the device tree */
const
char
*
outname
;
/* filename being written to, "-" for stdout */
};
/* DTS version flags definitions */
#define DTSF_V1 0x0001
/* /dts-v1/ */
#define DTSF_PLUGIN 0x0002
/* /plugin/ */
struct
dt_info
*
build_dt_info
(
unsigned
int
dtsflags
,
struct
reserve_info
*
reservelist
,
struct
node
*
tree
,
uint32_t
boot_cpuid_phys
);
void
sort_tree
(
struct
dt_info
*
dti
);
void
generate_label_tree
(
struct
dt_info
*
dti
,
char
*
name
,
bool
allocph
);
void
generate_fixups_tree
(
struct
dt_info
*
dti
,
char
*
name
);
void
generate_local_fixups_tree
(
struct
dt_info
*
dti
,
char
*
name
);
/* Checks */
void
parse_checks_option
(
bool
warn
,
bool
error
,
const
char
*
arg
);
void
process_checks
(
bool
force
,
struct
dt_info
*
dti
);
/* Flattened trees */
void
dt_to_blob
(
FILE
*
f
,
struct
dt_info
*
dti
,
int
version
);
void
dt_to_asm
(
FILE
*
f
,
struct
dt_info
*
dti
,
int
version
);
struct
dt_info
*
dt_from_blob
(
const
char
*
fname
);
/* Tree source */
void
dt_to_source
(
FILE
*
f
,
struct
dt_info
*
dti
);
struct
dt_info
*
dt_from_source
(
const
char
*
f
);
/* FS trees */
struct
dt_info
*
dt_from_fs
(
const
char
*
dirname
);
#endif
/* DTC_H */
u-boot-tree/scripts/dtc/flattree.c
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "dtc.h"
#include "srcpos.h"
#define FTF_FULLPATH 0x1
#define FTF_VARALIGN 0x2
#define FTF_NAMEPROPS 0x4
#define FTF_BOOTCPUID 0x8
#define FTF_STRTABSIZE 0x10
#define FTF_STRUCTSIZE 0x20
#define FTF_NOPS 0x40
static
struct
version_info
{
int
version
;
int
last_comp_version
;
int
hdr_size
;
int
flags
;
}
version_table
[]
=
{
{
1
,
1
,
FDT_V1_SIZE
,
FTF_FULLPATH
|
FTF_VARALIGN
|
FTF_NAMEPROPS
},
{
2
,
1
,
FDT_V2_SIZE
,
FTF_FULLPATH
|
FTF_VARALIGN
|
FTF_NAMEPROPS
|
FTF_BOOTCPUID
},
{
3
,
1
,
FDT_V3_SIZE
,
FTF_FULLPATH
|
FTF_VARALIGN
|
FTF_NAMEPROPS
|
FTF_BOOTCPUID
|
FTF_STRTABSIZE
},
{
16
,
16
,
FDT_V3_SIZE
,
FTF_BOOTCPUID
|
FTF_STRTABSIZE
|
FTF_NOPS
},
{
17
,
16
,
FDT_V17_SIZE
,
FTF_BOOTCPUID
|
FTF_STRTABSIZE
|
FTF_STRUCTSIZE
|
FTF_NOPS
},
};
struct
emitter
{
void
(
*
cell
)(
void
*
,
cell_t
);
void
(
*
string
)(
void
*
,
const
char
*
,
int
);
void
(
*
align
)(
void
*
,
int
);
void
(
*
data
)(
void
*
,
struct
data
);
void
(
*
beginnode
)(
void
*
,
struct
label
*
labels
);
void
(
*
endnode
)(
void
*
,
struct
label
*
labels
);
void
(
*
property
)(
void
*
,
struct
label
*
labels
);
};
static
void
bin_emit_cell
(
void
*
e
,
cell_t
val
)
{
struct
data
*
dtbuf
=
e
;
*
dtbuf
=
data_append_cell
(
*
dtbuf
,
val
);
}
static
void
bin_emit_string
(
void
*
e
,
const
char
*
str
,
int
len
)
{
struct
data
*
dtbuf
=
e
;
if
(
len
==
0
)
len
=
strlen
(
str
);
*
dtbuf
=
data_append_data
(
*
dtbuf
,
str
,
len
);
*
dtbuf
=
data_append_byte
(
*
dtbuf
,
'\0'
);
}
static
void
bin_emit_align
(
void
*
e
,
int
a
)
{
struct
data
*
dtbuf
=
e
;
*
dtbuf
=
data_append_align
(
*
dtbuf
,
a
);
}
static
void
bin_emit_data
(
void
*
e
,
struct
data
d
)
{
struct
data
*
dtbuf
=
e
;
*
dtbuf
=
data_append_data
(
*
dtbuf
,
d
.
val
,
d
.
len
);
}
static
void
bin_emit_beginnode
(
void
*
e
,
struct
label
*
labels
)
{
bin_emit_cell
(
e
,
FDT_BEGIN_NODE
);
}
static
void
bin_emit_endnode
(
void
*
e
,
struct
label
*
labels
)
{
bin_emit_cell
(
e
,
FDT_END_NODE
);
}
static
void
bin_emit_property
(
void
*
e
,
struct
label
*
labels
)
{
bin_emit_cell
(
e
,
FDT_PROP
);
}
static
struct
emitter
bin_emitter
=
{
.
cell
=
bin_emit_cell
,
.
string
=
bin_emit_string
,
.
align
=
bin_emit_align
,
.
data
=
bin_emit_data
,
.
beginnode
=
bin_emit_beginnode
,
.
endnode
=
bin_emit_endnode
,
.
property
=
bin_emit_property
,
};
static
void
emit_label
(
FILE
*
f
,
const
char
*
prefix
,
const
char
*
label
)
{
fprintf
(
f
,
"
\t
.globl
\t
%s_%s
\n
"
,
prefix
,
label
);
fprintf
(
f
,
"%s_%s:
\n
"
,
prefix
,
label
);
fprintf
(
f
,
"_%s_%s:
\n
"
,
prefix
,
label
);
}
static
void
emit_offset_label
(
FILE
*
f
,
const
char
*
label
,
int
offset
)
{
fprintf
(
f
,
"
\t
.globl
\t
%s
\n
"
,
label
);
fprintf
(
f
,
"%s
\t
= . + %d
\n
"
,
label
,
offset
);
}
#define ASM_EMIT_BELONG(f, fmt, ...) \
{ \
fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \
fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \
fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \
fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \
}
static
void
asm_emit_cell
(
void
*
e
,
cell_t
val
)
{
FILE
*
f
=
e
;
fprintf
(
f
,
"
\t
.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x
\n
"
,
(
val
>>
24
)
&
0xff
,
(
val
>>
16
)
&
0xff
,
(
val
>>
8
)
&
0xff
,
val
&
0xff
);
}
static
void
asm_emit_string
(
void
*
e
,
const
char
*
str
,
int
len
)
{
FILE
*
f
=
e
;
if
(
len
!=
0
)
fprintf
(
f
,
"
\t
.string
\t\"
%.*s
\"\n
"
,
len
,
str
);
else
fprintf
(
f
,
"
\t
.string
\t\"
%s
\"\n
"
,
str
);
}
static
void
asm_emit_align
(
void
*
e
,
int
a
)
{
FILE
*
f
=
e
;
fprintf
(
f
,
"
\t
.balign
\t
%d, 0
\n
"
,
a
);
}
static
void
asm_emit_data
(
void
*
e
,
struct
data
d
)
{
FILE
*
f
=
e
;
int
off
=
0
;
struct
marker
*
m
=
d
.
markers
;
for_each_marker_of_type
(
m
,
LABEL
)
emit_offset_label
(
f
,
m
->
ref
,
m
->
offset
);
while
((
d
.
len
-
off
)
>=
sizeof
(
uint32_t
))
{
asm_emit_cell
(
e
,
fdt32_to_cpu
(
*
((
fdt32_t
*
)(
d
.
val
+
off
))));
off
+=
sizeof
(
uint32_t
);
}
while
((
d
.
len
-
off
)
>=
1
)
{
fprintf
(
f
,
"
\t
.byte
\t
0x%hhx
\n
"
,
d
.
val
[
off
]);
off
+=
1
;
}
assert
(
off
==
d
.
len
);
}
static
void
asm_emit_beginnode
(
void
*
e
,
struct
label
*
labels
)
{
FILE
*
f
=
e
;
struct
label
*
l
;
for_each_label
(
labels
,
l
)
{
fprintf
(
f
,
"
\t
.globl
\t
%s
\n
"
,
l
->
label
);
fprintf
(
f
,
"%s:
\n
"
,
l
->
label
);
}
fprintf
(
f
,
"
\t
/* FDT_BEGIN_NODE */
\n
"
);
asm_emit_cell
(
e
,
FDT_BEGIN_NODE
);
}
static
void
asm_emit_endnode
(
void
*
e
,
struct
label
*
labels
)
{
FILE
*
f
=
e
;
struct
label
*
l
;
fprintf
(
f
,
"
\t
/* FDT_END_NODE */
\n
"
);
asm_emit_cell
(
e
,
FDT_END_NODE
);
for_each_label
(
labels
,
l
)
{
fprintf
(
f
,
"
\t
.globl
\t
%s_end
\n
"
,
l
->
label
);
fprintf
(
f
,
"%s_end:
\n
"
,
l
->
label
);
}
}
static
void
asm_emit_property
(
void
*
e
,
struct
label
*
labels
)
{
FILE
*
f
=
e
;
struct
label
*
l
;
for_each_label
(
labels
,
l
)
{
fprintf
(
f
,
"
\t
.globl
\t
%s
\n
"
,
l
->
label
);
fprintf
(
f
,
"%s:
\n
"
,
l
->
label
);
}
fprintf
(
f
,
"
\t
/* FDT_PROP */
\n
"
);
asm_emit_cell
(
e
,
FDT_PROP
);
}
static
struct
emitter
asm_emitter
=
{
.
cell
=
asm_emit_cell
,
.
string
=
asm_emit_string
,
.
align
=
asm_emit_align
,
.
data
=
asm_emit_data
,
.
beginnode
=
asm_emit_beginnode
,
.
endnode
=
asm_emit_endnode
,
.
property
=
asm_emit_property
,
};
static
int
stringtable_insert
(
struct
data
*
d
,
const
char
*
str
)
{
int
i
;
/* FIXME: do this more efficiently? */
for
(
i
=
0
;
i
<
d
->
len
;
i
++
)
{
if
(
streq
(
str
,
d
->
val
+
i
))
return
i
;
}
*
d
=
data_append_data
(
*
d
,
str
,
strlen
(
str
)
+
1
);
return
i
;
}
static
void
flatten_tree
(
struct
node
*
tree
,
struct
emitter
*
emit
,
void
*
etarget
,
struct
data
*
strbuf
,
struct
version_info
*
vi
)
{
struct
property
*
prop
;
struct
node
*
child
;
bool
seen_name_prop
=
false
;
if
(
tree
->
deleted
)
return
;
emit
->
beginnode
(
etarget
,
tree
->
labels
);
if
(
vi
->
flags
&
FTF_FULLPATH
)
emit
->
string
(
etarget
,
tree
->
fullpath
,
0
);
else
emit
->
string
(
etarget
,
tree
->
name
,
0
);
emit
->
align
(
etarget
,
sizeof
(
cell_t
));
for_each_property
(
tree
,
prop
)
{
int
nameoff
;
if
(
streq
(
prop
->
name
,
"name"
))
seen_name_prop
=
true
;
nameoff
=
stringtable_insert
(
strbuf
,
prop
->
name
);
emit
->
property
(
etarget
,
prop
->
labels
);
emit
->
cell
(
etarget
,
prop
->
val
.
len
);
emit
->
cell
(
etarget
,
nameoff
);
if
((
vi
->
flags
&
FTF_VARALIGN
)
&&
(
prop
->
val
.
len
>=
8
))
emit
->
align
(
etarget
,
8
);
emit
->
data
(
etarget
,
prop
->
val
);
emit
->
align
(
etarget
,
sizeof
(
cell_t
));
}
if
((
vi
->
flags
&
FTF_NAMEPROPS
)
&&
!
seen_name_prop
)
{
emit
->
property
(
etarget
,
NULL
);
emit
->
cell
(
etarget
,
tree
->
basenamelen
+
1
);
emit
->
cell
(
etarget
,
stringtable_insert
(
strbuf
,
"name"
));
if
((
vi
->
flags
&
FTF_VARALIGN
)
&&
((
tree
->
basenamelen
+
1
)
>=
8
))
emit
->
align
(
etarget
,
8
);
emit
->
string
(
etarget
,
tree
->
name
,
tree
->
basenamelen
);
emit
->
align
(
etarget
,
sizeof
(
cell_t
));
}
for_each_child
(
tree
,
child
)
{
flatten_tree
(
child
,
emit
,
etarget
,
strbuf
,
vi
);
}
emit
->
endnode
(
etarget
,
tree
->
labels
);
}
static
struct
data
flatten_reserve_list
(
struct
reserve_info
*
reservelist
,
struct
version_info
*
vi
)
{
struct
reserve_info
*
re
;
struct
data
d
=
empty_data
;
int
j
;
for
(
re
=
reservelist
;
re
;
re
=
re
->
next
)
{
d
=
data_append_re
(
d
,
re
->
address
,
re
->
size
);
}
/*
* Add additional reserved slots if the user asked for them.
*/
for
(
j
=
0
;
j
<
reservenum
;
j
++
)
{
d
=
data_append_re
(
d
,
0
,
0
);
}
return
d
;
}
static
void
make_fdt_header
(
struct
fdt_header
*
fdt
,
struct
version_info
*
vi
,
int
reservesize
,
int
dtsize
,
int
strsize
,
int
boot_cpuid_phys
)
{
int
reserve_off
;
reservesize
+=
sizeof
(
struct
fdt_reserve_entry
);
memset
(
fdt
,
0xff
,
sizeof
(
*
fdt
));
fdt
->
magic
=
cpu_to_fdt32
(
FDT_MAGIC
);
fdt
->
version
=
cpu_to_fdt32
(
vi
->
version
);
fdt
->
last_comp_version
=
cpu_to_fdt32
(
vi
->
last_comp_version
);
/* Reserve map should be doubleword aligned */
reserve_off
=
ALIGN
(
vi
->
hdr_size
,
8
);
fdt
->
off_mem_rsvmap
=
cpu_to_fdt32
(
reserve_off
);
fdt
->
off_dt_struct
=
cpu_to_fdt32
(
reserve_off
+
reservesize
);
fdt
->
off_dt_strings
=
cpu_to_fdt32
(
reserve_off
+
reservesize
+
dtsize
);
fdt
->
totalsize
=
cpu_to_fdt32
(
reserve_off
+
reservesize
+
dtsize
+
strsize
);
if
(
vi
->
flags
&
FTF_BOOTCPUID
)
fdt
->
boot_cpuid_phys
=
cpu_to_fdt32
(
boot_cpuid_phys
);
if
(
vi
->
flags
&
FTF_STRTABSIZE
)
fdt
->
size_dt_strings
=
cpu_to_fdt32
(
strsize
);
if
(
vi
->
flags
&
FTF_STRUCTSIZE
)
fdt
->
size_dt_struct
=
cpu_to_fdt32
(
dtsize
);
}
void
dt_to_blob
(
FILE
*
f
,
struct
dt_info
*
dti
,
int
version
)
{
struct
version_info
*
vi
=
NULL
;
int
i
;
struct
data
blob
=
empty_data
;
struct
data
reservebuf
=
empty_data
;
struct
data
dtbuf
=
empty_data
;
struct
data
strbuf
=
empty_data
;
struct
fdt_header
fdt
;
int
padlen
=
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
version_table
);
i
++
)
{
if
(
version_table
[
i
].
version
==
version
)
vi
=
&
version_table
[
i
];
}
if
(
!
vi
)
die
(
"Unknown device tree blob version %d
\n
"
,
version
);
flatten_tree
(
dti
->
dt
,
&
bin_emitter
,
&
dtbuf
,
&
strbuf
,
vi
);
bin_emit_cell
(
&
dtbuf
,
FDT_END
);
reservebuf
=
flatten_reserve_list
(
dti
->
reservelist
,
vi
);
/* Make header */
make_fdt_header
(
&
fdt
,
vi
,
reservebuf
.
len
,
dtbuf
.
len
,
strbuf
.
len
,
dti
->
boot_cpuid_phys
);
/*
* If the user asked for more space than is used, adjust the totalsize.
*/
if
(
minsize
>
0
)
{
padlen
=
minsize
-
fdt32_to_cpu
(
fdt
.
totalsize
);
if
(
padlen
<
0
)
{
padlen
=
0
;
if
(
quiet
<
1
)
fprintf
(
stderr
,
"Warning: blob size %d >= minimum size %d
\n
"
,
fdt32_to_cpu
(
fdt
.
totalsize
),
minsize
);
}
}
if
(
padsize
>
0
)
padlen
=
padsize
;
if
(
alignsize
>
0
)
padlen
=
ALIGN
(
fdt32_to_cpu
(
fdt
.
totalsize
)
+
padlen
,
alignsize
)
-
fdt32_to_cpu
(
fdt
.
totalsize
);
if
(
padlen
>
0
)
{
int
tsize
=
fdt32_to_cpu
(
fdt
.
totalsize
);
tsize
+=
padlen
;
fdt
.
totalsize
=
cpu_to_fdt32
(
tsize
);
}
/*
* Assemble the blob: start with the header, add with alignment
* the reserve buffer, add the reserve map terminating zeroes,
* the device tree itself, and finally the strings.
*/
blob
=
data_append_data
(
blob
,
&
fdt
,
vi
->
hdr_size
);
blob
=
data_append_align
(
blob
,
8
);
blob
=
data_merge
(
blob
,
reservebuf
);
blob
=
data_append_zeroes
(
blob
,
sizeof
(
struct
fdt_reserve_entry
));
blob
=
data_merge
(
blob
,
dtbuf
);
blob
=
data_merge
(
blob
,
strbuf
);
/*
* If the user asked for more space than is used, pad out the blob.
*/
if
(
padlen
>
0
)
blob
=
data_append_zeroes
(
blob
,
padlen
);
if
(
fwrite
(
blob
.
val
,
blob
.
len
,
1
,
f
)
!=
1
)
{
if
(
ferror
(
f
))
die
(
"Error writing device tree blob: %s
\n
"
,
strerror
(
errno
));
else
die
(
"Short write on device tree blob
\n
"
);
}
/*
* data_merge() frees the right-hand element so only the blob
* remains to be freed.
*/
data_free
(
blob
);
}
static
void
dump_stringtable_asm
(
FILE
*
f
,
struct
data
strbuf
)
{
const
char
*
p
;
int
len
;
p
=
strbuf
.
val
;
while
(
p
<
(
strbuf
.
val
+
strbuf
.
len
))
{
len
=
strlen
(
p
);
fprintf
(
f
,
"
\t
.string
\"
%s
\"\n
"
,
p
);
p
+=
len
+
1
;
}
}
void
dt_to_asm
(
FILE
*
f
,
struct
dt_info
*
dti
,
int
version
)
{
struct
version_info
*
vi
=
NULL
;
int
i
;
struct
data
strbuf
=
empty_data
;
struct
reserve_info
*
re
;
const
char
*
symprefix
=
"dt"
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
version_table
);
i
++
)
{
if
(
version_table
[
i
].
version
==
version
)
vi
=
&
version_table
[
i
];
}
if
(
!
vi
)
die
(
"Unknown device tree blob version %d
\n
"
,
version
);
fprintf
(
f
,
"/* autogenerated by dtc, do not edit */
\n\n
"
);
emit_label
(
f
,
symprefix
,
"blob_start"
);
emit_label
(
f
,
symprefix
,
"header"
);
fprintf
(
f
,
"
\t
/* magic */
\n
"
);
asm_emit_cell
(
f
,
FDT_MAGIC
);
fprintf
(
f
,
"
\t
/* totalsize */
\n
"
);
ASM_EMIT_BELONG
(
f
,
"_%s_blob_abs_end - _%s_blob_start"
,
symprefix
,
symprefix
);
fprintf
(
f
,
"
\t
/* off_dt_struct */
\n
"
);
ASM_EMIT_BELONG
(
f
,
"_%s_struct_start - _%s_blob_start"
,
symprefix
,
symprefix
);
fprintf
(
f
,
"
\t
/* off_dt_strings */
\n
"
);
ASM_EMIT_BELONG
(
f
,
"_%s_strings_start - _%s_blob_start"
,
symprefix
,
symprefix
);
fprintf
(
f
,
"
\t
/* off_mem_rsvmap */
\n
"
);
ASM_EMIT_BELONG
(
f
,
"_%s_reserve_map - _%s_blob_start"
,
symprefix
,
symprefix
);
fprintf
(
f
,
"
\t
/* version */
\n
"
);
asm_emit_cell
(
f
,
vi
->
version
);
fprintf
(
f
,
"
\t
/* last_comp_version */
\n
"
);
asm_emit_cell
(
f
,
vi
->
last_comp_version
);
if
(
vi
->
flags
&
FTF_BOOTCPUID
)
{
fprintf
(
f
,
"
\t
/* boot_cpuid_phys */
\n
"
);
asm_emit_cell
(
f
,
dti
->
boot_cpuid_phys
);
}
if
(
vi
->
flags
&
FTF_STRTABSIZE
)
{
fprintf
(
f
,
"
\t
/* size_dt_strings */
\n
"
);
ASM_EMIT_BELONG
(
f
,
"_%s_strings_end - _%s_strings_start"
,
symprefix
,
symprefix
);
}
if
(
vi
->
flags
&
FTF_STRUCTSIZE
)
{
fprintf
(
f
,
"
\t
/* size_dt_struct */
\n
"
);
ASM_EMIT_BELONG
(
f
,
"_%s_struct_end - _%s_struct_start"
,
symprefix
,
symprefix
);
}
/*
* Reserve map entries.
* Align the reserve map to a doubleword boundary.
* Each entry is an (address, size) pair of u64 values.
* Always supply a zero-sized temination entry.
*/
asm_emit_align
(
f
,
8
);
emit_label
(
f
,
symprefix
,
"reserve_map"
);
fprintf
(
f
,
"/* Memory reserve map from source file */
\n
"
);
/*
* Use .long on high and low halfs of u64s to avoid .quad
* as it appears .quad isn't available in some assemblers.
*/
for
(
re
=
dti
->
reservelist
;
re
;
re
=
re
->
next
)
{
struct
label
*
l
;
for_each_label
(
re
->
labels
,
l
)
{
fprintf
(
f
,
"
\t
.globl
\t
%s
\n
"
,
l
->
label
);
fprintf
(
f
,
"%s:
\n
"
,
l
->
label
);
}
ASM_EMIT_BELONG
(
f
,
"0x%08x"
,
(
unsigned
int
)(
re
->
address
>>
32
));
ASM_EMIT_BELONG
(
f
,
"0x%08x"
,
(
unsigned
int
)(
re
->
address
&
0xffffffff
));
ASM_EMIT_BELONG
(
f
,
"0x%08x"
,
(
unsigned
int
)(
re
->
size
>>
32
));
ASM_EMIT_BELONG
(
f
,
"0x%08x"
,
(
unsigned
int
)(
re
->
size
&
0xffffffff
));
}
for
(
i
=
0
;
i
<
reservenum
;
i
++
)
{
fprintf
(
f
,
"
\t
.long
\t
0, 0
\n\t
.long
\t
0, 0
\n
"
);
}
fprintf
(
f
,
"
\t
.long
\t
0, 0
\n\t
.long
\t
0, 0
\n
"
);
emit_label
(
f
,
symprefix
,
"struct_start"
);
flatten_tree
(
dti
->
dt
,
&
asm_emitter
,
f
,
&
strbuf
,
vi
);
fprintf
(
f
,
"
\t
/* FDT_END */
\n
"
);
asm_emit_cell
(
f
,
FDT_END
);
emit_label
(
f
,
symprefix
,
"struct_end"
);
emit_label
(
f
,
symprefix
,
"strings_start"
);
dump_stringtable_asm
(
f
,
strbuf
);
emit_label
(
f
,
symprefix
,
"strings_end"
);
emit_label
(
f
,
symprefix
,
"blob_end"
);
/*
* If the user asked for more space than is used, pad it out.
*/
if
(
minsize
>
0
)
{
fprintf
(
f
,
"
\t
.space
\t
%d - (_%s_blob_end - _%s_blob_start), 0
\n
"
,
minsize
,
symprefix
,
symprefix
);
}
if
(
padsize
>
0
)
{
fprintf
(
f
,
"
\t
.space
\t
%d, 0
\n
"
,
padsize
);
}
if
(
alignsize
>
0
)
asm_emit_align
(
f
,
alignsize
);
emit_label
(
f
,
symprefix
,
"blob_abs_end"
);
data_free
(
strbuf
);
}
struct
inbuf
{
char
*
base
,
*
limit
,
*
ptr
;
};
static
void
inbuf_init
(
struct
inbuf
*
inb
,
void
*
base
,
void
*
limit
)
{
inb
->
base
=
base
;
inb
->
limit
=
limit
;
inb
->
ptr
=
inb
->
base
;
}
static
void
flat_read_chunk
(
struct
inbuf
*
inb
,
void
*
p
,
int
len
)
{
if
((
inb
->
ptr
+
len
)
>
inb
->
limit
)
die
(
"Premature end of data parsing flat device tree
\n
"
);
memcpy
(
p
,
inb
->
ptr
,
len
);
inb
->
ptr
+=
len
;
}
static
uint32_t
flat_read_word
(
struct
inbuf
*
inb
)
{
fdt32_t
val
;
assert
(((
inb
->
ptr
-
inb
->
base
)
%
sizeof
(
val
))
==
0
);
flat_read_chunk
(
inb
,
&
val
,
sizeof
(
val
));
return
fdt32_to_cpu
(
val
);
}
static
void
flat_realign
(
struct
inbuf
*
inb
,
int
align
)
{
int
off
=
inb
->
ptr
-
inb
->
base
;
inb
->
ptr
=
inb
->
base
+
ALIGN
(
off
,
align
);
if
(
inb
->
ptr
>
inb
->
limit
)
die
(
"Premature end of data parsing flat device tree
\n
"
);
}
static
char
*
flat_read_string
(
struct
inbuf
*
inb
)
{
int
len
=
0
;
const
char
*
p
=
inb
->
ptr
;
char
*
str
;
do
{
if
(
p
>=
inb
->
limit
)
die
(
"Premature end of data parsing flat device tree
\n
"
);
len
++
;
}
while
((
*
p
++
)
!=
'\0'
);
str
=
xstrdup
(
inb
->
ptr
);
inb
->
ptr
+=
len
;
flat_realign
(
inb
,
sizeof
(
uint32_t
));
return
str
;
}
static
struct
data
flat_read_data
(
struct
inbuf
*
inb
,
int
len
)
{
struct
data
d
=
empty_data
;
if
(
len
==
0
)
return
empty_data
;
d
=
data_grow_for
(
d
,
len
);
d
.
len
=
len
;
flat_read_chunk
(
inb
,
d
.
val
,
len
);
flat_realign
(
inb
,
sizeof
(
uint32_t
));
return
d
;
}
static
char
*
flat_read_stringtable
(
struct
inbuf
*
inb
,
int
offset
)
{
const
char
*
p
;
p
=
inb
->
base
+
offset
;
while
(
1
)
{
if
(
p
>=
inb
->
limit
||
p
<
inb
->
base
)
die
(
"String offset %d overruns string table
\n
"
,
offset
);
if
(
*
p
==
'\0'
)
break
;
p
++
;
}
return
xstrdup
(
inb
->
base
+
offset
);
}
static
struct
property
*
flat_read_property
(
struct
inbuf
*
dtbuf
,
struct
inbuf
*
strbuf
,
int
flags
)
{
uint32_t
proplen
,
stroff
;
char
*
name
;
struct
data
val
;
proplen
=
flat_read_word
(
dtbuf
);
stroff
=
flat_read_word
(
dtbuf
);
name
=
flat_read_stringtable
(
strbuf
,
stroff
);
if
((
flags
&
FTF_VARALIGN
)
&&
(
proplen
>=
8
))
flat_realign
(
dtbuf
,
8
);
val
=
flat_read_data
(
dtbuf
,
proplen
);
return
build_property
(
name
,
val
);
}
static
struct
reserve_info
*
flat_read_mem_reserve
(
struct
inbuf
*
inb
)
{
struct
reserve_info
*
reservelist
=
NULL
;
struct
reserve_info
*
new
;
struct
fdt_reserve_entry
re
;
/*
* Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
* List terminates at an entry with size equal to zero.
*
* First pass, count entries.
*/
while
(
1
)
{
uint64_t
address
,
size
;
flat_read_chunk
(
inb
,
&
re
,
sizeof
(
re
));
address
=
fdt64_to_cpu
(
re
.
address
);
size
=
fdt64_to_cpu
(
re
.
size
);
if
(
size
==
0
)
break
;
new
=
build_reserve_entry
(
address
,
size
);
reservelist
=
add_reserve_entry
(
reservelist
,
new
);
}
return
reservelist
;
}
static
char
*
nodename_from_path
(
const
char
*
ppath
,
const
char
*
cpath
)
{
int
plen
;
plen
=
strlen
(
ppath
);
if
(
!
strstarts
(
cpath
,
ppath
))
die
(
"Path
\"
%s
\"
is not valid as a child of
\"
%s
\"\n
"
,
cpath
,
ppath
);
/* root node is a special case */
if
(
!
streq
(
ppath
,
"/"
))
plen
++
;
return
xstrdup
(
cpath
+
plen
);
}
static
struct
node
*
unflatten_tree
(
struct
inbuf
*
dtbuf
,
struct
inbuf
*
strbuf
,
const
char
*
parent_flatname
,
int
flags
)
{
struct
node
*
node
;
char
*
flatname
;
uint32_t
val
;
node
=
build_node
(
NULL
,
NULL
);
flatname
=
flat_read_string
(
dtbuf
);
if
(
flags
&
FTF_FULLPATH
)
node
->
name
=
nodename_from_path
(
parent_flatname
,
flatname
);
else
node
->
name
=
flatname
;
do
{
struct
property
*
prop
;
struct
node
*
child
;
val
=
flat_read_word
(
dtbuf
);
switch
(
val
)
{
case
FDT_PROP
:
if
(
node
->
children
)
fprintf
(
stderr
,
"Warning: Flat tree input has "
"subnodes preceding a property.
\n
"
);
prop
=
flat_read_property
(
dtbuf
,
strbuf
,
flags
);
add_property
(
node
,
prop
);
break
;
case
FDT_BEGIN_NODE
:
child
=
unflatten_tree
(
dtbuf
,
strbuf
,
flatname
,
flags
);
add_child
(
node
,
child
);
break
;
case
FDT_END_NODE
:
break
;
case
FDT_END
:
die
(
"Premature FDT_END in device tree blob
\n
"
);
break
;
case
FDT_NOP
:
if
(
!
(
flags
&
FTF_NOPS
))
fprintf
(
stderr
,
"Warning: NOP tag found in flat tree"
" version <16
\n
"
);
/* Ignore */
break
;
default:
die
(
"Invalid opcode word %08x in device tree blob
\n
"
,
val
);
}
}
while
(
val
!=
FDT_END_NODE
);
if
(
node
->
name
!=
flatname
)
{
free
(
flatname
);
}
return
node
;
}
struct
dt_info
*
dt_from_blob
(
const
char
*
fname
)
{
FILE
*
f
;
fdt32_t
magic_buf
,
totalsize_buf
;
uint32_t
magic
,
totalsize
,
version
,
size_dt
,
boot_cpuid_phys
;
uint32_t
off_dt
,
off_str
,
off_mem_rsvmap
;
int
rc
;
char
*
blob
;
struct
fdt_header
*
fdt
;
char
*
p
;
struct
inbuf
dtbuf
,
strbuf
;
struct
inbuf
memresvbuf
;
int
sizeleft
;
struct
reserve_info
*
reservelist
;
struct
node
*
tree
;
uint32_t
val
;
int
flags
=
0
;
f
=
srcfile_relative_open
(
fname
,
NULL
);
rc
=
fread
(
&
magic_buf
,
sizeof
(
magic_buf
),
1
,
f
);
if
(
ferror
(
f
))
die
(
"Error reading DT blob magic number: %s
\n
"
,
strerror
(
errno
));
if
(
rc
<
1
)
{
if
(
feof
(
f
))
die
(
"EOF reading DT blob magic number
\n
"
);
else
die
(
"Mysterious short read reading magic number
\n
"
);
}
magic
=
fdt32_to_cpu
(
magic_buf
);
if
(
magic
!=
FDT_MAGIC
)
die
(
"Blob has incorrect magic number
\n
"
);
rc
=
fread
(
&
totalsize_buf
,
sizeof
(
totalsize_buf
),
1
,
f
);
if
(
ferror
(
f
))
die
(
"Error reading DT blob size: %s
\n
"
,
strerror
(
errno
));
if
(
rc
<
1
)
{
if
(
feof
(
f
))
die
(
"EOF reading DT blob size
\n
"
);
else
die
(
"Mysterious short read reading blob size
\n
"
);
}
totalsize
=
fdt32_to_cpu
(
totalsize_buf
);
if
(
totalsize
<
FDT_V1_SIZE
)
die
(
"DT blob size (%d) is too small
\n
"
,
totalsize
);
blob
=
xmalloc
(
totalsize
);
fdt
=
(
struct
fdt_header
*
)
blob
;
fdt
->
magic
=
cpu_to_fdt32
(
magic
);
fdt
->
totalsize
=
cpu_to_fdt32
(
totalsize
);
sizeleft
=
totalsize
-
sizeof
(
magic
)
-
sizeof
(
totalsize
);
p
=
blob
+
sizeof
(
magic
)
+
sizeof
(
totalsize
);
while
(
sizeleft
)
{
if
(
feof
(
f
))
die
(
"EOF before reading %d bytes of DT blob
\n
"
,
totalsize
);
rc
=
fread
(
p
,
1
,
sizeleft
,
f
);
if
(
ferror
(
f
))
die
(
"Error reading DT blob: %s
\n
"
,
strerror
(
errno
));
sizeleft
-=
rc
;
p
+=
rc
;
}
off_dt
=
fdt32_to_cpu
(
fdt
->
off_dt_struct
);
off_str
=
fdt32_to_cpu
(
fdt
->
off_dt_strings
);
off_mem_rsvmap
=
fdt32_to_cpu
(
fdt
->
off_mem_rsvmap
);
version
=
fdt32_to_cpu
(
fdt
->
version
);
boot_cpuid_phys
=
fdt32_to_cpu
(
fdt
->
boot_cpuid_phys
);
if
(
off_mem_rsvmap
>=
totalsize
)
die
(
"Mem Reserve structure offset exceeds total size
\n
"
);
if
(
off_dt
>=
totalsize
)
die
(
"DT structure offset exceeds total size
\n
"
);
if
(
off_str
>
totalsize
)
die
(
"String table offset exceeds total size
\n
"
);
if
(
version
>=
3
)
{
uint32_t
size_str
=
fdt32_to_cpu
(
fdt
->
size_dt_strings
);
if
((
off_str
+
size_str
<
off_str
)
||
(
off_str
+
size_str
>
totalsize
))
die
(
"String table extends past total size
\n
"
);
inbuf_init
(
&
strbuf
,
blob
+
off_str
,
blob
+
off_str
+
size_str
);
}
else
{
inbuf_init
(
&
strbuf
,
blob
+
off_str
,
blob
+
totalsize
);
}
if
(
version
>=
17
)
{
size_dt
=
fdt32_to_cpu
(
fdt
->
size_dt_struct
);
if
((
off_dt
+
size_dt
<
off_dt
)
||
(
off_dt
+
size_dt
>
totalsize
))
die
(
"Structure block extends past total size
\n
"
);
}
if
(
version
<
16
)
{
flags
|=
FTF_FULLPATH
|
FTF_NAMEPROPS
|
FTF_VARALIGN
;
}
else
{
flags
|=
FTF_NOPS
;
}
inbuf_init
(
&
memresvbuf
,
blob
+
off_mem_rsvmap
,
blob
+
totalsize
);
inbuf_init
(
&
dtbuf
,
blob
+
off_dt
,
blob
+
totalsize
);
reservelist
=
flat_read_mem_reserve
(
&
memresvbuf
);
val
=
flat_read_word
(
&
dtbuf
);
if
(
val
!=
FDT_BEGIN_NODE
)
die
(
"Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)
\n
"
,
val
);
tree
=
unflatten_tree
(
&
dtbuf
,
&
strbuf
,
""
,
flags
);
val
=
flat_read_word
(
&
dtbuf
);
if
(
val
!=
FDT_END
)
die
(
"Device tree blob doesn't end with FDT_END
\n
"
);
free
(
blob
);
fclose
(
f
);
return
build_dt_info
(
DTSF_V1
,
reservelist
,
tree
,
boot_cpuid_phys
);
}
u-boot-tree/scripts/dtc/fstree.c
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "dtc.h"
#include <dirent.h>
#include <sys/stat.h>
static
struct
node
*
read_fstree
(
const
char
*
dirname
)
{
DIR
*
d
;
struct
dirent
*
de
;
struct
stat
st
;
struct
node
*
tree
;
d
=
opendir
(
dirname
);
if
(
!
d
)
die
(
"Couldn't opendir()
\"
%s
\"
: %s
\n
"
,
dirname
,
strerror
(
errno
));
tree
=
build_node
(
NULL
,
NULL
);
while
((
de
=
readdir
(
d
))
!=
NULL
)
{
char
*
tmpname
;
if
(
streq
(
de
->
d_name
,
"."
)
||
streq
(
de
->
d_name
,
".."
))
continue
;
tmpname
=
join_path
(
dirname
,
de
->
d_name
);
if
(
lstat
(
tmpname
,
&
st
)
<
0
)
die
(
"stat(%s): %s
\n
"
,
tmpname
,
strerror
(
errno
));
if
(
S_ISREG
(
st
.
st_mode
))
{
struct
property
*
prop
;
FILE
*
pfile
;
pfile
=
fopen
(
tmpname
,
"rb"
);
if
(
!
pfile
)
{
fprintf
(
stderr
,
"WARNING: Cannot open %s: %s
\n
"
,
tmpname
,
strerror
(
errno
));
}
else
{
prop
=
build_property
(
xstrdup
(
de
->
d_name
),
data_copy_file
(
pfile
,
st
.
st_size
));
add_property
(
tree
,
prop
);
fclose
(
pfile
);
}
}
else
if
(
S_ISDIR
(
st
.
st_mode
))
{
struct
node
*
newchild
;
newchild
=
read_fstree
(
tmpname
);
newchild
=
name_node
(
newchild
,
xstrdup
(
de
->
d_name
));
add_child
(
tree
,
newchild
);
}
free
(
tmpname
);
}
closedir
(
d
);
return
tree
;
}
struct
dt_info
*
dt_from_fs
(
const
char
*
dirname
)
{
struct
node
*
tree
;
tree
=
read_fstree
(
dirname
);
tree
=
name_node
(
tree
,
""
);
return
build_dt_info
(
DTSF_V1
,
NULL
,
tree
,
guess_boot_cpuid
(
tree
));
}
u-boot-tree/scripts/dtc/libfdt/Makefile.libfdt
deleted
100644 → 0
View file @
3e304607
# Makefile.libfdt
#
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
LIBFDT_soname
=
libfdt.
$(SHAREDLIB_EXT)
.1
LIBFDT_INCLUDES
=
fdt.h libfdt.h libfdt_env.h
LIBFDT_VERSION
=
version.lds
LIBFDT_SRCS
=
fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
\
fdt_addresses.c fdt_overlay.c
LIBFDT_OBJS
=
$
(
LIBFDT_SRCS:%.c
=
%.o
)
u-boot-tree/scripts/dtc/libfdt/fdt.c
deleted
100644 → 0
View file @
3e304607
/*
* 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
);
if
(
fdt_version
(
fdt
)
<
0x10
&&
fdt32_to_cpu
(
*
lenp
)
>=
8
&&
((
offset
-
fdt32_to_cpu
(
*
lenp
))
%
8
)
!=
0
)
offset
+=
4
;
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
;
}
u-boot-tree/scripts/dtc/libfdt/fdt_addresses.c
deleted
100644 → 0
View file @
3e304607
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
*
* 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_address_cells
(
const
void
*
fdt
,
int
nodeoffset
)
{
const
fdt32_t
*
ac
;
int
val
;
int
len
;
ac
=
fdt_getprop
(
fdt
,
nodeoffset
,
"#address-cells"
,
&
len
);
if
(
!
ac
)
return
2
;
if
(
len
!=
sizeof
(
*
ac
))
return
-
FDT_ERR_BADNCELLS
;
val
=
fdt32_to_cpu
(
*
ac
);
if
((
val
<=
0
)
||
(
val
>
FDT_MAX_NCELLS
))
return
-
FDT_ERR_BADNCELLS
;
return
val
;
}
int
fdt_size_cells
(
const
void
*
fdt
,
int
nodeoffset
)
{
const
fdt32_t
*
sc
;
int
val
;
int
len
;
sc
=
fdt_getprop
(
fdt
,
nodeoffset
,
"#size-cells"
,
&
len
);
if
(
!
sc
)
return
2
;
if
(
len
!=
sizeof
(
*
sc
))
return
-
FDT_ERR_BADNCELLS
;
val
=
fdt32_to_cpu
(
*
sc
);
if
((
val
<
0
)
||
(
val
>
FDT_MAX_NCELLS
))
return
-
FDT_ERR_BADNCELLS
;
return
val
;
}
u-boot-tree/scripts/dtc/libfdt/fdt_empty_tree.c
deleted
100644 → 0
View file @
3e304607
/*
* 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
);
}
u-boot-tree/scripts/dtc/libfdt/fdt_overlay.c
deleted
100644 → 0
View file @
3e304607
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2016 Free Electrons
* Copyright (C) 2016 NextThing Co.
*
* 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"
/**
* overlay_get_target_phandle - retrieves the target phandle of a fragment
* @fdto: pointer to the device tree overlay blob
* @fragment: node offset of the fragment in the overlay
*
* overlay_get_target_phandle() retrieves the target phandle of an
* overlay fragment when that fragment uses a phandle (target
* property) instead of a path (target-path property).
*
* returns:
* the phandle pointed by the target property
* 0, if the phandle was not found
* -1, if the phandle was malformed
*/
static
uint32_t
overlay_get_target_phandle
(
const
void
*
fdto
,
int
fragment
)
{
const
fdt32_t
*
val
;
int
len
;
val
=
fdt_getprop
(
fdto
,
fragment
,
"target"
,
&
len
);
if
(
!
val
)
return
0
;
if
((
len
!=
sizeof
(
*
val
))
||
(
fdt32_to_cpu
(
*
val
)
==
(
uint32_t
)
-
1
))
return
(
uint32_t
)
-
1
;
return
fdt32_to_cpu
(
*
val
);
}
/**
* overlay_get_target - retrieves the offset of a fragment's target
* @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
* done (through a phandle or a path)
*
* returns:
* the targetted node offset in the base device tree
* Negative error code on error
*/
static
int
overlay_get_target
(
const
void
*
fdt
,
const
void
*
fdto
,
int
fragment
,
char
const
**
pathp
)
{
uint32_t
phandle
;
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
;
/* 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
);
/*
* 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 pointer to path (if available) */
if
(
pathp
)
*
pathp
=
path
?
path
:
NULL
;
return
ret
;
}
/**
* overlay_phandle_add_offset - Increases a phandle by an offset
* @fdt: Base device tree blob
* @node: Device tree overlay blob
* @name: Name of the property to modify (phandle or linux,phandle)
* @delta: offset to apply
*
* overlay_phandle_add_offset() increments a node phandle by a given
* offset.
*
* returns:
* 0 on success.
* Negative error code on error
*/
static
int
overlay_phandle_add_offset
(
void
*
fdt
,
int
node
,
const
char
*
name
,
uint32_t
delta
)
{
const
fdt32_t
*
val
;
uint32_t
adj_val
;
int
len
;
val
=
fdt_getprop
(
fdt
,
node
,
name
,
&
len
);
if
(
!
val
)
return
len
;
if
(
len
!=
sizeof
(
*
val
))
return
-
FDT_ERR_BADPHANDLE
;
adj_val
=
fdt32_to_cpu
(
*
val
);
if
((
adj_val
+
delta
)
<
adj_val
)
return
-
FDT_ERR_NOPHANDLES
;
adj_val
+=
delta
;
if
(
adj_val
==
(
uint32_t
)
-
1
)
return
-
FDT_ERR_NOPHANDLES
;
return
fdt_setprop_inplace_u32
(
fdt
,
node
,
name
,
adj_val
);
}
/**
* overlay_adjust_node_phandles - Offsets the phandles of a node
* @fdto: Device tree overlay blob
* @node: Offset of the node we want to adjust
* @delta: Offset to shift the phandles of
*
* overlay_adjust_node_phandles() adds a constant to all the phandles
* of a given node. This is mainly use as part of the overlay
* application process, when we want to update all the overlay
* phandles to not conflict with the overlays of the base device tree.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_adjust_node_phandles
(
void
*
fdto
,
int
node
,
uint32_t
delta
)
{
int
child
;
int
ret
;
ret
=
overlay_phandle_add_offset
(
fdto
,
node
,
"phandle"
,
delta
);
if
(
ret
&&
ret
!=
-
FDT_ERR_NOTFOUND
)
return
ret
;
ret
=
overlay_phandle_add_offset
(
fdto
,
node
,
"linux,phandle"
,
delta
);
if
(
ret
&&
ret
!=
-
FDT_ERR_NOTFOUND
)
return
ret
;
fdt_for_each_subnode
(
child
,
fdto
,
node
)
{
ret
=
overlay_adjust_node_phandles
(
fdto
,
child
,
delta
);
if
(
ret
)
return
ret
;
}
return
0
;
}
/**
* overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
* @fdto: Device tree overlay blob
* @delta: Offset to shift the phandles of
*
* overlay_adjust_local_phandles() adds a constant to all the
* phandles of an overlay. This is mainly use as part of the overlay
* application process, when we want to update all the overlay
* phandles to not conflict with the overlays of the base device tree.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_adjust_local_phandles
(
void
*
fdto
,
uint32_t
delta
)
{
/*
* Start adjusting the phandles from the overlay root
*/
return
overlay_adjust_node_phandles
(
fdto
,
0
,
delta
);
}
/**
* overlay_update_local_node_references - Adjust the overlay references
* @fdto: Device tree overlay blob
* @tree_node: Node offset of the node to operate on
* @fixup_node: Node offset of the matching local fixups node
* @delta: Offset to shift the phandles of
*
* overlay_update_local_nodes_references() update the phandles
* pointing to a node within the device tree overlay by adding a
* constant delta.
*
* This is mainly used as part of a device tree application process,
* where you want the device tree overlays phandles to not conflict
* with the ones from the base device tree before merging them.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_update_local_node_references
(
void
*
fdto
,
int
tree_node
,
int
fixup_node
,
uint32_t
delta
)
{
int
fixup_prop
;
int
fixup_child
;
int
ret
;
fdt_for_each_property_offset
(
fixup_prop
,
fdto
,
fixup_node
)
{
const
fdt32_t
*
fixup_val
;
const
char
*
tree_val
;
const
char
*
name
;
int
fixup_len
;
int
tree_len
;
int
i
;
fixup_val
=
fdt_getprop_by_offset
(
fdto
,
fixup_prop
,
&
name
,
&
fixup_len
);
if
(
!
fixup_val
)
return
fixup_len
;
if
(
fixup_len
%
sizeof
(
uint32_t
))
return
-
FDT_ERR_BADOVERLAY
;
tree_val
=
fdt_getprop
(
fdto
,
tree_node
,
name
,
&
tree_len
);
if
(
!
tree_val
)
{
if
(
tree_len
==
-
FDT_ERR_NOTFOUND
)
return
-
FDT_ERR_BADOVERLAY
;
return
tree_len
;
}
for
(
i
=
0
;
i
<
(
fixup_len
/
sizeof
(
uint32_t
));
i
++
)
{
fdt32_t
adj_val
;
uint32_t
poffset
;
poffset
=
fdt32_to_cpu
(
fixup_val
[
i
]);
/*
* phandles to fixup can be unaligned.
*
* Use a memcpy for the architectures that do
* not support unaligned accesses.
*/
memcpy
(
&
adj_val
,
tree_val
+
poffset
,
sizeof
(
adj_val
));
adj_val
=
cpu_to_fdt32
(
fdt32_to_cpu
(
adj_val
)
+
delta
);
ret
=
fdt_setprop_inplace_namelen_partial
(
fdto
,
tree_node
,
name
,
strlen
(
name
),
poffset
,
&
adj_val
,
sizeof
(
adj_val
));
if
(
ret
==
-
FDT_ERR_NOSPACE
)
return
-
FDT_ERR_BADOVERLAY
;
if
(
ret
)
return
ret
;
}
}
fdt_for_each_subnode
(
fixup_child
,
fdto
,
fixup_node
)
{
const
char
*
fixup_child_name
=
fdt_get_name
(
fdto
,
fixup_child
,
NULL
);
int
tree_child
;
tree_child
=
fdt_subnode_offset
(
fdto
,
tree_node
,
fixup_child_name
);
if
(
tree_child
==
-
FDT_ERR_NOTFOUND
)
return
-
FDT_ERR_BADOVERLAY
;
if
(
tree_child
<
0
)
return
tree_child
;
ret
=
overlay_update_local_node_references
(
fdto
,
tree_child
,
fixup_child
,
delta
);
if
(
ret
)
return
ret
;
}
return
0
;
}
/**
* overlay_update_local_references - Adjust the overlay references
* @fdto: Device tree overlay blob
* @delta: Offset to shift the phandles of
*
* overlay_update_local_references() update all the phandles pointing
* to a node within the device tree overlay by adding a constant
* delta to not conflict with the base overlay.
*
* This is mainly used as part of a device tree application process,
* where you want the device tree overlays phandles to not conflict
* with the ones from the base device tree before merging them.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_update_local_references
(
void
*
fdto
,
uint32_t
delta
)
{
int
fixups
;
fixups
=
fdt_path_offset
(
fdto
,
"/__local_fixups__"
);
if
(
fixups
<
0
)
{
/* There's no local phandles to adjust, bail out */
if
(
fixups
==
-
FDT_ERR_NOTFOUND
)
return
0
;
return
fixups
;
}
/*
* Update our local references from the root of the tree
*/
return
overlay_update_local_node_references
(
fdto
,
0
,
fixups
,
delta
);
}
/**
* overlay_fixup_one_phandle - Set an overlay phandle to the base one
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
* @symbols_off: Node offset of the symbols node in the base device tree
* @path: Path to a node holding a phandle in the overlay
* @path_len: number of path characters to consider
* @name: Name of the property holding the phandle reference in the overlay
* @name_len: number of name characters to consider
* @poffset: Offset within the overlay property where the phandle is stored
* @label: Label of the node referenced by the phandle
*
* overlay_fixup_one_phandle() resolves an overlay phandle pointing to
* a node in the base device tree.
*
* This is part of the device tree overlay application process, when
* you want all the phandles in the overlay to point to the actual
* base dt nodes.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_fixup_one_phandle
(
void
*
fdt
,
void
*
fdto
,
int
symbols_off
,
const
char
*
path
,
uint32_t
path_len
,
const
char
*
name
,
uint32_t
name_len
,
int
poffset
,
const
char
*
label
)
{
const
char
*
symbol_path
;
uint32_t
phandle
;
fdt32_t
phandle_prop
;
int
symbol_off
,
fixup_off
;
int
prop_len
;
if
(
symbols_off
<
0
)
return
symbols_off
;
symbol_path
=
fdt_getprop
(
fdt
,
symbols_off
,
label
,
&
prop_len
);
if
(
!
symbol_path
)
return
prop_len
;
symbol_off
=
fdt_path_offset
(
fdt
,
symbol_path
);
if
(
symbol_off
<
0
)
return
symbol_off
;
phandle
=
fdt_get_phandle
(
fdt
,
symbol_off
);
if
(
!
phandle
)
return
-
FDT_ERR_NOTFOUND
;
fixup_off
=
fdt_path_offset_namelen
(
fdto
,
path
,
path_len
);
if
(
fixup_off
==
-
FDT_ERR_NOTFOUND
)
return
-
FDT_ERR_BADOVERLAY
;
if
(
fixup_off
<
0
)
return
fixup_off
;
phandle_prop
=
cpu_to_fdt32
(
phandle
);
return
fdt_setprop_inplace_namelen_partial
(
fdto
,
fixup_off
,
name
,
name_len
,
poffset
,
&
phandle_prop
,
sizeof
(
phandle_prop
));
};
/**
* overlay_fixup_phandle - Set an overlay phandle to the base one
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
* @symbols_off: Node offset of the symbols node in the base device tree
* @property: Property offset in the overlay holding the list of fixups
*
* overlay_fixup_phandle() resolves all the overlay phandles pointed
* to in a __fixups__ property, and updates them to match the phandles
* in use in the base device tree.
*
* This is part of the device tree overlay application process, when
* you want all the phandles in the overlay to point to the actual
* base dt nodes.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_fixup_phandle
(
void
*
fdt
,
void
*
fdto
,
int
symbols_off
,
int
property
)
{
const
char
*
value
;
const
char
*
label
;
int
len
;
value
=
fdt_getprop_by_offset
(
fdto
,
property
,
&
label
,
&
len
);
if
(
!
value
)
{
if
(
len
==
-
FDT_ERR_NOTFOUND
)
return
-
FDT_ERR_INTERNAL
;
return
len
;
}
do
{
const
char
*
path
,
*
name
,
*
fixup_end
;
const
char
*
fixup_str
=
value
;
uint32_t
path_len
,
name_len
;
uint32_t
fixup_len
;
char
*
sep
,
*
endptr
;
int
poffset
,
ret
;
fixup_end
=
memchr
(
value
,
'\0'
,
len
);
if
(
!
fixup_end
)
return
-
FDT_ERR_BADOVERLAY
;
fixup_len
=
fixup_end
-
fixup_str
;
len
-=
fixup_len
+
1
;
value
+=
fixup_len
+
1
;
path
=
fixup_str
;
sep
=
memchr
(
fixup_str
,
':'
,
fixup_len
);
if
(
!
sep
||
*
sep
!=
':'
)
return
-
FDT_ERR_BADOVERLAY
;
path_len
=
sep
-
path
;
if
(
path_len
==
(
fixup_len
-
1
))
return
-
FDT_ERR_BADOVERLAY
;
fixup_len
-=
path_len
+
1
;
name
=
sep
+
1
;
sep
=
memchr
(
name
,
':'
,
fixup_len
);
if
(
!
sep
||
*
sep
!=
':'
)
return
-
FDT_ERR_BADOVERLAY
;
name_len
=
sep
-
name
;
if
(
!
name_len
)
return
-
FDT_ERR_BADOVERLAY
;
poffset
=
strtoul
(
sep
+
1
,
&
endptr
,
10
);
if
((
*
endptr
!=
'\0'
)
||
(
endptr
<=
(
sep
+
1
)))
return
-
FDT_ERR_BADOVERLAY
;
ret
=
overlay_fixup_one_phandle
(
fdt
,
fdto
,
symbols_off
,
path
,
path_len
,
name
,
name_len
,
poffset
,
label
);
if
(
ret
)
return
ret
;
}
while
(
len
>
0
);
return
0
;
}
/**
* overlay_fixup_phandles - Resolve the overlay phandles to the base
* device tree
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
*
* overlay_fixup_phandles() resolves all the overlay phandles pointing
* to nodes in the base device tree.
*
* This is one of the steps of the device tree overlay application
* process, when you want all the phandles in the overlay to point to
* the actual base dt nodes.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_fixup_phandles
(
void
*
fdt
,
void
*
fdto
)
{
int
fixups_off
,
symbols_off
;
int
property
;
/* We can have overlays without any fixups */
fixups_off
=
fdt_path_offset
(
fdto
,
"/__fixups__"
);
if
(
fixups_off
==
-
FDT_ERR_NOTFOUND
)
return
0
;
/* nothing to do */
if
(
fixups_off
<
0
)
return
fixups_off
;
/* And base DTs without symbols */
symbols_off
=
fdt_path_offset
(
fdt
,
"/__symbols__"
);
if
((
symbols_off
<
0
&&
(
symbols_off
!=
-
FDT_ERR_NOTFOUND
)))
return
symbols_off
;
fdt_for_each_property_offset
(
property
,
fdto
,
fixups_off
)
{
int
ret
;
ret
=
overlay_fixup_phandle
(
fdt
,
fdto
,
symbols_off
,
property
);
if
(
ret
)
return
ret
;
}
return
0
;
}
/**
* overlay_apply_node - Merges a node into the base device tree
* @fdt: Base Device Tree blob
* @target: Node offset in the base device tree to apply the fragment to
* @fdto: Device tree overlay blob
* @node: Node offset in the overlay holding the changes to merge
*
* overlay_apply_node() merges a node into a target base device tree
* node pointed.
*
* This is part of the final 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.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_apply_node
(
void
*
fdt
,
int
target
,
void
*
fdto
,
int
node
)
{
int
property
;
int
subnode
;
fdt_for_each_property_offset
(
property
,
fdto
,
node
)
{
const
char
*
name
;
const
void
*
prop
;
int
prop_len
;
int
ret
;
prop
=
fdt_getprop_by_offset
(
fdto
,
property
,
&
name
,
&
prop_len
);
if
(
prop_len
==
-
FDT_ERR_NOTFOUND
)
return
-
FDT_ERR_INTERNAL
;
if
(
prop_len
<
0
)
return
prop_len
;
ret
=
fdt_setprop
(
fdt
,
target
,
name
,
prop
,
prop_len
);
if
(
ret
)
return
ret
;
}
fdt_for_each_subnode
(
subnode
,
fdto
,
node
)
{
const
char
*
name
=
fdt_get_name
(
fdto
,
subnode
,
NULL
);
int
nnode
;
int
ret
;
nnode
=
fdt_add_subnode
(
fdt
,
target
,
name
);
if
(
nnode
==
-
FDT_ERR_EXISTS
)
{
nnode
=
fdt_subnode_offset
(
fdt
,
target
,
name
);
if
(
nnode
==
-
FDT_ERR_NOTFOUND
)
return
-
FDT_ERR_INTERNAL
;
}
if
(
nnode
<
0
)
return
nnode
;
ret
=
overlay_apply_node
(
fdt
,
nnode
,
fdto
,
subnode
);
if
(
ret
)
return
ret
;
}
return
0
;
}
/**
* overlay_merge - Merge an overlay into its base device tree
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
*
* overlay_merge() merges an overlay into its base device tree.
*
* 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.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static
int
overlay_merge
(
void
*
fdt
,
void
*
fdto
)
{
int
fragment
;
fdt_for_each_subnode
(
fragment
,
fdto
,
0
)
{
int
overlay
;
int
target
;
int
ret
;
/*
* Each fragments will have an __overlay__ node. If
* they don't, it's not supposed to be merged
*/
overlay
=
fdt_subnode_offset
(
fdto
,
fragment
,
"__overlay__"
);
if
(
overlay
==
-
FDT_ERR_NOTFOUND
)
continue
;
if
(
overlay
<
0
)
return
overlay
;
target
=
overlay_get_target
(
fdt
,
fdto
,
fragment
,
NULL
);
if
(
target
<
0
)
return
target
;
ret
=
overlay_apply_node
(
fdt
,
target
,
fdto
,
overlay
);
if
(
ret
)
return
ret
;
}
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
);
int
ret
;
FDT_CHECK_HEADER
(
fdt
);
FDT_CHECK_HEADER
(
fdto
);
ret
=
overlay_adjust_local_phandles
(
fdto
,
delta
);
if
(
ret
)
goto
err
;
ret
=
overlay_update_local_references
(
fdto
,
delta
);
if
(
ret
)
goto
err
;
ret
=
overlay_fixup_phandles
(
fdt
,
fdto
);
if
(
ret
)
goto
err
;
ret
=
overlay_merge
(
fdt
,
fdto
);
if
(
ret
)
goto
err
;
ret
=
overlay_symbol_update
(
fdt
,
fdto
);
if
(
ret
)
goto
err
;
/*
* The overlay has been damaged, erase its magic.
*/
fdt_set_magic
(
fdto
,
~
0
);
return
0
;
err:
/*
* The overlay might have been damaged, erase its magic.
*/
fdt_set_magic
(
fdto
,
~
0
);
/*
* The base device tree might have been damaged, erase its
* magic.
*/
fdt_set_magic
(
fdt
,
~
0
);
return
ret
;
}
u-boot-tree/scripts/dtc/libfdt/fdt_ro.c
deleted
100644 → 0
View file @
3e304607
/*
* 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
)
{
int
olen
;
const
char
*
p
=
fdt_get_name
(
fdt
,
offset
,
&
olen
);
if
(
!
p
||
olen
<
len
)
/* 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
);
const
char
*
nameptr
;
int
err
;
if
(((
err
=
fdt_check_header
(
fdt
))
!=
0
)
||
((
err
=
fdt_check_node_offset_
(
fdt
,
nodeoffset
))
<
0
))
goto
fail
;
nameptr
=
nh
->
name
;
if
(
fdt_version
(
fdt
)
<
0x10
)
{
/*
* For old FDT versions, match the naming conventions of V16:
* give only the leaf name (after all /). The actual tree
* contents are loosely checked.
*/
const
char
*
leaf
;
leaf
=
strrchr
(
nameptr
,
'/'
);
if
(
leaf
==
NULL
)
{
err
=
-
FDT_ERR_BADSTRUCTURE
;
goto
fail
;
}
nameptr
=
leaf
+
1
;
}
if
(
len
)
*
len
=
strlen
(
nameptr
);
return
nameptr
;
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
);
}
static
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_by_offset
(
const
void
*
fdt
,
int
offset
,
int
*
lenp
)
{
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
if
(
fdt_version
(
fdt
)
<
0x10
)
{
if
(
lenp
)
*
lenp
=
-
FDT_ERR_BADVERSION
;
return
NULL
;
}
return
fdt_get_property_by_offset_
(
fdt
,
offset
,
lenp
);
}
static
const
struct
fdt_property
*
fdt_get_property_namelen_
(
const
void
*
fdt
,
int
offset
,
const
char
*
name
,
int
namelen
,
int
*
lenp
,
int
*
poffset
)
{
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
))
{
if
(
poffset
)
*
poffset
=
offset
;
return
prop
;
}
}
if
(
lenp
)
*
lenp
=
offset
;
return
NULL
;
}
const
struct
fdt_property
*
fdt_get_property_namelen
(
const
void
*
fdt
,
int
offset
,
const
char
*
name
,
int
namelen
,
int
*
lenp
)
{
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
if
(
fdt_version
(
fdt
)
<
0x10
)
{
if
(
lenp
)
*
lenp
=
-
FDT_ERR_BADVERSION
;
return
NULL
;
}
return
fdt_get_property_namelen_
(
fdt
,
offset
,
name
,
namelen
,
lenp
,
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
)
{
int
poffset
;
const
struct
fdt_property
*
prop
;
prop
=
fdt_get_property_namelen_
(
fdt
,
nodeoffset
,
name
,
namelen
,
lenp
,
&
poffset
);
if
(
!
prop
)
return
NULL
;
/* Handle realignment */
if
(
fdt_version
(
fdt
)
<
0x10
&&
(
poffset
+
sizeof
(
*
prop
))
%
8
&&
fdt32_to_cpu
(
prop
->
len
)
>=
8
)
return
prop
->
data
+
4
;
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
));
/* Handle realignment */
if
(
fdt_version
(
fdt
)
<
0x10
&&
(
offset
+
sizeof
(
*
prop
))
%
8
&&
fdt32_to_cpu
(
prop
->
len
)
>=
8
)
return
prop
->
data
+
4
;
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() */
}
u-boot-tree/scripts/dtc/libfdt/fdt_rw.c
deleted
100644 → 0
View file @
3e304607
/*
* 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
(((
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_placeholder
(
void
*
fdt
,
int
nodeoffset
,
const
char
*
name
,
int
len
,
void
**
prop_data
)
{
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
;
*
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
);
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
;
}
u-boot-tree/scripts/dtc/libfdt/fdt_strerror.c
deleted
100644 → 0
View file @
3e304607
/*
* 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
"<valid offset/length>"
;
else
if
(
errval
==
0
)
return
"<no error>"
;
else
if
(
errval
>
-
FDT_ERRTABSIZE
)
{
const
char
*
s
=
fdt_errtable
[
-
errval
].
str
;
if
(
s
)
return
s
;
}
return
"<unknown error>"
;
}
u-boot-tree/scripts/dtc/libfdt/fdt_sw.c
deleted
100644 → 0
View file @
3e304607
/*
* 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_placeholder
(
void
*
fdt
,
const
char
*
name
,
int
len
,
void
**
valp
)
{
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
);
*
valp
=
prop
->
data
;
return
0
;
}
int
fdt_property
(
void
*
fdt
,
const
char
*
name
,
const
void
*
val
,
int
len
)
{
void
*
ptr
;
int
ret
;
ret
=
fdt_property_placeholder
(
fdt
,
name
,
len
,
&
ptr
);
if
(
ret
)
return
ret
;
memcpy
(
ptr
,
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
;
}
u-boot-tree/scripts/dtc/libfdt/fdt_wip.c
deleted
100644 → 0
View file @
3e304607
/*
* 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
;
}
u-boot-tree/scripts/dtc/livetree.c
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "dtc.h"
/*
* Tree building functions
*/
void
add_label
(
struct
label
**
labels
,
char
*
label
)
{
struct
label
*
new
;
/* Make sure the label isn't already there */
for_each_label_withdel
(
*
labels
,
new
)
if
(
streq
(
new
->
label
,
label
))
{
new
->
deleted
=
0
;
return
;
}
new
=
xmalloc
(
sizeof
(
*
new
));
memset
(
new
,
0
,
sizeof
(
*
new
));
new
->
label
=
label
;
new
->
next
=
*
labels
;
*
labels
=
new
;
}
void
delete_labels
(
struct
label
**
labels
)
{
struct
label
*
label
;
for_each_label
(
*
labels
,
label
)
label
->
deleted
=
1
;
}
struct
property
*
build_property
(
char
*
name
,
struct
data
val
)
{
struct
property
*
new
=
xmalloc
(
sizeof
(
*
new
));
memset
(
new
,
0
,
sizeof
(
*
new
));
new
->
name
=
name
;
new
->
val
=
val
;
return
new
;
}
struct
property
*
build_property_delete
(
char
*
name
)
{
struct
property
*
new
=
xmalloc
(
sizeof
(
*
new
));
memset
(
new
,
0
,
sizeof
(
*
new
));
new
->
name
=
name
;
new
->
deleted
=
1
;
return
new
;
}
struct
property
*
chain_property
(
struct
property
*
first
,
struct
property
*
list
)
{
assert
(
first
->
next
==
NULL
);
first
->
next
=
list
;
return
first
;
}
struct
property
*
reverse_properties
(
struct
property
*
first
)
{
struct
property
*
p
=
first
;
struct
property
*
head
=
NULL
;
struct
property
*
next
;
while
(
p
)
{
next
=
p
->
next
;
p
->
next
=
head
;
head
=
p
;
p
=
next
;
}
return
head
;
}
struct
node
*
build_node
(
struct
property
*
proplist
,
struct
node
*
children
)
{
struct
node
*
new
=
xmalloc
(
sizeof
(
*
new
));
struct
node
*
child
;
memset
(
new
,
0
,
sizeof
(
*
new
));
new
->
proplist
=
reverse_properties
(
proplist
);
new
->
children
=
children
;
for_each_child
(
new
,
child
)
{
child
->
parent
=
new
;
}
return
new
;
}
struct
node
*
build_node_delete
(
void
)
{
struct
node
*
new
=
xmalloc
(
sizeof
(
*
new
));
memset
(
new
,
0
,
sizeof
(
*
new
));
new
->
deleted
=
1
;
return
new
;
}
struct
node
*
name_node
(
struct
node
*
node
,
char
*
name
)
{
assert
(
node
->
name
==
NULL
);
node
->
name
=
name
;
return
node
;
}
struct
node
*
merge_nodes
(
struct
node
*
old_node
,
struct
node
*
new_node
)
{
struct
property
*
new_prop
,
*
old_prop
;
struct
node
*
new_child
,
*
old_child
;
struct
label
*
l
;
old_node
->
deleted
=
0
;
/* Add new node labels to old node */
for_each_label_withdel
(
new_node
->
labels
,
l
)
add_label
(
&
old_node
->
labels
,
l
->
label
);
/* Move properties from the new node to the old node. If there
* is a collision, replace the old value with the new */
while
(
new_node
->
proplist
)
{
/* Pop the property off the list */
new_prop
=
new_node
->
proplist
;
new_node
->
proplist
=
new_prop
->
next
;
new_prop
->
next
=
NULL
;
if
(
new_prop
->
deleted
)
{
delete_property_by_name
(
old_node
,
new_prop
->
name
);
free
(
new_prop
);
continue
;
}
/* Look for a collision, set new value if there is */
for_each_property_withdel
(
old_node
,
old_prop
)
{
if
(
streq
(
old_prop
->
name
,
new_prop
->
name
))
{
/* Add new labels to old property */
for_each_label_withdel
(
new_prop
->
labels
,
l
)
add_label
(
&
old_prop
->
labels
,
l
->
label
);
old_prop
->
val
=
new_prop
->
val
;
old_prop
->
deleted
=
0
;
free
(
new_prop
);
new_prop
=
NULL
;
break
;
}
}
/* if no collision occurred, add property to the old node. */
if
(
new_prop
)
add_property
(
old_node
,
new_prop
);
}
/* Move the override child nodes into the primary node. If
* there is a collision, then merge the nodes. */
while
(
new_node
->
children
)
{
/* Pop the child node off the list */
new_child
=
new_node
->
children
;
new_node
->
children
=
new_child
->
next_sibling
;
new_child
->
parent
=
NULL
;
new_child
->
next_sibling
=
NULL
;
if
(
new_child
->
deleted
)
{
delete_node_by_name
(
old_node
,
new_child
->
name
);
free
(
new_child
);
continue
;
}
/* Search for a collision. Merge if there is */
for_each_child_withdel
(
old_node
,
old_child
)
{
if
(
streq
(
old_child
->
name
,
new_child
->
name
))
{
merge_nodes
(
old_child
,
new_child
);
new_child
=
NULL
;
break
;
}
}
/* if no collision occurred, add child to the old node. */
if
(
new_child
)
add_child
(
old_node
,
new_child
);
}
/* The new node contents are now merged into the old node. Free
* the new node. */
free
(
new_node
);
return
old_node
;
}
struct
node
*
add_orphan_node
(
struct
node
*
dt
,
struct
node
*
new_node
,
char
*
ref
)
{
static
unsigned
int
next_orphan_fragment
=
0
;
struct
node
*
node
;
struct
property
*
p
;
struct
data
d
=
empty_data
;
char
*
name
;
d
=
data_add_marker
(
d
,
REF_PHANDLE
,
ref
);
d
=
data_append_integer
(
d
,
0xffffffff
,
32
);
p
=
build_property
(
"target"
,
d
);
xasprintf
(
&
name
,
"fragment@%u"
,
next_orphan_fragment
++
);
name_node
(
new_node
,
"__overlay__"
);
node
=
build_node
(
p
,
new_node
);
name_node
(
node
,
name
);
add_child
(
dt
,
node
);
return
dt
;
}
struct
node
*
chain_node
(
struct
node
*
first
,
struct
node
*
list
)
{
assert
(
first
->
next_sibling
==
NULL
);
first
->
next_sibling
=
list
;
return
first
;
}
void
add_property
(
struct
node
*
node
,
struct
property
*
prop
)
{
struct
property
**
p
;
prop
->
next
=
NULL
;
p
=
&
node
->
proplist
;
while
(
*
p
)
p
=
&
((
*
p
)
->
next
);
*
p
=
prop
;
}
void
delete_property_by_name
(
struct
node
*
node
,
char
*
name
)
{
struct
property
*
prop
=
node
->
proplist
;
while
(
prop
)
{
if
(
streq
(
prop
->
name
,
name
))
{
delete_property
(
prop
);
return
;
}
prop
=
prop
->
next
;
}
}
void
delete_property
(
struct
property
*
prop
)
{
prop
->
deleted
=
1
;
delete_labels
(
&
prop
->
labels
);
}
void
add_child
(
struct
node
*
parent
,
struct
node
*
child
)
{
struct
node
**
p
;
child
->
next_sibling
=
NULL
;
child
->
parent
=
parent
;
p
=
&
parent
->
children
;
while
(
*
p
)
p
=
&
((
*
p
)
->
next_sibling
);
*
p
=
child
;
}
void
delete_node_by_name
(
struct
node
*
parent
,
char
*
name
)
{
struct
node
*
node
=
parent
->
children
;
while
(
node
)
{
if
(
streq
(
node
->
name
,
name
))
{
delete_node
(
node
);
return
;
}
node
=
node
->
next_sibling
;
}
}
void
delete_node
(
struct
node
*
node
)
{
struct
property
*
prop
;
struct
node
*
child
;
node
->
deleted
=
1
;
for_each_child
(
node
,
child
)
delete_node
(
child
);
for_each_property
(
node
,
prop
)
delete_property
(
prop
);
delete_labels
(
&
node
->
labels
);
}
void
append_to_property
(
struct
node
*
node
,
char
*
name
,
const
void
*
data
,
int
len
)
{
struct
data
d
;
struct
property
*
p
;
p
=
get_property
(
node
,
name
);
if
(
p
)
{
d
=
data_append_data
(
p
->
val
,
data
,
len
);
p
->
val
=
d
;
}
else
{
d
=
data_append_data
(
empty_data
,
data
,
len
);
p
=
build_property
(
name
,
d
);
add_property
(
node
,
p
);
}
}
struct
reserve_info
*
build_reserve_entry
(
uint64_t
address
,
uint64_t
size
)
{
struct
reserve_info
*
new
=
xmalloc
(
sizeof
(
*
new
));
memset
(
new
,
0
,
sizeof
(
*
new
));
new
->
address
=
address
;
new
->
size
=
size
;
return
new
;
}
struct
reserve_info
*
chain_reserve_entry
(
struct
reserve_info
*
first
,
struct
reserve_info
*
list
)
{
assert
(
first
->
next
==
NULL
);
first
->
next
=
list
;
return
first
;
}
struct
reserve_info
*
add_reserve_entry
(
struct
reserve_info
*
list
,
struct
reserve_info
*
new
)
{
struct
reserve_info
*
last
;
new
->
next
=
NULL
;
if
(
!
list
)
return
new
;
for
(
last
=
list
;
last
->
next
;
last
=
last
->
next
)
;
last
->
next
=
new
;
return
list
;
}
struct
dt_info
*
build_dt_info
(
unsigned
int
dtsflags
,
struct
reserve_info
*
reservelist
,
struct
node
*
tree
,
uint32_t
boot_cpuid_phys
)
{
struct
dt_info
*
dti
;
dti
=
xmalloc
(
sizeof
(
*
dti
));
dti
->
dtsflags
=
dtsflags
;
dti
->
reservelist
=
reservelist
;
dti
->
dt
=
tree
;
dti
->
boot_cpuid_phys
=
boot_cpuid_phys
;
return
dti
;
}
/*
* Tree accessor functions
*/
const
char
*
get_unitname
(
struct
node
*
node
)
{
if
(
node
->
name
[
node
->
basenamelen
]
==
'\0'
)
return
""
;
else
return
node
->
name
+
node
->
basenamelen
+
1
;
}
struct
property
*
get_property
(
struct
node
*
node
,
const
char
*
propname
)
{
struct
property
*
prop
;
for_each_property
(
node
,
prop
)
if
(
streq
(
prop
->
name
,
propname
))
return
prop
;
return
NULL
;
}
cell_t
propval_cell
(
struct
property
*
prop
)
{
assert
(
prop
->
val
.
len
==
sizeof
(
cell_t
));
return
fdt32_to_cpu
(
*
((
fdt32_t
*
)
prop
->
val
.
val
));
}
cell_t
propval_cell_n
(
struct
property
*
prop
,
int
n
)
{
assert
(
prop
->
val
.
len
/
sizeof
(
cell_t
)
>=
n
);
return
fdt32_to_cpu
(
*
((
fdt32_t
*
)
prop
->
val
.
val
+
n
));
}
struct
property
*
get_property_by_label
(
struct
node
*
tree
,
const
char
*
label
,
struct
node
**
node
)
{
struct
property
*
prop
;
struct
node
*
c
;
*
node
=
tree
;
for_each_property
(
tree
,
prop
)
{
struct
label
*
l
;
for_each_label
(
prop
->
labels
,
l
)
if
(
streq
(
l
->
label
,
label
))
return
prop
;
}
for_each_child
(
tree
,
c
)
{
prop
=
get_property_by_label
(
c
,
label
,
node
);
if
(
prop
)
return
prop
;
}
*
node
=
NULL
;
return
NULL
;
}
struct
marker
*
get_marker_label
(
struct
node
*
tree
,
const
char
*
label
,
struct
node
**
node
,
struct
property
**
prop
)
{
struct
marker
*
m
;
struct
property
*
p
;
struct
node
*
c
;
*
node
=
tree
;
for_each_property
(
tree
,
p
)
{
*
prop
=
p
;
m
=
p
->
val
.
markers
;
for_each_marker_of_type
(
m
,
LABEL
)
if
(
streq
(
m
->
ref
,
label
))
return
m
;
}
for_each_child
(
tree
,
c
)
{
m
=
get_marker_label
(
c
,
label
,
node
,
prop
);
if
(
m
)
return
m
;
}
*
prop
=
NULL
;
*
node
=
NULL
;
return
NULL
;
}
struct
node
*
get_subnode
(
struct
node
*
node
,
const
char
*
nodename
)
{
struct
node
*
child
;
for_each_child
(
node
,
child
)
if
(
streq
(
child
->
name
,
nodename
))
return
child
;
return
NULL
;
}
struct
node
*
get_node_by_path
(
struct
node
*
tree
,
const
char
*
path
)
{
const
char
*
p
;
struct
node
*
child
;
if
(
!
path
||
!
(
*
path
))
{
if
(
tree
->
deleted
)
return
NULL
;
return
tree
;
}
while
(
path
[
0
]
==
'/'
)
path
++
;
p
=
strchr
(
path
,
'/'
);
for_each_child
(
tree
,
child
)
{
if
(
p
&&
(
strlen
(
child
->
name
)
==
p
-
path
)
&&
strprefixeq
(
path
,
p
-
path
,
child
->
name
))
return
get_node_by_path
(
child
,
p
+
1
);
else
if
(
!
p
&&
streq
(
path
,
child
->
name
))
return
child
;
}
return
NULL
;
}
struct
node
*
get_node_by_label
(
struct
node
*
tree
,
const
char
*
label
)
{
struct
node
*
child
,
*
node
;
struct
label
*
l
;
assert
(
label
&&
(
strlen
(
label
)
>
0
));
for_each_label
(
tree
->
labels
,
l
)
if
(
streq
(
l
->
label
,
label
))
return
tree
;
for_each_child
(
tree
,
child
)
{
node
=
get_node_by_label
(
child
,
label
);
if
(
node
)
return
node
;
}
return
NULL
;
}
struct
node
*
get_node_by_phandle
(
struct
node
*
tree
,
cell_t
phandle
)
{
struct
node
*
child
,
*
node
;
if
((
phandle
==
0
)
||
(
phandle
==
-
1
))
{
assert
(
generate_fixups
);
return
NULL
;
}
if
(
tree
->
phandle
==
phandle
)
{
if
(
tree
->
deleted
)
return
NULL
;
return
tree
;
}
for_each_child
(
tree
,
child
)
{
node
=
get_node_by_phandle
(
child
,
phandle
);
if
(
node
)
return
node
;
}
return
NULL
;
}
struct
node
*
get_node_by_ref
(
struct
node
*
tree
,
const
char
*
ref
)
{
if
(
streq
(
ref
,
"/"
))
return
tree
;
else
if
(
ref
[
0
]
==
'/'
)
return
get_node_by_path
(
tree
,
ref
);
else
return
get_node_by_label
(
tree
,
ref
);
}
cell_t
get_node_phandle
(
struct
node
*
root
,
struct
node
*
node
)
{
static
cell_t
phandle
=
1
;
/* FIXME: ick, static local */
if
((
node
->
phandle
!=
0
)
&&
(
node
->
phandle
!=
-
1
))
return
node
->
phandle
;
while
(
get_node_by_phandle
(
root
,
phandle
))
phandle
++
;
node
->
phandle
=
phandle
;
if
(
!
get_property
(
node
,
"linux,phandle"
)
&&
(
phandle_format
&
PHANDLE_LEGACY
))
add_property
(
node
,
build_property
(
"linux,phandle"
,
data_append_cell
(
empty_data
,
phandle
)));
if
(
!
get_property
(
node
,
"phandle"
)
&&
(
phandle_format
&
PHANDLE_EPAPR
))
add_property
(
node
,
build_property
(
"phandle"
,
data_append_cell
(
empty_data
,
phandle
)));
/* If the node *does* have a phandle property, we must
* be dealing with a self-referencing phandle, which will be
* fixed up momentarily in the caller */
return
node
->
phandle
;
}
uint32_t
guess_boot_cpuid
(
struct
node
*
tree
)
{
struct
node
*
cpus
,
*
bootcpu
;
struct
property
*
reg
;
cpus
=
get_node_by_path
(
tree
,
"/cpus"
);
if
(
!
cpus
)
return
0
;
bootcpu
=
cpus
->
children
;
if
(
!
bootcpu
)
return
0
;
reg
=
get_property
(
bootcpu
,
"reg"
);
if
(
!
reg
||
(
reg
->
val
.
len
!=
sizeof
(
uint32_t
)))
return
0
;
/* FIXME: Sanity check node? */
return
propval_cell
(
reg
);
}
static
int
cmp_reserve_info
(
const
void
*
ax
,
const
void
*
bx
)
{
const
struct
reserve_info
*
a
,
*
b
;
a
=
*
((
const
struct
reserve_info
*
const
*
)
ax
);
b
=
*
((
const
struct
reserve_info
*
const
*
)
bx
);
if
(
a
->
address
<
b
->
address
)
return
-
1
;
else
if
(
a
->
address
>
b
->
address
)
return
1
;
else
if
(
a
->
size
<
b
->
size
)
return
-
1
;
else
if
(
a
->
size
>
b
->
size
)
return
1
;
else
return
0
;
}
static
void
sort_reserve_entries
(
struct
dt_info
*
dti
)
{
struct
reserve_info
*
ri
,
**
tbl
;
int
n
=
0
,
i
=
0
;
for
(
ri
=
dti
->
reservelist
;
ri
;
ri
=
ri
->
next
)
n
++
;
if
(
n
==
0
)
return
;
tbl
=
xmalloc
(
n
*
sizeof
(
*
tbl
));
for
(
ri
=
dti
->
reservelist
;
ri
;
ri
=
ri
->
next
)
tbl
[
i
++
]
=
ri
;
qsort
(
tbl
,
n
,
sizeof
(
*
tbl
),
cmp_reserve_info
);
dti
->
reservelist
=
tbl
[
0
];
for
(
i
=
0
;
i
<
(
n
-
1
);
i
++
)
tbl
[
i
]
->
next
=
tbl
[
i
+
1
];
tbl
[
n
-
1
]
->
next
=
NULL
;
free
(
tbl
);
}
static
int
cmp_prop
(
const
void
*
ax
,
const
void
*
bx
)
{
const
struct
property
*
a
,
*
b
;
a
=
*
((
const
struct
property
*
const
*
)
ax
);
b
=
*
((
const
struct
property
*
const
*
)
bx
);
return
strcmp
(
a
->
name
,
b
->
name
);
}
static
void
sort_properties
(
struct
node
*
node
)
{
int
n
=
0
,
i
=
0
;
struct
property
*
prop
,
**
tbl
;
for_each_property_withdel
(
node
,
prop
)
n
++
;
if
(
n
==
0
)
return
;
tbl
=
xmalloc
(
n
*
sizeof
(
*
tbl
));
for_each_property_withdel
(
node
,
prop
)
tbl
[
i
++
]
=
prop
;
qsort
(
tbl
,
n
,
sizeof
(
*
tbl
),
cmp_prop
);
node
->
proplist
=
tbl
[
0
];
for
(
i
=
0
;
i
<
(
n
-
1
);
i
++
)
tbl
[
i
]
->
next
=
tbl
[
i
+
1
];
tbl
[
n
-
1
]
->
next
=
NULL
;
free
(
tbl
);
}
static
int
cmp_subnode
(
const
void
*
ax
,
const
void
*
bx
)
{
const
struct
node
*
a
,
*
b
;
a
=
*
((
const
struct
node
*
const
*
)
ax
);
b
=
*
((
const
struct
node
*
const
*
)
bx
);
return
strcmp
(
a
->
name
,
b
->
name
);
}
static
void
sort_subnodes
(
struct
node
*
node
)
{
int
n
=
0
,
i
=
0
;
struct
node
*
subnode
,
**
tbl
;
for_each_child_withdel
(
node
,
subnode
)
n
++
;
if
(
n
==
0
)
return
;
tbl
=
xmalloc
(
n
*
sizeof
(
*
tbl
));
for_each_child_withdel
(
node
,
subnode
)
tbl
[
i
++
]
=
subnode
;
qsort
(
tbl
,
n
,
sizeof
(
*
tbl
),
cmp_subnode
);
node
->
children
=
tbl
[
0
];
for
(
i
=
0
;
i
<
(
n
-
1
);
i
++
)
tbl
[
i
]
->
next_sibling
=
tbl
[
i
+
1
];
tbl
[
n
-
1
]
->
next_sibling
=
NULL
;
free
(
tbl
);
}
static
void
sort_node
(
struct
node
*
node
)
{
struct
node
*
c
;
sort_properties
(
node
);
sort_subnodes
(
node
);
for_each_child_withdel
(
node
,
c
)
sort_node
(
c
);
}
void
sort_tree
(
struct
dt_info
*
dti
)
{
sort_reserve_entries
(
dti
);
sort_node
(
dti
->
dt
);
}
/* utility helper to avoid code duplication */
static
struct
node
*
build_and_name_child_node
(
struct
node
*
parent
,
char
*
name
)
{
struct
node
*
node
;
node
=
build_node
(
NULL
,
NULL
);
name_node
(
node
,
xstrdup
(
name
));
add_child
(
parent
,
node
);
return
node
;
}
static
struct
node
*
build_root_node
(
struct
node
*
dt
,
char
*
name
)
{
struct
node
*
an
;
an
=
get_subnode
(
dt
,
name
);
if
(
!
an
)
an
=
build_and_name_child_node
(
dt
,
name
);
if
(
!
an
)
die
(
"Could not build root node /%s
\n
"
,
name
);
return
an
;
}
static
bool
any_label_tree
(
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
c
;
if
(
node
->
labels
)
return
true
;
for_each_child
(
node
,
c
)
if
(
any_label_tree
(
dti
,
c
))
return
true
;
return
false
;
}
static
void
generate_label_tree_internal
(
struct
dt_info
*
dti
,
struct
node
*
an
,
struct
node
*
node
,
bool
allocph
)
{
struct
node
*
dt
=
dti
->
dt
;
struct
node
*
c
;
struct
property
*
p
;
struct
label
*
l
;
/* if there are labels */
if
(
node
->
labels
)
{
/* now add the label in the node */
for_each_label
(
node
->
labels
,
l
)
{
/* check whether the label already exists */
p
=
get_property
(
an
,
l
->
label
);
if
(
p
)
{
fprintf
(
stderr
,
"WARNING: label %s already"
" exists in /%s"
,
l
->
label
,
an
->
name
);
continue
;
}
/* insert it */
p
=
build_property
(
l
->
label
,
data_copy_mem
(
node
->
fullpath
,
strlen
(
node
->
fullpath
)
+
1
));
add_property
(
an
,
p
);
}
/* force allocation of a phandle for this node */
if
(
allocph
)
(
void
)
get_node_phandle
(
dt
,
node
);
}
for_each_child
(
node
,
c
)
generate_label_tree_internal
(
dti
,
an
,
c
,
allocph
);
}
static
bool
any_fixup_tree
(
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
c
;
struct
property
*
prop
;
struct
marker
*
m
;
for_each_property
(
node
,
prop
)
{
m
=
prop
->
val
.
markers
;
for_each_marker_of_type
(
m
,
REF_PHANDLE
)
{
if
(
!
get_node_by_ref
(
dti
->
dt
,
m
->
ref
))
return
true
;
}
}
for_each_child
(
node
,
c
)
{
if
(
any_fixup_tree
(
dti
,
c
))
return
true
;
}
return
false
;
}
static
void
add_fixup_entry
(
struct
dt_info
*
dti
,
struct
node
*
fn
,
struct
node
*
node
,
struct
property
*
prop
,
struct
marker
*
m
)
{
char
*
entry
;
/* m->ref can only be a REF_PHANDLE, but check anyway */
assert
(
m
->
type
==
REF_PHANDLE
);
/* there shouldn't be any ':' in the arguments */
if
(
strchr
(
node
->
fullpath
,
':'
)
||
strchr
(
prop
->
name
,
':'
))
die
(
"arguments should not contain ':'
\n
"
);
xasprintf
(
&
entry
,
"%s:%s:%u"
,
node
->
fullpath
,
prop
->
name
,
m
->
offset
);
append_to_property
(
fn
,
m
->
ref
,
entry
,
strlen
(
entry
)
+
1
);
free
(
entry
);
}
static
void
generate_fixups_tree_internal
(
struct
dt_info
*
dti
,
struct
node
*
fn
,
struct
node
*
node
)
{
struct
node
*
dt
=
dti
->
dt
;
struct
node
*
c
;
struct
property
*
prop
;
struct
marker
*
m
;
struct
node
*
refnode
;
for_each_property
(
node
,
prop
)
{
m
=
prop
->
val
.
markers
;
for_each_marker_of_type
(
m
,
REF_PHANDLE
)
{
refnode
=
get_node_by_ref
(
dt
,
m
->
ref
);
if
(
!
refnode
)
add_fixup_entry
(
dti
,
fn
,
node
,
prop
,
m
);
}
}
for_each_child
(
node
,
c
)
generate_fixups_tree_internal
(
dti
,
fn
,
c
);
}
static
bool
any_local_fixup_tree
(
struct
dt_info
*
dti
,
struct
node
*
node
)
{
struct
node
*
c
;
struct
property
*
prop
;
struct
marker
*
m
;
for_each_property
(
node
,
prop
)
{
m
=
prop
->
val
.
markers
;
for_each_marker_of_type
(
m
,
REF_PHANDLE
)
{
if
(
get_node_by_ref
(
dti
->
dt
,
m
->
ref
))
return
true
;
}
}
for_each_child
(
node
,
c
)
{
if
(
any_local_fixup_tree
(
dti
,
c
))
return
true
;
}
return
false
;
}
static
void
add_local_fixup_entry
(
struct
dt_info
*
dti
,
struct
node
*
lfn
,
struct
node
*
node
,
struct
property
*
prop
,
struct
marker
*
m
,
struct
node
*
refnode
)
{
struct
node
*
wn
,
*
nwn
;
/* local fixup node, walk node, new */
fdt32_t
value_32
;
char
**
compp
;
int
i
,
depth
;
/* walk back retreiving depth */
depth
=
0
;
for
(
wn
=
node
;
wn
;
wn
=
wn
->
parent
)
depth
++
;
/* allocate name array */
compp
=
xmalloc
(
sizeof
(
*
compp
)
*
depth
);
/* store names in the array */
for
(
wn
=
node
,
i
=
depth
-
1
;
wn
;
wn
=
wn
->
parent
,
i
--
)
compp
[
i
]
=
wn
->
name
;
/* walk the path components creating nodes if they don't exist */
for
(
wn
=
lfn
,
i
=
1
;
i
<
depth
;
i
++
,
wn
=
nwn
)
{
/* if no node exists, create it */
nwn
=
get_subnode
(
wn
,
compp
[
i
]);
if
(
!
nwn
)
nwn
=
build_and_name_child_node
(
wn
,
compp
[
i
]);
}
free
(
compp
);
value_32
=
cpu_to_fdt32
(
m
->
offset
);
append_to_property
(
wn
,
prop
->
name
,
&
value_32
,
sizeof
(
value_32
));
}
static
void
generate_local_fixups_tree_internal
(
struct
dt_info
*
dti
,
struct
node
*
lfn
,
struct
node
*
node
)
{
struct
node
*
dt
=
dti
->
dt
;
struct
node
*
c
;
struct
property
*
prop
;
struct
marker
*
m
;
struct
node
*
refnode
;
for_each_property
(
node
,
prop
)
{
m
=
prop
->
val
.
markers
;
for_each_marker_of_type
(
m
,
REF_PHANDLE
)
{
refnode
=
get_node_by_ref
(
dt
,
m
->
ref
);
if
(
refnode
)
add_local_fixup_entry
(
dti
,
lfn
,
node
,
prop
,
m
,
refnode
);
}
}
for_each_child
(
node
,
c
)
generate_local_fixups_tree_internal
(
dti
,
lfn
,
c
);
}
void
generate_label_tree
(
struct
dt_info
*
dti
,
char
*
name
,
bool
allocph
)
{
if
(
!
any_label_tree
(
dti
,
dti
->
dt
))
return
;
generate_label_tree_internal
(
dti
,
build_root_node
(
dti
->
dt
,
name
),
dti
->
dt
,
allocph
);
}
void
generate_fixups_tree
(
struct
dt_info
*
dti
,
char
*
name
)
{
if
(
!
any_fixup_tree
(
dti
,
dti
->
dt
))
return
;
generate_fixups_tree_internal
(
dti
,
build_root_node
(
dti
->
dt
,
name
),
dti
->
dt
);
}
void
generate_local_fixups_tree
(
struct
dt_info
*
dti
,
char
*
name
)
{
if
(
!
any_local_fixup_tree
(
dti
,
dti
->
dt
))
return
;
generate_local_fixups_tree_internal
(
dti
,
build_root_node
(
dti
->
dt
,
name
),
dti
->
dt
);
}
u-boot-tree/scripts/dtc/pylibfdt/.gitignore
deleted
100644 → 0
View file @
3e304607
/_libfdt.so
/libfdt.py
/libfdt.pyc
/libfdt_wrap.c
u-boot-tree/scripts/dtc/pylibfdt/Makefile
deleted
100644 → 0
View file @
3e304607
# Unfortunately setup.py below cannot handle srctree being ".." which it often
# is. It fails with an error like:
# Fatal error: can't create build/temp.linux-x86_64-2.7/../lib/libfdt/fdt.o:
# No such file or directory
# To fix this, use an absolute path.
LIBFDT_srcdir
=
$
(
abspath
$(srctree)
/
$(src)
/../libfdt
)
include
$(LIBFDT_srcdir)/Makefile.libfdt
# Unfortunately setup.py (or actually the Python distutil implementation) puts
# files into the same directory as the .i file. We cannot touch the source
# directory, so we "ship" .i file into the objtree.
PYLIBFDT_srcs
=
$
(
addprefix
$(LIBFDT_srcdir)
/,
$(LIBFDT_SRCS)
)
\
$(obj)
/libfdt.i
quiet_cmd_pymod
=
PYMOD
$@
cmd_pymod
=
unset
CROSS_COMPILE
;
unset
CFLAGS
;
\
CC
=
"
$(HOSTCC)
"
LDSHARED
=
"
$(HOSTCC)
-shared "
\
LDFLAGS
=
"
$(HOSTLDFLAGS)
"
\
VERSION
=
"u-boot-
$(UBOOTVERSION)
"
\
CPPFLAGS
=
"
$(HOSTCFLAGS)
-I
$(LIBFDT_srcdir)
"
OBJDIR
=
$(obj)
\
SOURCES
=
"
$(PYLIBFDT_srcs)
"
\
SWIG_OPTS
=
"-I
$(LIBFDT_srcdir)
-I
$(LIBFDT_srcdir)
/.."
\
$(PYTHON)
$<
--quiet
build_ext
--inplace
$(obj)/_libfdt.so
:
$(src)/setup.py $(PYLIBFDT_srcs) FORCE
$
(
call if_changed,pymod
)
always
+=
_libfdt.so
clean-files
+=
libfdt.i _libfdt.so libfdt.py libfdt_wrap.c
u-boot-tree/scripts/dtc/pylibfdt/libfdt.i_shipped
deleted
100644 → 0
View file @
3e304607
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
/*
* pylibfdt - Flat Device Tree manipulation in Python
* Copyright (C) 2017 Google, Inc.
* Written by Simon Glass <sjg@chromium.org>
*/
%module libfdt
%include <stdint.i>
%{
#define SWIG_FILE_WITH_INIT
#include "libfdt.h"
/*
* We rename this function here to avoid problems with swig, since we also have
* a struct called fdt_property. That struct causes swig to create a class in
* libfdt.py called fdt_property(), which confuses things.
*/
static int fdt_property_stub(void *fdt, const char *name, const char *val,
int len)
{
return fdt_property(fdt, name, val, len);
}
%}
%pythoncode %{
import struct
# Error codes, corresponding to FDT_ERR_... in libfdt.h
(NOTFOUND,
EXISTS,
NOSPACE,
BADOFFSET,
BADPATH,
BADPHANDLE,
BADSTATE,
TRUNCATED,
BADMAGIC,
BADVERSION,
BADSTRUCTURE,
BADLAYOUT,
INTERNAL,
BADNCELLS,
BADVALUE,
BADOVERLAY,
NOPHANDLES) = QUIET_ALL = range(1, 18)
# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
# altogether. All # functions passed this value will return an error instead
# of raising an exception.
# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
# instead of raising an exception.
QUIET_NOTFOUND = (NOTFOUND,)
QUIET_NOSPACE = (NOSPACE,)
class FdtException(Exception):
"""An exception caused by an error such as one of the codes above"""
def __init__(self, err):
self.err = err
def __str__(self):
return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
def strerror(fdt_err):
"""Get the string for an error number
Args:
fdt_err: Error number (-ve)
Returns:
String containing the associated error
"""
return fdt_strerror(fdt_err)
def check_err(val, quiet=()):
"""Raise an error if the return value is -ve
This is used to check for errors returned by libfdt C functions.
Args:
val: Return value from a libfdt function
quiet: Errors to ignore (empty to raise on all errors)
Returns:
val if val >= 0
Raises
FdtException if val < 0
"""
if val < 0:
if -val not in quiet:
raise FdtException(val)
return val
def check_err_null(val, quiet=()):
"""Raise an error if the return value is NULL
This is used to check for a NULL return value from certain libfdt C
functions
Args:
val: Return value from a libfdt function
quiet: Errors to ignore (empty to raise on all errors)
Returns:
val if val is a list, None if not
Raises
FdtException if val indicates an error was reported and the error
is not in @quiet.
"""
# Normally a list is returned which contains the data and its length.
# If we get just an integer error code, it means the function failed.
if not isinstance(val, list):
if -val not in quiet:
raise FdtException(val)
return val
class FdtRo(object):
"""Class for a read-only device-tree
This is a base class used by FdtRw (read-write access) and FdtSw
(sequential-write access). It implements read-only access to the
device tree.
Here are the three classes and when you should use them:
FdtRo - read-only access to an existing FDT
FdtRw - read-write access to an existing FDT (most common case)
FdtSw - for creating a new FDT, as well as allowing read-only access
"""
def __init__(self, data):
self._fdt = bytearray(data)
check_err(fdt_check_header(self._fdt));
def as_bytearray(self):
"""Get the device tree contents as a bytearray
This can be passed directly to libfdt functions that access a
const void * for the device tree.
Returns:
bytearray containing the device tree
"""
return bytearray(self._fdt)
def next_node(self, nodeoffset, depth, quiet=()):
"""Find the next subnode
Args:
nodeoffset: Node offset of previous node
depth: The depth of the node at nodeoffset. This is used to
calculate the depth of the returned node
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Typle:
Offset of the next node, if any, else a -ve error
Depth of the returned node, if any, else undefined
Raises:
FdtException if no more nodes found or other error occurs
"""
return check_err(fdt_next_node(self._fdt, nodeoffset, depth), quiet)
def first_subnode(self, nodeoffset, quiet=()):
"""Find the first subnode of a parent node
Args:
nodeoffset: Node offset of parent node
quiet: Errors to ignore (empty to raise on all errors)
Returns:
The offset of the first subnode, if any
Raises:
FdtException if no subnodes found or other error occurs
"""
return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
def next_subnode(self, nodeoffset, quiet=()):
"""Find the next subnode
Args:
nodeoffset: Node offset of previous subnode
quiet: Errors to ignore (empty to raise on all errors)
Returns:
The offset of the next subnode, if any
Raises:
FdtException if no more subnodes found or other error occurs
"""
return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
def magic(self):
"""Return the magic word from the header
Returns:
Magic word
"""
return fdt_magic(self._fdt)
def totalsize(self):
"""Return the total size of the device tree
Returns:
Total tree size in bytes
"""
return fdt_totalsize(self._fdt)
def off_dt_struct(self):
"""Return the start of the device-tree struct area
Returns:
Start offset of struct area
"""
return fdt_off_dt_struct(self._fdt)
def off_dt_strings(self):
"""Return the start of the device-tree string area
Returns:
Start offset of string area
"""
return fdt_off_dt_strings(self._fdt)
def off_mem_rsvmap(self):
"""Return the start of the memory reserve map
Returns:
Start offset of memory reserve map
"""
return fdt_off_mem_rsvmap(self._fdt)
def version(self):
"""Return the version of the device tree
Returns:
Version number of the device tree
"""
return fdt_version(self._fdt)
def last_comp_version(self):
"""Return the last compatible version of the device tree
Returns:
Last compatible version number of the device tree
"""
return fdt_last_comp_version(self._fdt)
def boot_cpuid_phys(self):
"""Return the physical boot CPU ID
Returns:
Physical boot CPU ID
"""
return fdt_boot_cpuid_phys(self._fdt)
def size_dt_strings(self):
"""Return the start of the device-tree string area
Returns:
Start offset of string area
"""
return fdt_size_dt_strings(self._fdt)
def size_dt_struct(self):
"""Return the start of the device-tree struct area
Returns:
Start offset of struct area
"""
return fdt_size_dt_struct(self._fdt)
def num_mem_rsv(self, quiet=()):
"""Return the number of memory reserve-map records
Returns:
Number of memory reserve-map records
"""
return check_err(fdt_num_mem_rsv(self._fdt), quiet)
def get_mem_rsv(self, index, quiet=()):
"""Return the indexed memory reserve-map record
Args:
index: Record to return (0=first)
Returns:
Number of memory reserve-map records
"""
return check_err(fdt_get_mem_rsv(self._fdt, index), quiet)
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
Args:
path: Path to the required node, e.g. '/node@3/subnode@1'
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Node offset
Raises
FdtException if the path is not valid or not found
"""
return check_err(fdt_path_offset(self._fdt, path), quiet)
def get_name(self, nodeoffset):
"""Get the name of a node
Args:
nodeoffset: Offset of node to check
Returns:
Node name
Raises:
FdtException on error (e.g. nodeoffset is invalid)
"""
return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
def first_property_offset(self, nodeoffset, quiet=()):
"""Get the offset of the first property in a node offset
Args:
nodeoffset: Offset to the node to check
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Offset of the first property
Raises
FdtException if the associated node has no properties, or some
other error occurred
"""
return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
quiet)
def next_property_offset(self, prop_offset, quiet=()):
"""Get the next property in a node
Args:
prop_offset: Offset of the previous property
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Offset of the next property
Raises:
FdtException if the associated node has no more properties, or
some other error occurred
"""
return check_err(fdt_next_property_offset(self._fdt, prop_offset),
quiet)
def get_property_by_offset(self, prop_offset, quiet=()):
"""Obtains a property that can be examined
Args:
prop_offset: Offset of property (e.g. from first_property_offset())
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Property object, or None if not found
Raises:
FdtException on error (e.g. invalid prop_offset or device
tree format)
"""
pdata = check_err_null(
fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
if isinstance(pdata, (int)):
return pdata
return Property(pdata[0], pdata[1])
def getprop(self, nodeoffset, prop_name, quiet=()):
"""Get a property from a node
Args:
nodeoffset: Node offset containing property to get
prop_name: Name of property to get
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Value of property as a Property object (which can be used as a
bytearray/string), or -ve error number. On failure, returns an
integer error
Raises:
FdtError if any error occurs (e.g. the property is not found)
"""
pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
quiet)
if isinstance(pdata, (int)):
return pdata
return Property(prop_name, 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 Fdt(FdtRo):
"""Device tree class, supporting all operations
The Fdt object is created is created from a device tree binary file,
e.g. with something like:
fdt = Fdt(open("filename.dtb").read())
Operations can then be performed using the methods in this class. Each
method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
All methods raise an FdtException if an error occurs. To avoid this
behaviour a 'quiet' parameter is provided for some functions. This
defaults to empty, but you can pass a list of errors that you expect.
If one of these errors occurs, the function will return an error number
(e.g. -NOTFOUND).
"""
def __init__(self, data):
FdtRo.__init__(self, data)
@staticmethod
def create_empty_tree(size, quiet=()):
"""Create an empty device tree ready for use
Args:
size: Size of device tree in bytes
Returns:
Fdt object containing the device tree
"""
data = bytearray(size)
err = check_err(fdt_create_empty_tree(data, size), quiet)
if err:
return err
return Fdt(data)
def resize(self, size, quiet=()):
"""Move the device tree into a larger or smaller space
This creates a new device tree of size @size and moves the existing
device tree contents over to that. It can be used to create more space
in a device tree. Note that the Fdt object remains the same, but it
now has a new bytearray holding the contents.
Args:
size: Required new size of device tree in bytes
"""
fdt = bytearray(size)
err = check_err(fdt_open_into(self._fdt, fdt, size), quiet)
if err:
return err
self._fdt = fdt
def pack(self, quiet=()):
"""Pack the device tree to remove unused space
This adjusts the tree in place.
Args:
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Error code, or 0 if OK
Raises:
FdtException if any error occurs
"""
err = check_err(fdt_pack(self._fdt), quiet)
if err:
return err
del self._fdt[self.totalsize():]
return err
def set_name(self, nodeoffset, name, quiet=()):
"""Set the name of a node
Args:
nodeoffset: Node offset of node to update
name: New node name (string without \0)
Returns:
Error code, or 0 if OK
Raises:
FdtException if no parent found or other error occurs
"""
if chr(0) in name:
raise ValueError('Property contains embedded nul characters')
return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet)
def setprop(self, nodeoffset, prop_name, val, quiet=()):
"""Set the value of a property
Args:
nodeoffset: Node offset containing the property to create/update
prop_name: Name of property
val: Value to write (string or bytearray)
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Error code, or 0 if OK
Raises:
FdtException if no parent found or other error occurs
"""
return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
len(val)), quiet)
def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
"""Set the value of a property
Args:
nodeoffset: Node offset containing the property to create/update
prop_name: Name of property
val: Value to write (integer)
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Error code, or 0 if OK
Raises:
FdtException if no parent found or other error occurs
"""
return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val),
quiet)
def setprop_u64(self, nodeoffset, prop_name, val, quiet=()):
"""Set the value of a property
Args:
nodeoffset: Node offset containing the property to create/update
prop_name: Name of property
val: Value to write (integer)
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Error code, or 0 if OK
Raises:
FdtException if no parent found or other error occurs
"""
return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val),
quiet)
def setprop_str(self, nodeoffset, prop_name, val, quiet=()):
"""Set the string value of a property
The property is set to the string, with a nul terminator added
Args:
nodeoffset: Node offset containing the property to create/update
prop_name: Name of property
val: Value to write (string without nul terminator). Unicode is
supposed by encoding to UTF-8
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Error code, or 0 if OK
Raises:
FdtException if no parent found or other error occurs
"""
val = val.encode('utf-8') + '\0'
return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name,
val, len(val)), quiet)
def delprop(self, nodeoffset, prop_name, quiet=()):
"""Delete a property from a node
Args:
nodeoffset: Node offset containing property to delete
prop_name: Name of property to delete
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Error code, or 0 if OK
Raises:
FdtError if the property does not exist, or another error occurs
"""
return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name), quiet)
def add_subnode(self, parentoffset, name, quiet=()):
"""Add a new subnode to a node
Args:
parentoffset: Parent offset to add the subnode to
name: Name of node to add
Returns:
offset of the node created, or negative error code on failure
Raises:
FdtError if there is not enough space, or another error occurs
"""
return check_err(fdt_add_subnode(self._fdt, parentoffset, name), quiet)
def del_node(self, nodeoffset, quiet=()):
"""Delete a node
Args:
nodeoffset: Offset of node to delete
Returns:
Error code, or 0 if OK
Raises:
FdtError if an error occurs
"""
return check_err(fdt_del_node(self._fdt, nodeoffset), quiet)
class Property(bytearray):
"""Holds a device tree property name and value.
This holds a copy of a property taken from the device tree. It does not
reference the device tree, so if anything changes in the device tree,
a Property object will remain valid.
Properties:
name: Property name
value: Property value as a bytearray
"""
def __init__(self, name, value):
bytearray.__init__(self, value)
self.name = name
def as_cell(self, fmt):
return struct.unpack('>' + fmt, self)[0]
def as_uint32(self):
return self.as_cell('L')
def as_int32(self):
return self.as_cell('l')
def as_uint64(self):
return self.as_cell('Q')
def as_int64(self):
return self.as_cell('q')
def as_str(self):
"""Unicode is supported by decoding from UTF-8"""
if self[-1] != 0:
raise ValueError('Property lacks nul termination')
if 0 in self[:-1]:
raise ValueError('Property contains embedded nul characters')
return self[:-1].decode('utf-8')
class FdtSw(FdtRo):
"""Software interface to create a device tree from scratch
The methods in this class work by adding to an existing 'partial' device
tree buffer of a fixed size created by instantiating this class. When the
tree is complete, call as_fdt() to obtain a device tree ready to be used.
Similarly with nodes, a new node is started with begin_node() and finished
with end_node().
The context manager functions can be used to make this a bit easier:
# First create the device tree with a node and property:
sw = FdtSw()
with sw.add_node('node'):
sw.property_u32('reg', 2)
fdt = sw.as_fdt()
# Now we can use it as a real device tree
fdt.setprop_u32(0, 'reg', 3)
The size hint provides a starting size for the space to be used by the
device tree. This will be increased automatically as needed as new items
are added to the tree.
"""
INC_SIZE = 1024 # Expand size by this much when out of space
def __init__(self, size_hint=None):
"""Create a new FdtSw object
Args:
size_hint: A hint as to the initial size to use
Raises:
ValueError if size_hint is negative
Returns:
FdtSw object on success, else integer error code (if not raising)
"""
if not size_hint:
size_hint = self.INC_SIZE
fdtsw = bytearray(size_hint)
err = check_err(fdt_create(fdtsw, size_hint))
if err:
return err
self._fdt = fdtsw
def as_fdt(self):
"""Convert a FdtSw into an Fdt so it can be accessed as normal
Creates a new Fdt object from the work-in-progress device tree. This
does not call fdt_finish() on the current object, so it is possible to
add more nodes/properties and call as_fdt() again to get an updated
tree.
Returns:
Fdt object allowing access to the newly created device tree
"""
fdtsw = bytearray(self._fdt)
check_err(fdt_finish(fdtsw))
return Fdt(fdtsw)
def check_space(self, val):
"""Check if we need to add more space to the FDT
This should be called with the error code from an operation. If this is
-NOSPACE then the FDT will be expanded to have more space, and True will
be returned, indicating that the operation needs to be tried again.
Args:
val: Return value from the operation that was attempted
Returns:
True if the operation must be retried, else False
"""
if check_err(val, QUIET_NOSPACE) < 0:
self.resize(len(self._fdt) + self.INC_SIZE)
return True
return False
def resize(self, size):
"""Resize the buffer to accommodate a larger tree
Args:
size: New size of tree
Raises:
FdtException on any error
"""
fdt = bytearray(size)
err = check_err(fdt_resize(self._fdt, fdt, size))
self._fdt = fdt
def add_reservemap_entry(self, addr, size):
"""Add a new memory reserve map entry
Once finished adding, you must call finish_reservemap().
Args:
addr: 64-bit start address
size: 64-bit size
Raises:
FdtException on any error
"""
while self.check_space(fdt_add_reservemap_entry(self._fdt, addr,
size)):
pass
def finish_reservemap(self):
"""Indicate that there are no more reserve map entries to add
Raises:
FdtException on any error
"""
while self.check_space(fdt_finish_reservemap(self._fdt)):
pass
def begin_node(self, name):
"""Begin a new node
Use this before adding properties to the node. Then call end_node() to
finish it. You can also use the context manager as shown in the FdtSw
class comment.
Args:
name: Name of node to begin
Raises:
FdtException on any error
"""
while self.check_space(fdt_begin_node(self._fdt, name)):
pass
def property_string(self, name, string):
"""Add a property with a string value
The string will be nul-terminated when written to the device tree
Args:
name: Name of property to add
string: String value of property
Raises:
FdtException on any error
"""
while self.check_space(fdt_property_string(self._fdt, name, string)):
pass
def property_u32(self, name, val):
"""Add a property with a 32-bit value
Write a single-cell value to the device tree
Args:
name: Name of property to add
val: Value of property
Raises:
FdtException on any error
"""
while self.check_space(fdt_property_u32(self._fdt, name, val)):
pass
def property_u64(self, name, val):
"""Add a property with a 64-bit value
Write a double-cell value to the device tree in big-endian format
Args:
name: Name of property to add
val: Value of property
Raises:
FdtException on any error
"""
while self.check_space(fdt_property_u64(self._fdt, name, val)):
pass
def property_cell(self, name, val):
"""Add a property with a single-cell value
Write a single-cell value to the device tree
Args:
name: Name of property to add
val: Value of property
quiet: Errors to ignore (empty to raise on all errors)
Raises:
FdtException on any error
"""
while self.check_space(fdt_property_cell(self._fdt, name, val)):
pass
def property(self, name, val):
"""Add a property
Write a new property with the given value to the device tree. The value
is taken as is and is not nul-terminated
Args:
name: Name of property to add
val: Value of property
quiet: Errors to ignore (empty to raise on all errors)
Raises:
FdtException on any error
"""
while self.check_space(fdt_property_stub(self._fdt, name, val,
len(val))):
pass
def end_node(self):
"""End a node
Use this after adding properties to a node to close it off. You can also
use the context manager as shown in the FdtSw class comment.
Args:
quiet: Errors to ignore (empty to raise on all errors)
Raises:
FdtException on any error
"""
while self.check_space(fdt_end_node(self._fdt)):
pass
def add_node(self, name):
"""Create a new context for adding a node
When used in a 'with' clause this starts a new node and finishes it
afterward.
Args:
name: Name of node to add
"""
return NodeAdder(self, name)
class NodeAdder():
"""Class to provide a node context
This allows you to add nodes in a more natural way:
with fdtsw.add_node('name'):
fdtsw.property_string('test', 'value')
The node is automatically completed with a call to end_node() when the
context exits.
"""
def __init__(self, fdtsw, name):
self._fdt = fdtsw
self._name = name
def __enter__(self):
self._fdt.begin_node(self._name)
def __exit__(self, type, value, traceback):
self._fdt.end_node()
%}
%rename(fdt_property) fdt_property_func;
/*
* fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h
* so use the same type here.
*/
typedef uint32_t fdt32_t;
%include "libfdt/fdt.h"
%include "typemaps.i"
/* Most functions don't change the device tree, so use a const void * */
%typemap(in) (const void *)(const void *fdt) {
if (!PyByteArray_Check($input)) {
SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
"', argument " "$argnum"" of type '" "$type""'");
}
$1 = (void *)PyByteArray_AsString($input);
fdt = $1;
fdt = fdt; /* avoid unused variable warning */
}
/* Some functions do change the device tree, so use void * */
%typemap(in) (void *)(const void *fdt) {
if (!PyByteArray_Check($input)) {
SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
"', argument " "$argnum"" of type '" "$type""'");
}
$1 = PyByteArray_AsString($input);
fdt = $1;
fdt = fdt; /* avoid unused variable warning */
}
/* typemap used for fdt_get_property_by_offset() */
%typemap(out) (struct fdt_property *) {
PyObject *buff;
if ($1) {
resultobj = PyString_FromString(
fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
buff = PyByteArray_FromStringAndSize(
(const char *)($1 + 1), fdt32_to_cpu($1->len));
resultobj = SWIG_Python_AppendOutput(resultobj, buff);
}
}
%apply int *OUTPUT { int *lenp };
/* typemap used for fdt_getprop() */
%typemap(out) (const void *) {
if (!$1)
$result = Py_None;
else
$result = Py_BuildValue("s#", $1, *arg4);
}
/* typemap used for fdt_setprop() */
%typemap(in) (const void *val) {
$1 = PyString_AsString($input); /* char *str */
}
/* typemap used for fdt_add_reservemap_entry() */
%typemap(in) uint64_t {
$1 = PyLong_AsUnsignedLong($input);
}
/* typemaps used for fdt_next_node() */
%typemap(in, numinputs=1) int *depth (int depth) {
depth = (int) PyInt_AsLong($input);
$1 = &depth;
}
%typemap(argout) int *depth {
PyObject *val = Py_BuildValue("i", *arg$argnum);
resultobj = SWIG_Python_AppendOutput(resultobj, val);
}
%apply int *depth { int *depth };
/* typemaps for fdt_get_mem_rsv */
%typemap(in, numinputs=0) uint64_t * (uint64_t temp) {
$1 = &temp;
}
%typemap(argout) uint64_t * {
PyObject *val = PyLong_FromUnsignedLong(*arg$argnum);
if (!result) {
if (PyTuple_GET_SIZE(resultobj) == 0)
resultobj = val;
else
resultobj = SWIG_Python_AppendOutput(resultobj, val);
}
}
/* We have both struct fdt_property and a function fdt_property() */
%warnfilter(302) fdt_property;
/* These are macros in the header so have to be redefined here */
uint32_t fdt_magic(const void *fdt);
uint32_t fdt_totalsize(const void *fdt);
uint32_t fdt_off_dt_struct(const void *fdt);
uint32_t fdt_off_dt_strings(const void *fdt);
uint32_t fdt_off_mem_rsvmap(const void *fdt);
uint32_t fdt_version(const void *fdt);
uint32_t fdt_last_comp_version(const void *fdt);
uint32_t fdt_boot_cpuid_phys(const void *fdt);
uint32_t fdt_size_dt_strings(const void *fdt);
uint32_t fdt_size_dt_struct(const void *fdt);
int fdt_property_string(void *fdt, const char *name, const char *val);
int fdt_property_cell(void *fdt, const char *name, uint32_t val);
/*
* This function has a stub since the name fdt_property is used for both a
* function and a struct, which confuses SWIG.
*/
int fdt_property_stub(void *fdt, const char *name, const char *val, int len);
%include <../libfdt/libfdt.h>
u-boot-tree/scripts/dtc/pylibfdt/setup.py
deleted
100755 → 0
View file @
3e304607
#!/usr/bin/env python2
"""
setup.py file for SWIG libfdt
Copyright (C) 2017 Google, Inc.
Written by Simon Glass <sjg@chromium.org>
SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
Files to be built into the extension are provided in SOURCES
C flags to use are provided in CPPFLAGS
Object file directory is provided in OBJDIR
Version is provided in VERSION
If these variables are not given they are parsed from the Makefiles. This
allows this script to be run stand-alone, e.g.:
./pylibfdt/setup.py install [--prefix=...]
"""
from
distutils.core
import
setup
,
Extension
import
os
import
re
import
sys
# Decodes a Makefile assignment line into key and value (and plus for +=)
RE_KEY_VALUE
=
re
.
compile
(
'(?P<key>
\
w+) *(?P<plus>[+])?= *(?P<value>.*)$'
)
def
ParseMakefile
(
fname
):
"""Parse a Makefile to obtain its variables.
This collects variable assigments of the form:
VAR = value
VAR += more
It does not pick out := assignments, as these are not needed here. It does
handle line continuation.
Returns a dict:
key: Variable name (e.g. 'VAR')
value: Variable value (e.g. 'value more')
"""
makevars
=
{}
with
open
(
fname
)
as
fd
:
prev_text
=
''
# Continuation text from previous line(s)
for
line
in
fd
.
read
()
.
splitlines
():
if
line
and
line
[
-
1
]
==
'
\\
'
:
# Deal with line continuation
prev_text
+=
line
[:
-
1
]
continue
elif
prev_text
:
line
=
prev_text
+
line
prev_text
=
''
# Continuation is now used up
m
=
RE_KEY_VALUE
.
match
(
line
)
if
m
:
value
=
m
.
group
(
'value'
)
or
''
key
=
m
.
group
(
'key'
)
# Appending to a variable inserts a space beforehand
if
'plus'
in
m
.
groupdict
()
and
key
in
makevars
:
makevars
[
key
]
+=
' '
+
value
else
:
makevars
[
key
]
=
value
return
makevars
def
GetEnvFromMakefiles
():
"""Scan the Makefiles to obtain the settings we need.
This assumes that this script is being run from the top-level directory,
not the pylibfdt directory.
Returns:
Tuple with:
List of swig options
Version string
List of files to build
List of extra C preprocessor flags needed
Object directory to use (always '')
"""
basedir
=
os
.
path
.
dirname
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
sys
.
argv
[
0
])))
swig_opts
=
[
'-I
%
s'
%
basedir
]
makevars
=
ParseMakefile
(
os
.
path
.
join
(
basedir
,
'Makefile'
))
version
=
'
%
s.
%
s.
%
s'
%
(
makevars
[
'VERSION'
],
makevars
[
'PATCHLEVEL'
],
makevars
[
'SUBLEVEL'
])
makevars
=
ParseMakefile
(
os
.
path
.
join
(
basedir
,
'libfdt'
,
'Makefile.libfdt'
))
files
=
makevars
[
'LIBFDT_SRCS'
]
.
split
()
files
=
[
os
.
path
.
join
(
basedir
,
'libfdt'
,
fname
)
for
fname
in
files
]
files
.
append
(
'pylibfdt/libfdt.i'
)
cflags
=
[
'-I
%
s'
%
basedir
,
'-I
%
s/libfdt'
%
basedir
]
objdir
=
''
return
swig_opts
,
version
,
files
,
cflags
,
objdir
progname
=
sys
.
argv
[
0
]
files
=
os
.
environ
.
get
(
'SOURCES'
,
''
)
.
split
()
cflags
=
os
.
environ
.
get
(
'CPPFLAGS'
,
''
)
.
split
()
objdir
=
os
.
environ
.
get
(
'OBJDIR'
)
version
=
os
.
environ
.
get
(
'VERSION'
)
swig_opts
=
os
.
environ
.
get
(
'SWIG_OPTS'
,
''
)
.
split
()
# If we were called directly rather than through our Makefile (which is often
# the case with Python module installation), read the settings from the
# Makefile.
if
not
all
((
swig_opts
,
version
,
files
,
cflags
,
objdir
)):
swig_opts
,
version
,
files
,
cflags
,
objdir
=
GetEnvFromMakefiles
()
libfdt_module
=
Extension
(
'_libfdt'
,
sources
=
files
,
extra_compile_args
=
cflags
,
swig_opts
=
swig_opts
,
)
setup
(
name
=
'libfdt'
,
version
=
version
,
author
=
'Simon Glass <sjg@chromium.org>'
,
description
=
'Python binding for libfdt'
,
ext_modules
=
[
libfdt_module
],
package_dir
=
{
''
:
objdir
},
py_modules
=
[
'pylibfdt/libfdt'
],
)
u-boot-tree/scripts/dtc/srcpos.c
deleted
100644 → 0
View file @
3e304607
/*
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#define _GNU_SOURCE
#include <stdio.h>
#include "dtc.h"
#include "srcpos.h"
/* A node in our list of directories to search for source/include files */
struct
search_path
{
struct
search_path
*
next
;
/* next node in list, NULL for end */
const
char
*
dirname
;
/* name of directory to search */
};
/* This is the list of directories that we search for source files */
static
struct
search_path
*
search_path_head
,
**
search_path_tail
;
static
char
*
get_dirname
(
const
char
*
path
)
{
const
char
*
slash
=
strrchr
(
path
,
'/'
);
if
(
slash
)
{
int
len
=
slash
-
path
;
char
*
dir
=
xmalloc
(
len
+
1
);
memcpy
(
dir
,
path
,
len
);
dir
[
len
]
=
'\0'
;
return
dir
;
}
return
NULL
;
}
FILE
*
depfile
;
/* = NULL */
struct
srcfile_state
*
current_srcfile
;
/* = NULL */
/* Detect infinite include recursion. */
#define MAX_SRCFILE_DEPTH (100)
static
int
srcfile_depth
;
/* = 0 */
/**
* Try to open a file in a given directory.
*
* If the filename is an absolute path, then dirname is ignored. If it is a
* relative path, then we look in that directory for the file.
*
* @param dirname Directory to look in, or NULL for none
* @param fname Filename to look for
* @param fp Set to NULL if file did not open
* @return allocated filename on success (caller must free), NULL on failure
*/
static
char
*
try_open
(
const
char
*
dirname
,
const
char
*
fname
,
FILE
**
fp
)
{
char
*
fullname
;
if
(
!
dirname
||
fname
[
0
]
==
'/'
)
fullname
=
xstrdup
(
fname
);
else
fullname
=
join_path
(
dirname
,
fname
);
*
fp
=
fopen
(
fullname
,
"rb"
);
if
(
!*
fp
)
{
free
(
fullname
);
fullname
=
NULL
;
}
return
fullname
;
}
/**
* Open a file for read access
*
* If it is a relative filename, we search the full search path for it.
*
* @param fname Filename to open
* @param fp Returns pointer to opened FILE, or NULL on failure
* @return pointer to allocated filename, which caller must free
*/
static
char
*
fopen_any_on_path
(
const
char
*
fname
,
FILE
**
fp
)
{
const
char
*
cur_dir
=
NULL
;
struct
search_path
*
node
;
char
*
fullname
;
/* Try current directory first */
assert
(
fp
);
if
(
current_srcfile
)
cur_dir
=
current_srcfile
->
dir
;
fullname
=
try_open
(
cur_dir
,
fname
,
fp
);
/* Failing that, try each search path in turn */
for
(
node
=
search_path_head
;
!*
fp
&&
node
;
node
=
node
->
next
)
fullname
=
try_open
(
node
->
dirname
,
fname
,
fp
);
return
fullname
;
}
FILE
*
srcfile_relative_open
(
const
char
*
fname
,
char
**
fullnamep
)
{
FILE
*
f
;
char
*
fullname
;
if
(
streq
(
fname
,
"-"
))
{
f
=
stdin
;
fullname
=
xstrdup
(
"<stdin>"
);
}
else
{
fullname
=
fopen_any_on_path
(
fname
,
&
f
);
if
(
!
f
)
die
(
"Couldn't open
\"
%s
\"
: %s
\n
"
,
fname
,
strerror
(
errno
));
}
if
(
depfile
)
fprintf
(
depfile
,
" %s"
,
fullname
);
if
(
fullnamep
)
*
fullnamep
=
fullname
;
else
free
(
fullname
);
return
f
;
}
void
srcfile_push
(
const
char
*
fname
)
{
struct
srcfile_state
*
srcfile
;
if
(
srcfile_depth
++
>=
MAX_SRCFILE_DEPTH
)
die
(
"Includes nested too deeply"
);
srcfile
=
xmalloc
(
sizeof
(
*
srcfile
));
srcfile
->
f
=
srcfile_relative_open
(
fname
,
&
srcfile
->
name
);
srcfile
->
dir
=
get_dirname
(
srcfile
->
name
);
srcfile
->
prev
=
current_srcfile
;
srcfile
->
lineno
=
1
;
srcfile
->
colno
=
1
;
current_srcfile
=
srcfile
;
}
bool
srcfile_pop
(
void
)
{
struct
srcfile_state
*
srcfile
=
current_srcfile
;
assert
(
srcfile
);
current_srcfile
=
srcfile
->
prev
;
if
(
fclose
(
srcfile
->
f
))
die
(
"Error closing
\"
%s
\"
: %s
\n
"
,
srcfile
->
name
,
strerror
(
errno
));
/* FIXME: We allow the srcfile_state structure to leak,
* because it could still be referenced from a location
* variable being carried through the parser somewhere. To
* fix this we could either allocate all the files from a
* table, or use a pool allocator. */
return
current_srcfile
?
true
:
false
;
}
void
srcfile_add_search_path
(
const
char
*
dirname
)
{
struct
search_path
*
node
;
/* Create the node */
node
=
xmalloc
(
sizeof
(
*
node
));
node
->
next
=
NULL
;
node
->
dirname
=
xstrdup
(
dirname
);
/* Add to the end of our list */
if
(
search_path_tail
)
*
search_path_tail
=
node
;
else
search_path_head
=
node
;
search_path_tail
=
&
node
->
next
;
}
/*
* The empty source position.
*/
struct
srcpos
srcpos_empty
=
{
.
first_line
=
0
,
.
first_column
=
0
,
.
last_line
=
0
,
.
last_column
=
0
,
.
file
=
NULL
,
};
void
srcpos_update
(
struct
srcpos
*
pos
,
const
char
*
text
,
int
len
)
{
int
i
;
pos
->
file
=
current_srcfile
;
pos
->
first_line
=
current_srcfile
->
lineno
;
pos
->
first_column
=
current_srcfile
->
colno
;
for
(
i
=
0
;
i
<
len
;
i
++
)
if
(
text
[
i
]
==
'\n'
)
{
current_srcfile
->
lineno
++
;
current_srcfile
->
colno
=
1
;
}
else
{
current_srcfile
->
colno
++
;
}
pos
->
last_line
=
current_srcfile
->
lineno
;
pos
->
last_column
=
current_srcfile
->
colno
;
}
struct
srcpos
*
srcpos_copy
(
struct
srcpos
*
pos
)
{
struct
srcpos
*
pos_new
;
pos_new
=
xmalloc
(
sizeof
(
struct
srcpos
));
memcpy
(
pos_new
,
pos
,
sizeof
(
struct
srcpos
));
return
pos_new
;
}
char
*
srcpos_string
(
struct
srcpos
*
pos
)
{
const
char
*
fname
=
"<no-file>"
;
char
*
pos_str
;
if
(
pos
->
file
&&
pos
->
file
->
name
)
fname
=
pos
->
file
->
name
;
if
(
pos
->
first_line
!=
pos
->
last_line
)
xasprintf
(
&
pos_str
,
"%s:%d.%d-%d.%d"
,
fname
,
pos
->
first_line
,
pos
->
first_column
,
pos
->
last_line
,
pos
->
last_column
);
else
if
(
pos
->
first_column
!=
pos
->
last_column
)
xasprintf
(
&
pos_str
,
"%s:%d.%d-%d"
,
fname
,
pos
->
first_line
,
pos
->
first_column
,
pos
->
last_column
);
else
xasprintf
(
&
pos_str
,
"%s:%d.%d"
,
fname
,
pos
->
first_line
,
pos
->
first_column
);
return
pos_str
;
}
void
srcpos_verror
(
struct
srcpos
*
pos
,
const
char
*
prefix
,
const
char
*
fmt
,
va_list
va
)
{
char
*
srcstr
;
srcstr
=
srcpos_string
(
pos
);
fprintf
(
stderr
,
"%s: %s "
,
prefix
,
srcstr
);
vfprintf
(
stderr
,
fmt
,
va
);
fprintf
(
stderr
,
"
\n
"
);
free
(
srcstr
);
}
void
srcpos_error
(
struct
srcpos
*
pos
,
const
char
*
prefix
,
const
char
*
fmt
,
...)
{
va_list
va
;
va_start
(
va
,
fmt
);
srcpos_verror
(
pos
,
prefix
,
fmt
,
va
);
va_end
(
va
);
}
void
srcpos_set_line
(
char
*
f
,
int
l
)
{
current_srcfile
->
name
=
f
;
current_srcfile
->
lineno
=
l
;
}
u-boot-tree/scripts/dtc/srcpos.h
deleted
100644 → 0
View file @
3e304607
/*
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifndef SRCPOS_H
#define SRCPOS_H
#include <stdio.h>
#include <stdbool.h>
#include "util.h"
struct
srcfile_state
{
FILE
*
f
;
char
*
name
;
char
*
dir
;
int
lineno
,
colno
;
struct
srcfile_state
*
prev
;
};
extern
FILE
*
depfile
;
/* = NULL */
extern
struct
srcfile_state
*
current_srcfile
;
/* = NULL */
/**
* Open a source file.
*
* If the source file is a relative pathname, then it is searched for in the
* current directory (the directory of the last source file read) and after
* that in the search path.
*
* We work through the search path in order from the first path specified to
* the last.
*
* If the file is not found, then this function does not return, but calls
* die().
*
* @param fname Filename to search
* @param fullnamep If non-NULL, it is set to the allocated filename of the
* file that was opened. The caller is then responsible
* for freeing the pointer.
* @return pointer to opened FILE
*/
FILE
*
srcfile_relative_open
(
const
char
*
fname
,
char
**
fullnamep
);
void
srcfile_push
(
const
char
*
fname
);
bool
srcfile_pop
(
void
);
/**
* Add a new directory to the search path for input files
*
* The new path is added at the end of the list.
*
* @param dirname Directory to add
*/
void
srcfile_add_search_path
(
const
char
*
dirname
);
struct
srcpos
{
int
first_line
;
int
first_column
;
int
last_line
;
int
last_column
;
struct
srcfile_state
*
file
;
};
#define YYLTYPE struct srcpos
#define YYLLOC_DEFAULT(Current, Rhs, N) \
do { \
if (N) { \
(Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
(Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
(Current).last_line = YYRHSLOC(Rhs, N).last_line; \
(Current).last_column = YYRHSLOC (Rhs, N).last_column; \
(Current).file = YYRHSLOC(Rhs, N).file; \
} else { \
(Current).first_line = (Current).last_line = \
YYRHSLOC(Rhs, 0).last_line; \
(Current).first_column = (Current).last_column = \
YYRHSLOC(Rhs, 0).last_column; \
(Current).file = YYRHSLOC (Rhs, 0).file; \
} \
} while (0)
/*
* Fictional source position used for IR nodes that are
* created without otherwise knowing a true source position.
* For example,constant definitions from the command line.
*/
extern
struct
srcpos
srcpos_empty
;
extern
void
srcpos_update
(
struct
srcpos
*
pos
,
const
char
*
text
,
int
len
);
extern
struct
srcpos
*
srcpos_copy
(
struct
srcpos
*
pos
);
extern
char
*
srcpos_string
(
struct
srcpos
*
pos
);
extern
void
PRINTF
(
3
,
0
)
srcpos_verror
(
struct
srcpos
*
pos
,
const
char
*
prefix
,
const
char
*
fmt
,
va_list
va
);
extern
void
PRINTF
(
3
,
4
)
srcpos_error
(
struct
srcpos
*
pos
,
const
char
*
prefix
,
const
char
*
fmt
,
...);
extern
void
srcpos_set_line
(
char
*
f
,
int
l
);
#endif
/* SRCPOS_H */
u-boot-tree/scripts/dtc/treesource.c
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "dtc.h"
#include "srcpos.h"
extern
FILE
*
yyin
;
extern
int
yyparse
(
void
);
extern
YYLTYPE
yylloc
;
struct
dt_info
*
parser_output
;
bool
treesource_error
;
struct
dt_info
*
dt_from_source
(
const
char
*
fname
)
{
parser_output
=
NULL
;
treesource_error
=
false
;
srcfile_push
(
fname
);
yyin
=
current_srcfile
->
f
;
yylloc
.
file
=
current_srcfile
;
if
(
yyparse
()
!=
0
)
die
(
"Unable to parse input tree
\n
"
);
if
(
treesource_error
)
die
(
"Syntax error parsing input tree
\n
"
);
return
parser_output
;
}
static
void
write_prefix
(
FILE
*
f
,
int
level
)
{
int
i
;
for
(
i
=
0
;
i
<
level
;
i
++
)
fputc
(
'\t'
,
f
);
}
static
bool
isstring
(
char
c
)
{
return
(
isprint
((
unsigned
char
)
c
)
||
(
c
==
'\0'
)
||
strchr
(
"
\a\b\t\n\v\f\r
"
,
c
));
}
static
void
write_propval_string
(
FILE
*
f
,
struct
data
val
)
{
const
char
*
str
=
val
.
val
;
int
i
;
struct
marker
*
m
=
val
.
markers
;
assert
(
str
[
val
.
len
-
1
]
==
'\0'
);
while
(
m
&&
(
m
->
offset
==
0
))
{
if
(
m
->
type
==
LABEL
)
fprintf
(
f
,
"%s: "
,
m
->
ref
);
m
=
m
->
next
;
}
fprintf
(
f
,
"
\"
"
);
for
(
i
=
0
;
i
<
(
val
.
len
-
1
);
i
++
)
{
char
c
=
str
[
i
];
switch
(
c
)
{
case
'\a'
:
fprintf
(
f
,
"
\\
a"
);
break
;
case
'\b'
:
fprintf
(
f
,
"
\\
b"
);
break
;
case
'\t'
:
fprintf
(
f
,
"
\\
t"
);
break
;
case
'\n'
:
fprintf
(
f
,
"
\\
n"
);
break
;
case
'\v'
:
fprintf
(
f
,
"
\\
v"
);
break
;
case
'\f'
:
fprintf
(
f
,
"
\\
f"
);
break
;
case
'\r'
:
fprintf
(
f
,
"
\\
r"
);
break
;
case
'\\'
:
fprintf
(
f
,
"
\\\\
"
);
break
;
case
'\"'
:
fprintf
(
f
,
"
\\\"
"
);
break
;
case
'\0'
:
fprintf
(
f
,
"
\"
, "
);
while
(
m
&&
(
m
->
offset
<=
(
i
+
1
)))
{
if
(
m
->
type
==
LABEL
)
{
assert
(
m
->
offset
==
(
i
+
1
));
fprintf
(
f
,
"%s: "
,
m
->
ref
);
}
m
=
m
->
next
;
}
fprintf
(
f
,
"
\"
"
);
break
;
default:
if
(
isprint
((
unsigned
char
)
c
))
fprintf
(
f
,
"%c"
,
c
);
else
fprintf
(
f
,
"
\\
x%02hhx"
,
c
);
}
}
fprintf
(
f
,
"
\"
"
);
/* Wrap up any labels at the end of the value */
for_each_marker_of_type
(
m
,
LABEL
)
{
assert
(
m
->
offset
==
val
.
len
);
fprintf
(
f
,
" %s:"
,
m
->
ref
);
}
}
static
void
write_propval_cells
(
FILE
*
f
,
struct
data
val
)
{
void
*
propend
=
val
.
val
+
val
.
len
;
fdt32_t
*
cp
=
(
fdt32_t
*
)
val
.
val
;
struct
marker
*
m
=
val
.
markers
;
fprintf
(
f
,
"<"
);
for
(;;)
{
while
(
m
&&
(
m
->
offset
<=
((
char
*
)
cp
-
val
.
val
)))
{
if
(
m
->
type
==
LABEL
)
{
assert
(
m
->
offset
==
((
char
*
)
cp
-
val
.
val
));
fprintf
(
f
,
"%s: "
,
m
->
ref
);
}
m
=
m
->
next
;
}
fprintf
(
f
,
"0x%x"
,
fdt32_to_cpu
(
*
cp
++
));
if
((
void
*
)
cp
>=
propend
)
break
;
fprintf
(
f
,
" "
);
}
/* Wrap up any labels at the end of the value */
for_each_marker_of_type
(
m
,
LABEL
)
{
assert
(
m
->
offset
==
val
.
len
);
fprintf
(
f
,
" %s:"
,
m
->
ref
);
}
fprintf
(
f
,
">"
);
}
static
void
write_propval_bytes
(
FILE
*
f
,
struct
data
val
)
{
void
*
propend
=
val
.
val
+
val
.
len
;
const
char
*
bp
=
val
.
val
;
struct
marker
*
m
=
val
.
markers
;
fprintf
(
f
,
"["
);
for
(;;)
{
while
(
m
&&
(
m
->
offset
==
(
bp
-
val
.
val
)))
{
if
(
m
->
type
==
LABEL
)
fprintf
(
f
,
"%s: "
,
m
->
ref
);
m
=
m
->
next
;
}
fprintf
(
f
,
"%02hhx"
,
(
unsigned
char
)(
*
bp
++
));
if
((
const
void
*
)
bp
>=
propend
)
break
;
fprintf
(
f
,
" "
);
}
/* Wrap up any labels at the end of the value */
for_each_marker_of_type
(
m
,
LABEL
)
{
assert
(
m
->
offset
==
val
.
len
);
fprintf
(
f
,
" %s:"
,
m
->
ref
);
}
fprintf
(
f
,
"]"
);
}
static
void
write_propval
(
FILE
*
f
,
struct
property
*
prop
)
{
int
len
=
prop
->
val
.
len
;
const
char
*
p
=
prop
->
val
.
val
;
struct
marker
*
m
=
prop
->
val
.
markers
;
int
nnotstring
=
0
,
nnul
=
0
;
int
nnotstringlbl
=
0
,
nnotcelllbl
=
0
;
int
i
;
if
(
len
==
0
)
{
fprintf
(
f
,
";
\n
"
);
return
;
}
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
!
isstring
(
p
[
i
]))
nnotstring
++
;
if
(
p
[
i
]
==
'\0'
)
nnul
++
;
}
for_each_marker_of_type
(
m
,
LABEL
)
{
if
((
m
->
offset
>
0
)
&&
(
prop
->
val
.
val
[
m
->
offset
-
1
]
!=
'\0'
))
nnotstringlbl
++
;
if
((
m
->
offset
%
sizeof
(
cell_t
))
!=
0
)
nnotcelllbl
++
;
}
fprintf
(
f
,
" = "
);
if
((
p
[
len
-
1
]
==
'\0'
)
&&
(
nnotstring
==
0
)
&&
(
nnul
<
(
len
-
nnul
))
&&
(
nnotstringlbl
==
0
))
{
write_propval_string
(
f
,
prop
->
val
);
}
else
if
(((
len
%
sizeof
(
cell_t
))
==
0
)
&&
(
nnotcelllbl
==
0
))
{
write_propval_cells
(
f
,
prop
->
val
);
}
else
{
write_propval_bytes
(
f
,
prop
->
val
);
}
fprintf
(
f
,
";
\n
"
);
}
static
void
write_tree_source_node
(
FILE
*
f
,
struct
node
*
tree
,
int
level
)
{
struct
property
*
prop
;
struct
node
*
child
;
struct
label
*
l
;
write_prefix
(
f
,
level
);
for_each_label
(
tree
->
labels
,
l
)
fprintf
(
f
,
"%s: "
,
l
->
label
);
if
(
tree
->
name
&&
(
*
tree
->
name
))
fprintf
(
f
,
"%s {
\n
"
,
tree
->
name
);
else
fprintf
(
f
,
"/ {
\n
"
);
for_each_property
(
tree
,
prop
)
{
write_prefix
(
f
,
level
+
1
);
for_each_label
(
prop
->
labels
,
l
)
fprintf
(
f
,
"%s: "
,
l
->
label
);
fprintf
(
f
,
"%s"
,
prop
->
name
);
write_propval
(
f
,
prop
);
}
for_each_child
(
tree
,
child
)
{
fprintf
(
f
,
"
\n
"
);
write_tree_source_node
(
f
,
child
,
level
+
1
);
}
write_prefix
(
f
,
level
);
fprintf
(
f
,
"};
\n
"
);
}
void
dt_to_source
(
FILE
*
f
,
struct
dt_info
*
dti
)
{
struct
reserve_info
*
re
;
fprintf
(
f
,
"/dts-v1/;
\n\n
"
);
for
(
re
=
dti
->
reservelist
;
re
;
re
=
re
->
next
)
{
struct
label
*
l
;
for_each_label
(
re
->
labels
,
l
)
fprintf
(
f
,
"%s: "
,
l
->
label
);
fprintf
(
f
,
"/memreserve/
\t
0x%016llx 0x%016llx;
\n
"
,
(
unsigned
long
long
)
re
->
address
,
(
unsigned
long
long
)
re
->
size
);
}
write_tree_source_node
(
f
,
dti
->
dt
,
0
);
}
u-boot-tree/scripts/dtc/update-dtc-source.sh
deleted
100755 → 0
View file @
3e304607
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Simple script to update the version of DTC carried by the Linux kernel
#
# This script assumes that the dtc and the linux git trees are in the
# same directory. After building dtc in the dtc directory, it copies the
# source files and generated source file(s) into the scripts/dtc directory
# in the kernel and creates a git commit updating them to the new
# version.
#
# Usage: from the top level Linux source tree, run:
# $ ./scripts/dtc/update-dtc-source.sh
#
# The script will change into the dtc tree, build and test dtc, copy the
# relevant files into the kernel tree and create a git commit. The commit
# message will need to be modified to reflect the version of DTC being
# imported
#
# TODO:
# This script is pretty basic, but it is seldom used so a few manual tasks
# aren't a big deal. If anyone is interested in making it more robust, the
# the following would be nice:
# * Actually fail to complete if any testcase fails.
# - The dtc "make check" target needs to return a failure
# * Extract the version number from the dtc repo for the commit message
# * Build dtc in the kernel tree
# * run 'make check" on dtc built from the kernel tree
set
-ev
DTC_UPSTREAM_PATH
=
`
pwd
`
/../dtc
DTC_LINUX_PATH
=
`
pwd
`
/scripts/dtc
DTC_SOURCE
=
"checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c
\
srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc
\
dtc-lexer.l dtc-parser.y"
LIBFDT_SOURCE
=
"Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c
\
fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c
\
fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h"
get_last_dtc_version
()
{
git log
--oneline
scripts/dtc/ |
grep
'upstream'
|
head
-1
|
sed
-e
's/^.* \(.*\)/\1/'
}
last_dtc_ver
=
$(
get_last_dtc_version
)
# Build DTC
cd
$DTC_UPSTREAM_PATH
make clean
make check
dtc_version
=
$(
git describe HEAD
)
dtc_log
=
$(
git log
--oneline
${
last_dtc_ver
}
..
)
# Copy the files into the Linux tree
cd
$DTC_LINUX_PATH
for
f
in
$DTC_SOURCE
;
do
cp
${
DTC_UPSTREAM_PATH
}
/
${
f
}
${
f
}
git add
${
f
}
done
for
f
in
$LIBFDT_SOURCE
;
do
cp
${
DTC_UPSTREAM_PATH
}
/libfdt/
${
f
}
libfdt/
${
f
}
git add libfdt/
${
f
}
done
sed
-i
--
's/#include <libfdt_env.h>/#include "libfdt_env.h"/g'
./libfdt/libfdt.h
sed
-i
--
's/#include <fdt.h>/#include "fdt.h"/g'
./libfdt/libfdt.h
git add ./libfdt/libfdt.h
commit_msg
=
$(
cat
<<
EOF
scripts/dtc: Update to upstream version
${
dtc_version
}
This adds the following commits from upstream:
${
dtc_log
}
EOF
)
git commit
-e
-v
-s
-m
"
${
commit_msg
}
"
u-boot-tree/scripts/dtc/util.c
deleted
100644 → 0
View file @
3e304607
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
*
* util_is_printable_string contributed by
* Pantelis Antoniou <pantelis.antoniou AT gmail.com>
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include "libfdt.h"
#include "util.h"
#include "version_gen.h"
char
*
xstrdup
(
const
char
*
s
)
{
int
len
=
strlen
(
s
)
+
1
;
char
*
d
=
xmalloc
(
len
);
memcpy
(
d
,
s
,
len
);
return
d
;
}
/* based in part from (3) vsnprintf */
int
xasprintf
(
char
**
strp
,
const
char
*
fmt
,
...)
{
int
n
,
size
=
128
;
/* start with 128 bytes */
char
*
p
;
va_list
ap
;
/* initial pointer is NULL making the fist realloc to be malloc */
p
=
NULL
;
while
(
1
)
{
p
=
xrealloc
(
p
,
size
);
/* Try to print in the allocated space. */
va_start
(
ap
,
fmt
);
n
=
vsnprintf
(
p
,
size
,
fmt
,
ap
);
va_end
(
ap
);
/* If that worked, return the string. */
if
(
n
>
-
1
&&
n
<
size
)
break
;
/* Else try again with more space. */
if
(
n
>
-
1
)
/* glibc 2.1 */
size
=
n
+
1
;
/* precisely what is needed */
else
/* glibc 2.0 */
size
*=
2
;
/* twice the old size */
}
*
strp
=
p
;
return
strlen
(
p
);
}
char
*
join_path
(
const
char
*
path
,
const
char
*
name
)
{
int
lenp
=
strlen
(
path
);
int
lenn
=
strlen
(
name
);
int
len
;
int
needslash
=
1
;
char
*
str
;
len
=
lenp
+
lenn
+
2
;
if
((
lenp
>
0
)
&&
(
path
[
lenp
-
1
]
==
'/'
))
{
needslash
=
0
;
len
--
;
}
str
=
xmalloc
(
len
);
memcpy
(
str
,
path
,
lenp
);
if
(
needslash
)
{
str
[
lenp
]
=
'/'
;
lenp
++
;
}
memcpy
(
str
+
lenp
,
name
,
lenn
+
1
);
return
str
;
}
bool
util_is_printable_string
(
const
void
*
data
,
int
len
)
{
const
char
*
s
=
data
;
const
char
*
ss
,
*
se
;
/* zero length is not */
if
(
len
==
0
)
return
0
;
/* must terminate with zero */
if
(
s
[
len
-
1
]
!=
'\0'
)
return
0
;
se
=
s
+
len
;
while
(
s
<
se
)
{
ss
=
s
;
while
(
s
<
se
&&
*
s
&&
isprint
((
unsigned
char
)
*
s
))
s
++
;
/* not zero, or not done yet */
if
(
*
s
!=
'\0'
||
s
==
ss
)
return
0
;
s
++
;
}
return
1
;
}
/*
* Parse a octal encoded character starting at index i in string s. The
* resulting character will be returned and the index i will be updated to
* point at the character directly after the end of the encoding, this may be
* the '\0' terminator of the string.
*/
static
char
get_oct_char
(
const
char
*
s
,
int
*
i
)
{
char
x
[
4
];
char
*
endx
;
long
val
;
x
[
3
]
=
'\0'
;
strncpy
(
x
,
s
+
*
i
,
3
);
val
=
strtol
(
x
,
&
endx
,
8
);
assert
(
endx
>
x
);
(
*
i
)
+=
endx
-
x
;
return
val
;
}
/*
* Parse a hexadecimal encoded character starting at index i in string s. The
* resulting character will be returned and the index i will be updated to
* point at the character directly after the end of the encoding, this may be
* the '\0' terminator of the string.
*/
static
char
get_hex_char
(
const
char
*
s
,
int
*
i
)
{
char
x
[
3
];
char
*
endx
;
long
val
;
x
[
2
]
=
'\0'
;
strncpy
(
x
,
s
+
*
i
,
2
);
val
=
strtol
(
x
,
&
endx
,
16
);
if
(
!
(
endx
>
x
))
die
(
"
\\
x used with no following hex digits
\n
"
);
(
*
i
)
+=
endx
-
x
;
return
val
;
}
char
get_escape_char
(
const
char
*
s
,
int
*
i
)
{
char
c
=
s
[
*
i
];
int
j
=
*
i
+
1
;
char
val
;
switch
(
c
)
{
case
'a'
:
val
=
'\a'
;
break
;
case
'b'
:
val
=
'\b'
;
break
;
case
't'
:
val
=
'\t'
;
break
;
case
'n'
:
val
=
'\n'
;
break
;
case
'v'
:
val
=
'\v'
;
break
;
case
'f'
:
val
=
'\f'
;
break
;
case
'r'
:
val
=
'\r'
;
break
;
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
j
--
;
/* need to re-read the first digit as
* part of the octal value */
val
=
get_oct_char
(
s
,
&
j
);
break
;
case
'x'
:
val
=
get_hex_char
(
s
,
&
j
);
break
;
default:
val
=
c
;
}
(
*
i
)
=
j
;
return
val
;
}
int
utilfdt_read_err_len
(
const
char
*
filename
,
char
**
buffp
,
off_t
*
len
)
{
int
fd
=
0
;
/* assume stdin */
char
*
buf
=
NULL
;
off_t
bufsize
=
1024
,
offset
=
0
;
int
ret
=
0
;
*
buffp
=
NULL
;
if
(
strcmp
(
filename
,
"-"
)
!=
0
)
{
fd
=
open
(
filename
,
O_RDONLY
);
if
(
fd
<
0
)
return
errno
;
}
/* Loop until we have read everything */
buf
=
xmalloc
(
bufsize
);
do
{
/* Expand the buffer to hold the next chunk */
if
(
offset
==
bufsize
)
{
bufsize
*=
2
;
buf
=
xrealloc
(
buf
,
bufsize
);
}
ret
=
read
(
fd
,
&
buf
[
offset
],
bufsize
-
offset
);
if
(
ret
<
0
)
{
ret
=
errno
;
break
;
}
offset
+=
ret
;
}
while
(
ret
!=
0
);
/* Clean up, including closing stdin; return errno on error */
close
(
fd
);
if
(
ret
)
free
(
buf
);
else
*
buffp
=
buf
;
*
len
=
bufsize
;
return
ret
;
}
int
utilfdt_read_err
(
const
char
*
filename
,
char
**
buffp
)
{
off_t
len
;
return
utilfdt_read_err_len
(
filename
,
buffp
,
&
len
);
}
char
*
utilfdt_read_len
(
const
char
*
filename
,
off_t
*
len
)
{
char
*
buff
;
int
ret
=
utilfdt_read_err_len
(
filename
,
&
buff
,
len
);
if
(
ret
)
{
fprintf
(
stderr
,
"Couldn't open blob from '%s': %s
\n
"
,
filename
,
strerror
(
ret
));
return
NULL
;
}
/* Successful read */
return
buff
;
}
char
*
utilfdt_read
(
const
char
*
filename
)
{
off_t
len
;
return
utilfdt_read_len
(
filename
,
&
len
);
}
int
utilfdt_write_err
(
const
char
*
filename
,
const
void
*
blob
)
{
int
fd
=
1
;
/* assume stdout */
int
totalsize
;
int
offset
;
int
ret
=
0
;
const
char
*
ptr
=
blob
;
if
(
strcmp
(
filename
,
"-"
)
!=
0
)
{
fd
=
open
(
filename
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0666
);
if
(
fd
<
0
)
return
errno
;
}
totalsize
=
fdt_totalsize
(
blob
);
offset
=
0
;
while
(
offset
<
totalsize
)
{
ret
=
write
(
fd
,
ptr
+
offset
,
totalsize
-
offset
);
if
(
ret
<
0
)
{
ret
=
-
errno
;
break
;
}
offset
+=
ret
;
}
/* Close the file/stdin; return errno on error */
if
(
fd
!=
1
)
close
(
fd
);
return
ret
<
0
?
-
ret
:
0
;
}
int
utilfdt_write
(
const
char
*
filename
,
const
void
*
blob
)
{
int
ret
=
utilfdt_write_err
(
filename
,
blob
);
if
(
ret
)
{
fprintf
(
stderr
,
"Couldn't write blob to '%s': %s
\n
"
,
filename
,
strerror
(
ret
));
}
return
ret
?
-
1
:
0
;
}
int
utilfdt_decode_type
(
const
char
*
fmt
,
int
*
type
,
int
*
size
)
{
int
qualifier
=
0
;
if
(
!*
fmt
)
return
-
1
;
/* get the conversion qualifier */
*
size
=
-
1
;
if
(
strchr
(
"hlLb"
,
*
fmt
))
{
qualifier
=
*
fmt
++
;
if
(
qualifier
==
*
fmt
)
{
switch
(
*
fmt
++
)
{
/* TODO: case 'l': qualifier = 'L'; break;*/
case
'h'
:
qualifier
=
'b'
;
break
;
}
}
}
/* we should now have a type */
if
((
*
fmt
==
'\0'
)
||
!
strchr
(
"iuxs"
,
*
fmt
))
return
-
1
;
/* convert qualifier (bhL) to byte size */
if
(
*
fmt
!=
's'
)
*
size
=
qualifier
==
'b'
?
1
:
qualifier
==
'h'
?
2
:
qualifier
==
'l'
?
4
:
-
1
;
*
type
=
*
fmt
++
;
/* that should be it! */
if
(
*
fmt
)
return
-
1
;
return
0
;
}
void
utilfdt_print_data
(
const
char
*
data
,
int
len
)
{
int
i
;
const
char
*
s
;
/* no data, don't print */
if
(
len
==
0
)
return
;
if
(
util_is_printable_string
(
data
,
len
))
{
printf
(
" = "
);
s
=
data
;
do
{
printf
(
"
\"
%s
\"
"
,
s
);
s
+=
strlen
(
s
)
+
1
;
if
(
s
<
data
+
len
)
printf
(
", "
);
}
while
(
s
<
data
+
len
);
}
else
if
((
len
%
4
)
==
0
)
{
const
fdt32_t
*
cell
=
(
const
fdt32_t
*
)
data
;
printf
(
" = <"
);
for
(
i
=
0
,
len
/=
4
;
i
<
len
;
i
++
)
printf
(
"0x%08x%s"
,
fdt32_to_cpu
(
cell
[
i
]),
i
<
(
len
-
1
)
?
" "
:
""
);
printf
(
">"
);
}
else
{
const
unsigned
char
*
p
=
(
const
unsigned
char
*
)
data
;
printf
(
" = ["
);
for
(
i
=
0
;
i
<
len
;
i
++
)
printf
(
"%02x%s"
,
*
p
++
,
i
<
len
-
1
?
" "
:
""
);
printf
(
"]"
);
}
}
void
NORETURN
util_version
(
void
)
{
printf
(
"Version: %s
\n
"
,
DTC_VERSION
);
exit
(
0
);
}
void
NORETURN
util_usage
(
const
char
*
errmsg
,
const
char
*
synopsis
,
const
char
*
short_opts
,
struct
option
const
long_opts
[],
const
char
*
const
opts_help
[])
{
FILE
*
fp
=
errmsg
?
stderr
:
stdout
;
const
char
a_arg
[]
=
"<arg>"
;
size_t
a_arg_len
=
strlen
(
a_arg
)
+
1
;
size_t
i
;
int
optlen
;
fprintf
(
fp
,
"Usage: %s
\n
"
"
\n
"
"Options: -[%s]
\n
"
,
synopsis
,
short_opts
);
/* prescan the --long opt length to auto-align */
optlen
=
0
;
for
(
i
=
0
;
long_opts
[
i
].
name
;
++
i
)
{
/* +1 is for space between --opt and help text */
int
l
=
strlen
(
long_opts
[
i
].
name
)
+
1
;
if
(
long_opts
[
i
].
has_arg
==
a_argument
)
l
+=
a_arg_len
;
if
(
optlen
<
l
)
optlen
=
l
;
}
for
(
i
=
0
;
long_opts
[
i
].
name
;
++
i
)
{
/* helps when adding new applets or options */
assert
(
opts_help
[
i
]
!=
NULL
);
/* first output the short flag if it has one */
if
(
long_opts
[
i
].
val
>
'~'
)
fprintf
(
fp
,
" "
);
else
fprintf
(
fp
,
" -%c, "
,
long_opts
[
i
].
val
);
/* then the long flag */
if
(
long_opts
[
i
].
has_arg
==
no_argument
)
fprintf
(
fp
,
"--%-*s"
,
optlen
,
long_opts
[
i
].
name
);
else
fprintf
(
fp
,
"--%s %s%*s"
,
long_opts
[
i
].
name
,
a_arg
,
(
int
)(
optlen
-
strlen
(
long_opts
[
i
].
name
)
-
a_arg_len
),
""
);
/* finally the help text */
fprintf
(
fp
,
"%s
\n
"
,
opts_help
[
i
]);
}
if
(
errmsg
)
{
fprintf
(
fp
,
"
\n
Error: %s
\n
"
,
errmsg
);
exit
(
EXIT_FAILURE
);
}
else
exit
(
EXIT_SUCCESS
);
}
u-boot-tree/scripts/dtc/util.h
deleted
100644 → 0
View file @
3e304607
#ifndef UTIL_H
#define UTIL_H
#include <stdarg.h>
#include <stdbool.h>
#include <getopt.h>
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifdef __GNUC__
#define PRINTF(i, j) __attribute__((format (printf, i, j)))
#define NORETURN __attribute__((noreturn))
#else
#define PRINTF(i, j)
#define NORETURN
#endif
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define stringify(s) stringify_(s)
#define stringify_(s) #s
static
inline
void
NORETURN
PRINTF
(
1
,
2
)
die
(
const
char
*
str
,
...)
{
va_list
ap
;
va_start
(
ap
,
str
);
fprintf
(
stderr
,
"FATAL ERROR: "
);
vfprintf
(
stderr
,
str
,
ap
);
va_end
(
ap
);
exit
(
1
);
}
static
inline
void
*
xmalloc
(
size_t
len
)
{
void
*
new
=
malloc
(
len
);
if
(
!
new
)
die
(
"malloc() failed
\n
"
);
return
new
;
}
static
inline
void
*
xrealloc
(
void
*
p
,
size_t
len
)
{
void
*
new
=
realloc
(
p
,
len
);
if
(
!
new
)
die
(
"realloc() failed (len=%zd)
\n
"
,
len
);
return
new
;
}
extern
char
*
xstrdup
(
const
char
*
s
);
extern
int
PRINTF
(
2
,
3
)
xasprintf
(
char
**
strp
,
const
char
*
fmt
,
...);
extern
char
*
join_path
(
const
char
*
path
,
const
char
*
name
);
/**
* Check a property of a given length to see if it is all printable and
* has a valid terminator. The property can contain either a single string,
* or multiple strings each of non-zero length.
*
* @param data The string to check
* @param len The string length including terminator
* @return 1 if a valid printable string, 0 if not
*/
bool
util_is_printable_string
(
const
void
*
data
,
int
len
);
/*
* Parse an escaped character starting at index i in string s. The resulting
* character will be returned and the index i will be updated to point at the
* character directly after the end of the encoding, this may be the '\0'
* terminator of the string.
*/
char
get_escape_char
(
const
char
*
s
,
int
*
i
);
/**
* Read a device tree file into a buffer. This will report any errors on
* stderr.
*
* @param filename The filename to read, or - for stdin
* @return Pointer to allocated buffer containing fdt, or NULL on error
*/
char
*
utilfdt_read
(
const
char
*
filename
);
/**
* Like utilfdt_read(), but also passes back the size of the file read.
*
* @param len If non-NULL, the amount of data we managed to read
*/
char
*
utilfdt_read_len
(
const
char
*
filename
,
off_t
*
len
);
/**
* Read a device tree file into a buffer. Does not report errors, but only
* returns them. The value returned can be passed to strerror() to obtain
* an error message for the user.
*
* @param filename The filename to read, or - for stdin
* @param buffp Returns pointer to buffer containing fdt
* @return 0 if ok, else an errno value representing the error
*/
int
utilfdt_read_err
(
const
char
*
filename
,
char
**
buffp
);
/**
* Like utilfdt_read_err(), but also passes back the size of the file read.
*
* @param len If non-NULL, the amount of data we managed to read
*/
int
utilfdt_read_err_len
(
const
char
*
filename
,
char
**
buffp
,
off_t
*
len
);
/**
* Write a device tree buffer to a file. This will report any errors on
* stderr.
*
* @param filename The filename to write, or - for stdout
* @param blob Poiner to buffer containing fdt
* @return 0 if ok, -1 on error
*/
int
utilfdt_write
(
const
char
*
filename
,
const
void
*
blob
);
/**
* Write a device tree buffer to a file. Does not report errors, but only
* returns them. The value returned can be passed to strerror() to obtain
* an error message for the user.
*
* @param filename The filename to write, or - for stdout
* @param blob Poiner to buffer containing fdt
* @return 0 if ok, else an errno value representing the error
*/
int
utilfdt_write_err
(
const
char
*
filename
,
const
void
*
blob
);
/**
* Decode a data type string. The purpose of this string
*
* The string consists of an optional character followed by the type:
* Modifier characters:
* hh or b 1 byte
* h 2 byte
* l 4 byte, default
*
* Type character:
* s string
* i signed integer
* u unsigned integer
* x hex
*
* TODO: Implement ll modifier (8 bytes)
* TODO: Implement o type (octal)
*
* @param fmt Format string to process
* @param type Returns type found(s/d/u/x), or 0 if none
* @param size Returns size found(1,2,4,8) or 4 if none
* @return 0 if ok, -1 on error (no type given, or other invalid format)
*/
int
utilfdt_decode_type
(
const
char
*
fmt
,
int
*
type
,
int
*
size
);
/*
* This is a usage message fragment for the -t option. It is the format
* supported by utilfdt_decode_type.
*/
#define USAGE_TYPE_MSG \
"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
"\tOptional modifier prefix:\n" \
"\t\thh or b=byte, h=2 byte, l=4 byte (default)";
/**
* Print property data in a readable format to stdout
*
* Properties that look like strings will be printed as strings. Otherwise
* the data will be displayed either as cells (if len is a multiple of 4
* bytes) or bytes.
*
* If len is 0 then this function does nothing.
*
* @param data Pointers to property data
* @param len Length of property data
*/
void
utilfdt_print_data
(
const
char
*
data
,
int
len
);
/**
* Show source version and exit
*/
void
NORETURN
util_version
(
void
);
/**
* Show usage and exit
*
* This helps standardize the output of various utils. You most likely want
* to use the usage() helper below rather than call this.
*
* @param errmsg If non-NULL, an error message to display
* @param synopsis The initial example usage text (and possible examples)
* @param short_opts The string of short options
* @param long_opts The structure of long options
* @param opts_help An array of help strings (should align with long_opts)
*/
void
NORETURN
util_usage
(
const
char
*
errmsg
,
const
char
*
synopsis
,
const
char
*
short_opts
,
struct
option
const
long_opts
[],
const
char
*
const
opts_help
[]);
/**
* Show usage and exit
*
* If you name all your usage variables with usage_xxx, then you can call this
* help macro rather than expanding all arguments yourself.
*
* @param errmsg If non-NULL, an error message to display
*/
#define usage(errmsg) \
util_usage(errmsg, usage_synopsis, usage_short_opts, \
usage_long_opts, usage_opts_help)
/**
* Call getopt_long() with standard options
*
* Since all util code runs getopt in the same way, provide a helper.
*/
#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
usage_long_opts, NULL)
/* Helper for aligning long_opts array */
#define a_argument required_argument
/* Helper for usage_short_opts string constant */
#define USAGE_COMMON_SHORT_OPTS "hV"
/* Helper for usage_long_opts option array */
#define USAGE_COMMON_LONG_OPTS \
{"help", no_argument, NULL, 'h'}, \
{"version", no_argument, NULL, 'V'}, \
{NULL, no_argument, NULL, 0x0}
/* Helper for usage_opts_help array */
#define USAGE_COMMON_OPTS_HELP \
"Print this help and exit", \
"Print version and exit", \
NULL
/* Helper for getopt case statements */
#define case_USAGE_COMMON_FLAGS \
case 'h': usage(NULL); \
case 'V': util_version(); \
case '?': usage("unknown option");
#endif
/* UTIL_H */
u-boot-tree/scripts/dtc/version_gen.h
deleted
100644 → 0
View file @
3e304607
#define DTC_VERSION "DTC 1.4.6-gaadd0b65"
u-boot-tree/tools/aisimage.c
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright 2011
* Stefano Babic, DENX Software Engineering, sbabic@denx.de.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "imagetool.h"
#include "aisimage.h"
#include <image.h>
#define IS_FNC_EXEC(c) (cmd_table[c].AIS_cmd == AIS_CMD_FNLOAD)
#define WORD_ALIGN0 4
#define WORD_ALIGN(len) (((len)+WORD_ALIGN0-1) & ~(WORD_ALIGN0-1))
#define MAX_CMD_BUFFER 4096
static
uint32_t
ais_img_size
;
/*
* Supported commands for configuration file
*/
static
table_entry_t
aisimage_cmds
[]
=
{
{
CMD_DATA
,
"DATA"
,
"Reg Write Data"
},
{
CMD_FILL
,
"FILL"
,
"Fill range with pattern"
},
{
CMD_CRCON
,
"CRCON"
,
"CRC Enable"
},
{
CMD_CRCOFF
,
"CRCOFF"
,
"CRC Disable"
},
{
CMD_CRCCHECK
,
"CRCCHECK"
,
"CRC Validate"
},
{
CMD_JMPCLOSE
,
"JMPCLOSE"
,
"Jump & Close"
},
{
CMD_JMP
,
"JMP"
,
"Jump"
},
{
CMD_SEQREAD
,
"SEQREAD"
,
"Sequential read"
},
{
CMD_PLL0
,
"PLL0"
,
"PLL0"
},
{
CMD_PLL1
,
"PLL1"
,
"PLL1"
},
{
CMD_CLK
,
"CLK"
,
"Clock configuration"
},
{
CMD_DDR2
,
"DDR2"
,
"DDR2 Configuration"
},
{
CMD_EMIFA
,
"EMIFA"
,
"EMIFA"
},
{
CMD_EMIFA_ASYNC
,
"EMIFA_ASYNC"
,
"EMIFA Async"
},
{
CMD_PLL
,
"PLL"
,
"PLL & Clock configuration"
},
{
CMD_PSC
,
"PSC"
,
"PSC setup"
},
{
CMD_PINMUX
,
"PINMUX"
,
"Pinmux setup"
},
{
CMD_BOOTTABLE
,
"BOOT_TABLE"
,
"Boot table command"
},
{
-
1
,
""
,
""
},
};
static
struct
ais_func_exec
{
uint32_t
index
;
uint32_t
argcnt
;
}
ais_func_table
[]
=
{
[
CMD_PLL0
]
=
{
0
,
2
},
[
CMD_PLL1
]
=
{
1
,
2
},
[
CMD_CLK
]
=
{
2
,
1
},
[
CMD_DDR2
]
=
{
3
,
8
},
[
CMD_EMIFA
]
=
{
4
,
5
},
[
CMD_EMIFA_ASYNC
]
=
{
5
,
5
},
[
CMD_PLL
]
=
{
6
,
3
},
[
CMD_PSC
]
=
{
7
,
1
},
[
CMD_PINMUX
]
=
{
8
,
3
}
};
static
struct
cmd_table_t
{
uint32_t
nargs
;
uint32_t
AIS_cmd
;
}
cmd_table
[]
=
{
[
CMD_FILL
]
=
{
4
,
AIS_CMD_FILL
},
[
CMD_CRCON
]
=
{
0
,
AIS_CMD_ENCRC
},
[
CMD_CRCOFF
]
=
{
0
,
AIS_CMD_DISCRC
},
[
CMD_CRCCHECK
]
=
{
2
,
AIS_CMD_ENCRC
},
[
CMD_JMPCLOSE
]
=
{
1
,
AIS_CMD_JMPCLOSE
},
[
CMD_JMP
]
=
{
1
,
AIS_CMD_JMP
},
[
CMD_SEQREAD
]
=
{
0
,
AIS_CMD_SEQREAD
},
[
CMD_PLL0
]
=
{
2
,
AIS_CMD_FNLOAD
},
[
CMD_PLL1
]
=
{
2
,
AIS_CMD_FNLOAD
},
[
CMD_CLK
]
=
{
1
,
AIS_CMD_FNLOAD
},
[
CMD_DDR2
]
=
{
8
,
AIS_CMD_FNLOAD
},
[
CMD_EMIFA
]
=
{
5
,
AIS_CMD_FNLOAD
},
[
CMD_EMIFA_ASYNC
]
=
{
5
,
AIS_CMD_FNLOAD
},
[
CMD_PLL
]
=
{
3
,
AIS_CMD_FNLOAD
},
[
CMD_PSC
]
=
{
1
,
AIS_CMD_FNLOAD
},
[
CMD_PINMUX
]
=
{
3
,
AIS_CMD_FNLOAD
},
[
CMD_BOOTTABLE
]
=
{
4
,
AIS_CMD_BOOTTBL
},
};
static
uint32_t
get_cfg_value
(
char
*
token
,
char
*
name
,
int
linenr
)
{
char
*
endptr
;
uint32_t
value
;
errno
=
0
;
value
=
strtoul
(
token
,
&
endptr
,
16
);
if
(
errno
||
(
token
==
endptr
))
{
fprintf
(
stderr
,
"Error: %s[%d] - Invalid hex data(%s)
\n
"
,
name
,
linenr
,
token
);
exit
(
EXIT_FAILURE
);
}
return
value
;
}
static
int
get_ais_table_id
(
uint32_t
*
ptr
)
{
int
i
;
int
func_no
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
cmd_table
);
i
++
)
{
if
(
*
ptr
==
cmd_table
[
i
].
AIS_cmd
)
{
if
(
cmd_table
[
i
].
AIS_cmd
!=
AIS_CMD_FNLOAD
)
return
i
;
func_no
=
((
struct
ais_cmd_func
*
)
ptr
)
->
func_args
&
0xFFFF
;
if
(
func_no
==
ais_func_table
[
i
].
index
)
return
i
;
}
}
return
-
1
;
}
static
void
aisimage_print_header
(
const
void
*
hdr
)
{
struct
ais_header
*
ais_hdr
=
(
struct
ais_header
*
)
hdr
;
uint32_t
*
ptr
;
struct
ais_cmd_load
*
ais_load
;
int
id
;
if
(
ais_hdr
->
magic
!=
AIS_MAGIC_WORD
)
{
fprintf
(
stderr
,
"Error: - AIS Magic Number not found
\n
"
);
return
;
}
fprintf
(
stdout
,
"Image Type: TI Davinci AIS Boot Image
\n
"
);
fprintf
(
stdout
,
"AIS magic : %08x
\n
"
,
ais_hdr
->
magic
);
ptr
=
(
uint32_t
*
)
&
ais_hdr
->
magic
;
ptr
++
;
while
(
*
ptr
!=
AIS_CMD_JMPCLOSE
)
{
/* Check if we find the image */
if
(
*
ptr
==
AIS_CMD_LOAD
)
{
ais_load
=
(
struct
ais_cmd_load
*
)
ptr
;
fprintf
(
stdout
,
"Image at : 0x%08x size 0x%08x
\n
"
,
ais_load
->
addr
,
ais_load
->
size
);
ptr
=
ais_load
->
data
+
ais_load
->
size
/
sizeof
(
*
ptr
);
continue
;
}
id
=
get_ais_table_id
(
ptr
);
if
(
id
<
0
)
{
fprintf
(
stderr
,
"Error: - AIS Image corrupted
\n
"
);
return
;
}
fprintf
(
stdout
,
"AIS cmd : %s
\n
"
,
get_table_entry_name
(
aisimage_cmds
,
NULL
,
id
));
ptr
+=
cmd_table
[
id
].
nargs
+
IS_FNC_EXEC
(
id
)
+
1
;
if
(((
void
*
)
ptr
-
hdr
)
>
ais_img_size
)
{
fprintf
(
stderr
,
"AIS Image not terminated by JMPCLOSE
\n
"
);
return
;
}
}
}
static
uint32_t
*
ais_insert_cmd_header
(
uint32_t
cmd
,
uint32_t
nargs
,
uint32_t
*
parms
,
struct
image_type_params
*
tparams
,
uint32_t
*
ptr
)
{
int
i
;
*
ptr
++
=
cmd_table
[
cmd
].
AIS_cmd
;
if
(
IS_FNC_EXEC
(
cmd
))
*
ptr
++
=
((
nargs
&
0xFFFF
)
<<
16
)
+
ais_func_table
[
cmd
].
index
;
/* Copy parameters */
for
(
i
=
0
;
i
<
nargs
;
i
++
)
*
ptr
++
=
cpu_to_le32
(
parms
[
i
]);
return
ptr
;
}
static
uint32_t
*
ais_alloc_buffer
(
struct
image_tool_params
*
params
)
{
int
dfd
;
struct
stat
sbuf
;
char
*
datafile
=
params
->
datafile
;
uint32_t
*
ptr
;
dfd
=
open
(
datafile
,
O_RDONLY
|
O_BINARY
);
if
(
dfd
<
0
)
{
fprintf
(
stderr
,
"%s: Can't open %s: %s
\n
"
,
params
->
cmdname
,
datafile
,
strerror
(
errno
));
exit
(
EXIT_FAILURE
);
}
if
(
fstat
(
dfd
,
&
sbuf
)
<
0
)
{
fprintf
(
stderr
,
"%s: Can't stat %s: %s
\n
"
,
params
->
cmdname
,
datafile
,
strerror
(
errno
));
exit
(
EXIT_FAILURE
);
}
/*
* Place for header is allocated. The size is taken from
* the size of the datafile, that the ais_image_generate()
* will copy into the header. Copying the datafile
* is not left to the main program, because after the datafile
* the header must be terminated with the Jump & Close command.
*/
ais_img_size
=
WORD_ALIGN
(
sbuf
.
st_size
)
+
MAX_CMD_BUFFER
;
ptr
=
(
uint32_t
*
)
malloc
(
WORD_ALIGN
(
sbuf
.
st_size
)
+
MAX_CMD_BUFFER
);
if
(
!
ptr
)
{
fprintf
(
stderr
,
"%s: malloc return failure: %s
\n
"
,
params
->
cmdname
,
strerror
(
errno
));
exit
(
EXIT_FAILURE
);
}
close
(
dfd
);
return
ptr
;
}
static
uint32_t
*
ais_copy_image
(
struct
image_tool_params
*
params
,
uint32_t
*
aisptr
)
{
int
dfd
;
struct
stat
sbuf
;
char
*
datafile
=
params
->
datafile
;
void
*
ptr
;
dfd
=
open
(
datafile
,
O_RDONLY
|
O_BINARY
);
if
(
dfd
<
0
)
{
fprintf
(
stderr
,
"%s: Can't open %s: %s
\n
"
,
params
->
cmdname
,
datafile
,
strerror
(
errno
));
exit
(
EXIT_FAILURE
);
}
if
(
fstat
(
dfd
,
&
sbuf
)
<
0
)
{
fprintf
(
stderr
,
"%s: Can't stat %s: %s
\n
"
,
params
->
cmdname
,
datafile
,
strerror
(
errno
));
exit
(
EXIT_FAILURE
);
}
ptr
=
mmap
(
0
,
sbuf
.
st_size
,
PROT_READ
,
MAP_SHARED
,
dfd
,
0
);
*
aisptr
++
=
AIS_CMD_LOAD
;
*
aisptr
++
=
params
->
ep
;
*
aisptr
++
=
sbuf
.
st_size
;
memcpy
((
void
*
)
aisptr
,
ptr
,
sbuf
.
st_size
);
aisptr
+=
WORD_ALIGN
(
sbuf
.
st_size
)
/
sizeof
(
uint32_t
);
(
void
)
munmap
((
void
*
)
ptr
,
sbuf
.
st_size
);
(
void
)
close
(
dfd
);
return
aisptr
;
}
static
int
aisimage_generate
(
struct
image_tool_params
*
params
,
struct
image_type_params
*
tparams
)
{
FILE
*
fd
=
NULL
;
char
*
line
=
NULL
;
char
*
token
,
*
saveptr1
,
*
saveptr2
;
int
lineno
=
0
;
int
fld
;
size_t
len
;
int32_t
cmd
;
uint32_t
nargs
,
cmd_parms
[
10
];
uint32_t
value
,
size
;
char
*
name
=
params
->
imagename
;
uint32_t
*
aishdr
;
fd
=
fopen
(
name
,
"r"
);
if
(
fd
==
0
)
{
fprintf
(
stderr
,
"Error: %s - Can't open AIS configuration
\n
"
,
name
);
exit
(
EXIT_FAILURE
);
}
/*
* the size of the header is variable and is computed
* scanning the configuration file.
*/
tparams
->
header_size
=
0
;
/*
* Start allocating a buffer suitable for most command
* The buffer is then reallocated if it is too small
*/
aishdr
=
ais_alloc_buffer
(
params
);
tparams
->
hdr
=
aishdr
;
*
aishdr
++
=
AIS_MAGIC_WORD
;
/* Very simple parsing, line starting with # are comments
* and are dropped
*/
while
((
getline
(
&
line
,
&
len
,
fd
))
>
0
)
{
lineno
++
;
token
=
strtok_r
(
line
,
"
\r\n
"
,
&
saveptr1
);
if
(
token
==
NULL
)
continue
;
/* Check inside the single line */
line
=
token
;
fld
=
CFG_COMMAND
;
cmd
=
CMD_INVALID
;
nargs
=
0
;
while
(
token
!=
NULL
)
{
token
=
strtok_r
(
line
,
"
\t
"
,
&
saveptr2
);
if
(
token
==
NULL
)
break
;
/* Drop all text starting with '#' as comments */
if
(
token
[
0
]
==
'#'
)
break
;
switch
(
fld
)
{
case
CFG_COMMAND
:
cmd
=
get_table_entry_id
(
aisimage_cmds
,
"aisimage commands"
,
token
);
if
(
cmd
<
0
)
{
fprintf
(
stderr
,
"Error: %s[%d] - Invalid command"
"(%s)
\n
"
,
name
,
lineno
,
token
);
exit
(
EXIT_FAILURE
);
}
break
;
case
CFG_VALUE
:
value
=
get_cfg_value
(
token
,
name
,
lineno
);
cmd_parms
[
nargs
++
]
=
value
;
if
(
nargs
>
cmd_table
[
cmd
].
nargs
)
{
fprintf
(
stderr
,
"Error: %s[%d] - too much arguments:"
"(%s) for command %s
\n
"
,
name
,
lineno
,
token
,
aisimage_cmds
[
cmd
].
sname
);
exit
(
EXIT_FAILURE
);
}
break
;
}
line
=
NULL
;
fld
=
CFG_VALUE
;
}
if
(
cmd
!=
CMD_INVALID
)
{
/* Now insert the command into the header */
aishdr
=
ais_insert_cmd_header
(
cmd
,
nargs
,
cmd_parms
,
tparams
,
aishdr
);
}
}
fclose
(
fd
);
aishdr
=
ais_copy_image
(
params
,
aishdr
);
/* Add Jmp & Close */
*
aishdr
++
=
AIS_CMD_JMPCLOSE
;
*
aishdr
++
=
params
->
ep
;
size
=
(
aishdr
-
(
uint32_t
*
)
tparams
->
hdr
)
*
sizeof
(
uint32_t
);
tparams
->
header_size
=
size
;
return
0
;
}
static
int
aisimage_check_image_types
(
uint8_t
type
)
{
if
(
type
==
IH_TYPE_AISIMAGE
)
return
EXIT_SUCCESS
;
else
return
EXIT_FAILURE
;
}
static
int
aisimage_verify_header
(
unsigned
char
*
ptr
,
int
image_size
,
struct
image_tool_params
*
params
)
{
struct
ais_header
*
ais_hdr
=
(
struct
ais_header
*
)
ptr
;
if
(
ais_hdr
->
magic
!=
AIS_MAGIC_WORD
)
return
-
FDT_ERR_BADSTRUCTURE
;
/* Store the total size to remember in print_hdr */
ais_img_size
=
image_size
;
return
0
;
}
static
void
aisimage_set_header
(
void
*
ptr
,
struct
stat
*
sbuf
,
int
ifd
,
struct
image_tool_params
*
params
)
{
}
int
aisimage_check_params
(
struct
image_tool_params
*
params
)
{
if
(
!
params
)
return
CFG_INVALID
;
if
(
!
strlen
(
params
->
imagename
))
{
fprintf
(
stderr
,
"Error: %s - Configuration file not specified, "
"it is needed for aisimage generation
\n
"
,
params
->
cmdname
);
return
CFG_INVALID
;
}
/*
* Check parameters:
* XIP is not allowed and verify that incompatible
* parameters are not sent at the same time
* For example, if list is required a data image must not be provided
*/
return
(
params
->
dflag
&&
(
params
->
fflag
||
params
->
lflag
))
||
(
params
->
fflag
&&
(
params
->
dflag
||
params
->
lflag
))
||
(
params
->
lflag
&&
(
params
->
dflag
||
params
->
fflag
))
||
(
params
->
xflag
)
||
!
(
strlen
(
params
->
imagename
));
}
/*
* aisimage parameters
*/
U_BOOT_IMAGE_TYPE
(
aisimage
,
"TI Davinci AIS Boot Image support"
,
0
,
NULL
,
aisimage_check_params
,
aisimage_verify_header
,
aisimage_print_header
,
aisimage_set_header
,
NULL
,
aisimage_check_image_types
,
NULL
,
aisimage_generate
);
u-boot-tree/tools/aisimage.h
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright 2011
* Stefano Babic, DENX Software Engineering, sbabic@denx.de.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _AISIMAGE_H_
#define _AISIMAGE_H_
/* all values are for little endian systems */
#define AIS_MAGIC_WORD 0x41504954
#define AIS_FCN_MAX 8
enum
{
AIS_CMD_LOAD
=
0x58535901
,
AIS_CMD_VALCRC
=
0x58535902
,
AIS_CMD_ENCRC
=
0x58535903
,
AIS_CMD_DISCRC
=
0x58535904
,
AIS_CMD_JMP
=
0x58535905
,
AIS_CMD_JMPCLOSE
=
0x58535906
,
AIS_CMD_BOOTTBL
=
0x58535907
,
AIS_CMD_FILL
=
0x5853590A
,
AIS_CMD_FNLOAD
=
0x5853590D
,
AIS_CMD_SEQREAD
=
0x58535963
,
};
struct
ais_cmd_load
{
uint32_t
cmd
;
uint32_t
addr
;
uint32_t
size
;
uint32_t
data
[
1
];
};
struct
ais_cmd_func
{
uint32_t
cmd
;
uint32_t
func_args
;
uint32_t
parms
[
AIS_FCN_MAX
];
};
struct
ais_cmd_jmpclose
{
uint32_t
cmd
;
uint32_t
addr
;
};
#define CMD_DATA_STR "DATA"
enum
ais_file_cmd
{
CMD_INVALID
,
CMD_FILL
,
CMD_CRCON
,
CMD_CRCOFF
,
CMD_CRCCHECK
,
CMD_JMPCLOSE
,
CMD_JMP
,
CMD_SEQREAD
,
CMD_DATA
,
CMD_PLL0
,
CMD_PLL1
,
CMD_CLK
,
CMD_DDR2
,
CMD_EMIFA
,
CMD_EMIFA_ASYNC
,
CMD_PLL
,
CMD_PSC
,
CMD_PINMUX
,
CMD_BOOTTABLE
};
enum
aisimage_fld_types
{
CFG_INVALID
=
-
1
,
CFG_COMMAND
,
CFG_VALUE
,
};
struct
ais_header
{
uint32_t
magic
;
char
data
[
1
];
};
#endif
/* _AISIMAGE_H_ */
u-boot-tree/tools/fdt_host.h
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright 2008 Semihalf
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __FDT_HOST_H__
#define __FDT_HOST_H__
/* Make sure to include u-boot version of libfdt include files */
#include "../include/libfdt.h"
#include "../include/fdt_support.h"
/**
* fdt_remove_unused_strings() - Remove any unused strings from an FDT
*
* This creates a new device tree in @new with unused strings removed. The
* called can then use fdt_pack() to minimise the space consumed.
*
* @old: Old device tree blog
* @new: Place to put new device tree blob, which must be as large as
* @old
* @return
* 0, on success
* -FDT_ERR_BADOFFSET, corrupt device tree
* -FDT_ERR_NOSPACE, out of space, which should not happen unless there
* is something very wrong with the device tree input
*/
int
fdt_remove_unused_strings
(
const
void
*
old
,
void
*
new
);
int
fit_check_sign
(
const
void
*
working_fdt
,
const
void
*
key
);
#endif
/* __FDT_HOST_H__ */
u-boot-tree/tools/imagetool.h
deleted
100644 → 0
View file @
3e304607
/*
* (C) Copyright 2013
*
* Written by Guilherme Maciel Ferreira <guilherme.maciel.ferreira@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _IMAGETOOL_H_
#define _IMAGETOOL_H_
#include "os_support.h"
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <u-boot/sha1.h>
#include "fdt_host.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define IH_ARCH_DEFAULT IH_ARCH_INVALID
/* Information about a file that needs to be placed into the FIT */
struct
content_info
{
struct
content_info
*
next
;
int
type
;
/* File type (IH_TYPE_...) */
const
char
*
fname
;
};
/*
* This structure defines all such variables those are initialized by
* mkimage and dumpimage main core and need to be referred by image
* type specific functions
*/
struct
image_tool_params
{
int
dflag
;
int
eflag
;
int
fflag
;
int
iflag
;
int
lflag
;
int
pflag
;
int
vflag
;
int
xflag
;
int
skipcpy
;
int
os
;
int
arch
;
int
type
;
int
comp
;
char
*
dtc
;
unsigned
int
addr
;
unsigned
int
ep
;
char
*
imagename
;
char
*
imagename2
;
char
*
datafile
;
char
*
imagefile
;
char
*
cmdname
;
const
char
*
outfile
;
/* Output filename */
const
char
*
keydir
;
/* Directory holding private keys */
const
char
*
keydest
;
/* Destination .dtb for public key */
const
char
*
comment
;
/* Comment to add to signature node */
int
require_keys
;
/* 1 to mark signing keys as 'required' */
int
file_size
;
/* Total size of output file */
int
orig_file_size
;
/* Original size for file before padding */
bool
auto_its
;
/* Automatically create the .its file */
int
fit_image_type
;
/* Image type to put into the FIT */
struct
content_info
*
content_head
;
/* List of files to include */
struct
content_info
*
content_tail
;
bool
external_data
;
/* Store data outside the FIT */
};
/*
* image type specific variables and callback functions
*/
struct
image_type_params
{
/* name is an identification tag string for added support */
char
*
name
;
/*
* header size is local to the specific image type to be supported,
* mkimage core treats this as number of bytes
*/
uint32_t
header_size
;
/* Image type header pointer */
void
*
hdr
;
/*
* There are several arguments that are passed on the command line
* and are registered as flags in image_tool_params structure.
* This callback function can be used to check the passed arguments
* are in-lined with the image type to be supported
*
* Returns 1 if parameter check is successful
*/
int
(
*
check_params
)
(
struct
image_tool_params
*
);
/*
* This function is used by list command (i.e. mkimage -l <filename>)
* image type verification code must be put here
*
* Returns 0 if image header verification is successful
* otherwise, returns respective negative error codes
*/
int
(
*
verify_header
)
(
unsigned
char
*
,
int
,
struct
image_tool_params
*
);
/* Prints image information abstracting from image header */
void
(
*
print_header
)
(
const
void
*
);
/*
* The header or image contents need to be set as per image type to
* be generated using this callback function.
* further output file post processing (for ex. checksum calculation,
* padding bytes etc..) can also be done in this callback function.
*/
void
(
*
set_header
)
(
void
*
,
struct
stat
*
,
int
,
struct
image_tool_params
*
);
/*
* This function is used by the command to retrieve a component
* (sub-image) from the image (i.e. dumpimage -i <image> -p <position>
* <sub-image-name>).
* Thus the code to extract a file from an image must be put here.
*
* Returns 0 if the file was successfully retrieved from the image,
* or a negative value on error.
*/
int
(
*
extract_subimage
)(
void
*
,
struct
image_tool_params
*
);
/*
* Some image generation support for ex (default image type) supports
* more than one type_ids, this callback function is used to check
* whether input (-T <image_type>) is supported by registered image
* generation/list low level code
*/
int
(
*
check_image_type
)
(
uint8_t
);
/* This callback function will be executed if fflag is defined */
int
(
*
fflag_handle
)
(
struct
image_tool_params
*
);
/*
* This callback function will be executed for variable size record
* It is expected to build this header in memory and return its length
* and a pointer to it by using image_type_params.header_size and
* image_type_params.hdr. The return value shall indicate if an
* additional padding should be used when copying the data image
* by returning the padding length.
*/
int
(
*
vrec_header
)
(
struct
image_tool_params
*
,
struct
image_type_params
*
);
};
/**
* imagetool_get_type() - find the image type params for a given image type
*
* It scans all registers image type supports
* checks the input type for each supported image type
*
* if successful,
* returns respective image_type_params pointer if success
* if input type_id is not supported by any of image_type_support
* returns NULL
*/
struct
image_type_params
*
imagetool_get_type
(
int
type
);
/*
* imagetool_verify_print_header() - verifies the image header
*
* Scan registered image types and verify the image_header for each
* supported image type. If verification is successful, this prints
* the respective header.
*
* @return 0 on success, negative if input image format does not match with
* any of supported image types
*/
int
imagetool_verify_print_header
(
void
*
ptr
,
struct
stat
*
sbuf
,
struct
image_type_params
*
tparams
,
struct
image_tool_params
*
params
);
/**
* imagetool_save_subimage - store data into a file
* @file_name: name of the destination file
* @file_data: data to be written
* @file_len: the amount of data to store
*
* imagetool_save_subimage() store file_len bytes of data pointed by file_data
* into the file name by file_name.
*
* returns:
* zero in case of success or a negative value if fail.
*/
int
imagetool_save_subimage
(
const
char
*
file_name
,
ulong
file_data
,
ulong
file_len
);
/**
* imagetool_get_filesize() - Utility function to obtain the size of a file
*
* This function prints a message if an error occurs, showing the error that
* was obtained.
*
* @params: mkimage parameters
* @fname: filename to check
* @return size of file, or -ve value on error
*/
int
imagetool_get_filesize
(
struct
image_tool_params
*
params
,
const
char
*
fname
);
/*
* There is a c file associated with supported image type low level code
* for ex. default_image.c, fit_image.c
*/
void
pbl_load_uboot
(
int
fd
,
struct
image_tool_params
*
mparams
);
#define ___cat(a, b) a ## b
#define __cat(a, b) ___cat(a, b)
/* we need some special handling for this host tool running eventually on
* Darwin. The Mach-O section handling is a bit different than ELF section
* handling. The differnces in detail are:
* a) we have segments which have sections
* b) we need a API call to get the respective section symbols */
#if defined(__MACH__)
#include <mach-o/getsect.h>
#define INIT_SECTION(name) do { \
unsigned long name ## _len; \
char *__cat(pstart_, name) = getsectdata("__TEXT", \
#name, &__cat(name, _len)); \
char *__cat(pstop_, name) = __cat(pstart_, name) + \
__cat(name, _len); \
__cat(__start_, name) = (void *)__cat(pstart_, name); \
__cat(__stop_, name) = (void *)__cat(pstop_, name); \
} while (0)
#define SECTION(name) __attribute__((section("__TEXT, " #name)))
struct
image_type_params
**
__start_image_type
,
**
__stop_image_type
;
#else
#define INIT_SECTION(name)
/* no-op for ELF */
#define SECTION(name) __attribute__((section(#name)))
/* We construct a table of pointers in an ELF section (pointers generally
* go unpadded by gcc). ld creates boundary syms for us. */
extern
struct
image_type_params
*
__start_image_type
[],
*
__stop_image_type
[];
#endif
/* __MACH__ */
#if !defined(__used)
# if __GNUC__ == 3 && __GNUC_MINOR__ < 3
# define __used __attribute__((__unused__))
# else
# define __used __attribute__((__used__))
# endif
#endif
#define U_BOOT_IMAGE_TYPE( \
_id, \
_name, \
_header_size, \
_header, \
_check_params, \
_verify_header, \
_print_header, \
_set_header, \
_extract_subimage, \
_check_image_type, \
_fflag_handle, \
_vrec_header \
) \
static struct image_type_params __cat(image_type_, _id) = \
{ \
.name = _name, \
.header_size = _header_size, \
.hdr = _header, \
.check_params = _check_params, \
.verify_header = _verify_header, \
.print_header = _print_header, \
.set_header = _set_header, \
.extract_subimage = _extract_subimage, \
.check_image_type = _check_image_type, \
.fflag_handle = _fflag_handle, \
.vrec_header = _vrec_header \
}; \
static struct image_type_params *SECTION(image_type) __used \
__cat(image_type_ptr_, _id) = &__cat(image_type_, _id)
#endif
/* _IMAGETOOL_H_ */
u-boot-tree/tools/libfdt/fdt.c
0 → 100644
View file @
47fad1d4
#include "fdt_host.h"
#include "../scripts/dtc/libfdt/fdt.c"
u-boot-tree/tools/libfdt/fdt_addresses.c
0 → 100644
View file @
47fad1d4
#include "fdt_host.h"
#include "../scripts/dtc/libfdt/fdt_addresses.c"
u-boot-tree/tools/libfdt/fdt_empty_tree.c
0 → 100644
View file @
47fad1d4
#include "fdt_host.h"
#include "../scripts/dtc/libfdt/fdt_empty_tree.c"
u-boot-tree/tools/libfdt/fdt_overlay.c
0 → 100644
View file @
47fad1d4
#include "fdt_host.h"
#include "../scripts/dtc/libfdt/fdt_overlay.c"
u-boot-tree/tools/libfdt/fdt_rw.c
0 → 100644
View file @
47fad1d4
/* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause */
#include "fdt_host.h"
#include "../../scripts/dtc/libfdt/fdt_rw.c"
int
fdt_remove_unused_strings
(
const
void
*
old
,
void
*
new
)
{
const
struct
fdt_property
*
old_prop
;
struct
fdt_property
*
new_prop
;
int
size
=
fdt_totalsize
(
old
);
int
next_offset
,
offset
;
const
char
*
str
;
int
ret
;
int
tag
=
FDT_PROP
;
/* Make a copy and remove the strings */
memcpy
(
new
,
old
,
size
);
fdt_set_size_dt_strings
(
new
,
0
);
/* Add every property name back into the new string table */
for
(
offset
=
0
;
tag
!=
FDT_END
;
offset
=
next_offset
)
{
tag
=
fdt_next_tag
(
old
,
offset
,
&
next_offset
);
if
(
tag
!=
FDT_PROP
)
continue
;
old_prop
=
fdt_get_property_by_offset
(
old
,
offset
,
NULL
);
new_prop
=
(
struct
fdt_property
*
)(
unsigned
long
)
fdt_get_property_by_offset
(
new
,
offset
,
NULL
);
str
=
fdt_string
(
old
,
fdt32_to_cpu
(
old_prop
->
nameoff
));
ret
=
_fdt_find_add_string
(
new
,
str
);
if
(
ret
<
0
)
return
ret
;
new_prop
->
nameoff
=
cpu_to_fdt32
(
ret
);
}
return
0
;
}
u-boot-tree/tools/libfdt/fdt_strerror.c
0 → 100644
View file @
47fad1d4
#include "fdt_host.h"
#include "../scripts/dtc/libfdt/fdt_strerror.c"
u-boot-tree/tools/libfdt/fdt_sw.c
0 → 100644
View file @
47fad1d4
#include "fdt_host.h"
#include "../scripts/dtc/libfdt/fdt_sw.c"
u-boot-tree/tools/libfdt/fdt_wip.c
0 → 100644
View file @
47fad1d4
#include "fdt_host.h"
#include "../scripts/dtc/libfdt/fdt_wip.c"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment