diff options
author | wdenk <wdenk> | 2002-12-17 01:51:00 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2002-12-17 01:51:00 +0000 |
commit | 6aff3115b90780933d390d2b471479179927468d (patch) | |
tree | ea9e54617d8a6f6b2d05d37c7f2bde24ce6dfb35 | |
parent | 228f29ac6e0026e596b3a6fbb640118b9944cdd8 (diff) | |
download | u-boot-6aff3115b90780933d390d2b471479179927468d.tar.gz |
* Use 1-byte-read instead of -write for iprobe() function
Add i2c commands to PM826 config
* extend I2C POST code: check for list on known addresses
-rw-r--r-- | CHANGELOG | 5 | ||||
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | common/cmd_bootm.c | 1 | ||||
-rw-r--r-- | common/soft_i2c.c | 3 | ||||
-rw-r--r-- | include/configs/CCM.h | 7 | ||||
-rw-r--r-- | include/configs/PM826.h | 1 | ||||
-rw-r--r-- | include/configs/TQM823L.h | 43 | ||||
-rw-r--r-- | include/configs/TQM850L.h | 44 | ||||
-rw-r--r-- | include/configs/TQM855L.h | 56 | ||||
-rw-r--r-- | include/configs/TQM860L.h | 28 | ||||
-rw-r--r-- | include/configs/lwmon.h | 11 | ||||
-rw-r--r-- | post/i2c.c | 51 | ||||
-rw-r--r-- | tools/env/Makefile | 46 | ||||
-rw-r--r-- | tools/env/README | 29 | ||||
-rw-r--r-- | tools/env/fw_env.c | 662 | ||||
-rw-r--r-- | tools/env/fw_env.h | 44 | ||||
-rw-r--r-- | tools/env/fw_env_main.c | 78 |
17 files changed, 1062 insertions, 53 deletions
@@ -2,6 +2,11 @@ Changes since for U-Boot 0.1.0: ====================================================================== +* Use 1-byte-read instead of -write for iprobe() function + Add i2c commands to PM826 config + +* extend I2C POST code: check for list on known addresses + * Improve log buffer code; use "loglevel" to decide which messages to log on the console, too (like in Linux); get rid of "logstart" @@ -2633,7 +2633,7 @@ U-Boot Porting Guide: ---------------------- [Based on messages by Jerry Van Baren in the U-Boot-Users mailing -list, Octover 2002] +list, October 2002] int main (int argc, char *argv[]) @@ -2650,6 +2650,8 @@ int main (int argc, char *argv[]) Download latest U-Boot source; + Subscribe to u-boot-users mailing list; + if (clueless) { email ("Hi, I am new to U-Boot, how do I get started?"); } @@ -2668,6 +2670,8 @@ int main (int argc, char *argv[]) Create your own board support subdirectory; + Create your own board config file; + while (!running) { do { Add / modify source code; diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 2cf625d6f3..e138d78b9b 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -366,6 +366,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, } #ifdef CONFIG_LOGBUFFER + kbd=gd->bd; /* Prevent initrd from overwriting logbuffer */ if (initrd_high < (kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD)) initrd_high = kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD; diff --git a/common/soft_i2c.c b/common/soft_i2c.c index 77774801e8..63574044ad 100644 --- a/common/soft_i2c.c +++ b/common/soft_i2c.c @@ -287,8 +287,9 @@ int i2c_probe(uchar addr) { int rc; + /* perform 1 byte read transaction */ send_start(); - rc = write_byte ((addr << 1) | 1); + rc = write_byte ((addr << 1) | 0); send_stop(); return (rc ? 1 : 0); diff --git a/include/configs/CCM.h b/include/configs/CCM.h index 0e0248d2c3..0fb24dbf97 100644 --- a/include/configs/CCM.h +++ b/include/configs/CCM.h @@ -212,6 +212,10 @@ #define CFG_ENV_IS_IN_FLASH 1 #define CFG_ENV_OFFSET 0x8000 /* Offset of Environment Sector */ #define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ + +/* Address and size of Redundant Environment Sector */ +#define CFG_ENV_OFFSET_REDUND (CFG_ENV_OFFSET+CFG_ENV_SIZE) +#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) #else /* Final version: environment in EEPROM */ #define CFG_ENV_IS_IN_EEPROM 1 @@ -242,7 +246,8 @@ #define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \ SYPCR_SWE | SYPCR_SWRI| SYPCR_SWP) #else -#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP) +#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \ + SYPCR_SWP) #endif /*----------------------------------------------------------------------- diff --git a/include/configs/PM826.h b/include/configs/PM826.h index dc06f958cb..13d7632700 100644 --- a/include/configs/PM826.h +++ b/include/configs/PM826.h @@ -140,6 +140,7 @@ CFG_CMD_BEDBUG | \ CFG_CMD_DATE | \ CFG_CMD_EEPROM | \ + CFG_CMD_I2C | \ CFG_CMD_DOC) /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ diff --git a/include/configs/TQM823L.h b/include/configs/TQM823L.h index 4eec70c560..bff0cece07 100644 --- a/include/configs/TQM823L.h +++ b/include/configs/TQM823L.h @@ -57,11 +57,25 @@ #define CONFIG_PREBOOT "echo;echo Type \"run flash_nfs\" to mount root filesystem over NFS;echo" #undef CONFIG_BOOTARGS -#define CONFIG_BOOTCOMMAND \ - "bootp; " \ - "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ - "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \ - "bootm" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=$(serverip):$(rootpath)\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs $(bootargs) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" \ + ":$(hostname):$(netdev):off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm $(kernel_addr)\0" \ + "flash_self=run ramargs addip;" \ + "bootm $(kernel_addr) $(ramdisk_addr)\0" \ + "net_nfs=tftp 200000 $(bootfile);run nfsargs addip;bootm\0" \ + "rootpath=/opt/eldk/ppc_8xx\0" \ + "bootfile=/tftpboot/TQM860L/pImage\0" \ + "kernel_addr=40040000\0" \ + "ramdisk_addr=40100000\0" \ + "" +#define CONFIG_BOOTCOMMAND "run flash_self" #define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ #undef CFG_LOADS_BAUD_CHANGE /* don't allow baudrate change */ @@ -84,6 +98,7 @@ #define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */ #define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ CFG_CMD_DHCP | \ CFG_CMD_IDE | \ CFG_CMD_DATE ) @@ -95,14 +110,22 @@ * Miscellaneous configurable options */ #define CFG_LONGHELP /* undef to save memory */ -#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ + +#if 0 +#define CFG_HUSH_PARSER 1 /* use "hush" command parser */ +#endif +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + #if (CONFIG_COMMANDS & CFG_CMD_KGDB) -#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ #else -#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ #endif #define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ -#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_MAXARGS 16 /* max number of command args */ #define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ #define CFG_MEMTEST_START 0x0400000 /* memtest works on */ @@ -110,7 +133,7 @@ #define CFG_LOAD_ADDR 0x100000 /* default load address */ -#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ #define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } diff --git a/include/configs/TQM850L.h b/include/configs/TQM850L.h index 71ea2a860a..a326375ec1 100644 --- a/include/configs/TQM850L.h +++ b/include/configs/TQM850L.h @@ -53,11 +53,25 @@ #define CONFIG_PREBOOT "echo;echo Type \"run flash_nfs\" to mount root filesystem over NFS;echo" #undef CONFIG_BOOTARGS -#define CONFIG_BOOTCOMMAND \ - "bootp; " \ - "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ - "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \ - "bootm" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=$(serverip):$(rootpath)\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs $(bootargs) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" \ + ":$(hostname):$(netdev):off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm $(kernel_addr)\0" \ + "flash_self=run ramargs addip;" \ + "bootm $(kernel_addr) $(ramdisk_addr)\0" \ + "net_nfs=tftp 200000 $(bootfile);run nfsargs addip;bootm\0" \ + "rootpath=/opt/eldk/ppc_8xx\0" \ + "bootfile=/tftpboot/TQM860L/pImage\0" \ + "kernel_addr=40040000\0" \ + "ramdisk_addr=40100000\0" \ + "" +#define CONFIG_BOOTCOMMAND "run flash_self" #define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ #undef CFG_LOADS_BAUD_CHANGE /* don't allow baudrate change */ @@ -76,6 +90,7 @@ #define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */ #define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ CFG_CMD_DHCP | \ CFG_CMD_IDE | \ CFG_CMD_DATE ) @@ -87,14 +102,22 @@ * Miscellaneous configurable options */ #define CFG_LONGHELP /* undef to save memory */ -#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ + +#if 0 +#define CFG_HUSH_PARSER 1 /* use "hush" command parser */ +#endif +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + #if (CONFIG_COMMANDS & CFG_CMD_KGDB) -#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ #else -#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ #endif #define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ -#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_MAXARGS 16 /* max number of command args */ #define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ #define CFG_MEMTEST_START 0x0400000 /* memtest works on */ @@ -102,7 +125,7 @@ #define CFG_LOAD_ADDR 0x100000 /* default load address */ -#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ #define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } @@ -294,7 +317,6 @@ /* Offset for alternate registers */ #define CFG_ATA_ALT_OFFSET 0x0100 - /*----------------------------------------------------------------------- * *----------------------------------------------------------------------- diff --git a/include/configs/TQM855L.h b/include/configs/TQM855L.h index 68151b41f2..f204e01bdd 100644 --- a/include/configs/TQM855L.h +++ b/include/configs/TQM855L.h @@ -39,25 +39,39 @@ #define CONFIG_8xx_CONS_SMC1 1 /* Console is on SMC1 */ #undef CONFIG_8xx_CONS_SMC2 #undef CONFIG_8xx_CONS_NONE + #define CONFIG_BAUDRATE 115200 /* console baudrate = 115kbps */ -#if 0 -#define CONFIG_BOOTDELAY -1 /* autoboot disabled */ -#else + #define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ -#endif #define CONFIG_CLOCKS_IN_MHZ 1 /* clocks passsed to Linux in MHz */ #define CONFIG_BOARD_TYPES 1 /* support board types */ -#define CONFIG_PREBOOT "echo;echo Type \"run flash_nfs\" to mount root filesystem over NFS;echo" +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" #undef CONFIG_BOOTARGS -#define CONFIG_BOOTCOMMAND \ - "bootp; " \ - "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ - "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \ - "bootm" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=$(serverip):$(rootpath)\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs $(bootargs) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" \ + ":$(hostname):$(netdev):off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm $(kernel_addr)\0" \ + "flash_self=run ramargs addip;" \ + "bootm $(kernel_addr) $(ramdisk_addr)\0" \ + "net_nfs=tftp 200000 $(bootfile);run nfsargs addip;bootm\0" \ + "rootpath=/opt/eldk/ppc_8xx\0" \ + "bootfile=/tftpboot/TQM860L/pImage\0" \ + "kernel_addr=40040000\0" \ + "ramdisk_addr=40100000\0" \ + "" +#define CONFIG_BOOTCOMMAND "run flash_self" #define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ #undef CFG_LOADS_BAUD_CHANGE /* don't allow baudrate change */ @@ -76,6 +90,7 @@ #define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */ #define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ CFG_CMD_DHCP | \ CFG_CMD_IDE | \ CFG_CMD_DATE ) @@ -87,14 +102,22 @@ * Miscellaneous configurable options */ #define CFG_LONGHELP /* undef to save memory */ -#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ + +#if 0 +#define CFG_HUSH_PARSER 1 /* use "hush" command parser */ +#endif +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + #if (CONFIG_COMMANDS & CFG_CMD_KGDB) -#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ #else -#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ #endif #define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ -#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_MAXARGS 16 /* max number of command args */ #define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ #define CFG_MEMTEST_START 0x0400000 /* memtest works on */ @@ -102,7 +125,7 @@ #define CFG_LOAD_ADDR 0x100000 /* default load address */ -#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ #define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } @@ -294,7 +317,6 @@ /* Offset for alternate registers */ #define CFG_ATA_ALT_OFFSET 0x0100 - /*----------------------------------------------------------------------- * *----------------------------------------------------------------------- @@ -441,5 +463,7 @@ #define BOOTFLAG_WARM 0x02 /* Software reboot */ #define CONFIG_SCC1_ENET +#define CONFIG_FEC_ENET +#define CONFIG_ETHPRIME "SCC ETHERNET" #endif /* __CONFIG_H */ diff --git a/include/configs/TQM860L.h b/include/configs/TQM860L.h index a3d6b27cae..dc5eb3cb56 100644 --- a/include/configs/TQM860L.h +++ b/include/configs/TQM860L.h @@ -49,15 +49,29 @@ #define CONFIG_BOARD_TYPES 1 /* support board types */ #define CONFIG_PREBOOT "echo;" \ - "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ - "echo" + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" #undef CONFIG_BOOTARGS -#define CONFIG_BOOTCOMMAND \ - "bootp; " \ - "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ - "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \ - "bootm" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=$(serverip):$(rootpath)\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs $(bootargs) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" \ + ":$(hostname):$(netdev):off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm $(kernel_addr)\0" \ + "flash_self=run ramargs addip;" \ + "bootm $(kernel_addr) $(ramdisk_addr)\0" \ + "net_nfs=tftp 200000 $(bootfile);run nfsargs addip;bootm\0" \ + "rootpath=/opt/eldk/ppc_8xx\0" \ + "bootfile=/tftpboot/TQM860L/pImage\0" \ + "kernel_addr=40040000\0" \ + "ramdisk_addr=40100000\0" \ + "" +#define CONFIG_BOOTCOMMAND "run flash_self" #define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ #undef CFG_LOADS_BAUD_CHANGE /* don't allow baudrate change */ diff --git a/include/configs/lwmon.h b/include/configs/lwmon.h index 587de2dd08..d227fffae7 100644 --- a/include/configs/lwmon.h +++ b/include/configs/lwmon.h @@ -288,6 +288,17 @@ #endif /* CONFIG_USE_FRAM */ #define CFG_EEPROM_PAGE_WRITE_BITS 4 +/* List of I2C addresses to be verified by POST */ +#define I2C_ADDR_LIST { /* CFG_I2C_AUDIO_ADDR, */ \ + CFG_I2C_SYSMON_ADDR, \ + CFG_I2C_RTC_ADDR, \ + CFG_I2C_POWER_A_ADDR, \ + CFG_I2C_POWER_B_ADDR, \ + CFG_I2C_KEYBD_ADDR, \ + CFG_I2C_PICIO_ADDR, \ + CFG_I2C_EEPROM_ADDR, \ + } + /*----------------------------------------------------------------------- * Cache Configuration */ diff --git a/post/i2c.c b/post/i2c.c index 2e38986662..1b2e64471b 100644 --- a/post/i2c.c +++ b/post/i2c.c @@ -29,8 +29,13 @@ * I2C test * * For verifying the I2C bus, a full I2C bus scanning is performed. - * If any I2C device is found, the test is considered as passed, - * otherwise failed. + * + * #ifdef I2C_ADDR_LIST + * The test is considered as passed if all the devices and + * only the devices in the list are found. + * #else [ ! I2C_ADDR_LIST ] + * The test is considered as passed if any I2C device is found. + * #endif */ #include <post.h> @@ -41,14 +46,48 @@ int i2c_post_test (int flags) { unsigned int i; - unsigned int chips = 0; + unsigned int good = 0; +#ifdef I2C_ADDR_LIST + unsigned int bad = 0; + int j; + unsigned char i2c_addr_list[] = I2C_ADDR_LIST; + unsigned char i2c_miss_list[] = I2C_ADDR_LIST; +#endif for (i = 0; i < 128; i++) { - if (i2c_probe (i) == 0) - chips++; + if (i2c_probe (i) == 0) { +#ifndef I2C_ADDR_LIST + good++; +#else /* I2C_ADDR_LIST */ + for (j=0; j<sizeof(i2c_addr_list); ++j) { + if (i == i2c_addr_list[j]) { + good++; + i2c_miss_list[j] = 0xFF; + break; + } + } + if (j == sizeof(i2c_addr_list)) { + bad++; + post_log ("I2C: addr %02X not expected\n", + i); + } +#endif /* I2C_ADDR_LIST */ + } } - return chips > 0 ? 0 : -1; +#ifndef I2C_ADDR_LIST + return good > 0 ? 0 : -1; +#else /* I2C_ADDR_LIST */ + if (good != sizeof(i2c_addr_list)) { + for (j=0; j<sizeof(i2c_miss_list); ++j) { + if (i2c_miss_list[j] != 0xFF) { + post_log ("I2C: addr %02X did not respond\n", + i2c_miss_list[j]); + } + } + } + return ((good == sizeof(i2c_addr_list)) && (bad == 0)) ? 0 : -1; +#endif } #endif /* CONFIG_POST & CFG_POST_I2C */ diff --git a/tools/env/Makefile b/tools/env/Makefile new file mode 100644 index 0000000000..7da1d2b7b0 --- /dev/null +++ b/tools/env/Makefile @@ -0,0 +1,46 @@ +# +# (C) Copyright 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 +# + +SOURCES := crc32.c fw_env.c fw_env_main.c +HEADERS := fw_env.h + +all: fw_printenv + +fw_printenv: $(SOURCES) $(HEADERS) + $(CROSS_COMPILE)gcc -Wall -DUSE_HOSTCC $(SOURCES) -o fw_printenv + +clean: + rm -f fw_printenv crc32.c + +crc32.c: + ln -s ../../lib_generic/crc32.c crc32.c + +######################################################################### + +.depend: Makefile $(SOURCES) + $(CC) -M $(HOST_CFLAGS) $(CPPFLAGS) -DUSE_HOSTCC $(SOURCES) > $@ + +sinclude .depend + +######################################################################### + diff --git a/tools/env/README b/tools/env/README new file mode 100644 index 0000000000..2b54adf76b --- /dev/null +++ b/tools/env/README @@ -0,0 +1,29 @@ + +This is a demo implementation of a Linux command line tool to access +the U-Boot's environment variables. + +Configuration is done via #defines in the fw_env.h file. The +following lines are relevant: + +#define HAVE_REDUND /* For systems with 2 env sectors */ +#define DEVICE1_NAME "/dev/mtd1" +#define DEVICE2_NAME "/dev/mtd2" +#define ENV1_SIZE 0x4000 +#define DEVICE1_ESIZE 0x4000 +#define ENV2_SIZE 0x4000 +#define DEVICE2_ESIZE 0x4000 + +Current configuration matches the environment layout of the TRAB +board. + +Un-define HAVE_REDUND, if you want to use the utlities on a system +that does not have support for redundant environment enabled. The +DEVICEx_NAME constants define which MTD character device(s) is (are) +to be used to access the environment. If HAVE_REDUND is undefined, +DEVICE2_NAME is ignored, as is ENV2_SIZE and DEVICE2_ESIZE. ENVx_SIZE +defines the size in bytes taken by the environment, which may be less +then flash sector size, if the environment takes less then 1 sector. +DEVICEx_ESIZE defines the size of the first sector in the flash +partition where the environment resides. It is assumed that the +environment is located in the first ENVx_SIZE bytes of the device +DEVICEx_NAME. diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c new file mode 100644 index 0000000000..5bf75ac2c2 --- /dev/null +++ b/tools/env/fw_env.c @@ -0,0 +1,662 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <unistd.h> +#include <linux/mtd/mtd.h> +#include "fw_env.h" + +typedef unsigned char uchar; + +#define CMD_GETENV "fw_printenv" +#define CMD_SETENV "fw_setenv" + +typedef struct envdev_s { + uchar devname[16]; /* Device name */ + ulong env_size; /* environment size */ + ulong erase_size; /* device erase size */ +} envdev_t; + +static envdev_t envdevices[2]; +static int curdev; + +#define DEVNAME(i) envdevices[(i)].devname +#define ENVSIZE(i) envdevices[(i)].env_size +#define DEVESIZE(i) envdevices[(i)].erase_size + +#define CFG_ENV_SIZE ENVSIZE(curdev) + +#ifdef HAVE_REDUND +#define ENV_SIZE (CFG_ENV_SIZE - sizeof(long) - 1) +#else +#define ENV_SIZE (CFG_ENV_SIZE - sizeof(long)) +#endif + +typedef struct environment_s { + ulong crc; /* CRC32 over data bytes */ + uchar flags; /* active or obsolete */ + uchar *data; +} env_t; + +static env_t environment; +static int valid = 0; + +#ifdef HAVE_REDUND +static uchar active_flag = 1; +static uchar obsolete_flag = 0; +#endif + +#define XMK_STR(x) #x +#define MK_STR(x) XMK_STR(x) + +static uchar default_environment[] = { +#ifdef CONFIG_BOOTARGS + "bootargs=" CONFIG_BOOTARGS "\0" +#endif +#ifdef CONFIG_BOOTCOMMAND + "bootcmd=" CONFIG_BOOTCOMMAND "\0" +#endif +#if (CONFIG_BOOTDELAY >= 0) + "bootdelay=" MK_STR(CONFIG_BOOTDELAY) "\0" +#endif +#if (CONFIG_BAUDRATE >= 0) + "baudrate=" MK_STR(CONFIG_BAUDRATE) "\0" +#endif +#ifdef CONFIG_ETHADDR + "ethaddr=" MK_STR(CONFIG_ETHADDR) "\0" +#endif +#ifdef CONFIG_IPADDR + "ipaddr=" MK_STR(CONFIG_IPADDR) "\0" +#endif +#ifdef CONFIG_SERVERIP + "serverip=" MK_STR(CONFIG_SERVERIP) "\0" +#endif + "\0" +}; + +static int flash_io (int mode); +static uchar *envmatch(uchar *s1, uchar *s2); +static int env_init(void); +static int parse_config(void); + + +/* + * Search the environment for a variable. + * Return the value, if found, or NULL, if not found. + */ +unsigned char *fw_getenv (unsigned char *name) +{ + uchar *env, *nxt; + + if (env_init()) + return (NULL); + + for (env=environment.data; *env; env=nxt+1) { + uchar *val; + + for (nxt=env; *nxt; ++nxt) { + if (nxt >= &environment.data[ENV_SIZE]) { + fprintf (stderr, "## Error: " + "environment not terminated\n"); + return (NULL); + } + } + val=envmatch(name, env); + if (!val) + continue; + return (val); + } + return (NULL); +} + +/* + * Print the current definition of one, or more, or all + * environment variables + */ +void fw_printenv(int argc, char *argv[]) +{ + uchar *env, *nxt; + int i, n_flag; + + if (env_init()) + return; + + if (argc == 1) { /* Print all env variables */ + for (env=environment.data; *env; env=nxt+1) { + for (nxt=env; *nxt; ++nxt) { + if (nxt >= &environment.data[ENV_SIZE]) { + fprintf (stderr, "## Error: " + "environment not terminated\n"); + return; + } + } + + printf("%s\n", env); + } + return; + } + + if (strcmp(argv[1], "-n") == 0) { + n_flag = 1; + ++argv; + --argc; + if (argc != 2) { + fprintf (stderr, "## Error: " + "`-n' option requires exactly one argument\n"); + return; + } + } else { + n_flag = 0; + } + + for (i=1; i<argc; ++i) { /* print single env variables */ + uchar *name = argv[i]; + uchar *val = NULL; + + for (env=environment.data; *env; env=nxt+1) { + + for (nxt=env; *nxt; ++nxt) { + if (nxt >= &environment.data[ENV_SIZE]) { + fprintf (stderr, "## Error: " + "environment not terminated\n"); + return; + } + } + val=envmatch(name, env); + if (val) { + if (!n_flag) { + fputs (name, stdout); + putc ('=', stdout); + } + puts (val); + break; + } + } + if (!val) + fprintf (stderr, "## Error: \"%s\" not defined\n", + name); + } +} + +/* + * Deletes or sets environment variables. Returns errno style error codes: + * 0 - OK + * EINVAL - need at least 1 argument + * EROFS - certain variables ("ethaddr", "serial#") cannot be + * modified or deleted + * + */ +int fw_setenv (int argc, char *argv[]) +{ + int i, len; + uchar *env, *nxt; + uchar *oldval = NULL; + uchar *name; + + if (argc < 2) { + return (EINVAL); + } + + if (env_init()) + return (errno); + + name = argv[1]; + + /* + * search if variable with this name already exists + */ + for (env=environment.data; *env; env=nxt+1) { + for (nxt=env; *nxt; ++nxt) { + if (nxt >= &environment.data[ENV_SIZE]) { + fprintf (stderr, "## Error: " + "environment not terminated\n"); + return (EINVAL); + } + } + if ((oldval=envmatch(name, env)) != NULL) + break; + } + + /* + * Delete any existing definition + */ + if (oldval) { + /* + * Ethernet Address and serial# can be set only once + */ + if ((strcmp (name, "ethaddr") == 0) || + (strcmp (name, "serial#") == 0) ) { + fprintf (stderr, "Can't overwrite \"%s\"\n", name); + return (EROFS); + } + + if (*++nxt == '\0') { + *env = '\0'; + } else { + for (;;) { + *env = *nxt++; + if ((*env == '\0') && (*nxt == '\0')) + break; + ++env; + } + } + *++env = '\0'; + } + + /* Delete only ? */ + if (argc < 3) + goto WRITE_FLASH; + + /* + * Append new definition at the end + */ + for (env=environment.data; *env || *(env+1); ++env) + ; + if (env > environment.data) + ++env; + /* + * Overflow when: + * "name" + "=" + "val" +"\0\0" > CFG_ENV_SIZE - (env-environment) + */ + len = strlen(name) + 2; + /* add '=' for first arg, ' ' for all others */ + for (i=2; i<argc; ++i) { + len += strlen(argv[i]) + 1; + } + if (len > (&environment.data[ENV_SIZE]-env)) { + fprintf (stderr, + "Error: environment overflow, \"%s\" deleted\n", + name); + return (-1); + } + while ((*env = *name++) != '\0') + env++; + for (i=2; i<argc; ++i) { + uchar *val = argv[i]; + + *env = (i==2) ? '=' : ' '; + while ((*++env = *val++) != '\0') + ; + } + + /* end is marked with double '\0' */ + *++env = '\0'; + +WRITE_FLASH: + + /* Update CRC */ + environment.crc = crc32(0, environment.data, ENV_SIZE); + + /* write environment back to flash */ + if (flash_io (O_RDWR)) { + fprintf (stderr, + "Error: can't write fw_env to flash\n"); + return (-1); + } + + return (0); +} + +static int flash_io (int mode) +{ + int fd, fdr, rc, otherdev, len, resid; + erase_info_t erase; + char *data; + + if ((fd = open(DEVNAME(curdev), mode)) < 0) { + fprintf (stderr, + "Can't open %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } + + len = sizeof(environment.crc) + sizeof(environment.flags); + + if (mode == O_RDWR) { +#ifdef HAVE_REDUND + /* switch to next partition for writing */ + otherdev = !curdev; + if ((fdr = open(DEVNAME(otherdev), mode)) < 0) { + fprintf (stderr, + "Can't open %s: %s\n", + DEVNAME(otherdev), strerror(errno)); + return (-1); + } +#else + otherdev = curdev; + fdr = fd; + len = sizeof(environment.crc); +#endif + printf("Unlocking flash...\n"); + erase.length = DEVESIZE(otherdev); + erase.start = 0; + ioctl (fdr, MEMUNLOCK, &erase); + +#ifdef HAVE_REDUND + erase.length = DEVESIZE(curdev); + erase.start = 0; + ioctl (fd, MEMUNLOCK, &erase); + environment.flags = active_flag; +#endif + printf("Done\n"); + resid = DEVESIZE(otherdev) - CFG_ENV_SIZE; + if (resid) { + if ((data = malloc(resid)) == NULL) { + fprintf(stderr, + "Cannot malloc %d bytes: %s\n", + resid, strerror(errno)); + return (-1); + } + if (lseek (fdr, CFG_ENV_SIZE, SEEK_SET) == -1) { + fprintf (stderr, + "seek error on %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } + if ((rc = read (fdr, data, resid)) != resid) { + fprintf (stderr, + "read error on %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } + if (lseek (fdr, 0, SEEK_SET) == -1) { + fprintf (stderr, + "seek error on %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } + } + + printf("Erasing old environment...\n"); + + erase.length = DEVESIZE(otherdev); + if (ioctl (fdr, MEMERASE, &erase) != 0) { + fprintf (stderr, "MTD erase error on %s: %s\n", + DEVNAME(otherdev), strerror(errno)); + return (-1); + } + + printf("Done\n"); + + printf("Writing environment to %s...\n",DEVNAME(otherdev)); + if (write(fdr, &environment, len) != len) { + fprintf (stderr, + "CRC write error on %s: %s\n", + DEVNAME(otherdev), strerror(errno)); + return (-1); + } + if (write(fdr, environment.data, ENV_SIZE) != ENV_SIZE) { + fprintf (stderr, + "Write error on %s: %s\n", + DEVNAME(otherdev), strerror(errno)); + return (-1); + } + if (resid) { + if (write (fdr, data, resid) != resid) { + fprintf (stderr, + "write error on %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } + free(data); + } +#ifdef HAVE_REDUND + /* change flag on current active env partition */ + if (lseek (fd, sizeof(ulong), SEEK_SET) == -1) { + fprintf (stderr, + "seek error on %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } + if (write (fd, &obsolete_flag, sizeof(obsolete_flag)) != + sizeof(obsolete_flag)) { + fprintf (stderr, + "Write error on %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } +#endif + printf("Done\n"); + printf("Locking ...\n"); + erase.length = DEVESIZE(otherdev); + erase.start = 0; + ioctl (fdr, MEMLOCK, &erase); +#ifdef HAVE_REDUND + erase.length = DEVESIZE(curdev); + erase.start = 0; + ioctl (fd, MEMLOCK, &erase); + if (close(fdr)) { + fprintf (stderr, + "I/O error on %s: %s\n", + DEVNAME(otherdev), strerror(errno)); + return (-1); + } +#endif + printf("Done\n"); + } else { +#ifndef HAVE_REDUND + len = sizeof(environment.crc); +#endif + if (read (fd, &environment, len) != len) { + fprintf (stderr, + "CRC read error on %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } + if ((rc = read (fd, environment.data, ENV_SIZE)) != ENV_SIZE) { + fprintf (stderr, + "Read error on %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } + } + + if (close(fd)) { + fprintf (stderr, + "I/O error on %s: %s\n", + DEVNAME(curdev), strerror(errno)); + return (-1); + } + + /* everything ok */ + return (0); +} + +/* + * s1 is either a simple 'name', or a 'name=value' pair. + * s2 is a 'name=value' pair. + * If the names match, return the value of s2, else NULL. + */ + +static uchar * +envmatch (uchar *s1, uchar *s2) +{ + + while (*s1 == *s2++) + if (*s1++ == '=') + return(s2); + if (*s1 == '\0' && *(s2-1) == '=') + return(s2); + return(NULL); +} + +/* + * Prevent confusion if running from erased flash memory + */ +static int env_init(void) +{ + int crc1, crc1_ok; + uchar *addr1; +#ifdef HAVE_REDUND + int crc2, crc2_ok; + uchar flag1, flag2, *addr2; +#endif + + + if (!valid) { + + if (parse_config()) /* should fill envdevices */ + return 1; + + if ((addr1 = calloc (1, ENV_SIZE)) == NULL) { + fprintf (stderr, + "Not enough memory for environment (%ld bytes)\n", + ENV_SIZE); + return (errno); + } + + /* read environment from FLASH to local buffer */ + environment.data = addr1; + curdev = 0; + if (flash_io (O_RDONLY)) { + return (errno); + } + + crc1_ok = ((crc1 = crc32(0, environment.data, ENV_SIZE)) + == environment.crc); +#ifndef HAVE_REDUND + if (!crc1_ok) { + fprintf (stderr, + "Warning: Bad CRC, using default environment\n"); + environment.data = default_environment; + free(addr1); + } +#else + flag1 = environment.flags; + + curdev = 1; + if ((addr2 = calloc (1, ENV_SIZE)) == NULL) { + fprintf (stderr, + "Not enough memory for environment (%ld bytes)\n", + ENV_SIZE); + return (errno); + } + environment.data = addr2; + + if (flash_io (O_RDONLY)) { + return (errno); + } + + crc2_ok = ((crc2 = crc32(0, environment.data, ENV_SIZE)) + == environment.crc); + flag2 = environment.flags; + + if (crc1_ok && ! crc2_ok) { + environment.data = addr1; + environment.flags = flag1; + environment.crc = crc1; + curdev = 0; + free(addr2); + } + else if (! crc1_ok && crc2_ok) { + environment.data = addr2; + environment.flags = flag2; + environment.crc = crc2; + curdev = 1; + free(addr1); + } + else if (! crc1_ok && ! crc2_ok) { + fprintf (stderr, + "Warning: Bad CRC, using default environment\n"); + environment.data = default_environment; + curdev = 0; + free(addr2); + free(addr1); + } + else if (flag1 == active_flag && flag2 == obsolete_flag) { + environment.data = addr1; + environment.flags = flag1; + environment.crc = crc1; + curdev = 0; + free(addr2); + } + else if (flag1 == obsolete_flag && flag2 == active_flag) { + environment.data = addr2; + environment.flags = flag2; + environment.crc = crc2; + curdev = 1; + free(addr1); + } + else if (flag1 == flag2) { + environment.data = addr1; + environment.flags = flag1; + environment.crc = crc1; + curdev = 0; + free(addr2); + } + else if (flag1 == 0xFF) { + environment.data = addr1; + environment.flags = flag1; + environment.crc = crc1; + curdev = 0; + free(addr2); + } + else if (flag2 == 0xFF) { + environment.data = addr2; + environment.flags = flag2; + environment.crc = crc2; + curdev = 1; + free(addr1); + } +#endif + valid = 1; + } + return (0); +} + + +static int parse_config() +{ + struct stat st; + + if (stat (DEVICE1_NAME, &st)) { + fprintf (stderr, + "Cannot access MTD device %s: %s\n", + DEVICE1_NAME, strerror(errno)); + return 1; + } + + strcpy(DEVNAME(0), DEVICE1_NAME); + ENVSIZE(0) = ENV1_SIZE; + DEVESIZE(0) = DEVICE1_ESIZE; +#ifdef HAVE_REDUND + if (stat (DEVICE2_NAME, &st)) { + fprintf (stderr, + "Cannot access MTD device %s: %s\n", + DEVICE2_NAME, strerror(errno)); + return 1; + } + strcpy(DEVNAME(1), DEVICE2_NAME); + ENVSIZE(1) = ENV2_SIZE; + DEVESIZE(1) = DEVICE2_ESIZE; +#endif + return 0; +} diff --git a/tools/env/fw_env.h b/tools/env/fw_env.h new file mode 100644 index 0000000000..d98edc9975 --- /dev/null +++ b/tools/env/fw_env.h @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 + */ + +#define HAVE_REDUND /* For systems with 2 env sectors */ +#define DEVICE1_NAME "/dev/mtd1" +#define DEVICE2_NAME "/dev/mtd2" +#define ENV1_SIZE 0x4000 +#define DEVICE1_ESIZE 0x4000 +#define ENV2_SIZE 0x4000 +#define DEVICE2_ESIZE 0x4000 + +#define CONFIG_BAUDRATE 115200 +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ +#define CONFIG_BOOTCOMMAND \ + "bootp; " \ + "setenv bootargs root=/dev/nfs nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \ + "bootm" + +extern void fw_printenv(int argc, char *argv[]); +extern unsigned char *fw_getenv (unsigned char *name); +extern int fw_setenv (int argc, char *argv[]); + +extern unsigned long crc32 (unsigned long, const unsigned char *, unsigned); diff --git a/tools/env/fw_env_main.c b/tools/env/fw_env_main.c new file mode 100644 index 0000000000..1c22e7143d --- /dev/null +++ b/tools/env/fw_env_main.c @@ -0,0 +1,78 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 + */ + +/* + * Command line user interface to firmware (=PPCBoot) environment. + * + * Implements: + * fw_printenv [ name ... ] + * - prints the values of the environment variables + * "name", or the whole environment if no names are + * specified + * fw_setenv name [ value ... ] + * - If a name without any values is given, the variable + * with this name is deleted from the environment; + * otherwise, all "value" arguments are concatenated, + * separated by sinlge blank characters, and the + * resulting string is assigned to the environment + * variable "name" + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "fw_env.h" + +#define CMD_PRINTENV "fw_printenv" +#define CMD_SETENV "fw_setenv" + +int +main(int argc, char *argv[]) +{ + char *p; + char *cmdname = *argv; + + if ((p = strrchr (cmdname, '/')) != NULL) { + cmdname = p + 1; + } + + if (strcmp(cmdname, CMD_PRINTENV) == 0) { + + fw_printenv (argc, argv); + + return (EXIT_SUCCESS); + + } else if (strcmp(cmdname, CMD_SETENV) == 0) { + + if (fw_setenv (argc, argv) != 0) + return (EXIT_FAILURE); + + return (EXIT_SUCCESS); + } + + fprintf (stderr, + "Identity crisis - may be called as `" CMD_PRINTENV + "' or as `" CMD_SETENV "' but not as `%s'\n", + cmdname); + return (EXIT_FAILURE); +} |