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#include <common.h>
28
29#if !(defined(CONFIG_FIT) && defined(CONFIG_OF_LIBFDT))
30#error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update feature"
31#endif
32
33#if defined(CONFIG_SYS_NO_FLASH)
34#error "CONFIG_SYS_NO_FLASH defined, but FLASH is required for auto-update feature"
35#endif
36
37#include <command.h>
38#include <flash.h>
39#include <net.h>
40#include <malloc.h>
41
42
43#define UPDATE_FILE_ENV "updatefile"
44
45
46#ifndef CONFIG_UPDATE_LOAD_ADDR
47#define CONFIG_UPDATE_LOAD_ADDR 0x100000
48#endif
49
50#ifndef CONFIG_UPDATE_TFTP_MSEC_MAX
51#define CONFIG_UPDATE_TFTP_MSEC_MAX 100
52#endif
53
54#ifndef CONFIG_UPDATE_TFTP_CNT_MAX
55#define CONFIG_UPDATE_TFTP_CNT_MAX 0
56#endif
57
58extern ulong TftpRRQTimeoutMSecs;
59extern int TftpRRQTimeoutCountMax;
60extern flash_info_t flash_info[];
61extern ulong load_addr;
62
63static uchar *saved_prot_info;
64
65static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
66{
67 int size, rv;
68 ulong saved_timeout_msecs;
69 int saved_timeout_count;
70 char *saved_netretry, *saved_bootfile;
71
72 rv = 0;
73
74 saved_timeout_msecs = TftpRRQTimeoutMSecs;
75 saved_timeout_count = TftpRRQTimeoutCountMax;
76 saved_netretry = strdup(getenv("netretry"));
77 saved_bootfile = strdup(BootFile);
78
79
80 TftpRRQTimeoutMSecs = msec_max;
81 TftpRRQTimeoutCountMax = cnt_max;
82
83
84 setenv("netretry", "no");
85
86
87 load_addr = addr;
88 copy_filename(BootFile, filename, sizeof(BootFile));
89 size = NetLoop(TFTP);
90
91 if (size < 0)
92 rv = 1;
93 else if (size > 0)
94 flush_cache(addr, size);
95
96
97 TftpRRQTimeoutMSecs = saved_timeout_msecs;
98 TftpRRQTimeoutCountMax = saved_timeout_count;
99
100 setenv("netretry", saved_netretry);
101 if (saved_netretry != NULL)
102 free(saved_netretry);
103
104 if (saved_bootfile != NULL) {
105 copy_filename(BootFile, saved_bootfile, sizeof(BootFile));
106 free(saved_bootfile);
107 }
108
109 return rv;
110}
111
112static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
113{
114 uchar *sp_info_ptr;
115 ulong s;
116 int i, bank, cnt;
117 flash_info_t *info;
118
119 sp_info_ptr = NULL;
120
121 if (prot == 0) {
122 saved_prot_info =
123 calloc(CONFIG_SYS_MAX_FLASH_BANKS * CONFIG_SYS_MAX_FLASH_SECT, 1);
124 if (!saved_prot_info)
125 return 1;
126 }
127
128 for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
129 cnt = 0;
130 info = &flash_info[bank];
131
132
133 if (info->sector_count == 0)
134 return 0;
135
136
137 sp_info_ptr = saved_prot_info + (bank * CONFIG_SYS_MAX_FLASH_SECT);
138
139
140
141
142
143
144
145
146 if (addr_last > info->start[0] + info->size - 1)
147 addr_last = info->start[0] + info->size - 1;
148 if (addr_first < info->start[0])
149 addr_first = info->start[0];
150
151 for (i = 0; i < info->sector_count; i++) {
152
153 if (prot == 0) {
154 s = info->start[i];
155 if ((s >= addr_first) && (s <= addr_last))
156 sp_info_ptr[i] = info->protect[i];
157
158 }
159
160
161 if (sp_info_ptr[i] == 1) {
162#if defined(CONFIG_SYS_FLASH_PROTECTION)
163 if (flash_real_protect(info, i, prot))
164 return 1;
165#else
166 info->protect[i] = prot;
167#endif
168 cnt++;
169 }
170 }
171
172 if (cnt) {
173 printf("%sProtected %d sectors\n",
174 prot ? "": "Un-", cnt);
175 }
176 }
177
178 if((prot == 1) && saved_prot_info)
179 free(saved_prot_info);
180
181 return 0;
182}
183
184static int update_flash(ulong addr_source, ulong addr_first, ulong size)
185{
186 ulong addr_last = addr_first + size - 1;
187
188
189 if (flash_sect_roundb(&addr_last) > 0)
190 return 1;
191
192 if (addr_first >= addr_last) {
193 printf("Error: end address exceeds addressing space\n");
194 return 1;
195 }
196
197
198 if (update_flash_protect(0, addr_first, addr_last) > 0) {
199 printf("Error: could not unprotect flash sectors\n");
200 return 1;
201 }
202
203 printf("Erasing 0x%08lx - 0x%08lx", addr_first, addr_last);
204 if (flash_sect_erase(addr_first, addr_last) > 0) {
205 printf("Error: could not erase flash\n");
206 return 1;
207 }
208
209 printf("Copying to flash...");
210 if (flash_write((char *)addr_source, addr_first, size) > 0) {
211 printf("Error: could not copy to flash\n");
212 return 1;
213 }
214 printf("done\n");
215
216
217 if (update_flash_protect(1, addr_first, addr_last) > 0) {
218 printf("Error: could not protect flash sectors\n");
219 return 1;
220 }
221
222 return 0;
223}
224
225static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
226 ulong *fladdr, ulong *size)
227{
228 const void *data;
229
230 if (fit_image_get_data(fit, noffset, &data, (size_t *)size))
231 return 1;
232
233 if (fit_image_get_load(fit, noffset, (ulong *)fladdr))
234 return 1;
235
236 *addr = (ulong)data;
237
238 return 0;
239}
240
241int update_tftp(ulong addr)
242{
243 char *filename, *env_addr;
244 int images_noffset, ndepth, noffset;
245 ulong update_addr, update_fladdr, update_size;
246 void *fit;
247 int ret = 0;
248
249
250 if (addr)
251 goto got_update_file;
252
253 printf("Auto-update from TFTP: ");
254
255
256 filename = getenv(UPDATE_FILE_ENV);
257 if (filename == NULL) {
258 printf("failed, env. variable '%s' not found\n",
259 UPDATE_FILE_ENV);
260 return 1;
261 }
262
263 printf("trying update file '%s'\n", filename);
264
265
266 if ((env_addr = getenv("loadaddr")) != NULL)
267 addr = simple_strtoul(env_addr, NULL, 16);
268 else
269 addr = CONFIG_UPDATE_LOAD_ADDR;
270
271
272 if (update_load(filename, CONFIG_UPDATE_TFTP_MSEC_MAX,
273 CONFIG_UPDATE_TFTP_CNT_MAX, addr)) {
274 printf("Can't load update file, aborting auto-update\n");
275 return 1;
276 }
277
278got_update_file:
279 fit = (void *)addr;
280
281 if (!fit_check_format((void *)fit)) {
282 printf("Bad FIT format of the update file, aborting "
283 "auto-update\n");
284 return 1;
285 }
286
287
288 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
289
290 ndepth = 0;
291 noffset = fdt_next_node(fit, images_noffset, &ndepth);
292 while (noffset >= 0 && ndepth > 0) {
293 if (ndepth != 1)
294 goto next_node;
295
296 printf("Processing update '%s' :",
297 fit_get_name(fit, noffset, NULL));
298
299 if (!fit_image_check_hashes(fit, noffset)) {
300 printf("Error: invalid update hash, aborting\n");
301 ret = 1;
302 goto next_node;
303 }
304
305 printf("\n");
306 if (update_fit_getparams(fit, noffset, &update_addr,
307 &update_fladdr, &update_size)) {
308 printf("Error: can't get update parameteres, "
309 "aborting\n");
310 ret = 1;
311 goto next_node;
312 }
313 if (update_flash(update_addr, update_fladdr, update_size)) {
314 printf("Error: can't flash update, aborting\n");
315 ret = 1;
316 goto next_node;
317 }
318next_node:
319 noffset = fdt_next_node(fit, noffset, &ndepth);
320 }
321
322 return ret;
323}
324