@ -47,6 +47,7 @@ DECLARE_GLOBAL_DATA_PTR;
static int fdt_valid ( void ) ;
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 .
@ -64,6 +65,34 @@ void set_working_fdt_addr(void *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 .
*/
int do_fdt ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
@ -253,6 +282,117 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
return 1 ;
}
/********************************************************************
* Get the value of a property in the working_fdt .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} else if ( argv [ 1 ] [ 0 ] = = ' g ' ) {
char * subcmd ; /* sub-command */
char * pathp ; /* path */
char * prop ; /* property */
char * var ; /* variable to store result */
int nodeoffset ; /* node offset from libfdt */
const void * nodep ; /* property node pointer */
int len = 0 ; /* new length of the property */
/*
* Parameters : Node path , property , optional value .
*/
if ( argc < 5 )
return CMD_RET_USAGE ;
subcmd = argv [ 2 ] ;
if ( argc < 6 & & subcmd [ 0 ] ! = ' s ' )
return CMD_RET_USAGE ;
var = argv [ 3 ] ;
pathp = argv [ 4 ] ;
prop = argv [ 5 ] ;
nodeoffset = fdt_path_offset ( working_fdt , pathp ) ;
if ( nodeoffset < 0 ) {
/*
* Not found or something else bad happened .
*/
printf ( " libfdt fdt_path_offset() returned %s \n " ,
fdt_strerror ( nodeoffset ) ) ;
return 1 ;
}
if ( subcmd [ 0 ] = = ' n ' | | ( subcmd [ 0 ] = = ' s ' & & argc = = 5 ) ) {
int reqIndex = - 1 ;
int startDepth = fdt_node_depth (
working_fdt , nodeoffset ) ;
int curDepth = startDepth ;
int curIndex = - 1 ;
int nextNodeOffset = fdt_next_node (
working_fdt , nodeoffset , & curDepth ) ;
if ( subcmd [ 0 ] = = ' n ' )
reqIndex = simple_strtoul ( argv [ 5 ] , NULL , 16 ) ;
while ( curDepth > startDepth ) {
if ( curDepth = = startDepth + 1 )
curIndex + + ;
if ( subcmd [ 0 ] = = ' n ' & & curIndex = = reqIndex ) {
const char * nodeName = fdt_get_name (
working_fdt , nextNodeOffset , NULL ) ;
setenv ( var , ( char * ) nodeName ) ;
return 0 ;
}
nextNodeOffset = fdt_next_node (
working_fdt , nextNodeOffset , & curDepth ) ;
if ( nextNodeOffset < 0 )
break ;
}
if ( subcmd [ 0 ] = = ' s ' ) {
/* get the num nodes at this level */
char buf [ 11 ] ;
sprintf ( buf , " %d " , curIndex + 1 ) ;
setenv ( var , buf ) ;
} else {
/* node index not found */
printf ( " libfdt node not found \n " ) ;
return 1 ;
}
} else {
nodep = fdt_getprop (
working_fdt , nodeoffset , prop , & len ) ;
if ( len = = 0 ) {
/* no property value */
setenv ( var , " " ) ;
return 0 ;
} else if ( len > 0 ) {
if ( subcmd [ 0 ] = = ' v ' ) {
int ret ;
ret = fdt_value_setenv ( nodep , len , var ) ;
if ( ret ! = 0 )
return ret ;
} else if ( subcmd [ 0 ] = = ' a ' ) {
/* Get address */
char buf [ 11 ] ;
sprintf ( buf , " 0x%08X " , ( uint32_t ) nodep ) ;
setenv ( var , buf ) ;
} else if ( subcmd [ 0 ] = = ' s ' ) {
/* Get size */
char buf [ 11 ] ;
sprintf ( buf , " 0x%08X " , len ) ;
setenv ( var , buf ) ;
} else
return CMD_RET_USAGE ;
return 0 ;
} else {
printf ( " libfdt fdt_getprop(): %s \n " ,
fdt_strerror ( len ) ) ;
return 1 ;
}
}
/*
* Print ( recursive ) / List ( single level )
*/
@ -836,6 +976,10 @@ U_BOOT_CMD(
" fdt resize - Resize fdt to size + padding to 4k addr \n "
" fdt print <path> [<prop>] - Recursive print starting at <path> \n "
" fdt list <path> [<prop>] - Print one level starting at <path> \n "
" fdt get value <var> <path> <prop> - Get <property> and store in <var> \n "
" fdt get name <var> <path> <index> - Get name of node <index> and store in <var> \n "
" fdt get addr <var> <path> <prop> - Get start address of <property> and store in <var> \n "
" fdt get size <var> <path> [<prop>] - Get size of [<property>] or num nodes and store in <var> \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 "