|
|
|
/*
|
|
|
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
|
|
* USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "dtc.h"
|
|
|
|
#include "srcpos.h"
|
|
|
|
|
|
|
|
extern FILE *yyin;
|
|
|
|
extern int yyparse(void);
|
|
|
|
extern YYLTYPE yylloc;
|
|
|
|
|
|
|
|
struct dt_info *parser_output;
|
|
|
|
bool treesource_error;
|
|
|
|
|
|
|
|
struct dt_info *dt_from_source(const char *fname)
|
|
|
|
{
|
|
|
|
parser_output = NULL;
|
|
|
|
treesource_error = false;
|
|
|
|
|
|
|
|
srcfile_push(fname);
|
|
|
|
yyin = current_srcfile->f;
|
|
|
|
yylloc.file = current_srcfile;
|
|
|
|
|
|
|
|
if (yyparse() != 0)
|
dtc: Simplify error handling for unparseable input
Currently, main() tests if it got a valid input tree from whichever
dt_from_*() function it invoked and if not, die()s. For one thing,
this test has, for no good reason, three different ways for those
functions to communicate a failure to provide input (bi NULL, bi->dt
NULL, or bi->error non-zero). For another, in every case save one, if
the dt_from_*() functions are unable to provide input they will
immediately die() (with a more specific error message) rather than
proceeding to the test in main().
Therefore, this patch removes this test, making the one case that
could have triggered it (in dt_from_source()) call die() directly
instead. With this change, the error field in struct boot_info is now
unused, so remove it.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
17 years ago
|
|
|
die("Unable to parse input tree\n");
|
|
|
|
|
|
|
|
if (treesource_error)
|
|
|
|
die("Syntax error parsing input tree\n");
|
|
|
|
|
|
|
|
return parser_output;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_prefix(FILE *f, int level)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < level; i++)
|
|
|
|
fputc('\t', f);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isstring(char c)
|
|
|
|
{
|
|
|
|
return (isprint((unsigned char)c)
|
|
|
|
|| (c == '\0')
|
|
|
|
|| strchr("\a\b\t\n\v\f\r", c));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_propval_string(FILE *f, const char *s, size_t len)
|
|
|
|
{
|
|
|
|
const char *end = s + len - 1;
|
|
|
|
|
|
|
|
if (!len)
|
|
|
|
return;
|
|
|
|
|
|
|
|
assert(*end == '\0');
|
|
|
|
|
|
|
|
fprintf(f, "\"");
|
|
|
|
while (s < end) {
|
|
|
|
char c = *s++;
|
|
|
|
switch (c) {
|
|
|
|
case '\a':
|
|
|
|
fprintf(f, "\\a");
|
|
|
|
break;
|
|
|
|
case '\b':
|
|
|
|
fprintf(f, "\\b");
|
|
|
|
break;
|
|
|
|
case '\t':
|
|
|
|
fprintf(f, "\\t");
|
|
|
|
break;
|
|
|
|
case '\n':
|
|
|
|
fprintf(f, "\\n");
|
|
|
|
break;
|
|
|
|
case '\v':
|
|
|
|
fprintf(f, "\\v");
|
|
|
|
break;
|
|
|
|
case '\f':
|
|
|
|
fprintf(f, "\\f");
|
|
|
|
break;
|
|
|
|
case '\r':
|
|
|
|
fprintf(f, "\\r");
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
fprintf(f, "\\\\");
|
|
|
|
break;
|
|
|
|
case '\"':
|
|
|
|
fprintf(f, "\\\"");
|
|
|
|
break;
|
|
|
|
case '\0':
|
|
|
|
fprintf(f, "\\0");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (isprint((unsigned char)c))
|
|
|
|
fprintf(f, "%c", c);
|
|
|
|
else
|
|
|
|
fprintf(f, "\\x%02"PRIx8, c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf(f, "\"");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
|
|
|
|
{
|
|
|
|
const char *end = p + len;
|
|
|
|
assert(len % width == 0);
|
|
|
|
|
|
|
|
for (; p < end; p += width) {
|
|
|
|
switch (width) {
|
|
|
|
case 1:
|
|
|
|
fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (p + width < end)
|
|
|
|
fputc(' ', f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Kill bogus TYPE_BLOB marker type
Since commit 32b9c6130762 "Preserve datatype markers when emitting dts
format", we no longer try to guess the value type. Instead, we reuse
the type of the datatype markers when they are present, if the type
is either TYPE_UINT* or TYPE_STRING.
This causes 'dtc -I fs' to crash:
Starting program: /root/dtc -q -f -O dts -I fs /proc/device-tree
/dts-v1/;
/ {
Program received signal SIGSEGV, Segmentation fault.
__strlen_power8 () at ../sysdeps/powerpc/powerpc64/power8/strlen.S:47
47 ld r12,0(r4) /* Load doubleword from memory. */
(gdb) bt
#0 __strlen_power8 () at ../sysdeps/powerpc/powerpc64/power8/strlen.S:47
#1 0x00007ffff7de3d10 in __GI__IO_fputs (str=<optimized out>,
fp=<optimized out>) at iofputs.c:33
#2 0x000000001000c7a0 in write_propval (prop=0x100525e0,
f=0x7ffff7f718a0 <_IO_2_1_stdout_>) at treesource.c:245
The offending line is:
fprintf(f, "%s", delim_start[emit_type]);
where emit_type is TYPE_BLOB and:
static const char *delim_start[] = {
[TYPE_UINT8] = "[",
[TYPE_UINT16] = "/bits/ 16 <",
[TYPE_UINT32] = "<",
[TYPE_UINT64] = "/bits/ 64 <",
[TYPE_STRING] = "",
};
/* Data blobs */
enum markertype {
TYPE_NONE,
REF_PHANDLE,
REF_PATH,
LABEL,
TYPE_UINT8,
TYPE_UINT16,
TYPE_UINT32,
TYPE_UINT64,
TYPE_BLOB,
TYPE_STRING,
};
Because TYPE_BLOB < TYPE_STRING and delim_start[] is a static array,
delim_start[emit_type] is 0x0. The glibc usually prints out "(null)"
when one passes 0x0 to %s, but it seems to call fputs() internally if
the format is exactly "%s", hence the crash.
TYPE_BLOB basically means the data comes from a file and we don't know
its type. We don't care for the former, and the latter is TYPE_NONE.
So let's drop TYPE_BLOB completely and use TYPE_NONE instead when reading
the file. Then, try to guess the data type at emission time, like the
code already does for refs and labels.
Instead of adding yet another check for TYPE_NONE, an helper is introduced
to check if the data marker has type information, ie, >= TYPE_UINT8.
Fixes: 32b9c61307629ac76c6ac0bead6f926d579b3d2c
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Greg Kurz <groug@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
static bool has_data_type_information(struct marker *m)
|
|
|
|
{
|
|
|
|
return m->type >= TYPE_UINT8;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct marker *next_type_marker(struct marker *m)
|
|
|
|
{
|
Kill bogus TYPE_BLOB marker type
Since commit 32b9c6130762 "Preserve datatype markers when emitting dts
format", we no longer try to guess the value type. Instead, we reuse
the type of the datatype markers when they are present, if the type
is either TYPE_UINT* or TYPE_STRING.
This causes 'dtc -I fs' to crash:
Starting program: /root/dtc -q -f -O dts -I fs /proc/device-tree
/dts-v1/;
/ {
Program received signal SIGSEGV, Segmentation fault.
__strlen_power8 () at ../sysdeps/powerpc/powerpc64/power8/strlen.S:47
47 ld r12,0(r4) /* Load doubleword from memory. */
(gdb) bt
#0 __strlen_power8 () at ../sysdeps/powerpc/powerpc64/power8/strlen.S:47
#1 0x00007ffff7de3d10 in __GI__IO_fputs (str=<optimized out>,
fp=<optimized out>) at iofputs.c:33
#2 0x000000001000c7a0 in write_propval (prop=0x100525e0,
f=0x7ffff7f718a0 <_IO_2_1_stdout_>) at treesource.c:245
The offending line is:
fprintf(f, "%s", delim_start[emit_type]);
where emit_type is TYPE_BLOB and:
static const char *delim_start[] = {
[TYPE_UINT8] = "[",
[TYPE_UINT16] = "/bits/ 16 <",
[TYPE_UINT32] = "<",
[TYPE_UINT64] = "/bits/ 64 <",
[TYPE_STRING] = "",
};
/* Data blobs */
enum markertype {
TYPE_NONE,
REF_PHANDLE,
REF_PATH,
LABEL,
TYPE_UINT8,
TYPE_UINT16,
TYPE_UINT32,
TYPE_UINT64,
TYPE_BLOB,
TYPE_STRING,
};
Because TYPE_BLOB < TYPE_STRING and delim_start[] is a static array,
delim_start[emit_type] is 0x0. The glibc usually prints out "(null)"
when one passes 0x0 to %s, but it seems to call fputs() internally if
the format is exactly "%s", hence the crash.
TYPE_BLOB basically means the data comes from a file and we don't know
its type. We don't care for the former, and the latter is TYPE_NONE.
So let's drop TYPE_BLOB completely and use TYPE_NONE instead when reading
the file. Then, try to guess the data type at emission time, like the
code already does for refs and labels.
Instead of adding yet another check for TYPE_NONE, an helper is introduced
to check if the data marker has type information, ie, >= TYPE_UINT8.
Fixes: 32b9c61307629ac76c6ac0bead6f926d579b3d2c
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Greg Kurz <groug@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
while (m && !has_data_type_information(m))
|
|
|
|
m = m->next;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t type_marker_length(struct marker *m)
|
|
|
|
{
|
|
|
|
struct marker *next = next_type_marker(m->next);
|
|
|
|
|
|
|
|
if (next)
|
|
|
|
return next->offset - m->offset;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *delim_start[] = {
|
|
|
|
[TYPE_UINT8] = "[",
|
|
|
|
[TYPE_UINT16] = "/bits/ 16 <",
|
|
|
|
[TYPE_UINT32] = "<",
|
|
|
|
[TYPE_UINT64] = "/bits/ 64 <",
|
|
|
|
[TYPE_STRING] = "",
|
|
|
|
};
|
|
|
|
static const char *delim_end[] = {
|
|
|
|
[TYPE_UINT8] = "]",
|
|
|
|
[TYPE_UINT16] = ">",
|
|
|
|
[TYPE_UINT32] = ">",
|
|
|
|
[TYPE_UINT64] = ">",
|
|
|
|
[TYPE_STRING] = "",
|
|
|
|
};
|
|
|
|
|
|
|
|
static enum markertype guess_value_type(struct property *prop)
|
|
|
|
{
|
|
|
|
int len = prop->val.len;
|
|
|
|
const char *p = prop->val.val;
|
|
|
|
struct marker *m = prop->val.markers;
|
|
|
|
int nnotstring = 0, nnul = 0;
|
|
|
|
int nnotstringlbl = 0, nnotcelllbl = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if (! isstring(p[i]))
|
|
|
|
nnotstring++;
|
|
|
|
if (p[i] == '\0')
|
|
|
|
nnul++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for_each_marker_of_type(m, LABEL) {
|
|
|
|
if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
|
|
|
|
nnotstringlbl++;
|
|
|
|
if ((m->offset % sizeof(cell_t)) != 0)
|
|
|
|
nnotcelllbl++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
|
|
|
|
&& (nnotstringlbl == 0)) {
|
|
|
|
return TYPE_STRING;
|
|
|
|
} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
|
|
|
|
return TYPE_UINT32;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TYPE_UINT8;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_propval(FILE *f, struct property *prop)
|
|
|
|
{
|
|
|
|
size_t len = prop->val.len;
|
|
|
|
struct marker *m = prop->val.markers;
|
|
|
|
struct marker dummy_marker;
|
|
|
|
enum markertype emit_type = TYPE_NONE;
|
|
|
|
|
|
|
|
if (len == 0) {
|
|
|
|
fprintf(f, ";\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Fix missing labels when emitting dts format
When there is a label inside a sequence of ints at the end of a
property, an assertion is hit because write_propval() expects all the
labels to be at the very end of the property data. This is clearly wrong
behaviour.
To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property
/randomnode/blob.
Fix by reworking the write_propval() loop to remove the separate
iterating over label markers. Instead handle the label markers as part
of the main marker iteration loop. This guarantees that each label
marker is handled at the right location, even if all the data markers
have already been handled, and has the added advantage of making the
code simpler.
However, a side effect of this code is that a label at the very end of
an int sequence will be emitted outside the sequence delimiters. For
example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:;
The two representations are equivalent in the data model, but the
current test case was looking for the former, but needed to be modified
to look for the later. The alternative would be to render labels before
closing the sequence, but that makes less sense syntactically because
labels between sequences are normally to point at the next one, not the
former. For example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 L1: L2: >, < 3 4 L3: L4: >;
DTC doesn't current have the information to know if the label should be
inside or outside the sequence, but in common usage, it is more likely
that L1 & L2 refer to the second sequence, not the end of the first.
Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts
format")
Reported-by: Łukasz Dobrowolski <lukasz.dobrowolski@nokia.com>
Signed-off-by: Grant Likely <grant.likely@arm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
fprintf(f, " =");
|
|
|
|
|
|
|
|
if (!next_type_marker(m)) {
|
|
|
|
/* data type information missing, need to guess */
|
|
|
|
dummy_marker.type = guess_value_type(prop);
|
|
|
|
dummy_marker.next = prop->val.markers;
|
|
|
|
dummy_marker.offset = 0;
|
|
|
|
dummy_marker.ref = NULL;
|
|
|
|
m = &dummy_marker;
|
|
|
|
}
|
|
|
|
|
|
|
|
for_each_marker(m) {
|
Fix missing labels when emitting dts format
When there is a label inside a sequence of ints at the end of a
property, an assertion is hit because write_propval() expects all the
labels to be at the very end of the property data. This is clearly wrong
behaviour.
To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property
/randomnode/blob.
Fix by reworking the write_propval() loop to remove the separate
iterating over label markers. Instead handle the label markers as part
of the main marker iteration loop. This guarantees that each label
marker is handled at the right location, even if all the data markers
have already been handled, and has the added advantage of making the
code simpler.
However, a side effect of this code is that a label at the very end of
an int sequence will be emitted outside the sequence delimiters. For
example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:;
The two representations are equivalent in the data model, but the
current test case was looking for the former, but needed to be modified
to look for the later. The alternative would be to render labels before
closing the sequence, but that makes less sense syntactically because
labels between sequences are normally to point at the next one, not the
former. For example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 L1: L2: >, < 3 4 L3: L4: >;
DTC doesn't current have the information to know if the label should be
inside or outside the sequence, but in common usage, it is more likely
that L1 & L2 refer to the second sequence, not the end of the first.
Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts
format")
Reported-by: Łukasz Dobrowolski <lukasz.dobrowolski@nokia.com>
Signed-off-by: Grant Likely <grant.likely@arm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
|
|
|
|
size_t data_len = type_marker_length(m) ? : len - m->offset;
|
|
|
|
const char *p = &prop->val.val[m->offset];
|
|
|
|
|
Fix missing labels when emitting dts format
When there is a label inside a sequence of ints at the end of a
property, an assertion is hit because write_propval() expects all the
labels to be at the very end of the property data. This is clearly wrong
behaviour.
To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property
/randomnode/blob.
Fix by reworking the write_propval() loop to remove the separate
iterating over label markers. Instead handle the label markers as part
of the main marker iteration loop. This guarantees that each label
marker is handled at the right location, even if all the data markers
have already been handled, and has the added advantage of making the
code simpler.
However, a side effect of this code is that a label at the very end of
an int sequence will be emitted outside the sequence delimiters. For
example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:;
The two representations are equivalent in the data model, but the
current test case was looking for the former, but needed to be modified
to look for the later. The alternative would be to render labels before
closing the sequence, but that makes less sense syntactically because
labels between sequences are normally to point at the next one, not the
former. For example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 L1: L2: >, < 3 4 L3: L4: >;
DTC doesn't current have the information to know if the label should be
inside or outside the sequence, but in common usage, it is more likely
that L1 & L2 refer to the second sequence, not the end of the first.
Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts
format")
Reported-by: Łukasz Dobrowolski <lukasz.dobrowolski@nokia.com>
Signed-off-by: Grant Likely <grant.likely@arm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
if (has_data_type_information(m)) {
|
|
|
|
emit_type = m->type;
|
|
|
|
fprintf(f, " %s", delim_start[emit_type]);
|
|
|
|
} else if (m->type == LABEL)
|
Fix missing labels when emitting dts format
When there is a label inside a sequence of ints at the end of a
property, an assertion is hit because write_propval() expects all the
labels to be at the very end of the property data. This is clearly wrong
behaviour.
To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property
/randomnode/blob.
Fix by reworking the write_propval() loop to remove the separate
iterating over label markers. Instead handle the label markers as part
of the main marker iteration loop. This guarantees that each label
marker is handled at the right location, even if all the data markers
have already been handled, and has the added advantage of making the
code simpler.
However, a side effect of this code is that a label at the very end of
an int sequence will be emitted outside the sequence delimiters. For
example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:;
The two representations are equivalent in the data model, but the
current test case was looking for the former, but needed to be modified
to look for the later. The alternative would be to render labels before
closing the sequence, but that makes less sense syntactically because
labels between sequences are normally to point at the next one, not the
former. For example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 L1: L2: >, < 3 4 L3: L4: >;
DTC doesn't current have the information to know if the label should be
inside or outside the sequence, but in common usage, it is more likely
that L1 & L2 refer to the second sequence, not the end of the first.
Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts
format")
Reported-by: Łukasz Dobrowolski <lukasz.dobrowolski@nokia.com>
Signed-off-by: Grant Likely <grant.likely@arm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
fprintf(f, " %s:", m->ref);
|
|
|
|
else if (m->offset)
|
|
|
|
fputc(' ', f);
|
|
|
|
|
Fix missing labels when emitting dts format
When there is a label inside a sequence of ints at the end of a
property, an assertion is hit because write_propval() expects all the
labels to be at the very end of the property data. This is clearly wrong
behaviour.
To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property
/randomnode/blob.
Fix by reworking the write_propval() loop to remove the separate
iterating over label markers. Instead handle the label markers as part
of the main marker iteration loop. This guarantees that each label
marker is handled at the right location, even if all the data markers
have already been handled, and has the added advantage of making the
code simpler.
However, a side effect of this code is that a label at the very end of
an int sequence will be emitted outside the sequence delimiters. For
example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:;
The two representations are equivalent in the data model, but the
current test case was looking for the former, but needed to be modified
to look for the later. The alternative would be to render labels before
closing the sequence, but that makes less sense syntactically because
labels between sequences are normally to point at the next one, not the
former. For example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 L1: L2: >, < 3 4 L3: L4: >;
DTC doesn't current have the information to know if the label should be
inside or outside the sequence, but in common usage, it is more likely
that L1 & L2 refer to the second sequence, not the end of the first.
Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts
format")
Reported-by: Łukasz Dobrowolski <lukasz.dobrowolski@nokia.com>
Signed-off-by: Grant Likely <grant.likely@arm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
if (emit_type == TYPE_NONE) {
|
|
|
|
assert(chunk_len == 0);
|
|
|
|
continue;
|
Fix missing labels when emitting dts format
When there is a label inside a sequence of ints at the end of a
property, an assertion is hit because write_propval() expects all the
labels to be at the very end of the property data. This is clearly wrong
behaviour.
To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property
/randomnode/blob.
Fix by reworking the write_propval() loop to remove the separate
iterating over label markers. Instead handle the label markers as part
of the main marker iteration loop. This guarantees that each label
marker is handled at the right location, even if all the data markers
have already been handled, and has the added advantage of making the
code simpler.
However, a side effect of this code is that a label at the very end of
an int sequence will be emitted outside the sequence delimiters. For
example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:;
The two representations are equivalent in the data model, but the
current test case was looking for the former, but needed to be modified
to look for the later. The alternative would be to render labels before
closing the sequence, but that makes less sense syntactically because
labels between sequences are normally to point at the next one, not the
former. For example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 L1: L2: >, < 3 4 L3: L4: >;
DTC doesn't current have the information to know if the label should be
inside or outside the sequence, but in common usage, it is more likely
that L1 & L2 refer to the second sequence, not the end of the first.
Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts
format")
Reported-by: Łukasz Dobrowolski <lukasz.dobrowolski@nokia.com>
Signed-off-by: Grant Likely <grant.likely@arm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
}
|
|
|
|
|
|
|
|
switch(emit_type) {
|
|
|
|
case TYPE_UINT16:
|
|
|
|
write_propval_int(f, p, chunk_len, 2);
|
|
|
|
break;
|
|
|
|
case TYPE_UINT32:
|
|
|
|
write_propval_int(f, p, chunk_len, 4);
|
|
|
|
break;
|
|
|
|
case TYPE_UINT64:
|
|
|
|
write_propval_int(f, p, chunk_len, 8);
|
|
|
|
break;
|
|
|
|
case TYPE_STRING:
|
|
|
|
write_propval_string(f, p, chunk_len);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
write_propval_int(f, p, chunk_len, 1);
|
|
|
|
}
|
|
|
|
|
Fix missing labels when emitting dts format
When there is a label inside a sequence of ints at the end of a
property, an assertion is hit because write_propval() expects all the
labels to be at the very end of the property data. This is clearly wrong
behaviour.
To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property
/randomnode/blob.
Fix by reworking the write_propval() loop to remove the separate
iterating over label markers. Instead handle the label markers as part
of the main marker iteration loop. This guarantees that each label
marker is handled at the right location, even if all the data markers
have already been handled, and has the added advantage of making the
code simpler.
However, a side effect of this code is that a label at the very end of
an int sequence will be emitted outside the sequence delimiters. For
example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:;
The two representations are equivalent in the data model, but the
current test case was looking for the former, but needed to be modified
to look for the later. The alternative would be to render labels before
closing the sequence, but that makes less sense syntactically because
labels between sequences are normally to point at the next one, not the
former. For example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 L1: L2: >, < 3 4 L3: L4: >;
DTC doesn't current have the information to know if the label should be
inside or outside the sequence, but in common usage, it is more likely
that L1 & L2 refer to the second sequence, not the end of the first.
Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts
format")
Reported-by: Łukasz Dobrowolski <lukasz.dobrowolski@nokia.com>
Signed-off-by: Grant Likely <grant.likely@arm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
if (chunk_len == data_len) {
|
|
|
|
size_t pos = m->offset + chunk_len;
|
|
|
|
fprintf(f, pos == len ? "%s" : "%s,",
|
|
|
|
delim_end[emit_type] ? : "");
|
|
|
|
emit_type = TYPE_NONE;
|
|
|
|
}
|
|
|
|
}
|
Fix missing labels when emitting dts format
When there is a label inside a sequence of ints at the end of a
property, an assertion is hit because write_propval() expects all the
labels to be at the very end of the property data. This is clearly wrong
behaviour.
To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property
/randomnode/blob.
Fix by reworking the write_propval() loop to remove the separate
iterating over label markers. Instead handle the label markers as part
of the main marker iteration loop. This guarantees that each label
marker is handled at the right location, even if all the data markers
have already been handled, and has the added advantage of making the
code simpler.
However, a side effect of this code is that a label at the very end of
an int sequence will be emitted outside the sequence delimiters. For
example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:;
The two representations are equivalent in the data model, but the
current test case was looking for the former, but needed to be modified
to look for the later. The alternative would be to render labels before
closing the sequence, but that makes less sense syntactically because
labels between sequences are normally to point at the next one, not the
former. For example:
Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
Output: intprop = < 1 2 L1: L2: >, < 3 4 L3: L4: >;
DTC doesn't current have the information to know if the label should be
inside or outside the sequence, but in common usage, it is more likely
that L1 & L2 refer to the second sequence, not the end of the first.
Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts
format")
Reported-by: Łukasz Dobrowolski <lukasz.dobrowolski@nokia.com>
Signed-off-by: Grant Likely <grant.likely@arm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
6 years ago
|
|
|
fprintf(f, ";\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_tree_source_node(FILE *f, struct node *tree, int level)
|
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
struct node *child;
|
|
|
|
struct label *l;
|
|
|
|
|
|
|
|
write_prefix(f, level);
|
|
|
|
for_each_label(tree->labels, l)
|
|
|
|
fprintf(f, "%s: ", l->label);
|
|
|
|
if (tree->name && (*tree->name))
|
|
|
|
fprintf(f, "%s {\n", tree->name);
|
|
|
|
else
|
|
|
|
fprintf(f, "/ {\n");
|
|
|
|
|
|
|
|
for_each_property(tree, prop) {
|
|
|
|
write_prefix(f, level+1);
|
|
|
|
for_each_label(prop->labels, l)
|
|
|
|
fprintf(f, "%s: ", l->label);
|
|
|
|
fprintf(f, "%s", prop->name);
|
|
|
|
write_propval(f, prop);
|
|
|
|
}
|
|
|
|
for_each_child(tree, child) {
|
|
|
|
fprintf(f, "\n");
|
|
|
|
write_tree_source_node(f, child, level+1);
|
|
|
|
}
|
|
|
|
write_prefix(f, level);
|
|
|
|
fprintf(f, "};\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void dt_to_source(FILE *f, struct dt_info *dti)
|
|
|
|
{
|
|
|
|
struct reserve_info *re;
|
|
|
|
|
|
|
|
fprintf(f, "/dts-v1/;\n\n");
|
|
|
|
|
|
|
|
for (re = dti->reservelist; re; re = re->next) {
|
|
|
|
struct label *l;
|
|
|
|
|
|
|
|
for_each_label(re->labels, l)
|
|
|
|
fprintf(f, "%s: ", l->label);
|
|
|
|
fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
|
|
|
|
(unsigned long long)re->address,
|
|
|
|
(unsigned long long)re->size);
|
|
|
|
}
|
|
|
|
|
|
|
|
write_tree_source_node(f, dti->dt, 0);
|
|
|
|
}
|