@@ -1382,10 +1382,10 @@ struct provider {
};
static void check_property_phandle_args(struct check *c,
- struct dt_info *dti,
- struct node *node,
- struct property *prop,
- const struct provider *provider)
+ struct dt_info *dti,
+ struct node *node,
+ struct property *prop,
+ const struct provider *provider)
{
struct node *root = dti->dt;
unsigned int cell, cellsize = 0;
@@ -1401,6 +1401,7 @@ static void check_property_phandle_args(struct check *c,
struct node *provider_node;
struct property *cellprop;
cell_t phandle;
+ unsigned int expected;
phandle = propval_cell_n(prop, cell);
/*
@@ -1450,10 +1451,12 @@ static void check_property_phandle_args(struct check *c,
break;
}
- if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
+ expected = (cell + cellsize + 1) * sizeof(cell_t);
+ if ((expected <= cell) || prop->val.len < expected) {
FAIL_PROP(c, dti, node, prop,
- "property size (%d) too small for cell size %d",
+ "property size (%d) too small for cell size %u",
prop->val.len, cellsize);
+ break;
}
}
}
@@ -200,7 +200,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_LABEL_REF;
}
-<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
+<*>"&{"{PATHCHAR}*\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = xstrdup(yytext+2);
@@ -23,6 +23,12 @@ extern void yyerror(char const *s);
extern struct dt_info *parser_output;
extern bool treesource_error;
+
+static bool is_ref_relative(const char *ref)
+{
+ return ref[0] != '/' && strchr(&ref[1], '/');
+}
+
%}
%union {
@@ -169,6 +175,8 @@ devicetree:
*/
if (!($<flags>-1 & DTSF_PLUGIN))
ERROR(&@2, "Label or path %s not found", $1);
+ else if (is_ref_relative($1))
+ ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
$$ = add_orphan_node(
name_node(build_node(NULL, NULL, NULL),
""),
@@ -178,6 +186,9 @@ devicetree:
{
struct node *target = get_node_by_ref($1, $3);
+ if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
+ ERROR(&@2, "Label-relative reference %s not supported in plugin", $3);
+
if (target) {
add_label(&target->labels, $2);
merge_nodes(target, $4);
@@ -193,6 +204,8 @@ devicetree:
* so $-1 is what we want (plugindecl)
*/
if ($<flags>-1 & DTSF_PLUGIN) {
+ if (is_ref_relative($2))
+ ERROR(&@2, "Label-relative reference %s not supported in plugin", $2);
add_orphan_node($1, $3, $2);
} else {
struct node *target = get_node_by_ref($1, $2);
@@ -106,7 +106,6 @@ int fdt_check_header(const void *fdt)
}
hdrsize = fdt_header_size(fdt);
if (!can_assume(VALID_DTB)) {
-
if ((fdt_totalsize(fdt) < hdrsize)
|| (fdt_totalsize(fdt) > INT_MAX))
return -FDT_ERR_TRUNCATED;
@@ -115,9 +114,7 @@ int fdt_check_header(const void *fdt)
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_mem_rsvmap(fdt)))
return -FDT_ERR_TRUNCATED;
- }
- if (!can_assume(VALID_DTB)) {
/* Bounds check structure block */
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
if (!check_off_(hdrsize, fdt_totalsize(fdt),
@@ -165,7 +162,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const fdt32_t *tagp, *lenp;
- uint32_t tag;
+ uint32_t tag, len, sum;
int offset = startoffset;
const char *p;
@@ -191,12 +188,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
if (!can_assume(VALID_DTB) && !lenp)
return FDT_END; /* premature end */
+
+ len = fdt32_to_cpu(*lenp);
+ sum = len + offset;
+ if (!can_assume(VALID_DTB) &&
+ (INT_MAX <= sum || sum < (uint32_t) offset))
+ return FDT_END; /* premature end */
+
/* skip-name offset, length and value */
- offset += sizeof(struct fdt_property) - FDT_TAGSIZE
- + fdt32_to_cpu(*lenp);
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
+
if (!can_assume(LATEST) &&
- fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
- ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
+ fdt_version(fdt) < 0x10 && len >= 8 &&
+ ((offset - len) % 8) != 0)
offset += 4;
break;
@@ -35,14 +35,14 @@ struct fdt_reserve_entry {
struct fdt_node_header {
fdt32_t tag;
- char name[];
+ char name[0];
};
struct fdt_property {
fdt32_t tag;
fdt32_t len;
fdt32_t nameoff;
- char data[];
+ char data[0];
};
#endif /* !__ASSEMBLY */
@@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
/* check validity of address */
prop = data;
if (addr_cells == 1) {
- if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
+ if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
return -FDT_ERR_BADVALUE;
fdt32_st(prop, (uint32_t)addr);
@@ -40,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
return fdt32_to_cpu(*val);
}
-/**
- * overlay_get_target - retrieves the offset of a fragment's target
- * @fdt: Base device tree blob
- * @fdto: Device tree overlay blob
- * @fragment: node offset of the fragment in the overlay
- * @pathp: pointer which receives the path of the target (or NULL)
- *
- * overlay_get_target() retrieves the target offset in the base
- * device tree of a fragment, no matter how the actual targeting is
- * done (through a phandle or a path)
- *
- * returns:
- * the targeted node offset in the base device tree
- * Negative error code on error
- */
-static int overlay_get_target(const void *fdt, const void *fdto,
- int fragment, char const **pathp)
+int fdt_overlay_target_offset(const void *fdt, const void *fdto,
+ int fragment_offset, char const **pathp)
{
uint32_t phandle;
const char *path = NULL;
int path_len = 0, ret;
/* Try first to do a phandle based lookup */
- phandle = overlay_get_target_phandle(fdto, fragment);
+ phandle = overlay_get_target_phandle(fdto, fragment_offset);
if (phandle == (uint32_t)-1)
return -FDT_ERR_BADPHANDLE;
/* no phandle, try path */
if (!phandle) {
/* And then a path based lookup */
- path = fdt_getprop(fdto, fragment, "target-path", &path_len);
+ path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
if (path)
ret = fdt_path_offset(fdt, path);
else
@@ -636,7 +621,7 @@ static int overlay_merge(void *fdt, void *fdto)
if (overlay < 0)
return overlay;
- target = overlay_get_target(fdt, fdto, fragment, NULL);
+ target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
if (target < 0)
return target;
@@ -779,7 +764,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
return -FDT_ERR_BADOVERLAY;
/* get the target of the fragment */
- ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+ ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@@ -801,7 +786,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
if (!target_path) {
/* again in case setprop_placeholder changed it */
- ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+ ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@@ -481,12 +481,12 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
if (!can_assume(VALID_INPUT)) {
name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
&namelen);
+ *namep = name;
if (!name) {
if (lenp)
*lenp = namelen;
return NULL;
}
- *namep = name;
} else {
*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
}
@@ -660,6 +660,13 @@ int fdt_next_property_offset(const void *fdt, int offset);
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset,
int *lenp);
+static inline struct fdt_property *fdt_get_property_by_offset_w(void *fdt,
+ int offset,
+ int *lenp)
+{
+ return (struct fdt_property *)(uintptr_t)
+ fdt_get_property_by_offset(fdt, offset, lenp);
+}
/**
* fdt_get_property_namelen - find a property based on substring
@@ -2116,6 +2123,24 @@ int fdt_del_node(void *fdt, int nodeoffset);
*/
int fdt_overlay_apply(void *fdt, void *fdto);
+/**
+ * fdt_overlay_target_offset - retrieves the offset of a fragment's target
+ * @fdt: Base device tree blob
+ * @fdto: Device tree overlay blob
+ * @fragment_offset: node offset of the fragment in the overlay
+ * @pathp: pointer which receives the path of the target (or NULL)
+ *
+ * fdt_overlay_target_offset() retrieves the target offset in the base
+ * device tree of a fragment, no matter how the actual targeting is
+ * done (through a phandle or a path)
+ *
+ * returns:
+ * the targeted node offset in the base device tree
+ * Negative error code on error
+ */
+int fdt_overlay_target_offset(const void *fdt, const void *fdto,
+ int fragment_offset, char const **pathp);
+
/**********************************************************************/
/* Debugging / informational functions */
/**********************************************************************/
@@ -581,12 +581,39 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
struct node *get_node_by_ref(struct node *tree, const char *ref)
{
+ struct node *target = tree;
+ const char *label = NULL, *path = NULL;
+
if (streq(ref, "/"))
return tree;
- else if (ref[0] == '/')
- return get_node_by_path(tree, ref);
+
+ if (ref[0] == '/')
+ path = ref;
else
- return get_node_by_label(tree, ref);
+ label = ref;
+
+ if (label) {
+ const char *slash = strchr(label, '/');
+ char *buf = NULL;
+
+ if (slash) {
+ buf = xstrndup(label, slash - label);
+ label = buf;
+ path = slash + 1;
+ }
+
+ target = get_node_by_label(tree, label);
+
+ free(buf);
+
+ if (!target)
+ return NULL;
+ }
+
+ if (path)
+ target = get_node_by_path(target, path);
+
+ return target;
}
cell_t get_node_phandle(struct node *root, struct node *node)
@@ -892,6 +919,12 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
/* m->ref can only be a REF_PHANDLE, but check anyway */
assert(m->type == REF_PHANDLE);
+ /* The format only permits fixups for references to label, not
+ * references to path */
+ if (strchr(m->ref, '/'))
+ die("Can't generate fixup for reference to path &{%s}\n",
+ m->ref);
+
/* there shouldn't be any ':' in the arguments */
if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
die("arguments should not contain ':'\n");
@@ -33,6 +33,17 @@ char *xstrdup(const char *s)
return d;
}
+char *xstrndup(const char *s, size_t n)
+{
+ size_t len = strnlen(s, n) + 1;
+ char *d = xmalloc(len);
+
+ memcpy(d, s, len - 1);
+ d[len - 1] = '\0';
+
+ return d;
+}
+
int xavsprintf_append(char **strp, const char *fmt, va_list ap)
{
int n, size = 0; /* start with 128 bytes */
@@ -353,11 +364,11 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
}
/* we should now have a type */
- if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+ if ((*fmt == '\0') || !strchr("iuxsr", *fmt))
return -1;
/* convert qualifier (bhL) to byte size */
- if (*fmt != 's')
+ if (*fmt != 's' && *fmt != 'r')
*size = qualifier == 'b' ? 1 :
qualifier == 'h' ? 2 :
qualifier == 'l' ? 4 : -1;
@@ -61,6 +61,7 @@ static inline void *xrealloc(void *p, size_t len)
}
extern char *xstrdup(const char *s);
+extern char *xstrndup(const char *s, size_t len);
extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
@@ -143,6 +144,7 @@ int utilfdt_write_err(const char *filename, const void *blob);
* i signed integer
* u unsigned integer
* x hex
+ * r raw
*
* TODO: Implement ll modifier (8 bytes)
* TODO: Implement o type (octal)
@@ -160,7 +162,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
*/
#define USAGE_TYPE_MSG \
- "<type>\ts=string, i=int, u=unsigned, x=hex\n" \
+ "<type>\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \
"\tOptional modifier prefix:\n" \
"\t\thh or b=byte, h=2 byte, l=4 byte (default)";
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.6.1-g0a3a9d34"
+#define DTC_VERSION "DTC 1.6.1-g55778a03"