]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0 |
fa61ef6b KP |
2 | /* |
3 | * Copyright (C) 2016 Marvell International Ltd. | |
fa61ef6b KP |
4 | * https://spdx.org/licenses |
5 | */ | |
6 | ||
7 | #include <config.h> | |
8 | #include <common.h> | |
9 | #include <command.h> | |
10 | #include <vsprintf.h> | |
11 | #include <errno.h> | |
12 | #include <dm.h> | |
13 | ||
14 | #include <spi_flash.h> | |
15 | #include <spi.h> | |
16 | #include <nand.h> | |
17 | #include <usb.h> | |
18 | #include <fs.h> | |
19 | #include <mmc.h> | |
e559ef1a KP |
20 | #ifdef CONFIG_BLK |
21 | #include <blk.h> | |
22 | #endif | |
fa61ef6b KP |
23 | #include <u-boot/sha1.h> |
24 | #include <u-boot/sha256.h> | |
25 | ||
26 | #ifndef CONFIG_SYS_MMC_ENV_DEV | |
27 | #define CONFIG_SYS_MMC_ENV_DEV 0 | |
28 | #endif | |
29 | ||
30 | #if defined(CONFIG_ARMADA_8K) | |
31 | #define MAIN_HDR_MAGIC 0xB105B002 | |
32 | ||
33 | struct mvebu_image_header { | |
34 | u32 magic; /* 0-3 */ | |
35 | u32 prolog_size; /* 4-7 */ | |
36 | u32 prolog_checksum; /* 8-11 */ | |
37 | u32 boot_image_size; /* 12-15 */ | |
38 | u32 boot_image_checksum; /* 16-19 */ | |
39 | u32 rsrvd0; /* 20-23 */ | |
40 | u32 load_addr; /* 24-27 */ | |
41 | u32 exec_addr; /* 28-31 */ | |
42 | u8 uart_cfg; /* 32 */ | |
43 | u8 baudrate; /* 33 */ | |
44 | u8 ext_count; /* 34 */ | |
45 | u8 aux_flags; /* 35 */ | |
46 | u32 io_arg_0; /* 36-39 */ | |
47 | u32 io_arg_1; /* 40-43 */ | |
48 | u32 io_arg_2; /* 43-47 */ | |
49 | u32 io_arg_3; /* 48-51 */ | |
50 | u32 rsrvd1; /* 52-55 */ | |
51 | u32 rsrvd2; /* 56-59 */ | |
52 | u32 rsrvd3; /* 60-63 */ | |
53 | }; | |
54 | #elif defined(CONFIG_ARMADA_3700) /* A3700 */ | |
55 | #define HASH_SUM_LEN 16 | |
56 | #define IMAGE_VERSION_3_6_0 0x030600 | |
57 | #define IMAGE_VERSION_3_5_0 0x030500 | |
58 | ||
59 | struct common_tim_data { | |
60 | u32 version; | |
61 | u32 identifier; | |
62 | u32 trusted; | |
63 | u32 issue_date; | |
64 | u32 oem_unique_id; | |
65 | u32 reserved[5]; /* Reserve 20 bytes */ | |
66 | u32 boot_flash_sign; | |
67 | u32 num_images; | |
68 | u32 num_keys; | |
69 | u32 size_of_reserved; | |
70 | }; | |
71 | ||
72 | struct mvebu_image_info { | |
73 | u32 image_id; | |
74 | u32 next_image_id; | |
75 | u32 flash_entry_addr; | |
76 | u32 load_addr; | |
77 | u32 image_size; | |
78 | u32 image_size_to_hash; | |
79 | u32 hash_algorithm_id; | |
80 | u32 hash[HASH_SUM_LEN]; /* Reserve 512 bits for the hash */ | |
81 | u32 partition_number; | |
82 | u32 enc_algorithm_id; | |
83 | u32 encrypt_start_offset; | |
84 | u32 encrypt_size; | |
85 | }; | |
86 | #endif /* CONFIG_ARMADA_XXX */ | |
87 | ||
88 | struct bubt_dev { | |
89 | char name[8]; | |
90 | size_t (*read)(const char *file_name); | |
91 | int (*write)(size_t image_size); | |
92 | int (*active)(void); | |
93 | }; | |
94 | ||
95 | static ulong get_load_addr(void) | |
96 | { | |
97 | const char *addr_str; | |
98 | unsigned long addr; | |
99 | ||
00caae6d | 100 | addr_str = env_get("loadaddr"); |
fa61ef6b KP |
101 | if (addr_str) |
102 | addr = simple_strtoul(addr_str, NULL, 16); | |
103 | else | |
104 | addr = CONFIG_SYS_LOAD_ADDR; | |
105 | ||
106 | return addr; | |
107 | } | |
108 | ||
109 | /******************************************************************** | |
110 | * eMMC services | |
111 | ********************************************************************/ | |
d6400c3f | 112 | #if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(MMC_WRITE) |
fa61ef6b KP |
113 | static int mmc_burn_image(size_t image_size) |
114 | { | |
115 | struct mmc *mmc; | |
116 | lbaint_t start_lba; | |
117 | lbaint_t blk_count; | |
118 | ulong blk_written; | |
119 | int err; | |
120 | const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV; | |
e559ef1a KP |
121 | #ifdef CONFIG_BLK |
122 | struct blk_desc *blk_desc; | |
123 | #endif | |
fa61ef6b KP |
124 | mmc = find_mmc_device(mmc_dev_num); |
125 | if (!mmc) { | |
126 | printf("No SD/MMC/eMMC card found\n"); | |
127 | return -ENOMEDIUM; | |
128 | } | |
129 | ||
130 | err = mmc_init(mmc); | |
131 | if (err) { | |
132 | printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC", | |
133 | mmc_dev_num); | |
134 | return err; | |
135 | } | |
136 | ||
137 | #ifdef CONFIG_SYS_MMC_ENV_PART | |
138 | if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART) { | |
139 | err = mmc_switch_part(mmc_dev_num, CONFIG_SYS_MMC_ENV_PART); | |
140 | if (err) { | |
141 | printf("MMC partition switch failed\n"); | |
142 | return err; | |
143 | } | |
144 | } | |
145 | #endif | |
146 | ||
147 | /* SD reserves LBA-0 for MBR and boots from LBA-1, | |
148 | * MMC/eMMC boots from LBA-0 | |
149 | */ | |
150 | start_lba = IS_SD(mmc) ? 1 : 0; | |
e559ef1a KP |
151 | #ifdef CONFIG_BLK |
152 | blk_count = image_size / mmc->write_bl_len; | |
153 | if (image_size % mmc->write_bl_len) | |
154 | blk_count += 1; | |
155 | ||
156 | blk_desc = mmc_get_blk_desc(mmc); | |
157 | if (!blk_desc) { | |
158 | printf("Error - failed to obtain block descriptor\n"); | |
159 | return -ENODEV; | |
160 | } | |
161 | blk_written = blk_dwrite(blk_desc, start_lba, blk_count, | |
162 | (void *)get_load_addr()); | |
163 | #else | |
fa61ef6b KP |
164 | blk_count = image_size / mmc->block_dev.blksz; |
165 | if (image_size % mmc->block_dev.blksz) | |
166 | blk_count += 1; | |
167 | ||
168 | blk_written = mmc->block_dev.block_write(mmc_dev_num, | |
e559ef1a KP |
169 | start_lba, blk_count, |
170 | (void *)get_load_addr()); | |
171 | #endif /* CONFIG_BLK */ | |
fa61ef6b KP |
172 | if (blk_written != blk_count) { |
173 | printf("Error - written %#lx blocks\n", blk_written); | |
174 | return -ENOSPC; | |
175 | } | |
176 | printf("Done!\n"); | |
177 | ||
178 | #ifdef CONFIG_SYS_MMC_ENV_PART | |
179 | if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART) | |
180 | mmc_switch_part(mmc_dev_num, mmc->part_num); | |
181 | #endif | |
182 | ||
183 | return 0; | |
184 | } | |
185 | ||
186 | static size_t mmc_read_file(const char *file_name) | |
187 | { | |
188 | loff_t act_read = 0; | |
189 | int rc; | |
190 | struct mmc *mmc; | |
191 | const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV; | |
192 | ||
193 | mmc = find_mmc_device(mmc_dev_num); | |
194 | if (!mmc) { | |
195 | printf("No SD/MMC/eMMC card found\n"); | |
196 | return 0; | |
197 | } | |
198 | ||
199 | if (mmc_init(mmc)) { | |
200 | printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC", | |
201 | mmc_dev_num); | |
202 | return 0; | |
203 | } | |
204 | ||
205 | /* Load from data partition (0) */ | |
206 | if (fs_set_blk_dev("mmc", "0", FS_TYPE_ANY)) { | |
207 | printf("Error: MMC 0 not found\n"); | |
208 | return 0; | |
209 | } | |
210 | ||
211 | /* Perfrom file read */ | |
212 | rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read); | |
213 | if (rc) | |
214 | return 0; | |
215 | ||
216 | return act_read; | |
217 | } | |
218 | ||
219 | static int is_mmc_active(void) | |
220 | { | |
221 | return 1; | |
222 | } | |
223 | #else /* CONFIG_DM_MMC */ | |
224 | static int mmc_burn_image(size_t image_size) | |
225 | { | |
226 | return -ENODEV; | |
227 | } | |
228 | ||
229 | static size_t mmc_read_file(const char *file_name) | |
230 | { | |
231 | return 0; | |
232 | } | |
233 | ||
234 | static int is_mmc_active(void) | |
235 | { | |
236 | return 0; | |
237 | } | |
238 | #endif /* CONFIG_DM_MMC */ | |
239 | ||
240 | /******************************************************************** | |
241 | * SPI services | |
242 | ********************************************************************/ | |
243 | #ifdef CONFIG_SPI_FLASH | |
244 | static int spi_burn_image(size_t image_size) | |
245 | { | |
246 | int ret; | |
247 | struct spi_flash *flash; | |
248 | u32 erase_bytes; | |
249 | ||
250 | /* Probe the SPI bus to get the flash device */ | |
251 | flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, | |
252 | CONFIG_ENV_SPI_CS, | |
253 | CONFIG_SF_DEFAULT_SPEED, | |
254 | CONFIG_SF_DEFAULT_MODE); | |
255 | if (!flash) { | |
256 | printf("Failed to probe SPI Flash\n"); | |
257 | return -ENOMEDIUM; | |
258 | } | |
259 | ||
260 | #ifdef CONFIG_SPI_FLASH_PROTECTION | |
261 | spi_flash_protect(flash, 0); | |
262 | #endif | |
263 | erase_bytes = image_size + | |
264 | (flash->erase_size - image_size % flash->erase_size); | |
265 | printf("Erasing %d bytes (%d blocks) at offset 0 ...", | |
266 | erase_bytes, erase_bytes / flash->erase_size); | |
267 | ret = spi_flash_erase(flash, 0, erase_bytes); | |
268 | if (ret) | |
269 | printf("Error!\n"); | |
270 | else | |
271 | printf("Done!\n"); | |
272 | ||
273 | printf("Writing %d bytes from 0x%lx to offset 0 ...", | |
274 | (int)image_size, get_load_addr()); | |
275 | ret = spi_flash_write(flash, 0, image_size, (void *)get_load_addr()); | |
276 | if (ret) | |
277 | printf("Error!\n"); | |
278 | else | |
279 | printf("Done!\n"); | |
280 | ||
281 | #ifdef CONFIG_SPI_FLASH_PROTECTION | |
282 | spi_flash_protect(flash, 1); | |
283 | #endif | |
284 | ||
285 | return ret; | |
286 | } | |
287 | ||
288 | static int is_spi_active(void) | |
289 | { | |
290 | return 1; | |
291 | } | |
292 | ||
293 | #else /* CONFIG_SPI_FLASH */ | |
294 | static int spi_burn_image(size_t image_size) | |
295 | { | |
296 | return -ENODEV; | |
297 | } | |
298 | ||
299 | static int is_spi_active(void) | |
300 | { | |
301 | return 0; | |
302 | } | |
303 | #endif /* CONFIG_SPI_FLASH */ | |
304 | ||
305 | /******************************************************************** | |
306 | * NAND services | |
307 | ********************************************************************/ | |
308 | #ifdef CONFIG_CMD_NAND | |
309 | static int nand_burn_image(size_t image_size) | |
310 | { | |
f2ca24d9 KP |
311 | int ret; |
312 | uint32_t block_size; | |
7021c7e6 | 313 | struct mtd_info *mtd; |
fa61ef6b | 314 | |
7021c7e6 GS |
315 | mtd = get_nand_dev_by_index(nand_curr_device); |
316 | if (!mtd) { | |
fa61ef6b KP |
317 | puts("\nno devices available\n"); |
318 | return -ENOMEDIUM; | |
319 | } | |
7021c7e6 | 320 | block_size = mtd->erasesize; |
fa61ef6b KP |
321 | |
322 | /* Align U-Boot size to currently used blocksize */ | |
323 | image_size = ((image_size + (block_size - 1)) & (~(block_size - 1))); | |
324 | ||
325 | /* Erase the U-BOOT image space */ | |
326 | printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size); | |
7021c7e6 | 327 | ret = nand_erase(mtd, 0, image_size); |
fa61ef6b KP |
328 | if (ret) { |
329 | printf("Error!\n"); | |
330 | goto error; | |
331 | } | |
332 | printf("Done!\n"); | |
333 | ||
334 | /* Write the image to flash */ | |
f2ca24d9 KP |
335 | printf("Writing %d bytes from 0x%lx to offset 0 ... ", |
336 | (int)image_size, get_load_addr()); | |
7021c7e6 | 337 | ret = nand_write(mtd, 0, &image_size, (void *)get_load_addr()); |
fa61ef6b KP |
338 | if (ret) |
339 | printf("Error!\n"); | |
340 | else | |
341 | printf("Done!\n"); | |
342 | ||
343 | error: | |
344 | return ret; | |
345 | } | |
346 | ||
347 | static int is_nand_active(void) | |
348 | { | |
349 | return 1; | |
350 | } | |
351 | ||
352 | #else /* CONFIG_CMD_NAND */ | |
353 | static int nand_burn_image(size_t image_size) | |
354 | { | |
355 | return -ENODEV; | |
356 | } | |
357 | ||
358 | static int is_nand_active(void) | |
359 | { | |
360 | return 0; | |
361 | } | |
362 | #endif /* CONFIG_CMD_NAND */ | |
363 | ||
364 | /******************************************************************** | |
365 | * USB services | |
366 | ********************************************************************/ | |
367 | #if defined(CONFIG_USB_STORAGE) && defined(CONFIG_BLK) | |
368 | static size_t usb_read_file(const char *file_name) | |
369 | { | |
370 | loff_t act_read = 0; | |
371 | struct udevice *dev; | |
372 | int rc; | |
373 | ||
374 | usb_stop(); | |
375 | ||
376 | if (usb_init() < 0) { | |
377 | printf("Error: usb_init failed\n"); | |
378 | return 0; | |
379 | } | |
380 | ||
381 | /* Try to recognize storage devices immediately */ | |
382 | blk_first_device(IF_TYPE_USB, &dev); | |
383 | if (!dev) { | |
384 | printf("Error: USB storage device not found\n"); | |
385 | return 0; | |
386 | } | |
387 | ||
388 | /* Always load from usb 0 */ | |
389 | if (fs_set_blk_dev("usb", "0", FS_TYPE_ANY)) { | |
390 | printf("Error: USB 0 not found\n"); | |
391 | return 0; | |
392 | } | |
393 | ||
394 | /* Perfrom file read */ | |
395 | rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read); | |
396 | if (rc) | |
397 | return 0; | |
398 | ||
399 | return act_read; | |
400 | } | |
401 | ||
402 | static int is_usb_active(void) | |
403 | { | |
404 | return 1; | |
405 | } | |
406 | ||
407 | #else /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */ | |
408 | static size_t usb_read_file(const char *file_name) | |
409 | { | |
410 | return 0; | |
411 | } | |
412 | ||
413 | static int is_usb_active(void) | |
414 | { | |
415 | return 0; | |
416 | } | |
417 | #endif /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */ | |
418 | ||
419 | /******************************************************************** | |
420 | * Network services | |
421 | ********************************************************************/ | |
422 | #ifdef CONFIG_CMD_NET | |
423 | static size_t tftp_read_file(const char *file_name) | |
424 | { | |
425 | /* update global variable load_addr before tftp file from network */ | |
426 | load_addr = get_load_addr(); | |
427 | return net_loop(TFTPGET); | |
428 | } | |
429 | ||
430 | static int is_tftp_active(void) | |
431 | { | |
432 | return 1; | |
433 | } | |
434 | ||
435 | #else | |
436 | static size_t tftp_read_file(const char *file_name) | |
437 | { | |
438 | return 0; | |
439 | } | |
440 | ||
441 | static int is_tftp_active(void) | |
442 | { | |
443 | return 0; | |
444 | } | |
445 | #endif /* CONFIG_CMD_NET */ | |
446 | ||
447 | enum bubt_devices { | |
448 | BUBT_DEV_NET = 0, | |
449 | BUBT_DEV_USB, | |
450 | BUBT_DEV_MMC, | |
451 | BUBT_DEV_SPI, | |
452 | BUBT_DEV_NAND, | |
453 | ||
454 | BUBT_MAX_DEV | |
455 | }; | |
456 | ||
457 | struct bubt_dev bubt_devs[BUBT_MAX_DEV] = { | |
458 | {"tftp", tftp_read_file, NULL, is_tftp_active}, | |
459 | {"usb", usb_read_file, NULL, is_usb_active}, | |
460 | {"mmc", mmc_read_file, mmc_burn_image, is_mmc_active}, | |
461 | {"spi", NULL, spi_burn_image, is_spi_active}, | |
462 | {"nand", NULL, nand_burn_image, is_nand_active}, | |
463 | }; | |
464 | ||
465 | static int bubt_write_file(struct bubt_dev *dst, size_t image_size) | |
466 | { | |
467 | if (!dst->write) { | |
468 | printf("Error: Write not supported on device %s\n", dst->name); | |
469 | return -ENOTSUPP; | |
470 | } | |
471 | ||
472 | return dst->write(image_size); | |
473 | } | |
474 | ||
475 | #if defined(CONFIG_ARMADA_8K) | |
476 | u32 do_checksum32(u32 *start, int32_t len) | |
477 | { | |
478 | u32 sum = 0; | |
479 | u32 *startp = start; | |
480 | ||
481 | do { | |
482 | sum += *startp; | |
483 | startp++; | |
484 | len -= 4; | |
485 | } while (len > 0); | |
486 | ||
487 | return sum; | |
488 | } | |
489 | ||
490 | static int check_image_header(void) | |
491 | { | |
492 | struct mvebu_image_header *hdr = | |
493 | (struct mvebu_image_header *)get_load_addr(); | |
494 | u32 header_len = hdr->prolog_size; | |
495 | u32 checksum; | |
496 | u32 checksum_ref = hdr->prolog_checksum; | |
497 | ||
498 | /* | |
499 | * For now compare checksum, and magic. Later we can | |
500 | * verify more stuff on the header like interface type, etc | |
501 | */ | |
502 | if (hdr->magic != MAIN_HDR_MAGIC) { | |
503 | printf("ERROR: Bad MAGIC 0x%08x != 0x%08x\n", | |
504 | hdr->magic, MAIN_HDR_MAGIC); | |
505 | return -ENOEXEC; | |
506 | } | |
507 | ||
508 | /* The checksum value is discarded from checksum calculation */ | |
509 | hdr->prolog_checksum = 0; | |
510 | ||
511 | checksum = do_checksum32((u32 *)hdr, header_len); | |
512 | if (checksum != checksum_ref) { | |
513 | printf("Error: Bad Image checksum. 0x%x != 0x%x\n", | |
514 | checksum, checksum_ref); | |
515 | return -ENOEXEC; | |
516 | } | |
517 | ||
518 | /* Restore the checksum before writing */ | |
519 | hdr->prolog_checksum = checksum_ref; | |
520 | printf("Image checksum...OK!\n"); | |
521 | ||
522 | return 0; | |
523 | } | |
524 | #elif defined(CONFIG_ARMADA_3700) /* Armada 3700 */ | |
525 | static int check_image_header(void) | |
526 | { | |
527 | struct common_tim_data *hdr = (struct common_tim_data *)get_load_addr(); | |
528 | int image_num; | |
529 | u8 hash_160_output[SHA1_SUM_LEN]; | |
530 | u8 hash_256_output[SHA256_SUM_LEN]; | |
531 | sha1_context hash1_text; | |
532 | sha256_context hash256_text; | |
533 | u8 *hash_output; | |
534 | u32 hash_algorithm_id; | |
535 | u32 image_size_to_hash; | |
536 | u32 flash_entry_addr; | |
537 | u32 *hash_value; | |
538 | u32 internal_hash[HASH_SUM_LEN]; | |
539 | const u8 *buff; | |
540 | u32 num_of_image = hdr->num_images; | |
541 | u32 version = hdr->version; | |
542 | u32 trusted = hdr->trusted; | |
543 | ||
544 | /* bubt checksum validation only supports nontrusted images */ | |
545 | if (trusted == 1) { | |
546 | printf("bypass image validation, "); | |
547 | printf("only untrusted image is supported now\n"); | |
548 | return 0; | |
549 | } | |
550 | /* only supports image version 3.5 and 3.6 */ | |
551 | if (version != IMAGE_VERSION_3_5_0 && version != IMAGE_VERSION_3_6_0) { | |
552 | printf("Error: Unsupported Image version = 0x%08x\n", version); | |
553 | return -ENOEXEC; | |
554 | } | |
555 | /* validate images hash value */ | |
556 | for (image_num = 0; image_num < num_of_image; image_num++) { | |
557 | struct mvebu_image_info *info = | |
558 | (struct mvebu_image_info *)(get_load_addr() + | |
559 | sizeof(struct common_tim_data) + | |
560 | image_num * sizeof(struct mvebu_image_info)); | |
561 | hash_algorithm_id = info->hash_algorithm_id; | |
562 | image_size_to_hash = info->image_size_to_hash; | |
563 | flash_entry_addr = info->flash_entry_addr; | |
564 | hash_value = info->hash; | |
565 | buff = (const u8 *)(get_load_addr() + flash_entry_addr); | |
566 | ||
567 | if (image_num == 0) { | |
568 | /* | |
569 | * The first image includes hash values in its content. | |
570 | * For hash calculation, we need to save the original | |
571 | * hash values to a local variable that will be | |
572 | * copied back for comparsion and set all zeros to | |
573 | * the orignal hash values for calculating new value. | |
574 | * First image original format : | |
575 | * x...x (datum1) x...x(orig. hash values) x...x(datum2) | |
576 | * Replaced first image format : | |
577 | * x...x (datum1) 0...0(hash values) x...x(datum2) | |
578 | */ | |
579 | memcpy(internal_hash, hash_value, | |
580 | sizeof(internal_hash)); | |
581 | memset(hash_value, 0, sizeof(internal_hash)); | |
582 | } | |
583 | if (image_size_to_hash == 0) { | |
584 | printf("Warning: Image_%d hash checksum is disabled, ", | |
585 | image_num); | |
586 | printf("skip the image validation.\n"); | |
587 | continue; | |
588 | } | |
589 | switch (hash_algorithm_id) { | |
590 | case SHA1_SUM_LEN: | |
591 | sha1_starts(&hash1_text); | |
592 | sha1_update(&hash1_text, buff, image_size_to_hash); | |
593 | sha1_finish(&hash1_text, hash_160_output); | |
594 | hash_output = hash_160_output; | |
595 | break; | |
596 | case SHA256_SUM_LEN: | |
597 | sha256_starts(&hash256_text); | |
598 | sha256_update(&hash256_text, buff, image_size_to_hash); | |
599 | sha256_finish(&hash256_text, hash_256_output); | |
600 | hash_output = hash_256_output; | |
601 | break; | |
602 | default: | |
603 | printf("Error: Unsupported hash_algorithm_id = %d\n", | |
604 | hash_algorithm_id); | |
605 | return -ENOEXEC; | |
606 | } | |
607 | if (image_num == 0) | |
608 | memcpy(hash_value, internal_hash, | |
609 | sizeof(internal_hash)); | |
610 | if (memcmp(hash_value, hash_output, hash_algorithm_id) != 0) { | |
611 | printf("Error: Image_%d checksum is not correct\n", | |
612 | image_num); | |
613 | return -ENOEXEC; | |
614 | } | |
615 | } | |
616 | printf("Image checksum...OK!\n"); | |
617 | ||
618 | return 0; | |
619 | } | |
620 | ||
621 | #else /* Not ARMADA? */ | |
622 | static int check_image_header(void) | |
623 | { | |
624 | printf("bubt cmd does not support this SoC device or family!\n"); | |
625 | return -ENOEXEC; | |
626 | } | |
627 | #endif | |
628 | ||
629 | static int bubt_verify(size_t image_size) | |
630 | { | |
631 | int err; | |
632 | ||
633 | /* Check a correct image header exists */ | |
634 | err = check_image_header(); | |
635 | if (err) { | |
636 | printf("Error: Image header verification failed\n"); | |
637 | return err; | |
638 | } | |
639 | ||
640 | return 0; | |
641 | } | |
642 | ||
643 | static int bubt_read_file(struct bubt_dev *src) | |
644 | { | |
645 | size_t image_size; | |
646 | ||
647 | if (!src->read) { | |
648 | printf("Error: Read not supported on device \"%s\"\n", | |
649 | src->name); | |
650 | return 0; | |
651 | } | |
652 | ||
653 | image_size = src->read(net_boot_file_name); | |
654 | if (image_size <= 0) { | |
655 | printf("Error: Failed to read file %s from %s\n", | |
656 | net_boot_file_name, src->name); | |
657 | return 0; | |
658 | } | |
659 | ||
660 | return image_size; | |
661 | } | |
662 | ||
663 | static int bubt_is_dev_active(struct bubt_dev *dev) | |
664 | { | |
665 | if (!dev->active) { | |
666 | printf("Device \"%s\" not supported by U-BOOT image\n", | |
667 | dev->name); | |
668 | return 0; | |
669 | } | |
670 | ||
671 | if (!dev->active()) { | |
672 | printf("Device \"%s\" is inactive\n", dev->name); | |
673 | return 0; | |
674 | } | |
675 | ||
676 | return 1; | |
677 | } | |
678 | ||
679 | struct bubt_dev *find_bubt_dev(char *dev_name) | |
680 | { | |
681 | int dev; | |
682 | ||
683 | for (dev = 0; dev < BUBT_MAX_DEV; dev++) { | |
684 | if (strcmp(bubt_devs[dev].name, dev_name) == 0) | |
685 | return &bubt_devs[dev]; | |
686 | } | |
687 | ||
688 | return 0; | |
689 | } | |
690 | ||
691 | #define DEFAULT_BUBT_SRC "tftp" | |
692 | ||
693 | #ifndef DEFAULT_BUBT_DST | |
694 | #ifdef CONFIG_MVEBU_SPI_BOOT | |
695 | #define DEFAULT_BUBT_DST "spi" | |
696 | #elif defined(CONFIG_MVEBU_NAND_BOOT) | |
697 | #define DEFAULT_BUBT_DST "nand" | |
698 | #elif defined(CONFIG_MVEBU_MMC_BOOT) | |
699 | #define DEFAULT_BUBT_DST "mmc" | |
700 | else | |
701 | #define DEFAULT_BUBT_DST "error" | |
702 | #endif | |
703 | #endif /* DEFAULT_BUBT_DST */ | |
704 | ||
705 | int do_bubt_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
706 | { | |
707 | struct bubt_dev *src, *dst; | |
708 | size_t image_size; | |
709 | char src_dev_name[8]; | |
710 | char dst_dev_name[8]; | |
711 | char *name; | |
712 | int err; | |
713 | ||
714 | if (argc < 2) | |
715 | copy_filename(net_boot_file_name, | |
716 | CONFIG_MVEBU_UBOOT_DFLT_NAME, | |
717 | sizeof(net_boot_file_name)); | |
718 | else | |
719 | copy_filename(net_boot_file_name, argv[1], | |
720 | sizeof(net_boot_file_name)); | |
721 | ||
722 | if (argc >= 3) { | |
723 | strncpy(dst_dev_name, argv[2], 8); | |
724 | } else { | |
725 | name = DEFAULT_BUBT_DST; | |
726 | strncpy(dst_dev_name, name, 8); | |
727 | } | |
728 | ||
729 | if (argc >= 4) | |
730 | strncpy(src_dev_name, argv[3], 8); | |
731 | else | |
732 | strncpy(src_dev_name, DEFAULT_BUBT_SRC, 8); | |
733 | ||
734 | /* Figure out the destination device */ | |
735 | dst = find_bubt_dev(dst_dev_name); | |
736 | if (!dst) { | |
737 | printf("Error: Unknown destination \"%s\"\n", dst_dev_name); | |
738 | return -EINVAL; | |
739 | } | |
740 | ||
741 | if (!bubt_is_dev_active(dst)) | |
742 | return -ENODEV; | |
743 | ||
744 | /* Figure out the source device */ | |
745 | src = find_bubt_dev(src_dev_name); | |
746 | if (!src) { | |
747 | printf("Error: Unknown source \"%s\"\n", src_dev_name); | |
748 | return 1; | |
749 | } | |
750 | ||
751 | if (!bubt_is_dev_active(src)) | |
752 | return -ENODEV; | |
753 | ||
754 | printf("Burning U-BOOT image \"%s\" from \"%s\" to \"%s\"\n", | |
755 | net_boot_file_name, src->name, dst->name); | |
756 | ||
757 | image_size = bubt_read_file(src); | |
758 | if (!image_size) | |
759 | return -EIO; | |
760 | ||
761 | err = bubt_verify(image_size); | |
762 | if (err) | |
763 | return err; | |
764 | ||
765 | err = bubt_write_file(dst, image_size); | |
766 | if (err) | |
767 | return err; | |
768 | ||
769 | return 0; | |
770 | } | |
771 | ||
772 | U_BOOT_CMD( | |
773 | bubt, 4, 0, do_bubt_cmd, | |
774 | "Burn a u-boot image to flash", | |
775 | "[file-name] [destination [source]]\n" | |
776 | "\t-file-name The image file name to burn. Default = flash-image.bin\n" | |
777 | "\t-destination Flash to burn to [spi, nand, mmc]. Default = active boot device\n" | |
778 | "\t-source The source to load image from [tftp, usb, mmc]. Default = tftp\n" | |
779 | "Examples:\n" | |
780 | "\tbubt - Burn flash-image.bin from tftp to active boot device\n" | |
781 | "\tbubt flash-image-new.bin nand - Burn flash-image-new.bin from tftp to NAND flash\n" | |
782 | "\tbubt backup-flash-image.bin mmc usb - Burn backup-flash-image.bin from usb to MMC\n" | |
783 | ||
784 | ); |