summaryrefslogtreecommitdiffstats
path: root/packages/u-boot/u-boot-mkimage-openmoko-native/dynenv-harden.patch
blob: e7eca4ede5410e6f726d0beb65fa66c6cdc2dadb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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 <werner@openmoko.org>

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 <werner@openmoko.org>
+ *
+ * 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 <malloc.h>
 #include <environment.h>
 #include <nand.h>
+#include <util.h>
 #include <asm/errno.h>
 
 #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;
 }