@ -37,46 +37,32 @@
# include <fdt_support.h>
# define MAX_LEVEL 32 /* how deeply nested we will go */
# define SCRATCHPAD 1024 /* bytes of scratchpad memory */
# define SCRATCHPAD 1024 /* bytes of scratchpad memory */
/*
* Global data ( for the gd - > bd )
*/
DECLARE_GLOBAL_DATA_PTR ;
/*
* Scratchpad memory .
*/
static char data [ SCRATCHPAD ] ;
/*
* Function prototypes / declarations .
*/
static int fdt_valid ( void ) ;
static void print_data ( const void * data , int len ) ;
static int fdt_parse_prop ( char * pathp , char * prop , char * newval ,
char * data , int * len ) ;
static int fdt_print ( char * pathp , char * prop , int depth ) ;
/*
* Flattened Device Tree command , see the help for parameter definitions .
*/
int do_fdt ( cmd_tbl_t * cmdtp , int flag , int argc , char * argv [ ] )
{
char op ;
if ( argc < 2 ) {
printf ( " Usage: \n %s \n " , cmdtp - > usage ) ;
return 1 ;
}
/*
* Figure out which subcommand was given
*/
op = argv [ 1 ] [ 0 ] ;
/********************************************************************
* Set the address of the fdt
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
if ( op = = ' a ' ) {
if ( argv [ 1 ] [ 0 ] = = ' a ' ) {
/*
* Set the address [ and length ] of the fdt .
*/
@ -94,7 +80,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
*/
len = simple_strtoul ( argv [ 3 ] , NULL , 16 ) ;
if ( len < fdt_totalsize ( fdt ) ) {
printf ( " New length %d < existing length %d, ignoring. \n " ,
printf ( " New length %d < existing length %d, "
" ignoring. \n " ,
len , fdt_totalsize ( fdt ) ) ;
} else {
/*
@ -102,7 +89,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
*/
err = fdt_open_into ( fdt , fdt , len ) ;
if ( err ! = 0 ) {
printf ( " libfdt: %s \n " , fdt_strerror ( err ) ) ;
printf ( " libfdt fdt_open_into(): %s \n " ,
fdt_strerror ( err ) ) ;
}
}
}
@ -110,12 +98,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
/********************************************************************
* Move the fdt
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else if ( op = = ' m ' ) {
} else if ( ( argv [ 1 ] [ 0 ] = = ' m ' ) & & ( argv [ 1 ] [ 1 ] = = ' o ' ) ) {
struct fdt_header * newaddr ;
int len ;
int err ;
if ( argc ! = 5 ) {
if ( argc < 4 ) {
printf ( " Usage: \n %s \n " , cmdtp - > usage ) ;
return 1 ;
}
@ -128,12 +116,22 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
return 1 ;
}
newaddr = ( struct fdt_header * ) simple_strtoul ( argv [ 3 ] , NULL , 16 ) ;
len = simple_strtoul ( argv [ 4 ] , NULL , 16 ) ;
if ( len < fdt_totalsize ( fdt ) ) {
printf ( " New length %d < existing length %d, aborting. \n " ,
len , fdt_totalsize ( fdt ) ) ;
return 1 ;
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 ( fdt ) ;
} else {
len = simple_strtoul ( argv [ 4 ] , NULL , 16 ) ;
if ( len < fdt_totalsize ( fdt ) ) {
printf ( " New length 0x%X < existing length "
" 0x%X, aborting. \n " ,
len , fdt_totalsize ( fdt ) ) ;
return 1 ;
}
}
/*
@ -141,26 +139,59 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
*/
err = fdt_open_into ( fdt , newaddr , len ) ;
if ( err ! = 0 ) {
printf ( " libfdt: %s \n " , fdt_strerror ( err ) ) ;
printf ( " libfdt fdt_open_into(): %s \n " ,
fdt_strerror ( err ) ) ;
return 1 ;
}
fdt = newaddr ;
/********************************************************************
* Set the value of a node in the fdt .
* Make a new node
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else if ( ( argv [ 1 ] [ 0 ] = = ' m ' ) & & ( argv [ 1 ] [ 1 ] = = ' k ' ) ) {
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 .
*/
if ( argc < 4 ) {
printf ( " Usage: \n %s \n " , cmdtp - > usage ) ;
return 1 ;
}
pathp = argv [ 2 ] ;
nodep = argv [ 3 ] ;
nodeoffset = fdt_find_node_by_path ( fdt , pathp ) ;
if ( nodeoffset < 0 ) {
/*
* Not found or something else bad happened .
*/
printf ( " libfdt fdt_find_node_by_path() returned %s \n " ,
fdt_strerror ( nodeoffset ) ) ;
return 1 ;
}
err = fdt_add_subnode ( fdt , nodeoffset , nodep ) ;
if ( err < 0 ) {
printf ( " libfdt fdt_add_subnode(): %s \n " ,
fdt_strerror ( err ) ) ;
return 1 ;
}
/********************************************************************
* Set the value of a property in the fdt .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else if ( op = = ' s ' ) {
} else if ( argv [ 1 ] [ 0 ] = = ' s ' ) {
char * pathp ; /* path */
char * prop ; /* property */
struct fdt_property * nodep ; /* node struct pointer */
char * prop ; /* property */
char * newval ; /* value from the user (as a string) */
char * vp ; /* temporary value pointer */
char * cp ; /* temporary char pointer */
int nodeoffset ; /* node offset from libfdt */
int len ; /* new length of the property */
int oldlen ; /* original length of the property */
unsigned long tmp ; /* holds converted values */
int ret ; /* return value */
static char data [ SCRATCHPAD ] ; /* storage for the property */
int len ; /* new length of the property */
int ret ; /* return value */
/*
* Parameters : Node path , property , value .
@ -174,121 +205,38 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
prop = argv [ 3 ] ;
newval = argv [ 4 ] ;
if ( strcmp ( pathp , " / " ) = = 0 ) {
nodeoffset = 0 ;
} else {
nodeoffset = fdt_path_offset ( fdt , pathp ) ;
if ( nodeoffset < 0 ) {
/*
* Not found or something else bad happened .
*/
printf ( " libfdt: %s \n " , fdt_strerror ( nodeoffset ) ) ;
return 1 ;
}
}
nodep = fdt_getprop ( fdt , nodeoffset , prop , & oldlen ) ;
if ( oldlen < 0 ) {
printf ( " libfdt %s \n " , fdt_strerror ( oldlen ) ) ;
return 1 ;
} else if ( oldlen = = 0 ) {
nodeoffset = fdt_find_node_by_path ( fdt , pathp ) ;
if ( nodeoffset < 0 ) {
/*
* The specified property has no value
* Not found or something else bad happened .
*/
printf ( " %s has no value, cannot set one (yet). \n " , prop ) ;
printf ( " libfdt fdt_find_node_by_path() returned %s \n " ,
fdt_strerror ( nodeoffset ) ) ;
return 1 ;
} else {
/*
* Convert the new property
*/
vp = data ;
if ( * newval = = ' < ' ) {
/*
* Bigger values than bytes .
*/
len = 0 ;
newval + + ;
while ( ( * newval ! = ' > ' ) & & ( * newval ! = ' \0 ' ) ) {
cp = newval ;
tmp = simple_strtoul ( cp , & newval , 16 ) ;
if ( ( newval - cp ) < = 2 ) {
* vp = tmp & 0xFF ;
vp + = 1 ;
len + = 1 ;
} else if ( ( newval - cp ) < = 4 ) {
* ( uint16_t * ) vp = __cpu_to_be16 ( tmp ) ;
vp + = 2 ;
len + = 2 ;
} else if ( ( newval - cp ) < = 8 ) {
* ( uint32_t * ) vp = __cpu_to_be32 ( tmp ) ;
vp + = 4 ;
len + = 4 ;
} else {
printf ( " Sorry, I could not convert \" %s \" \n " , cp ) ;
return 1 ;
}
while ( * newval = = ' ' )
newval + + ;
}
if ( * newval ! = ' > ' ) {
printf ( " Unexpected character '%c' \n " , * newval ) ;
return 1 ;
}
} else if ( * newval = = ' [ ' ) {
/*
* Byte stream . Convert the values .
*/
len = 0 ;
newval + + ;
while ( ( * newval ! = ' ] ' ) & & ( * newval ! = ' \0 ' ) ) {
tmp = simple_strtoul ( newval , & newval , 16 ) ;
* vp + + = tmp & 0xFF ;
len + + ;
while ( * newval = = ' ' )
newval + + ;
}
if ( * newval ! = ' ] ' ) {
printf ( " Unexpected character '%c' \n " , * newval ) ;
return 1 ;
}
} else {
/*
* Assume it is a string . Copy it into our data area for
* convenience ( including the terminating ' \0 ' ) .
*/
len = strlen ( newval ) + 1 ;
strcpy ( data , newval ) ;
}
}
ret = fdt_parse_prop ( pathp , prop , newval , data , & len ) ;
if ( ret ! = 0 )
return ret ;
ret = fdt_setprop ( fdt , nodeoffset , prop , data , len ) ;
if ( ret < 0 ) {
printf ( " libfdt %s \n " , fdt_strerror ( ret ) ) ;
return 1 ;
}
ret = fdt_setprop ( fdt , nodeoffset , prop , data , len ) ;
if ( ret < 0 ) {
printf ( " libfdt fdt_setprop(): %s \n " , fdt_strerror ( ret ) ) ;
return 1 ;
}
/********************************************************************
* Print ( recursive ) / List ( single level )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else if ( ( op = = ' p ' ) | | ( op = = ' l ' ) ) {
/*
* Recursively print ( a portion of ) the fdt .
*/
static int offstack [ MAX_LEVEL ] ;
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 " ;
} else if ( ( argv [ 1 ] [ 0 ] = = ' p ' ) | | ( argv [ 1 ] [ 0 ] = = ' l ' ) ) {
int depth = MAX_LEVEL ; /* how deep to print */
char * pathp ; /* path */
char * prop ; /* property */
void * nodep ; /* property node pointer */
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 */
char * prop ; /* property */
int ret ; /* return value */
/*
* list is an alias for print , but limited to 1 level
*/
if ( op = = ' l ' ) {
if ( argv [ 1 ] [ 0 ] = = ' l ' ) {
depth = 1 ;
}
@ -302,99 +250,14 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
else
prop = NULL ;
if ( strcmp ( pathp , " / " ) = = 0 ) {
nodeoffset = 0 ;
printf ( " / " ) ;
} else {
nodeoffset = fdt_path_offset ( fdt , pathp ) ;
if ( nodeoffset < 0 ) {
/*
* Not found or something else bad happened .
*/
printf ( " libfdt %s \n " , fdt_strerror ( nodeoffset ) ) ;
return 1 ;
}
}
/*
* The user passed in a property as well as node path . Print only
* the given property and then return .
*/
if ( prop ) {
nodep = fdt_getprop ( fdt , nodeoffset , prop , & len ) ;
if ( len = = 0 ) {
printf ( " %s %s \n " , pathp , prop ) ; /* no property value */
return 0 ;
} else if ( len > 0 ) {
printf ( " %s= " , prop ) ;
print_data ( nodep , len ) ;
printf ( " \n " ) ;
return 0 ;
} else {
printf ( " libfdt %s \n " , fdt_strerror ( len ) ) ;
return 1 ;
}
}
/*
* The user passed in a node path and no property , print the node
* and all subnodes .
*/
offstack [ 0 ] = nodeoffset ;
while ( level > = 0 ) {
tag = fdt_next_tag ( fdt , nodeoffset , & nextoffset , & pathp ) ;
switch ( tag ) {
case FDT_BEGIN_NODE :
if ( level < = depth )
printf ( " %s%s { \n " , & tabs [ MAX_LEVEL - level ] , pathp ) ;
level + + ;
offstack [ level ] = nodeoffset ;
if ( level > = MAX_LEVEL ) {
printf ( " Aaaiii <splat> nested too deep. \n " ) ;
return 1 ;
}
break ;
case FDT_END_NODE :
level - - ;
if ( level < = depth )
printf ( " %s}; \n " , & tabs [ MAX_LEVEL - level ] ) ;
if ( level = = 0 ) {
level = - 1 ; /* exit the loop */
}
break ;
case FDT_PROP :
nodep = fdt_getprop ( fdt , offstack [ level ] , pathp , & len ) ;
if ( len < 0 ) {
printf ( " libfdt %s \n " , fdt_strerror ( len ) ) ;
return 1 ;
} else if ( len = = 0 ) {
/* the property has no value */
if ( level < = depth )
printf ( " %s%s; \n " , & tabs [ MAX_LEVEL - level ] , pathp ) ;
} else {
if ( level < = depth ) {
printf ( " %s%s= " , & tabs [ MAX_LEVEL - level ] , pathp ) ;
print_data ( nodep , len ) ;
printf ( " ; \n " ) ;
}
}
break ;
case FDT_NOP :
break ;
case FDT_END :
return 1 ;
default :
if ( level < = depth )
printf ( " Unknown tag 0x%08X \n " , tag ) ;
return 1 ;
}
nodeoffset = nextoffset ;
}
ret = fdt_print ( pathp , prop , depth ) ;
if ( ret ! = 0 )
return ret ;
/********************************************************************
* Remove a property / node
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else if ( op = = ' r ' ) {
} else if ( argv [ 1 ] [ 0 ] = = ' r ' ) {
int nodeoffset ; /* node offset from libfdt */
int err ;
@ -402,17 +265,14 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
* Get the path . The root node is an oddball , the offset
* is zero and has no name .
*/
if ( strcmp ( argv [ 2 ] , " / " ) = = 0 ) {
nodeoffset = 0 ;
} else {
nodeoffset = fdt_path_offset ( fdt , argv [ 2 ] ) ;
if ( nodeoffset < 0 ) {
/*
* Not found or something else bad happened .
*/
printf ( " libfdt %s \n " , fdt_strerror ( nodeoffset ) ) ;
return 1 ;
}
nodeoffset = fdt_find_node_by_path ( fdt , argv [ 2 ] ) ;
if ( nodeoffset < 0 ) {
/*
* Not found or something else bad happened .
*/
printf ( " libfdt fdt_find_node_by_path() returned %s \n " ,
fdt_strerror ( nodeoffset ) ) ;
return 1 ;
}
/*
* Do the delete . A fourth parameter means delete a property ,
@ -421,39 +281,40 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
if ( argc > 3 ) {
err = fdt_delprop ( fdt , nodeoffset , argv [ 3 ] ) ;
if ( err < 0 ) {
printf ( " fdt_delprop libfdt: %s \n " , fdt_strerror ( err ) ) ;
printf ( " libfdt fdt_delprop(): %s \n " ,
fdt_strerror ( err ) ) ;
return err ;
}
} else {
err = fdt_del_node ( fdt , nodeoffset ) ;
if ( err < 0 ) {
printf ( " fdt_del_node libfdt: %s \n " , fdt_strerror ( err ) ) ;
printf ( " libfdt fdt_del_node(): %s \n " ,
fdt_strerror ( err ) ) ;
return err ;
}
}
/********************************************************************
* Create a chosen node
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else if ( op = = ' c ' ) {
}
# ifdef CONFIG_OF_BOARD_SETUP
/* Call the board-specific fixup routine */
else if ( argv [ 1 ] [ 0 ] = = ' b ' )
ft_board_setup ( fdt , gd - > bd ) ;
# endif
/* Create a chosen node */
else if ( argv [ 1 ] [ 0 ] = = ' c ' )
fdt_chosen ( fdt , 0 , 0 , 1 ) ;
/********************************************************************
* Create a u - boot - env node
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else if ( op = = ' e ' ) {
# ifdef CONFIG_OF_HAS_UBOOT_ENV
/* Create a u-boot-env node */
else if ( argv [ 1 ] [ 0 ] = = ' e ' )
fdt_env ( fdt ) ;
/********************************************************************
* Create a bd_t node
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else if ( op = = ' b ' ) {
# endif
# ifdef CONFIG_OF_HAS_BD_T
/* Create a bd_t node */
else if ( argv [ 1 ] [ 0 ] = = ' b ' )
fdt_bd_t ( fdt ) ;
/********************************************************************
* Unrecognized command
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else {
# endif
else {
/* Unrecognized command */
printf ( " Usage: \n %s \n " , cmdtp - > usage ) ;
return 1 ;
}
@ -461,7 +322,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
return 0 ;
}
/********************************************************************/
/**************************************************************************** /
static int fdt_valid ( void )
{
@ -477,19 +338,21 @@ static int fdt_valid(void)
return 1 ; /* valid */
if ( err < 0 ) {
printf ( " libfdt: %s " , fdt_strerror ( err ) ) ;
printf ( " libfdt fdt_check_header() : %s " , fdt_strerror ( err ) ) ;
/*
* Be more informative on bad version .
*/
if ( err = = - FDT_ERR_BADVERSION ) {
if ( fdt_version ( fdt ) < FDT_FIRST_SUPPORTED_VERSION ) {
printf ( " - too old, fdt $d < %d " ,
fdt_version ( fdt ) , FDT_FIRST_SUPPORTED_VERSION ) ;
fdt_version ( fdt ) ,
FDT_FIRST_SUPPORTED_VERSION ) ;
fdt = NULL ;
}
if ( fdt_last_comp_version ( fdt ) > FDT_LAST_SUPPORTED_VERSION ) {
printf ( " - too new, fdt $d > %d " ,
fdt_version ( fdt ) , FDT_LAST_SUPPORTED_VERSION ) ;
fdt_version ( fdt ) ,
FDT_LAST_SUPPORTED_VERSION ) ;
fdt = NULL ;
}
return 0 ;
@ -500,13 +363,91 @@ static int fdt_valid(void)
return 1 ;
}
/********************************************************************/
/**************************************************************************** /
/*
* OF flat tree handling
* Written by : Pantelis Antoniou < pantelis . antoniou @ gmail . com >
* Updated by : Matthew McClintock < msm @ freescale . com >
* Converted to libfdt by : Gerald Van Baren < vanbaren @ cideas . com >
* Parse the user ' s input , partially heuristic . Valid formats :
* < 00 > - hex byte
* < 0011 > - hex half word ( 16 bits )
* < 00112233 > - hex word ( 32 bits )
* - hex double words ( 64 bits ) are not supported , must use
* a byte stream instead .
* [ 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 .
*/
static int fdt_parse_prop ( char * pathp , char * prop , char * newval ,
char * data , int * len )
{
char * cp ; /* temporary char pointer */
unsigned long tmp ; /* holds converted values */
if ( * newval = = ' < ' ) {
/*
* Bigger values than bytes .
*/
* len = 0 ;
newval + + ;
while ( ( * newval ! = ' > ' ) & & ( * newval ! = ' \0 ' ) ) {
cp = newval ;
tmp = simple_strtoul ( cp , & newval , 16 ) ;
if ( ( newval - cp ) < = 2 ) {
* data = tmp & 0xFF ;
data + = 1 ;
* len + = 1 ;
} else if ( ( newval - cp ) < = 4 ) {
* ( uint16_t * ) data = __cpu_to_be16 ( tmp ) ;
data + = 2 ;
* len + = 2 ;
} else if ( ( newval - cp ) < = 8 ) {
* ( uint32_t * ) data = __cpu_to_be32 ( tmp ) ;
data + = 4 ;
* len + = 4 ;
} else {
printf ( " Sorry, I could not convert \" %s \" \n " ,
cp ) ;
return 1 ;
}
while ( * newval = = ' ' )
newval + + ;
}
if ( * newval ! = ' > ' ) {
printf ( " Unexpected character '%c' \n " , * newval ) ;
return 1 ;
}
} else if ( * newval = = ' [ ' ) {
/*
* Byte stream . Convert the values .
*/
* len = 0 ;
newval + + ;
while ( ( * newval ! = ' ] ' ) & & ( * newval ! = ' \0 ' ) ) {
tmp = simple_strtoul ( newval , & newval , 16 ) ;
* data + + = tmp & 0xFF ;
* len = * len + 1 ;
while ( * newval = = ' ' )
newval + + ;
}
if ( * newval ! = ' ] ' ) {
printf ( " Unexpected character '%c' \n " , * newval ) ;
return 1 ;
}
} else {
/*
* Assume it is a string . Copy it into our data area for
* convenience ( including the terminating ' \0 ' ) .
*/
* len = strlen ( newval ) + 1 ;
strcpy ( data , newval ) ;
}
return 0 ;
}
/****************************************************************************/
/*
* Heuristic to guess if this is a string or concatenated strings .
*/
static int is_printable_string ( const void * data , int len )
@ -546,6 +487,12 @@ static int is_printable_string(const void *data, int len)
return 1 ;
}
/*
* 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 .
*/
static void print_data ( const void * data , int len )
{
int j ;
@ -601,32 +548,146 @@ static void print_data(const void *data, int len)
}
}
/****************************************************************************/
/*
* Recursively print ( a portion of ) the fdt . The depth parameter
* determines how deeply nested the fdt is printed .
*/
static int fdt_print ( char * pathp , char * prop , int depth )
{
static int offstack [ MAX_LEVEL ] ;
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 " ;
void * nodep ; /* property node pointer */
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 */
nodeoffset = fdt_find_node_by_path ( fdt , pathp ) ;
if ( nodeoffset < 0 ) {
/*
* Not found or something else bad happened .
*/
printf ( " libfdt fdt_find_node_by_path() returned %s \n " ,
fdt_strerror ( nodeoffset ) ) ;
return 1 ;
}
/*
* The user passed in a property as well as node path .
* Print only the given property and then return .
*/
if ( prop ) {
nodep = fdt_getprop ( fdt , nodeoffset , prop , & len ) ;
if ( len = = 0 ) {
/* no property value */
printf ( " %s %s \n " , pathp , prop ) ;
return 0 ;
} else if ( len > 0 ) {
printf ( " %s= " , prop ) ;
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 .
*/
offstack [ 0 ] = nodeoffset ;
while ( level > = 0 ) {
tag = fdt_next_tag ( fdt , nodeoffset , & nextoffset , & pathp ) ;
switch ( tag ) {
case FDT_BEGIN_NODE :
if ( level < = depth )
printf ( " %s%s { \n " ,
& tabs [ MAX_LEVEL - level ] , pathp ) ;
level + + ;
offstack [ level ] = nodeoffset ;
if ( level > = MAX_LEVEL ) {
printf ( " Aaaiii <splat> nested too deep. "
" Aborting. \n " ) ;
return 1 ;
}
break ;
case FDT_END_NODE :
level - - ;
if ( level < = depth )
printf ( " %s}; \n " , & tabs [ MAX_LEVEL - level ] ) ;
if ( level = = 0 ) {
level = - 1 ; /* exit the loop */
}
break ;
case FDT_PROP :
nodep = fdt_getprop ( fdt , offstack [ level ] , pathp , & len ) ;
if ( len < 0 ) {
printf ( " libfdt fdt_getprop(): %s \n " ,
fdt_strerror ( len ) ) ;
return 1 ;
} else if ( len = = 0 ) {
/* the property has no value */
if ( level < = depth )
printf ( " %s%s; \n " ,
& tabs [ MAX_LEVEL - level ] ,
pathp ) ;
} else {
if ( level < = depth ) {
printf ( " %s%s= " ,
& tabs [ MAX_LEVEL - level ] ,
pathp ) ;
print_data ( nodep , len ) ;
printf ( " ; \n " ) ;
}
}
break ;
case FDT_NOP :
break ;
case FDT_END :
return 1 ;
default :
if ( level < = depth )
printf ( " Unknown tag 0x%08X \n " , tag ) ;
return 1 ;
}
nodeoffset = nextoffset ;
}
return 0 ;
}
/********************************************************************/
U_BOOT_CMD (
fdt , 5 , 0 , do_fdt ,
" fdt - flattened device tree utility commands \n " ,
" addr <addr> [<length>] - Set the fdt location to <addr> \n "
# ifdef CONFIG_OF_BOARD_SETUP
" fdt boardsetup - Do board-specific set up \n "
# endif
" fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> \n "
" fdt print <path> [<prop>] - Recursive print starting at <path> \n "
" fdt list <path> [<prop>] - Print one level starting at <path> \n "
" 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 chosen - Add/update the \" /chosen \" branch in the tree \n "
" fdt chosen - Add/update the /chosen branch in the tree \n "
# ifdef CONFIG_OF_HAS_UBOOT_ENV
" fdt env - Add/replace the \" /u-boot-env \" branch in the tree \n "
" fdt env - Add/replace the /u-boot-env branch in the tree \n "
# endif
# ifdef CONFIG_OF_HAS_BD_T
" fdt bd_t - Add/replace the \" /bd_t \" branch in the tree \n "
" fdt bd_t - Add/replace the /bd_t branch in the tree \n "
# endif
" Hints: \n "
" * Set a larger length with the fdt addr command to add to the blob. \n "
" * If the property you are setting/printing has a '#' character, \n "
" you MUST escape it with a \\ character or quote it with \" or \n "
" it will be ignored as a comment. \n "
" * If the value has spaces in it, you MUST escape the spaces with \n "
" \\ characters or quote it with \" \" \n "
" If the property you are setting/printing has a '#' character or spaces, \n "
" you MUST escape it with a \\ character or quote it with \" . \n "
" Examples: fdt print / # print the whole tree \n "
" fdt print /cpus \" #address-cells \" \n "
" fdt set /cpus \" #address-cells \" \" [00 00 00 01] \" \n "