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>
*
* 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
*/
#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>
#define MAX_LEVEL 32 /* how deeply nested we will go */
Gerald Van Baren
committed
#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(void *addr)
{
void *buf;
buf = map_sysmem((ulong)addr, 0);
working_fdt = buf;
setenv_addr("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", *(uint32_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[])
return CMD_RET_USAGE;
* Set the address of the fdt
unsigned long addr;
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))
return 1;
printf("The address of the fdt is %#08lx\n",
control ? (ulong)blob :
getenv_hex("fdtaddr", 0));
return 0;
}
addr = simple_strtoul(argv[0], NULL, 16);
if (!fdt_valid(&blob))
if (control)
gd->fdt_blob = blob;
else
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;
}
if (strncmp(argv[1], "mo", 2) == 0) {
struct fdt_header *newaddr;
int len;
int err;
return CMD_RET_USAGE;
/*
* Set the address and length of the fdt.
*/
working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
/*
* If the user specifies a length, use that. Otherwise use the
* current length.
Loading
Loading full blame...