* Pantelis Antoniou <pantelis.antoniou@gmail.com> and
* Matthew McClintock <msm@freescale.com>
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <linux/ctype.h>
#include <linux/types.h>
#include <asm/global_data.h>
-#include <fdt.h>
#include <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 */
*/
DECLARE_GLOBAL_DATA_PTR;
-static int fdt_valid(void);
+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);
*/
struct fdt_header *working_fdt;
-void set_working_fdt_addr(void *addr)
+void set_working_fdt_addr(ulong addr)
{
- char buf[17];
+ void *buf;
- working_fdt = addr;
-
- sprintf(buf, "%lx", (unsigned long)addr);
- setenv("fdtaddr", buf);
+ buf = map_sysmem(addr, 0);
+ working_fdt = buf;
+ setenv_hex("fdtaddr", addr);
}
/*
/*
* Flattened Device Tree command, see the help for parameter definitions.
*/
-int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
if (argc < 2)
return CMD_RET_USAGE;
*/
if (argv[1][0] == 'a') {
unsigned long addr;
+ int control = 0;
+ struct fdt_header *blob;
/*
* Set the address [and length] of the fdt.
*/
- if (argc == 2) {
- if (!fdt_valid()) {
+ 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;
+ else
+ blob = working_fdt;
+ if (!blob || !fdt_valid(&blob))
return 1;
- }
- printf("The address of the fdt is %p\n", working_fdt);
+ printf("The address of the fdt is %#08lx\n",
+ control ? (ulong)map_to_sysmem(blob) :
+ getenv_hex("fdtaddr", 0));
return 0;
}
- addr = simple_strtoul(argv[2], NULL, 16);
- set_working_fdt_addr((void *)addr);
-
- if (!fdt_valid()) {
+ addr = simple_strtoul(argv[0], NULL, 16);
+ blob = map_sysmem(addr, 0);
+ if (!fdt_valid(&blob))
return 1;
- }
+ if (control)
+ gd->fdt_blob = blob;
+ else
+ set_working_fdt_addr(addr);
- if (argc >= 4) {
+ if (argc >= 2) {
int len;
int err;
/*
* Optional new length
*/
- len = simple_strtoul(argv[3], NULL, 16);
- if (len < fdt_totalsize(working_fdt)) {
+ len = simple_strtoul(argv[1], NULL, 16);
+ if (len < fdt_totalsize(blob)) {
printf ("New length %d < existing length %d, "
"ignoring.\n",
- len, fdt_totalsize(working_fdt));
+ len, fdt_totalsize(blob));
} else {
/*
* Open in place with a new length.
*/
- err = fdt_open_into(working_fdt, working_fdt, len);
+ err = fdt_open_into(blob, blob, len);
if (err != 0) {
printf ("libfdt fdt_open_into(): %s\n",
fdt_strerror(err));
* Set the address and length of the fdt.
*/
working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
- if (!fdt_valid()) {
+ if (!fdt_valid(&working_fdt))
return 1;
- }
newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
}
if (subcmd[0] == 's') {
/* get the num nodes at this level */
- char buf[11];
-
- sprintf(buf, "%d", curIndex + 1);
- setenv(var, buf);
+ setenv_ulong(var, curIndex + 1);
} else {
/* node index not found */
printf("libfdt node not found\n");
/* Get address */
char buf[11];
- sprintf(buf, "0x%08X", (uint32_t)nodep);
+ sprintf(buf, "0x%p", nodep);
setenv(var, buf);
} else if (subcmd[0] == 's') {
/* Get size */
}
#ifdef CONFIG_OF_BOARD_SETUP
/* Call the board-specific fixup routine */
- else if (strncmp(argv[1], "boa", 3) == 0)
- ft_board_setup(working_fdt, gd->bd);
+ 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;
+ }
+ }
+#endif
+#ifdef CONFIG_OF_SYSTEM_SETUP
+ /* Call the board-specific fixup routine */
+ else if (strncmp(argv[1], "sys", 3) == 0) {
+ int err = ft_system_setup(working_fdt, gd->bd);
+
+ if (err) {
+ printf("Failed to add system information to FDT: %s\n",
+ fdt_strerror(err));
+ return CMD_RET_FAILURE;
+ }
+ }
#endif
/* Create a chosen node */
- else if (argv[1][0] == 'c') {
+ else if (strncmp(argv[1], "cho", 3) == 0) {
unsigned long initrd_start = 0, initrd_end = 0;
if ((argc != 2) && (argc != 4))
initrd_end = simple_strtoul(argv[3], NULL, 16);
}
- fdt_chosen(working_fdt, 1);
- fdt_initrd(working_fdt, initrd_start, initrd_end, 1);
+ fdt_chosen(working_fdt);
+ fdt_initrd(working_fdt, initrd_start, initrd_end);
+
+#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) {
+ addr = simple_strtoul(argv[2], NULL, 16);
+ 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);
+ if (ret == 0)
+ return CMD_RET_SUCCESS;
+ else
+ return CMD_RET_FAILURE;
+#endif
+
}
/* resize the fdt */
else if (strncmp(argv[1], "re", 2) == 0) {
- fdt_resize(working_fdt);
+ fdt_shrink_to_minimum(working_fdt);
}
else {
/* Unrecognized command */
/****************************************************************************/
-static int fdt_valid(void)
+/**
+ * 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)
{
- int err;
+ const void *blob = *blobp;
+ int err;
- if (working_fdt == NULL) {
+ if (blob == NULL) {
printf ("The address of the fdt is invalid (NULL).\n");
return 0;
}
- err = fdt_check_header(working_fdt);
+ err = fdt_check_header(blob);
if (err == 0)
return 1; /* valid */
* Be more informative on bad version.
*/
if (err == -FDT_ERR_BADVERSION) {
- if (fdt_version(working_fdt) <
+ if (fdt_version(blob) <
FDT_FIRST_SUPPORTED_VERSION) {
printf (" - too old, fdt %d < %d",
- fdt_version(working_fdt),
+ fdt_version(blob),
FDT_FIRST_SUPPORTED_VERSION);
- working_fdt = NULL;
}
- if (fdt_last_comp_version(working_fdt) >
+ if (fdt_last_comp_version(blob) >
FDT_LAST_SUPPORTED_VERSION) {
printf (" - too new, fdt %d > %d",
- fdt_version(working_fdt),
+ fdt_version(blob),
FDT_LAST_SUPPORTED_VERSION);
- working_fdt = NULL;
}
- return 0;
}
printf("\n");
+ *blobp = NULL;
return 0;
}
return 1;
cp = newp;
tmp = simple_strtoul(cp, &newp, 0);
- *(uint32_t *)data = __cpu_to_be32(tmp);
+ *(__be32 *)data = __cpu_to_be32(tmp);
data += 4;
*len += 4;
if ((len %4) == 0) {
if (len > CONFIG_CMD_FDT_MAX_DUMP)
- printf("* 0x%08x [0x%08x]", (unsigned int)data, len);
+ printf("* 0x%p [0x%08x]", data, len);
else {
- const u32 *p;
+ const __be32 *p;
printf("<");
for (j = 0, p = data; j < len/4; j++)
}
} else { /* anything else... hexdump */
if (len > CONFIG_CMD_FDT_MAX_DUMP)
- printf("* 0x%08x [0x%08x]", (unsigned int)data, len);
+ printf("* 0x%p [0x%08x]", data, len);
else {
const u8 *s;
}
/********************************************************************/
-
-U_BOOT_CMD(
- fdt, 255, 0, do_fdt,
- "flattened device tree utility commands",
- "addr <addr> [<length>] - Set the fdt location to <addr>\n"
+#ifdef CONFIG_SYS_LONGHELP
+static char fdt_help_text[] =
+ "addr [-c] <addr> [<length>] - Set the [control] fdt location to <addr>\n"
#ifdef CONFIG_OF_BOARD_SETUP
"fdt boardsetup - Do board-specific set up\n"
+#endif
+#ifdef CONFIG_OF_SYSTEM_SETUP
+ "fdt systemsetup - Do system-specific set up\n"
#endif
"fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n"
"fdt resize - Resize fdt to size + padding to 4k addr\n"
"fdt rsvmem delete <index> - Delete a mem reserves\n"
"fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n"
" <start>/<end> - initrd start/end addr\n"
+#if defined(CONFIG_FIT_SIGNATURE)
+ "fdt checksign [<addr>] - check FIT signature\n"
+ " <start> - addr of key blob\n"
+ " default gd->fdt_blob\n"
+#endif
"NOTE: Dereference aliases by omiting the leading '/', "
- "e.g. fdt print ethernet0."
+ "e.g. fdt print ethernet0.";
+#endif
+
+U_BOOT_CMD(
+ fdt, 255, 0, do_fdt,
+ "flattened device tree utility commands", fdt_help_text
);