common/cmd_nand.c: globalized arg_off_size include/util.h: new header to convenience functions, such as arg_off_size common/cmd_dynenv.c (do_dynenv): use arg_off_size to sanity-check offset and to allow use of partition name common/cmd_dynenv.c (do_dynenv): indicate in no uncertain terms when an update would not work due to Flash bits already cleared common/cmd_dynenv.c (do_dynenv): update CFG_ENV_OFFSET after successful "dynenv set", so that we can write the new environment without having to reboot - Werner Almesberger Index: u-boot/common/cmd_nand.c =================================================================== --- u-boot.orig/common/cmd_nand.c +++ u-boot/common/cmd_nand.c @@ -100,7 +100,7 @@ static inline int str2long(char *p, ulon return (*p != '\0' && *endptr == '\0') ? 1 : 0; } -static int +int arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, ulong *size) { int idx = nand_curr_device; Index: u-boot/include/util.h =================================================================== --- /dev/null +++ u-boot/include/util.h @@ -0,0 +1,33 @@ +/* + * util.h - Convenience functions + * + * (C) Copyright 2006-2007 OpenMoko, Inc. + * Author: Werner Almesberger + * + * 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 + */ + +#ifndef UTIL_H +#define UTIL_H + +#include "nand.h" + + +/* common/cmd_nand.c */ +int arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, + ulong *size); + +#endif /* UTIL_H */ Index: u-boot/common/cmd_dynenv.c =================================================================== --- u-boot.orig/common/cmd_dynenv.c +++ u-boot/common/cmd_dynenv.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #if defined(CFG_ENV_OFFSET_OOB) @@ -39,8 +40,8 @@ int do_dynenv(cmd_tbl_t *cmdtp, int flag if (!buf) return -ENOMEM; + ret = mtd->read_oob(mtd, 8, size, (size_t *) &size, (u_char *) buf); if (!strcmp(cmd, "get")) { - ret = mtd->read_oob(mtd, 8, size, (size_t *) &size, (u_char *) buf); if (buf[0] == 'E' && buf[1] == 'N' && buf[2] == 'V' && buf[3] == '0') @@ -49,7 +50,8 @@ int do_dynenv(cmd_tbl_t *cmdtp, int flag printf("No dynamic environment marker in OOB block 0\n"); } else if (!strcmp(cmd, "set")) { - unsigned long addr; + unsigned long addr, dummy; + if (argc < 3) goto usage; @@ -57,7 +59,23 @@ int do_dynenv(cmd_tbl_t *cmdtp, int flag buf[1] = 'N'; buf[2] = 'V'; buf[3] = '0'; - addr = simple_strtoul(argv[2], NULL, 16); + + if (arg_off_size(argc-2, argv+2, mtd, &addr, &dummy) < 0) { + printf("Offset or partition name expected\n"); + goto fail; + } + if (!ret) { + uint8_t tmp[4]; + int i; + + memcpy(&tmp, &addr, 4); + for (i = 0; i != 4; i++) + if (tmp[i] & ~buf[i+4]) { + printf("ERROR: erase OOB block to " + "write this value\n"); + goto fail; + } + } memcpy(buf+4, &addr, 4); printf("%02x %02x %02x %02x - %02x %02x %02x %02x\n", @@ -65,6 +83,8 @@ int do_dynenv(cmd_tbl_t *cmdtp, int flag buf[4], buf[5], buf[6], buf[7]); ret = mtd->write_oob(mtd, 8, size, (size_t *) &size, (u_char *) buf); + if (!ret) + CFG_ENV_OFFSET = addr; } else goto usage; @@ -72,8 +92,9 @@ int do_dynenv(cmd_tbl_t *cmdtp, int flag return ret; usage: - free(buf); printf("Usage:\n%s\n", cmdtp->usage); +fail: + free(buf); return 1; }