mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
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:
commit
31e182363b
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
39
Documentation/devicetree/bindings/property-units.txt
Normal file
39
Documentation/devicetree/bindings/property-units.txt
Normal 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
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
;
|
||||
|
||||
|
|
|
@ -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
349
scripts/dtc/dtx_diff
Executable 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
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) */
|
||||
/**********************************************************************/
|
||||
|
|
|
@ -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 ? " " : "");
|
||||
|
|
|
@ -1 +1 @@
|
|||
#define DTC_VERSION "DTC 1.4.1-g9d3649bd"
|
||||
#define DTC_VERSION "DTC 1.4.1-gb06e55c8"
|
||||
|
|
Loading…
Reference in a new issue