Skip to content
Snippets Groups Projects
fdt.c 26.9 KiB
Newer Older
/*
 * (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 <linux/ctype.h>
#include <linux/types.h>
#include <asm/global_data.h>
#include <libfdt.h>
#include <fdt_support.h>
#include <asm/io.h>

#define MAX_LEVEL	32		/* how deeply nested we will go */
#define SCRATCHPAD	1024		/* bytes of scratchpad memory */
#ifndef CONFIG_CMD_FDT_MAX_DUMP
#define CONFIG_CMD_FDT_MAX_DUMP 64
#endif

/*
 * 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);
/*
 * The working_fdt points to our working flattened device tree.
 */
struct fdt_header *working_fdt;

void set_working_fdt_addr(ulong addr)
	buf = map_sysmem(addr, 0);
	working_fdt = buf;
	setenv_hex("fdtaddr", addr);
/*
 * Get a value from the fdt and format it to be set in the environment
 */
static int fdt_value_setenv(const void *nodep, int len, const char *var)
{
	if (is_printable_string(nodep, len))
		setenv(var, (void *)nodep);
	else if (len == 4) {
		char buf[11];

		sprintf(buf, "0x%08X", fdt32_to_cpu(*(fdt32_t *)nodep));
		setenv(var, buf);
	} 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));
		setenv(var, buf);
	} else {
		printf("error: unprintable value\n");
		return 1;
	}
	return 0;
}

/*
 * 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[])
	 * Set the address of the fdt
	if (strncmp(argv[1], "ad", 2) == 0) {
		int control = 0;
		struct fdt_header *blob;
		/*
		 * 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;
			else
				blob = working_fdt;
			if (!blob || !fdt_valid(&blob))
			printf("The address of the fdt is %#08lx\n",
			       control ? (ulong)map_to_sysmem(blob) :
					getenv_hex("fdtaddr", 0));
		addr = simple_strtoul(argv[0], NULL, 16);
		blob = map_sysmem(addr, 0);
		if (!fdt_valid(&blob))
		if (control)
			gd->fdt_blob = blob;
		else
			set_working_fdt_addr(addr);
			int  len;
			int  err;
			/*
			 * Optional new length
			 */
			len = simple_strtoul(argv[1], NULL, 16);
			if (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.
				 */
				err = fdt_open_into(blob, blob, len);
					printf ("libfdt fdt_open_into(): %s\n",
						fdt_strerror(err));
		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;
	}

	 * Move the working_fdt
	if (strncmp(argv[1], "mo", 2) == 0) {
		struct fdt_header *newaddr;
		int  len;
		int  err;


		/*
		 * Set the address and length of the fdt.
		 */
		working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
		if (!fdt_valid(&working_fdt))
		newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);

		/*
		 * If the user specifies a length, use that.  Otherwise use the
		 * current length.
		 */
		if (argc <= 4) {
			len = fdt_totalsize(working_fdt);
		} else {
			len = simple_strtoul(argv[4], NULL, 16);
			if (len < fdt_totalsize(working_fdt)) {
				printf ("New length 0x%X < existing length "
					"0x%X, aborting.\n",
					len, fdt_totalsize(working_fdt));
Loading
Loading full blame...