📄 fw_env.c
字号:
/* * (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_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 *);#endifstatic 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -