1 /*
2 * auto_update.c
3 *
4 * Description:Read the image from the external storage medium SD or USB and
5 * burn it to the board storage medium.
6 *
7 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24 #include <common.h>
25 #include <environment.h>
26 #include <command.h>
27 #include <malloc.h>
28 #include <image.h>
29 #include <asm/byteorder.h>
30 #include <asm/io.h>
31 #include <spi_flash.h>
32 #include <linux/mtd/mtd.h>
33 #include <fat.h>
34
35 #if (CONFIG_AUTO_UPDATE == 1) /* cover the whole file */
36
37 #ifdef CONFIG_AUTO_SD_UPDATE
38 #ifndef CONFIG_MMC
39 #error "should have defined CONFIG_MMC"
40 #endif
41 #include <mmc.h>
42 #include "mmc_init.c"
43 #endif
44
45 #if defined CONFIG_AUTO_USB_UPDATE
46 #if !defined CONFIG_USB_OHCI && !defined CONFIG_USB_XHCI
47 #error "should have defined CONFIG_USB_OHCI or CONFIG_USB_XHCI"
48 #endif
49 #ifndef CONFIG_USB_STORAGE
50 #error "should have defined CONFIG_USB_STORAGE"
51 #endif
52 #include <usb.h>
53 #include "usb_init.c"
54 #endif
55
56 #undef AU_DEBUG
57 #undef debug
58 #ifdef AU_DEBUG
59 #define debug(fmt, args...) printf(fmt, ##args)
60 #else
61 #define debug(fmt, args...)
62 #endif /* AU_DEBUG */
63
64 /* possible names of files on the medium. */
65 #define AU_FIRMWARE "u-boot"
66 #define AU_KERNEL "kernel"
67 #define AU_ROOTFS "rootfs"
68
69 #define NAME_LEN 20
70 #define ENV_LEN 20
71 #define PERCENT 100
72 #define HEX 16
73 #define COUNT 3
74 #define MMC2 2
75 #define MAX_HZ 1000000UL
76 #define SPI_MODE3 3
77
78 struct flash_layout {
79 long start;
80 long end;
81 };
82 static struct spi_flash *flash;
83
84 struct medium_interface {
85 char name[NAME_LEN];
86 int (*init)(void);
87 void (*exit)(void);
88 };
89
90 #define MAX_UPDATE_INTF 3
91 static struct medium_interface s_intf[MAX_UPDATE_INTF] = {
92 #ifdef CONFIG_AUTO_SD_UPDATE
93 {.name = "mmc", .init = mmc_stor_init, .exit = mmc_stor_exit, },
94 #endif
95 #ifdef CONFIG_AUTO_USB_UPDATE
96 {.name = "usb", .init = usb_stor_init, .exit = usb_stor_exit, },
97 #endif
98 };
99
100 /* layout of the FLASH. ST = start address, ND = end address. */
101 #define AU_FL_FIRMWARE_ST 0x0
102 #define AU_FL_FIRMWARE_ND 0x7FFFF
103 #define AU_FL_KERNEL_ST 0x100000
104 #define AU_FL_KERNEL_ND 0x5FFFFF
105 #define AU_FL_ROOTFS_ST 0x600000
106 #define AU_FL_ROOTFS_ND 0xbFFFFF
107
108 static int au_stor_curr_dev; /* current device */
109
110 /* index of each file in the following arrays */
111 #define IDX_FIRMWARE 0
112 #define IDX_KERNEL 1
113 #define IDX_ROOTFS 2
114
115 /* max. number of files which could interest us */
116 #define AU_MAXFILES 3
117
118 /* pointers to file names */
119 char *aufile[AU_MAXFILES] = {
120 AU_FIRMWARE,
121 AU_KERNEL,
122 AU_ROOTFS
123 };
124
125 /* sizes of flash areas for each file */
126 long ausize[AU_MAXFILES] = {
127 (AU_FL_FIRMWARE_ND + 1) - AU_FL_FIRMWARE_ST,
128 (AU_FL_KERNEL_ND + 1) - AU_FL_KERNEL_ST,
129 (AU_FL_ROOTFS_ND + 1) - AU_FL_ROOTFS_ST,
130 };
131
132 /* array of flash areas start and end addresses */
133 struct flash_layout aufl_layout[AU_MAXFILES] = {
134 { AU_FL_FIRMWARE_ST, AU_FL_FIRMWARE_ND, },
135 { AU_FL_KERNEL_ST, AU_FL_KERNEL_ND, },
136 { AU_FL_ROOTFS_ST, AU_FL_ROOTFS_ND, },
137 };
138
139 /* where to load files into memory */
140 #if defined(CONFIG_HI3559AV100ES)
141 #define LOAD_ADDR ((unsigned char *)0x42000000)
142 #else
143 #define LOAD_ADDR ((unsigned char *)0x82000000)
144 #endif
145 /* the app is the largest image */
146 #define MAX_LOADSZ ausize[IDX_ROOTFS]
147
au_check_cksum_valid(int idx,long nbytes)148 static int au_check_cksum_valid(int idx, long nbytes)
149 {
150 image_header_t *hdr;
151 unsigned long checksum;
152
153 hdr = (image_header_t *)LOAD_ADDR;
154
155 if (nbytes != (sizeof(*hdr) + ntohl(hdr->ih_size))) {
156 printf("Image %s bad total SIZE\n", aufile[idx]);
157 return -1;
158 }
159 /* check the data CRC */
160 checksum = ntohl(hdr->ih_dcrc);
161 if (crc32(0, (unsigned char const *)(LOAD_ADDR + sizeof(*hdr)),
162 ntohl(hdr->ih_size)) != checksum) {
163 printf("Image %s bad data checksum\n", aufile[idx]);
164 return -1;
165 }
166
167 return 0;
168 }
169
au_check_header_valid(int idx,long nbytes)170 static int au_check_header_valid(int idx, long nbytes)
171 {
172 image_header_t *hdr;
173 unsigned long checksum;
174
175 char env[ENV_LEN];
176 char auversion[ENV_LEN];
177
178 hdr = (image_header_t *)LOAD_ADDR;
179 /* check the easy ones first */
180
181 #undef CHECK_VALID_DEBUG
182 #ifdef CHECK_VALID_DEBUG
183 printf("\nmagic %#x %#x\n", ntohl(hdr->ih_magic), IH_MAGIC);
184 printf("arch %#x %#x\n", hdr->ih_arch, IH_ARCH_ARM);
185 printf("size %#x %#lx\n", ntohl(hdr->ih_size), nbytes);
186 printf("type %#x %#x\n", hdr->ih_type, IH_TYPE_KERNEL);
187 #endif
188 if (nbytes < sizeof(*hdr)) {
189 printf("Image %s bad header SIZE\n", aufile[idx]);
190 return -1;
191 }
192 if (ntohl(hdr->ih_magic) != IH_MAGIC || hdr->ih_arch != IH_ARCH_ARM) {
193 printf("Image %s bad MAGIC or ARCH\n", aufile[idx]);
194 return -1;
195 }
196 /* check the hdr CRC */
197 checksum = ntohl(hdr->ih_hcrc);
198 hdr->ih_hcrc = 0;
199
200 if (crc32(0, (unsigned char const *)hdr, sizeof(*hdr)) != checksum) {
201 printf("Image %s bad header checksum\n", aufile[idx]);
202 return -1;
203 }
204 hdr->ih_hcrc = htonl(checksum);
205 /* check the type - could do this all in one gigantic if() */
206 if ((idx == IDX_FIRMWARE) && (hdr->ih_type != IH_TYPE_FIRMWARE)) {
207 printf("Image %s wrong type\n", aufile[idx]);
208 return -1;
209 }
210 if ((idx == IDX_KERNEL) && (hdr->ih_type != IH_TYPE_KERNEL)) {
211 printf("Image %s wrong type\n", aufile[idx]);
212 return -1;
213 }
214 if ((idx == IDX_ROOTFS) &&
215 (hdr->ih_type != IH_TYPE_RAMDISK) &&
216 (hdr->ih_type != IH_TYPE_FILESYSTEM)) {
217 printf("Image %s wrong type\n", aufile[idx]);
218 ausize[idx] = 0;
219 return -1;
220 }
221
222 /* recycle checksum */
223 checksum = ntohl(hdr->ih_size);
224 /* for kernel and app the image header must also fit into flash */
225 if ((idx == IDX_KERNEL) || (hdr->ih_type == IH_TYPE_RAMDISK))
226 checksum += sizeof(*hdr);
227
228 /* check the size does not exceed space in flash. HUSH scripts */
229 /* all have ausize[] set to 0 */
230 if ((ausize[idx] != 0) && (ausize[idx] < checksum)) {
231 printf("Image %s is bigger than FLASH\n", aufile[idx]);
232 return -1;
233 }
234
235 sprintf(env, "%lx", (unsigned long)ntohl(hdr->ih_time));
236 setenv(auversion, env);
237
238 return 0;
239 }
240
schedule_notify(unsigned long offset,unsigned long len,unsigned long off_start)241 static void schedule_notify(unsigned long offset, unsigned long len,
242 unsigned long off_start)
243 {
244 int percent_complete = -1;
245
246 do {
247 unsigned long long n =
248 (unsigned long long)(offset - off_start) * PERCENT;
249 int percent;
250
251 do_div(n, len);
252 percent = (int)n;
253
254 /* output progress message only at whole percent
255 * steps to reduce the number of messages
256 * printed on (slow) serial consoles
257 */
258 if (percent != percent_complete) {
259 percent_complete = percent;
260
261 printf("\rOperation at 0x%lx -- %3d%% complete",
262 offset, percent);
263 }
264 } while (0);
265 }
266
spi_flash_erase_op(struct spi_flash * flash,unsigned long offset,unsigned long len)267 static int spi_flash_erase_op(struct spi_flash *flash, unsigned long offset,
268 unsigned long len)
269 {
270 int ret;
271 struct mtd_info_ex *spiflash_info = get_spiflash_info();
272 unsigned long erase_start, erase_len, erase_step;
273
274 erase_start = offset;
275 erase_len = len;
276 erase_step = spiflash_info->erasesize;
277
278 while (len > 0) {
279 if (len < erase_step)
280 erase_step = len;
281
282 ret = flash->erase(flash, (u32)offset, erase_step);
283 if (ret)
284 return 1;
285
286 len -= erase_step;
287 offset += erase_step;
288 /* notify real time schedule */
289 schedule_notify(offset, erase_len, erase_start);
290 }
291 return ret;
292 }
293
spi_flash_write_op(struct spi_flash * flash,unsigned long offset,unsigned long len,char * buf)294 static int spi_flash_write_op(struct spi_flash *flash, unsigned long offset,
295 unsigned long len, char *buf)
296 {
297 int ret;
298 unsigned long write_start, write_len, write_step;
299 char *pbuf = buf;
300 struct mtd_info_ex *spiflash_info = get_spiflash_info();
301
302 write_start = offset;
303 write_len = len;
304 write_step = spiflash_info->erasesize;
305
306 while (len > 0) {
307 if (len < write_step)
308 write_step = len;
309
310 ret = flash->write(flash, offset, write_step, pbuf);
311 if (ret)
312 break;
313
314 offset += write_step;
315 pbuf += write_step;
316 len -= write_step;
317 /* notify real time schedule */
318 schedule_notify(offset, write_len, write_start);
319 }
320
321 return ret;
322 }
323
au_do_update(int idx,long sz)324 static int au_do_update(int idx, long sz)
325 {
326 image_header_t *hdr;
327 unsigned long start, len;
328 unsigned long write_len;
329 int rc;
330 void *buf;
331 char *pbuf;
332
333 hdr = (image_header_t *)LOAD_ADDR;
334
335 start = aufl_layout[idx].start;
336 len = aufl_layout[idx].end - aufl_layout[idx].start + 1;
337
338 /*
339 * erase the address range.
340 */
341 printf("flash erase...\n");
342 rc = spi_flash_erase_op(flash, start, len);
343 if (rc) {
344 printf("SPI flash sector erase failed\n");
345 return 1;
346 }
347
348 buf = map_physmem((unsigned long)LOAD_ADDR, len, MAP_WRBACK);
349 if (!buf) {
350 puts("Failed to map physical memory\n");
351 return 1;
352 }
353
354 /* strip the header - except for the kernel and ramdisk */
355 if (hdr->ih_type == IH_TYPE_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) {
356 pbuf = buf;
357 write_len = sizeof(*hdr) + ntohl(hdr->ih_size);
358 } else {
359 pbuf = (buf + sizeof(*hdr));
360 write_len = ntohl(hdr->ih_size);
361 }
362
363 /* copy the data from RAM to FLASH */
364 printf("\nflash write...\n");
365 rc = spi_flash_write_op(flash, start, write_len, pbuf);
366 if (rc) {
367 printf("SPI flash write failed, return %d\n", rc);
368 return 1;
369 }
370
371 /* check the dcrc of the copy */
372 if (crc32(0, (unsigned char const *)(buf + sizeof(*hdr)),
373 ntohl(hdr->ih_size)) != ntohl(hdr->ih_dcrc)) {
374 printf("Image %s Bad Data Checksum After COPY\n", aufile[idx]);
375 return -1;
376 }
377
378 unmap_physmem(buf, len);
379
380 return 0;
381 }
382
get_update_env(char * img_start,char * img_end)383 static void get_update_env(char *img_start, char *img_end)
384 {
385 long start = -1;
386 long end = 0;
387 char *env;
388
389 /*
390 * check whether start and end are defined in environment
391 * variables.
392 */
393 env = env_get(img_start);
394 if (env != NULL)
395 start = simple_strtoul(env, NULL, HEX);
396
397 env = env_get(img_end);
398 if (env != NULL)
399 end = simple_strtoul(env, NULL, HEX);
400
401 if (start >= 0 && end && end > start) {
402 ausize[IDX_FIRMWARE] = (end + 1) - start;
403 aufl_layout[0].start = start;
404 aufl_layout[0].end = end;
405 }
406 }
407
408 /*
409 * If none of the update file(u-boot, kernel or rootfs) was found
410 * in the medium, return -1;
411 * If u-boot has been updated, return 1;
412 * Others, return 0;
413 */
update_to_flash(void)414 static int update_to_flash(void)
415 {
416 int i;
417 long sz;
418 int res, cnt;
419 int uboot_updated;
420 int image_found;
421
422 /* just loop thru all the possible files */
423 for (i = 0; i < AU_MAXFILES; i++) {
424 /* just read the header */
425 sz = file_fat_read(aufile[i], LOAD_ADDR, sizeof(image_header_t));
426 debug("read %s sz %ld hdr %d\n", aufile[i], sz, sizeof(image_header_t));
427 if (sz <= 0 || sz < sizeof(image_header_t)) {
428 debug("%s not found\n", aufile[i]);
429 continue;
430 }
431
432 image_found = 1;
433
434 if (au_check_header_valid(i, sz) < 0) {
435 debug("%s header not valid\n", aufile[i]);
436 continue;
437 }
438
439 sz = file_fat_read(aufile[i], LOAD_ADDR, MAX_LOADSZ);
440 debug("read %s sz %ld hdr %d\n", aufile[i], sz, sizeof(image_header_t));
441 if (sz <= 0 || sz <= sizeof(image_header_t)) {
442 debug("%s not found\n", aufile[i]);
443 continue;
444 }
445
446 if (au_check_cksum_valid(i, sz) < 0) {
447 debug("%s checksum not valid\n", aufile[i]);
448 continue;
449 }
450
451 /* If u-boot had been updated, we need to
452 * save current env to flash
453 */
454 if (strcmp((char *)AU_FIRMWARE, aufile[i]) == 0)
455 uboot_updated = 1;
456
457 /* this is really not a good idea, but it's what the customer wants. */
458 cnt = 0;
459 do {
460 res = au_do_update(i, sz);
461 /* let the user break out of the loop */
462 if (ctrlc() || had_ctrlc()) {
463 clear_ctrlc();
464
465 break;
466 }
467 cnt++;
468 } while (res < 0);
469 }
470
471 if (uboot_updated == 1)
472 return 1;
473
474 if (image_found == 1)
475 return 0;
476
477 return -1;
478 }
479
480 /*
481 * This is called by board_init() after the hardware has been set up
482 * and is usable. Only if SPI flash initialization failed will this function
483 * return -1, otherwise it will return 0;
484 */
do_auto_update(void)485 int do_auto_update(void)
486 {
487 struct blk_desc *stor_dev;
488 int old_ctrlc;
489 int j;
490 int state = -1;
491 int dev;
492
493 au_stor_curr_dev = -1;
494 for (j = 0; j < MAX_UPDATE_INTF; j++) {
495 if ((unsigned long)s_intf[j].name[0] != 0) {
496 au_stor_curr_dev = s_intf[j].init();
497 if (au_stor_curr_dev == -1) {
498 debug("No %s storage device found!\n",
499 s_intf[j].name);
500 continue;
501 }
502
503 dev = 0;
504
505 #if (defined CONFIG_ARCH_HI3559AV100ES)
506 if (strncmp("mmc", s_intf[j].name, sizeof("mmc")) == 0)
507 dev = MMC2;
508 #endif
509 debug("device name %s!\n", s_intf[j].name);
510 stor_dev = blk_get_dev(s_intf[j].name, dev);
511 if (stor_dev == NULL) {
512 debug("Unknow device type!\n");
513 continue;
514 }
515
516 if (fat_register_device(stor_dev, 1) != 0) {
517 debug("Unable to use %s %d:%d for fatls\n",
518 s_intf[j].name, au_stor_curr_dev, 1);
519 continue;
520 }
521
522 if (file_fat_detectfs() != 0) {
523 debug("file_fat_detectfs failed\n");
524 continue;
525 }
526
527 /*
528 * Get image layout from environment.
529 * If the start address and the end address
530 * were not definedin environment virables,
531 * use the default value
532 */
533 get_update_env("firmware_st", "firmware_nd");
534 get_update_env("kernel_st", "kernel_nd");
535 get_update_env("rootfs_st", "rootfs_nd");
536
537 /*
538 * make sure that we see CTRL-C
539 * and save the old state
540 */
541 old_ctrlc = disable_ctrlc(0);
542
543 /*
544 * CONFIG_SF_DEFAULT_SPEED equals 1000000,
545 * CONFIG_SF_DEFAULT_MODE equals 0x3
546 */
547 flash = spi_flash_probe(0, 0, MAX_HZ, SPI_MODE3);
548 if (!flash) {
549 printf("Failed to initialize SPI flash\n");
550 return -1;
551 }
552
553 state = update_to_flash();
554
555 /* restore the old state */
556 disable_ctrlc(old_ctrlc);
557
558 s_intf[j].exit();
559
560 /*
561 * no update file found
562 */
563 if (state == -1)
564 continue;
565 /*
566 * update files have been found on current medium,
567 * so just break here
568 */
569 break;
570 }
571 }
572
573 /*
574 * If u-boot has been updated, it's better to save environment to flash
575 */
576 if (state == 1)
577 saveenv();
578 return 0;
579 }
580 #endif /* CONFIG_AUTO_UPDATE */
581