DeviceTree updates for 4.6:

- New tool dtx_diff to diff DT files.
 
 - Sync kernel's dtc/libfdt to current dtc repo master.
 
 - Fix for reserved memory regions located in highmem.
 
 - Document standard unit suffixes for DT properties.
 
 - Various DT binding doc updates.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJW7B34AAoJEPr7XbWNvGHDI4QP/0W0s3dvJ4l/TNeu/n1ZN8i7
 H4FYNcNGVEPJMaI4gIV+GOnxJ4hTnEX2ftG9MEZCywVHWNCg4IAaIW1wQ52Sufnc
 Uncc9qO0MMR5Y1Siu/DuLi+ARyPQrke3M/o5xU9XJjSdz9QpnYw1MpMnpAJANomk
 /8Wjn2jEBHDJrxmJ73nE/CAVu8iFyWHTmt5pDQBoQub2NVuAX6rNcVmpmr0PhDMd
 0CKokB+wmLHZEA2R4BBefjLwwKU1WrF/5ytXpsJ01NeZsExagJZz1fQdy3Z6o1Xx
 PRTukmmNhknatNTJOD8XmLr/SWN2CKNuJK5EOoV2opAvN/fc+mrk95DGKzjh5n64
 aCRHzZgKAOYOqdVJKHfJ9hfzgG/zdt4mt1RKhLD+6qZNoSeQSrtikN3DWibPMZQR
 uHRC9fqalx+W4cBH4jakGYrpsbQOaQFjb6vHY8V/auSB2cx97YVuKCawnSerjWZv
 1tu8dqNG0qwt9g0hgA+ycwitulUNSLSvLGp3mxBJXN2ULPHygCw53JUWFQEZhoAa
 JQqZ7lrUSE+AEp6Cwc0sNn07UMoCAoZKbTaurm2rn2RrKMfnirbf/sdZkc9Hq2pg
 TIJOJlmJmvheoCl7894iV1l18ooPqldk6h8d9fc6rngaQYkNaV0c9nlaMLTa2Rwi
 bVztrJItiymIhjIB86Iw
 =hz7v
 -----END PGP SIGNATURE-----

Merge tag 'devicetree-for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux

Pull DeviceTree updates from Rob Herring:

 - new tool 'dtx_diff' to diff DT files

 - sync kernel's dtc/libfdt to current dtc repo master

 - fix for reserved memory regions located in highmem

 - document standard unit suffixes for DT properties

 - various DT binding doc updates

* tag 'devicetree-for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux:
  of: Add vendor prefix for eGalax_eMPIA Technology Inc
  Input: ads7846: Add description how to use internal reference (ADS7846)
  ARM: realview: add EB syscon variants to bindings
  devicetree: bindings: ARM: Use "uV" for micro-volt
  serial: fsl-imx-uart: Fix typo in fsl,dte-mode description
  of: add 'const' for of_property_*_string*() parameter '*np'
  of/unittest: fix infinite loop in of_unittest_destroy_tracked_overlays()
  of: alloc anywhere from memblock if range not specified
  kbuild: Allow using host dtc instead of kernel's copy
  of: resolver: Add missing of_node_get and of_node_put
  of: Add United Radiant Technology Corporation vendor prefix
  dt/bindings: add documentation on standard property unit suffixes
  scripts/dtc: Update to upstream commit b06e55c88b9b
  ARM: boot: Add an implementation of strnlen for libfdt
  scripts/dtc: dtx_diff - add info to error message
  dtc: create tool to diff device trees
This commit is contained in:
Linus Torvalds 2016-03-19 15:15:07 -07:00
commit 31e182363b
25 changed files with 836 additions and 142 deletions

View File

@ -123,7 +123,9 @@ Required nodes:
- syscon: some subnode of the RealView SoC node must be a
system controller node pointing to the control registers,
with the compatible string set to one of these tuples:
with the compatible string set to one of these:
"arm,realview-eb11mp-revb-syscon", "arm,realview-eb-syscon", "syscon"
"arm,realview-eb11mp-revc-syscon", "arm,realview-eb-syscon", "syscon"
"arm,realview-eb-syscon", "syscon"
"arm,realview-pb1176-syscon", "syscon"
"arm,realview-pb11mp-syscon", "syscon"

View File

@ -250,7 +250,7 @@ nodes to be present and contain the properties described below.
Usage: optional
Value type: <prop-encoded-array>
Definition: A u32 value that represents the running time dynamic
power coefficient in units of mW/MHz/uVolt^2. The
power coefficient in units of mW/MHz/uV^2. The
coefficient can either be calculated from power
measurements or derived by analysis.

View File

@ -29,6 +29,8 @@ Optional properties:
ti,vref-delay-usecs vref supply delay in usecs, 0 for
external vref (u16).
ti,vref-mv The VREF voltage, in millivolts (u16).
Set to 0 to use internal refernce
(ADS7846).
ti,keep-vref-on set to keep vref on for differential
measurements as well
ti,swap-xy swap x and y axis

View File

@ -0,0 +1,39 @@
Standard Unit Suffixes for Property names
Properties which have a unit of measure are recommended to have a unit
suffix appended to the property name. The list below contains the
recommended suffixes. Other variations exist in bindings, but should not
be used in new bindings or added here. The inconsistency in the unit
prefixes is due to selecting the most commonly used variants.
It is also recommended to use the units listed here and not add additional
unit prefixes.
Time/Frequency
----------------------------------------
-mhz : megahertz
-hz : Hertz (preferred)
-sec : seconds
-ms : milliseconds
-us : microseconds
-ns : nanoseconds
Distance
----------------------------------------
-mm : millimeters
Electricity
----------------------------------------
-microamp : micro amps
-ohms : Ohms
-micro-ohms : micro Ohms
-microvolt : micro volts
Temperature
----------------------------------------
-celsius : Degrees Celsius
-millicelsius : Degreee milli-Celsius
Pressure
----------------------------------------
-kpascal : kiloPascal

View File

@ -72,6 +72,7 @@ dmo Data Modul AG
ea Embedded Artists AB
ebv EBV Elektronik
edt Emerging Display Technologies
eeti eGalax_eMPIA Technology Inc
elan Elan Microelectronic Corp.
emmicro EM Microelectronic
energymicro Silicon Laboratories (formerly Energy Micro AS)
@ -247,6 +248,7 @@ tplink TP-LINK Technologies Co., Ltd.
tronfy Tronfy
truly Truly Semiconductors Limited
upisemi uPI Semiconductor Corp.
urt United Radiant Technology Corporation
usi Universal Scientific Industrial Co., Ltd.
v3 V3 Semiconductor
variscite Variscite Ltd.

View File

@ -65,6 +65,15 @@ size_t strlen(const char *s)
return sc - s;
}
size_t strnlen(const char *s, size_t count)
{
const char *sc;
for (sc = s; count-- && *sc != '\0'; ++sc)
/* nothing */;
return sc - s;
}
int memcmp(const void *cs, const void *ct, size_t count)
{
const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;

View File

@ -1341,10 +1341,10 @@ EXPORT_SYMBOL_GPL(of_property_read_u64_array);
*
* The out_string pointer is modified only if a valid string can be decoded.
*/
int of_property_read_string(struct device_node *np, const char *propname,
int of_property_read_string(const struct device_node *np, const char *propname,
const char **out_string)
{
struct property *prop = of_find_property(np, propname, NULL);
const struct property *prop = of_find_property(np, propname, NULL);
if (!prop)
return -EINVAL;
if (!prop->value)
@ -1365,10 +1365,10 @@ EXPORT_SYMBOL_GPL(of_property_read_string);
* This function searches a string list property and returns the index
* of a specific string value.
*/
int of_property_match_string(struct device_node *np, const char *propname,
int of_property_match_string(const struct device_node *np, const char *propname,
const char *string)
{
struct property *prop = of_find_property(np, propname, NULL);
const struct property *prop = of_find_property(np, propname, NULL);
size_t l;
int i;
const char *p, *end;
@ -1404,10 +1404,11 @@ EXPORT_SYMBOL_GPL(of_property_match_string);
* Don't call this function directly. It is a utility helper for the
* of_property_read_string*() family of functions.
*/
int of_property_read_string_helper(struct device_node *np, const char *propname,
const char **out_strs, size_t sz, int skip)
int of_property_read_string_helper(const struct device_node *np,
const char *propname, const char **out_strs,
size_t sz, int skip)
{
struct property *prop = of_find_property(np, propname, NULL);
const struct property *prop = of_find_property(np, propname, NULL);
int l = 0, i = 0;
const char *p, *end;

View File

@ -32,11 +32,13 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
phys_addr_t *res_base)
{
phys_addr_t base;
/*
* We use __memblock_alloc_base() because memblock_alloc_base()
* panic()s on allocation failure.
*/
phys_addr_t base = __memblock_alloc_base(size, align, end);
end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end;
base = __memblock_alloc_base(size, align, end);
if (!base)
return -ENOMEM;

View File

@ -36,12 +36,14 @@ static struct device_node *__of_find_node_by_full_name(struct device_node *node,
/* check */
if (of_node_cmp(node->full_name, full_name) == 0)
return node;
return of_node_get(node);
for_each_child_of_node(node, child) {
found = __of_find_node_by_full_name(child, full_name);
if (found != NULL)
if (found != NULL) {
of_node_put(child);
return found;
}
}
return NULL;
@ -174,6 +176,7 @@ static int __of_adjust_phandle_ref(struct device_node *node,
if (of_prop_cmp(sprop->name, propstr) == 0)
break;
}
of_node_put(refnode);
if (!sprop) {
pr_err("%s: Could not find property '%s'\n",

View File

@ -1165,6 +1165,11 @@ static void of_unittest_destroy_tracked_overlays(void)
continue;
ret = of_overlay_destroy(id + overlay_first_id);
if (ret == -ENODEV) {
pr_warn("%s: no overlay to destroy for #%d\n",
__func__, id + overlay_first_id);
continue;
}
if (ret != 0) {
defers++;
pr_warn("%s: overlay destroy failed for #%d\n",

View File

@ -296,13 +296,13 @@ extern int of_property_read_u64_array(const struct device_node *np,
u64 *out_values,
size_t sz);
extern int of_property_read_string(struct device_node *np,
extern int of_property_read_string(const struct device_node *np,
const char *propname,
const char **out_string);
extern int of_property_match_string(struct device_node *np,
extern int of_property_match_string(const struct device_node *np,
const char *propname,
const char *string);
extern int of_property_read_string_helper(struct device_node *np,
extern int of_property_read_string_helper(const struct device_node *np,
const char *propname,
const char **out_strs, size_t sz, int index);
extern int of_device_is_compatible(const struct device_node *device,
@ -538,14 +538,14 @@ static inline int of_property_read_u64_array(const struct device_node *np,
return -ENOSYS;
}
static inline int of_property_read_string(struct device_node *np,
static inline int of_property_read_string(const struct device_node *np,
const char *propname,
const char **out_string)
{
return -ENOSYS;
}
static inline int of_property_read_string_helper(struct device_node *np,
static inline int of_property_read_string_helper(const struct device_node *np,
const char *propname,
const char **out_strs, size_t sz, int index)
{
@ -571,7 +571,7 @@ static inline int of_property_read_u64(const struct device_node *np,
return -ENOSYS;
}
static inline int of_property_match_string(struct device_node *np,
static inline int of_property_match_string(const struct device_node *np,
const char *propname,
const char *string)
{
@ -773,7 +773,7 @@ static inline int of_property_count_u64_elems(const struct device_node *np,
*
* If @out_strs is NULL, the number of strings in the property is returned.
*/
static inline int of_property_read_string_array(struct device_node *np,
static inline int of_property_read_string_array(const struct device_node *np,
const char *propname, const char **out_strs,
size_t sz)
{
@ -792,7 +792,7 @@ static inline int of_property_read_string_array(struct device_node *np,
* does not have a value, and -EILSEQ if the string is not null-terminated
* within the length of the property data.
*/
static inline int of_property_count_strings(struct device_node *np,
static inline int of_property_count_strings(const struct device_node *np,
const char *propname)
{
return of_property_read_string_helper(np, propname, NULL, 0, 0);
@ -816,7 +816,7 @@ static inline int of_property_count_strings(struct device_node *np,
*
* The out_string pointer is modified only if a valid string can be decoded.
*/
static inline int of_property_read_string_index(struct device_node *np,
static inline int of_property_read_string_index(const struct device_node *np,
const char *propname,
int index, const char **output)
{

View File

@ -269,6 +269,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
# DTC
# ---------------------------------------------------------------------------
DTC ?= $(objtree)/scripts/dtc/dtc
# Generate an assembly file to wrap the output of the device tree compiler
quiet_cmd_dt_S_dtb= DTB $@
@ -291,7 +292,7 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
quiet_cmd_dtc = DTC $@
cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
$(DTC) -O dtb -o $@ -b 0 \
-i $(dir $<) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)

View File

@ -560,7 +560,7 @@ static void check_reg_format(struct check *c, struct node *dt,
size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
if ((prop->val.len % entrylen) != 0)
if (!entrylen || (prop->val.len % entrylen) != 0)
FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
node->fullpath, prop->val.len, addr_cells, size_cells);

View File

@ -73,24 +73,32 @@ static void lexical_error(const char *fmt, ...);
}
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
char *line, *tmp, *fn;
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
line = yytext;
while (!isdigit((unsigned char)*line))
line++;
/* skip digits in line # */
tmp = line;
while (!isspace((unsigned char)*tmp))
tmp++;
/* "NULL"-terminate line # */
*tmp = '\0';
/* start of filename */
fn = strchr(tmp + 1, '"') + 1;
/* strip trailing " from filename */
tmp = strchr(fn, '"');
*tmp = 0;
/* 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), atoi(line) - 1);
srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
data_free(fn);
}
<*><<EOF>> {
@ -153,7 +161,10 @@ static void lexical_error(const char *fmt, ...);
errno = 0;
yylval.integer = strtoull(yytext, &e, 0);
assert(!(*e) || !e[strspn(e, "UL")]);
if (*e && e[strspn(e, "UL")]) {
lexical_error("Bad integer literal '%s'",
yytext);
}
if (errno == ERANGE)
lexical_error("Integer literal '%s' out of range",

View File

@ -951,31 +951,39 @@ case 2:
YY_RULE_SETUP
#line 75 "dtc-lexer.l"
{
char *line, *tmp, *fn;
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
line = yytext;
while (!isdigit((unsigned char)*line))
line++;
/* skip digits in line # */
tmp = line;
while (!isspace((unsigned char)*tmp))
tmp++;
/* "NULL"-terminate line # */
*tmp = '\0';
/* start of filename */
fn = strchr(tmp + 1, '"') + 1;
/* strip trailing " from filename */
tmp = strchr(fn, '"');
*tmp = 0;
/* 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), atoi(line) - 1);
srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
data_free(fn);
}
YY_BREAK
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(BYTESTRING):
case YY_STATE_EOF(PROPNODENAME):
case YY_STATE_EOF(V1):
#line 96 "dtc-lexer.l"
#line 104 "dtc-lexer.l"
{
if (!pop_input_file()) {
yyterminate();
@ -985,7 +993,7 @@ case YY_STATE_EOF(V1):
case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
#line 102 "dtc-lexer.l"
#line 110 "dtc-lexer.l"
{
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
@ -995,7 +1003,7 @@ YY_RULE_SETUP
YY_BREAK
case 4:
YY_RULE_SETUP
#line 109 "dtc-lexer.l"
#line 117 "dtc-lexer.l"
{
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
@ -1005,7 +1013,7 @@ YY_RULE_SETUP
YY_BREAK
case 5:
YY_RULE_SETUP
#line 116 "dtc-lexer.l"
#line 124 "dtc-lexer.l"
{
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
@ -1014,7 +1022,7 @@ YY_RULE_SETUP
YY_BREAK
case 6:
YY_RULE_SETUP
#line 122 "dtc-lexer.l"
#line 130 "dtc-lexer.l"
{
DPRINT("Keyword: /bits/\n");
BEGIN_DEFAULT();
@ -1023,7 +1031,7 @@ YY_RULE_SETUP
YY_BREAK
case 7:
YY_RULE_SETUP
#line 128 "dtc-lexer.l"
#line 136 "dtc-lexer.l"
{
DPRINT("Keyword: /delete-property/\n");
DPRINT("<PROPNODENAME>\n");
@ -1033,7 +1041,7 @@ YY_RULE_SETUP
YY_BREAK
case 8:
YY_RULE_SETUP
#line 135 "dtc-lexer.l"
#line 143 "dtc-lexer.l"
{
DPRINT("Keyword: /delete-node/\n");
DPRINT("<PROPNODENAME>\n");
@ -1043,7 +1051,7 @@ YY_RULE_SETUP
YY_BREAK
case 9:
YY_RULE_SETUP
#line 142 "dtc-lexer.l"
#line 150 "dtc-lexer.l"
{
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@ -1053,7 +1061,7 @@ YY_RULE_SETUP
YY_BREAK
case 10:
YY_RULE_SETUP
#line 149 "dtc-lexer.l"
#line 157 "dtc-lexer.l"
{
char *e;
DPRINT("Integer Literal: '%s'\n", yytext);
@ -1061,7 +1069,10 @@ YY_RULE_SETUP
errno = 0;
yylval.integer = strtoull(yytext, &e, 0);
assert(!(*e) || !e[strspn(e, "UL")]);
if (*e && e[strspn(e, "UL")]) {
lexical_error("Bad integer literal '%s'",
yytext);
}
if (errno == ERANGE)
lexical_error("Integer literal '%s' out of range",
@ -1076,7 +1087,7 @@ YY_RULE_SETUP
case 11:
/* rule 11 can match eol */
YY_RULE_SETUP
#line 168 "dtc-lexer.l"
#line 179 "dtc-lexer.l"
{
struct data d;
DPRINT("Character literal: %s\n", yytext);
@ -1100,7 +1111,7 @@ YY_RULE_SETUP
YY_BREAK
case 12:
YY_RULE_SETUP
#line 189 "dtc-lexer.l"
#line 200 "dtc-lexer.l"
{ /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
@ -1109,7 +1120,7 @@ YY_RULE_SETUP
YY_BREAK
case 13:
YY_RULE_SETUP
#line 195 "dtc-lexer.l"
#line 206 "dtc-lexer.l"
{ /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
@ -1119,7 +1130,7 @@ YY_RULE_SETUP
YY_BREAK
case 14:
YY_RULE_SETUP
#line 202 "dtc-lexer.l"
#line 213 "dtc-lexer.l"
{
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
@ -1128,7 +1139,7 @@ YY_RULE_SETUP
YY_BREAK
case 15:
YY_RULE_SETUP
#line 208 "dtc-lexer.l"
#line 219 "dtc-lexer.l"
{
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
@ -1137,7 +1148,7 @@ YY_RULE_SETUP
YY_BREAK
case 16:
YY_RULE_SETUP
#line 214 "dtc-lexer.l"
#line 225 "dtc-lexer.l"
{
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@ -1148,7 +1159,7 @@ YY_RULE_SETUP
YY_BREAK
case 17:
YY_RULE_SETUP
#line 222 "dtc-lexer.l"
#line 233 "dtc-lexer.l"
{
DPRINT("Binary Include\n");
return DT_INCBIN;
@ -1157,64 +1168,64 @@ YY_RULE_SETUP
case 18:
/* rule 18 can match eol */
YY_RULE_SETUP
#line 227 "dtc-lexer.l"
#line 238 "dtc-lexer.l"
/* eat whitespace */
YY_BREAK
case 19:
/* rule 19 can match eol */
YY_RULE_SETUP
#line 228 "dtc-lexer.l"
#line 239 "dtc-lexer.l"
/* eat C-style comments */
YY_BREAK
case 20:
/* rule 20 can match eol */
YY_RULE_SETUP
#line 229 "dtc-lexer.l"
#line 240 "dtc-lexer.l"
/* eat C++-style comments */
YY_BREAK
case 21:
YY_RULE_SETUP
#line 231 "dtc-lexer.l"
#line 242 "dtc-lexer.l"
{ return DT_LSHIFT; };
YY_BREAK
case 22:
YY_RULE_SETUP
#line 232 "dtc-lexer.l"
#line 243 "dtc-lexer.l"
{ return DT_RSHIFT; };
YY_BREAK
case 23:
YY_RULE_SETUP
#line 233 "dtc-lexer.l"
#line 244 "dtc-lexer.l"
{ return DT_LE; };
YY_BREAK
case 24:
YY_RULE_SETUP
#line 234 "dtc-lexer.l"
#line 245 "dtc-lexer.l"
{ return DT_GE; };
YY_BREAK
case 25:
YY_RULE_SETUP
#line 235 "dtc-lexer.l"
#line 246 "dtc-lexer.l"
{ return DT_EQ; };
YY_BREAK
case 26:
YY_RULE_SETUP
#line 236 "dtc-lexer.l"
#line 247 "dtc-lexer.l"
{ return DT_NE; };
YY_BREAK
case 27:
YY_RULE_SETUP
#line 237 "dtc-lexer.l"
#line 248 "dtc-lexer.l"
{ return DT_AND; };
YY_BREAK
case 28:
YY_RULE_SETUP
#line 238 "dtc-lexer.l"
#line 249 "dtc-lexer.l"
{ return DT_OR; };
YY_BREAK
case 29:
YY_RULE_SETUP
#line 240 "dtc-lexer.l"
#line 251 "dtc-lexer.l"
{
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
@ -1232,10 +1243,10 @@ YY_RULE_SETUP
YY_BREAK
case 30:
YY_RULE_SETUP
#line 255 "dtc-lexer.l"
#line 266 "dtc-lexer.l"
ECHO;
YY_BREAK
#line 1239 "dtc-lexer.lex.c"
#line 1250 "dtc-lexer.lex.c"
case YY_END_OF_BUFFER:
{
@ -2195,7 +2206,7 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables"
#line 254 "dtc-lexer.l"
#line 265 "dtc-lexer.l"

View File

@ -499,9 +499,9 @@ static const yytype_uint16 yyrline[] =
298, 303, 322, 336, 343, 344, 345, 352, 356, 357,
361, 362, 366, 367, 371, 372, 376, 377, 381, 382,
386, 387, 388, 392, 393, 394, 395, 396, 400, 401,
402, 406, 407, 408, 412, 413, 414, 415, 419, 420,
421, 422, 427, 430, 434, 442, 445, 449, 457, 461,
465
402, 406, 407, 408, 412, 413, 422, 431, 435, 436,
437, 438, 443, 446, 450, 458, 461, 465, 473, 477,
481
};
#endif
@ -1909,111 +1909,125 @@ yyreduce:
break;
case 65:
#line 413 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); }
#line 1915 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 414 "dtc-parser.y" /* yacc.c:1646 */
{
if ((yyvsp[0].integer) != 0) {
(yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer);
} else {
ERROR(&(yyloc), "Division by zero");
(yyval.integer) = 0;
}
}
#line 1922 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 66:
#line 414 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); }
#line 1921 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 423 "dtc-parser.y" /* yacc.c:1646 */
{
if ((yyvsp[0].integer) != 0) {
(yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer);
} else {
ERROR(&(yyloc), "Division by zero");
(yyval.integer) = 0;
}
}
#line 1935 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 69:
#line 420 "dtc-parser.y" /* yacc.c:1646 */
#line 436 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = -(yyvsp[0].integer); }
#line 1927 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1941 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 70:
#line 421 "dtc-parser.y" /* yacc.c:1646 */
#line 437 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = ~(yyvsp[0].integer); }
#line 1933 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 71:
#line 422 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = !(yyvsp[0].integer); }
#line 1939 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 72:
#line 427 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = empty_data;
}
#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 71:
#line 438 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = !(yyvsp[0].integer); }
#line 1953 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 72:
#line 443 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = empty_data;
}
#line 1961 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 73:
#line 431 "dtc-parser.y" /* yacc.c:1646 */
#line 447 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte));
}
#line 1955 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1969 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 74:
#line 435 "dtc-parser.y" /* yacc.c:1646 */
#line 451 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
}
#line 1963 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1977 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 75:
#line 442 "dtc-parser.y" /* yacc.c:1646 */
#line 458 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.nodelist) = NULL;
}
#line 1971 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 76:
#line 446 "dtc-parser.y" /* yacc.c:1646 */
#line 462 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist));
}
#line 1979 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1993 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 77:
#line 450 "dtc-parser.y" /* yacc.c:1646 */
#line 466 "dtc-parser.y" /* yacc.c:1646 */
{
ERROR(&(yylsp[0]), "Properties must precede subnodes");
YYERROR;
}
#line 1988 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2002 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 78:
#line 458 "dtc-parser.y" /* yacc.c:1646 */
#line 474 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename));
}
#line 1996 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2010 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 79:
#line 462 "dtc-parser.y" /* yacc.c:1646 */
#line 478 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename));
}
#line 2004 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2018 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 80:
#line 466 "dtc-parser.y" /* yacc.c:1646 */
#line 482 "dtc-parser.y" /* yacc.c:1646 */
{
add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref));
(yyval.node) = (yyvsp[0].node);
}
#line 2013 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2027 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
#line 2017 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2031 "dtc-parser.tab.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@ -2248,7 +2262,7 @@ yyreturn:
#endif
return yyresult;
}
#line 472 "dtc-parser.y" /* yacc.c:1906 */
#line 488 "dtc-parser.y" /* yacc.c:1906 */
void yyerror(char const *s)

View File

@ -410,8 +410,24 @@ integer_add:
integer_mul:
integer_mul '*' integer_unary { $$ = $1 * $3; }
| integer_mul '/' integer_unary { $$ = $1 / $3; }
| 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
;

View File

@ -18,6 +18,8 @@
* USA
*/
#include <sys/stat.h>
#include "dtc.h"
#include "srcpos.h"
@ -104,11 +106,56 @@ static const char * const usage_opts_help[] = {
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;
uint32_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);
magic = fdt32_to_cpu(magic);
if (magic == FDT_MAGIC)
return "dtb";
return guess_type_by_name(fname, fallback);
}
int main(int argc, char *argv[])
{
struct boot_info *bi;
const char *inform = "dts";
const char *outform = "dts";
const char *inform = NULL;
const char *outform = NULL;
const char *outname = "-";
const char *depname = NULL;
bool force = false, sort = false;
@ -213,6 +260,17 @@ int main(int argc, char *argv[])
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"))
bi = dt_from_source(arg);
else if (streq(inform, "fs"))

349
scripts/dtc/dtx_diff Executable file
View File

@ -0,0 +1,349 @@
#! /bin/bash
# Copyright (C) 2015 Frank Rowand
#
# 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; version 2 of the License.
usage() {
# use spaces instead of tabs in the usage message
cat >&2 <<eod
Usage:
`basename $0` DTx
decompile DTx
`basename $0` DTx_1 DTx_2
diff DTx_1 and DTx_2
-f print full dts in diff (--unified=99999)
-h synonym for --help
-help synonym for --help
--help print this message and exit
-s SRCTREE linux kernel source tree is at path SRCTREE
(default is current directory)
-S linux kernel source tree is at root of current git repo
-u unsorted, do not sort DTx
Each DTx is processed by the dtc compiler to produce a sorted dts source
file. If DTx is a dts source file then it is pre-processed in the same
manner as done for the compile of the dts source file in the Linux kernel
build system ('#include' and '/include/' directives are processed).
If two DTx are provided, the resulting dts source files are diffed.
If DTx is a directory, it is treated as a DT subtree, such as
/proc/device-tree.
If DTx contains the binary blob magic value in the first four bytes,
it is treated as a binary blob (aka .dtb or FDT).
Otherwise DTx is treated as a dts source file (aka .dts).
If this script is not run from the root of the linux source tree,
and DTx utilizes '#include' or '/include/' then the path of the
linux source tree can be provided by '-s SRCTREE' or '-S' so that
include paths will be set properly.
The shell variable \${ARCH} must provide the architecture containing
the dts source file for include paths to be set properly for '#include'
or '/include/' to be processed.
If DTx_1 and DTx_2 are in different architectures, then this script
may not work since \${ARCH} is part of the include path. Two possible
workarounds:
`basename $0` \\
<(ARCH=arch_of_dtx_1 `basename $0` DTx_1) \\
<(ARCH=arch_of_dtx_2 `basename $0` DTx_2)
`basename $0` ARCH=arch_of_dtx_1 DTx_1 >tmp_dtx_1.dts
`basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts
`basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
rm tmp_dtx_1.dts tmp_dtx_2.dts
If DTx_1 and DTx_2 are in different directories, then this script will
add the path of DTx_1 and DTx_2 to the include paths. If DTx_2 includes
a local file that exists in both the path of DTx_1 and DTx_2 then the
file in the path of DTx_1 will incorrectly be included. Possible
workaround:
`basename $0` DTx_1 >tmp_dtx_1.dts
`basename $0` DTx_2 >tmp_dtx_2.dts
`basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
rm tmp_dtx_1.dts tmp_dtx_2.dts
eod
}
compile_to_dts() {
dtx="$1"
if [ -d "${dtx}" ] ; then
# ----- input is file tree
if ( ! ${DTC} -I fs ${dtx} ) ; then
exit 3
fi
elif [ -f "${dtx}" ] && [ -r "${dtx}" ] ; then
magic=`hexdump -n 4 -e '/1 "%02x"' ${dtx}`
if [ "${magic}" = "d00dfeed" ] ; then
# ----- input is FDT (binary blob)
if ( ! ${DTC} -I dtb ${dtx} ) ; then
exit 3
fi
return
fi
# ----- input is DTS (source)
if ( cpp ${cpp_flags} -x assembler-with-cpp ${dtx} \
| ${DTC} -I dts ) ; then
return
fi
echo "" >&2
echo "Possible hints to resolve the above error:" >&2
echo " (hints might not fix the problem)" >&2
hint_given=0
if [ "${ARCH}" = "" ] ; then
hint_given=1
echo "" >&2
echo " shell variable \$ARCH not set" >&2
fi
dtx_arch=`echo "/${dtx}" | sed -e 's|.*/arch/||' -e 's|/.*||'`
if [ "${dtx_arch}" != "" -a "${dtx_arch}" != "${ARCH}" ] ; then
hint_given=1
echo "" >&2
echo " architecture ${dtx_arch} is in file path," >&2
echo " but does not match shell variable \$ARCH" >&2
echo " >>\$ARCH<< is: >>${ARCH}<<" >&2
fi
if [ ! -d ${srctree}/arch/${ARCH} ] ; then
hint_given=1
echo "" >&2
echo " ${srctree}/arch/${ARCH}/ does not exist" >&2
echo " Is \$ARCH='${ARCH}' correct?" >&2
echo " Possible fix: use '-s' option" >&2
git_root=`git rev-parse --show-toplevel 2>/dev/null`
if [ -d ${git_root}/arch/ ] ; then
echo " Possible fix: use '-S' option" >&2
fi
fi
if [ $hint_given = 0 ] ; then
echo "" >&2
echo " No hints available." >&2
fi
echo "" >&2
exit 3
else
echo "" >&2
echo "ERROR: ${dtx} does not exist or is not readable" >&2
echo "" >&2
exit 2
fi
}
# ----- start of script
cmd_diff=0
diff_flags="-u"
dtx_file_1=""
dtx_file_2=""
dtc_sort="-s"
help=0
srctree=""
while [ $# -gt 0 ] ; do
case $1 in
-f )
diff_flags="--unified=999999"
shift
;;
-h | -help | --help )
help=1
shift
;;
-s )
srctree="$2"
shift 2
;;
-S )
git_root=`git rev-parse --show-toplevel 2>/dev/null`
srctree="${git_root}"
shift
;;
-u )
dtc_sort=""
shift
;;
*)
if [ "${dtx_file_1}" = "" ] ; then
dtx_file_1="$1"
elif [ "${dtx_file_2}" = "" ] ; then
dtx_file_2="$1"
else
echo "" >&2
echo "ERROR: Unexpected parameter: $1" >&2
echo "" >&2
exit 2
fi
shift
;;
esac
done
if [ "${srctree}" = "" ] ; then
srctree="."
fi
if [ "${dtx_file_2}" != "" ]; then
cmd_diff=1
fi
if (( ${help} )) ; then
usage
exit 1
fi
# this must follow check for ${help}
if [ "${dtx_file_1}" = "" ]; then
echo "" >&2
echo "ERROR: parameter DTx required" >&2
echo "" >&2
exit 2
fi
# ----- prefer dtc from linux kernel, allow fallback to dtc in $PATH
if [ "${KBUILD_OUTPUT:0:2}" = ".." ] ; then
__KBUILD_OUTPUT="${srctree}/${KBUILD_OUTPUT}"
elif [ "${KBUILD_OUTPUT}" = "" ] ; then
__KBUILD_OUTPUT="."
else
__KBUILD_OUTPUT="${KBUILD_OUTPUT}"
fi
DTC="${__KBUILD_OUTPUT}/scripts/dtc/dtc"
if [ ! -x ${DTC} ] ; then
__DTC="dtc"
if grep -q "^CONFIG_DTC=y" ${__KBUILD_OUTPUT}/.config ; then
make_command='
make scripts'
else
make_command='
Enable CONFIG_DTC in the kernel configuration
make scripts'
fi
if ( ! which ${__DTC} >/dev/null ) ; then
# use spaces instead of tabs in the error message
cat >&2 <<eod
ERROR: unable to find a 'dtc' program
Preferred 'dtc' (built from Linux kernel source tree) was not found or
is not executable.
'dtc' is: ${DTC}
If it does not exist, create it from the root of the Linux source tree:
${make_command}
If not at the root of the Linux kernel source tree -s SRCTREE or -S
may need to be specified to find 'dtc'.
If 'O=\${dir}' is specified in your Linux builds, this script requires
'export KBUILD_OUTPUT=\${dir}' or add \${dir}/scripts/dtc to \$PATH
before running.
If \${KBUILD_OUTPUT} is a relative path, then '-s SRCDIR', -S, or run
this script from the root of the Linux kernel source tree is required.
Fallback '${__DTC}' was also not in \${PATH} or is not executable.
eod
exit 2
fi
DTC=${__DTC}
fi
# ----- cpp and dtc flags same as for linux source tree build of .dtb files,
# plus directories of the dtx file(s)
dtx_path_1_dtc_include="-i `dirname ${dtx_file_1}`"
dtx_path_2_dtc_include=""
if (( ${cmd_diff} )) ; then
dtx_path_2_dtc_include="-i `dirname ${dtx_file_2}`"
fi
cpp_flags="\
-nostdinc \
-I${srctree}/arch/${ARCH}/boot/dts \
-I${srctree}/arch/${ARCH}/boot/dts/include \
-I${srctree}/drivers/of/testcase-data \
-undef -D__DTS__"
dtc_flags="\
-i ${srctree}/arch/${ARCH}/boot/dts/ \
-i ${srctree}/kernel/dts \
${dtx_path_1_dtc_include} \
${dtx_path_2_dtc_include}"
DTC="${DTC} ${dtc_flags} -O dts -qq -f ${dtc_sort} -o -"
# ----- do the diff or decompile
if (( ${cmd_diff} )) ; then
diff ${diff_flags} \
<(compile_to_dts "${dtx_file_1}") \
<(compile_to_dts "${dtx_file_2}")
else
compile_to_dts "${dtx_file_1}"
fi

View File

@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
const char *p;
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;
p = _fdt_offset_ptr(fdt, offset);
if (p + len < p)
return NULL;
return p;
return _fdt_offset_ptr(fdt, offset);
}
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)

View File

@ -538,6 +538,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
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)
{

View File

@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
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);

View File

@ -121,7 +121,12 @@
/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
* or similar property with a bad format or value */
#define FDT_ERR_MAX 14
#define FDT_ERR_BADVALUE 15
/* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
* value. For example: a property expected to contain a string list
* is not NUL-terminated within the length of its value. */
#define FDT_ERR_MAX 15
/**********************************************************************/
/* Low-level functions (you probably don't need these) */
@ -457,8 +462,8 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
* @namelen: number of characters of name to consider
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
* Identical to fdt_get_property_namelen(), but only examine the first
* namelen characters of name for matching the property name.
* Identical to fdt_get_property(), but only examine the first namelen
* characters of name for matching the property name.
*/
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int nodeoffset,
@ -868,6 +873,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
*/
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
/**
* fdt_stringlist_count - count the number of strings in a string list
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
* @return:
* the number of strings in the given property
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist
*/
int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
/**
* fdt_stringlist_search - find a string in a string list and return its index
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
* @string: string to look up in the string list
*
* Note that it is possible for this function to succeed on property values
* that are not NUL-terminated. That's because the function will stop after
* finding the first occurrence of @string. This can for example happen with
* small-valued cell properties, such as #address-cells, when searching for
* the empty string.
*
* @return:
* the index of the string in the list of strings
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist or does not contain
* the given string
*/
int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
const char *string);
/**
* fdt_stringlist_get() - obtain the string at a given index in a string list
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
* @index: index of the string to return
* @lenp: return location for the string length or an error code on failure
*
* Note that this will successfully extract strings from properties with
* non-NUL-terminated values. For example on small-valued cell properties
* this function will return the empty string.
*
* If non-NULL, the length of the string (on success) or a negative error-code
* (on failure) will be stored in the integer pointer to by lenp.
*
* @return:
* A pointer to the string at the given index in the string list or NULL on
* failure. On success the length of the string will be stored in the memory
* location pointed to by the lenp parameter, if non-NULL. On failure one of
* the following negative error codes will be returned in the lenp parameter
* (if non-NULL):
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist
*/
const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
const char *property, int index,
int *lenp);
/**********************************************************************/
/* Read-only functions (addressing related) */
/**********************************************************************/

View File

@ -152,7 +152,6 @@ char get_escape_char(const char *s, int *i)
int j = *i + 1;
char val;
assert(c);
switch (c) {
case 'a':
val = '\a';
@ -349,7 +348,6 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
void utilfdt_print_data(const char *data, int len)
{
int i;
const char *p = data;
const char *s;
/* no data, don't print */
@ -376,6 +374,7 @@ void utilfdt_print_data(const char *data, int len)
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 ? " " : "");

View File

@ -1 +1 @@
#define DTC_VERSION "DTC 1.4.1-g9d3649bd"
#define DTC_VERSION "DTC 1.4.1-gb06e55c8"