2018-05-06 21:58:06 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2007-03-31 16:22:10 +00:00
|
|
|
/*
|
|
|
|
* (C) Copyright 2007
|
|
|
|
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
|
|
|
|
* Based on code written by:
|
|
|
|
* Pantelis Antoniou <pantelis.antoniou@gmail.com> and
|
|
|
|
* Matthew McClintock <msm@freescale.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <common.h>
|
|
|
|
#include <command.h>
|
2019-08-01 15:46:46 +00:00
|
|
|
#include <env.h>
|
2020-05-10 17:40:01 +00:00
|
|
|
#include <image.h>
|
2007-03-31 16:22:10 +00:00
|
|
|
#include <linux/ctype.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <asm/global_data.h>
|
2018-03-04 16:20:11 +00:00
|
|
|
#include <linux/libfdt.h>
|
2007-04-06 18:19:43 +00:00
|
|
|
#include <fdt_support.h>
|
2015-03-22 22:08:59 +00:00
|
|
|
#include <mapmem.h>
|
2013-04-20 08:42:45 +00:00
|
|
|
#include <asm/io.h>
|
2007-03-31 16:22:10 +00:00
|
|
|
|
|
|
|
#define MAX_LEVEL 32 /* how deeply nested we will go */
|
2007-06-26 03:25:28 +00:00
|
|
|
#define SCRATCHPAD 1024 /* bytes of scratchpad memory */
|
2007-03-31 16:22:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Global data (for the gd->bd)
|
|
|
|
*/
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
|
2010-06-28 20:00:46 +00:00
|
|
|
static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
|
2007-11-21 20:07:46 +00:00
|
|
|
static int fdt_print(const char *pathp, char *prop, int depth);
|
2012-08-17 10:34:37 +00:00
|
|
|
static int is_printable_string(const void *data, int len);
|
2007-03-31 16:22:10 +00:00
|
|
|
|
2008-06-11 02:15:58 +00:00
|
|
|
/*
|
|
|
|
* The working_fdt points to our working flattened device tree.
|
|
|
|
*/
|
|
|
|
struct fdt_header *working_fdt;
|
|
|
|
|
2015-02-05 03:56:53 +00:00
|
|
|
void set_working_fdt_addr(ulong addr)
|
2008-08-15 13:24:39 +00:00
|
|
|
{
|
2013-04-20 08:42:45 +00:00
|
|
|
void *buf;
|
|
|
|
|
2022-10-11 15:47:12 +00:00
|
|
|
printf("Working FDT set to %lx\n", addr);
|
2015-02-05 03:56:53 +00:00
|
|
|
buf = map_sysmem(addr, 0);
|
2013-04-20 08:42:45 +00:00
|
|
|
working_fdt = buf;
|
2017-08-03 18:22:10 +00:00
|
|
|
env_set_hex("fdtaddr", addr);
|
2008-08-15 13:24:39 +00:00
|
|
|
}
|
|
|
|
|
2012-08-17 10:34:37 +00:00
|
|
|
/*
|
|
|
|
* Get a value from the fdt and format it to be set in the environment
|
|
|
|
*/
|
2022-07-08 21:50:43 +00:00
|
|
|
static int fdt_value_env_set(const void *nodep, int len,
|
|
|
|
const char *var, int index)
|
2012-08-17 10:34:37 +00:00
|
|
|
{
|
2022-07-08 21:50:43 +00:00
|
|
|
if (is_printable_string(nodep, len)) {
|
|
|
|
const char *nodec = (const char *)nodep;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Iterate over all members in stringlist and find the one at
|
|
|
|
* offset $index. If no such index exists, indicate failure.
|
|
|
|
*/
|
2022-11-14 21:49:59 +00:00
|
|
|
for (i = 0; i < len; ) {
|
|
|
|
if (index-- > 0) {
|
|
|
|
i += strlen(nodec) + 1;
|
|
|
|
nodec += strlen(nodec) + 1;
|
2022-07-08 21:50:43 +00:00
|
|
|
continue;
|
2022-11-14 21:49:59 +00:00
|
|
|
}
|
2022-07-08 21:50:43 +00:00
|
|
|
|
2022-11-14 21:49:59 +00:00
|
|
|
env_set(var, nodec);
|
2022-07-08 21:50:43 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
} else if (len == 4) {
|
2012-08-17 10:34:37 +00:00
|
|
|
char buf[11];
|
|
|
|
|
2017-01-09 15:08:02 +00:00
|
|
|
sprintf(buf, "0x%08X", fdt32_to_cpu(*(fdt32_t *)nodep));
|
2017-08-03 18:22:09 +00:00
|
|
|
env_set(var, buf);
|
2012-08-17 10:34:37 +00:00
|
|
|
} else if (len%4 == 0 && len <= 20) {
|
|
|
|
/* Needed to print things like sha1 hashes. */
|
|
|
|
char buf[41];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i += sizeof(unsigned int))
|
|
|
|
sprintf(buf + (i * 2), "%08x",
|
|
|
|
*(unsigned int *)(nodep + i));
|
2017-08-03 18:22:09 +00:00
|
|
|
env_set(var, buf);
|
2012-08-17 10:34:37 +00:00
|
|
|
} else {
|
|
|
|
printf("error: unprintable value\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-11-15 05:06:06 +00:00
|
|
|
static const char * const fdt_member_table[] = {
|
|
|
|
"magic",
|
|
|
|
"totalsize",
|
|
|
|
"off_dt_struct",
|
|
|
|
"off_dt_strings",
|
|
|
|
"off_mem_rsvmap",
|
|
|
|
"version",
|
|
|
|
"last_comp_version",
|
|
|
|
"boot_cpuid_phys",
|
|
|
|
"size_dt_strings",
|
|
|
|
"size_dt_struct",
|
|
|
|
};
|
|
|
|
|
2020-05-10 17:40:03 +00:00
|
|
|
static int fdt_get_header_value(int argc, char *const argv[])
|
2018-11-15 05:06:06 +00:00
|
|
|
{
|
|
|
|
fdt32_t *fdtp = (fdt32_t *)working_fdt;
|
|
|
|
ulong val;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (argv[2][0] != 'g')
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(fdt_member_table); i++) {
|
|
|
|
if (strcmp(fdt_member_table[i], argv[4]))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
val = fdt32_to_cpu(fdtp[i]);
|
|
|
|
env_set_hex(argv[3], val);
|
|
|
|
return CMD_RET_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
}
|
|
|
|
|
2007-03-31 16:22:10 +00:00
|
|
|
/*
|
|
|
|
* Flattened Device Tree command, see the help for parameter definitions.
|
|
|
|
*/
|
2020-05-10 17:40:03 +00:00
|
|
|
static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
2007-03-31 16:22:10 +00:00
|
|
|
{
|
2010-07-16 23:06:04 +00:00
|
|
|
if (argc < 2)
|
2011-12-10 08:44:01 +00:00
|
|
|
return CMD_RET_USAGE;
|
2007-03-31 16:22:10 +00:00
|
|
|
|
2021-07-21 20:55:25 +00:00
|
|
|
/* fdt addr: Set the address of the fdt */
|
2016-07-05 08:26:34 +00:00
|
|
|
if (strncmp(argv[1], "ad", 2) == 0) {
|
2008-08-15 13:24:39 +00:00
|
|
|
unsigned long addr;
|
2013-04-20 08:42:44 +00:00
|
|
|
int control = 0;
|
2022-03-31 10:53:22 +00:00
|
|
|
int quiet = 0;
|
2013-04-20 08:42:44 +00:00
|
|
|
struct fdt_header *blob;
|
2021-07-21 20:55:25 +00:00
|
|
|
|
|
|
|
/* Set the address [and length] of the fdt */
|
2013-04-20 08:42:44 +00:00
|
|
|
argc -= 2;
|
|
|
|
argv += 2;
|
2022-03-31 10:53:22 +00:00
|
|
|
while (argc > 0 && **argv == '-') {
|
|
|
|
char *arg = *argv;
|
|
|
|
|
|
|
|
while (*++arg) {
|
|
|
|
switch (*arg) {
|
|
|
|
case 'c':
|
|
|
|
control = 1;
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
quiet = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return CMD_RET_USAGE;
|
|
|
|
}
|
|
|
|
}
|
2013-04-20 08:42:44 +00:00
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
}
|
|
|
|
if (argc == 0) {
|
|
|
|
if (control)
|
|
|
|
blob = (struct fdt_header *)gd->fdt_blob;
|
|
|
|
else
|
|
|
|
blob = working_fdt;
|
|
|
|
if (!blob || !fdt_valid(&blob))
|
2008-08-15 13:24:35 +00:00
|
|
|
return 1;
|
2021-07-21 20:55:26 +00:00
|
|
|
printf("%s fdt: %08lx\n",
|
|
|
|
control ? "Control" : "Working",
|
2015-02-05 03:56:54 +00:00
|
|
|
control ? (ulong)map_to_sysmem(blob) :
|
2021-07-21 20:55:26 +00:00
|
|
|
env_get_hex("fdtaddr", 0));
|
2008-08-15 13:24:35 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-24 15:03:29 +00:00
|
|
|
addr = hextoul(argv[0], NULL);
|
2013-04-20 08:42:45 +00:00
|
|
|
blob = map_sysmem(addr, 0);
|
2022-03-31 10:53:22 +00:00
|
|
|
if ((quiet && fdt_check_header(blob)) ||
|
|
|
|
(!quiet && !fdt_valid(&blob)))
|
2007-03-31 16:22:10 +00:00
|
|
|
return 1;
|
2013-04-20 08:42:44 +00:00
|
|
|
if (control)
|
|
|
|
gd->fdt_blob = blob;
|
|
|
|
else
|
2015-02-05 03:56:53 +00:00
|
|
|
set_working_fdt_addr(addr);
|
2007-03-31 16:22:10 +00:00
|
|
|
|
2013-04-20 08:42:44 +00:00
|
|
|
if (argc >= 2) {
|
2007-03-31 16:22:10 +00:00
|
|
|
int len;
|
|
|
|
int err;
|
2021-07-21 20:55:25 +00:00
|
|
|
|
|
|
|
/* Optional new length */
|
2021-07-24 15:03:29 +00:00
|
|
|
len = hextoul(argv[1], NULL);
|
2013-04-20 08:42:44 +00:00
|
|
|
if (len < fdt_totalsize(blob)) {
|
2022-03-31 10:53:22 +00:00
|
|
|
if (!quiet)
|
|
|
|
printf("New length %d < existing length %d, ignoring\n",
|
|
|
|
len, fdt_totalsize(blob));
|
2007-03-31 16:22:10 +00:00
|
|
|
} else {
|
2021-07-21 20:55:25 +00:00
|
|
|
/* Open in place with a new length */
|
2013-04-20 08:42:44 +00:00
|
|
|
err = fdt_open_into(blob, blob, len);
|
2022-03-31 10:53:22 +00:00
|
|
|
if (!quiet && err != 0) {
|
2021-07-21 20:55:25 +00:00
|
|
|
printf("libfdt fdt_open_into(): %s\n",
|
|
|
|
fdt_strerror(err));
|
2007-03-31 16:22:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-05 06:34:44 +00:00
|
|
|
return CMD_RET_SUCCESS;
|
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
/*
|
2008-06-10 16:06:17 +00:00
|
|
|
* Move the working_fdt
|
2010-07-16 23:06:04 +00:00
|
|
|
*/
|
2023-02-10 11:02:12 +00:00
|
|
|
} else if (strncmp(argv[1], "mo", 2) == 0) {
|
2007-03-31 16:22:10 +00:00
|
|
|
struct fdt_header *newaddr;
|
|
|
|
int len;
|
|
|
|
int err;
|
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
if (argc < 4)
|
2011-12-10 08:44:01 +00:00
|
|
|
return CMD_RET_USAGE;
|
2007-03-31 16:22:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the address and length of the fdt.
|
|
|
|
*/
|
2023-02-10 11:02:11 +00:00
|
|
|
working_fdt = map_sysmem(hextoul(argv[2], NULL), 0);
|
2013-04-20 08:42:42 +00:00
|
|
|
if (!fdt_valid(&working_fdt))
|
2007-03-31 16:22:10 +00:00
|
|
|
return 1;
|
|
|
|
|
2023-02-10 11:02:11 +00:00
|
|
|
newaddr = map_sysmem(hextoul(argv[3], NULL), 0);
|
2007-04-26 02:47:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the user specifies a length, use that. Otherwise use the
|
|
|
|
* current length.
|
|
|
|
*/
|
|
|
|
if (argc <= 4) {
|
2008-06-10 16:06:17 +00:00
|
|
|
len = fdt_totalsize(working_fdt);
|
2007-04-26 02:47:15 +00:00
|
|
|
} else {
|
2021-07-24 15:03:29 +00:00
|
|
|
len = hextoul(argv[4], NULL);
|
2008-06-10 16:06:17 +00:00
|
|
|
if (len < fdt_totalsize(working_fdt)) {
|
2007-05-17 02:39:59 +00:00
|
|
|
printf ("New length 0x%X < existing length "
|
|
|
|
"0x%X, aborting.\n",
|
2008-06-10 16:06:17 +00:00
|
|
|
len, fdt_totalsize(working_fdt));
|
2007-04-26 02:47:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2007-03-31 16:22:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy to the new location.
|
|
|
|
*/
|
2008-06-10 16:06:17 +00:00
|
|
|
err = fdt_open_into(working_fdt, newaddr, len);
|
2007-03-31 16:22:10 +00:00
|
|
|
if (err != 0) {
|
2007-05-17 02:39:59 +00:00
|
|
|
printf ("libfdt fdt_open_into(): %s\n",
|
|
|
|
fdt_strerror(err));
|
2007-03-31 16:22:10 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2023-02-10 11:02:11 +00:00
|
|
|
set_working_fdt_addr(map_to_sysmem(newaddr));
|
2023-02-10 11:02:12 +00:00
|
|
|
|
|
|
|
return CMD_RET_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!working_fdt) {
|
|
|
|
puts("No FDT memory address configured. Please configure\n"
|
|
|
|
"the FDT address via \"fdt addr <address>\" command.\n"
|
|
|
|
"Aborting!\n");
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
}
|
|
|
|
|
2016-11-24 14:02:18 +00:00
|
|
|
#ifdef CONFIG_OF_SYSTEM_SETUP
|
|
|
|
/* Call the board-specific fixup routine */
|
2023-02-10 11:02:12 +00:00
|
|
|
if (strncmp(argv[1], "sys", 3) == 0) {
|
2016-11-24 14:02:18 +00:00
|
|
|
int err = ft_system_setup(working_fdt, gd->bd);
|
2007-03-31 16:22:10 +00:00
|
|
|
|
2016-11-24 14:02:18 +00:00
|
|
|
if (err) {
|
|
|
|
printf("Failed to add system information to FDT: %s\n",
|
|
|
|
fdt_strerror(err));
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
}
|
2023-02-10 11:02:12 +00:00
|
|
|
|
|
|
|
return CMD_RET_SUCCESS;
|
|
|
|
}
|
2016-11-24 14:02:18 +00:00
|
|
|
#endif
|
2010-07-16 23:06:04 +00:00
|
|
|
/*
|
2007-05-12 13:47:25 +00:00
|
|
|
* Make a new node
|
2010-07-16 23:06:04 +00:00
|
|
|
*/
|
2023-02-10 11:02:12 +00:00
|
|
|
if (strncmp(argv[1], "mk", 2) == 0) {
|
2007-05-12 13:47:25 +00:00
|
|
|
char *pathp; /* path */
|
|
|
|
char *nodep; /* new node to add */
|
|
|
|
int nodeoffset; /* node offset from libfdt */
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parameters: Node path, new node to be appended to the path.
|
|
|
|
*/
|
2010-07-16 23:06:04 +00:00
|
|
|
if (argc < 4)
|
2011-12-10 08:44:01 +00:00
|
|
|
return CMD_RET_USAGE;
|
2007-05-12 13:47:25 +00:00
|
|
|
|
|
|
|
pathp = argv[2];
|
|
|
|
nodep = argv[3];
|
|
|
|
|
2008-06-10 16:06:17 +00:00
|
|
|
nodeoffset = fdt_path_offset (working_fdt, pathp);
|
2007-05-12 13:47:25 +00:00
|
|
|
if (nodeoffset < 0) {
|
|
|
|
/*
|
|
|
|
* Not found or something else bad happened.
|
|
|
|
*/
|
2007-10-24 16:04:22 +00:00
|
|
|
printf ("libfdt fdt_path_offset() returned %s\n",
|
2007-05-22 03:27:16 +00:00
|
|
|
fdt_strerror(nodeoffset));
|
2007-05-12 13:47:25 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2008-06-10 16:06:17 +00:00
|
|
|
err = fdt_add_subnode(working_fdt, nodeoffset, nodep);
|
2007-05-12 13:47:25 +00:00
|
|
|
if (err < 0) {
|
2007-05-17 02:39:59 +00:00
|
|
|
printf ("libfdt fdt_add_subnode(): %s\n",
|
|
|
|
fdt_strerror(err));
|
2007-05-12 13:47:25 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
/*
|
2008-06-10 16:06:17 +00:00
|
|
|
* Set the value of a property in the working_fdt.
|
2010-07-16 23:06:04 +00:00
|
|
|
*/
|
2020-03-26 22:20:44 +00:00
|
|
|
} else if (strncmp(argv[1], "se", 2) == 0) {
|
2007-03-31 16:22:10 +00:00
|
|
|
char *pathp; /* path */
|
2007-05-17 02:39:59 +00:00
|
|
|
char *prop; /* property */
|
2007-03-31 16:22:10 +00:00
|
|
|
int nodeoffset; /* node offset from libfdt */
|
2017-09-28 09:29:52 +00:00
|
|
|
static char data[SCRATCHPAD] __aligned(4);/* property storage */
|
2017-05-30 13:05:44 +00:00
|
|
|
const void *ptmp;
|
2007-05-17 02:39:59 +00:00
|
|
|
int len; /* new length of the property */
|
|
|
|
int ret; /* return value */
|
2007-03-31 16:22:10 +00:00
|
|
|
|
|
|
|
/*
|
2008-01-05 19:52:04 +00:00
|
|
|
* Parameters: Node path, property, optional value.
|
2007-03-31 16:22:10 +00:00
|
|
|
*/
|
2010-07-16 23:06:04 +00:00
|
|
|
if (argc < 4)
|
2011-12-10 08:44:01 +00:00
|
|
|
return CMD_RET_USAGE;
|
2007-03-31 16:22:10 +00:00
|
|
|
|
|
|
|
pathp = argv[2];
|
|
|
|
prop = argv[3];
|
|
|
|
|
2008-06-10 16:06:17 +00:00
|
|
|
nodeoffset = fdt_path_offset (working_fdt, pathp);
|
2007-05-12 13:47:25 +00:00
|
|
|
if (nodeoffset < 0) {
|
2007-03-31 16:22:10 +00:00
|
|
|
/*
|
2007-05-12 13:47:25 +00:00
|
|
|
* Not found or something else bad happened.
|
2007-03-31 16:22:10 +00:00
|
|
|
*/
|
2007-10-24 16:04:22 +00:00
|
|
|
printf ("libfdt fdt_path_offset() returned %s\n",
|
2007-05-22 03:27:16 +00:00
|
|
|
fdt_strerror(nodeoffset));
|
2007-03-31 16:22:10 +00:00
|
|
|
return 1;
|
2007-05-12 13:47:25 +00:00
|
|
|
}
|
|
|
|
|
2017-05-30 13:05:44 +00:00
|
|
|
if (argc == 4) {
|
|
|
|
len = 0;
|
|
|
|
} else {
|
|
|
|
ptmp = fdt_getprop(working_fdt, nodeoffset, prop, &len);
|
|
|
|
if (len > SCRATCHPAD) {
|
|
|
|
printf("prop (%d) doesn't fit in scratchpad!\n",
|
|
|
|
len);
|
|
|
|
return 1;
|
|
|
|
}
|
2017-08-18 12:41:14 +00:00
|
|
|
if (ptmp != NULL)
|
|
|
|
memcpy(data, ptmp, len);
|
|
|
|
|
2017-05-30 13:05:44 +00:00
|
|
|
ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
|
|
|
|
if (ret != 0)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-06-10 16:06:17 +00:00
|
|
|
ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len);
|
2007-05-12 13:47:25 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret));
|
|
|
|
return 1;
|
2007-03-31 16:22:10 +00:00
|
|
|
}
|
|
|
|
|
2012-08-17 10:34:37 +00:00
|
|
|
/********************************************************************
|
|
|
|
* Get the value of a property in the working_fdt.
|
|
|
|
********************************************************************/
|
|
|
|
} else if (argv[1][0] == 'g') {
|
|
|
|
char *subcmd; /* sub-command */
|
|
|
|
char *pathp; /* path */
|
|
|
|
char *prop; /* property */
|
|
|
|
char *var; /* variable to store result */
|
|
|
|
int nodeoffset; /* node offset from libfdt */
|
|
|
|
const void *nodep; /* property node pointer */
|
|
|
|
int len = 0; /* new length of the property */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parameters: Node path, property, optional value.
|
|
|
|
*/
|
|
|
|
if (argc < 5)
|
|
|
|
return CMD_RET_USAGE;
|
|
|
|
|
|
|
|
subcmd = argv[2];
|
|
|
|
|
|
|
|
if (argc < 6 && subcmd[0] != 's')
|
|
|
|
return CMD_RET_USAGE;
|
|
|
|
|
|
|
|
var = argv[3];
|
|
|
|
pathp = argv[4];
|
|
|
|
prop = argv[5];
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) {
|
2021-07-24 15:03:29 +00:00
|
|
|
int req_index = -1;
|
2012-08-17 10:34:37 +00:00
|
|
|
int startDepth = fdt_node_depth(
|
|
|
|
working_fdt, nodeoffset);
|
|
|
|
int curDepth = startDepth;
|
2021-07-24 15:03:29 +00:00
|
|
|
int cur_index = -1;
|
2012-08-17 10:34:37 +00:00
|
|
|
int nextNodeOffset = fdt_next_node(
|
|
|
|
working_fdt, nodeoffset, &curDepth);
|
|
|
|
|
|
|
|
if (subcmd[0] == 'n')
|
2021-07-24 15:03:29 +00:00
|
|
|
req_index = hextoul(argv[5], NULL);
|
2012-08-17 10:34:37 +00:00
|
|
|
|
|
|
|
while (curDepth > startDepth) {
|
|
|
|
if (curDepth == startDepth + 1)
|
2021-07-24 15:03:29 +00:00
|
|
|
cur_index++;
|
|
|
|
if (subcmd[0] == 'n' &&
|
|
|
|
cur_index == req_index) {
|
2017-08-03 18:22:09 +00:00
|
|
|
const char *node_name;
|
2012-08-17 10:34:37 +00:00
|
|
|
|
2017-08-03 18:22:09 +00:00
|
|
|
node_name = fdt_get_name(working_fdt,
|
|
|
|
nextNodeOffset,
|
|
|
|
NULL);
|
|
|
|
env_set(var, node_name);
|
2012-08-17 10:34:37 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
nextNodeOffset = fdt_next_node(
|
|
|
|
working_fdt, nextNodeOffset, &curDepth);
|
|
|
|
if (nextNodeOffset < 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (subcmd[0] == 's') {
|
|
|
|
/* get the num nodes at this level */
|
2021-07-24 15:03:29 +00:00
|
|
|
env_set_ulong(var, cur_index + 1);
|
2012-08-17 10:34:37 +00:00
|
|
|
} else {
|
|
|
|
/* node index not found */
|
|
|
|
printf("libfdt node not found\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
nodep = fdt_getprop(
|
|
|
|
working_fdt, nodeoffset, prop, &len);
|
2023-03-02 03:08:15 +00:00
|
|
|
if (nodep && len >= 0) {
|
2012-08-17 10:34:37 +00:00
|
|
|
if (subcmd[0] == 'v') {
|
2022-07-08 21:50:43 +00:00
|
|
|
int index = 0;
|
2012-08-17 10:34:37 +00:00
|
|
|
int ret;
|
|
|
|
|
2023-03-02 03:08:15 +00:00
|
|
|
if (len == 0) {
|
|
|
|
/* no property value */
|
|
|
|
env_set(var, "");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-07-08 21:50:43 +00:00
|
|
|
if (argc == 7)
|
|
|
|
index = simple_strtoul(argv[6], NULL, 10);
|
|
|
|
|
2017-08-03 18:22:09 +00:00
|
|
|
ret = fdt_value_env_set(nodep, len,
|
2022-07-08 21:50:43 +00:00
|
|
|
var, index);
|
2012-08-17 10:34:37 +00:00
|
|
|
if (ret != 0)
|
|
|
|
return ret;
|
|
|
|
} else if (subcmd[0] == 'a') {
|
|
|
|
/* Get address */
|
2023-03-02 03:08:21 +00:00
|
|
|
char buf[19];
|
2012-08-17 10:34:37 +00:00
|
|
|
|
2023-03-02 03:08:22 +00:00
|
|
|
snprintf(buf, sizeof(buf), "0x%lx",
|
|
|
|
(ulong)map_to_sysmem(nodep));
|
2017-08-03 18:22:09 +00:00
|
|
|
env_set(var, buf);
|
2012-08-17 10:34:37 +00:00
|
|
|
} else if (subcmd[0] == 's') {
|
|
|
|
/* Get size */
|
|
|
|
char buf[11];
|
|
|
|
|
|
|
|
sprintf(buf, "0x%08X", len);
|
2017-08-03 18:22:09 +00:00
|
|
|
env_set(var, buf);
|
2012-08-17 10:34:37 +00:00
|
|
|
} else
|
|
|
|
return CMD_RET_USAGE;
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
printf("libfdt fdt_getprop(): %s\n",
|
|
|
|
fdt_strerror(len));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
/*
|
2007-03-31 16:22:10 +00:00
|
|
|
* Print (recursive) / List (single level)
|
2010-07-16 23:06:04 +00:00
|
|
|
*/
|
2007-05-12 13:47:25 +00:00
|
|
|
} else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {
|
2007-03-31 16:22:10 +00:00
|
|
|
int depth = MAX_LEVEL; /* how deep to print */
|
|
|
|
char *pathp; /* path */
|
2007-05-17 02:39:59 +00:00
|
|
|
char *prop; /* property */
|
|
|
|
int ret; /* return value */
|
2007-10-25 21:15:07 +00:00
|
|
|
static char root[2] = "/";
|
2007-03-31 16:22:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* list is an alias for print, but limited to 1 level
|
|
|
|
*/
|
2007-05-12 13:47:25 +00:00
|
|
|
if (argv[1][0] == 'l') {
|
2007-03-31 16:22:10 +00:00
|
|
|
depth = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the starting path. The root node is an oddball,
|
|
|
|
* the offset is zero and has no name.
|
|
|
|
*/
|
2007-10-25 21:15:07 +00:00
|
|
|
if (argc == 2)
|
|
|
|
pathp = root;
|
|
|
|
else
|
|
|
|
pathp = argv[2];
|
2007-03-31 16:22:10 +00:00
|
|
|
if (argc > 3)
|
|
|
|
prop = argv[3];
|
|
|
|
else
|
|
|
|
prop = NULL;
|
|
|
|
|
2007-05-17 02:39:59 +00:00
|
|
|
ret = fdt_print(pathp, prop, depth);
|
|
|
|
if (ret != 0)
|
|
|
|
return ret;
|
2007-03-31 16:22:10 +00:00
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
/*
|
2007-03-31 16:22:10 +00:00
|
|
|
* Remove a property/node
|
2010-07-16 23:06:04 +00:00
|
|
|
*/
|
2008-06-10 01:02:17 +00:00
|
|
|
} else if (strncmp(argv[1], "rm", 2) == 0) {
|
2007-03-31 16:22:10 +00:00
|
|
|
int nodeoffset; /* node offset from libfdt */
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the path. The root node is an oddball, the offset
|
|
|
|
* is zero and has no name.
|
|
|
|
*/
|
2008-06-10 16:06:17 +00:00
|
|
|
nodeoffset = fdt_path_offset (working_fdt, argv[2]);
|
2007-05-12 13:47:25 +00:00
|
|
|
if (nodeoffset < 0) {
|
|
|
|
/*
|
|
|
|
* Not found or something else bad happened.
|
|
|
|
*/
|
2007-10-24 16:04:22 +00:00
|
|
|
printf ("libfdt fdt_path_offset() returned %s\n",
|
2007-05-22 03:27:16 +00:00
|
|
|
fdt_strerror(nodeoffset));
|
2007-05-12 13:47:25 +00:00
|
|
|
return 1;
|
2007-03-31 16:22:10 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Do the delete. A fourth parameter means delete a property,
|
|
|
|
* otherwise delete the node.
|
|
|
|
*/
|
|
|
|
if (argc > 3) {
|
2008-06-10 16:06:17 +00:00
|
|
|
err = fdt_delprop(working_fdt, nodeoffset, argv[3]);
|
2007-03-31 16:22:10 +00:00
|
|
|
if (err < 0) {
|
2023-03-02 03:08:16 +00:00
|
|
|
printf("libfdt fdt_delprop(): %s\n",
|
2007-05-17 02:39:59 +00:00
|
|
|
fdt_strerror(err));
|
2023-03-02 03:08:16 +00:00
|
|
|
return CMD_RET_FAILURE;
|
2007-03-31 16:22:10 +00:00
|
|
|
}
|
|
|
|
} else {
|
2008-06-10 16:06:17 +00:00
|
|
|
err = fdt_del_node(working_fdt, nodeoffset);
|
2007-03-31 16:22:10 +00:00
|
|
|
if (err < 0) {
|
2023-03-02 03:08:16 +00:00
|
|
|
printf("libfdt fdt_del_node(): %s\n",
|
2007-05-17 02:39:59 +00:00
|
|
|
fdt_strerror(err));
|
2023-03-02 03:08:16 +00:00
|
|
|
return CMD_RET_FAILURE;
|
2007-03-31 16:22:10 +00:00
|
|
|
}
|
|
|
|
}
|
2008-02-15 09:34:36 +00:00
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
/*
|
2008-02-15 09:34:36 +00:00
|
|
|
* Display header info
|
2010-07-16 23:06:04 +00:00
|
|
|
*/
|
2008-02-15 09:34:36 +00:00
|
|
|
} else if (argv[1][0] == 'h') {
|
2018-11-15 05:06:06 +00:00
|
|
|
if (argc == 5)
|
|
|
|
return fdt_get_header_value(argc, argv);
|
|
|
|
|
2008-06-10 16:06:17 +00:00
|
|
|
u32 version = fdt_version(working_fdt);
|
|
|
|
printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt));
|
|
|
|
printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt),
|
|
|
|
fdt_totalsize(working_fdt));
|
|
|
|
printf("off_dt_struct:\t\t0x%x\n",
|
|
|
|
fdt_off_dt_struct(working_fdt));
|
|
|
|
printf("off_dt_strings:\t\t0x%x\n",
|
|
|
|
fdt_off_dt_strings(working_fdt));
|
|
|
|
printf("off_mem_rsvmap:\t\t0x%x\n",
|
|
|
|
fdt_off_mem_rsvmap(working_fdt));
|
2008-02-15 09:34:36 +00:00
|
|
|
printf("version:\t\t%d\n", version);
|
2008-06-10 16:06:17 +00:00
|
|
|
printf("last_comp_version:\t%d\n",
|
|
|
|
fdt_last_comp_version(working_fdt));
|
2008-02-15 09:34:36 +00:00
|
|
|
if (version >= 2)
|
|
|
|
printf("boot_cpuid_phys:\t0x%x\n",
|
2008-06-10 16:06:17 +00:00
|
|
|
fdt_boot_cpuid_phys(working_fdt));
|
2008-02-15 09:34:36 +00:00
|
|
|
if (version >= 3)
|
|
|
|
printf("size_dt_strings:\t0x%x\n",
|
2008-06-10 16:06:17 +00:00
|
|
|
fdt_size_dt_strings(working_fdt));
|
2008-02-15 09:34:36 +00:00
|
|
|
if (version >= 17)
|
|
|
|
printf("size_dt_struct:\t\t0x%x\n",
|
2008-06-10 16:06:17 +00:00
|
|
|
fdt_size_dt_struct(working_fdt));
|
|
|
|
printf("number mem_rsv:\t\t0x%x\n",
|
|
|
|
fdt_num_mem_rsv(working_fdt));
|
2008-02-15 09:34:36 +00:00
|
|
|
printf("\n");
|
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
/*
|
2008-02-15 09:34:36 +00:00
|
|
|
* Set boot cpu id
|
2010-07-16 23:06:04 +00:00
|
|
|
*/
|
2008-06-10 01:02:17 +00:00
|
|
|
} else if (strncmp(argv[1], "boo", 3) == 0) {
|
2023-03-02 03:08:18 +00:00
|
|
|
unsigned long tmp;
|
|
|
|
|
|
|
|
if (argc != 3)
|
|
|
|
return CMD_RET_USAGE;
|
|
|
|
|
|
|
|
tmp = hextoul(argv[2], NULL);
|
2008-06-10 16:06:17 +00:00
|
|
|
fdt_set_boot_cpuid_phys(working_fdt, tmp);
|
2008-02-15 09:34:36 +00:00
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
/*
|
2008-02-15 09:34:36 +00:00
|
|
|
* memory command
|
2010-07-16 23:06:04 +00:00
|
|
|
*/
|
2008-06-10 01:02:17 +00:00
|
|
|
} else if (strncmp(argv[1], "me", 2) == 0) {
|
2008-02-15 09:34:36 +00:00
|
|
|
uint64_t addr, size;
|
|
|
|
int err;
|
2023-03-02 03:08:19 +00:00
|
|
|
|
|
|
|
if (argc != 4)
|
|
|
|
return CMD_RET_USAGE;
|
|
|
|
|
2009-12-03 10:21:21 +00:00
|
|
|
addr = simple_strtoull(argv[2], NULL, 16);
|
|
|
|
size = simple_strtoull(argv[3], NULL, 16);
|
2008-06-10 16:06:17 +00:00
|
|
|
err = fdt_fixup_memory(working_fdt, addr, size);
|
2008-02-15 09:34:36 +00:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
/*
|
2008-02-15 09:34:36 +00:00
|
|
|
* mem reserve commands
|
2010-07-16 23:06:04 +00:00
|
|
|
*/
|
2008-06-10 01:02:17 +00:00
|
|
|
} else if (strncmp(argv[1], "rs", 2) == 0) {
|
2008-02-15 09:34:36 +00:00
|
|
|
if (argv[2][0] == 'p') {
|
|
|
|
uint64_t addr, size;
|
2008-06-10 16:06:17 +00:00
|
|
|
int total = fdt_num_mem_rsv(working_fdt);
|
2008-02-15 09:34:36 +00:00
|
|
|
int j, err;
|
|
|
|
printf("index\t\t start\t\t size\n");
|
|
|
|
printf("-------------------------------"
|
|
|
|
"-----------------\n");
|
|
|
|
for (j = 0; j < total; j++) {
|
2008-06-10 16:06:17 +00:00
|
|
|
err = fdt_get_mem_rsv(working_fdt, j, &addr, &size);
|
2008-02-15 09:34:36 +00:00
|
|
|
if (err < 0) {
|
|
|
|
printf("libfdt fdt_get_mem_rsv(): %s\n",
|
|
|
|
fdt_strerror(err));
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
printf(" %x\t%08x%08x\t%08x%08x\n", j,
|
|
|
|
(u32)(addr >> 32),
|
|
|
|
(u32)(addr & 0xffffffff),
|
|
|
|
(u32)(size >> 32),
|
|
|
|
(u32)(size & 0xffffffff));
|
|
|
|
}
|
|
|
|
} else if (argv[2][0] == 'a') {
|
|
|
|
uint64_t addr, size;
|
|
|
|
int err;
|
|
|
|
addr = simple_strtoull(argv[3], NULL, 16);
|
|
|
|
size = simple_strtoull(argv[4], NULL, 16);
|
2008-06-10 16:06:17 +00:00
|
|
|
err = fdt_add_mem_rsv(working_fdt, addr, size);
|
2008-02-15 09:34:36 +00:00
|
|
|
|
|
|
|
if (err < 0) {
|
2023-03-02 03:08:17 +00:00
|
|
|
printf("libfdt fdt_add_mem_rsv(): %s\n",
|
2008-02-15 09:34:36 +00:00
|
|
|
fdt_strerror(err));
|
2023-03-02 03:08:17 +00:00
|
|
|
return CMD_RET_FAILURE;
|
2008-02-15 09:34:36 +00:00
|
|
|
}
|
|
|
|
} else if (argv[2][0] == 'd') {
|
2021-07-24 15:03:29 +00:00
|
|
|
unsigned long idx = hextoul(argv[3], NULL);
|
2008-06-10 16:06:17 +00:00
|
|
|
int err = fdt_del_mem_rsv(working_fdt, idx);
|
2008-02-15 09:34:36 +00:00
|
|
|
|
|
|
|
if (err < 0) {
|
2023-03-02 03:08:17 +00:00
|
|
|
printf("libfdt fdt_del_mem_rsv(): %s\n",
|
2008-02-15 09:34:36 +00:00
|
|
|
fdt_strerror(err));
|
2023-03-02 03:08:17 +00:00
|
|
|
return CMD_RET_FAILURE;
|
2008-02-15 09:34:36 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Unrecognized command */
|
2011-12-10 08:44:01 +00:00
|
|
|
return CMD_RET_USAGE;
|
2008-02-15 09:34:36 +00:00
|
|
|
}
|
2007-07-17 18:57:04 +00:00
|
|
|
}
|
2007-06-26 03:25:28 +00:00
|
|
|
#ifdef CONFIG_OF_BOARD_SETUP
|
2007-07-17 18:57:04 +00:00
|
|
|
/* Call the board-specific fixup routine */
|
2014-10-24 00:58:48 +00:00
|
|
|
else if (strncmp(argv[1], "boa", 3) == 0) {
|
|
|
|
int err = ft_board_setup(working_fdt, gd->bd);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
printf("Failed to update board information in FDT: %s\n",
|
|
|
|
fdt_strerror(err));
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
}
|
2021-09-13 00:32:32 +00:00
|
|
|
#ifdef CONFIG_ARCH_KEYSTONE
|
2018-10-03 10:58:48 +00:00
|
|
|
ft_board_setup_ex(working_fdt, gd->bd);
|
|
|
|
#endif
|
2014-10-24 00:58:48 +00:00
|
|
|
}
|
2007-06-26 03:25:28 +00:00
|
|
|
#endif
|
2007-07-17 18:57:04 +00:00
|
|
|
/* Create a chosen node */
|
2014-03-03 11:19:24 +00:00
|
|
|
else if (strncmp(argv[1], "cho", 3) == 0) {
|
2008-08-15 13:24:34 +00:00
|
|
|
unsigned long initrd_start = 0, initrd_end = 0;
|
|
|
|
|
2010-07-16 23:06:04 +00:00
|
|
|
if ((argc != 2) && (argc != 4))
|
2011-12-10 08:44:01 +00:00
|
|
|
return CMD_RET_USAGE;
|
2008-08-15 13:24:34 +00:00
|
|
|
|
|
|
|
if (argc == 4) {
|
2021-07-24 15:03:29 +00:00
|
|
|
initrd_start = hextoul(argv[2], NULL);
|
2022-03-22 20:59:21 +00:00
|
|
|
initrd_end = initrd_start + hextoul(argv[3], NULL) - 1;
|
2008-08-15 13:24:34 +00:00
|
|
|
}
|
|
|
|
|
2014-04-18 08:41:00 +00:00
|
|
|
fdt_chosen(working_fdt);
|
2014-04-18 08:40:59 +00:00
|
|
|
fdt_initrd(working_fdt, initrd_start, initrd_end);
|
2014-03-03 11:19:24 +00:00
|
|
|
|
|
|
|
#if defined(CONFIG_FIT_SIGNATURE)
|
|
|
|
} else if (strncmp(argv[1], "che", 3) == 0) {
|
|
|
|
int cfg_noffset;
|
|
|
|
int ret;
|
|
|
|
unsigned long addr;
|
|
|
|
struct fdt_header *blob;
|
|
|
|
|
|
|
|
if (!working_fdt)
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
|
|
|
|
if (argc > 2) {
|
2021-07-24 15:03:29 +00:00
|
|
|
addr = hextoul(argv[2], NULL);
|
2014-03-03 11:19:24 +00:00
|
|
|
blob = map_sysmem(addr, 0);
|
|
|
|
} else {
|
|
|
|
blob = (struct fdt_header *)gd->fdt_blob;
|
|
|
|
}
|
|
|
|
if (!fdt_valid(&blob))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
gd->fdt_blob = blob;
|
|
|
|
cfg_noffset = fit_conf_get_node(working_fdt, NULL);
|
|
|
|
if (!cfg_noffset) {
|
|
|
|
printf("Could not find configuration node: %s\n",
|
|
|
|
fdt_strerror(cfg_noffset));
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = fit_config_verify(working_fdt, cfg_noffset);
|
2014-06-12 13:24:45 +00:00
|
|
|
if (ret == 0)
|
2014-03-03 11:19:24 +00:00
|
|
|
return CMD_RET_SUCCESS;
|
|
|
|
else
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
#endif
|
|
|
|
|
2008-08-15 13:24:44 +00:00
|
|
|
}
|
2016-07-05 08:26:45 +00:00
|
|
|
#ifdef CONFIG_OF_LIBFDT_OVERLAY
|
|
|
|
/* apply an overlay */
|
|
|
|
else if (strncmp(argv[1], "ap", 2) == 0) {
|
|
|
|
unsigned long addr;
|
|
|
|
struct fdt_header *blob;
|
2016-12-20 14:58:45 +00:00
|
|
|
int ret;
|
2016-07-05 08:26:45 +00:00
|
|
|
|
|
|
|
if (argc != 3)
|
|
|
|
return CMD_RET_USAGE;
|
|
|
|
|
|
|
|
if (!working_fdt)
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
|
2021-07-24 15:03:29 +00:00
|
|
|
addr = hextoul(argv[2], NULL);
|
2016-07-05 08:26:45 +00:00
|
|
|
blob = map_sysmem(addr, 0);
|
|
|
|
if (!fdt_valid(&blob))
|
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
|
2017-09-04 20:12:12 +00:00
|
|
|
/* apply method prints messages on error */
|
|
|
|
ret = fdt_overlay_apply_verbose(working_fdt, blob);
|
|
|
|
if (ret)
|
2016-07-05 08:26:45 +00:00
|
|
|
return CMD_RET_FAILURE;
|
|
|
|
}
|
|
|
|
#endif
|
2008-08-15 13:24:44 +00:00
|
|
|
/* resize the fdt */
|
|
|
|
else if (strncmp(argv[1], "re", 2) == 0) {
|
2016-09-20 16:10:43 +00:00
|
|
|
uint extrasize;
|
|
|
|
if (argc > 2)
|
2021-07-24 15:03:29 +00:00
|
|
|
extrasize = hextoul(argv[2], NULL);
|
2016-09-20 16:10:43 +00:00
|
|
|
else
|
|
|
|
extrasize = 0;
|
|
|
|
fdt_shrink_to_minimum(working_fdt, extrasize);
|
2008-08-15 13:24:44 +00:00
|
|
|
}
|
|
|
|
else {
|
2007-07-17 18:57:04 +00:00
|
|
|
/* Unrecognized command */
|
2011-12-10 08:44:01 +00:00
|
|
|
return CMD_RET_USAGE;
|
2007-03-31 16:22:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-05-17 02:39:59 +00:00
|
|
|
/****************************************************************************/
|
2007-03-31 16:22:10 +00:00
|
|
|
|
|
|
|
/*
|
2007-05-17 02:39:59 +00:00
|
|
|
* Parse the user's input, partially heuristic. Valid formats:
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
* <0x00112233 4 05> - an array of cells. Numbers follow standard
|
2008-05-20 14:00:29 +00:00
|
|
|
* C conventions.
|
2007-05-17 02:39:59 +00:00
|
|
|
* [00 11 22 .. nn] - byte stream
|
|
|
|
* "string" - If the the value doesn't start with "<" or "[", it is
|
|
|
|
* treated as a string. Note that the quotes are
|
|
|
|
* stripped by the parser before we get the string.
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
* newval: An array of strings containing the new property as specified
|
2008-05-20 14:00:29 +00:00
|
|
|
* on the command line
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
* count: The number of strings in the array
|
|
|
|
* data: A bytestream to be placed in the property
|
|
|
|
* len: The length of the resulting bytestream
|
2007-05-17 02:39:59 +00:00
|
|
|
*/
|
2010-06-28 20:00:46 +00:00
|
|
|
static int fdt_parse_prop(char * const *newval, int count, char *data, int *len)
|
2007-05-17 02:39:59 +00:00
|
|
|
{
|
|
|
|
char *cp; /* temporary char pointer */
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
char *newp; /* temporary newval char pointer */
|
2007-05-17 02:39:59 +00:00
|
|
|
unsigned long tmp; /* holds converted values */
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
int stridx = 0;
|
2007-05-17 02:39:59 +00:00
|
|
|
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
*len = 0;
|
|
|
|
newp = newval[0];
|
|
|
|
|
|
|
|
/* An array of cells */
|
|
|
|
if (*newp == '<') {
|
|
|
|
newp++;
|
|
|
|
while ((*newp != '>') && (stridx < count)) {
|
|
|
|
/*
|
|
|
|
* Keep searching until we find that last ">"
|
|
|
|
* That way users don't have to escape the spaces
|
|
|
|
*/
|
|
|
|
if (*newp == '\0') {
|
|
|
|
newp = newval[++stridx];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = newp;
|
|
|
|
tmp = simple_strtoul(cp, &newp, 0);
|
2017-05-30 13:05:44 +00:00
|
|
|
if (*cp != '?')
|
|
|
|
*(fdt32_t *)data = cpu_to_fdt32(tmp);
|
|
|
|
else
|
|
|
|
newp++;
|
|
|
|
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
data += 4;
|
|
|
|
*len += 4;
|
|
|
|
|
|
|
|
/* If the ptr didn't advance, something went wrong */
|
|
|
|
if ((newp - cp) <= 0) {
|
2007-05-17 02:39:59 +00:00
|
|
|
printf("Sorry, I could not convert \"%s\"\n",
|
|
|
|
cp);
|
|
|
|
return 1;
|
|
|
|
}
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
|
|
|
|
while (*newp == ' ')
|
|
|
|
newp++;
|
2007-05-17 02:39:59 +00:00
|
|
|
}
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
|
|
|
|
if (*newp != '>') {
|
|
|
|
printf("Unexpected character '%c'\n", *newp);
|
2007-05-17 02:39:59 +00:00
|
|
|
return 1;
|
|
|
|
}
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
} else if (*newp == '[') {
|
2007-05-17 02:39:59 +00:00
|
|
|
/*
|
|
|
|
* Byte stream. Convert the values.
|
|
|
|
*/
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
newp++;
|
2009-09-11 20:16:18 +00:00
|
|
|
while ((stridx < count) && (*newp != ']')) {
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
while (*newp == ' ')
|
|
|
|
newp++;
|
2009-09-11 20:16:18 +00:00
|
|
|
if (*newp == '\0') {
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
newp = newval[++stridx];
|
2009-09-11 20:16:18 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!isxdigit(*newp))
|
|
|
|
break;
|
2021-07-24 15:03:29 +00:00
|
|
|
tmp = hextoul(newp, &newp);
|
2009-09-11 20:16:18 +00:00
|
|
|
*data++ = tmp & 0xFF;
|
|
|
|
*len = *len + 1;
|
2007-05-17 02:39:59 +00:00
|
|
|
}
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
if (*newp != ']') {
|
2008-07-07 13:41:14 +00:00
|
|
|
printf("Unexpected character '%c'\n", *newp);
|
2007-05-17 02:39:59 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
2009-09-11 20:16:18 +00:00
|
|
|
* Assume it is one or more strings. Copy it into our
|
|
|
|
* data area for convenience (including the
|
|
|
|
* terminating '\0's).
|
2007-05-17 02:39:59 +00:00
|
|
|
*/
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
while (stridx < count) {
|
2009-09-11 20:16:18 +00:00
|
|
|
size_t length = strlen(newp) + 1;
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
strcpy(data, newp);
|
2009-09-11 20:16:18 +00:00
|
|
|
data += length;
|
|
|
|
*len += length;
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
newp = newval[++stridx];
|
|
|
|
}
|
2007-05-17 02:39:59 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Heuristic to guess if this is a string or concatenated strings.
|
2007-03-31 16:22:10 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static int is_printable_string(const void *data, int len)
|
|
|
|
{
|
|
|
|
const char *s = data;
|
cmd: fdt: Import is_printable_string() from DTC to fix u32 misprint
Import is_printable_string() implementation from DTC 1.7.0 as of
DTC commit 039a994 ("Bump version to v1.7.0") . This fixes a print
of u32 property which so far used to be printed as string by U-Boot
fdt print command.
We might see the case where the parsed property value, in this case
it is a 32-bit integer, identified as a printable string or a null byte
(concatenated strings) because of its last character happens to be:
0x00 (null character), 0xB (vertical tab character) or
0x10 (line feed character)
In this situation, if the string is identified as printable string,
it will be displayed as character instead of hex value
When the isprint() condition is true, there are two possibilities:
1) The character is ASCII character (except the first 32)
2) The character is extended ASCII character
For example,
NG property in device tree:
clock-frequency = <16640000>;
by default, would be displayed as
clock-frequency = "", "ýè";
and with this patch applied, would be displayed as
clock-frequency = <0x00fde800>;
Full investigation was done by Nam and Hai, patch reworked by Marek
to use common code from DTC.
Signed-off-by: Hai Pham <hai.pham.ud@renesas.com>
Signed-off-by: Nam Nguyen <nam.nguyen.yh@renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
2023-03-02 03:08:14 +00:00
|
|
|
const char *ss, *se;
|
2007-03-31 16:22:10 +00:00
|
|
|
|
|
|
|
/* zero length is not */
|
|
|
|
if (len == 0)
|
|
|
|
return 0;
|
|
|
|
|
cmd: fdt: Import is_printable_string() from DTC to fix u32 misprint
Import is_printable_string() implementation from DTC 1.7.0 as of
DTC commit 039a994 ("Bump version to v1.7.0") . This fixes a print
of u32 property which so far used to be printed as string by U-Boot
fdt print command.
We might see the case where the parsed property value, in this case
it is a 32-bit integer, identified as a printable string or a null byte
(concatenated strings) because of its last character happens to be:
0x00 (null character), 0xB (vertical tab character) or
0x10 (line feed character)
In this situation, if the string is identified as printable string,
it will be displayed as character instead of hex value
When the isprint() condition is true, there are two possibilities:
1) The character is ASCII character (except the first 32)
2) The character is extended ASCII character
For example,
NG property in device tree:
clock-frequency = <16640000>;
by default, would be displayed as
clock-frequency = "", "ýè";
and with this patch applied, would be displayed as
clock-frequency = <0x00fde800>;
Full investigation was done by Nam and Hai, patch reworked by Marek
to use common code from DTC.
Signed-off-by: Hai Pham <hai.pham.ud@renesas.com>
Signed-off-by: Nam Nguyen <nam.nguyen.yh@renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
2023-03-02 03:08:14 +00:00
|
|
|
/* must terminate with zero */
|
|
|
|
if (s[len - 1] != '\0')
|
2007-03-31 16:22:10 +00:00
|
|
|
return 0;
|
|
|
|
|
cmd: fdt: Import is_printable_string() from DTC to fix u32 misprint
Import is_printable_string() implementation from DTC 1.7.0 as of
DTC commit 039a994 ("Bump version to v1.7.0") . This fixes a print
of u32 property which so far used to be printed as string by U-Boot
fdt print command.
We might see the case where the parsed property value, in this case
it is a 32-bit integer, identified as a printable string or a null byte
(concatenated strings) because of its last character happens to be:
0x00 (null character), 0xB (vertical tab character) or
0x10 (line feed character)
In this situation, if the string is identified as printable string,
it will be displayed as character instead of hex value
When the isprint() condition is true, there are two possibilities:
1) The character is ASCII character (except the first 32)
2) The character is extended ASCII character
For example,
NG property in device tree:
clock-frequency = <16640000>;
by default, would be displayed as
clock-frequency = "", "ýè";
and with this patch applied, would be displayed as
clock-frequency = <0x00fde800>;
Full investigation was done by Nam and Hai, patch reworked by Marek
to use common code from DTC.
Signed-off-by: Hai Pham <hai.pham.ud@renesas.com>
Signed-off-by: Nam Nguyen <nam.nguyen.yh@renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
2023-03-02 03:08:14 +00:00
|
|
|
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;
|
|
|
|
|
2007-03-31 16:22:10 +00:00
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2007-05-17 02:39:59 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2007-03-31 16:22:10 +00:00
|
|
|
static void print_data(const void *data, int len)
|
|
|
|
{
|
|
|
|
int j;
|
2020-06-19 17:45:55 +00:00
|
|
|
const char *env_max_dump;
|
|
|
|
ulong max_dump = ULONG_MAX;
|
2007-03-31 16:22:10 +00:00
|
|
|
|
|
|
|
/* no data, don't print */
|
|
|
|
if (len == 0)
|
|
|
|
return;
|
|
|
|
|
2020-06-19 17:45:55 +00:00
|
|
|
env_max_dump = env_get("fdt_max_dump");
|
|
|
|
if (env_max_dump)
|
2021-07-24 15:03:29 +00:00
|
|
|
max_dump = hextoul(env_max_dump, NULL);
|
2020-06-19 17:45:55 +00:00
|
|
|
|
2007-03-31 16:22:10 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
if ((len %4) == 0) {
|
2020-06-19 17:45:55 +00:00
|
|
|
if (len > max_dump)
|
2012-10-29 14:53:18 +00:00
|
|
|
printf("* 0x%p [0x%08x]", data, len);
|
2012-08-17 10:34:36 +00:00
|
|
|
else {
|
2012-10-29 13:34:31 +00:00
|
|
|
const __be32 *p;
|
2012-08-17 10:34:36 +00:00
|
|
|
|
|
|
|
printf("<");
|
|
|
|
for (j = 0, p = data; j < len/4; j++)
|
|
|
|
printf("0x%08x%s", fdt32_to_cpu(p[j]),
|
|
|
|
j < (len/4 - 1) ? " " : "");
|
|
|
|
printf(">");
|
|
|
|
}
|
Fix fdt set command to conform to dts spec
The fdt set command was treating properties specified as <00> and <0011>
as byte streams, rather than as an array of cells. As we already have
syntax for expressing the desire for a stream of bytes ([ xx xx ...]),
we should use the <> syntax to describe arrays of cells, which are always
32-bits per element. If we imagine this likely (IMHO) scenario:
> fdt set /ethernet-phy@1 reg <1>
With the old code, this would create a bad fdt, since the reg cell would be
made to be one byte in length. But the cell must be 4 bytes, so this would
break mysteriously.
Also, the dts spec calls for constants inside the angle brackets (<>)
to conform to C constant standards as they pertain to base.
Take this scenario:
> fdt set /ethernet@f00 reg <0xe250000\ 0x1000>
The old fdt command would complain that it couldn't parse that. Or, if you
wanted to specify that a certain clock ran at 33 MHz, you'd be required to
do this:
> fdt set /mydev clock <1f78a40>
Whereas the new code will accept decimal numbers.
While I was in there, I extended the fdt command parser to handle property
strings which are split across multiple arguments:
> fdt set /ethernet@f00 interrupts < 33 2 34 2 36 2 >
> fdt p /ethernet@f00
ethernet@f00 {
interrupts = <0x21 0x2 0x22 0x2 0x24 0x2>;
};
Lastly, the fdt print code was rearranged slightly to print arrays of cells
if the length of the property is a multiple of 4 bytes, and to not print
leading zeros.
Signed-off-by: Andy Fleming <afleming@freescale.com>
2008-04-01 01:45:56 +00:00
|
|
|
} else { /* anything else... hexdump */
|
2020-06-19 17:45:55 +00:00
|
|
|
if (len > max_dump)
|
2012-10-29 14:53:18 +00:00
|
|
|
printf("* 0x%p [0x%08x]", data, len);
|
2012-08-17 10:34:36 +00:00
|
|
|
else {
|
|
|
|
const u8 *s;
|
|
|
|
|
|
|
|
printf("[");
|
|
|
|
for (j = 0, s = data; j < len; j++)
|
|
|
|
printf("%02x%s", s[j], j < len - 1 ? " " : "");
|
|
|
|
printf("]");
|
|
|
|
}
|
2007-03-31 16:22:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-17 02:39:59 +00:00
|
|
|
/****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
2008-06-10 16:06:17 +00:00
|
|
|
* Recursively print (a portion of) the working_fdt. The depth parameter
|
2007-05-17 02:39:59 +00:00
|
|
|
* determines how deeply nested the fdt is printed.
|
|
|
|
*/
|
2007-11-21 20:07:46 +00:00
|
|
|
static int fdt_print(const char *pathp, char *prop, int depth)
|
2007-05-17 02:39:59 +00:00
|
|
|
{
|
|
|
|
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";
|
2007-11-21 20:07:46 +00:00
|
|
|
const void *nodep; /* property node pointer */
|
2007-05-17 02:39:59 +00:00
|
|
|
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 */
|
2007-11-22 22:23:23 +00:00
|
|
|
const struct fdt_property *fdt_prop;
|
2007-05-17 02:39:59 +00:00
|
|
|
|
2008-06-10 16:06:17 +00:00
|
|
|
nodeoffset = fdt_path_offset (working_fdt, pathp);
|
2007-05-17 02:39:59 +00:00
|
|
|
if (nodeoffset < 0) {
|
|
|
|
/*
|
|
|
|
* Not found or something else bad happened.
|
|
|
|
*/
|
2007-10-24 16:04:22 +00:00
|
|
|
printf ("libfdt fdt_path_offset() returned %s\n",
|
2007-05-22 03:27:16 +00:00
|
|
|
fdt_strerror(nodeoffset));
|
2007-05-17 02:39:59 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* The user passed in a property as well as node path.
|
|
|
|
* Print only the given property and then return.
|
|
|
|
*/
|
|
|
|
if (prop) {
|
2008-06-10 16:06:17 +00:00
|
|
|
nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len);
|
2007-05-17 02:39:59 +00:00
|
|
|
if (len == 0) {
|
|
|
|
/* no property value */
|
|
|
|
printf("%s %s\n", pathp, prop);
|
|
|
|
return 0;
|
2017-06-07 16:28:42 +00:00
|
|
|
} else if (nodep && len > 0) {
|
2007-11-24 00:43:20 +00:00
|
|
|
printf("%s = ", prop);
|
2007-05-17 02:39:59 +00:00
|
|
|
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) {
|
2008-06-10 16:06:17 +00:00
|
|
|
tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
|
2007-05-17 02:39:59 +00:00
|
|
|
switch(tag) {
|
|
|
|
case FDT_BEGIN_NODE:
|
2008-06-10 16:06:17 +00:00
|
|
|
pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
|
2007-11-22 22:23:23 +00:00
|
|
|
if (level <= depth) {
|
|
|
|
if (pathp == NULL)
|
|
|
|
pathp = "/* NULL pointer error */";
|
|
|
|
if (*pathp == '\0')
|
|
|
|
pathp = "/"; /* root is nameless */
|
2007-05-17 02:39:59 +00:00
|
|
|
printf("%s%s {\n",
|
|
|
|
&tabs[MAX_LEVEL - level], pathp);
|
2007-11-22 22:23:23 +00:00
|
|
|
}
|
2007-05-17 02:39:59 +00:00
|
|
|
level++;
|
|
|
|
if (level >= MAX_LEVEL) {
|
2007-11-22 22:23:23 +00:00
|
|
|
printf("Nested too deep, aborting.\n");
|
2007-05-17 02:39:59 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FDT_END_NODE:
|
|
|
|
level--;
|
2007-11-22 22:23:23 +00:00
|
|
|
if (level <= depth)
|
2007-05-17 02:39:59 +00:00
|
|
|
printf("%s};\n", &tabs[MAX_LEVEL - level]);
|
|
|
|
if (level == 0) {
|
|
|
|
level = -1; /* exit the loop */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FDT_PROP:
|
2008-06-10 16:06:17 +00:00
|
|
|
fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
|
2007-11-22 22:23:23 +00:00
|
|
|
sizeof(*fdt_prop));
|
2008-06-10 16:06:17 +00:00
|
|
|
pathp = fdt_string(working_fdt,
|
2007-11-22 22:23:23 +00:00
|
|
|
fdt32_to_cpu(fdt_prop->nameoff));
|
|
|
|
len = fdt32_to_cpu(fdt_prop->len);
|
|
|
|
nodep = fdt_prop->data;
|
2007-05-17 02:39:59 +00:00
|
|
|
if (len < 0) {
|
|
|
|
printf ("libfdt fdt_getprop(): %s\n",
|
|
|
|
fdt_strerror(len));
|
|
|
|
return 1;
|
|
|
|
} else if (len == 0) {
|
|
|
|
/* the property has no value */
|
2007-11-22 22:23:23 +00:00
|
|
|
if (level <= depth)
|
2007-05-17 02:39:59 +00:00
|
|
|
printf("%s%s;\n",
|
|
|
|
&tabs[MAX_LEVEL - level],
|
|
|
|
pathp);
|
|
|
|
} else {
|
2007-11-22 22:23:23 +00:00
|
|
|
if (level <= depth) {
|
2007-11-24 00:43:20 +00:00
|
|
|
printf("%s%s = ",
|
2007-05-17 02:39:59 +00:00
|
|
|
&tabs[MAX_LEVEL - level],
|
|
|
|
pathp);
|
|
|
|
print_data (nodep, len);
|
|
|
|
printf(";\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FDT_NOP:
|
2008-07-07 13:41:14 +00:00
|
|
|
printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
|
2007-05-17 02:39:59 +00:00
|
|
|
break;
|
|
|
|
case FDT_END:
|
|
|
|
return 1;
|
|
|
|
default:
|
2007-11-22 22:23:23 +00:00
|
|
|
if (level <= depth)
|
2007-05-17 02:39:59 +00:00
|
|
|
printf("Unknown tag 0x%08X\n", tag);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
nodeoffset = nextoffset;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-03-31 16:22:10 +00:00
|
|
|
/********************************************************************/
|
2012-10-29 13:34:31 +00:00
|
|
|
#ifdef CONFIG_SYS_LONGHELP
|
|
|
|
static char fdt_help_text[] =
|
2022-04-25 16:35:05 +00:00
|
|
|
"addr [-c] [-q] <addr> [<size>] - Set the [control] fdt location to <addr>\n"
|
2016-07-05 08:26:45 +00:00
|
|
|
#ifdef CONFIG_OF_LIBFDT_OVERLAY
|
|
|
|
"fdt apply <addr> - Apply overlay to the DT\n"
|
|
|
|
#endif
|
2007-06-26 03:25:28 +00:00
|
|
|
#ifdef CONFIG_OF_BOARD_SETUP
|
|
|
|
"fdt boardsetup - Do board-specific set up\n"
|
2014-10-24 00:58:54 +00:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_OF_SYSTEM_SETUP
|
|
|
|
"fdt systemsetup - Do system-specific set up\n"
|
2007-06-26 03:25:28 +00:00
|
|
|
#endif
|
2008-01-05 20:33:29 +00:00
|
|
|
"fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n"
|
2016-09-20 16:10:43 +00:00
|
|
|
"fdt resize [<extrasize>] - Resize fdt to size + padding to 4k addr + some optional <extrasize> if needed\n"
|
2007-03-31 16:22:10 +00:00
|
|
|
"fdt print <path> [<prop>] - Recursive print starting at <path>\n"
|
|
|
|
"fdt list <path> [<prop>] - Print one level starting at <path>\n"
|
2022-07-08 21:50:43 +00:00
|
|
|
"fdt get value <var> <path> <prop> [<index>] - Get <property> and store in <var>\n"
|
|
|
|
" In case of stringlist property, use optional <index>\n"
|
|
|
|
" to select string within the stringlist. Default is 0.\n"
|
2012-08-17 10:34:37 +00:00
|
|
|
"fdt get name <var> <path> <index> - Get name of node <index> and store in <var>\n"
|
|
|
|
"fdt get addr <var> <path> <prop> - Get start address of <property> and store in <var>\n"
|
|
|
|
"fdt get size <var> <path> [<prop>] - Get size of [<property>] or num nodes and store in <var>\n"
|
2007-03-31 16:22:10 +00:00
|
|
|
"fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n"
|
|
|
|
"fdt mknode <path> <node> - Create a new node after <path>\n"
|
|
|
|
"fdt rm <path> [<prop>] - Delete the node or <property>\n"
|
2018-11-15 05:06:06 +00:00
|
|
|
"fdt header [get <var> <member>] - Display header info\n"
|
|
|
|
" get - get header member <member> and store it in <var>\n"
|
2008-02-15 09:34:36 +00:00
|
|
|
"fdt bootcpu <id> - Set boot cpuid\n"
|
|
|
|
"fdt memory <addr> <size> - Add/Update memory node\n"
|
|
|
|
"fdt rsvmem print - Show current mem reserves\n"
|
|
|
|
"fdt rsvmem add <addr> <size> - Add a mem reserve\n"
|
|
|
|
"fdt rsvmem delete <index> - Delete a mem reserves\n"
|
2022-03-22 20:59:21 +00:00
|
|
|
"fdt chosen [<start> <size>] - Add/update the /chosen branch in the tree\n"
|
|
|
|
" <start>/<size> - initrd start addr/size\n"
|
2014-03-03 11:19:24 +00:00
|
|
|
#if defined(CONFIG_FIT_SIGNATURE)
|
|
|
|
"fdt checksign [<addr>] - check FIT signature\n"
|
2023-03-02 03:08:20 +00:00
|
|
|
" <addr> - address of key blob\n"
|
|
|
|
" default gd->fdt_blob\n"
|
2014-03-03 11:19:24 +00:00
|
|
|
#endif
|
2016-05-04 08:47:31 +00:00
|
|
|
"NOTE: Dereference aliases by omitting the leading '/', "
|
2012-10-29 13:34:31 +00:00
|
|
|
"e.g. fdt print ethernet0.";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
U_BOOT_CMD(
|
|
|
|
fdt, 255, 0, do_fdt,
|
|
|
|
"flattened device tree utility commands", fdt_help_text
|
2007-03-31 16:22:10 +00:00
|
|
|
);
|