mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-09 03:21:51 +00:00
libfdt: Add fdt_find_regions()
Add a function to find regions in device tree given a list of nodes to include and properties to exclude. See the header file for full documentation. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
399c744b22
commit
3e06cd1f97
2 changed files with 193 additions and 0 deletions
|
@ -1511,4 +1511,68 @@ int fdt_del_node(void *fdt, int nodeoffset);
|
||||||
|
|
||||||
const char *fdt_strerror(int errval);
|
const char *fdt_strerror(int errval);
|
||||||
|
|
||||||
|
struct fdt_region {
|
||||||
|
int offset;
|
||||||
|
int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fdt_find_regions() - find regions in device tree
|
||||||
|
*
|
||||||
|
* Given a list of nodes to include and properties to exclude, find
|
||||||
|
* the regions of the device tree which describe those included parts.
|
||||||
|
*
|
||||||
|
* The intent is to get a list of regions which will be invariant provided
|
||||||
|
* those parts are invariant. For example, if you request a list of regions
|
||||||
|
* for all nodes but exclude the property "data", then you will get the
|
||||||
|
* same region contents regardless of any change to "data" properties.
|
||||||
|
*
|
||||||
|
* This function can be used to produce a byte-stream to send to a hashing
|
||||||
|
* function to verify that critical parts of the FDT have not changed.
|
||||||
|
*
|
||||||
|
* Nodes which are given in 'inc' are included in the region list, as
|
||||||
|
* are the names of the immediate subnodes nodes (but not the properties
|
||||||
|
* or subnodes of those subnodes).
|
||||||
|
*
|
||||||
|
* For eaxample "/" means to include the root node, all root properties
|
||||||
|
* and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
|
||||||
|
* ensures that we capture the names of the subnodes. In a hashing situation
|
||||||
|
* it prevents the root node from changing at all Any change to non-excluded
|
||||||
|
* properties, names of subnodes or number of subnodes would be detected.
|
||||||
|
*
|
||||||
|
* When used with FITs this provides the ability to hash and sign parts of
|
||||||
|
* the FIT based on different configurations in the FIT. Then it is
|
||||||
|
* impossible to change anything about that configuration (include images
|
||||||
|
* attached to the configuration), but it may be possible to add new
|
||||||
|
* configurations, new images or new signatures within the existing
|
||||||
|
* framework.
|
||||||
|
*
|
||||||
|
* Adding new properties to a device tree may result in the string table
|
||||||
|
* being extended (if the new property names are different from those
|
||||||
|
* already added). This function can optionally include a region for
|
||||||
|
* the string table so that this can be part of the hash too.
|
||||||
|
*
|
||||||
|
* The device tree header is not included in the list.
|
||||||
|
*
|
||||||
|
* @fdt: Device tree to check
|
||||||
|
* @inc: List of node paths to included
|
||||||
|
* @inc_count: Number of node paths in list
|
||||||
|
* @exc_prop: List of properties names to exclude
|
||||||
|
* @exc_prop_count: Number of properties in exclude list
|
||||||
|
* @region: Returns list of regions
|
||||||
|
* @max_region: Maximum length of region list
|
||||||
|
* @path: Pointer to a temporary string for the function to use for
|
||||||
|
* building path names
|
||||||
|
* @path_len: Length of path, must be large enough to hold the longest
|
||||||
|
* path in the tree
|
||||||
|
* @add_string_tab: 1 to add a region for the string table
|
||||||
|
* @return number of regions in list. If this is >max_regions then the
|
||||||
|
* region array was exhausted. You should increase max_regions and try
|
||||||
|
* the call again.
|
||||||
|
*/
|
||||||
|
int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
|
||||||
|
char * const exc_prop[], int exc_prop_count,
|
||||||
|
struct fdt_region region[], int max_regions,
|
||||||
|
char *path, int path_len, int add_string_tab);
|
||||||
|
|
||||||
#endif /* _LIBFDT_H */
|
#endif /* _LIBFDT_H */
|
||||||
|
|
|
@ -120,3 +120,132 @@ int fdt_nop_node(void *fdt, int nodeoffset)
|
||||||
endoffset - nodeoffset);
|
endoffset - nodeoffset);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FDT_MAX_DEPTH 32
|
||||||
|
|
||||||
|
static int str_in_list(const char *str, char * const list[], int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
if (!strcmp(list[i], str))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
|
||||||
|
char * const exc_prop[], int exc_prop_count,
|
||||||
|
struct fdt_region region[], int max_regions,
|
||||||
|
char *path, int path_len, int add_string_tab)
|
||||||
|
{
|
||||||
|
int stack[FDT_MAX_DEPTH];
|
||||||
|
char *end;
|
||||||
|
int nextoffset = 0;
|
||||||
|
uint32_t tag;
|
||||||
|
int count = 0;
|
||||||
|
int start = -1;
|
||||||
|
int depth = -1;
|
||||||
|
int want = 0;
|
||||||
|
int base = fdt_off_dt_struct(fdt);
|
||||||
|
|
||||||
|
end = path;
|
||||||
|
*end = '\0';
|
||||||
|
do {
|
||||||
|
const struct fdt_property *prop;
|
||||||
|
const char *name;
|
||||||
|
const char *str;
|
||||||
|
int include = 0;
|
||||||
|
int stop_at = 0;
|
||||||
|
int offset;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
offset = nextoffset;
|
||||||
|
tag = fdt_next_tag(fdt, offset, &nextoffset);
|
||||||
|
stop_at = nextoffset;
|
||||||
|
|
||||||
|
switch (tag) {
|
||||||
|
case FDT_PROP:
|
||||||
|
include = want >= 2;
|
||||||
|
stop_at = offset;
|
||||||
|
prop = fdt_get_property_by_offset(fdt, offset, NULL);
|
||||||
|
str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
|
||||||
|
if (str_in_list(str, exc_prop, exc_prop_count))
|
||||||
|
include = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FDT_NOP:
|
||||||
|
include = want >= 2;
|
||||||
|
stop_at = offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FDT_BEGIN_NODE:
|
||||||
|
depth++;
|
||||||
|
if (depth == FDT_MAX_DEPTH)
|
||||||
|
return -FDT_ERR_BADSTRUCTURE;
|
||||||
|
name = fdt_get_name(fdt, offset, &len);
|
||||||
|
if (end - path + 2 + len >= path_len)
|
||||||
|
return -FDT_ERR_NOSPACE;
|
||||||
|
if (end != path + 1)
|
||||||
|
*end++ = '/';
|
||||||
|
strcpy(end, name);
|
||||||
|
end += len;
|
||||||
|
stack[depth] = want;
|
||||||
|
if (want == 1)
|
||||||
|
stop_at = offset;
|
||||||
|
if (str_in_list(path, inc, inc_count))
|
||||||
|
want = 2;
|
||||||
|
else if (want)
|
||||||
|
want--;
|
||||||
|
else
|
||||||
|
stop_at = offset;
|
||||||
|
include = want;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FDT_END_NODE:
|
||||||
|
include = want;
|
||||||
|
want = stack[depth--];
|
||||||
|
while (end > path && *--end != '/')
|
||||||
|
;
|
||||||
|
*end = '\0';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FDT_END:
|
||||||
|
include = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include && start == -1) {
|
||||||
|
/* Should we merge with previous? */
|
||||||
|
if (count && count <= max_regions &&
|
||||||
|
offset == region[count - 1].offset +
|
||||||
|
region[count - 1].size - base)
|
||||||
|
start = region[--count].offset - base;
|
||||||
|
else
|
||||||
|
start = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!include && start != -1) {
|
||||||
|
if (count < max_regions) {
|
||||||
|
region[count].offset = base + start;
|
||||||
|
region[count].size = stop_at - start;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
start = -1;
|
||||||
|
}
|
||||||
|
} while (tag != FDT_END);
|
||||||
|
|
||||||
|
if (nextoffset != fdt_size_dt_struct(fdt))
|
||||||
|
return -FDT_ERR_BADLAYOUT;
|
||||||
|
|
||||||
|
/* Add a region for the END tag and the string table */
|
||||||
|
if (count < max_regions) {
|
||||||
|
region[count].offset = base + start;
|
||||||
|
region[count].size = nextoffset - start;
|
||||||
|
if (add_string_tab)
|
||||||
|
region[count].size += fdt_size_dt_strings(fdt);
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue