+// SPDX-License-Identifier: GPL-2.0+
/*
* (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>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <command.h>
+#include <env.h>
+#include <image.h>
#include <linux/ctype.h>
#include <linux/types.h>
#include <asm/global_data.h>
-#include <libfdt.h>
+#include <linux/libfdt.h>
#include <fdt_support.h>
#include <mapmem.h>
#include <asm/io.h>
#define MAX_LEVEL 32 /* how deeply nested we will go */
#define SCRATCHPAD 1024 /* bytes of scratchpad memory */
-#define CMD_FDT_MAX_DUMP 64
/*
* Global data (for the gd->bd)
*/
DECLARE_GLOBAL_DATA_PTR;
-static int fdt_valid(struct fdt_header **blobp);
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);
buf = map_sysmem(addr, 0);
working_fdt = buf;
- setenv_hex("fdtaddr", addr);
+ env_set_hex("fdtaddr", addr);
}
/*
return 0;
}
+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",
+};
+
+static int fdt_get_header_value(int argc, char *const argv[])
+{
+ 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;
+}
+
/*
* Flattened Device Tree command, see the help for parameter definitions.
*/
-static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
if (argc < 2)
return CMD_RET_USAGE;
- /*
- * Set the address of the fdt
- */
+ /* fdt addr: Set the address of the fdt */
if (strncmp(argv[1], "ad", 2) == 0) {
unsigned long addr;
int control = 0;
struct fdt_header *blob;
- /*
- * Set the address [and length] of the fdt.
- */
+
+ /* Set the address [and length] of the fdt */
argc -= 2;
argv += 2;
-/* Temporary #ifdef - some archs don't have fdt_blob yet */
-#ifdef CONFIG_OF_CONTROL
if (argc && !strcmp(*argv, "-c")) {
control = 1;
argc--;
argv++;
}
-#endif
if (argc == 0) {
if (control)
blob = (struct fdt_header *)gd->fdt_blob;
blob = working_fdt;
if (!blob || !fdt_valid(&blob))
return 1;
- printf("The address of the fdt is %#08lx\n",
+ printf("%s fdt: %08lx\n",
+ control ? "Control" : "Working",
control ? (ulong)map_to_sysmem(blob) :
- getenv_hex("fdtaddr", 0));
+ env_get_hex("fdtaddr", 0));
return 0;
}
- addr = simple_strtoul(argv[0], NULL, 16);
+ addr = hextoul(argv[0], NULL);
blob = map_sysmem(addr, 0);
if (!fdt_valid(&blob))
return 1;
if (argc >= 2) {
int len;
int err;
- /*
- * Optional new length
- */
- len = simple_strtoul(argv[1], NULL, 16);
+
+ /* Optional new length */
+ len = hextoul(argv[1], NULL);
if (len < fdt_totalsize(blob)) {
- printf ("New length %d < existing length %d, "
- "ignoring.\n",
- len, fdt_totalsize(blob));
+ printf("New length %d < existing length %d, ignoring\n",
+ len, fdt_totalsize(blob));
} else {
- /*
- * Open in place with a new length.
- */
+ /* Open in place with a new length */
err = fdt_open_into(blob, blob, len);
if (err != 0) {
- printf ("libfdt fdt_open_into(): %s\n",
- fdt_strerror(err));
+ printf("libfdt fdt_open_into(): %s\n",
+ fdt_strerror(err));
}
}
}
}
if (!working_fdt) {
- puts(
- "No FDT memory address configured. Please configure\n"
- "the FDT address via \"fdt addr <address>\" command.\n"
- "Aborting!\n");
+ puts("No FDT memory address configured. Please configure\n"
+ "the FDT address via \"fdt addr <address>\" command.\n"
+ "Aborting!\n");
return CMD_RET_FAILURE;
}
/*
* Set the address and length of the fdt.
*/
- working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
+ working_fdt = (struct fdt_header *)hextoul(argv[2], NULL);
if (!fdt_valid(&working_fdt))
return 1;
- newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
+ newaddr = (struct fdt_header *)hextoul(argv[3], NULL);
/*
* If the user specifies a length, use that. Otherwise use the
if (argc <= 4) {
len = fdt_totalsize(working_fdt);
} else {
- len = simple_strtoul(argv[4], NULL, 16);
+ len = hextoul(argv[4], NULL);
if (len < fdt_totalsize(working_fdt)) {
printf ("New length 0x%X < existing length "
"0x%X, aborting.\n",
fdt_strerror(err));
return 1;
}
- working_fdt = newaddr;
+ set_working_fdt_addr((ulong)newaddr);
#ifdef CONFIG_OF_SYSTEM_SETUP
/* Call the board-specific fixup routine */
} else if (strncmp(argv[1], "sys", 3) == 0) {
/*
* Set the value of a property in the working_fdt.
*/
- } else if (argv[1][0] == 's') {
+ } else if (strncmp(argv[1], "se", 2) == 0) {
char *pathp; /* path */
char *prop; /* property */
int nodeoffset; /* node offset from libfdt */
- static char data[SCRATCHPAD]; /* storage for the property */
+ static char data[SCRATCHPAD] __aligned(4);/* property storage */
const void *ptmp;
int len; /* new length of the property */
int ret; /* return value */
len = 0;
} else {
ptmp = fdt_getprop(working_fdt, nodeoffset, prop, &len);
- if (!ptmp) {
- printf("prop (%s) not found!\n", prop);
- return 1;
- }
if (len > SCRATCHPAD) {
printf("prop (%d) doesn't fit in scratchpad!\n",
len);
return 1;
}
- memcpy(data, ptmp, len);
+ if (ptmp != NULL)
+ memcpy(data, ptmp, len);
+
ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
if (ret != 0)
return ret;
}
if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) {
- int reqIndex = -1;
+ int req_index = -1;
int startDepth = fdt_node_depth(
working_fdt, nodeoffset);
int curDepth = startDepth;
- int curIndex = -1;
+ int cur_index = -1;
int nextNodeOffset = fdt_next_node(
working_fdt, nodeoffset, &curDepth);
if (subcmd[0] == 'n')
- reqIndex = simple_strtoul(argv[5], NULL, 16);
+ req_index = hextoul(argv[5], NULL);
while (curDepth > startDepth) {
if (curDepth == startDepth + 1)
- curIndex++;
- if (subcmd[0] == 'n' && curIndex == reqIndex) {
+ cur_index++;
+ if (subcmd[0] == 'n' &&
+ cur_index == req_index) {
const char *node_name;
node_name = fdt_get_name(working_fdt,
}
if (subcmd[0] == 's') {
/* get the num nodes at this level */
- setenv_ulong(var, curIndex + 1);
+ env_set_ulong(var, cur_index + 1);
} else {
/* node index not found */
printf("libfdt node not found\n");
* Display header info
*/
} else if (argv[1][0] == 'h') {
+ if (argc == 5)
+ return fdt_get_header_value(argc, argv);
+
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),
* Set boot cpu id
*/
} else if (strncmp(argv[1], "boo", 3) == 0) {
- unsigned long tmp = simple_strtoul(argv[2], NULL, 16);
+ unsigned long tmp = hextoul(argv[2], NULL);
fdt_set_boot_cpuid_phys(working_fdt, tmp);
/*
return err;
}
} else if (argv[2][0] == 'd') {
- unsigned long idx = simple_strtoul(argv[3], NULL, 16);
+ unsigned long idx = hextoul(argv[3], NULL);
int err = fdt_del_mem_rsv(working_fdt, idx);
if (err < 0) {
fdt_strerror(err));
return CMD_RET_FAILURE;
}
+#ifdef CONFIG_ARCH_KEYSTONE
+ ft_board_setup_ex(working_fdt, gd->bd);
+#endif
}
#endif
/* Create a chosen node */
return CMD_RET_USAGE;
if (argc == 4) {
- initrd_start = simple_strtoul(argv[2], NULL, 16);
- initrd_end = simple_strtoul(argv[3], NULL, 16);
+ initrd_start = hextoul(argv[2], NULL);
+ initrd_end = hextoul(argv[3], NULL);
}
fdt_chosen(working_fdt);
return CMD_RET_FAILURE;
if (argc > 2) {
- addr = simple_strtoul(argv[2], NULL, 16);
+ addr = hextoul(argv[2], NULL);
blob = map_sysmem(addr, 0);
} else {
blob = (struct fdt_header *)gd->fdt_blob;
if (!working_fdt)
return CMD_RET_FAILURE;
- addr = simple_strtoul(argv[2], NULL, 16);
+ addr = hextoul(argv[2], NULL);
blob = map_sysmem(addr, 0);
if (!fdt_valid(&blob))
return CMD_RET_FAILURE;
- ret = fdt_overlay_apply(working_fdt, blob);
- if (ret) {
- printf("fdt_overlay_apply(): %s\n", fdt_strerror(ret));
+ /* apply method prints messages on error */
+ ret = fdt_overlay_apply_verbose(working_fdt, blob);
+ if (ret)
return CMD_RET_FAILURE;
- }
}
#endif
/* resize the fdt */
else if (strncmp(argv[1], "re", 2) == 0) {
uint extrasize;
if (argc > 2)
- extrasize = simple_strtoul(argv[2], NULL, 16);
+ extrasize = hextoul(argv[2], NULL);
else
extrasize = 0;
fdt_shrink_to_minimum(working_fdt, extrasize);
/****************************************************************************/
-/**
- * fdt_valid() - Check if an FDT is valid. If not, change it to NULL
- *
- * @blobp: Pointer to FDT pointer
- * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL)
- */
-static int fdt_valid(struct fdt_header **blobp)
-{
- const void *blob = *blobp;
- int err;
-
- if (blob == NULL) {
- printf ("The address of the fdt is invalid (NULL).\n");
- return 0;
- }
-
- err = fdt_check_header(blob);
- if (err == 0)
- return 1; /* valid */
-
- if (err < 0) {
- printf("libfdt fdt_check_header(): %s", fdt_strerror(err));
- /*
- * Be more informative on bad version.
- */
- if (err == -FDT_ERR_BADVERSION) {
- if (fdt_version(blob) <
- FDT_FIRST_SUPPORTED_VERSION) {
- printf (" - too old, fdt %d < %d",
- fdt_version(blob),
- FDT_FIRST_SUPPORTED_VERSION);
- }
- if (fdt_last_comp_version(blob) >
- FDT_LAST_SUPPORTED_VERSION) {
- printf (" - too new, fdt %d > %d",
- fdt_version(blob),
- FDT_LAST_SUPPORTED_VERSION);
- }
- }
- printf("\n");
- *blobp = NULL;
- return 0;
- }
- return 1;
-}
-
-/****************************************************************************/
-
/*
* Parse the user's input, partially heuristic. Valid formats:
* <0x00112233 4 05> - an array of cells. Numbers follow standard
}
if (!isxdigit(*newp))
break;
- tmp = simple_strtoul(newp, &newp, 16);
+ tmp = hextoul(newp, &newp);
*data++ = tmp & 0xFF;
*len = *len + 1;
}
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 ((len %4) == 0) {
- if (len > CMD_FDT_MAX_DUMP)
+ if (len > max_dump)
printf("* 0x%p [0x%08x]", data, len);
else {
const __be32 *p;
printf(">");
}
} else { /* anything else... hexdump */
- if (len > CMD_FDT_MAX_DUMP)
+ if (len > max_dump)
printf("* 0x%p [0x%08x]", data, len);
else {
const u8 *s;
"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"
- "fdt header - Display header info\n"
+ "fdt header [get <var> <member>] - Display header info\n"
+ " get - get header member <member> and store it in <var>\n"
"fdt bootcpu <id> - Set boot cpuid\n"
"fdt memory <addr> <size> - Add/Update memory node\n"
"fdt rsvmem print - Show current mem reserves\n"