@ -1,5 +1,5 @@
/*
/*
* ( C ) Copyright 2000
* ( C ) Copyright 2000 - 2003
* Wolfgang Denk , DENX Software Engineering , wd @ denx . de .
* Wolfgang Denk , DENX Software Engineering , wd @ denx . de .
*
*
* See file CREDITS for list of people who contributed to this
* See file CREDITS for list of people who contributed to this
@ -12,7 +12,7 @@
*
*
* This program is distributed in the hope that it will be useful ,
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
* GNU General Public License for more details .
*
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU General Public License
@ -34,16 +34,16 @@
# include <linux/mtd/mtd.h>
# include <linux/mtd/mtd.h>
# include "fw_env.h"
# include "fw_env.h"
typedef unsigned char uchar ;
typedef unsigned char uchar ;
# define CMD_GETENV "fw_printenv"
# define CMD_GETENV "fw_printenv"
# define CMD_SETENV "fw_setenv"
# define CMD_SETENV "fw_setenv"
typedef struct envdev_s {
typedef struct envdev_s {
uchar devname [ 16 ] ; /* Device name */
uchar devname [ 16 ] ; /* Device name */
ulong devoff ; /* Device offset */
ulong devoff ; /* Device offset */
ulong env_size ; /* environment size */
ulong env_size ; /* environment size */
ulong erase_size ; /* device erase size */
ulong erase_size ; /* device erase size */
} envdev_t ;
} envdev_t ;
static envdev_t envdevices [ 2 ] ;
static envdev_t envdevices [ 2 ] ;
@ -59,8 +59,8 @@ static int curdev;
# define ENV_SIZE getenvsize()
# define ENV_SIZE getenvsize()
typedef struct environment_s {
typedef struct environment_s {
ulong crc ; /* CRC32 over data bytes */
ulong crc ; /* CRC32 over data bytes */
uchar flags ; /* active or obsolete */
uchar flags ; /* active or obsolete */
uchar * data ;
uchar * data ;
} env_t ;
} env_t ;
@ -77,92 +77,94 @@ static uchar obsolete_flag = 0;
static uchar default_environment [ ] = {
static uchar default_environment [ ] = {
# if defined(CONFIG_BOOTARGS)
# if defined(CONFIG_BOOTARGS)
" bootargs= " CONFIG_BOOTARGS " \0 "
" bootargs= " CONFIG_BOOTARGS " \0 "
# endif
# endif
# if defined(CONFIG_BOOTCOMMAND)
# if defined(CONFIG_BOOTCOMMAND)
" bootcmd= " CONFIG_BOOTCOMMAND " \0 "
" bootcmd= " CONFIG_BOOTCOMMAND " \0 "
# endif
# endif
# if defined(CONFIG_RAMBOOTCOMMAND)
# if defined(CONFIG_RAMBOOTCOMMAND)
" ramboot= " CONFIG_RAMBOOTCOMMAND " \0 "
" ramboot= " CONFIG_RAMBOOTCOMMAND " \0 "
# endif
# endif
# if defined(CONFIG_NFSBOOTCOMMAND)
# if defined(CONFIG_NFSBOOTCOMMAND)
" nfsboot= " CONFIG_NFSBOOTCOMMAND " \0 "
" nfsboot= " CONFIG_NFSBOOTCOMMAND " \0 "
# endif
# endif
# if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
# if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
" bootdelay= " MK_STR ( CONFIG_BOOTDELAY ) " \0 "
" bootdelay= " MK_STR ( CONFIG_BOOTDELAY ) " \0 "
# endif
# endif
# if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
# if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
" baudrate= " MK_STR ( CONFIG_BAUDRATE ) " \0 "
" baudrate= " MK_STR ( CONFIG_BAUDRATE ) " \0 "
# endif
# endif
# ifdef CONFIG_LOADS_ECHO
# ifdef CONFIG_LOADS_ECHO
" loads_echo= " MK_STR ( CONFIG_LOADS_ECHO ) " \0 "
" loads_echo= " MK_STR ( CONFIG_LOADS_ECHO ) " \0 "
# endif
# endif
# ifdef CONFIG_ETHADDR
# ifdef CONFIG_ETHADDR
" ethaddr= " MK_STR ( CONFIG_ETHADDR ) " \0 "
" ethaddr= " MK_STR ( CONFIG_ETHADDR ) " \0 "
# endif
# endif
# ifdef CONFIG_ETH1ADDR
# ifdef CONFIG_ETH1ADDR
" eth1addr= " MK_STR ( CONFIG_ETH1ADDR ) " \0 "
" eth1addr= " MK_STR ( CONFIG_ETH1ADDR ) " \0 "
# endif
# endif
# ifdef CONFIG_ETH2ADDR
# ifdef CONFIG_ETH2ADDR
" eth2addr= " MK_STR ( CONFIG_ETH2ADDR ) " \0 "
" eth2addr= " MK_STR ( CONFIG_ETH2ADDR ) " \0 "
# endif
# endif
# ifdef CONFIG_ETHPRIME
# ifdef CONFIG_ETHPRIME
" ethprime= " CONFIG_ETHPRIME " \0 "
" ethprime= " CONFIG_ETHPRIME " \0 "
# endif
# endif
# ifdef CONFIG_IPADDR
# ifdef CONFIG_IPADDR
" ipaddr= " MK_STR ( CONFIG_IPADDR ) " \0 "
" ipaddr= " MK_STR ( CONFIG_IPADDR ) " \0 "
# endif
# endif
# ifdef CONFIG_SERVERIP
# ifdef CONFIG_SERVERIP
" serverip= " MK_STR ( CONFIG_SERVERIP ) " \0 "
" serverip= " MK_STR ( CONFIG_SERVERIP ) " \0 "
# endif
# endif
# ifdef CFG_AUTOLOAD
# ifdef CFG_AUTOLOAD
" autoload= " CFG_AUTOLOAD " \0 "
" autoload= " CFG_AUTOLOAD " \0 "
# endif
# endif
# ifdef CONFIG_ROOTPATH
# ifdef CONFIG_ROOTPATH
" rootpath= " MK_STR ( CONFIG_ROOTPATH ) " \0 "
" rootpath= " MK_STR ( CONFIG_ROOTPATH ) " \0 "
# endif
# endif
# ifdef CONFIG_GATEWAYIP
# ifdef CONFIG_GATEWAYIP
" gatewayip= " MK_STR ( CONFIG_GATEWAYIP ) " \0 "
" gatewayip= " MK_STR ( CONFIG_GATEWAYIP ) " \0 "
# endif
# endif
# ifdef CONFIG_NETMASK
# ifdef CONFIG_NETMASK
" netmask= " MK_STR ( CONFIG_NETMASK ) " \0 "
" netmask= " MK_STR ( CONFIG_NETMASK ) " \0 "
# endif
# endif
# ifdef CONFIG_HOSTNAME
# ifdef CONFIG_HOSTNAME
" hostname= " MK_STR ( CONFIG_HOSTNAME ) " \0 "
" hostname= " MK_STR ( CONFIG_HOSTNAME ) " \0 "
# endif
# endif
# ifdef CONFIG_BOOTFILE
# ifdef CONFIG_BOOTFILE
" bootfile= " MK_STR ( CONFIG_BOOTFILE ) " \0 "
" bootfile= " MK_STR ( CONFIG_BOOTFILE ) " \0 "
# endif
# endif
# ifdef CONFIG_LOADADDR
# ifdef CONFIG_LOADADDR
" loadaddr= " MK_STR ( CONFIG_LOADADDR ) " \0 "
" loadaddr= " MK_STR ( CONFIG_LOADADDR ) " \0 "
# endif
# endif
# ifdef CONFIG_PREBOOT
# ifdef CONFIG_PREBOOT
" preboot= " CONFIG_PREBOOT " \0 "
" preboot= " CONFIG_PREBOOT " \0 "
# endif
# endif
# ifdef CONFIG_CLOCKS_IN_MHZ
# ifdef CONFIG_CLOCKS_IN_MHZ
" clocks_in_mhz= " " 1 " " \0 "
" clocks_in_mhz= " " 1 " " \0 "
# endif
# endif
# if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
# if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
" pcidelay= " MK_STR ( CONFIG_PCI_BOOTDELAY ) " \0 "
" pcidelay= " MK_STR ( CONFIG_PCI_BOOTDELAY ) " \0 "
# endif
# endif
# ifdef CONFIG_EXTRA_ENV_SETTINGS
# ifdef CONFIG_EXTRA_ENV_SETTINGS
CONFIG_EXTRA_ENV_SETTINGS
CONFIG_EXTRA_ENV_SETTINGS
# endif
# endif
" \0 " /* Termimate env_t data with 2 NULs */
" \0 " /* Termimate env_t data with 2 NULs */
} ;
} ;
static int flash_io ( int mode ) ;
static int flash_io ( int mode ) ;
static uchar * envmatch ( uchar * s1 , uchar * s2 ) ;
static uchar * envmatch ( uchar * s1 , uchar * s2 ) ;
static int env_init ( void ) ;
static int env_init ( void ) ;
static int parse_config ( void ) ;
static int parse_config ( void ) ;
# if defined(CONFIG_FILE)
# if defined(CONFIG_FILE)
static int get_config ( char * ) ;
static int get_config ( char * ) ;
# endif
# endif
static inline ulong getenvsize ( void )
static inline ulong getenvsize ( void )
{
{
ulong rc = CFG_ENV_SIZE - sizeof ( long ) ;
ulong rc = CFG_ENV_SIZE - sizeof ( long ) ;
if ( HaveRedundEnv )
if ( HaveRedundEnv )
rc - = sizeof ( char ) ;
rc - = sizeof ( char ) ;
return rc ;
return rc ;
}
}
@ -174,20 +176,20 @@ unsigned char *fw_getenv (unsigned char *name)
{
{
uchar * env , * nxt ;
uchar * env , * nxt ;
if ( env_init ( ) )
if ( env_init ( ) )
return ( NULL ) ;
return ( NULL ) ;
for ( env = environment . data ; * env ; env = nxt + 1 ) {
for ( env = environment . data ; * env ; env = nxt + 1 ) {
uchar * val ;
uchar * val ;
for ( nxt = env ; * nxt ; + + nxt ) {
for ( nxt = env ; * nxt ; + + nxt ) {
if ( nxt > = & environment . data [ ENV_SIZE ] ) {
if ( nxt > = & environment . data [ ENV_SIZE ] ) {
fprintf ( stderr , " ## Error: "
fprintf ( stderr , " ## Error: "
" environment not terminated \n " ) ;
" environment not terminated \n " ) ;
return ( NULL ) ;
return ( NULL ) ;
}
}
}
}
val = envmatch ( name , env ) ;
val = envmatch ( name , env ) ;
if ( ! val )
if ( ! val )
continue ;
continue ;
return ( val ) ;
return ( val ) ;
@ -199,17 +201,17 @@ unsigned char *fw_getenv (unsigned char *name)
* Print the current definition of one , or more , or all
* Print the current definition of one , or more , or all
* environment variables
* environment variables
*/
*/
void fw_printenv ( int argc , char * argv [ ] )
void fw_printenv ( int argc , char * argv [ ] )
{
{
uchar * env , * nxt ;
uchar * env , * nxt ;
int i , n_flag ;
int i , n_flag ;
if ( env_init ( ) )
if ( env_init ( ) )
return ;
return ;
if ( argc = = 1 ) { /* Print all env variables */
if ( argc = = 1 ) { /* Print all env variables */
for ( env = environment . data ; * env ; env = nxt + 1 ) {
for ( env = environment . data ; * env ; env = nxt + 1 ) {
for ( nxt = env ; * nxt ; + + nxt ) {
for ( nxt = env ; * nxt ; + + nxt ) {
if ( nxt > = & environment . data [ ENV_SIZE ] ) {
if ( nxt > = & environment . data [ ENV_SIZE ] ) {
fprintf ( stderr , " ## Error: "
fprintf ( stderr , " ## Error: "
" environment not terminated \n " ) ;
" environment not terminated \n " ) ;
@ -217,12 +219,12 @@ void fw_printenv(int argc, char *argv[])
}
}
}
}
printf ( " %s \n " , env ) ;
printf ( " %s \n " , env ) ;
}
}
return ;
return ;
}
}
if ( strcmp ( argv [ 1 ] , " -n " ) = = 0 ) {
if ( strcmp ( argv [ 1 ] , " -n " ) = = 0 ) {
n_flag = 1 ;
n_flag = 1 ;
+ + argv ;
+ + argv ;
- - argc ;
- - argc ;
@ -235,32 +237,31 @@ void fw_printenv(int argc, char *argv[])
n_flag = 0 ;
n_flag = 0 ;
}
}
for ( i = 1 ; i < argc ; + + i ) { /* print single env variables */
for ( i = 1 ; i < argc ; + + i ) { /* print single env variables */
uchar * name = argv [ i ] ;
uchar * name = argv [ i ] ;
uchar * val = NULL ;
uchar * val = NULL ;
for ( env = environment . data ; * env ; env = nxt + 1 ) {
for ( env = environment . data ; * env ; env = nxt + 1 ) {
for ( nxt = env ; * nxt ; + + nxt ) {
for ( nxt = env ; * nxt ; + + nxt ) {
if ( nxt > = & environment . data [ ENV_SIZE ] ) {
if ( nxt > = & environment . data [ ENV_SIZE ] ) {
fprintf ( stderr , " ## Error: "
fprintf ( stderr , " ## Error: "
" environment not terminated \n " ) ;
" environment not terminated \n " ) ;
return ;
return ;
}
}
}
}
val = envmatch ( name , env ) ;
val = envmatch ( name , env ) ;
if ( val ) {
if ( val ) {
if ( ! n_flag ) {
if ( ! n_flag ) {
fputs ( name , stdout ) ;
fputs ( name , stdout ) ;
putc ( ' = ' , stdout ) ;
putc ( ' = ' , stdout ) ;
}
}
puts ( val ) ;
puts ( val ) ;
break ;
break ;
}
}
}
}
if ( ! val )
if ( ! val )
fprintf ( stderr , " ## Error: \" %s \" not defined \n " ,
fprintf ( stderr , " ## Error: \" %s \" not defined \n " , name ) ;
name ) ;
}
}
}
}
@ -274,7 +275,7 @@ void fw_printenv(int argc, char *argv[])
*/
*/
int fw_setenv ( int argc , char * argv [ ] )
int fw_setenv ( int argc , char * argv [ ] )
{
{
int i , len ;
int i , len ;
uchar * env , * nxt ;
uchar * env , * nxt ;
uchar * oldval = NULL ;
uchar * oldval = NULL ;
uchar * name ;
uchar * name ;
@ -283,7 +284,7 @@ int fw_setenv (int argc, char *argv[])
return ( EINVAL ) ;
return ( EINVAL ) ;
}
}
if ( env_init ( ) )
if ( env_init ( ) )
return ( errno ) ;
return ( errno ) ;
name = argv [ 1 ] ;
name = argv [ 1 ] ;
@ -291,15 +292,15 @@ int fw_setenv (int argc, char *argv[])
/*
/*
* search if variable with this name already exists
* search if variable with this name already exists
*/
*/
for ( env = environment . data ; * env ; env = nxt + 1 ) {
for ( nxt = env = environment . data ; * env ; env = nxt + 1 ) {
for ( nxt = env ; * nxt ; + + nxt ) {
for ( nxt = env ; * nxt ; + + nxt ) {
if ( nxt > = & environment . data [ ENV_SIZE ] ) {
if ( nxt > = & environment . data [ ENV_SIZE ] ) {
fprintf ( stderr , " ## Error: "
fprintf ( stderr , " ## Error: "
" environment not terminated \n " ) ;
" environment not terminated \n " ) ;
return ( EINVAL ) ;
return ( EINVAL ) ;
}
}
}
}
if ( ( oldval = envmatch ( name , env ) ) ! = NULL )
if ( ( oldval = envmatch ( name , env ) ) ! = NULL )
break ;
break ;
}
}
@ -311,7 +312,7 @@ int fw_setenv (int argc, char *argv[])
* Ethernet Address and serial # can be set only once
* Ethernet Address and serial # can be set only once
*/
*/
if ( ( strcmp ( name , " ethaddr " ) = = 0 ) | |
if ( ( strcmp ( name , " ethaddr " ) = = 0 ) | |
( strcmp ( name , " serial# " ) = = 0 ) ) {
( strcmp ( name , " serial# " ) = = 0 ) ) {
fprintf ( stderr , " Can't overwrite \" %s \" \n " , name ) ;
fprintf ( stderr , " Can't overwrite \" %s \" \n " , name ) ;
return ( EROFS ) ;
return ( EROFS ) ;
}
}
@ -336,20 +337,19 @@ int fw_setenv (int argc, char *argv[])
/*
/*
* Append new definition at the end
* Append new definition at the end
*/
*/
for ( env = environment . data ; * env | | * ( env + 1 ) ; + + env )
for ( env = environment . data ; * env | | * ( env + 1 ) ; + + env ) ;
;
if ( env > environment . data )
if ( env > environment . data )
+ + env ;
+ + env ;
/*
/*
* Overflow when :
* Overflow when :
* " name " + " = " + " val " + " \0 \0 " > CFG_ENV_SIZE - ( env - environment )
* " name " + " = " + " val " + " \0 \0 " > CFG_ENV_SIZE - ( env - environment )
*/
*/
len = strlen ( name ) + 2 ;
len = strlen ( name ) + 2 ;
/* add '=' for first arg, ' ' for all others */
/* add '=' for first arg, ' ' for all others */
for ( i = 2 ; i < argc ; + + i ) {
for ( i = 2 ; i < argc ; + + i ) {
len + = strlen ( argv [ i ] ) + 1 ;
len + = strlen ( argv [ i ] ) + 1 ;
}
}
if ( len > ( & environment . data [ ENV_SIZE ] - env ) ) {
if ( len > ( & environment . data [ ENV_SIZE ] - env ) ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Error: environment overflow, \" %s \" deleted \n " ,
" Error: environment overflow, \" %s \" deleted \n " ,
name ) ;
name ) ;
@ -357,26 +357,24 @@ int fw_setenv (int argc, char *argv[])
}
}
while ( ( * env = * name + + ) ! = ' \0 ' )
while ( ( * env = * name + + ) ! = ' \0 ' )
env + + ;
env + + ;
for ( i = 2 ; i < argc ; + + i ) {
for ( i = 2 ; i < argc ; + + i ) {
uchar * val = argv [ i ] ;
uchar * val = argv [ i ] ;
* env = ( i = = 2 ) ? ' = ' : ' ' ;
* env = ( i = = 2 ) ? ' = ' : ' ' ;
while ( ( * + + env = * val + + ) ! = ' \0 ' )
while ( ( * + + env = * val + + ) ! = ' \0 ' ) ;
;
}
}
/* end is marked with double '\0' */
/* end is marked with double '\0' */
* + + env = ' \0 ' ;
* + + env = ' \0 ' ;
WRITE_FLASH :
WRITE_FLASH :
/* Update CRC */
/* Update CRC */
environment . crc = crc32 ( 0 , environment . data , ENV_SIZE ) ;
environment . crc = crc32 ( 0 , environment . data , ENV_SIZE ) ;
/* write environment back to flash */
/* write environment back to flash */
if ( flash_io ( O_RDWR ) ) {
if ( flash_io ( O_RDWR ) ) {
fprintf ( stderr ,
fprintf ( stderr , " Error: can't write fw_env to flash \n " ) ;
" Error: can't write fw_env to flash \n " ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
@ -389,166 +387,172 @@ static int flash_io (int mode)
erase_info_t erase ;
erase_info_t erase ;
char * data ;
char * data ;
if ( ( fd = open ( DEVNAME ( curdev ) , mode ) ) < 0 ) {
if ( ( fd = open ( DEVNAME ( curdev ) , mode ) ) < 0 ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Can't open %s: %s \n " ,
" Can't open %s: %s \n " ,
DEVNAME ( curdev ) , strerror ( errno ) ) ;
DEVNAME ( curdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
len = sizeof ( environment . crc ) ;
len = sizeof ( environment . crc ) ;
if ( HaveRedundEnv ) {
if ( HaveRedundEnv ) {
len + = sizeof ( environment . flags ) ;
len + = sizeof ( environment . flags ) ;
}
}
if ( mode = = O_RDWR ) {
if ( mode = = O_RDWR ) {
if ( HaveRedundEnv ) {
if ( HaveRedundEnv ) {
/* switch to next partition for writing */
/* switch to next partition for writing */
otherdev = ! curdev ;
otherdev = ! curdev ;
if ( ( fdr = open ( DEVNAME ( otherdev ) , mode ) ) < 0 ) {
if ( ( fdr = open ( DEVNAME ( otherdev ) , mode ) ) < 0 ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Can't open %s: %s \n " ,
" Can't open %s: %s \n " ,
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
DEVNAME ( otherdev ) ,
strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
} else {
} else {
otherdev = curdev ;
otherdev = curdev ;
fdr = fd ;
fdr = fd ;
}
}
printf ( " Unlocking flash... \n " ) ;
printf ( " Unlocking flash... \n " ) ;
erase . length = DEVESIZE ( otherdev ) ;
erase . length = DEVESIZE ( otherdev ) ;
erase . start = DEVOFFSET ( otherdev ) ;
erase . start = DEVOFFSET ( otherdev ) ;
ioctl ( fdr , MEMUNLOCK , & erase ) ;
ioctl ( fdr , MEMUNLOCK , & erase ) ;
if ( HaveRedundEnv ) {
if ( HaveRedundEnv ) {
erase . length = DEVESIZE ( curdev ) ;
erase . length = DEVESIZE ( curdev ) ;
erase . start = DEVOFFSET ( curdev ) ;
erase . start = DEVOFFSET ( curdev ) ;
ioctl ( fd , MEMUNLOCK , & erase ) ;
ioctl ( fd , MEMUNLOCK , & erase ) ;
environment . flags = active_flag ;
environment . flags = active_flag ;
}
}
printf ( " Done \n " ) ;
printf ( " Done \n " ) ;
resid = DEVESIZE ( otherdev ) - CFG_ENV_SIZE ;
resid = DEVESIZE ( otherdev ) - CFG_ENV_SIZE ;
if ( resid ) {
if ( resid ) {
if ( ( data = malloc ( resid ) ) = = NULL ) {
if ( ( data = malloc ( resid ) ) = = NULL ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Cannot malloc %d bytes: %s \n " ,
" Cannot malloc %d bytes: %s \n " ,
resid , strerror ( errno ) ) ;
resid ,
strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
if ( lseek ( fdr , DEVOFFSET ( otherdev ) + CFG_ENV_SIZE , SEEK_SET ) = = - 1 ) {
if ( lseek ( fdr , DEVOFFSET ( otherdev ) + CFG_ENV_SIZE , SEEK_SET )
fprintf ( stderr ,
= = - 1 ) {
" seek error on %s: %s \n " ,
fprintf ( stderr , " seek error on %s: %s \n " ,
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
DEVNAME ( otherdev ) ,
strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
if ( ( rc = read ( fdr , data , resid ) ) ! = resid ) {
if ( ( rc = read ( fdr , data , resid ) ) ! = resid ) {
fprintf ( stderr ,
fprintf ( stderr ,
" read error on %s: %s \n " ,
" read error on %s: %s \n " ,
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
DEVNAME ( otherdev ) ,
strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
}
}
printf ( " Erasing old environment... \n " ) ;
printf ( " Erasing old environment... \n " ) ;
erase . length = DEVESIZE ( otherdev ) ;
erase . length = DEVESIZE ( otherdev ) ;
erase . start = DEVOFFSET ( otherdev ) ;
erase . start = DEVOFFSET ( otherdev ) ;
if ( ioctl ( fdr , MEMERASE , & erase ) ! = 0 ) {
if ( ioctl ( fdr , MEMERASE , & erase ) ! = 0 ) {
fprintf ( stderr , " MTD erase error on %s: %s \n " ,
fprintf ( stderr , " MTD erase error on %s: %s \n " ,
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
DEVNAME ( otherdev ) ,
strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
printf ( " Done \n " ) ;
printf ( " Done \n " ) ;
printf ( " Writing environment to %s... \n " , DEVNAME ( otherdev ) ) ;
printf ( " Writing environment to %s... \n " , DEVNAME ( otherdev ) ) ;
if ( lseek ( fdr , DEVOFFSET ( otherdev ) , SEEK_SET ) = = - 1 ) {
if ( lseek ( fdr , DEVOFFSET ( otherdev ) , SEEK_SET ) = = - 1 ) {
fprintf ( stderr ,
fprintf ( stderr ,
" seek error on %s: %s \n " ,
" seek error on %s: %s \n " ,
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
if ( write ( fdr , & environment , len ) ! = len ) {
if ( write ( fdr , & environment , len ) ! = len ) {
fprintf ( stderr ,
fprintf ( stderr ,
" CRC write error on %s: %s \n " ,
" CRC write error on %s: %s \n " ,
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
if ( write ( fdr , environment . data , ENV_SIZE ) ! = ENV_SIZE ) {
if ( write ( fdr , environment . data , ENV_SIZE ) ! = ENV_SIZE ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Write error on %s: %s \n " ,
" Write error on %s: %s \n " ,
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
if ( resid ) {
if ( resid ) {
if ( write ( fdr , data , resid ) ! = resid ) {
if ( write ( fdr , data , resid ) ! = resid ) {
fprintf ( stderr ,
fprintf ( stderr ,
" write error on %s: %s \n " ,
" write error on %s: %s \n " ,
DEVNAME ( curdev ) , strerror ( errno ) ) ;
DEVNAME ( curdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
free ( data ) ;
free ( data ) ;
}
}
if ( HaveRedundEnv ) {
if ( HaveRedundEnv ) {
/* change flag on current active env partition */
/* change flag on current active env partition */
if ( lseek ( fd , DEVOFFSET ( curdev ) + sizeof ( ulong ) , SEEK_SET ) = = - 1 ) {
if ( lseek ( fd , DEVOFFSET ( curdev ) + sizeof ( ulong ) , SEEK_SET )
fprintf ( stderr ,
= = - 1 ) {
" seek error on %s: %s \n " ,
fprintf ( stderr , " seek error on %s: %s \n " ,
DEVNAME ( curdev ) , strerror ( errno ) ) ;
DEVNAME ( curdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
if ( write ( fd , & obsolete_flag , sizeof ( obsolete_flag ) ) ! =
if ( write ( fd , & obsolete_flag , sizeof ( obsolete_flag ) ) ! =
sizeof ( obsolete_flag ) ) {
sizeof ( obsolete_flag ) ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Write error on %s: %s \n " ,
" Write error on %s: %s \n " ,
DEVNAME ( curdev ) , strerror ( errno ) ) ;
DEVNAME ( curdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
}
}
printf ( " Done \n " ) ;
printf ( " Done \n " ) ;
printf ( " Locking ... \n " ) ;
printf ( " Locking ... \n " ) ;
erase . length = DEVESIZE ( otherdev ) ;
erase . length = DEVESIZE ( otherdev ) ;
erase . start = DEVOFFSET ( otherdev ) ;
erase . start = DEVOFFSET ( otherdev ) ;
ioctl ( fdr , MEMLOCK , & erase ) ;
ioctl ( fdr , MEMLOCK , & erase ) ;
if ( HaveRedundEnv ) {
if ( HaveRedundEnv ) {
erase . length = DEVESIZE ( curdev ) ;
erase . length = DEVESIZE ( curdev ) ;
erase . start = DEVOFFSET ( curdev ) ;
erase . start = DEVOFFSET ( curdev ) ;
ioctl ( fd , MEMLOCK , & erase ) ;
ioctl ( fd , MEMLOCK , & erase ) ;
if ( close ( fdr ) ) {
if ( close ( fdr ) ) {
fprintf ( stderr ,
fprintf ( stderr ,
" I/O error on %s: %s \n " ,
" I/O error on %s: %s \n " ,
DEVNAME ( otherdev ) , strerror ( errno ) ) ;
DEVNAME ( otherdev ) ,
strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
}
}
printf ( " Done \n " ) ;
printf ( " Done \n " ) ;
} else {
} else {
if ( lseek ( fd , DEVOFFSET ( curdev ) , SEEK_SET ) = = - 1 ) {
if ( lseek ( fd , DEVOFFSET ( curdev ) , SEEK_SET ) = = - 1 ) {
fprintf ( stderr ,
fprintf ( stderr ,
" seek error on %s: %s \n " ,
" seek error on %s: %s \n " ,
DEVNAME ( curdev ) , strerror ( errno ) ) ;
DEVNAME ( curdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
if ( read ( fd , & environment , len ) ! = len ) {
if ( read ( fd , & environment , len ) ! = len ) {
fprintf ( stderr ,
fprintf ( stderr ,
" CRC read error on %s: %s \n " ,
" CRC read error on %s: %s \n " ,
DEVNAME ( curdev ) , strerror ( errno ) ) ;
DEVNAME ( curdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
if ( ( rc = read ( fd , environment . data , ENV_SIZE ) ) ! = ENV_SIZE ) {
if ( ( rc = read ( fd , environment . data , ENV_SIZE ) ) ! = ENV_SIZE ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Read error on %s: %s \n " ,
" Read error on %s: %s \n " ,
DEVNAME ( curdev ) , strerror ( errno ) ) ;
DEVNAME ( curdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
}
}
if ( close ( fd ) ) {
if ( close ( fd ) ) {
fprintf ( stderr ,
fprintf ( stderr ,
" I/O error on %s: %s \n " ,
" I/O error on %s: %s \n " ,
DEVNAME ( curdev ) , strerror ( errno ) ) ;
DEVNAME ( curdev ) , strerror ( errno ) ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
@ -562,22 +566,21 @@ static int flash_io (int mode)
* If the names match , return the value of s2 , else NULL .
* If the names match , return the value of s2 , else NULL .
*/
*/
static uchar *
static uchar * envmatch ( uchar * s1 , uchar * s2 )
envmatch ( uchar * s1 , uchar * s2 )
{
{
while ( * s1 = = * s2 + + )
while ( * s1 = = * s2 + + )
if ( * s1 + + = = ' = ' )
if ( * s1 + + = = ' = ' )
return ( s2 ) ;
return ( s2 ) ;
if ( * s1 = = ' \0 ' & & * ( s2 - 1 ) = = ' = ' )
if ( * s1 = = ' \0 ' & & * ( s2 - 1 ) = = ' = ' )
return ( s2 ) ;
return ( s2 ) ;
return ( NULL ) ;
return ( NULL ) ;
}
}
/*
/*
* Prevent confusion if running from erased flash memory
* Prevent confusion if running from erased flash memory
*/
*/
static int env_init ( void )
static int env_init ( void )
{
{
int crc1 , crc1_ok ;
int crc1 , crc1_ok ;
uchar * addr1 ;
uchar * addr1 ;
@ -585,151 +588,142 @@ static int env_init(void)
int crc2 , crc2_ok ;
int crc2 , crc2_ok ;
uchar flag1 , flag2 , * addr2 ;
uchar flag1 , flag2 , * addr2 ;
if ( parse_config ( ) ) /* should fill envdevices */
if ( parse_config ( ) ) /* should fill envdevices */
return 1 ;
return 1 ;
if ( ( addr1 = calloc ( 1 , ENV_SIZE ) ) = = NULL ) {
if ( ( addr1 = calloc ( 1 , ENV_SIZE ) ) = = NULL ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Not enough memory for environment (%ld bytes) \n " ,
" Not enough memory for environment (%ld bytes) \n " ,
ENV_SIZE ) ;
ENV_SIZE ) ;
return ( errno ) ;
return ( errno ) ;
}
}
/* read environment from FLASH to local buffer */
/* read environment from FLASH to local buffer */
environment . data = addr1 ;
environment . data = addr1 ;
curdev = 0 ;
curdev = 0 ;
if ( flash_io ( O_RDONLY ) ) {
if ( flash_io ( O_RDONLY ) ) {
return ( errno ) ;
return ( errno ) ;
}
}
crc1_ok = ( ( crc1 = crc32 ( 0 , environment . data , ENV_SIZE ) )
crc1_ok = ( ( crc1 = crc32 ( 0 , environment . data , ENV_SIZE ) )
= = environment . crc ) ;
= = environment . crc ) ;
if ( ! HaveRedundEnv ) {
if ( ! HaveRedundEnv ) {
if ( ! crc1_ok ) {
if ( ! crc1_ok ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Warning: Bad CRC, using default environment \n " ) ;
" Warning: Bad CRC, using default environment \n " ) ;
environment . data = default_environment ;
environment . data = default_environment ;
free ( addr1 ) ;
free ( addr1 ) ;
}
}
} else {
} else {
flag1 = environment . flags ;
flag1 = environment . flags ;
curdev = 1 ;
curdev = 1 ;
if ( ( addr2 = calloc ( 1 , ENV_SIZE ) ) = = NULL ) {
if ( ( addr2 = calloc ( 1 , ENV_SIZE ) ) = = NULL ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Not enough memory for environment (%ld bytes) \n " ,
" Not enough memory for environment (%ld bytes) \n " ,
ENV_SIZE ) ;
ENV_SIZE ) ;
return ( errno ) ;
return ( errno ) ;
}
}
environment . data = addr2 ;
environment . data = addr2 ;
if ( flash_io ( O_RDONLY ) ) {
if ( flash_io ( O_RDONLY ) ) {
return ( errno ) ;
return ( errno ) ;
}
}
crc2_ok = ( ( crc2 = crc32 ( 0 , environment . data , ENV_SIZE ) )
crc2_ok = ( ( crc2 = crc32 ( 0 , environment . data , ENV_SIZE ) )
= = environment . crc ) ;
= = environment . crc ) ;
flag2 = environment . flags ;
flag2 = environment . flags ;
if ( crc1_ok & & ! crc2_ok ) {
if ( crc1_ok & & ! crc2_ok ) {
environment . data = addr1 ;
environment . data = addr1 ;
environment . flags = flag1 ;
environment . flags = flag1 ;
environment . crc = crc1 ;
environment . crc = crc1 ;
curdev = 0 ;
curdev = 0 ;
free ( addr2 ) ;
free ( addr2 ) ;
}
} else if ( ! crc1_ok & & crc2_ok ) {
else if ( ! crc1_ok & & crc2_ok ) {
environment . data = addr2 ;
environment . data = addr2 ;
environment . flags = flag2 ;
environment . flags = flag2 ;
environment . crc = crc2 ;
environment . crc = crc2 ;
curdev = 1 ;
curdev = 1 ;
free ( addr1 ) ;
free ( addr1 ) ;
}
} else if ( ! crc1_ok & & ! crc2_ok ) {
else if ( ! crc1_ok & & ! crc2_ok ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Warning: Bad CRC, using default environment \n " ) ;
" Warning: Bad CRC, using default environment \n " ) ;
environment . data = default_environment ;
environment . data = default_environment ;
curdev = 0 ;
curdev = 0 ;
free ( addr2 ) ;
free ( addr2 ) ;
free ( addr1 ) ;
free ( addr1 ) ;
}
} else if ( flag1 = = active_flag & & flag2 = = obsolete_flag ) {
else if ( flag1 = = active_flag & & flag2 = = obsolete_flag ) {
environment . data = addr1 ;
environment . data = addr1 ;
environment . flags = flag1 ;
environment . flags = flag1 ;
environment . crc = crc1 ;
environment . crc = crc1 ;
curdev = 0 ;
curdev = 0 ;
free ( addr2 ) ;
free ( addr2 ) ;
}
} else if ( flag1 = = obsolete_flag & & flag2 = = active_flag ) {
else if ( flag1 = = obsolete_flag & & flag2 = = active_flag ) {
environment . data = addr2 ;
environment . data = addr2 ;
environment . flags = flag2 ;
environment . flags = flag2 ;
environment . crc = crc2 ;
environment . crc = crc2 ;
curdev = 1 ;
curdev = 1 ;
free ( addr1 ) ;
free ( addr1 ) ;
}
} else if ( flag1 = = flag2 ) {
else if ( flag1 = = flag2 ) {
environment . data = addr1 ;
environment . data = addr1 ;
environment . flags = flag1 ;
environment . flags = flag1 ;
environment . crc = crc1 ;
environment . crc = crc1 ;
curdev = 0 ;
curdev = 0 ;
free ( addr2 ) ;
free ( addr2 ) ;
}
} else if ( flag1 = = 0xFF ) {
else if ( flag1 = = 0xFF ) {
environment . data = addr1 ;
environment . data = addr1 ;
environment . flags = flag1 ;
environment . flags = flag1 ;
environment . crc = crc1 ;
environment . crc = crc1 ;
curdev = 0 ;
curdev = 0 ;
free ( addr2 ) ;
free ( addr2 ) ;
}
} else if ( flag2 = = 0xFF ) {
else if ( flag2 = = 0xFF ) {
environment . data = addr2 ;
environment . data = addr2 ;
environment . flags = flag2 ;
environment . flags = flag2 ;
environment . crc = crc2 ;
environment . crc = crc2 ;
curdev = 1 ;
curdev = 1 ;
free ( addr1 ) ;
free ( addr1 ) ;
}
}
}
}
return ( 0 ) ;
return ( 0 ) ;
}
}
static int parse_config ( )
static int parse_config ( )
{
{
struct stat st ;
struct stat st ;
# if defined(CONFIG_FILE)
# if defined(CONFIG_FILE)
/* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */
/* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */
if ( get_config ( CONFIG_FILE ) ) {
if ( get_config ( CONFIG_FILE ) ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Cannot parse config file: %s \n " ,
" Cannot parse config file: %s \n " , strerror ( errno ) ) ;
strerror ( errno ) ) ;
return 1 ;
return 1 ;
}
}
# else
# else
strcpy ( DEVNAME ( 0 ) , DEVICE1_NAME ) ;
strcpy ( DEVNAME ( 0 ) , DEVICE1_NAME ) ;
DEVOFFSET ( 0 ) = DEVICE1_OFFSET ;
DEVOFFSET ( 0 ) = DEVICE1_OFFSET ;
ENVSIZE ( 0 ) = ENV1_SIZE ;
ENVSIZE ( 0 ) = ENV1_SIZE ;
DEVESIZE ( 0 ) = DEVICE1_ESIZE ;
DEVESIZE ( 0 ) = DEVICE1_ESIZE ;
# ifdef HAVE_REDUND
# ifdef HAVE_REDUND
strcpy ( DEVNAME ( 1 ) , DEVICE2_NAME ) ;
strcpy ( DEVNAME ( 1 ) , DEVICE2_NAME ) ;
DEVOFFSET ( 1 ) = DEVICE2_OFFSET ;
DEVOFFSET ( 1 ) = DEVICE2_OFFSET ;
ENVSIZE ( 1 ) = ENV2_SIZE ;
ENVSIZE ( 1 ) = ENV2_SIZE ;
DEVESIZE ( 1 ) = DEVICE2_ESIZE ;
DEVESIZE ( 1 ) = DEVICE2_ESIZE ;
HaveRedundEnv = 1 ;
HaveRedundEnv = 1 ;
# endif
# endif
# endif
# endif
if ( stat ( DEVNAME ( 0 ) , & st ) ) {
if ( stat ( DEVNAME ( 0 ) , & st ) ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Cannot access MTD device %s: %s \n " ,
" Cannot access MTD device %s: %s \n " ,
DEVNAME ( 0 ) , strerror ( errno ) ) ;
DEVNAME ( 0 ) , strerror ( errno ) ) ;
return 1 ;
return 1 ;
}
}
if ( HaveRedundEnv & & stat ( DEVNAME ( 1 ) , & st ) ) {
if ( HaveRedundEnv & & stat ( DEVNAME ( 1 ) , & st ) ) {
fprintf ( stderr ,
fprintf ( stderr ,
" Cannot access MTD device %s: %s \n " ,
" Cannot access MTD device %s: %s \n " ,
DEVNAME ( 2 ) , strerror ( errno ) ) ;
DEVNAME ( 2 ) , strerror ( errno ) ) ;
return 1 ;
return 1 ;
}
}
return 0 ;
return 0 ;
@ -743,26 +737,28 @@ static int get_config (char *fname)
int rc ;
int rc ;
char dump [ 128 ] ;
char dump [ 128 ] ;
if ( ( fp = fopen ( fname , " r " ) ) = = NULL ) {
if ( ( fp = fopen ( fname , " r " ) ) = = NULL ) {
return 1 ;
return 1 ;
}
}
while ( ( i < 2 ) & &
while ( ( i < 2 ) & & ( ( rc = fscanf ( fp , " %s %lx %lx %lx " ,
( ( rc = fscanf ( fp , " %s %lx %lx %lx " ,
DEVNAME ( i ) ,
DEVNAME ( i ) , & DEVOFFSET ( i ) , & ENVSIZE ( i ) , & DEVESIZE ( i ) ) ) ! = EOF ) ) {
& DEVOFFSET ( i ) ,
& ENVSIZE ( i ) ,
& DEVESIZE ( i ) ) ) ! = EOF ) ) {
/* Skip incomplete conversions and comment strings */
/* Skip incomplete conversions and comment strings */
if ( ( rc < 3 ) | | ( * DEVNAME ( i ) = = ' # ' ) ) {
if ( ( rc < 3 ) | | ( * DEVNAME ( i ) = = ' # ' ) ) {
fgets ( dump , sizeof ( dump ) , fp ) ; /* Consume till end */
fgets ( dump , sizeof ( dump ) , fp ) ; /* Consume till end */
continue ;
continue ;
}
}
i + + ;
i + + ;
}
}
fclose ( fp ) ;
fclose ( fp ) ;
HaveRedundEnv = i - 1 ;
HaveRedundEnv = i - 1 ;
if ( ! i ) { /* No valid entries found */
if ( ! i ) { /* No valid entries found */
errno = EINVAL ;
errno = EINVAL ;
return 1 ;
return 1 ;
} else
} else