@ -1,5 +1,5 @@
/*
/*
* ( C ) Copyright 2000 - 2002
* ( C ) Copyright 2000 - 201 0
* Wolfgang Denk , DENX Software Engineering , wd @ denx . de .
* Wolfgang Denk , DENX Software Engineering , wd @ denx . de .
*
*
* ( C ) Copyright 2001 Sysgo Real - Time Solutions , GmbH < www . elinos . com >
* ( C ) Copyright 2001 Sysgo Real - Time Solutions , GmbH < www . elinos . com >
@ -24,27 +24,26 @@
* MA 02111 - 1307 USA
* MA 02111 - 1307 USA
*/
*/
/**************************************************************************
/*
*
* Support for persistent environment data
* Support for persistent environment data
*
*
* The " environment " is stored as a list of ' \0 ' terminated
* The " environment " is stored on external storage as a list of ' \0 '
* " name=value " strings . The end of the list is marked by a double
* terminated " name=value " strings . The end of the list is marked by
* ' \0 ' . New entries are always added at the end . Deleting an entry
* a double ' \0 ' . The environment is preceeded by a 32 bit CRC over
* shifts the remaining entries to the front . Replacing an entry is a
* the data part and , in case of redundant environment , a byte of
* combination of deleting the old value and adding the new one .
* flags .
*
* The environment is preceeded by a 32 bit CRC over the data part .
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This linearized representation will also be used before
* relocation , i . e . as long as we don ' t have a full C runtime
* environment . After that , we use a hash table .
*/
*/
# include <common.h>
# include <common.h>
# include <command.h>
# include <command.h>
# include <environment.h>
# include <environment.h>
# if defined(CONFIG_CMD_EDITENV)
# include <search.h>
# include <errno.h>
# include <malloc.h>
# include <malloc.h>
# endif
# include <watchdog.h>
# include <watchdog.h>
# include <serial.h>
# include <serial.h>
# include <linux/stddef.h>
# include <linux/stddef.h>
@ -72,8 +71,10 @@ SPI_FLASH|MG_DISK|NVRAM|MMC|NOWHERE}
# define XMK_STR(x) #x
# define XMK_STR(x) #x
# define MK_STR(x) XMK_STR(x)
# define MK_STR(x) XMK_STR(x)
/************************************************************************
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
* Maximum expected input data size for import command
*/
# define MAX_ENV_SIZE (1 << 20) /* 1 MiB */
/*
/*
* Table with supported baudrates ( defined in config_xyz . h )
* Table with supported baudrates ( defined in config_xyz . h )
@ -82,7 +83,7 @@ static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
# define N_BAUDRATES (sizeof(baudrate_table) / sizeof(baudrate_table[0]))
# define N_BAUDRATES (sizeof(baudrate_table) / sizeof(baudrate_table[0]))
/*
/*
* This variable is incremented on each do_setenv ( ) , so it can
* This variable is incremented on each do_env_ set ( ) , so it can
* be used via get_env_id ( ) as an indication , if the environment
* be used via get_env_id ( ) as an indication , if the environment
* has changed or not . So it is possible to reread an environment
* has changed or not . So it is possible to reread an environment
* variable only if the environment was changed . . . done so for
* variable only if the environment was changed . . . done so for
@ -94,61 +95,51 @@ int get_env_id (void)
{
{
return env_id ;
return env_id ;
}
}
/************************************************************************
* Command interface : print one or all environment variables
*/
/*
/*
* state 0 : finish printing this string and return ( matched ! )
* Command interface : print one or all environment variables
* state 1 : no matching to be done ; print everything
*
* state 2 : continue searching for matched name
* Returns 0 in case of error , or length of printed string
*/
*/
static int printenv ( char * name , int stat e )
static int env_ print( char * name )
{
{
int i , j ;
char * res = NULL ;
char c , buf [ 17 ] ;
size_t len ;
i = 0 ;
if ( name ) { /* print a single name */
buf [ 16 ] = ' \0 ' ;
ENTRY e , * ep ;
while ( state & & env_get_char ( i ) ! = ' \0 ' ) {
e . key = name ;
if ( state = = 2 & & envmatch ( ( uchar * ) name , i ) > = 0 )
e . data = NULL ;
state = 0 ;
ep = hsearch ( e , FIND ) ;
if ( ep = = NULL )
j = 0 ;
return 0 ;
do {
len = printf ( " %s=%s \n " , ep - > key , ep - > data ) ;
buf [ j + + ] = c = env_get_char ( i + + ) ;
return len ;
if ( j = = sizeof ( buf ) - 1 ) {
}
if ( state < = 1 )
puts ( buf ) ;
j = 0 ;
}
} while ( c ! = ' \0 ' ) ;
if ( state < = 1 ) {
/* print whole list */
if ( j )
len = hexport ( ' \n ' , & res , 0 ) ;
puts ( buf ) ;
putc ( ' \n ' ) ;
}
if ( ctrlc ( ) )
if ( len > 0 ) {
return - 1 ;
puts ( res ) ;
free ( res ) ;
return len ;
}
}
if ( state = = 0 )
/* should never happen */
i = 0 ;
return 0 ;
return i ;
}
}
int do_printenv ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
int do_env_ print ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
{
int i ;
int i ;
int rcode = 0 ;
int rcode = 0 ;
if ( argc = = 1 ) {
if ( argc = = 1 ) {
/* print all env vars */
/* print all env vars */
rcode = printenv ( NULL , 1 ) ;
rcode = env_ print( NULL ) ;
if ( rcode < 0 )
if ( ! rcode )
return 1 ;
return 1 ;
printf ( " \n Environment size: %d/%ld bytes \n " ,
printf ( " \n Environment size: %d/%ld bytes \n " ,
rcode , ( ulong ) ENV_SIZE ) ;
rcode , ( ulong ) ENV_SIZE ) ;
@ -157,9 +148,9 @@ int do_printenv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/* print selected env vars */
/* print selected env vars */
for ( i = 1 ; i < argc ; + + i ) {
for ( i = 1 ; i < argc ; + + i ) {
char * name = argv [ i ] ;
int rc = env_print ( argv [ i ] ) ;
if ( printenv ( name , 2 ) ) {
if ( ! rc ) {
printf ( " ## Error: \" %s \" not defined \n " , name ) ;
printf ( " ## Error: \" %s \" not defined \n " , argv [ i ] ) ;
+ + rcode ;
+ + rcode ;
}
}
}
}
@ -167,25 +158,18 @@ int do_printenv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return rcode ;
return rcode ;
}
}
/************************************************************************
/*
* Set a new environment variable ,
* Set a new environment variable ,
* or replace or delete an existing one .
* or replace or delete an existing one .
*
* This function will ONLY work with a in - RAM copy of the environment
*/
*/
int _do_setenv ( int flag , int argc , char * const argv [ ] )
int _do_env_ set ( int flag , int argc , char * const argv [ ] )
{
{
int i , len , oldval ;
bd_t * bd = gd - > bd ;
int i , len ;
int console = - 1 ;
int console = - 1 ;
uchar * env , * nxt = NULL ;
char * name , * value , * s ;
char * name ;
ENTRY e , * ep ;
bd_t * bd = gd - > bd ;
uchar * env_data = env_get_addr ( 0 ) ;
if ( ! env_data ) /* need copy in RAM */
return 1 ;
name = argv [ 1 ] ;
name = argv [ 1 ] ;
@ -198,13 +182,9 @@ int _do_setenv (int flag, int argc, char * const argv[])
/*
/*
* search if variable with this name already exists
* search if variable with this name already exists
*/
*/
oldval = - 1 ;
e . key = name ;
for ( env = env_data ; * env ; env = nxt + 1 ) {
e . data = NULL ;
for ( nxt = env ; * nxt ; + + nxt )
ep = hsearch ( e , FIND ) ;
;
if ( ( oldval = envmatch ( ( uchar * ) name , env - env_data ) ) > = 0 )
break ;
}
/* Check for console redirection */
/* Check for console redirection */
if ( strcmp ( name , " stdin " ) = = 0 ) {
if ( strcmp ( name , " stdin " ) = = 0 ) {
@ -238,31 +218,25 @@ int _do_setenv (int flag, int argc, char * const argv[])
}
}
/*
/*
* Delete any existing definition
* Some variables like " ethaddr " and " serial# " can be set only
* once and cannot be deleted ; also , " ver " is readonly .
*/
*/
if ( oldval > = 0 ) {
if ( ep ) { /* variable exists */
# ifndef CONFIG_ENV_OVERWRITE
# ifndef CONFIG_ENV_OVERWRITE
if ( ( strcmp ( name , " serial# " ) = = 0 ) | |
/*
* Ethernet Address and serial # can be set only once ,
* ver is readonly .
*/
if (
( strcmp ( name , " serial# " ) = = 0 ) | |
( ( strcmp ( name , " ethaddr " ) = = 0 )
( ( strcmp ( name , " ethaddr " ) = = 0 )
# if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
# if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
& & ( strcmp ( ( char * ) env_get_addr ( oldval ) , MK_STR ( CONFIG_ETHADDR ) ) ! = 0 )
& & ( strcmp ( ep - > data , MK_STR ( CONFIG_ETHADDR ) ) ! = 0 )
# endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
# endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
) ) {
) ) {
printf ( " Can't overwrite \" %s \" \n " , name ) ;
printf ( " Can't overwrite \" %s \" \n " , name ) ;
return 1 ;
return 1 ;
}
}
# endif
# endif
/*
/*
* Switch to new baudrate if new baudrate is supported
* Switch to new baudrate if new baudrate is supported
*/
*/
if ( strcmp ( argv [ 1 ] , " baudrate " ) = = 0 ) {
if ( strcmp ( name , " baudrate " ) = = 0 ) {
int baudrate = simple_strtoul ( argv [ 2 ] , NULL , 10 ) ;
int baudrate = simple_strtoul ( argv [ 2 ] , NULL , 10 ) ;
int i ;
int i ;
for ( i = 0 ; i < N_BAUDRATES ; + + i ) {
for ( i = 0 ; i < N_BAUDRATES ; + + i ) {
@ -289,75 +263,50 @@ int _do_setenv (int flag, int argc, char * const argv[])
break ;
break ;
}
}
}
}
if ( * + + nxt = = ' \0 ' ) {
if ( env > env_data ) {
env - - ;
} else {
* env = ' \0 ' ;
}
} else {
for ( ; ; ) {
* env = * nxt + + ;
if ( ( * env = = ' \0 ' ) & & ( * nxt = = ' \0 ' ) )
break ;
+ + env ;
}
}
* + + env = ' \0 ' ;
}
}
/* Delete only ? */
/* Delete only ? */
if ( ( argc < 3 ) | | argv [ 2 ] = = NULL ) {
if ( ( argc < 3 ) | | argv [ 2 ] = = NULL ) {
env_crc_update ( ) ;
int rc = hdelete ( name ) ;
return 0 ;
return ! rc ;
}
}
/*
/*
* Append new definition at the end
* Insert / replace new value
*/
*/
for ( env = env_data ; * env | | * ( env + 1 ) ; + + env )
for ( i = 2 , len = 0 ; i < argc ; + + i ) {
;
if ( env > env_data )
+ + env ;
/*
* Overflow when :
* " name " + " = " + " val " + " \0 \0 " > ENV_SIZE - ( env - env_data )
*/
len = strlen ( name ) + 2 ;
/* add '=' for first arg, ' ' for all others */
for ( i = 2 ; i < argc ; + + i ) {
len + = strlen ( argv [ i ] ) + 1 ;
len + = strlen ( argv [ i ] ) + 1 ;
}
}
if ( len > ( & env_data [ ENV_SIZE ] - env ) ) {
if ( ( value = malloc ( len ) ) = = NULL ) {
printf ( " ## Error: environment overflow, \" %s \" deleted \n " , name ) ;
printf ( " ## Can't malloc %d bytes \n " , len ) ;
return 1 ;
return 1 ;
}
}
while ( ( * env = * name + + ) ! = ' \0 ' )
for ( i = 2 , s = value ; i < argc ; + + i ) {
env + + ;
char * v = argv [ i ] ;
for ( i = 2 ; i < argc ; + + i ) {
char * val = argv [ i ] ;
* env = ( i = = 2 ) ? ' = ' : ' ' ;
while ( ( * s + + = * v + + ) ! = ' \0 ' )
while ( ( * + + env = * val + + ) ! = ' \0 ' )
;
;
* ( s - 1 ) = ' ' ;
}
if ( s ! = value )
* - - s = ' \0 ' ;
e . key = name ;
e . data = value ;
ep = hsearch ( e , ENTER ) ;
free ( value ) ;
if ( ! ep ) {
printf ( " ## Error inserting \" %s \" variable, errno=%d \n " ,
name , errno ) ;
return 1 ;
}
}
/* end is marked with double '\0' */
* + + env = ' \0 ' ;
/* Update CRC */
env_crc_update ( ) ;
/*
/*
* Some variables should be updated when the corresponding
* Some variables should be updated when the corresponding
* entry in the enviornment is changed
* entry in the environment is changed
*/
*/
if ( strcmp ( argv [ 1 ] , " ethaddr " ) = = 0 )
if ( strcmp ( name , " ipaddr " ) = = 0 ) {
return 0 ;
if ( strcmp ( argv [ 1 ] , " ipaddr " ) = = 0 ) {
char * s = argv [ 2 ] ; /* always use only one arg */
char * s = argv [ 2 ] ; /* always use only one arg */
char * e ;
char * e ;
unsigned long addr ;
unsigned long addr ;
@ -370,13 +319,12 @@ int _do_setenv (int flag, int argc, char * const argv[])
}
}
bd - > bi_ip_addr = htonl ( addr ) ;
bd - > bi_ip_addr = htonl ( addr ) ;
return 0 ;
return 0 ;
}
} else if ( strcmp ( argv [ 1 ] , " loadaddr " ) = = 0 ) {
if ( strcmp ( argv [ 1 ] , " loadaddr " ) = = 0 ) {
load_addr = simple_strtoul ( argv [ 2 ] , NULL , 16 ) ;
load_addr = simple_strtoul ( argv [ 2 ] , NULL , 16 ) ;
return 0 ;
return 0 ;
}
}
# if defined(CONFIG_CMD_NET)
# if defined(CONFIG_CMD_NET)
if ( strcmp ( argv [ 1 ] , " bootfile " ) = = 0 ) {
else if ( strcmp ( argv [ 1 ] , " bootfile " ) = = 0 ) {
copy_filename ( BootFile , argv [ 2 ] , sizeof ( BootFile ) ) ;
copy_filename ( BootFile , argv [ 2 ] , sizeof ( BootFile ) ) ;
return 0 ;
return 0 ;
}
}
@ -388,30 +336,29 @@ int setenv (char *varname, char *varvalue)
{
{
char * const argv [ 4 ] = { " setenv " , varname , varvalue , NULL } ;
char * const argv [ 4 ] = { " setenv " , varname , varvalue , NULL } ;
if ( ( varvalue = = NULL ) | | ( varvalue [ 0 ] = = ' \0 ' ) )
if ( ( varvalue = = NULL ) | | ( varvalue [ 0 ] = = ' \0 ' ) )
return _do_setenv ( 0 , 2 , argv ) ;
return _do_env_ set ( 0 , 2 , argv ) ;
else
else
return _do_setenv ( 0 , 3 , argv ) ;
return _do_env_ set ( 0 , 3 , argv ) ;
}
}
int do_setenv ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
int do_env_ set ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
{
if ( argc < 2 )
if ( argc < 2 )
return cmd_usage ( cmdtp ) ;
return cmd_usage ( cmdtp ) ;
return _do_setenv ( flag , argc , argv ) ;
return _do_env_ set ( flag , argc , argv ) ;
}
}
/************************************************************************
/*
* Prompt for environment variable
* Prompt for environment variable
*/
*/
# if defined(CONFIG_CMD_ASKENV)
# if defined(CONFIG_CMD_ASKENV)
int do_askenv ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
int do_env_ ask ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
{
extern char console_buffer [ CONFIG_SYS_CBSIZE ] ;
extern char console_buffer [ CONFIG_SYS_CBSIZE ] ;
char message [ CONFIG_SYS_CBSIZE ] ;
char message [ CONFIG_SYS_CBSIZE ] ;
int size = CONFIG_SYS_CBSIZE - 1 ;
int size = CONFIG_SYS_CBSIZE - 1 ;
int len ;
int i , len , pos ;
char * local_args [ 4 ] ;
char * local_args [ 4 ] ;
local_args [ 0 ] = argv [ 0 ] ;
local_args [ 0 ] = argv [ 0 ] ;
@ -419,38 +366,30 @@ int do_askenv ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
local_args [ 2 ] = NULL ;
local_args [ 2 ] = NULL ;
local_args [ 3 ] = NULL ;
local_args [ 3 ] = NULL ;
if ( argc < 2 )
return cmd_usage ( cmdtp ) ;
/* Check the syntax */
/* Check the syntax */
switch ( argc ) {
switch ( argc ) {
case 1 :
case 1 :
return cmd_usage ( cmdtp ) ;
return cmd_usage ( cmdtp ) ;
case 2 : /* askenv envname */
case 2 : /* env_ ask envname */
sprintf ( message , " Please enter '%s': " , argv [ 1 ] ) ;
sprintf ( message , " Please enter '%s': " , argv [ 1 ] ) ;
break ;
break ;
case 3 : /* askenv envname size */
case 3 : /* env_ ask envname size */
sprintf ( message , " Please enter '%s': " , argv [ 1 ] ) ;
sprintf ( message , " Please enter '%s': " , argv [ 1 ] ) ;
size = simple_strtoul ( argv [ 2 ] , NULL , 10 ) ;
size = simple_strtoul ( argv [ 2 ] , NULL , 10 ) ;
break ;
break ;
default : /* askenv envname message1 ... messagen size */
default : /* env_ask envname message1 ... messagen size */
{
for ( i = 2 , pos = 0 ; i < argc - 1 ; i + + ) {
int i ;
int pos = 0 ;
for ( i = 2 ; i < argc - 1 ; i + + ) {
if ( pos ) {
if ( pos ) {
message [ pos + + ] = ' ' ;
message [ pos + + ] = ' ' ;
}
}
strcpy ( message + pos , argv [ i ] ) ;
strcpy ( message + pos , argv [ i ] ) ;
pos + = strlen ( argv [ i ] ) ;
pos + = strlen ( argv [ i ] ) ;
}
}
message [ pos ] = ' \0 ' ;
message [ pos ] = ' \0 ' ;
size = simple_strtoul ( argv [ argc - 1 ] , NULL , 10 ) ;
size = simple_strtoul ( argv [ argc - 1 ] , NULL , 10 ) ;
}
break ;
break ;
}
}
@ -461,7 +400,7 @@ int do_askenv ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return 1 ;
return 1 ;
/* prompt for input */
/* prompt for input */
len = readline ( message ) ;
len = readline ( message ) ;
if ( size < len )
if ( size < len )
console_buffer [ size ] = ' \0 ' ;
console_buffer [ size ] = ' \0 ' ;
@ -473,15 +412,15 @@ int do_askenv ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
}
/* Continue calling setenv code */
/* Continue calling setenv code */
return _do_setenv ( flag , len , local_args ) ;
return _do_env_ set ( flag , len , local_args ) ;
}
}
# endif
# endif
/************************************************************************
/*
* Interactively edit an environment variable
* Interactively edit an environment variable
*/
*/
# if defined(CONFIG_CMD_EDITENV)
# if defined(CONFIG_CMD_EDITENV)
int do_editenv ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
int do_env_e dit ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
{
char buffer [ CONFIG_SYS_CBSIZE ] ;
char buffer [ CONFIG_SYS_CBSIZE ] ;
char * init_val ;
char * init_val ;
@ -503,42 +442,37 @@ int do_editenv(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
}
# endif /* CONFIG_CMD_EDITENV */
# endif /* CONFIG_CMD_EDITENV */
/************************************************************************
/*
* Look up variable from environment ,
* Look up variable from environment ,
* return address of storage for that variable ,
* return address of storage for that variable ,
* or NULL if not found
* or NULL if not found
*/
*/
char * getenv ( char * name )
char * getenv ( char * name )
{
{
if ( gd - > flags & GD_FLG_RELOC ) { /* full C runtime after reloc */
if ( gd - > flags & GD_FLG_ENV_READY ) { /* after import into hashtable */
int i , nxt ;
ENTRY e , * ep ;
WATCHDOG_RESET ( ) ;
WATCHDOG_RESET ( ) ;
for ( i = 0 ; env_get_char ( i ) ! = ' \0 ' ; i = nxt + 1 ) {
e . key = name ;
int val ;
e . data = NULL ;
ep = hsearch ( e , FIND ) ;
for ( nxt = i ; env_get_char ( nxt ) ! = ' \0 ' ; + + nxt ) {
if ( nxt > = CONFIG_ENV_SIZE ) {
return ( NULL ) ;
}
}
if ( ( val = envmatch ( ( uchar * ) name , i ) ) < 0 )
continue ;
return ( ( char * ) env_get_addr ( val ) ) ;
}
return ( NULL ) ;
return ( ep ? ep - > data : NULL ) ;
}
}
/* restricted C runtime before reloc */
/* restricted capabilities before import */
if ( getenv_f ( name , ( char * ) ( gd - > env_buf ) , sizeof ( gd - > env_buf ) ) > 0 )
return ( char * ) ( gd - > env_buf ) ;
return ( ( getenv_f ( name , gd - > env_buf , sizeof ( gd - > env_buf ) ) > 0 ) ?
return NULL ;
gd - > env_buf : NULL ) ;
}
}
int getenv_f ( char * name , char * buf , unsigned len )
/*
* Look up variable from environment for restricted C runtime env .
*/
int getenv_f ( char * name , char * buf , unsigned len )
{
{
int i , nxt ;
int i , nxt ;
@ -571,7 +505,7 @@ int getenv_f(char *name, char *buf, unsigned len)
# if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
# if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
int do_saveenv ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
int do_env_ save ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
{
extern char * env_name_spec ;
extern char * env_name_spec ;
@ -581,7 +515,7 @@ int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
}
U_BOOT_CMD (
U_BOOT_CMD (
saveenv , 1 , 0 , do_saveenv ,
saveenv , 1 , 0 , do_env_ save ,
" save environment variables to persistent storage " ,
" save environment variables to persistent storage " ,
" "
" "
) ;
) ;
@ -589,7 +523,7 @@ U_BOOT_CMD(
# endif
# endif
/************************************************************************
/*
* Match a name / name = value pair
* Match a name / name = value pair
*
*
* s1 is either a simple ' name ' , or a ' name = value ' pair .
* s1 is either a simple ' name ' , or a ' name = value ' pair .
@ -608,12 +542,345 @@ int envmatch (uchar *s1, int i2)
return ( - 1 ) ;
return ( - 1 ) ;
}
}
static int do_env_default ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
if ( ( argc ! = 2 ) | | ( strcmp ( argv [ 1 ] , " -f " ) ! = 0 ) ) {
cmd_usage ( cmdtp ) ;
return 1 ;
}
set_default_env ( " ## Resetting to default environment \n " ) ;
return 0 ;
}
static int do_env_delete ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
printf ( " Not implemented yet \n " ) ;
return 0 ;
}
/*
* env export [ - t | - b | - c ] addr [ size ]
* - t : export as text format ; if size is given , data will be
* padded with ' \0 ' bytes ; if not , one terminating ' \0 '
* will be added ( which is included in the " filesize "
* setting so you can for exmple copy this to flash and
* keep the termination ) .
* - b : export as binary format ( name = value pairs separated by
* ' \0 ' , list end marked by double " \0 \0 " )
* - c : export as checksum protected environment format as
* used for example by " saveenv " command
* addr : memory address where environment gets stored
* size : size of output buffer
*
* With " -c " and size is NOT given , then the export command will
* format the data as currently used for the persistent storage ,
* i . e . it will use CONFIG_ENV_SECT_SIZE as output block size and
* prepend a valid CRC32 checksum and , in case of resundant
* environment , a " current " redundancy flag . If size is given , this
* value will be used instead of CONFIG_ENV_SECT_SIZE ; again , CRC32
* checksum and redundancy flag will be inserted .
*
* With " -b " and " -t " , always only the real data ( including a
* terminating ' \0 ' byte ) will be written ; here the optional size
* argument will be used to make sure not to overflow the user
* provided buffer ; the command will abort if the size is not
* sufficient . Any remainign space will be ' \0 ' padded .
*
* On successful return , the variable " filesize " will be set .
* Note that filesize includes the trailing / terminating ' \0 ' byte ( s ) .
*
* Usage szenario : create a text snapshot / backup of the current settings :
*
* = > env export - t 100000
* = > era $ { backup_addr } + $ { filesize }
* = > cp . b 100000 $ { backup_addr } $ { filesize }
*
* Re - import this snapshot , deleting all other settings :
*
* = > env import - d - t $ { backup_addr }
*/
static int do_env_export ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
char buf [ 32 ] ;
char * addr , * cmd , * res ;
size_t size ;
ssize_t len ;
env_t * envp ;
char sep = ' \n ' ;
int chk = 0 ;
int fmt = 0 ;
cmd = * argv ;
while ( - - argc > 0 & & * * + + argv = = ' - ' ) {
char * arg = * argv ;
while ( * + + arg ) {
switch ( * arg ) {
case ' b ' : /* raw binary format */
if ( fmt + + )
goto sep_err ;
sep = ' \0 ' ;
break ;
case ' c ' : /* external checksum format */
if ( fmt + + )
goto sep_err ;
sep = ' \0 ' ;
chk = 1 ;
break ;
case ' t ' : /* text format */
if ( fmt + + )
goto sep_err ;
sep = ' \n ' ;
break ;
default :
cmd_usage ( cmdtp ) ;
return 1 ;
}
}
}
if ( argc < 1 ) {
cmd_usage ( cmdtp ) ;
return 1 ;
}
/**************************************************/
addr = ( char * ) simple_strtoul ( argv [ 0 ] , NULL , 16 ) ;
if ( argc = = 2 ) {
size = simple_strtoul ( argv [ 1 ] , NULL , 16 ) ;
memset ( addr , ' \0 ' , size ) ;
} else {
size = 0 ;
}
if ( sep ) { /* export as text file */
len = hexport ( sep , & addr , size ) ;
if ( len < 0 ) {
error ( " Cannot export environment: errno = %d \n " ,
errno ) ;
return 1 ;
}
sprintf ( buf , " %zX " , len ) ;
setenv ( " filesize " , buf ) ;
return 0 ;
}
envp = ( env_t * ) addr ;
if ( chk ) /* export as checksum protected block */
res = ( char * ) envp - > data ;
else /* export as raw binary data */
res = addr ;
len = hexport ( ' \0 ' , & res , ENV_SIZE ) ;
if ( len < 0 ) {
error ( " Cannot export environment: errno = %d \n " ,
errno ) ;
return 1 ;
}
if ( chk ) {
envp - > crc = crc32 ( 0 , envp - > data , ENV_SIZE ) ;
# ifdef CONFIG_ENV_ADDR_REDUND
envp - > flags = ACTIVE_FLAG ;
# endif
}
sprintf ( buf , " %zX " , len + offsetof ( env_t , data ) ) ;
setenv ( " filesize " , buf ) ;
return 0 ;
sep_err :
printf ( " ## %s: only one of \" -b \" , \" -c \" or \" -t \" allowed \n " ,
cmd ) ;
return 1 ;
}
/*
* env import [ - d ] [ - t | - b | - c ] addr [ size ]
* - d : delete existing environment before importing ;
* otherwise overwrite / append to existion definitions
* - t : assume text format ; either " size " must be given or the
* text data must be ' \0 ' terminated
* - b : assume binary format ( ' \0 ' separated , " \0 \0 " terminated )
* - c : assume checksum protected environment format
* addr : memory address to read from
* size : length of input data ; if missing , proper ' \0 '
* termination is mandatory
*/
static int do_env_import ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
char * cmd , * addr ;
char sep = ' \n ' ;
int chk = 0 ;
int fmt = 0 ;
int del = 0 ;
size_t size ;
cmd = * argv ;
while ( - - argc > 0 & & * * + + argv = = ' - ' ) {
char * arg = * argv ;
while ( * + + arg ) {
switch ( * arg ) {
case ' b ' : /* raw binary format */
if ( fmt + + )
goto sep_err ;
sep = ' \0 ' ;
break ;
case ' c ' : /* external checksum format */
if ( fmt + + )
goto sep_err ;
sep = ' \0 ' ;
chk = 1 ;
break ;
case ' t ' : /* text format */
if ( fmt + + )
goto sep_err ;
sep = ' \n ' ;
break ;
case ' d ' :
del = 1 ;
break ;
default :
cmd_usage ( cmdtp ) ;
return 1 ;
}
}
}
if ( argc < 1 ) {
cmd_usage ( cmdtp ) ;
return 1 ;
}
if ( ! fmt )
printf ( " ## Warning: defaulting to text format \n " ) ;
addr = ( char * ) simple_strtoul ( argv [ 0 ] , NULL , 16 ) ;
if ( argc = = 2 ) {
size = simple_strtoul ( argv [ 1 ] , NULL , 16 ) ;
} else {
char * s = addr ;
size = 0 ;
while ( size < MAX_ENV_SIZE ) {
if ( ( * s = = sep ) & & ( * ( s + 1 ) = = ' \0 ' ) )
break ;
+ + s ;
+ + size ;
}
if ( size = = MAX_ENV_SIZE ) {
printf ( " ## Warning: Input data exceeds %d bytes "
" - truncated \n " , MAX_ENV_SIZE ) ;
}
+ + size ;
printf ( " ## Info: input data size = %zd = 0x%zX \n " , size , size ) ;
}
if ( chk ) {
uint32_t crc ;
env_t * ep = ( env_t * ) addr ;
size - = offsetof ( env_t , data ) ;
memcpy ( & crc , & ep - > crc , sizeof ( crc ) ) ;
if ( crc32 ( 0 , ep - > data , size ) ! = crc ) {
puts ( " ## Error: bad CRC, import failed \n " ) ;
return 1 ;
}
addr = ( char * ) ep - > data ;
}
if ( himport ( addr , size , sep , del ? 0 : H_NOCLEAR ) = = 0 ) {
error ( " Environment import failed: errno = %d \n " , errno ) ;
return 1 ;
}
gd - > flags | = GD_FLG_ENV_READY ;
return 0 ;
sep_err :
printf ( " ## %s: only one of \" -b \" , \" -c \" or \" -t \" allowed \n " ,
cmd ) ;
return 1 ;
}
# if defined(CONFIG_CMD_RUN)
extern int do_run ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] ) ;
# endif
/*
* New command line interface : " env " command with subcommands
*/
static cmd_tbl_t cmd_env_sub [ ] = {
# if defined(CONFIG_CMD_ASKENV)
U_BOOT_CMD_MKENT ( ask , CONFIG_SYS_MAXARGS , 1 , do_env_ask , " " , " " ) ,
# endif
U_BOOT_CMD_MKENT ( default , 1 , 0 , do_env_default , " " , " " ) ,
U_BOOT_CMD_MKENT ( delete , 2 , 0 , do_env_delete , " " , " " ) ,
# if defined(CONFIG_CMD_EDITENV)
U_BOOT_CMD_MKENT ( edit , 2 , 0 , do_env_edit , " " , " " ) ,
# endif
U_BOOT_CMD_MKENT ( export , 4 , 0 , do_env_export , " " , " " ) ,
U_BOOT_CMD_MKENT ( import , 5 , 0 , do_env_import , " " , " " ) ,
U_BOOT_CMD_MKENT ( print , CONFIG_SYS_MAXARGS , 1 , do_env_print , " " , " " ) ,
# if defined(CONFIG_CMD_RUN)
U_BOOT_CMD_MKENT ( run , CONFIG_SYS_MAXARGS , 1 , do_run , " " , " " ) ,
# endif
# if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
U_BOOT_CMD_MKENT ( save , 1 , 0 , do_env_save , " " , " " ) ,
# endif
U_BOOT_CMD_MKENT ( set , CONFIG_SYS_MAXARGS , 0 , do_env_set , " " , " " ) ,
} ;
static int do_env ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
cmd_tbl_t * cp ;
/* drop initial "env" arg */
argc - - ;
argv + + ;
cp = find_cmd_tbl ( argv [ 0 ] , cmd_env_sub , ARRAY_SIZE ( cmd_env_sub ) ) ;
if ( cp )
return cp - > cmd ( cmdtp , flag , argc , argv ) ;
cmd_usage ( cmdtp ) ;
return 1 ;
}
U_BOOT_CMD (
env , CONFIG_SYS_MAXARGS , 1 , do_env ,
" environment handling commands " ,
# if defined(CONFIG_CMD_ASKENV)
" ask name [message] [size] - ask for environment variable \n env "
# endif
" default -f - reset default environment \n "
# if defined(CONFIG_CMD_EDITENV)
" env edit name - edit environment variable \n "
# endif
" env export [-t | -b | -c] addr [size] - export environmnt \n "
" env import [-d] [-t | -b | -c] addr [size] - import environmnt \n "
" env print [name ...] - print environment \n "
# if defined(CONFIG_CMD_RUN)
" env run var [...] - run commands in an environment variable \n "
# endif
" env save - save environment \n "
" env set [-f] name [arg ...] \n "
) ;
/*
* Old command line interface , kept for compatibility
*/
# if defined(CONFIG_CMD_EDITENV)
# if defined(CONFIG_CMD_EDITENV)
U_BOOT_CMD (
U_BOOT_CMD (
editenv , 2 , 0 , do_editenv ,
editenv , 2 , 0 , do_env_e dit ,
" edit environment variable " ,
" edit environment variable " ,
" name \n "
" name \n "
" - edit environment variable 'name' "
" - edit environment variable 'name' "
@ -621,7 +888,7 @@ U_BOOT_CMD(
# endif
# endif
U_BOOT_CMD (
U_BOOT_CMD (
printenv , CONFIG_SYS_MAXARGS , 1 , do_printenv ,
printenv , CONFIG_SYS_MAXARGS , 1 , do_env_ print ,
" print environment variables " ,
" print environment variables " ,
" \n - print values of all environment variables \n "
" \n - print values of all environment variables \n "
" printenv name ... \n "
" printenv name ... \n "
@ -629,7 +896,7 @@ U_BOOT_CMD(
) ;
) ;
U_BOOT_CMD (
U_BOOT_CMD (
setenv , CONFIG_SYS_MAXARGS , 0 , do_setenv ,
setenv , CONFIG_SYS_MAXARGS , 0 , do_env_ set ,
" set environment variables " ,
" set environment variables " ,
" name value ... \n "
" name value ... \n "
" - set environment variable 'name' to 'value ...' \n "
" - set environment variable 'name' to 'value ...' \n "
@ -640,7 +907,7 @@ U_BOOT_CMD(
# if defined(CONFIG_CMD_ASKENV)
# if defined(CONFIG_CMD_ASKENV)
U_BOOT_CMD (
U_BOOT_CMD (
askenv , CONFIG_SYS_MAXARGS , 1 , do_askenv ,
askenv , CONFIG_SYS_MAXARGS , 1 , do_env_ ask ,
" get environment variables from stdin " ,
" get environment variables from stdin " ,
" name [message] [size] \n "
" name [message] [size] \n "
" - get environment variable 'name' from stdin (max 'size' chars) \n "
" - get environment variable 'name' from stdin (max 'size' chars) \n "
@ -655,7 +922,6 @@ U_BOOT_CMD(
# endif
# endif
# if defined(CONFIG_CMD_RUN)
# if defined(CONFIG_CMD_RUN)
int do_run ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] ) ;
U_BOOT_CMD (
U_BOOT_CMD (
run , CONFIG_SYS_MAXARGS , 1 , do_run ,
run , CONFIG_SYS_MAXARGS , 1 , do_run ,
" run commands in an environment variable " ,
" run commands in an environment variable " ,