Add Broadcom / Netgear changes from RAXE 1.0.0.48
[project/bcm63xx/u-boot.git] / board / broadcom / bcmbca / sdk_test_commands.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2019
4 * Broadcom Corp
5 */
6
7 #include <stdlib.h>
8 #include <command.h>
9 #include <common.h>
10 #include <environment.h>
11 #include <hexdump.h>
12 #include <ubi_uboot.h>
13 #include <cli.h>
14 #include <console.h>
15 #include "bca_common.h"
16 #include "bcm_bootstate.h"
17 #include "spl_env.h"
18 #include "bca_sdk.h"
19 #include "bcm_secure.h"
20 #include "httpd/bcmbca_net.h"
21 #include <nand.h>
22 #include <mmc.h>
23 #if defined(CONFIG_WDT)
24 #include <wdt.h>
25 #endif
26 #if defined(CONFIG_BCMBCA_PMC)
27 #include "pmc_drv.h"
28 #endif
29
30 #define SIZE_OVERHEAD 0x100000UL //1M
31 #define BOOTFS_SIZE_BYTES 0x00A00000UL //10M
32 #define ROOTFS_SIZE_BYTES 0x02800000UL //40M
33 #define SQUASHFS_MAGIC 0x73717368
34 #define UBIFS_MAGIC 0x06101831
35 #define MIN_IMG_INDEX 1
36 #define MAX_IMG_INDEX 2
37
38 #define atoi(s) simple_strtol(s, NULL, 0)
39
40 DECLARE_GLOBAL_DATA_PTR;
41
42 /* Flag indicating whether we want to force an update and disregard any compatibility checks */
43 static int forced_updates = 0;
44 static char forced_image_media[256] = {0};
45 static char forced_boot_media[256] = {0};
46 /* Flag to prevent synching of runtime env to loader bin when flashing a new loader */
47 static int disable_runtime_env_sync = 0;
48
49 typedef int (*flash_fn)( ulong addr, ulong size , int img_index);
50
51 typedef struct {
52 char name[20]; /* Name of upgrade bundle component */
53 flash_fn func; /* Function to flash this upgrade bundle component */
54 } flashfn_table_entry;
55
56 /* Enable CLI commands based on included CMD modules */
57 #if defined(CONFIG_CMD_GPT) && defined(CONFIG_CMD_PART) && defined(CONFIG_CMD_MMC) && defined(CONFIG_MMC)
58 #define BCA_SDK_EMMC_CMD 1
59 #endif
60
61 #if defined(CONFIG_CMD_UBI) && defined(CONFIG_CMD_MTD) && defined(CONFIG_NAND)
62 #define BCA_SDK_NAND_CMD 1
63 #endif
64
65 #if defined(CONFIG_CMD_SF) && defined(CONFIG_SPI_FLASH) && defined(CONFIG_DM_SPI_FLASH) && defined(CONFIG_CMD_MTD)
66 #define BCA_SDK_SPINOR_CMD 1
67 #endif
68
69 #if defined(BCA_SDK_SPINOR_CMD)
70 static int spinor_load_bootfs(uint32_t bootfs_load_addr );
71 static int spinor_restoredefault(void);
72 static int write_spinor_partition( char *const partitionname, ulong addr, ulong size );
73 static int do_flash_spinor_binary(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
74 static int do_flash_spinor_bootfs_rootfs(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
75 static int flash_loader_spinor( ulong addr, ulong size);
76 #endif
77 #ifdef BCA_SDK_EMMC_CMD
78 /* EMMC specific routines */
79 static int flash_rootfs_emmc( ulong addr, ulong size, int img_index );
80 static int flash_bootfs_emmc( ulong addr, ulong size, int img_index );
81 static int flash_loader_emmc( ulong addr, ulong size, int img_index );
82 static int set_emmc_metadata( char* metadata, int size );
83 static int get_emmc_metadata( char* metadata, int size );
84 static int emmc_load_bootfs( int img_index, uint32_t bootfs_load_addr );
85 static int emmc_rdwr_userdata_part( char * part_name, ulong addr, ulong size, int write );
86 static int emmc_rdwr_boot_part( ulong addr, ulong size, int img_index, int write );
87 static int emmc_restoredefault(void);
88 static int emmc_do_gpt_fixup(void);
89 #endif /* BCA_SDK_EMMC_CMD */
90
91 #ifdef BCA_SDK_NAND_CMD
92 /* NAND Specific routines */
93 static int flash_rootfs_nand( ulong addr, ulong size, int img_index );
94 static int flash_bootfs_nand( ulong addr, ulong size, int img_index );
95 static int flash_loader_nand( ulong addr, ulong size, int img_index );
96 static int set_nand_metadata( char* metadata, int size );
97 static int get_nand_metadata( char* metadata, int size );
98 static int nand_load_fit( int img_index, uint32_t fit_load_addr );
99 static int nand_load_bootfs( int img_index, uint32_t bootfs_load_addr );
100 static int nand_restoredefault(void);
101 #endif /* BCA_SDK_NAND_CMD */
102
103 /* Generic routines */
104 static unsigned int bcm_handle_mapper(void* fit, char *flash_device, char *flash_opts);
105 static int update_flash_parts_from_loader_bin( ulong loader_addr, ulong loader_size );
106 static int get_binary_from_bundle( ulong bundle_addr, char * conf_name, char * name,
107 char ** bin_name, ulong * addr, ulong * size );
108 static int sync_update_loader_bin_env(ulong loader_addr);
109 static int verify_compat_string( const char * compat_str );
110 static int do_flash_bins(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
111 static int do_boot(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
112 static int do_load(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
113 static int load_linux_img(int flag, int argc, char *const argv[]);
114 static int do_restoredefault(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
115 static int do_metadata(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
116 static int do_force(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
117 static int flash_rootfs( ulong addr, ulong size , int img_index);
118 static int flash_bootfs( ulong addr, ulong size , int img_index);
119 static int flash_loader( ulong addr, ulong size , int img_index);
120 static int do_flash_loader(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
121 static int do_flash_bootfs_rootfs( char * bootfs_filename, char * rootfs_filename, int image_index );
122 static int do_flash_upgrade_img (cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
123 static int set_metadata_val( int * committed, int * valid, int * seq );
124 static int get_metadata_val( int * committed, int * valid, int * seq );
125 static int do_activate(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
126 char * get_loader_media(void);
127 static char * get_image_media(void);
128 static int get_active_img_idx(void);
129 static int set_active_img_idx( int img_idx);
130 #ifdef CONFIG_BCMBCA_HTTPD
131 static int do_httpd_start(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
132 #endif
133 #ifdef CONFIG_BCMBCA_XRDP_ETH
134 static int do_eth_active_port(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[]);
135 #endif
136
137 /* Local Variables */
138 static flashfn_table_entry fn_table[] = {
139 { "bootfs", flash_bootfs },
140 { "rootfs", flash_rootfs },
141 { "loader", flash_loader }
142 };
143
144 #ifdef CONFIG_BCMBCA_BOARD_SPECIFIC_DT
145 #define BCMBCA_BOARDID_MAXSIZE 28
146 #define BCMBCA_VOICEBOARDID_MAXSIZE BCMBCA_BOARDID_MAXSIZE
147 #include "spl_ddrinit.h"
148 static int on_boardid(const char *name, const char *value, enum env_op op, int flags)
149 {
150 char boardid[BCMBCA_BOARDID_MAXSIZE+4];
151 int ret = 0;
152 int img_index = 0;
153 long conf, node, offset;
154 uint32_t env_mcb;
155
156 if (forced_updates || ((flags & H_INTERACTIVE) == 0))
157 return 0;
158
159 switch (op) {
160 case env_op_create:
161 case env_op_overwrite:
162 img_index = get_active_img_idx();
163 if((img_index < MIN_IMG_INDEX) || (img_index > MAX_IMG_INDEX))
164 img_index = MIN_IMG_INDEX;
165 /* Load bootfs to load address */
166 if( strcasecmp(get_image_media(), FLASH_DEV_STR_NAND) == 0 ) {
167 #ifdef BCA_SDK_NAND_CMD
168 if (nand_load_fit(img_index, load_addr))
169 {
170 printf("Failed to load bootfs\n");
171 return 0;
172 }
173 #endif
174 }
175
176 if( ( strcasecmp(get_image_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
177 #ifdef BCA_SDK_EMMC_CMD
178 ret = emmc_load_bootfs(img_index, load_addr);
179 if (ret)
180 {
181 printf("Failed to load bootfs\n");
182 return 0;
183 }
184 #endif
185 }
186
187 conf = fdt_path_offset((void*)load_addr, FIT_IMAGES_PATH);
188 if (conf < 0) {
189 printf("Cannot find /images node: %ld\n", conf);
190 return 0;
191 }
192
193 if (strlen(value) > BCMBCA_BOARDID_MAXSIZE)
194 {
195 printf("boardid is too long, max size is %d\n", BCMBCA_BOARDID_MAXSIZE);
196 return 1;
197 }
198 sprintf(boardid,"fdt_%s", value);
199 for (node = fdt_first_subnode((const void*)load_addr, conf); node >= 0; node = fdt_next_subnode((const void*)load_addr, node))
200 {
201 const char* image_name = fit_get_name((const char*)load_addr, node, NULL);
202
203 if (strcmp(image_name, boardid) == 0)
204 {
205 const uint32_t* memcfg;
206 uint32_t fdt_mcb;
207 const void* fdt;
208 size_t size;
209
210 ret = fit_image_get_data_and_size((const void*)load_addr, node, &fdt, &size);
211 if (ret)
212 {
213 printf("Failed to get FDT\n");
214 return 0;
215 }
216
217 offset = fdt_path_offset(fdt, "/memory_controller");
218 if (offset < 0) {
219 printf("Not found memory_controller node in FDT\n");
220 return 0;
221 }
222
223 memcfg = fdt_getprop(fdt, offset, "memcfg", NULL);
224 if (memcfg == NULL)
225 {
226 printf("Can't find memcfg parameter in DTB\n");
227 return 0;
228 }
229 fdt_mcb = be32_to_cpu(*memcfg);
230 env_mcb = env_get_hex("MCB", 0);
231 if (env_mcb & BP_DDR_CONFIG_OVERRIDE)
232 {
233 printf("MCB sticky bit is set, MCB is not updated\n Current MCB 0x%x, FDT MCB 0x%x\n", env_mcb, fdt_mcb);
234 return 0;
235 }
236 printf("Updating MCB environment from 0x%x to 0x%x\n", env_mcb, fdt_mcb);
237 env_set_hex("MCB", fdt_mcb);
238 env_set("boardid", value);
239 printf("Memory Configuration Changed -- SAVING ENV AND REBOOT NEEDED\n");
240 return 0;
241 }
242 }
243 printf("Error: boardid %s not supported.\nList of supported boards:\n", value);
244 for (node = fdt_first_subnode((const void*)load_addr, conf); node >= 0; node = fdt_next_subnode((const void*)load_addr, node))
245 {
246 char* name = fit_get_name((const char*)load_addr, node, NULL);
247 if ((strncmp("fdt_", name, 4) == 0) && (strcmp("fdt_uboot", name)))
248 printf("%s\n", (name+4));
249 }
250 return 1;
251 case env_op_delete:
252 if (flags & H_FORCE)
253 return 0;
254
255 printf("## boardid may not be deleted\n");
256 return 1;
257 default:
258 return 0;
259 }
260 }
261 U_BOOT_ENV_CALLBACK(boardid, on_boardid);
262
263 static int on_voiceBoardid(const char *name, const char *value, enum env_op op, int flags)
264 {
265 char boardid[BCMBCA_BOARDID_MAXSIZE+4];
266 int ret = 0;
267 int img_index = 0;
268 long conf, node, offset;
269 char *pboardid;
270
271 if (forced_updates || ((flags & H_INTERACTIVE) == 0))
272 return 0;
273
274 pboardid = env_get("boardid");
275 if (!pboardid)
276 {
277 printf("boardId must be set first.\n");
278 return 1;
279 }
280
281 switch (op) {
282 case env_op_create:
283 case env_op_overwrite:
284 img_index = get_active_img_idx();
285 if((img_index < MIN_IMG_INDEX) || (img_index > MAX_IMG_INDEX))
286 img_index = MIN_IMG_INDEX;
287 /* Load bootfs to load address */
288 if( strcasecmp(get_image_media(), FLASH_DEV_STR_NAND) == 0 ) {
289 #ifdef BCA_SDK_NAND_CMD
290 if (nand_load_fit(img_index, load_addr))
291 {
292 printf("Failed to load bootfs\n");
293 return 0;
294 }
295 #endif
296 }
297
298 if( ( strcasecmp(get_image_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
299 #ifdef BCA_SDK_EMMC_CMD
300 ret = emmc_load_bootfs(img_index, load_addr);
301 if (ret)
302 {
303 printf("Failed to load bootfs\n");
304 return 0;
305 }
306 #endif
307 }
308
309 conf = fdt_path_offset((void*)load_addr, FIT_IMAGES_PATH);
310 if (conf < 0) {
311 printf("Cannot find /images node: %ld\n", conf);
312 return 0;
313 }
314
315 if (strlen(value) > BCMBCA_VOICEBOARDID_MAXSIZE)
316 {
317 printf("voiceboardid is too long, max size is %d\n", BCMBCA_VOICEBOARDID_MAXSIZE);
318 return 1;
319 }
320 sprintf(boardid,"fdt_%s", pboardid);
321 for (node = fdt_first_subnode((const void*)load_addr, conf); node >= 0; node = fdt_next_subnode((const void*)load_addr, node))
322 {
323 const char* image_name = fit_get_name((const char*)load_addr, node, NULL);
324
325 if (strcmp(image_name, boardid) == 0)
326 {
327 size_t size;
328 const void* fdt;
329 int i, len, idx, slicCount;
330 const char *sliclist;
331
332 ret = fit_image_get_data_and_size((const void*)load_addr, node, &fdt, &size);
333 if (ret)
334 {
335 printf("Failed to get FDT\n");
336 return 0;
337 }
338
339 offset = fdt_path_offset(fdt, "/bcm_voice");
340 if (offset < 0) {
341 printf("Not found voice node in FDT\n");
342 return 0;
343 }
344 idx = fdt_stringlist_search(fdt, offset, "sliclist", value);
345 /* is the string is found, save it and exit */
346 if (0 <= idx)
347 {
348 env_set("voiceboardid", value);
349 printf("-- saving env and reboot needeD\n");
350 return 0;
351 }
352 printf("%d: %s is not found. idx=%d\n", __LINE__, value, idx);
353 slicCount = fdt_stringlist_count(fdt, offset, "sliclist");
354 printf("slicCount=%d. List of supported daughter cards:\n", slicCount);
355 for (i=0; i < slicCount; i++)
356 {
357 sliclist = fdt_stringlist_get(fdt, offset, "sliclist", i, &len);
358 if (sliclist)
359 printf("%s\n", sliclist);
360 else
361 printf("%d: fdt_stringlist_get failed. len=%d\n", __LINE__, len);
362 }
363 return 1;
364 }
365 }
366 return 1;
367 case env_op_delete:
368 env_set("voiceboardid", "");
369 printf("-- Saving env and reboot needed\n");
370 return 0;
371 default:
372 return 0;
373 }
374 }
375 U_BOOT_ENV_CALLBACK( voiceboardid, on_voiceBoardid);
376 #endif
377
378 static int get_active_img_idx( void )
379 {
380 int node,len;
381 unsigned int active_img_idx = 0;
382 fdt32_t * nodep = NULL;
383 node = fdt_path_offset(gd->fdt_blob, "/chosen");
384 if (node < 0) {
385 printf("Can't find /chosen node in uboot DTB\n");
386 return node;
387 }
388 nodep = (fdt32_t *)fdt_getprop(gd->fdt_blob, node, "active_image", &len);
389 active_img_idx = fdt32_to_cpu(*(fdt32_t *)nodep);
390
391 return active_img_idx;
392 }
393
394 static int set_active_img_idx( int img_idx )
395 {
396 int node,len;
397 fdt32_t * nodep = NULL;
398 node = fdt_path_offset(gd->fdt_blob, "/chosen");
399 int ret = -1;
400 if (node < 0) {
401 printf("Can't find /chosen node in uboot DTB, device may not boot properly!\n");
402 } else {
403 ret = fdt_setprop_u32(gd->fdt_blob, node, "active_image", img_idx);
404 if(ret)
405 {
406 printf("Could not set active image node in the fdt, device may not boot properly!\n");
407 }
408 }
409 return ret;
410 }
411
412 /************************************************************
413 * Flash Specific Functions *
414 ************************************************************/
415 #ifdef BCA_SDK_EMMC_CMD
416 static int emmc_restoredefault(void)
417 {
418 ulong part_size_blk, part_start_blk;
419 char cmd[128];
420 int ret = -1;
421
422 /* Switch to user data partition */
423 if ( run_command("mmc dev 0 0", 0) == 0 ) {
424 env_set("part_start_blk", NULL);
425 env_set("part_size_blk", NULL);
426 run_command("part start mmc 0 data part_start_blk", 0);
427 run_command("part size mmc 0 data part_size_blk", 0);
428 part_start_blk = env_get_hex("part_start_blk", 0);
429 part_size_blk = env_get_hex("part_size_blk", 0);
430
431 /* If data exists, delete it */
432 if( part_size_blk ) {
433 sprintf(cmd, "mmc erase 0x%lx 0x%lx", part_start_blk, part_size_blk);
434 ret = run_command(cmd, 0);
435 } else {
436 ret = 0;
437 }
438 } else {
439 printf("Error: Cannot switch to userdata partition!\n");
440 }
441
442 return ret;
443 }
444
445 static int emmc_rdwr_boot_part( ulong addr, ulong size, int img_index, int write )
446 {
447 char cmd[128];
448 ulong num_blocks = 0;
449 ulong block_addr = 0;
450 ulong part_size_blk = 0;
451 int boot_part_num = 1;
452 int ret = -1;
453 struct mmc *mmc = NULL;
454
455 mmc = find_mmc_device(0);
456 if( !mmc ) {
457 printf("Error: Cannot access mmc device!\n");
458 goto emmc_rdwr_boot_part_exit;
459 }
460
461 /* Calculate number of blocks */
462 num_blocks = size/mmc->read_bl_len + (size%mmc->read_bl_len?1:0);
463
464 /* Determine size of raw boot partition */
465 part_size_blk = mmc->capacity_boot/mmc->read_bl_len;
466 if( num_blocks > part_size_blk ) {
467 printf("Error: Insufficient space in boot partition %d for 0x%lx blocks. Partition size is 0x%lx\n", boot_part_num, num_blocks, part_size_blk);
468 goto emmc_rdwr_boot_part_exit;
469 }
470
471 /* Switch to boot partition */
472 sprintf(cmd, "mmc dev 0 %d", boot_part_num);
473 if ( run_command(cmd, 0) ) {
474 printf("Error: Cannot switch to bootpartition %d!\n", boot_part_num);
475 goto emmc_rdwr_boot_part_exit;
476 }
477
478 /* Write to raw boot partition */
479 sprintf(cmd, "mmc %s 0x%lx 0x%lx 0x%lx", (write?"write":"read"), addr, block_addr, num_blocks);
480 ret = run_command(cmd, 0);
481 printf("%s: %s (bootp%d)\n", __FUNCTION__, cmd, boot_part_num);
482
483 /* Switch back to userdata partition */
484 run_command("mmc dev 0 0", 0);
485
486 emmc_rdwr_boot_part_exit:
487 if( ret )
488 printf("Error: Failed %s 0x%lx blocks from/to boot partition %d!\n", (write?"writing":"reading"), num_blocks, boot_part_num);
489
490 return ret;
491 }
492
493 static int emmc_rdwr_userdata_part( char * part_name, ulong addr, ulong size, int write )
494 {
495 char cmd[128];
496 ulong num_blocks = 0;
497 ulong block_addr = 0;
498 ulong part_size_blk = 0;
499 int ret = -1;
500 struct mmc *mmc = NULL;
501
502 mmc = find_mmc_device(0);
503 if( !mmc ) {
504 printf("Error: Cannot access mmc device!\n");
505 goto emmc_rdwr_usrdata_part_exit;
506 }
507
508 /* Calculate number of blocks */
509 num_blocks = size/mmc->read_bl_len + (size%mmc->read_bl_len?1:0);
510
511 /* Switch to user data partition */
512 if ( run_command("mmc dev 0 0", 0) ) {
513 printf("Error: Cannot switch to userdata partition!\n");
514 goto emmc_rdwr_usrdata_part_exit;
515 }
516
517 /* Get GPT partition size in blocks */
518 env_set("part_size_blk", NULL);
519 sprintf(cmd, "part size mmc 0 %s part_size_blk", part_name);
520 if(run_command(cmd, 0) == 0) {
521 part_size_blk = env_get_hex("part_size_blk", 0);
522 if( num_blocks > part_size_blk ) {
523 printf("Error: Insufficient space in partition %s for 0x%lx blocks. Partition size is 0x%lx\n", part_name, num_blocks, part_size_blk);
524 goto emmc_rdwr_usrdata_part_exit;
525 }
526 } else {
527 printf("Error: Cannot determine size of GPT partition %s\n", part_name);
528 goto emmc_rdwr_usrdata_part_exit;
529 }
530
531 /* Get start block address of partition */
532 sprintf(cmd, "part start mmc 0 %s part_start_blk", part_name);
533 env_set("part_start_blk", NULL);
534 if(run_command(cmd, 0) == 0) {
535 block_addr = env_get_hex("part_start_blk", 0);
536 sprintf(cmd, "mmc %s 0x%lx 0x%lx 0x%lx", (write?"write":"read"), addr, block_addr, num_blocks);
537 ret = run_command(cmd, 0);
538 printf("%s: %s (%s)\n", __FUNCTION__, cmd, part_name);
539 } else {
540 printf("Error: Cannot determine start block of GPT partition %s\n", part_name);
541 goto emmc_rdwr_usrdata_part_exit;
542 }
543
544 emmc_rdwr_usrdata_part_exit:
545 if( ret )
546 printf("Error: Failed %s 0x%lx blocks from/to GPT partition %s!\n", (write?"writing":"reading"), num_blocks, part_name);
547 return ret;
548 }
549
550 static int flash_rootfs_emmc( ulong addr, ulong size, int img_index )
551 {
552 char part_name[128];
553 int ret = CMD_RET_FAILURE;
554
555 if( !addr || !size || img_index < MIN_IMG_INDEX || img_index > MAX_IMG_INDEX )
556 return CMD_RET_USAGE;
557
558 sprintf(part_name, "rootfs%d", img_index);
559 ret = emmc_rdwr_userdata_part( part_name, (ulong)addr, size, 1 );
560
561 return ret;
562 }
563
564 static int flash_bootfs_emmc( ulong addr, ulong size, int img_index )
565 {
566 char part_name[128];
567 int ret = CMD_RET_FAILURE;
568
569 if( !addr || !size || img_index < MIN_IMG_INDEX || img_index > MAX_IMG_INDEX )
570 return CMD_RET_USAGE;
571
572 sprintf(part_name, "bootfs%d", img_index);
573 ret = emmc_rdwr_userdata_part( part_name, (ulong)addr, size, 1 );
574 return ret;
575 }
576
577 static int flash_loader_emmc( ulong addr, ulong size, int img_index )
578 {
579 int ret = -1;
580
581 if( !addr || !size )
582 return CMD_RET_USAGE;
583
584 ret = emmc_rdwr_boot_part( addr, size, img_index, 1);
585
586 return ret;
587 }
588
589 static int set_emmc_metadata( char* metadata, int size )
590 {
591 char part_name[128];
592 int ret;
593 int i;
594
595 for (i = 1; i < 3; i++) {
596 sprintf(part_name, "metadata%d", i);
597 ret = emmc_rdwr_userdata_part( part_name, (ulong)metadata, size, 1 );
598 }
599 return ret;
600 }
601
602 static int get_emmc_metadata( char* metadata, int size )
603 {
604 int ret;
605 int committed = 0;
606 int valid[2] = {0,0};
607 int seq[2] = {-1,-1};
608 int i;
609 char part_name[128];
610
611 for (i = 1; i < 3; i++) {
612 sprintf(part_name, "metadata%d", i);
613 ret = emmc_rdwr_userdata_part( part_name, (ulong)metadata, size, 0 );
614 if (0 == validate_metadata(metadata, valid, &committed, seq)) {
615 break;
616 } else {
617 printf("metadata parse error\n");
618 ret = CMD_RET_FAILURE;
619 }
620 }
621 return ret;
622 }
623
624 static ulong emmc_get_bootfs_size( char * fit )
625 {
626 int images_noffset;
627 int noffset;
628 int ndepth;
629 int count;
630 size_t size;
631 ulong bootfs_size = 0;
632 const void *data;
633
634 /* Find images parent node offset */
635 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
636 if (images_noffset < 0) {
637 printf("Can't find images parent node '%s' (%s)\n",
638 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
639 return 0;
640 }
641
642 /* Process all image subnodes */
643 for (ndepth = 0, count = 0,
644 noffset = fdt_next_node(fit, images_noffset, &ndepth);
645 (noffset >= 0) && (ndepth > 0);
646 noffset = fdt_next_node(fit, noffset, &ndepth)) {
647 if (ndepth == 1) {
648 /*
649 * Direct child node of the images parent node,
650 * i.e. component image node.
651 */
652 count++;
653
654 if (fit_image_get_data_and_size(fit, noffset, &data, &size) == 0) {
655 bootfs_size = ((ulong)data+(ulong)size) - (ulong)fit;
656 }
657 }
658 }
659 printf("Bootfs size is %lu bytes\n", bootfs_size);
660 return bootfs_size;
661 }
662
663 static int emmc_add_gpt_part( char * name, ulong size )
664 {
665 char * current_parts = NULL;
666 char * new_parts = NULL;
667 int ret = -1;
668
669 /* Read partitions into variable */
670 env_set("current_parts", NULL);
671 run_command("gpt read mmc 0 current_parts", 0);
672 current_parts = env_get("current_parts");
673
674 if( strstr(current_parts, name) ) {
675 printf("%s: GPT partition:%s of size:%luMiB exists!\n", __FUNCTION__, name, size);
676 return 0;
677 } else {
678 printf("%s: Adding GPT partition %s of size %luMiB\n", __FUNCTION__, name, size);
679 }
680
681 /* Update partitions */
682 new_parts = malloc(strlen(current_parts) + 1024 );
683 if( new_parts ) {
684 sprintf(new_parts, "%sname=%s,size=%luMiB;", current_parts, name, size);
685 ret = env_set("current_parts", new_parts);
686 free(new_parts);
687 ret = run_command("gpt write mmc 0 $current_parts", 0);
688 ret = run_command("gpt verify mmc 0 $current_parts", 0);
689 } else {
690 printf("%s: Error allocating memory for partition string!\n", __FUNCTION__);
691 }
692
693 //env_set("current_parts", NULL);
694 return ret;
695
696 }
697
698 /* This function will create GPT partitions if it detects partition sizes specfied via
699 * uboot environment variables. The env variable name has to be in the format:
700 * <partition_name>_vol_size=<size in MiB>
701 * The function will then create GPT partition with name <partition_name> of size <size>
702 *
703 * NOTE: For NAND, equivalent ubi volumes are also created dynamically based on the same
704 * uboot env variables. However, for NAND the volumes are created in the mount-fs.sh linux
705 * startup script instead of in uboot proper.
706 */
707 #define VOL_SIZE_STR "_vol_size="
708 static int emmc_do_gpt_fixup(void)
709 {
710 env_t *ep;
711 char *envbuf = NULL;
712 int ret = -2;
713 int elen;
714 char *config;
715 char * token = NULL;
716 char * token2 = NULL;
717 char * name;
718 int value;
719 ulong token_len = 0;
720
721 config = env_get("env_boot_magic");
722 if (NULL == config)
723 {
724 printf("env_boot_magic missing in the env\n");
725 return -1;
726 }
727 elen = simple_strtoul(config, NULL, 0);
728 elen = max(elen, CONFIG_ENV_SIZE);
729 envbuf = malloc(elen);
730 memset(envbuf, 0, elen);
731
732 if (!envbuf)
733 {
734 printf("memory allocation failed\n");
735 return -2;
736 }
737 ep = (env_t *) (envbuf + 8);
738 ret = env_export(ep);
739
740 /* Search environment for variable names matching <part>_vol_size */
741 token = (char*)(ep->data);
742 while(strlen(token) && (ret == 0) && ((ulong)token < ((ulong)envbuf+elen)))
743 {
744 token_len = strlen(token);
745 if( (token2 = strstr(token, VOL_SIZE_STR)) )
746 {
747 *token2 = '\0';
748 name = token;
749 value = atoi( (char*)((ulong)token2 + strlen(VOL_SIZE_STR)) );
750 printf("%s: Detected env defined partition:%s, of size:%dM\n", __FUNCTION__, name, value);
751 ret = emmc_add_gpt_part(name, value);
752 ret = 0;
753 }
754 token = (char*)((ulong)token + token_len + 1);
755 }
756 free(envbuf);
757 return(ret);
758 }
759
760 static int do_gpt_fixup(cmd_tbl_t * cmdtp, int flag, int argc,
761 char *const argv[])
762 {
763 return emmc_do_gpt_fixup();
764 }
765
766 static int emmc_load_bootfs( int img_index, uint32_t bootfs_load_addr )
767 {
768 char cmd[128];
769 ulong size;
770 int ret = CMD_RET_FAILURE;
771 int fit_auth= -1;
772
773 /* Set rootfs volume id */
774 int rootfs_partid = (img_index == 1?IMAGE_PART_ID_1:IMAGE_PART_ID_2)+1;
775
776 /* Switch to userdata partition */
777 if( run_command("mmc dev 0 0", 0) == 0 ) {
778 //FIXME: OR skip loading if FIT is already in memory
779 //FIXME: IF FIT is loaded from flash, reverify RSA of header
780 sprintf(cmd, "bootfs%d", img_index);
781
782 /* Get FDT header */
783 size = sizeof(struct fdt_header);
784 ret = emmc_rdwr_userdata_part( cmd, (ulong)bootfs_load_addr, size, 0 );
785
786 /* Retrieve entire FIT header */
787 ret = emmc_rdwr_userdata_part( cmd, (ulong)bootfs_load_addr,
788 bcm_sec_get_reqd_load_size((ulong)bootfs_load_addr), 0 );
789
790 if (!ret) {
791 fit_auth = bcm_sec_validate_fit((void*)bootfs_load_addr, 0x10000);
792 }
793
794 /* Determine size of bootfs from fdt_header and load it */
795 size = emmc_get_bootfs_size((void *)bootfs_load_addr);
796 ret = emmc_rdwr_userdata_part( cmd, (ulong)bootfs_load_addr, size, 0 );
797
798 /* generate mapper parameters */
799 sprintf(cmd,"/dev/mmcblk0p%d", rootfs_partid);
800
801 /* If device mapper not being used, set rootfs_opts manually */
802 if ( (bcm_handle_mapper((void*)(ulong)bootfs_load_addr, cmd, "")) != 0)
803 {
804 /* Set default bootargs */
805 sprintf(cmd, "env set -f rootfs_opts root=/dev/mmcblk0p%d", rootfs_partid);
806 run_command(cmd, 0);
807 }
808
809 if (!fit_auth) {
810 bcm_board_boot_fdt_fixup((void*)bootfs_load_addr);
811 }
812 }
813 return ret;
814 }
815
816 #endif /* BCA_SDK_EMMC_CMD */
817
818 #ifdef BCA_SDK_NAND_CMD
819 #define EXTRA_SPC_SUFFIX_STR "_extra_space"
820 static uint64_t nand_get_part_extra_bytes(char* partition_prefix)
821 {
822 char var_name[128];
823 char * extra_space_str = NULL;
824 uint64_t extra_bytes = 0;
825 unsigned long iargs[4] = {0};
826 char units[4]= {0};
827 sprintf(var_name, "%s%s", partition_prefix, EXTRA_SPC_SUFFIX_STR);
828 extra_space_str = env_get(var_name);
829 if( extra_space_str ) {
830 parse_env_nums(extra_space_str, 1, iargs, units);
831 extra_bytes = ((long long)iargs[0]) << suffix2shift(units[0]);
832 }
833 if( extra_bytes < SIZE_OVERHEAD )
834 extra_bytes = SIZE_OVERHEAD;
835
836 return extra_bytes;
837 }
838
839 static uint64_t nand_get_avail_space(char * update_vol_name)
840 {
841 int i;
842 static struct ubi_device *ubi;
843 static struct ubi_volume *vol;
844 uint64_t vol_size = 0;
845 uint64_t avail_space = 0;
846 int ret = -1;
847
848 ret = run_command("ubi part image", 0);
849 if( ret == 0 ) {
850 ubi = ubi_devices[0];
851 for (i = 0; i < (ubi->vtbl_slots + 1); i++) {
852 if (!ubi->volumes[i])
853 continue; /* Empty record */
854 vol = ubi->volumes[i];
855 if( strcmp(vol->name,update_vol_name) == 0 ) {
856 vol_size = vol->reserved_pebs * vol->usable_leb_size;
857 break;
858 }
859 }
860 avail_space = ubi->avail_pebs * ubi->leb_size + vol_size;
861 }
862 return avail_space;
863 }
864
865 static int nand_restoredefault(void)
866 {
867 int ret = -1;
868 if(run_command("ubi part image", 0) == 0) {
869
870 /* If data exists, delete it */
871 if(run_command("ubi check data", 0) == 0 ) {
872 ret = run_command("ubi remove data", 0);
873 } else {
874 ret = 0;
875 }
876 } else {
877 printf("Error: Cannot attach ubi!\n");
878 }
879 return ret;
880 }
881
882 static int flash_rootfs_nand( ulong addr, ulong size, int img_index )
883 {
884 char cmd[128];
885 int ret = CMD_RET_FAILURE;
886 int rootfs_volid = (img_index == 1? IMAGE_VOL_ID_1:IMAGE_VOL_ID_2) + 1;
887 uint64_t avail_bytes = 0;
888 uint64_t extra_space_bytes = nand_get_part_extra_bytes("rootfs");
889
890 if( !addr || !size || img_index < MIN_IMG_INDEX || img_index > MAX_IMG_INDEX )
891 return CMD_RET_USAGE;
892
893 if(run_command("ubi part image", 0) == 0) {
894
895 /* check if new rootfs will fit in flash */
896 sprintf(cmd, "rootfs%d", img_index);
897 avail_bytes = nand_get_avail_space(cmd);
898 if( avail_bytes < size+extra_space_bytes ) {
899 printf("Error: Insufficient space in NAND for 0x%lx Bytes . Available size is 0x%llx\n", size+extra_space_bytes, avail_bytes);
900 return -1;
901 }
902
903 /* If rootfs1 exists, delete it */
904 sprintf(cmd, "ubi check rootfs%d", img_index);
905 if(run_command(cmd, 0) == 0) {
906 sprintf(cmd, "ubi remove rootfs%d", img_index);
907 run_command(cmd, 0);
908 }
909
910 /* Create rootfs volume */
911 sprintf(cmd, "ubi create rootfs%d %llx dynamic %d", img_index, size+extra_space_bytes,
912 rootfs_volid);
913 ret = run_command(cmd, 0);
914
915 /* Write rootfs data volume */
916 if( ret == 0 ) {
917 sprintf(cmd, "ubi write %lx rootfs%d %lx\n", addr, img_index, size);
918 ret = run_command(cmd, 0);
919 }
920
921 run_command("ubi detach", 0);
922 }
923 return ret;
924 }
925
926 static int flash_bootfs_nand( ulong addr, ulong size, int img_index )
927 {
928 char cmd[128];
929 int ret = CMD_RET_FAILURE;
930 int bootfs_volid = (img_index == 1? IMAGE_VOL_ID_1:IMAGE_VOL_ID_2);
931 int active_img_idx;
932 uint64_t avail_bytes = 0;
933 uint64_t extra_space_bytes = nand_get_part_extra_bytes("bootfs");
934
935 if( !addr || !size || img_index < MIN_IMG_INDEX || img_index > MAX_IMG_INDEX )
936 return CMD_RET_USAGE;
937
938 ret = run_command("ubi part image", 0);
939 if( ret ) {
940 /* Attach failed, check if we are running bootstrap code */
941 active_img_idx = get_active_img_idx();
942 if( active_img_idx == ACTIVE_IMGIDX_BOOTSTRAP ) {
943 /* We are running bootstrap image, wipe Image partition and retry */
944 printf("UBI attach fails for bootstrap image --> erasing IMAGE MTD partition\n");
945 run_command("mtd erase image", 0);
946 ret = run_command("ubi part image", 0);
947 }
948 }
949
950 if(ret == 0) {
951 /* If fit1 exists, delete it */
952 if(run_command("ubi check fit1", 0) == 0)
953 run_command("ubi remove fit1", 0);
954
955 /* check if new bootfs will fit in flash */
956 sprintf(cmd, "bootfs%d", img_index);
957 avail_bytes = nand_get_avail_space(cmd);
958 if( avail_bytes < size+extra_space_bytes ) {
959 printf("Error: Insufficient space in NAND for 0x%lx Bytes . Available size is 0x%llx\n", size+extra_space_bytes, avail_bytes);
960 return -1;
961 }
962
963 /* If bootfs exists, delete it */
964 sprintf(cmd, "ubi check bootfs%d", img_index);
965 if(run_command(cmd, 0) == 0) {
966 sprintf(cmd, "ubi remove bootfs%d", img_index);
967 run_command(cmd, 0);
968 }
969
970 /* Create bootfs volume */
971 sprintf(cmd, "ubi create bootfs%d %llx static %d", img_index, size+extra_space_bytes,
972 bootfs_volid);
973 ret = run_command(cmd, 0);
974
975 /* Write img data */
976 if( ret == 0 ) {
977 sprintf(cmd, "ubi write %lx bootfs%d %lx\n", addr, img_index, size);
978 ret = run_command(cmd, 0);
979 }
980
981 run_command("ubi detach", 0);
982 } else {
983 printf("Error! UBI attach failed!\n");
984 }
985
986 return ret;
987 }
988
989
990 static int flash_loader_nand( ulong addr, ulong size, int img_index )
991 {
992 struct mtd_info * mtd;
993 struct erase_info erase_op = {};
994 loff_t off;
995 int ret;
996 size_t retlen;
997 ulong remaining_bytes = size;
998 mtd = get_mtd_device_nm("loader");
999
1000 if( !addr || !size )
1001 return CMD_RET_USAGE;
1002
1003 if( !mtd ) {
1004 printf("ERROR: Failed to retrieve MTD device for NAND loader!\n");
1005 return -1;
1006 }
1007
1008 if( size > mtd->size ) {
1009 printf("ERROR: loader size 0x%08llx is greater than mtd partition size 0x%08llx!\n", size, mtd->size);
1010 put_mtd_device(mtd);
1011 return -1;
1012 }
1013
1014 (void)img_index;
1015
1016 /* Block by block write of loader */
1017 for( off=0; off < mtd->size; off += mtd->erasesize )
1018 {
1019 if( remaining_bytes ) {
1020 /* Erase block */
1021 erase_op.mtd = mtd;
1022 erase_op.addr = off;
1023 erase_op.len = mtd->erasesize;
1024 erase_op.scrub = 0;
1025 printf("Erasing next block at 0x%08llx\n", off);
1026 ret = mtd_erase(mtd, &erase_op);
1027
1028 /* Abort if its not a bad block error */
1029 if ((ret == -EIO) && erase_op.fail_addr) {
1030 printf("Skipping bad block at 0x%08llx\n", erase_op.fail_addr);
1031
1032 /* Truncate image size if we cant fit due to bad block skip */
1033 if( remaining_bytes > (mtd->size - off - mtd->erasesize) )
1034 remaining_bytes -= (remaining_bytes < mtd->erasesize?remaining_bytes:mtd->erasesize);
1035
1036 continue;
1037 } else if ( ret ) {
1038 printf("ERROR: Failed to erase NAND block 0x%08llx\n", off);
1039 break;
1040 }
1041
1042 /* write block */
1043 printf("Writing next block at 0x%08llx\n", off);
1044 ret = mtd_write(mtd, off,
1045 (remaining_bytes < mtd->erasesize?remaining_bytes:mtd->erasesize),
1046 &retlen, (const uchar*)(addr));
1047
1048 if( ret ) {
1049 printf("ERROR: Failed to write NAND block 0x%08llx\n", off);
1050 break;
1051 }
1052
1053 addr += (remaining_bytes < mtd->erasesize?remaining_bytes:mtd->erasesize);
1054 remaining_bytes -= (remaining_bytes < mtd->erasesize?remaining_bytes:mtd->erasesize);
1055 }
1056 else
1057 break;
1058 }
1059
1060 if( ret ) {
1061 /* Loader upgrade failed for some reason */
1062 printf("ERROR: Failed to flash NAND loader! re=%d\n", ret);
1063 } else {
1064 /* Loader upgrade worked */
1065 printf("NAND loader flashed successfully!\n");
1066 }
1067
1068 put_mtd_device(mtd);
1069 return ret;
1070 }
1071
1072 static int set_nand_metadata( char* metadata, int size )
1073 {
1074 char cmd[128];
1075 int ret;
1076 int i;
1077 int volmap[] = {-1,METADATA_VOL_ID_1,METADATA_VOL_ID_2};
1078
1079 ret = ubi_part("image", NULL);
1080 if (ret != 0) {
1081 return (ret);
1082 }
1083 for (i = 1; i < 3; i++) {
1084 sprintf(cmd, "ubi remove metadata%d", i);
1085 run_command(cmd, 0);
1086 sprintf(cmd,
1087 "ubi create metadata%d %d static %d", i,
1088 METADATA_SIZE + 1024, volmap[i]);
1089 run_command(cmd, 0);
1090 sprintf(cmd, "metadata%d", i);
1091 ubi_volume_write(cmd, metadata, size);
1092 }
1093 run_command("ubi detach", 0);
1094 return ret;
1095 }
1096
1097 static int get_nand_metadata( char* metadata, int size )
1098 {
1099 int ret;
1100 int committed = 0;
1101 int valid[2] = {0,0};
1102 int seq[2] = {-1,-1};
1103 int i;
1104 char name[128];
1105
1106 ret = ubi_part("image", NULL);
1107 if (ret != 0) {
1108 return (ret);
1109 }
1110 for (i = 1; i < 3; i++) {
1111 sprintf(name, "metadata%d", i);
1112 ret = ubi_volume_read(name, metadata, size);
1113 printf("read from %s returned %d\n", name, ret);
1114 if (0 == validate_metadata(metadata, valid, &committed, seq)) {
1115 break;
1116 } else {
1117 printf("metadata parse error\n");
1118 ret = CMD_RET_FAILURE;
1119 }
1120 }
1121 run_command("ubi detach", 0);
1122 return ret;
1123 }
1124
1125 static int nand_load_fit( int img_index, uint32_t fit_load_addr )
1126 {
1127 char cmd[128];
1128 int ret = CMD_RET_FAILURE;
1129 int fit_auth= -1;
1130
1131 if(run_command("ubi part image", 0) == 0) {
1132 //FIXME: OR skip loading if FIT is already in memory
1133 //FIXME: IF FIT is loaded from flash, reverify RSA of header
1134 sprintf(cmd, "ubi read %lx bootfs%d", fit_load_addr, img_index);
1135 ret = run_command(cmd, 0);
1136 /* may be it is just bootstrap image */
1137 if (ret) {
1138 sprintf(cmd, "ubi read %lx fit1", fit_load_addr);
1139 ret = run_command(cmd, 0);
1140 }
1141 }
1142 return ret;
1143 }
1144
1145
1146 static unsigned int bcm_handle_mapper(void* fit, char *flash_device, char *flash_opts)
1147 {
1148 const char *val;
1149 char cmd[768];
1150 char work[768];
1151 char *cp;
1152 int off, len;
1153 char dmdev[32];
1154 unsigned int magic;
1155
1156 off = fdt_path_offset(fit, "/brcm_rootfs_encrypt");
1157 if (off < 0) {
1158 return(1);
1159 }
1160 strcpy(dmdev,"/dev/dm-0");
1161 if (val = fdt_getprop(fit, off, "dev", &len)) {
1162 strncpy(dmdev, val, len);
1163 dmdev[len] = 0;
1164 }
1165 val = fdt_getprop(fit, off, "type", &len);
1166 if (val == NULL) {
1167 return(1);
1168 }
1169 val = fdt_getprop(fit, off, "mapper", &len);
1170 if (val == NULL) {
1171 return(1);
1172 }
1173 strncpy(work, val, len);
1174 work[len] = 0;
1175
1176 while (cp = strstr(work,"%DEVICE%")) {
1177 strncpy(cmd, work, cp-work);
1178 sprintf(&cmd[cp-work], "%s %s", \
1179 flash_device, cp+8);
1180 strcpy(work,cmd);
1181 }
1182 if (cp = strstr(work,"%IMAGE_KEY%")) {
1183 int i;
1184 val = NULL;
1185 len = 0;
1186 off = fdt_path_offset(gd->fdt_blob, "/trust/key_image_aes");
1187 if (off < 0) {
1188 printf("ERROR: Can't find /trust/key_image_aes node in boot DTB!\n");
1189 }
1190 val = (char*)(fdt_getprop(gd->fdt_blob, off, "value", &len));
1191 strncpy(cmd, work, cp-work);
1192 for (i = 0 ; i < len ; i++) {
1193 sprintf(&cmd[cp-work+2*i], "%02x", val[i]);
1194 }
1195 sprintf(&cmd[cp-work+2*i], "%s", cp+11);
1196 strcpy(work,cmd);
1197 }
1198 sprintf(cmd, "root=%s %s dm-mod.create=\"%s\"", dmdev, flash_opts, work);
1199 env_set("rootfs_opts", cmd);
1200 return(0);
1201 }
1202
1203 static int nand_load_bootfs( int img_index, uint32_t bootfs_load_addr )
1204 {
1205 char cmd[128];
1206 char device[32];
1207 unsigned int magic = 0;
1208 int ret = CMD_RET_FAILURE;
1209 int fit_auth= -1;
1210
1211 /* Set rootfs volume id */
1212 int rootfs_volid = (img_index == 1?IMAGE_VOL_ID_1:IMAGE_VOL_ID_2)+1;
1213
1214 if(run_command("ubi part image", 0) == 0) {
1215 /* Set default bootargs */
1216 /* Determine rootfs type */
1217 sprintf(cmd, "ubi read %lx bootfs%d", bootfs_load_addr, img_index);
1218 ret = run_command(cmd, 0);
1219 if (!ret) {
1220 fit_auth = bcm_sec_validate_fit((void*)bootfs_load_addr, 0x10000);
1221 }
1222
1223 sprintf(device,"/dev/ubiblock0_%d", rootfs_volid);
1224 sprintf(cmd,"ubi.mtd=1 ubi.block=0,%d rootfstype=squashfs", rootfs_volid);
1225 if (bcm_handle_mapper((void*)(ulong)bootfs_load_addr, device, cmd) == 0)
1226 {
1227 /* mapper has set up the whole thing */
1228 if (!fit_auth) {
1229 bcm_board_boot_fdt_fixup((void*)bootfs_load_addr);
1230 }
1231 return(0);
1232 }
1233
1234 sprintf(cmd, "ubi read %lx rootfs%d %d", &magic, img_index, (int)sizeof(unsigned int));
1235 if (run_command(cmd, 0) == 0) {
1236 if( magic == UBIFS_MAGIC ) {
1237 sprintf(cmd, "env set -f rootfs_opts root=ubi:rootfs%d ubi.mtd=1 rootfstype=ubifs", img_index);
1238 run_command(cmd, 0);
1239 }
1240 else if ( magic == SQUASHFS_MAGIC ) {
1241 sprintf(cmd, "env set -f rootfs_opts root=/dev/ubiblock0_%d ubi.mtd=1 ubi.block=0,%d rootfstype=squashfs", rootfs_volid, rootfs_volid);
1242 run_command(cmd, 0);
1243 } else {
1244 printf("ERROR: Invalid rootfs detected in volume rootfs1! Boot aborted!\n");
1245 return ret;
1246 }
1247 } else {
1248 printf("ERROR: Cannot determine rootfs type! Boot aborted!\n");
1249 return ret;
1250 }
1251
1252 if (!fit_auth && magic == SQUASHFS_MAGIC ) {
1253 bcm_board_boot_fdt_fixup((void*)bootfs_load_addr);
1254 }
1255 }
1256 return ret;
1257 }
1258 #endif /* BCA_SDK_NAND_CMD */
1259 #if defined(BCA_SDK_SPINOR_CMD)
1260 static int spinor_load_bootfs(uint32_t bootfs_load_addr)
1261 {
1262 int ret= -1;
1263 struct mtd_info *mtd;
1264 size_t retlen;
1265 int fit_auth;
1266
1267 mtd_probe_devices();
1268 mtd = get_mtd_device_nm(BOOTFS_PART);
1269 if (IS_ERR_OR_NULL(mtd)){
1270 debug("%s:MTD device %s not found, ret %ld\n",__func__, BOOTFS_PART,
1271 PTR_ERR(mtd));
1272 return ret;
1273 }
1274
1275 ret = mtd_read(mtd,0,mtd->size,&retlen,(u_char*)bootfs_load_addr );
1276
1277 if (!ret) {
1278 fit_auth = bcm_sec_validate_fit((void*)bootfs_load_addr, 0x10000);
1279 }
1280
1281 /* If device mapper not being used, set the rootfs_opts manually */
1282 if (bcm_handle_mapper((void*)(ulong)bootfs_load_addr, "/dev/mtdblock3", "rootfstype=squashfs") != 0) {
1283 env_set("rootfs_opts","root=/dev/mtdblock3 rootfstype=squashfs");
1284 }
1285
1286 if (!fit_auth) {
1287 bcm_board_boot_fdt_fixup((void*)bootfs_load_addr);
1288 }
1289
1290 put_mtd_device(mtd);
1291 return ret;
1292 }
1293 static int spinor_restoredefault(void)
1294 {
1295 struct mtd_info *mtd;
1296 struct erase_info ei;
1297 int ret;
1298
1299 mtd_probe_devices();
1300 mtd = get_mtd_device_nm(DATA_PART);
1301 if (IS_ERR_OR_NULL(mtd)){
1302 printf("ERROR!!:failed to get data partition!!\n");
1303 return CMD_RET_FAILURE;
1304 }
1305
1306 memset(&ei, 0, sizeof(ei));
1307 ei.mtd = mtd;
1308 ei.addr = 0;
1309 ei.len = mtd->size;
1310 ret = mtd_erase(mtd, &ei);
1311 if (ret){
1312 printf("ERROR!!: failed to restore to default!!\n");
1313 ret = CMD_RET_FAILURE;
1314 }
1315 else
1316 printf("Restore to default done.\n");
1317
1318 put_mtd_device(mtd);
1319 return ret;
1320 }
1321
1322 static int flash_loader_spinor( ulong addr, ulong size)
1323 {
1324 int ret= -1;
1325 struct mtd_info *mtd;
1326 struct erase_info ei;
1327 size_t retlen;
1328 char *config;
1329 u_char *envbuf = NULL;
1330 char *found = NULL;
1331 int elen;
1332 int i;
1333 size_t wr_len;
1334 char *c;
1335
1336 if( !addr || !size )
1337 return CMD_RET_USAGE;
1338 mtd_probe_devices();
1339 mtd = get_mtd_device_nm(LOADER_PART);
1340 if (IS_ERR_OR_NULL(mtd)){
1341 printf("%s:MTD device %s not found, ret %ld\n",__func__, LOADER_PART,
1342 PTR_ERR(mtd));
1343 return ret;
1344 }
1345
1346 config = env_get("env_boot_magic");
1347 if (NULL != config){
1348 elen = simple_strtoul(config, NULL, 0);
1349 found = malloc(strlen(config) + 1);
1350 if (found){
1351 strcpy(found, config);
1352 envbuf = malloc(elen + 12);
1353 if(envbuf){
1354 strtok(found, "@");
1355 while ((c = strtok(NULL, ","))) {
1356 i = simple_strtoul(c, NULL, 0);
1357 debug("read from %x\n", i);
1358 wr_len = elen+12;
1359 debug("read len %x\n", wr_len);
1360 if( mtd_read(mtd,i,wr_len,&retlen, envbuf)){
1361 debug("%s:MTD device %s read fail\n",__func__, LOADER_PART);
1362 continue;
1363 }
1364 /*assume addr + i will not cause any issue*/
1365 memcpy(addr+i, envbuf, wr_len);
1366 /*need this?*/
1367 if( size < (i + wr_len)){
1368 debug("%s:Change original size from %ld to %d \n",__func__,size, i + wr_len);
1369 size = i + wr_len;
1370 }
1371 }
1372 free(envbuf);
1373 }
1374 free(found);
1375 }
1376 }
1377
1378 printf("\nErasing MTD partition %s...\n",LOADER_PART);
1379 memset(&ei, 0, sizeof(ei));
1380 ei.mtd = mtd;
1381 ei.addr = 0;
1382 ei.len = mtd->size;
1383 ret = mtd_erase(mtd, &ei);
1384 if (ret){
1385 debug("%s:erase MTD device %s fail, ret %d\n",__func__, LOADER_PART,
1386 ret);
1387 goto done;
1388 }
1389
1390 printf("Writing MTD partition %s...\n",LOADER_PART);
1391 ret = mtd_write(mtd, 0, size, &retlen, addr);
1392 if (ret){
1393 debug("%s:write MTD device %s fail, ret %d\n",__func__, LOADER_PART,
1394 ret);
1395 }
1396 debug("%s:Erase/write MTD device %s done, ret %d\n",__func__, LOADER_PART,
1397 ret);
1398 done:
1399 put_mtd_device(mtd);
1400 return ret;
1401
1402 }
1403
1404 static int write_spinor_partition( char *const partitionname, ulong addr, ulong size )
1405 {
1406 int ret= -1;
1407 struct mtd_info *mtd;
1408 struct erase_info ei;
1409 size_t retlen;
1410
1411 if( !addr || !size )
1412 return CMD_RET_USAGE;
1413
1414 mtd_probe_devices();
1415 mtd = get_mtd_device_nm(partitionname);
1416 if (IS_ERR_OR_NULL(mtd)){
1417 debug("%s:MTD device %s not found, ret %d\n",__func__, partitionname,
1418 PTR_ERR(mtd));
1419 return ret;
1420 }
1421 printf("\nErasing MTD partition %s...\n",partitionname);
1422 memset(&ei, 0, sizeof(ei));
1423 ei.mtd = mtd;
1424 ei.addr = 0;
1425 ei.len = mtd->size;
1426 ret = mtd_erase(mtd, &ei);
1427 if (ret){
1428 debug("%s:erase MTD device %s fail, ret %d\n",__func__, partitionname,
1429 ret);
1430 goto done;
1431 }
1432
1433 printf("Writing MTD partition %s...\n",partitionname);
1434 ret = mtd_write(mtd, 0, size, &retlen, (u_char*)addr);
1435 if (ret){
1436 debug("%s:write MTD device %s fail, ret %d\n",__func__, partitionname,
1437 ret);
1438 }
1439 done:
1440 put_mtd_device(mtd);
1441 return ret;
1442 }
1443
1444 static int do_flash_spinor_binary(cmd_tbl_t * cmdtp, int flag, int argc,
1445 char *const argv[])
1446 {
1447 char cmd[128];
1448 ulong size;
1449 ulong addr;
1450
1451 /* Download binary image */
1452 sprintf(cmd, "tftp %lx %s", load_addr, argv[1]);
1453 if( run_command(cmd, 0) == 0 ) {
1454 addr = env_get_hex("fileaddr", 0);
1455 size = env_get_hex("filesize", 0);
1456 write_spinor_partition(SPIFLASH_MTDNAME, addr, size);
1457 } else
1458 printf("ERROR!!: Failed to tftp spinor binary!!\n");
1459
1460 return 0;
1461 }
1462
1463 static int do_flash_spinor_bootfs_rootfs(cmd_tbl_t * cmdtp, int flag, int argc,
1464 char *const argv[])
1465 {
1466 char filename[30];
1467 int flash_fit=0;
1468 int ret = CMD_RET_FAILURE;
1469 char cmd[128];
1470 ulong size;
1471 ulong addr;
1472
1473
1474 /* Parse arguments */
1475 if ( strcmp(argv[0], "flash_spinor_fit") == 0) {
1476 flash_fit=1;
1477 sprintf(filename, "brcm_full_linux.itb");
1478 } else {
1479 sprintf(filename, "rootfs.squashfs");
1480 }
1481
1482 sprintf(cmd, "tftp %lx %s\n", load_addr, filename);
1483 if( run_command(cmd, 0) == 0 ) {
1484 size = env_get_hex("filesize", 0);
1485 addr = env_get_hex("fileaddr", 0);
1486 if(flash_fit){
1487 ret = write_spinor_partition(BOOTFS_PART, addr, size);
1488 }
1489 else{
1490 ret = write_spinor_partition(ROOTFS_PART, addr, size);
1491 }
1492 }
1493 else
1494 printf("ERROR!!: Failed to tftp rootfs binary!!\n");
1495
1496 return ret;
1497 }
1498 #endif /*BCA_SDK_SPINOR_CMD*/
1499
1500 /************************************************************
1501 * Generic Functions *
1502 ************************************************************/
1503 static int sync_update_loader_bin_env(ulong loader_addr)
1504 {
1505 env_t *ep;
1506 uint32_t calc_crc;
1507 char *envbuf = NULL;
1508 uint32_t *envintp;
1509 int ret = -2;
1510 int i;
1511 loff_t off;
1512 size_t rdlen;
1513 uint32_t magichdr[3];
1514 int num_env_found = 0;
1515 char * config;
1516
1517 /* Search loader in memory for env headers */
1518 for (off = 0; off < (loff_t)env_boot_magic_search_size(); off += 4096) {
1519 rdlen = 12;
1520 memcpy((char*)magichdr, (char*)loader_addr + off, rdlen);
1521 if (magichdr[0] != BOOT_MAGIC_MAGIC) {
1522 continue;
1523 } else {
1524 /* Verify CRC */
1525 rdlen = magichdr[1];
1526 ep = (env_t *) ((char*)loader_addr + off + 8);
1527 calc_crc = the_env_crc32(0, ep->data, rdlen - 4);
1528 if( ep->crc == calc_crc ) {
1529 num_env_found++;
1530 } else {
1531 continue;
1532 }
1533 }
1534
1535 /* Create synced env blob */
1536 if(num_env_found == 1)
1537 {
1538 /* Export environment to embed in new loader */
1539 envbuf = malloc(max(rdlen + 12, CONFIG_ENV_SIZE + 12));
1540 if( !envbuf ) {
1541 printf("ERROR: Failed to allocate mem for env!\n");
1542 ret = -1;
1543 break;
1544 }
1545 ep = (env_t *) (envbuf + 8);
1546 envintp = (uint32_t *) envbuf;
1547
1548 /* Delete boot magic string before exporting env */
1549 config = env_get("env_boot_magic");
1550 env_set("env_boot_magic", NULL);
1551 ret = env_export(ep);
1552 if( ret ) {
1553 printf("ERROR: Failed to export env!\n");
1554 env_set("env_boot_magic", config);
1555 break;
1556 }
1557
1558 for (i = CONFIG_ENV_SIZE; i < rdlen; i++) {
1559 envbuf[12 + i] = 0xff;
1560 }
1561 calc_crc = the_env_crc32(0, ep->data, rdlen - 4);
1562 memcpy(&ep->crc, &calc_crc, sizeof(calc_crc));
1563 envintp[0] = BOOT_MAGIC_MAGIC;
1564 envintp[1] = rdlen;
1565 }
1566
1567 /* Write synched env back to loader binary */
1568 printf("Updating env in loader bin at 0x%lx\n", (long)off);
1569 memcpy((char*)loader_addr + off, envbuf, rdlen+12);
1570 }
1571
1572 if(envbuf)
1573 free(envbuf);
1574
1575 if(!num_env_found)
1576 ret = -1;
1577
1578 return ret;
1579 }
1580
1581 char * get_loader_media(void)
1582 {
1583 int node,len;
1584 char *media = NULL;
1585
1586 if(forced_updates && strlen(forced_boot_media)) {
1587 media = forced_boot_media;
1588 printf("WARNING: forced_updates == 1, forcing boot media to %s!\n", media);
1589 } else {
1590 node = fdt_path_offset(gd->fdt_blob, "/chosen");
1591 if (node < 0) {
1592 printf("ERROR: Can't find /chosen node in cboot DTB! Cannot determine boot media!\n");
1593 return media;
1594 }
1595 media = (char*)(fdt_getprop(gd->fdt_blob, node, "boot_device", &len));
1596 }
1597 return media;
1598 }
1599
1600 static char * get_image_media(void)
1601 {
1602 char *cp = NULL;
1603 char *media = NULL;
1604
1605 if(forced_updates && strlen(forced_image_media)) {
1606 media = forced_image_media;
1607 printf("WARNING: forced_updates == 1, forcing image media to %s!\n", media);
1608 } else {
1609 cp = env_get("IMAGE");
1610 if (NULL != cp)
1611 {
1612 unsigned long iargs[4];
1613 char units[4];
1614 parse_env_string_plus_nums(cp, &media, 4, iargs, units);
1615 }
1616 else
1617 printf("ERROR: Can't find IMAGE env parameter! Cannot determine image media!\n");
1618 }
1619
1620 return media;
1621 }
1622
1623 static int flash_rootfs( ulong addr, ulong size , int img_index)
1624 {
1625 int ret = -1;
1626 if( strcasecmp(get_image_media(), FLASH_DEV_STR_NAND) == 0 ) {
1627 #ifdef BCA_SDK_NAND_CMD
1628 ret = flash_rootfs_nand(addr, size, img_index);
1629 #endif
1630 }
1631
1632 if( ret && ( strcasecmp(get_image_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
1633 #ifdef BCA_SDK_EMMC_CMD
1634 ret = flash_rootfs_emmc(addr, size, img_index);
1635 #endif
1636 }
1637
1638 if( ret && ( strcasecmp(get_image_media(), FLASH_DEV_STR_SPINOR) == 0 ) ) {
1639 #ifdef BCA_SDK_SPINOR_CMD
1640 ret = write_spinor_partition(ROOTFS_PART, addr, size);
1641 #endif
1642 }
1643
1644 if( ret )
1645 printf("ERROR: Failed to flash bootfs binary!\n");
1646
1647 return ret;
1648
1649 }
1650 static int flash_bootfs( ulong addr, ulong size , int img_index)
1651 {
1652 int ret = -1;
1653 if( strcasecmp(get_image_media(), FLASH_DEV_STR_NAND) == 0 ) {
1654 #ifdef BCA_SDK_NAND_CMD
1655 ret = flash_bootfs_nand(addr, size, img_index);
1656 #endif
1657 }
1658
1659 if( ret && ( strcasecmp(get_image_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
1660 #ifdef BCA_SDK_EMMC_CMD
1661 ret = flash_bootfs_emmc(addr, size, img_index);
1662 #endif
1663 }
1664
1665 if( ret && ( strcasecmp(get_image_media(), FLASH_DEV_STR_SPINOR) == 0 ) ) {
1666 #ifdef BCA_SDK_SPINOR_CMD
1667 ret = write_spinor_partition(BOOTFS_PART, addr, size);
1668 #endif
1669 }
1670 if( ret )
1671 printf("ERROR: Failed to flash bootfs binary!\n");
1672
1673 return ret;
1674 }
1675 static int flash_loader( ulong addr, ulong size , int img_index)
1676 {
1677 int ret = -1;
1678 char * config;
1679
1680 /* Synch uboot env to loader binary */
1681 if( disable_runtime_env_sync ) {
1682 printf("WARNING: Not synching runtime env to loader board_spl_fit_pre_load!\n");
1683 } else {
1684 if( sync_update_loader_bin_env(addr) ) {
1685 printf("ERROR: Could not sync runtime env to loader bin!\n");
1686 return ret;
1687 }
1688 }
1689
1690 if( strcasecmp(get_loader_media(), FLASH_DEV_STR_NAND) == 0 ) {
1691 #ifdef BCA_SDK_NAND_CMD
1692 ret = flash_loader_nand(addr, size, img_index);
1693 #endif
1694 }
1695
1696 if( ret && ( strcasecmp(get_loader_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
1697 #ifdef BCA_SDK_EMMC_CMD
1698 ret = flash_loader_emmc(addr, size, img_index);
1699 #endif
1700 }
1701
1702 if( ret && ( strcasecmp(get_loader_media(), FLASH_DEV_STR_SPINOR) == 0 ) ) {
1703 #ifdef BCA_SDK_SPINOR_CMD
1704 ret = flash_loader_spinor(addr, size);
1705 #endif
1706 }
1707 if( disable_runtime_env_sync ) {
1708 printf("WARNING: Not updating runtime env from flashed loader!\n");
1709 disable_runtime_env_sync = 0;
1710 } else {
1711 /* Since sync was successful, we need to scan loader
1712 * for boot magic and update runtime env */
1713 env_relocate();
1714 env_set("fileaddr", NULL);
1715 env_save();
1716 }
1717
1718 if( ret )
1719 printf("ERROR: Failed to flash loader binary!\n");
1720
1721 return ret;
1722 }
1723
1724 static int set_metadata_val( int * committed, int * valid, int * seq )
1725 {
1726 char* b;
1727 uint32_t *d, crc;
1728 env_t * ep;
1729 int i;
1730 int ret = -1;
1731
1732 b = malloc(METADATA_SIZE + 2048);
1733 d = (uint32_t *) b;
1734 ep = (env_t *) & d[2];
1735 d[0] = METADATA_SIZE;
1736 d[1] = METADATA_SIZE;
1737 i = sprintf((char*)ep->data, "COMMITTED=%d",*committed) + 1;
1738 i = i + sprintf((char*)&ep->data[i], "VALID=%d,%d",valid[0],valid[1]) + 1;
1739 i = i + sprintf((char*)&ep->data[i], "SEQ=%d,%d",seq[0],seq[1]) + 1;
1740 ep->data[i] = '\0';
1741 crc = the_env_crc32(0, ep->data, (d[0] - 4) & 0xffff);
1742 /*
1743 * We can't use plain crc32 because someone redefines it??
1744 * crc = crc32(0, ep->data, (d[0] - 4) & 0xffff);
1745 */
1746 memcpy(&ep->crc, &crc, sizeof(crc));
1747
1748 /* Flash metadata */
1749 if( strcasecmp(get_image_media(), FLASH_DEV_STR_NAND) == 0 ) {
1750 #ifdef BCA_SDK_NAND_CMD
1751 ret = set_nand_metadata(b, METADATA_SIZE + 16);
1752 #endif
1753 }
1754
1755 if( ret && ( strcasecmp(get_image_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
1756 #ifdef BCA_SDK_EMMC_CMD
1757 ret = set_emmc_metadata(b, METADATA_SIZE + 16);
1758 #endif
1759 }
1760
1761 printf("Setting committed %d valid %d,%d seq %d,%d\n", *committed, valid[0], valid[1], seq[0], seq[1]);
1762 free(b);
1763 return ret;
1764 }
1765
1766 static int get_metadata_val( int * committed, int * valid, int * seq )
1767 {
1768 char *b = malloc(MAX_METADATA_SIZE);
1769 int ret = -1;
1770
1771 /* Read metadata from flash */
1772 if( strcasecmp(get_image_media(), FLASH_DEV_STR_NAND) == 0 ) {
1773 #ifdef BCA_SDK_NAND_CMD
1774 ret = get_nand_metadata( b, MAX_METADATA_SIZE);
1775 #endif
1776 }
1777
1778 if( ret && ( strcasecmp(get_image_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
1779 #ifdef BCA_SDK_EMMC_CMD
1780 ret = get_emmc_metadata(b, MAX_METADATA_SIZE);
1781 #endif
1782 }
1783
1784 /* Validate metadata */
1785 ret = validate_metadata(b, valid, committed, seq);
1786 free(b);
1787 printf("Getting committed %d valid %d,%d seq %d,%d\n", *committed, valid[0], valid[1], seq[0], seq[1]);
1788 return ret;
1789 }
1790
1791 int commit_image( int img_index )
1792 {
1793 int committed = 0;
1794 int valid[2] = {0,0};
1795 int seq[2] = {-1,-1};
1796
1797 /*Return directly for SPI Nor*/
1798 if( strcmp(get_image_media(), FLASH_DEV_STR_SPINOR) == 0)
1799 return 0;
1800
1801 /* Get committed image */
1802 get_metadata_val(&committed, valid, seq);
1803
1804 /* update committed image */
1805 committed = img_index;
1806 valid[img_index-1] = img_index;
1807 seq[img_index-1] = (seq[(img_index == 1) ? 1 : 0] + 1) % 1000; // set newly written image sequence number one greater than other image
1808
1809 /* Set committed image */
1810 set_metadata_val(&committed, valid, seq);
1811
1812 return 0;
1813 }
1814
1815 int get_img_index_for_upgrade(int flag)
1816 {
1817 int committed = 0;
1818 int valid[2] = {0,0};
1819 int seq[2] = {-1,-1};
1820 (void) flag;
1821 int img_index = get_active_img_idx();
1822
1823 /*Return 1 for SPI Nor*/
1824 if( strcmp(get_image_media(), FLASH_DEV_STR_SPINOR) == 0 )
1825 return 1;
1826
1827 /* If we know the active image, always write to the inactive image */
1828 if( img_index ) {
1829 return( (img_index==1)?2:1 );
1830 }
1831
1832 /* If we cannot determine active image, then get non committed image */
1833 get_metadata_val(&committed, valid, seq);
1834 if( !committed ) {
1835 /* If no commited images then we will flash to the 1st img index */
1836 return 1;
1837 } else {
1838 /* If we have a committed image, then we will upgrade the uncommitted one */
1839 return (committed == 1? 2: 1);
1840 }
1841 }
1842
1843 #ifndef CONFIG_LOAD_FIT_OFFSET
1844 #define CONFIG_LOAD_FIT_OFFSET SZ_16M
1845 #endif
1846
1847 static int load_linux_img( int flag, int argc, char *const argv[])
1848 {
1849 char cmd[128];
1850 char * board_id = NULL;
1851 int img_index = 0;
1852 uint32_t bootfs_load_addr = load_addr + CONFIG_LOAD_FIT_OFFSET;
1853 int ret = -1;
1854
1855 if( argc == 1 ) {
1856 img_index = get_active_img_idx();
1857 } else if( argc > 1 ) {
1858 if( strlen(argv[1]) == 1 )
1859 img_index = *argv[1] - '0';
1860 else {
1861 board_id = argv[1];
1862 img_index = get_active_img_idx();
1863 }
1864
1865 if( argc > 2 ) {
1866 board_id = argv[2];
1867 }
1868 }
1869
1870 if( img_index < MIN_IMG_INDEX || img_index > MAX_IMG_INDEX ) {
1871 printf("ERROR: Invalid Image Index specified!\n");
1872 return CMD_RET_FAILURE;
1873 }
1874
1875 #if defined(CONFIG_BCM_BOOTSTATE)
1876 /* bcmbca_set_boot_reason(BCM_BOOT_REASON_WATCHDOG | BCM_BOOT_PHASE_LINUX_START | (bcmbca_get_boot_reason() & 0xffff0000) ); */
1877 #endif
1878 /* Load bootfs to load address */
1879 if( strcasecmp(get_image_media(), FLASH_DEV_STR_NAND) == 0 ) {
1880 #ifdef BCA_SDK_NAND_CMD
1881 ret = nand_load_bootfs(img_index, bootfs_load_addr);
1882 #endif
1883 }
1884
1885 if( ret && ( strcasecmp(get_image_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
1886 #ifdef BCA_SDK_EMMC_CMD
1887 ret = emmc_load_bootfs(img_index, bootfs_load_addr);
1888 ret = emmc_do_gpt_fixup();
1889 #endif
1890 }
1891
1892 if( ret && ( strcasecmp(get_image_media(), FLASH_DEV_STR_SPINOR) == 0 ) ) {
1893 #ifdef BCA_SDK_SPINOR_CMD
1894 ret = spinor_load_bootfs(bootfs_load_addr);
1895 #endif
1896 }
1897
1898 if( ret == 0 ) {
1899 #if defined(CONFIG_WDT)
1900 if (gd->watchdog_dev)
1901 wdt_stop(gd->watchdog_dev);
1902 #endif
1903 if(!board_id)
1904 board_id = env_get("boardid");
1905
1906 /* Load binaries */
1907 sprintf(cmd, "/configurations/conf_lx_%s", board_id);
1908 if(board_id && (fdt_path_offset((void *)bootfs_load_addr, cmd) >= 0))
1909 sprintf(cmd, "bootm start %lx#conf_lx_%s; bootm loados; bootm prep;", bootfs_load_addr, board_id);
1910 else
1911 sprintf(cmd, "bootm start %lx#conf_linux; bootm loados; bootm prep;", bootfs_load_addr);
1912
1913 run_command(cmd, 0);
1914 } else {
1915 printf("ERROR: Failed to load bootfs%d!\n", img_index);
1916 }
1917
1918 return ret;
1919 }
1920
1921 static int do_load(cmd_tbl_t * cmdtp, int flag, int argc,
1922 char *const argv[])
1923 {
1924 if( load_linux_img( flag, argc, argv ) == 0 ) {
1925 printf("\nAll Image components have been loaded to DDR:\n");
1926 printf(" - To edit FDT: 'fdt <fdt cmds> ..'\n");
1927 printf(" - To launch Linux: 'bootm go'\n");
1928 } else
1929 printf("Linux image loading Failed!\n");
1930
1931 return 0;
1932 }
1933
1934 static int do_boot(cmd_tbl_t * cmdtp, int flag, int argc,
1935 char *const argv[])
1936 {
1937 if( load_linux_img( flag, argc, argv ) == 0 )
1938 run_command("bootm go\n", 0);
1939 else
1940 printf("Linux image booting Failed!\n");
1941
1942 return 0;
1943 }
1944
1945 static int do_flash_loader(cmd_tbl_t * cmdtp, int flag, int argc,
1946 char *const argv[])
1947 {
1948 char cmd[128];
1949 const char *chip_num;
1950 ulong size;
1951 ulong addr;
1952
1953 /* Determine chip number */
1954 chip_num = strstr(CONFIG_SYS_SOC, "bcm");
1955 chip_num += strlen("bcm");
1956
1957 if( strcasecmp(get_loader_media(), FLASH_DEV_STR_NAND) == 0 ) {
1958 sprintf(cmd, "tftp %lx loader_test_nand_%s.bin\n", load_addr, chip_num);
1959 }
1960
1961 if( ( strcasecmp(get_loader_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
1962 sprintf(cmd, "tftp %lx loader_test_emmc_%s.bin\n", load_addr, chip_num);
1963 }
1964
1965 if( ( strcasecmp(get_loader_media(), FLASH_DEV_STR_SPINOR) == 0 ) ) {
1966 sprintf(cmd, "tftp %lx loader_test_spinor_%s.bin\n", load_addr, chip_num);
1967 }
1968
1969 if( run_command(cmd, 0) == 0 ) {
1970 size = env_get_hex("filesize", 0);
1971 addr = env_get_hex("fileaddr", 0);
1972 flash_loader(addr, size, 0);
1973 } else
1974 printf("ERROR!!: Failed to tftp loader binary!!\n");
1975
1976 return 0;
1977 }
1978
1979 static int do_flash_bootfs_rootfs( char * bootfs_filename, char * rootfs_filename, int img_index )
1980 {
1981 char cmd[128];
1982 ulong size;
1983 ulong addr;
1984 int ret = CMD_RET_FAILURE;
1985
1986 /* Write bootfs */
1987 if(bootfs_filename) {
1988 sprintf(cmd, "tftp %lx %s", load_addr, bootfs_filename);
1989 if( run_command(cmd, 0) == 0 ) {
1990 size = env_get_hex("filesize", 0);
1991 addr = env_get_hex("fileaddr", 0);
1992 ret = flash_bootfs(addr, size, img_index);
1993 } else
1994 printf("ERROR!!: Failed to tftp FIT image!!\n");
1995 }
1996
1997 /* Write rootfs */
1998 if(rootfs_filename) {
1999 sprintf(cmd, "tftp %lx %s\n", load_addr, rootfs_filename);
2000
2001 if( run_command(cmd, 0) == 0 ) {
2002 size = env_get_hex("filesize", 0);
2003 addr = env_get_hex("fileaddr", 0);
2004 ret = flash_rootfs(addr, size, img_index);
2005 } else
2006 printf("ERROR!!: Failed to tftp rootfs binary!!\n");
2007 }
2008
2009 return ret;
2010 }
2011
2012 static int do_flash_bins(cmd_tbl_t * cmdtp, int flag, int argc,
2013 char *const argv[])
2014 {
2015 char * rootfs_fname = NULL;
2016 char * bootfs_fname = NULL;
2017 int img_index = 0;
2018 int ret = CMD_RET_FAILURE;
2019
2020 /* Parse arguments */
2021 if ( (strcmp(argv[0], "flash_bootfs_raw") == 0) ) {
2022 bootfs_fname = argv[1];
2023 }
2024 if( (strcmp(argv[0], "flash_rootfs_raw") == 0) ) {
2025 rootfs_fname = argv[1];
2026 }
2027
2028 if( argc >= 2 ) {
2029 if( (argc == 3) && (strlen(argv[2]) == 1) )
2030 img_index = *argv[2] - '0';
2031 else
2032 img_index = get_img_index_for_upgrade(0);
2033 } else {
2034 return CMD_RET_USAGE;
2035 }
2036
2037 ret = do_flash_bootfs_rootfs(bootfs_fname, rootfs_fname, img_index);
2038
2039 return ret;
2040 }
2041
2042 static int verify_compat_string( const char * compat_str )
2043 {
2044 const char *chip_num;
2045 char * flash_type;
2046 char * token = NULL;
2047 #ifdef BCA_SDK_NAND_CMD
2048 char flash_type_full[20];
2049 struct mtd_info *mtd = NULL;
2050 #endif
2051
2052 /* Early return if forced updates are enabled */
2053 if( forced_updates ) {
2054 printf("WARNING: Skipping all compatibility checks due to forced updates being enabled!\n");
2055 return 0;
2056 }
2057
2058 /* Determine chip number */
2059 chip_num = strstr(CONFIG_SYS_SOC, "bcm");
2060 chip_num += strlen("bcm");
2061
2062 /* Determine flash type matches*/
2063 flash_type = get_image_media();
2064
2065 if( strcmp(flash_type, FLASH_DEV_STR_NAND) == 0 ) {
2066 #ifdef BCA_SDK_NAND_CMD
2067 mtd = get_nand_dev_by_index(0);
2068 if (!mtd) {
2069 printf("ERROR: Cannot determine NAND erase block size!\n");
2070 return CMD_RET_FAILURE;
2071 }
2072 sprintf(flash_type_full, "%s%d", flash_type, mtd->erasesize >> 10 );
2073 #endif
2074 }
2075
2076 /* Check compat string */
2077 token = strtok((char *)compat_str,";");
2078 while( token ) {
2079 if( strstr(token, "chip=")) {
2080 token += strlen("chip=");
2081 if( strcasecmp(token, chip_num) ) {
2082 printf("ERROR: Img bundle is for %s, current chip is %s\n", token, chip_num);
2083 return -1;
2084 }
2085 } else if( strstr(token, "flash=")) {
2086 token += strlen("flash=");
2087 if( strcasecmp(token, flash_type) ) {
2088 if( strcmp(flash_type, FLASH_DEV_STR_NAND) == 0 ) {
2089 #ifdef BCA_SDK_NAND_CMD
2090 if( strcasecmp(token, flash_type_full) )
2091 {
2092 printf("ERROR: Img bundle is for %s, current flash is %s\n", token, flash_type_full);
2093 return -1;
2094 }
2095 #endif
2096 } else {
2097 printf("ERROR: Img bundle is for %s, current flash is %s\n", token, flash_type);
2098 return -1;
2099 }
2100 }
2101 }
2102 token = strtok(NULL,";");
2103 }
2104 return 0;
2105 }
2106
2107 static int get_binary_from_bundle( ulong bundle_addr, char * conf_name, char * name,
2108 char ** bin_name, ulong * addr, ulong * size )
2109 {
2110 char path[128];
2111 int conf_nodeoffset = 0;
2112 int nodeoffset = 0;
2113 int len;
2114 int ret = -1;
2115
2116 if ( !conf_name || !name || !bin_name ) {
2117 printf("ERROR: Invalid conf_name %p, bin_name %p, name %p\n",
2118 conf_name, bin_name, name);
2119 return ret;
2120 }
2121
2122 /* retrieve configuration node */
2123 sprintf(path, "/configurations");
2124 sprintf(path, "%s/%s", path, conf_name);
2125 conf_nodeoffset = fdt_path_offset((void *)bundle_addr, path);
2126 if( conf_nodeoffset < 0 ) {
2127 printf("ERROR: %s node not found in bundle!\n", conf_name);
2128 return ret;
2129 }
2130
2131 /* Get actual name of fit node for bundle component */
2132 *bin_name = fdt_getprop( (void *)bundle_addr, conf_nodeoffset, name, &len);
2133 if( !*bin_name ) {
2134 printf("INFO: %s not found in configuration %s ...skipping!\n", name, conf_name);
2135 return ret;
2136 }
2137
2138 /* Retrieve node offset for bundle component */
2139 sprintf(path, "/images/%s", *bin_name);
2140 nodeoffset = fdt_path_offset((void *)bundle_addr, path);
2141 if( nodeoffset < 0 ) {
2142 printf("ERROR: %s node not found in bundle!\n", path);
2143 return ret;
2144 }
2145
2146 /* Get location and size of binary's data */
2147 fit_image_get_data_and_size((void *)bundle_addr, nodeoffset, (const void**)addr, size);
2148 if( !*size ) {
2149 printf("ERROR: %s data not found in bundle!\n", *bin_name);
2150 return ret;
2151 }
2152 return 0;
2153 }
2154
2155 static int update_flash_parts_from_loader_bin( ulong loader_addr, ulong loader_size ) {
2156 env_t *ep;
2157 uint32_t calc_crc;
2158 char *envbuf = NULL;
2159 uint32_t *envintp;
2160 int ret = -2;
2161 int i;
2162 loff_t off;
2163 size_t rdlen;
2164 uint32_t magichdr[3];
2165 char cmd[128];
2166
2167 /* Search loader in memory for env headers */
2168 for (off = 0; off < (loff_t)env_boot_magic_search_size(); off += 4096) {
2169 /* Search loader bin for environment */
2170 rdlen = 12;
2171 memcpy((char*)magichdr, (char*)loader_addr + off, rdlen);
2172 if (magichdr[0] != BOOT_MAGIC_MAGIC) {
2173 continue;
2174 } else {
2175 /* Verify CRC */
2176 rdlen = magichdr[1];
2177 ep = (env_t *) ((char*)loader_addr + off + 8);
2178 calc_crc = the_env_crc32(0, ep->data, rdlen - 4);
2179 if( ep->crc == calc_crc ) {
2180 break;
2181 } else {
2182 continue;
2183 }
2184 }
2185 }
2186
2187 /* Set runtime env variables based on loader's env */
2188 if( off < (loff_t)env_boot_magic_search_size() ) {
2189
2190 /* read IMAGE variable */
2191 sprintf(cmd, "env import %lx - IMAGE", (char*)ep);
2192 run_command(cmd, 0);
2193
2194 /* Verify */
2195 if( env_get("IMAGE") == NULL ) {
2196 printf("ERROR! Failed to import IMAGE parameter from loader!\n");
2197 return ret;
2198 }
2199
2200 /* read default_partitions */
2201 if( ( strcasecmp(get_image_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
2202 sprintf(cmd, "env import %lx - default_partitions", (char*)ep);
2203 run_command(cmd, 0);
2204
2205 /* Verify */
2206 if( env_get("default_partitions") == NULL ) {
2207 printf("ERROR! Failed to import default_partitions parameter from loader!\n");
2208 return ret;
2209 }
2210 }
2211
2212 /* Call partition init code */
2213 printf("INFO: flash partition config updated. Repartitioning flash!\n");
2214 ret = board_init_flash_parts(1);
2215 } else {
2216 printf("ERROR!: No environment found in loader binary!\n");
2217 }
2218 return ret;
2219 }
2220
2221 int flash_upgrade_img_bundle( ulong bundle_addr , int img_index, const char * conf_name)
2222 {
2223 char path[128];
2224 ulong addr=0;
2225 ulong size=0;
2226 ulong loader_addr=0;
2227 ulong loader_size=0;
2228 int i=0;
2229 int err = 0;
2230 const char * bin_name;
2231 const char * loader_bin_name;
2232 const char * compat_str;
2233 char *compat_copy;
2234 int nodeoffset = 0;
2235 int conf_nodeoffset = 0;
2236 int max_entries = sizeof(fn_table)/sizeof(flashfn_table_entry);
2237 int len;
2238
2239 /* verify hashes of all upgrade bundle contents */
2240 if( fit_all_image_verify((void *)bundle_addr) ) {
2241
2242 /* Get offset of config node */
2243 sprintf(path, "/configurations");
2244 nodeoffset = fdt_path_offset((void *)bundle_addr, path);
2245 if( nodeoffset < 0 ) {
2246 printf("ERROR: %s node not found in bundle!\n", path);
2247 return CMD_RET_FAILURE;
2248 }
2249
2250 /* If configuration is specifed then use it */
2251 if( !conf_name ) {
2252 /* Get name of the default configuration */
2253 conf_name = fdt_getprop((void *)bundle_addr, nodeoffset, "default", &len);
2254 if( !conf_name ) {
2255 printf("ERROR: Default configuration not found in bundle!\n");
2256 return CMD_RET_FAILURE;
2257 }
2258 }
2259
2260 /* Get offset of selected configurations fit node */
2261 sprintf(path, "%s/%s", path, conf_name);
2262 conf_nodeoffset = fdt_path_offset((void *)bundle_addr, path);
2263 if( conf_nodeoffset < 0 ) {
2264 printf("ERROR: %s node not found in bundle!\n", conf_name);
2265 return CMD_RET_FAILURE;
2266 }
2267
2268 /* Verify compatibility */
2269 compat_str = fdt_getprop( (void *)bundle_addr, conf_nodeoffset, "compatible", &len);
2270 if( !compat_str ) {
2271 printf("Error: 'compatible' node not found in bundle!\n");
2272 return CMD_RET_FAILURE;
2273 }
2274
2275 compat_copy = malloc(strlen(compat_str)+1);
2276 if(!compat_copy)
2277 {
2278 printf("Error allocating memory for compatibility string!\n");
2279 return CMD_RET_FAILURE;
2280 }
2281 strcpy(compat_copy, compat_str);
2282
2283 if( verify_compat_string(compat_copy) ) {
2284 printf("Error: Bundle is not compatible with platform!\n");
2285 free(compat_copy);
2286 return CMD_RET_FAILURE;
2287 }
2288 free(compat_copy);
2289
2290 /* Decide whether we want to reformat partitions based on loader
2291 * binaries partition configuration configuration */
2292 if( NULL == env_get("IMAGE") ) {
2293 printf("WARNING: IMAGE env variable missing! Using IMAGE from loader binary!\n");
2294 if( get_binary_from_bundle(bundle_addr, conf_name, "loader",
2295 &loader_bin_name, &loader_addr, &loader_size) == 0 ) {
2296 printf("INFO: Reformatting flash media based on new loader binary\n");
2297 if( update_flash_parts_from_loader_bin( loader_addr, loader_size ) ) {
2298 printf("ERROR: Failed to reformat flash based loader binary!\n");
2299 return CMD_RET_FAILURE;
2300 }
2301
2302 /* Set flag to prevent sync of run-time env to loader bin */
2303 disable_runtime_env_sync = 1;
2304 } else {
2305 printf("ERROR! No loader binary AND IMAGE parameter not set!\n");
2306 return CMD_RET_FAILURE;
2307 }
2308 } else if (env_get_hex("reformatOnUpgrade", 0)) {
2309 printf("INFO: Reformatting partitions because reformatOnUpgrade == 1!\n");
2310 err = board_init_flash_parts(1);
2311 env_set("reformatOnUpgrade", NULL);
2312 }
2313
2314 for( i=0; i<max_entries && !err; i++ ) {
2315 /* Parse loader only if it has not been parsed before */
2316 if( (strcmp(fn_table[i].name,"loader") == 0 ) && loader_addr && loader_size ) {
2317 bin_name = loader_bin_name;
2318 size = loader_size;
2319 addr = loader_addr;
2320 } else {
2321 if (get_binary_from_bundle( bundle_addr, conf_name, fn_table[i].name,
2322 &bin_name, &addr, &size ) ) {
2323 continue;
2324 }
2325 }
2326
2327 /* Calling flashing function */
2328 printf("Flashing %s (%s: 0x%lx bytes from 0x%lx) to %s%d.....\n",
2329 fn_table[i].name, bin_name, size, addr, fn_table[i].name,
2330 (strcmp(fn_table[i].name,"loader")?img_index:0));
2331 err = fn_table[i].func(addr, size, img_index);
2332 }
2333
2334 /* Reset flag */
2335 disable_runtime_env_sync = 0;
2336 } else {
2337 err = CMD_RET_FAILURE;
2338 }
2339
2340 return err;
2341 }
2342
2343 static int do_flash_upgrade_img (cmd_tbl_t * cmdtp, int flag, int argc,
2344 char *const argv[])
2345 {
2346 char cmd[128];
2347 ulong bundle_addr=0;
2348 int err = CMD_RET_FAILURE;
2349 const char * conf_name = NULL;
2350 int img_index = 0;
2351 bool download = true;
2352 bool commit = true;
2353 int active_img_idx = get_active_img_idx();
2354
2355 /* Parse and remove the optional skip argument */
2356 if ( argc > 1) {
2357 if ( !strcmp(argv[1], "-s")) {
2358 download = false;
2359 argc--;
2360 argv++;
2361 } else if ( !strcmp(argv[1], "-i")) {
2362 commit = false;
2363 argc--;
2364 argv++;
2365 }
2366 }
2367
2368 if( argc == 2 ) {
2369 img_index = get_img_index_for_upgrade(0);
2370 } else if( argc > 2 ) {
2371 if( strlen(argv[2]) == 1 )
2372 img_index = *argv[2] - '0';
2373 else {
2374 conf_name = argv[2];
2375 img_index = get_img_index_for_upgrade(0);
2376 }
2377
2378 if( argc > 3 ) {
2379 conf_name = argv[3];
2380 }
2381 }
2382
2383 if( img_index < MIN_IMG_INDEX || img_index > MAX_IMG_INDEX ) {
2384 printf("ERROR: Invalid Image Index specified!\n");
2385 return CMD_RET_USAGE;
2386 }
2387
2388 if (download)
2389 sprintf(cmd, "tftp %lx %s", load_addr, argv[1]);
2390
2391 if( !download || run_command(cmd, 0) == 0 ) {
2392 bundle_addr = env_get_hex("fileaddr", 0);
2393
2394 if (bundle_addr)
2395 /* Call main img flashing function */
2396 err = flash_upgrade_img_bundle(bundle_addr, img_index, conf_name);
2397 }
2398
2399 if(err) {
2400 printf("ERROR: Image upgrade failed!!\n");
2401 } else {
2402 printf("INFO: Image upgrade successfull!!\n");
2403 if( commit ) {
2404 printf("INFO: Committing Image!!\n");
2405 commit_image( img_index );
2406
2407 /* Handle bootstrap condition */
2408 if( active_img_idx == ACTIVE_IMGIDX_BOOTSTRAP ) {
2409 /* Now that we have a valid image flashed, change active image index */
2410 set_active_img_idx(img_index);
2411 }
2412 } else {
2413 printf("INFO: Not Committing Image!!\n");
2414 }
2415 }
2416
2417 return err;
2418 }
2419
2420 static int do_restoredefault(cmd_tbl_t * cmdtp, int flag, int argc,
2421 char *const argv[])
2422 {
2423 int ret = -1;
2424 if( strcmp(get_image_media(), FLASH_DEV_STR_NAND) == 0 ) {
2425 #ifdef BCA_SDK_NAND_CMD
2426 ret = nand_restoredefault();
2427 #endif
2428 }
2429
2430 if( ret && ( strcmp(get_image_media(), FLASH_DEV_STR_EMMC) == 0 ) ) {
2431 #ifdef BCA_SDK_EMMC_CMD
2432 ret = emmc_restoredefault();
2433 #endif
2434 }
2435
2436 if( ret && ( strcmp(get_image_media(), FLASH_DEV_STR_SPINOR) == 0 ) ) {
2437 #ifdef BCA_SDK_SPINOR_CMD
2438 ret = spinor_restoredefault();
2439 #endif
2440 }
2441
2442 return ret;
2443 }
2444
2445 static int do_metadata(cmd_tbl_t * cmdtp, int flag, int argc,
2446 char *const argv[])
2447 {
2448 int ret = -1;
2449 int committed = 0;
2450 int valid[2] = {0,0};
2451 int seq[2] = {-1,-1};
2452 int status = get_metadata_val(&committed, valid, seq);
2453
2454 if (argc == 1) {
2455 if (0 == status) {
2456 printf("committed-img: %d valid-imgs: ", committed);
2457 if( valid[0] )
2458 printf("%d", valid[0]);
2459 if( valid[1] )
2460 printf("%d", valid[1]);
2461 printf(", seq# img 1: %d, img2: %d\n\n", seq[0], seq[1]);
2462 ret = 0;
2463 } else {
2464 printf("metadata parse error\n");
2465 }
2466 } else if (argc == 3) {
2467 committed = atoi(argv[1]);
2468 valid[0] = atoi(strtok(argv[2],","));
2469 valid[1] = atoi(strtok(NULL,","));
2470
2471 if (0 != set_metadata_val(&committed, valid, seq)) {
2472 printf("metadata parse error\n");
2473 } else {
2474 ret = 0;
2475 }
2476 }
2477 return ret;
2478 }
2479
2480 #if defined(CONFIG_BCM_BOOTSTATE)
2481 static int do_activate(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
2482 {
2483 bcmbca_set_boot_reason(BCM_BOOT_REASON_ACTIVATE);
2484 run_command("reset", 0);
2485 return 0;
2486 }
2487 #endif
2488
2489 static int do_force(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
2490 {
2491 int ret = 0;
2492 if( argc > 1 ) {
2493 if( atoi(argv[1]) == 1 ) {
2494 if( (argc == 4)
2495 && ( ( strcasecmp(argv[2], FLASH_DEV_STR_NAND) == 0 )
2496 || ( strcasecmp(argv[2], FLASH_DEV_STR_SPINOR) == 0 )
2497 || ( strcasecmp(argv[2], FLASH_DEV_STR_EMMC) == 0 ) )
2498 && ( ( strcasecmp(argv[3], FLASH_DEV_STR_NAND) == 0 )
2499 || ( strcasecmp(argv[3], FLASH_DEV_STR_SPINOR) == 0 )
2500 || ( strcasecmp(argv[3], FLASH_DEV_STR_EMMC) == 0 ) ) ) {
2501 forced_updates = 1;
2502 strcpy(forced_boot_media,argv[2]);
2503 strcpy(forced_image_media,argv[3]);
2504 } else if(argc == 2) {
2505 forced_updates = 1;
2506 } else {
2507 ret = CMD_RET_USAGE;
2508 printf("Cannot determine boot/image flash type, please specify flash types!\n");
2509 }
2510 } else {
2511 forced_updates = 0;
2512 forced_boot_media[0] = '\0';
2513 forced_image_media[0] = '\0';
2514 }
2515 }
2516
2517 printf("Forced Image Updates: %s, Forced flash types: Boot=%s, Image=%s\n",
2518 (forced_updates?"Enabled":"Disabled"),
2519 (forced_updates?forced_boot_media:"NOT SPECIFIED"),
2520 (forced_updates?forced_image_media:"NOT SPECIFIED"));
2521
2522 return ret;
2523 }
2524
2525 #ifdef CONFIG_BCMBCA_HTTPD
2526 static int do_httpd_start(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
2527 {
2528 if(!httpd_check_net_env())
2529 register_cli_job_cb(0, http_poll);
2530 return 0;
2531 }
2532 #endif
2533
2534 #ifdef CONFIG_BCMBCA_PMC
2535 static int do_bpcm_cmd(cmd_tbl_t * cmdtp, int flag, int argc,
2536 char *const argv[])
2537 {
2538 int err = CMD_RET_USAGE;
2539 int read = 0;
2540 u32 addr, off, data;
2541
2542 if ((argc != 5) && (argc != 4))
2543 return err;
2544
2545 if (!strcmp(argv[1], "r"))
2546 read = 1;
2547 else if (!strcmp(argv[1], "w"))
2548 read = 0;
2549 else
2550 return err;
2551
2552 addr = atoi(argv[2]);
2553 off = atoi(argv[3]);
2554 if (!read) {
2555 data = atoi(argv[4]);
2556 err = WriteBPCMRegister(addr, off>>2, data);
2557 printf("bpcm write data 0x%x to addr 0x%x offset 0x%x ret %d\n",
2558 data, addr, off, err);
2559 } else {
2560 err = ReadBPCMRegister(addr, off>>2, &data);
2561 printf("bpcm read data 0x%x from addr 0x%x offset 0x%x ret %d\n",
2562 data, addr, off, err);
2563 }
2564
2565
2566 return err;
2567 }
2568
2569 static int do_cpufreq(cmd_tbl_t * cmdtp, int flag, int argc,
2570 char *const argv[])
2571 {
2572 int err = CMD_RET_USAGE, freqMHz;
2573
2574 if (argc != 2)
2575 return err;
2576
2577 err = CMD_RET_SUCCESS;
2578 freqMHz = atoi(argv[1]);
2579 freqMHz = set_cpu_freq(freqMHz);
2580 if (freqMHz > 0)
2581 printf("cpu freq set to %dMHz\n", freqMHz);
2582 else
2583 err = CMD_RET_FAILURE;
2584
2585 return err;
2586 }
2587 #endif
2588
2589 static int do_dev_spec_key(cmd_tbl_t * cmdtp, int flag, int argc,
2590 char *const argv[])
2591 {
2592 int err = CMD_RET_USAGE;
2593 int rc, len;
2594 u32 dev_spec_key[8];
2595 int i;
2596 bool force = false;
2597
2598 if ( (argc == 2) && (strcmp(argv[1], "get") == 0)) {
2599 rc = bcm_sec_get_dev_spec_key((char*)dev_spec_key, sizeof(u32)*8);
2600 } else if ( (argc >= 10) && (strcmp(argv[1], "set") == 0)) {
2601 /* Parse and remove the optional FORCE argument */
2602 if( argc > 10 ) {
2603 if ( !strcasecmp(argv[2], "-f")) {
2604 force = true;
2605 argc--;
2606 argv++;
2607 }
2608 }
2609
2610 for(i=0; i<8; i++) {
2611 dev_spec_key[i] = simple_strtoul(argv[i+2],NULL, 0);
2612 }
2613 if ( !force ) {
2614 printf("WARNING: You are attempting to set a new device specific key.\n");
2615 len = cli_readline("This operation cannot be undone, enter 'Y' to continue: ");
2616 if( !len || console_buffer[0] != 'Y' ) {
2617 printf("Device specific key setting aborted.\n");
2618 return CMD_RET_SUCCESS;
2619 }
2620 }
2621 rc = bcm_sec_set_dev_spec_key((char*)dev_spec_key, sizeof(u32)*8);
2622 } else {
2623 return err;
2624 }
2625
2626 if (rc == 0) {
2627 printf("Current Device Specific Key:\n");
2628 for( i=0; i<8; i++ ) {
2629 printf(" [%d]0x%08x\n", i, dev_spec_key[i]);
2630 }
2631 printf("\n\n");
2632 err = CMD_RET_SUCCESS;
2633 } else {
2634 err = CMD_RET_FAILURE;
2635 }
2636
2637 return err;
2638 }
2639
2640 static int do_sec_ser_num(cmd_tbl_t * cmdtp, int flag, int argc,
2641 char *const argv[])
2642 {
2643 int err = CMD_RET_USAGE;
2644 int rc, len;
2645 u32 sec_ser_num[8] = {0};
2646 char * sec_ser_num_ptr = (char*)&sec_ser_num[0];
2647 char * sec_ser_num_char_array;
2648 char byte_buf[3] = {0};
2649 int i,j;
2650 bool force = false;
2651 bool is_set = false;
2652 bool is_odd = false;
2653
2654 if ( (argc == 2) && (strcmp(argv[1], "get") == 0)) {
2655 rc = bcm_sec_get_sec_ser_num((char*)sec_ser_num, sizeof(u32)*8);
2656 } else if ( (argc >= 3) && (strcmp(argv[1], "set") == 0)) {
2657 is_set = true;
2658 /* Parse and remove the optional FORCE argument */
2659 if( argc == 4 ) {
2660 if ( !strcasecmp(argv[2], "-f")) {
2661 force = true;
2662 argc--;
2663 argv++;
2664 }
2665 }
2666
2667 /* Check if byte array exceeds 32 bytes OR contains an ODD number of characters */
2668 sec_ser_num_char_array = argv[2];
2669
2670 /* Skip leading 0x if present */
2671 if( sec_ser_num_char_array[1] == 'x' || sec_ser_num_char_array[1] == 'X' )
2672 sec_ser_num_char_array += 2;
2673
2674 debug("sernum:%s len:%d\n", sec_ser_num_char_array, (int)strlen(sec_ser_num_char_array));
2675 if( ((strlen(sec_ser_num_char_array)/2) > sizeof(sec_ser_num)) || (strlen(sec_ser_num_char_array) % 2)){
2676 return CMD_RET_USAGE;
2677 }
2678
2679 /* Check if there is an odd number of digits so that we can insert an extra zero */
2680 if( strlen(sec_ser_num_char_array) % 2 )
2681 is_odd = 1;
2682
2683 for(i=0,j=sizeof(sec_ser_num)-strlen(sec_ser_num_char_array)/2;
2684 i<strlen(sec_ser_num_char_array),j<sizeof(sec_ser_num); j++){
2685 if( is_odd && (i == 0) ) {
2686 byte_buf[1] = sec_ser_num_char_array[i];
2687 is_odd = false;
2688 i++;
2689 } else {
2690 memcpy(byte_buf,&sec_ser_num_char_array[i], 2);
2691 i += 2;
2692 }
2693
2694 sec_ser_num_ptr[j] = simple_strtoul(byte_buf,NULL,16);
2695 debug("byte_buf: %s 0x%02x\n", byte_buf, sec_ser_num_ptr[j]);
2696 }
2697
2698 if ( !force ) {
2699 printf("WARNING: You are attempting to set a new secure serial number.\n");
2700 len = cli_readline("This operation cannot be undone, enter 'Y' to continue: ");
2701 if( !len || console_buffer[0] != 'Y' ) {
2702 printf("secure serial number setting aborted.\n");
2703 return CMD_RET_SUCCESS;
2704 }
2705 }
2706 rc = bcm_sec_set_sec_ser_num((char*)sec_ser_num, sizeof(u32)*8);
2707 } else {
2708 return err;
2709 }
2710
2711 if (rc == 0) {
2712 if( is_set )
2713 printf("Set Secure Serial Number as:\n");
2714 else
2715 printf("Current Secure Serial Number:\n");
2716
2717 printf(" [");
2718 for( i=0; i<sizeof(sec_ser_num); i++ ) {
2719 printf("%02x", sec_ser_num_ptr[i]);
2720 }
2721 printf("]\n");
2722
2723 printf("In memory represenation:\n");
2724 for( i=0; i<8; i++ ) {
2725 printf(" [%d]0x%08x\n", i, sec_ser_num[i]);
2726 }
2727 printf("\n\n");
2728 err = CMD_RET_SUCCESS;
2729 } else {
2730 err = CMD_RET_FAILURE;
2731 }
2732
2733 return err;
2734 }
2735 static int do_antirollback(cmd_tbl_t * cmdtp, int flag, int argc,
2736 char *const argv[])
2737 {
2738 int err = CMD_RET_USAGE;
2739 int rc, len;
2740 u32 lvl;
2741 bool force = false;
2742
2743
2744 if ( (argc == 2) && (strcmp(argv[1], "get") == 0)) {
2745 rc = bcm_sec_get_antirollback_lvl(&lvl);
2746 } else if ( (argc >= 3) && (strcmp(argv[1], "set") == 0)) {
2747 /* Parse and remove the optional FORCE argument */
2748 if( argc > 3 ) {
2749 if ( !strcasecmp(argv[2], "-f")) {
2750 force = true;
2751 argc--;
2752 argv++;
2753 }
2754 }
2755
2756 /* get level */
2757 lvl = atoi(argv[2]);
2758 if ( !force ) {
2759 printf("WARNING: You are attempting to set a new anti-rollback level.\n");
2760 len = cli_readline("This operation cannot be undone, enter 'Y' to continue: ");
2761 if( !len || console_buffer[0] != 'Y' ) {
2762 printf("Anti-rollback level setting aborted.\n");
2763 return CMD_RET_SUCCESS;
2764 }
2765 }
2766 rc = bcm_sec_set_antirollback_lvl(lvl);
2767 } else {
2768 return err;
2769 }
2770
2771 if (rc == 0) {
2772 printf("Current anti-rollback level set to: %d\n", lvl);
2773 err = CMD_RET_SUCCESS;
2774 } else {
2775 err = CMD_RET_FAILURE;
2776 }
2777
2778 return err;
2779 }
2780
2781 #ifdef CONFIG_BCMBCA_XRDP_ETH
2782 extern int bcmbca_xrdp_eth_phy_status(void);
2783 extern int bcmbca_xrdp_eth_mac_status(void);
2784 extern int bcmbca_xrdp_eth_active_port_get(void);
2785 extern int bcmbca_xrdp_eth_active_port_set(int port);
2786 extern int bcmbca_xrdp_eth_env_active_port_set(int port);
2787
2788 static int do_eth_active_port(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
2789 {
2790 int port;
2791
2792 if (argc == 2)
2793 {
2794 port = (atoi(argv[1]));
2795 bcmbca_xrdp_eth_active_port_set(port);
2796 }
2797
2798 port = bcmbca_xrdp_eth_active_port_get();
2799 printf("XRDP Ethernet active port is set to %d\n" ,port);
2800
2801 return 0;
2802 }
2803
2804 static int on_active_port(const char *name, const char *value, enum env_op op, int flags)
2805 {
2806 int active_port = -1;
2807
2808 if ((flags & H_INTERACTIVE) == 0)
2809 return 0;
2810
2811 switch (op) {
2812 case env_op_create:
2813 case env_op_overwrite:
2814 active_port = simple_strtoul(value, NULL, 10);
2815 break;
2816 case env_op_delete:
2817 break;
2818 default:
2819 break;
2820 }
2821
2822 return bcmbca_xrdp_eth_env_active_port_set(active_port);
2823 }
2824 U_BOOT_ENV_CALLBACK(active_port, on_active_port);
2825 #endif
2826
2827 static char usage[] =
2828 #ifdef BCA_SDK_EMMC_CMD
2829 "\n## eMMC Specific Test Commands ##\n"
2830 "gpt_fixup\n"
2831 " - Create GPT partitions if partition sizes are specfied via special uboot\n"
2832 " - environment variables. The env variable name has to be in the format:\n"
2833 " - <partition_name>_vol_size=<size in MiB>\n"
2834 #endif /* BCA_SDK_EMMC_CMD */
2835 #ifdef BCA_SDK_SPINOR_CMD
2836 "\n## SPINOR Specific Test Commands ##\n"
2837 "flash_spinor_fit\n"
2838 " - Download and flash atf+uboot+vmlinux+dtb in brcm_full.itb to SPI NOR flash \n"
2839 "flash_spinor_rootfs\n"
2840 " - Download and flash rootfs in rootfs.squashfs to SPI NOR flash\n"
2841 "flash_spinor_upgrade [-s] <filename> [conf]\n"
2842 "flash_spinor_upgrade <filename> [<img> [<conf>]]\n"
2843 " - Download and flash an image upgrade bundle to SPI NOR flash\n"
2844 "flash_spinor_binary <filename> \n"
2845 " - Erase whole flash,download and flash a binary image to SPI NOR flash start from 0\n"
2846 "boot_spinor [boardid]\n"
2847 " - Boot linux from image in SPI NOR flash.\n"
2848 #endif
2849 "\n## Generic Test Commands ##\n"
2850 "force \n"
2851 " - Without arguments, display if forced image updates are enabled\n"
2852 "force [force value] <[Boot Flash Type] [Image Flash Type]>\n"
2853 " - Enable(value=1)/Disable(value=0) forced image updates. All compatibility checks are ignored if enabled\n"
2854 " - If boot and image flash types are not detected, then they need to be specified as 2nd and 3rd args\n"
2855 " - Valid flash type values = [NAND|SPINAND|EMMC|NOR]\n"
2856 "restoredefault\n"
2857 " - Delete contents of /data so that it gets populated with default values\n"
2858 "flash_loader\n"
2859 " - Download and flash SPL+TPL in loader_test_<flash>_<chip>.bin to boot flash\n"
2860 #if defined(BCA_SDK_NAND_CMD) || defined(BCA_SDK_EMMC_CMD)
2861 "flash_bootfs_raw <bootfs binary> [img]\n"
2862 "flash_rootfs_raw <rootfs binary> [img]\n"
2863 " - Download and flash raw bootfs/rootfs binary to flash \n"
2864 " - WARNING: These are raw writes with no content, security or compatibility checks. Metadata is NOT updated \n"
2865 "metadata \n"
2866 "metadata [committed] [valid],[valid]\n"
2867 " - without arguments, parse and display metadata\n"
2868 " - set metadata values (example \"metadata 1 1,2\" for both images valid and #1 committed)\n"
2869 " - NOTE: Must do a sw reset for metadata changes to take affect\n"
2870 #endif
2871 "flash_img_upgrade [-s] <filename> [conf]\n"
2872 "flash_img_upgrade [-i] <filename> [<img> [<conf>]]\n"
2873 " - Download and flash an image upgrade bundle via TFTP\n"
2874 " - NOTE: Must do a sw reset to use the new image\n"
2875 "load_img [boardid]\n"
2876 "load_img [<img> [<boardid>]]\n"
2877 " - Load image from flash into DDR.\n"
2878 "boot_img [boardid]\n"
2879 "boot_img [<img> [<boardid>]]\n"
2880 " - Boot linux from image in flash.\n"
2881 "[Legend - Optional Parameters]\n"
2882 " -s: Skip downloading the image via tftp. Assume it is already at ${fileaddr}\n"
2883 " -i: Inactive. Do not change activation state of new image i.e do not commit image\n"
2884 " img: Image index for flashing/booting. Valid values: [1|2]. Default index is determined from metadata\n"
2885 " fstype: Filesystem type for flashing. Valid values: [squashfs|ubifs|ext4]. Default is squashfs\n"
2886 " boardid: Boardid to determine boot configuration. If omitted default configuration node is used\n"
2887 " conf: Configuration name used for flashing img bundle. If omitted default configuration node is used\n\n"
2888 #ifdef CONFIG_BCMBCA_HTTPD
2889 "httpd_start \n"
2890 " - without arguments, start httpd server\n"
2891 #endif
2892 #ifdef CONFIG_BCMBCA_PMC
2893 "bpcm_cmd <r|w> <addr> <offset> [<data>]\n"
2894 " - read/write bpcm register\n"
2895 "cpufreq <freq in MHz>\n"
2896 " - set cpu frequency\n"
2897 #endif
2898 "antirollback get\n"
2899 " - get current anti-rollback level\n"
2900 "antirollback set [-f] <new anti-rollback level to set>\n"
2901 " - set new anti-rollback level. [-f] will force the commit and skip warnings\n"
2902 "sec_ser_num get \n"
2903 " - get current secure serial number level ( 64 digits )\n"
2904 "sec_ser_num set [-f] < Hex secure serial number ( Max 64 digits )>\n"
2905 " - set new secure serial number . [-f] will force the commit and skip warnings\n"
2906 "dev_spec_key get \n"
2907 " - get current device specific key ( 32 bytes )\n"
2908 "dev_spec_key set [-f] <32-bit hex word 0>...<32-bit hex word 7> \n"
2909 " - set new device specific key. [-f] will force the commit and skip warnings\n"
2910 ;
2911
2912 static char sdk_usage[] =
2913 "\nforce\n"
2914 " - Without arguments, display if forced image updates are enabled\n"
2915 "force [force value] <[Boot Flash Type] [Image Flash Type]>\n"
2916 " - Enable(value=1)/Disable(value=0) forced image updates. All compatibility checks are ignored if enabled\n"
2917 " - If boot and image flash types are not detected, then they need to be specified as 2nd and 3rd args\n"
2918 " - Valid flash type values = [NAND|SPINAND|EMMC|NOR]\n"
2919 "restoredefault\n"
2920 " - Delete contents of /data so that it gets populated with default values\n"
2921 #if defined(BCA_SDK_NAND_CMD) || defined(BCA_SDK_EMMC_CMD)
2922 "metadata \n"
2923 "metadata [committed] [valid],[valid]\n"
2924 " - without arguments, parse and display metadata\n"
2925 " - set metadata values (example \"metadata 1 1,2\" for both images valid and #1 committed)\n"
2926 " - NOTE: Must do a sw reset for metadata changes to take affect\n"
2927 #endif
2928 "flash_img_upgrade [-s] <filename> [conf]\n"
2929 "flash_img_upgrade [-i] <filename> [<img> [<conf>]]\n"
2930 " - Download and flash an image upgrade bundle via TFTP\n"
2931 " - NOTE: Must do a sw reset to use the new image\n"
2932 "load_img [boardid]\n"
2933 "load_img [<img> [<boardid>]]\n"
2934 " - Load image from flash into DDR.\n"
2935 "boot_img [boardid]\n"
2936 "boot_img [<img> [<boardid>]]\n"
2937 " - Boot linux from image in flash.\n"
2938 "[Legend - Optional Parameters]\n"
2939 " -s: Skip downloading the image via tftp. Assume it is already at ${fileaddr}\n"
2940 " -i: Inactive. Mark new image as inactive i.e do not commit image\n"
2941 " img: Image index for flashing/booting. Valid values: [1|2]. Default index is determined from metadata\n"
2942 " boardid: Boardid to determine boot configuration. If omitted default configuration node is used\n"
2943 " conf: Configuration name used for flashing img bundle. If omitted default configuration node is used\n\n"
2944 #ifdef CONFIG_BCMBCA_HTTPD
2945 "httpd_start \n"
2946 " - without arguments, start httpd server\n"
2947 #endif
2948 #ifdef CONFIG_BCMBCA_XRDP_ETH
2949 "active_port [port]\n"
2950 " - Set the active network driver's port to send packets from\n"
2951 " - without arguments, display the current active port\n"
2952 "eth_status [type]\n"
2953 " - Print the XRDP Ethernet network driver status tables\n"
2954 " - Argument can be phy or mac. If no argument provided, both tables will be printed\n"
2955 #endif
2956 ;
2957
2958 U_BOOT_CMD_WITH_SUBCMDS(bca_test, "Broadcom test commands", usage,
2959 U_BOOT_SUBCMD_MKENT(flash_loader, 1, 0, do_flash_loader),
2960 #ifdef BCA_SDK_EMMC_CMD
2961 U_BOOT_SUBCMD_MKENT(gpt_fixup, 1, 0, do_gpt_fixup),
2962 #endif /* BCA_SDK_EMMC_CMD */
2963 #ifdef BCA_SDK_SPINOR_CMD
2964 U_BOOT_SUBCMD_MKENT(flash_spinor_fit, 1, 0, do_flash_spinor_bootfs_rootfs),
2965 U_BOOT_SUBCMD_MKENT(flash_spinor_rootfs, 1, 0, do_flash_spinor_bootfs_rootfs),
2966 U_BOOT_SUBCMD_MKENT(flash_spinor_upgrade, 5, 0, do_flash_upgrade_img),
2967 U_BOOT_SUBCMD_MKENT(flash_spinor_binary, 2, 0, do_flash_spinor_binary),
2968 U_BOOT_SUBCMD_MKENT(boot_spinor, 3, 0, do_boot),
2969 #endif
2970 #if defined(CONFIG_BCM_BOOTSTATE)
2971 U_BOOT_SUBCMD_MKENT(activate, 1, 0, do_activate),
2972 #endif /* CONFIG_BCM_BOOTSTATE */
2973 U_BOOT_SUBCMD_MKENT(force, 4, 0, do_force),
2974 U_BOOT_SUBCMD_MKENT(restoredefault, 1, 0, do_restoredefault),
2975 #if defined(BCA_SDK_NAND_CMD) || defined(BCA_SDK_EMMC_CMD)
2976 U_BOOT_SUBCMD_MKENT(flash_bootfs_raw, 3, 0, do_flash_bins),
2977 U_BOOT_SUBCMD_MKENT(flash_rootfs_raw, 3, 0, do_flash_bins),
2978 U_BOOT_SUBCMD_MKENT(metadata, 5, 0, do_metadata),
2979 #endif
2980 U_BOOT_SUBCMD_MKENT(flash_img_upgrade, 5, 0, do_flash_upgrade_img),
2981 U_BOOT_SUBCMD_MKENT(boot_img, 3, 0, do_boot)
2982 #ifdef CONFIG_BCMBCA_HTTPD
2983 ,U_BOOT_SUBCMD_MKENT(httpd_start, 1, 0, do_httpd_start)
2984 #endif
2985 #ifdef CONFIG_BCMBCA_PMC
2986 ,U_BOOT_SUBCMD_MKENT(bpcm_cmd, 5, 0, do_bpcm_cmd)
2987 ,U_BOOT_SUBCMD_MKENT(cpufreq, 2, 0, do_cpufreq)
2988 #endif
2989 ,U_BOOT_SUBCMD_MKENT(antirollback, 4, 0, do_antirollback)
2990 ,U_BOOT_SUBCMD_MKENT(sec_ser_num, 12, 0, do_sec_ser_num)
2991 ,U_BOOT_SUBCMD_MKENT(dev_spec_key, 12, 0, do_dev_spec_key)
2992 );
2993
2994 U_BOOT_CMD_WITH_SUBCMDS(sdk, "Broadcom SDK support commands", sdk_usage,
2995 U_BOOT_SUBCMD_MKENT(force, 4, 0, do_force),
2996 U_BOOT_SUBCMD_MKENT(restoredefault, 1, 0, do_restoredefault),
2997 #if defined(BCA_SDK_NAND_CMD) || defined(BCA_SDK_EMMC_CMD)
2998 U_BOOT_SUBCMD_MKENT(metadata, 5, 0, do_metadata),
2999 #endif
3000 U_BOOT_SUBCMD_MKENT(flash_img_upgrade, 5, 0, do_flash_upgrade_img),
3001 U_BOOT_SUBCMD_MKENT(boot_img, 3, 0, do_boot),
3002 U_BOOT_SUBCMD_MKENT(load_img, 3, 0, do_load)
3003 #ifdef CONFIG_BCMBCA_HTTPD
3004 ,U_BOOT_SUBCMD_MKENT(httpd_start, 1, 0, do_httpd_start)
3005 #endif
3006 #ifdef CONFIG_BCMBCA_XRDP_ETH
3007 ,U_BOOT_SUBCMD_MKENT(active_port, 2, 0, do_eth_active_port)
3008 #endif
3009 );
3010