diff options
Diffstat (limited to 'tools/env/fw_env.c')
-rw-r--r-- | tools/env/fw_env.c | 768 |
1 files changed, 0 insertions, 768 deletions
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c deleted file mode 100644 index f723b5bca1..0000000000 --- a/tools/env/fw_env.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * (C) Copyright 2000-2003 - * 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 devoff; /* Device offset */ - 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 DEVOFFSET(i) envdevices[(i)].devoff -#define ENVSIZE(i) envdevices[(i)].env_size -#define DEVESIZE(i) envdevices[(i)].erase_size - -#define CFG_ENV_SIZE ENVSIZE(curdev) - -#define ENV_SIZE getenvsize() - -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 HaveRedundEnv = 0; - -static uchar active_flag = 1; -static uchar obsolete_flag = 0; - - -#define XMK_STR(x) #x -#define MK_STR(x) XMK_STR(x) - -static uchar default_environment[] = { -#if defined(CONFIG_BOOTARGS) - "bootargs=" CONFIG_BOOTARGS "\0" -#endif -#if defined(CONFIG_BOOTCOMMAND) - "bootcmd=" CONFIG_BOOTCOMMAND "\0" -#endif -#if defined(CONFIG_RAMBOOTCOMMAND) - "ramboot=" CONFIG_RAMBOOTCOMMAND "\0" -#endif -#if defined(CONFIG_NFSBOOTCOMMAND) - "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0" -#endif -#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) - "bootdelay=" MK_STR (CONFIG_BOOTDELAY) "\0" -#endif -#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0) - "baudrate=" MK_STR (CONFIG_BAUDRATE) "\0" -#endif -#ifdef CONFIG_LOADS_ECHO - "loads_echo=" MK_STR (CONFIG_LOADS_ECHO) "\0" -#endif -#ifdef CONFIG_ETHADDR - "ethaddr=" MK_STR (CONFIG_ETHADDR) "\0" -#endif -#ifdef CONFIG_ETH1ADDR - "eth1addr=" MK_STR (CONFIG_ETH1ADDR) "\0" -#endif -#ifdef CONFIG_ETH2ADDR - "eth2addr=" MK_STR (CONFIG_ETH2ADDR) "\0" -#endif -#ifdef CONFIG_ETH3ADDR - "eth3addr=" MK_STR (CONFIG_ETH3ADDR) "\0" -#endif -#ifdef CONFIG_ETHPRIME - "ethprime=" CONFIG_ETHPRIME "\0" -#endif -#ifdef CONFIG_IPADDR - "ipaddr=" MK_STR (CONFIG_IPADDR) "\0" -#endif -#ifdef CONFIG_SERVERIP - "serverip=" MK_STR (CONFIG_SERVERIP) "\0" -#endif -#ifdef CFG_AUTOLOAD - "autoload=" CFG_AUTOLOAD "\0" -#endif -#ifdef CONFIG_ROOTPATH - "rootpath=" MK_STR (CONFIG_ROOTPATH) "\0" -#endif -#ifdef CONFIG_GATEWAYIP - "gatewayip=" MK_STR (CONFIG_GATEWAYIP) "\0" -#endif -#ifdef CONFIG_NETMASK - "netmask=" MK_STR (CONFIG_NETMASK) "\0" -#endif -#ifdef CONFIG_HOSTNAME - "hostname=" MK_STR (CONFIG_HOSTNAME) "\0" -#endif -#ifdef CONFIG_BOOTFILE - "bootfile=" MK_STR (CONFIG_BOOTFILE) "\0" -#endif -#ifdef CONFIG_LOADADDR - "loadaddr=" MK_STR (CONFIG_LOADADDR) "\0" -#endif -#ifdef CONFIG_PREBOOT - "preboot=" CONFIG_PREBOOT "\0" -#endif -#ifdef CONFIG_CLOCKS_IN_MHZ - "clocks_in_mhz=" "1" "\0" -#endif -#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0) - "pcidelay=" MK_STR (CONFIG_PCI_BOOTDELAY) "\0" -#endif -#ifdef CONFIG_EXTRA_ENV_SETTINGS - CONFIG_EXTRA_ENV_SETTINGS -#endif - "\0" /* Termimate env_t data with 2 NULs */ -}; - -static int flash_io (int mode); -static uchar *envmatch (uchar * s1, uchar * s2); -static int env_init (void); -static int parse_config (void); - -#if defined(CONFIG_FILE) -static int get_config (char *); -#endif -static inline ulong getenvsize (void) -{ - ulong rc = CFG_ENV_SIZE - sizeof (long); - - if (HaveRedundEnv) - rc -= sizeof (char); - return rc; -} - -/* - * 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 (nxt = 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 = NULL; - - 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); - if (HaveRedundEnv) { - len += sizeof (environment.flags); - } - - if (mode == O_RDWR) { - if (HaveRedundEnv) { - /* 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; - } - printf ("Unlocking flash...\n"); - erase.length = DEVESIZE (otherdev); - erase.start = DEVOFFSET (otherdev); - ioctl (fdr, MEMUNLOCK, &erase); - - if (HaveRedundEnv) { - erase.length = DEVESIZE (curdev); - erase.start = DEVOFFSET (curdev); - ioctl (fd, MEMUNLOCK, &erase); - environment.flags = active_flag; - } - - 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, DEVOFFSET (otherdev) + CFG_ENV_SIZE, SEEK_SET) - == -1) { - fprintf (stderr, "seek error on %s: %s\n", - DEVNAME (otherdev), - strerror (errno)); - return (-1); - } - if ((rc = read (fdr, data, resid)) != resid) { - fprintf (stderr, - "read error on %s: %s\n", - DEVNAME (otherdev), - strerror (errno)); - return (-1); - } - } - - printf ("Erasing old environment...\n"); - - erase.length = DEVESIZE (otherdev); - erase.start = DEVOFFSET (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 (lseek (fdr, DEVOFFSET (otherdev), SEEK_SET) == -1) { - fprintf (stderr, - "seek error on %s: %s\n", - DEVNAME (otherdev), strerror (errno)); - return (-1); - } - 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); - } - if (HaveRedundEnv) { - /* change flag on current active env partition */ - if (lseek (fd, DEVOFFSET (curdev) + 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); - } - } - printf ("Done\n"); - printf ("Locking ...\n"); - erase.length = DEVESIZE (otherdev); - erase.start = DEVOFFSET (otherdev); - ioctl (fdr, MEMLOCK, &erase); - if (HaveRedundEnv) { - erase.length = DEVESIZE (curdev); - erase.start = DEVOFFSET (curdev); - ioctl (fd, MEMLOCK, &erase); - if (close (fdr)) { - fprintf (stderr, - "I/O error on %s: %s\n", - DEVNAME (otherdev), - strerror (errno)); - return (-1); - } - } - printf ("Done\n"); - } else { - - if (lseek (fd, DEVOFFSET (curdev), SEEK_SET) == -1) { - fprintf (stderr, - "seek error on %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); - } - 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; - - int crc2, crc2_ok; - uchar flag1, flag2, *addr2; - - 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); - if (!HaveRedundEnv) { - if (!crc1_ok) { - fprintf (stderr, - "Warning: Bad CRC, using default environment\n"); - memcpy(environment.data, default_environment, sizeof default_environment); - } - } 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"); - memcpy(environment.data, default_environment, sizeof default_environment); - curdev = 0; - 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); - } - } - return (0); -} - - -static int parse_config () -{ - struct stat st; - -#if defined(CONFIG_FILE) - /* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */ - if (get_config (CONFIG_FILE)) { - fprintf (stderr, - "Cannot parse config file: %s\n", strerror (errno)); - return 1; - } -#else - strcpy (DEVNAME (0), DEVICE1_NAME); - DEVOFFSET (0) = DEVICE1_OFFSET; - ENVSIZE (0) = ENV1_SIZE; - DEVESIZE (0) = DEVICE1_ESIZE; -#ifdef HAVE_REDUND - strcpy (DEVNAME (1), DEVICE2_NAME); - DEVOFFSET (1) = DEVICE2_OFFSET; - ENVSIZE (1) = ENV2_SIZE; - DEVESIZE (1) = DEVICE2_ESIZE; - HaveRedundEnv = 1; -#endif -#endif - if (stat (DEVNAME (0), &st)) { - fprintf (stderr, - "Cannot access MTD device %s: %s\n", - DEVNAME (0), strerror (errno)); - return 1; - } - - if (HaveRedundEnv && stat (DEVNAME (1), &st)) { - fprintf (stderr, - "Cannot access MTD device %s: %s\n", - DEVNAME (1), strerror (errno)); - return 1; - } - return 0; -} - -#if defined(CONFIG_FILE) -static int get_config (char *fname) -{ - FILE *fp; - int i = 0; - int rc; - char dump[128]; - - if ((fp = fopen (fname, "r")) == NULL) { - return 1; - } - - while ((i < 2) && ((rc = fscanf (fp, "%s %lx %lx %lx", - DEVNAME (i), - &DEVOFFSET (i), - &ENVSIZE (i), - &DEVESIZE (i) )) != EOF)) { - - /* Skip incomplete conversions and comment strings */ - if ((rc < 3) || (*DEVNAME (i) == '#')) { - fgets (dump, sizeof (dump), fp); /* Consume till end */ - continue; - } - - i++; - } - fclose (fp); - - HaveRedundEnv = i - 1; - if (!i) { /* No valid entries found */ - errno = EINVAL; - return 1; - } else - return 0; -} -#endif |