lib: Split fdt_print() into separate library file
Move fdt_print() function from cmd/fdt.c to a new lib/fdt_print.c file to make it available as a library function for other code to use. Move and rename is_printable_string(), making it available as well. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
225
cmd/fdt.c
225
cmd/fdt.c
@@ -27,8 +27,6 @@
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
|
||||
static int fdt_print(const char *pathp, char *prop, int depth);
|
||||
static int is_printable_string(const void *data, int len);
|
||||
|
||||
/*
|
||||
* The working_fdt points to our working flattened device tree.
|
||||
@@ -56,7 +54,7 @@ void set_working_fdt_addr(ulong addr)
|
||||
static int fdt_value_env_set(const void *nodep, int len,
|
||||
const char *var, int index)
|
||||
{
|
||||
if (is_printable_string(nodep, len)) {
|
||||
if (fdt_printable_str(nodep, len)) {
|
||||
const char *nodec = (const char *)nodep;
|
||||
int i;
|
||||
|
||||
@@ -890,227 +888,6 @@ static int fdt_parse_prop(char * const *newval, int count, char *data, int *len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Heuristic to guess if this is a string or concatenated strings.
|
||||
*/
|
||||
|
||||
static int is_printable_string(const void *data, int len)
|
||||
{
|
||||
const char *s = data;
|
||||
const char *ss, *se;
|
||||
|
||||
/* zero length is not */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* must terminate with zero */
|
||||
if (s[len - 1] != '\0')
|
||||
return 0;
|
||||
|
||||
se = s + len;
|
||||
|
||||
while (s < se) {
|
||||
ss = s;
|
||||
while (s < se && *s && isprint((unsigned char)*s))
|
||||
s++;
|
||||
|
||||
/* not zero, or not done yet */
|
||||
if (*s != '\0' || s == ss)
|
||||
return 0;
|
||||
|
||||
s++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the property in the best format, a heuristic guess. Print as
|
||||
* a string, concatenated strings, a byte, word, double word, or (if all
|
||||
* else fails) it is printed as a stream of bytes.
|
||||
*/
|
||||
static void print_data(const void *data, int len)
|
||||
{
|
||||
int j;
|
||||
const char *env_max_dump;
|
||||
ulong max_dump = ULONG_MAX;
|
||||
|
||||
/* no data, don't print */
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
env_max_dump = env_get("fdt_max_dump");
|
||||
if (env_max_dump)
|
||||
max_dump = hextoul(env_max_dump, NULL);
|
||||
|
||||
/*
|
||||
* It is a string, but it may have multiple strings (embedded '\0's).
|
||||
*/
|
||||
if (is_printable_string(data, len)) {
|
||||
puts("\"");
|
||||
j = 0;
|
||||
while (j < len) {
|
||||
if (j > 0)
|
||||
puts("\", \"");
|
||||
puts(data);
|
||||
j += strlen(data) + 1;
|
||||
data += strlen(data) + 1;
|
||||
}
|
||||
puts("\"");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((len %4) == 0) {
|
||||
if (len > max_dump)
|
||||
printf("* 0x%p [0x%08x]", data, len);
|
||||
else {
|
||||
const __be32 *p;
|
||||
|
||||
printf("<");
|
||||
for (j = 0, p = data; j < len/4; j++)
|
||||
printf("0x%08x%s", fdt32_to_cpu(p[j]),
|
||||
j < (len/4 - 1) ? " " : "");
|
||||
printf(">");
|
||||
}
|
||||
} else { /* anything else... hexdump */
|
||||
if (len > max_dump)
|
||||
printf("* 0x%p [0x%08x]", data, len);
|
||||
else {
|
||||
const u8 *s;
|
||||
|
||||
printf("[");
|
||||
for (j = 0, s = data; j < len; j++)
|
||||
printf("%02x%s", s[j], j < len - 1 ? " " : "");
|
||||
printf("]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Recursively print (a portion of) the working_fdt. The depth parameter
|
||||
* determines how deeply nested the fdt is printed.
|
||||
*/
|
||||
static int fdt_print(const char *pathp, char *prop, int depth)
|
||||
{
|
||||
static char tabs[MAX_LEVEL+1] =
|
||||
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
|
||||
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
|
||||
const void *nodep; /* property node pointer */
|
||||
int nodeoffset; /* node offset from libfdt */
|
||||
int nextoffset; /* next node offset from libfdt */
|
||||
uint32_t tag; /* tag */
|
||||
int len; /* length of the property */
|
||||
int level = 0; /* keep track of nesting level */
|
||||
const struct fdt_property *fdt_prop;
|
||||
|
||||
nodeoffset = fdt_path_offset (working_fdt, pathp);
|
||||
if (nodeoffset < 0) {
|
||||
/*
|
||||
* Not found or something else bad happened.
|
||||
*/
|
||||
printf ("libfdt fdt_path_offset() returned %s\n",
|
||||
fdt_strerror(nodeoffset));
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* The user passed in a property as well as node path.
|
||||
* Print only the given property and then return.
|
||||
*/
|
||||
if (prop) {
|
||||
nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len);
|
||||
if (len == 0) {
|
||||
/* no property value */
|
||||
printf("%s %s\n", pathp, prop);
|
||||
return 0;
|
||||
} else if (nodep && len > 0) {
|
||||
printf("%s = ", prop);
|
||||
print_data (nodep, len);
|
||||
printf("\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf ("libfdt fdt_getprop(): %s\n",
|
||||
fdt_strerror(len));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The user passed in a node path and no property,
|
||||
* print the node and all subnodes.
|
||||
*/
|
||||
while(level >= 0) {
|
||||
tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
|
||||
switch(tag) {
|
||||
case FDT_BEGIN_NODE:
|
||||
pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
|
||||
if (level <= depth) {
|
||||
if (pathp == NULL)
|
||||
pathp = "/* NULL pointer error */";
|
||||
if (*pathp == '\0')
|
||||
pathp = "/"; /* root is nameless */
|
||||
printf("%s%s {\n",
|
||||
&tabs[MAX_LEVEL - level], pathp);
|
||||
}
|
||||
level++;
|
||||
if (level >= MAX_LEVEL) {
|
||||
printf("Nested too deep, aborting.\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case FDT_END_NODE:
|
||||
level--;
|
||||
if (level <= depth)
|
||||
printf("%s};\n", &tabs[MAX_LEVEL - level]);
|
||||
if (level == 0) {
|
||||
level = -1; /* exit the loop */
|
||||
}
|
||||
break;
|
||||
case FDT_PROP:
|
||||
fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
|
||||
sizeof(*fdt_prop));
|
||||
pathp = fdt_string(working_fdt,
|
||||
fdt32_to_cpu(fdt_prop->nameoff));
|
||||
len = fdt32_to_cpu(fdt_prop->len);
|
||||
nodep = fdt_prop->data;
|
||||
if (len < 0) {
|
||||
printf ("libfdt fdt_getprop(): %s\n",
|
||||
fdt_strerror(len));
|
||||
return 1;
|
||||
} else if (len == 0) {
|
||||
/* the property has no value */
|
||||
if (level <= depth)
|
||||
printf("%s%s;\n",
|
||||
&tabs[MAX_LEVEL - level],
|
||||
pathp);
|
||||
} else {
|
||||
if (level <= depth) {
|
||||
printf("%s%s = ",
|
||||
&tabs[MAX_LEVEL - level],
|
||||
pathp);
|
||||
print_data (nodep, len);
|
||||
printf(";\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FDT_NOP:
|
||||
printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
|
||||
break;
|
||||
case FDT_END:
|
||||
return 1;
|
||||
default:
|
||||
if (level <= depth)
|
||||
printf("Unknown tag 0x%08X\n", tag);
|
||||
return 1;
|
||||
}
|
||||
nodeoffset = nextoffset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
U_BOOT_LONGHELP(fdt,
|
||||
"addr [-c] [-q] <addr> [<size>] - Set the [control] fdt location to <addr>\n"
|
||||
|
||||
Reference in New Issue
Block a user