fw_env.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. /*
  2. * (C) Copyright 2000
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <errno.h>
  24. #include <fcntl.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <stddef.h>
  28. #include <string.h>
  29. #include <sys/types.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/stat.h>
  32. #include <unistd.h>
  33. #include <linux/mtd/mtd.h>
  34. #include "fw_env.h"
  35. typedef unsigned char uchar;
  36. #define CMD_GETENV "fw_printenv"
  37. #define CMD_SETENV "fw_setenv"
  38. typedef struct envdev_s {
  39. uchar devname[16]; /* Device name */
  40. ulong devoff; /* Device offset */
  41. ulong env_size; /* environment size */
  42. ulong erase_size; /* device erase size */
  43. } envdev_t;
  44. static envdev_t envdevices[2];
  45. static int curdev;
  46. #define DEVNAME(i) envdevices[(i)].devname
  47. #define DEVOFFSET(i) envdevices[(i)].devoff
  48. #define ENVSIZE(i) envdevices[(i)].env_size
  49. #define DEVESIZE(i) envdevices[(i)].erase_size
  50. #define CFG_ENV_SIZE ENVSIZE(curdev)
  51. #define ENV_SIZE getenvsize()
  52. typedef struct environment_s {
  53. ulong crc; /* CRC32 over data bytes */
  54. uchar flags; /* active or obsolete */
  55. uchar *data;
  56. } env_t;
  57. static env_t environment;
  58. static int HaveRedundEnv = 0;
  59. static uchar active_flag = 1;
  60. static uchar obsolete_flag = 0;
  61. #define XMK_STR(x) #x
  62. #define MK_STR(x) XMK_STR(x)
  63. static uchar default_environment[] = {
  64. #if defined(CONFIG_BOOTARGS)
  65. "bootargs=" CONFIG_BOOTARGS "\0"
  66. #endif
  67. #if defined(CONFIG_BOOTCOMMAND)
  68. "bootcmd=" CONFIG_BOOTCOMMAND "\0"
  69. #endif
  70. #if defined(CONFIG_RAMBOOTCOMMAND)
  71. "ramboot=" CONFIG_RAMBOOTCOMMAND "\0"
  72. #endif
  73. #if defined(CONFIG_NFSBOOTCOMMAND)
  74. "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0"
  75. #endif
  76. #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
  77. "bootdelay=" MK_STR(CONFIG_BOOTDELAY) "\0"
  78. #endif
  79. #if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
  80. "baudrate=" MK_STR(CONFIG_BAUDRATE) "\0"
  81. #endif
  82. #ifdef CONFIG_LOADS_ECHO
  83. "loads_echo=" MK_STR(CONFIG_LOADS_ECHO) "\0"
  84. #endif
  85. #ifdef CONFIG_ETHADDR
  86. "ethaddr=" MK_STR(CONFIG_ETHADDR) "\0"
  87. #endif
  88. #ifdef CONFIG_ETH1ADDR
  89. "eth1addr=" MK_STR(CONFIG_ETH1ADDR) "\0"
  90. #endif
  91. #ifdef CONFIG_ETH2ADDR
  92. "eth2addr=" MK_STR(CONFIG_ETH2ADDR) "\0"
  93. #endif
  94. #ifdef CONFIG_ETHPRIME
  95. "ethprime=" CONFIG_ETHPRIME "\0"
  96. #endif
  97. #ifdef CONFIG_IPADDR
  98. "ipaddr=" MK_STR(CONFIG_IPADDR) "\0"
  99. #endif
  100. #ifdef CONFIG_SERVERIP
  101. "serverip=" MK_STR(CONFIG_SERVERIP) "\0"
  102. #endif
  103. #ifdef CFG_AUTOLOAD
  104. "autoload=" CFG_AUTOLOAD "\0"
  105. #endif
  106. #ifdef CONFIG_ROOTPATH
  107. "rootpath=" MK_STR(CONFIG_ROOTPATH) "\0"
  108. #endif
  109. #ifdef CONFIG_GATEWAYIP
  110. "gatewayip=" MK_STR(CONFIG_GATEWAYIP) "\0"
  111. #endif
  112. #ifdef CONFIG_NETMASK
  113. "netmask=" MK_STR(CONFIG_NETMASK) "\0"
  114. #endif
  115. #ifdef CONFIG_HOSTNAME
  116. "hostname=" MK_STR(CONFIG_HOSTNAME) "\0"
  117. #endif
  118. #ifdef CONFIG_BOOTFILE
  119. "bootfile=" MK_STR(CONFIG_BOOTFILE) "\0"
  120. #endif
  121. #ifdef CONFIG_LOADADDR
  122. "loadaddr=" MK_STR(CONFIG_LOADADDR) "\0"
  123. #endif
  124. #ifdef CONFIG_PREBOOT
  125. "preboot=" CONFIG_PREBOOT "\0"
  126. #endif
  127. #ifdef CONFIG_CLOCKS_IN_MHZ
  128. "clocks_in_mhz=" "1" "\0"
  129. #endif
  130. #ifdef CONFIG_EXTRA_ENV_SETTINGS
  131. CONFIG_EXTRA_ENV_SETTINGS
  132. #endif
  133. "\0" /* Termimate env_t data with 2 NULs */
  134. };
  135. static int flash_io (int mode);
  136. static uchar *envmatch(uchar *s1, uchar *s2);
  137. static int env_init(void);
  138. static int parse_config(void);
  139. #if defined(CONFIG_FILE)
  140. static int get_config(char *);
  141. #endif
  142. static inline ulong getenvsize(void)
  143. {
  144. ulong rc = CFG_ENV_SIZE - sizeof(long);
  145. if (HaveRedundEnv)
  146. rc -= sizeof(char);
  147. return rc;
  148. }
  149. /*
  150. * Search the environment for a variable.
  151. * Return the value, if found, or NULL, if not found.
  152. */
  153. unsigned char *fw_getenv (unsigned char *name)
  154. {
  155. uchar *env, *nxt;
  156. if (env_init())
  157. return (NULL);
  158. for (env=environment.data; *env; env=nxt+1) {
  159. uchar *val;
  160. for (nxt=env; *nxt; ++nxt) {
  161. if (nxt >= &environment.data[ENV_SIZE]) {
  162. fprintf (stderr, "## Error: "
  163. "environment not terminated\n");
  164. return (NULL);
  165. }
  166. }
  167. val=envmatch(name, env);
  168. if (!val)
  169. continue;
  170. return (val);
  171. }
  172. return (NULL);
  173. }
  174. /*
  175. * Print the current definition of one, or more, or all
  176. * environment variables
  177. */
  178. void fw_printenv(int argc, char *argv[])
  179. {
  180. uchar *env, *nxt;
  181. int i, n_flag;
  182. if (env_init())
  183. return;
  184. if (argc == 1) { /* Print all env variables */
  185. for (env=environment.data; *env; env=nxt+1) {
  186. for (nxt=env; *nxt; ++nxt) {
  187. if (nxt >= &environment.data[ENV_SIZE]) {
  188. fprintf (stderr, "## Error: "
  189. "environment not terminated\n");
  190. return;
  191. }
  192. }
  193. printf("%s\n", env);
  194. }
  195. return;
  196. }
  197. if (strcmp(argv[1], "-n") == 0) {
  198. n_flag = 1;
  199. ++argv;
  200. --argc;
  201. if (argc != 2) {
  202. fprintf (stderr, "## Error: "
  203. "`-n' option requires exactly one argument\n");
  204. return;
  205. }
  206. } else {
  207. n_flag = 0;
  208. }
  209. for (i=1; i<argc; ++i) { /* print single env variables */
  210. uchar *name = argv[i];
  211. uchar *val = NULL;
  212. for (env=environment.data; *env; env=nxt+1) {
  213. for (nxt=env; *nxt; ++nxt) {
  214. if (nxt >= &environment.data[ENV_SIZE]) {
  215. fprintf (stderr, "## Error: "
  216. "environment not terminated\n");
  217. return;
  218. }
  219. }
  220. val=envmatch(name, env);
  221. if (val) {
  222. if (!n_flag) {
  223. fputs (name, stdout);
  224. putc ('=', stdout);
  225. }
  226. puts (val);
  227. break;
  228. }
  229. }
  230. if (!val)
  231. fprintf (stderr, "## Error: \"%s\" not defined\n",
  232. name);
  233. }
  234. }
  235. /*
  236. * Deletes or sets environment variables. Returns errno style error codes:
  237. * 0 - OK
  238. * EINVAL - need at least 1 argument
  239. * EROFS - certain variables ("ethaddr", "serial#") cannot be
  240. * modified or deleted
  241. *
  242. */
  243. int fw_setenv (int argc, char *argv[])
  244. {
  245. int i, len;
  246. uchar *env, *nxt;
  247. uchar *oldval = NULL;
  248. uchar *name;
  249. if (argc < 2) {
  250. return (EINVAL);
  251. }
  252. if (env_init())
  253. return (errno);
  254. name = argv[1];
  255. /*
  256. * search if variable with this name already exists
  257. */
  258. for (env=environment.data; *env; env=nxt+1) {
  259. for (nxt=env; *nxt; ++nxt) {
  260. if (nxt >= &environment.data[ENV_SIZE]) {
  261. fprintf (stderr, "## Error: "
  262. "environment not terminated\n");
  263. return (EINVAL);
  264. }
  265. }
  266. if ((oldval=envmatch(name, env)) != NULL)
  267. break;
  268. }
  269. /*
  270. * Delete any existing definition
  271. */
  272. if (oldval) {
  273. /*
  274. * Ethernet Address and serial# can be set only once
  275. */
  276. if ((strcmp (name, "ethaddr") == 0) ||
  277. (strcmp (name, "serial#") == 0) ) {
  278. fprintf (stderr, "Can't overwrite \"%s\"\n", name);
  279. return (EROFS);
  280. }
  281. if (*++nxt == '\0') {
  282. *env = '\0';
  283. } else {
  284. for (;;) {
  285. *env = *nxt++;
  286. if ((*env == '\0') && (*nxt == '\0'))
  287. break;
  288. ++env;
  289. }
  290. }
  291. *++env = '\0';
  292. }
  293. /* Delete only ? */
  294. if (argc < 3)
  295. goto WRITE_FLASH;
  296. /*
  297. * Append new definition at the end
  298. */
  299. for (env=environment.data; *env || *(env+1); ++env)
  300. ;
  301. if (env > environment.data)
  302. ++env;
  303. /*
  304. * Overflow when:
  305. * "name" + "=" + "val" +"\0\0" > CFG_ENV_SIZE - (env-environment)
  306. */
  307. len = strlen(name) + 2;
  308. /* add '=' for first arg, ' ' for all others */
  309. for (i=2; i<argc; ++i) {
  310. len += strlen(argv[i]) + 1;
  311. }
  312. if (len > (&environment.data[ENV_SIZE]-env)) {
  313. fprintf (stderr,
  314. "Error: environment overflow, \"%s\" deleted\n",
  315. name);
  316. return (-1);
  317. }
  318. while ((*env = *name++) != '\0')
  319. env++;
  320. for (i=2; i<argc; ++i) {
  321. uchar *val = argv[i];
  322. *env = (i==2) ? '=' : ' ';
  323. while ((*++env = *val++) != '\0')
  324. ;
  325. }
  326. /* end is marked with double '\0' */
  327. *++env = '\0';
  328. WRITE_FLASH:
  329. /* Update CRC */
  330. environment.crc = crc32(0, environment.data, ENV_SIZE);
  331. /* write environment back to flash */
  332. if (flash_io (O_RDWR)) {
  333. fprintf (stderr,
  334. "Error: can't write fw_env to flash\n");
  335. return (-1);
  336. }
  337. return (0);
  338. }
  339. static int flash_io (int mode)
  340. {
  341. int fd, fdr, rc, otherdev, len, resid;
  342. erase_info_t erase;
  343. char *data;
  344. if ((fd = open(DEVNAME(curdev), mode)) < 0) {
  345. fprintf (stderr,
  346. "Can't open %s: %s\n",
  347. DEVNAME(curdev), strerror(errno));
  348. return (-1);
  349. }
  350. len = sizeof(environment.crc);
  351. if (HaveRedundEnv) {
  352. len += sizeof(environment.flags);
  353. }
  354. if (mode == O_RDWR) {
  355. if (HaveRedundEnv) {
  356. /* switch to next partition for writing */
  357. otherdev = !curdev;
  358. if ((fdr = open(DEVNAME(otherdev), mode)) < 0) {
  359. fprintf (stderr,
  360. "Can't open %s: %s\n",
  361. DEVNAME(otherdev), strerror(errno));
  362. return (-1);
  363. }
  364. } else {
  365. otherdev = curdev;
  366. fdr = fd;
  367. }
  368. printf("Unlocking flash...\n");
  369. erase.length = DEVESIZE(otherdev);
  370. erase.start = DEVOFFSET(otherdev);
  371. ioctl (fdr, MEMUNLOCK, &erase);
  372. if (HaveRedundEnv) {
  373. erase.length = DEVESIZE(curdev);
  374. erase.start = DEVOFFSET(curdev);
  375. ioctl (fd, MEMUNLOCK, &erase);
  376. environment.flags = active_flag;
  377. }
  378. printf("Done\n");
  379. resid = DEVESIZE(otherdev) - CFG_ENV_SIZE;
  380. if (resid) {
  381. if ((data = malloc(resid)) == NULL) {
  382. fprintf(stderr,
  383. "Cannot malloc %d bytes: %s\n",
  384. resid, strerror(errno));
  385. return (-1);
  386. }
  387. if (lseek (fdr, DEVOFFSET(otherdev) + CFG_ENV_SIZE, SEEK_SET) == -1) {
  388. fprintf (stderr,
  389. "seek error on %s: %s\n",
  390. DEVNAME(otherdev), strerror(errno));
  391. return (-1);
  392. }
  393. if ((rc = read (fdr, data, resid)) != resid) {
  394. fprintf (stderr,
  395. "read error on %s: %s\n",
  396. DEVNAME(otherdev), strerror(errno));
  397. return (-1);
  398. }
  399. }
  400. printf("Erasing old environment...\n");
  401. erase.length = DEVESIZE(otherdev);
  402. erase.start = DEVOFFSET(otherdev);
  403. if (ioctl (fdr, MEMERASE, &erase) != 0) {
  404. fprintf (stderr, "MTD erase error on %s: %s\n",
  405. DEVNAME(otherdev), strerror(errno));
  406. return (-1);
  407. }
  408. printf("Done\n");
  409. printf("Writing environment to %s...\n",DEVNAME(otherdev));
  410. if (lseek (fdr, DEVOFFSET(otherdev), SEEK_SET) == -1) {
  411. fprintf (stderr,
  412. "seek error on %s: %s\n",
  413. DEVNAME(otherdev), strerror(errno));
  414. return (-1);
  415. }
  416. if (write(fdr, &environment, len) != len) {
  417. fprintf (stderr,
  418. "CRC write error on %s: %s\n",
  419. DEVNAME(otherdev), strerror(errno));
  420. return (-1);
  421. }
  422. if (write(fdr, environment.data, ENV_SIZE) != ENV_SIZE) {
  423. fprintf (stderr,
  424. "Write error on %s: %s\n",
  425. DEVNAME(otherdev), strerror(errno));
  426. return (-1);
  427. }
  428. if (resid) {
  429. if (write (fdr, data, resid) != resid) {
  430. fprintf (stderr,
  431. "write error on %s: %s\n",
  432. DEVNAME(curdev), strerror(errno));
  433. return (-1);
  434. }
  435. free(data);
  436. }
  437. if (HaveRedundEnv) {
  438. /* change flag on current active env partition */
  439. if (lseek (fd, DEVOFFSET(curdev) + sizeof(ulong), SEEK_SET) == -1) {
  440. fprintf (stderr,
  441. "seek error on %s: %s\n",
  442. DEVNAME(curdev), strerror(errno));
  443. return (-1);
  444. }
  445. if (write (fd, &obsolete_flag, sizeof(obsolete_flag)) !=
  446. sizeof(obsolete_flag)) {
  447. fprintf (stderr,
  448. "Write error on %s: %s\n",
  449. DEVNAME(curdev), strerror(errno));
  450. return (-1);
  451. }
  452. }
  453. printf("Done\n");
  454. printf("Locking ...\n");
  455. erase.length = DEVESIZE(otherdev);
  456. erase.start = DEVOFFSET(otherdev);
  457. ioctl (fdr, MEMLOCK, &erase);
  458. if (HaveRedundEnv) {
  459. erase.length = DEVESIZE(curdev);
  460. erase.start = DEVOFFSET(curdev);
  461. ioctl (fd, MEMLOCK, &erase);
  462. if (close(fdr)) {
  463. fprintf (stderr,
  464. "I/O error on %s: %s\n",
  465. DEVNAME(otherdev), strerror(errno));
  466. return (-1);
  467. }
  468. }
  469. printf("Done\n");
  470. } else {
  471. if (lseek (fd, DEVOFFSET(curdev), SEEK_SET) == -1) {
  472. fprintf (stderr,
  473. "seek error on %s: %s\n",
  474. DEVNAME(curdev), strerror(errno));
  475. return (-1);
  476. }
  477. if (read (fd, &environment, len) != len) {
  478. fprintf (stderr,
  479. "CRC read error on %s: %s\n",
  480. DEVNAME(curdev), strerror(errno));
  481. return (-1);
  482. }
  483. if ((rc = read (fd, environment.data, ENV_SIZE)) != ENV_SIZE) {
  484. fprintf (stderr,
  485. "Read error on %s: %s\n",
  486. DEVNAME(curdev), strerror(errno));
  487. return (-1);
  488. }
  489. }
  490. if (close(fd)) {
  491. fprintf (stderr,
  492. "I/O error on %s: %s\n",
  493. DEVNAME(curdev), strerror(errno));
  494. return (-1);
  495. }
  496. /* everything ok */
  497. return (0);
  498. }
  499. /*
  500. * s1 is either a simple 'name', or a 'name=value' pair.
  501. * s2 is a 'name=value' pair.
  502. * If the names match, return the value of s2, else NULL.
  503. */
  504. static uchar *
  505. envmatch (uchar *s1, uchar *s2)
  506. {
  507. while (*s1 == *s2++)
  508. if (*s1++ == '=')
  509. return(s2);
  510. if (*s1 == '\0' && *(s2-1) == '=')
  511. return(s2);
  512. return(NULL);
  513. }
  514. /*
  515. * Prevent confusion if running from erased flash memory
  516. */
  517. static int env_init(void)
  518. {
  519. int crc1, crc1_ok;
  520. uchar *addr1;
  521. int crc2, crc2_ok;
  522. uchar flag1, flag2, *addr2;
  523. if (parse_config()) /* should fill envdevices */
  524. return 1;
  525. if ((addr1 = calloc (1, ENV_SIZE)) == NULL) {
  526. fprintf (stderr,
  527. "Not enough memory for environment (%ld bytes)\n",
  528. ENV_SIZE);
  529. return (errno);
  530. }
  531. /* read environment from FLASH to local buffer */
  532. environment.data = addr1;
  533. curdev = 0;
  534. if (flash_io (O_RDONLY)) {
  535. return (errno);
  536. }
  537. crc1_ok = ((crc1 = crc32(0, environment.data, ENV_SIZE))
  538. == environment.crc);
  539. if (!HaveRedundEnv) {
  540. if (!crc1_ok) {
  541. fprintf (stderr,
  542. "Warning: Bad CRC, using default environment\n");
  543. environment.data = default_environment;
  544. free(addr1);
  545. }
  546. } else {
  547. flag1 = environment.flags;
  548. curdev = 1;
  549. if ((addr2 = calloc (1, ENV_SIZE)) == NULL) {
  550. fprintf (stderr,
  551. "Not enough memory for environment (%ld bytes)\n",
  552. ENV_SIZE);
  553. return (errno);
  554. }
  555. environment.data = addr2;
  556. if (flash_io (O_RDONLY)) {
  557. return (errno);
  558. }
  559. crc2_ok = ((crc2 = crc32(0, environment.data, ENV_SIZE))
  560. == environment.crc);
  561. flag2 = environment.flags;
  562. if (crc1_ok && ! crc2_ok) {
  563. environment.data = addr1;
  564. environment.flags = flag1;
  565. environment.crc = crc1;
  566. curdev = 0;
  567. free(addr2);
  568. }
  569. else if (! crc1_ok && crc2_ok) {
  570. environment.data = addr2;
  571. environment.flags = flag2;
  572. environment.crc = crc2;
  573. curdev = 1;
  574. free(addr1);
  575. }
  576. else if (! crc1_ok && ! crc2_ok) {
  577. fprintf (stderr,
  578. "Warning: Bad CRC, using default environment\n");
  579. environment.data = default_environment;
  580. curdev = 0;
  581. free(addr2);
  582. free(addr1);
  583. }
  584. else if (flag1 == active_flag && flag2 == obsolete_flag) {
  585. environment.data = addr1;
  586. environment.flags = flag1;
  587. environment.crc = crc1;
  588. curdev = 0;
  589. free(addr2);
  590. }
  591. else if (flag1 == obsolete_flag && flag2 == active_flag) {
  592. environment.data = addr2;
  593. environment.flags = flag2;
  594. environment.crc = crc2;
  595. curdev = 1;
  596. free(addr1);
  597. }
  598. else if (flag1 == flag2) {
  599. environment.data = addr1;
  600. environment.flags = flag1;
  601. environment.crc = crc1;
  602. curdev = 0;
  603. free(addr2);
  604. }
  605. else if (flag1 == 0xFF) {
  606. environment.data = addr1;
  607. environment.flags = flag1;
  608. environment.crc = crc1;
  609. curdev = 0;
  610. free(addr2);
  611. }
  612. else if (flag2 == 0xFF) {
  613. environment.data = addr2;
  614. environment.flags = flag2;
  615. environment.crc = crc2;
  616. curdev = 1;
  617. free(addr1);
  618. }
  619. }
  620. return (0);
  621. }
  622. static int parse_config()
  623. {
  624. struct stat st;
  625. #if defined(CONFIG_FILE)
  626. /* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */
  627. if (get_config(CONFIG_FILE)) {
  628. fprintf (stderr,
  629. "Cannot parse config file: %s\n",
  630. strerror(errno));
  631. return 1;
  632. }
  633. #else
  634. strcpy(DEVNAME(0), DEVICE1_NAME);
  635. DEVOFFSET(0) = DEVICE1_OFFSET;
  636. ENVSIZE(0) = ENV1_SIZE;
  637. DEVESIZE(0) = DEVICE1_ESIZE;
  638. #ifdef HAVE_REDUND
  639. strcpy(DEVNAME(1), DEVICE2_NAME);
  640. DEVOFFSET(1) = DEVICE2_OFFSET;
  641. ENVSIZE(1) = ENV2_SIZE;
  642. DEVESIZE(1) = DEVICE2_ESIZE;
  643. HaveRedundEnv = 1;
  644. #endif
  645. #endif
  646. if (stat (DEVNAME(0), &st)) {
  647. fprintf (stderr,
  648. "Cannot access MTD device %s: %s\n",
  649. DEVNAME(0), strerror(errno));
  650. return 1;
  651. }
  652. if (HaveRedundEnv && stat (DEVNAME(1), &st)) {
  653. fprintf (stderr,
  654. "Cannot access MTD device %s: %s\n",
  655. DEVNAME(2), strerror(errno));
  656. return 1;
  657. }
  658. return 0;
  659. }
  660. #if defined(CONFIG_FILE)
  661. static int get_config (char *fname)
  662. {
  663. FILE *fp;
  664. int i = 0;
  665. int rc;
  666. char dump[128];
  667. if ((fp = fopen(fname, "r")) == NULL) {
  668. return 1;
  669. }
  670. while ((i < 2) &&
  671. ((rc = fscanf (fp, "%s %lx %lx %lx",
  672. DEVNAME(i), &DEVOFFSET(i), &ENVSIZE(i), &DEVESIZE(i))) != EOF)) {
  673. /* Skip incomplete conversions and comment strings */
  674. if ((rc < 3) || (*DEVNAME(i) == '#')) {
  675. fgets (dump, sizeof(dump), fp); /* Consume till end */
  676. continue;
  677. }
  678. i++;
  679. }
  680. fclose(fp);
  681. HaveRedundEnv = i - 1;
  682. if (!i) { /* No valid entries found */
  683. errno = EINVAL;
  684. return 1;
  685. } else
  686. return 0;
  687. }
  688. #endif