1 /* 2 * (C) Copyright 2003 3 * Kyle Harris, kharris@nexus-tech.net 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 #include <common.h> 8 #include <command.h> 9 #include <console.h> 10 #include <mmc.h> 11 #include <optee_include/OpteeClientInterface.h> 12 #include <optee_include/OpteeClientApiLib.h> 13 #include <optee_test.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 static int curr_device = -1; 18 19 static void print_mmcinfo(struct mmc *mmc) 20 { 21 int i; 22 const char *timing[] = { 23 "Legacy", "High Speed", "High Speed", "SDR12", 24 "SDR25", "SDR50", "SDR104", "DDR50", 25 "DDR52", "HS200", "HS400", "HS400 Enhanced Strobe"}; 26 27 printf("Device: %s\n", mmc->cfg->name); 28 printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24); 29 printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff); 30 printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff, 31 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff, 32 (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff); 33 34 printf("Timing Interface: %s\n", timing[mmc->timing]); 35 printf("Tran Speed: %d\n", mmc->clock); 36 printf("Rd Block Len: %d\n", mmc->read_bl_len); 37 38 printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC", 39 EXTRACT_SDMMC_MAJOR_VERSION(mmc->version), 40 EXTRACT_SDMMC_MINOR_VERSION(mmc->version)); 41 if (EXTRACT_SDMMC_CHANGE_VERSION(mmc->version) != 0) 42 printf(".%d", EXTRACT_SDMMC_CHANGE_VERSION(mmc->version)); 43 printf("\n"); 44 45 printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No"); 46 puts("Capacity: "); 47 print_size(mmc->capacity, "\n"); 48 49 printf("Bus Width: %d-bit%s\n", mmc->bus_width, 50 mmc_card_ddr(mmc) ? " DDR" : ""); 51 52 puts("Erase Group Size: "); 53 print_size(((u64)mmc->erase_grp_size) << 9, "\n"); 54 55 if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4_41) { 56 bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0; 57 bool usr_enh = has_enh && (mmc->part_attr & EXT_CSD_ENH_USR); 58 59 puts("HC WP Group Size: "); 60 print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n"); 61 62 puts("User Capacity: "); 63 print_size(mmc->capacity_user, usr_enh ? " ENH" : ""); 64 if (mmc->wr_rel_set & EXT_CSD_WR_DATA_REL_USR) 65 puts(" WRREL\n"); 66 else 67 putc('\n'); 68 if (usr_enh) { 69 puts("User Enhanced Start: "); 70 print_size(mmc->enh_user_start, "\n"); 71 puts("User Enhanced Size: "); 72 print_size(mmc->enh_user_size, "\n"); 73 } 74 puts("Boot Capacity: "); 75 print_size(mmc->capacity_boot, has_enh ? " ENH\n" : "\n"); 76 puts("RPMB Capacity: "); 77 print_size(mmc->capacity_rpmb, has_enh ? " ENH\n" : "\n"); 78 79 for (i = 0; i < ARRAY_SIZE(mmc->capacity_gp); i++) { 80 bool is_enh = has_enh && 81 (mmc->part_attr & EXT_CSD_ENH_GP(i)); 82 if (mmc->capacity_gp[i]) { 83 printf("GP%i Capacity: ", i+1); 84 print_size(mmc->capacity_gp[i], 85 is_enh ? " ENH" : ""); 86 if (mmc->wr_rel_set & EXT_CSD_WR_DATA_REL_GP(i)) 87 puts(" WRREL\n"); 88 else 89 putc('\n'); 90 } 91 } 92 } 93 } 94 static struct mmc *init_mmc_device(int dev, bool force_init) 95 { 96 struct mmc *mmc; 97 mmc = find_mmc_device(dev); 98 if (!mmc) { 99 printf("no mmc device at slot %x\n", dev); 100 return NULL; 101 } 102 103 if (force_init) 104 mmc->has_init = 0; 105 if (mmc_init(mmc)) 106 return NULL; 107 return mmc; 108 } 109 static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 110 { 111 struct mmc *mmc; 112 113 if (curr_device < 0) { 114 if (get_mmc_num() > 0) 115 curr_device = 0; 116 else { 117 puts("No MMC device available\n"); 118 return 1; 119 } 120 } 121 122 mmc = init_mmc_device(curr_device, false); 123 if (!mmc) 124 return CMD_RET_FAILURE; 125 126 print_mmcinfo(mmc); 127 return CMD_RET_SUCCESS; 128 } 129 130 #ifdef CONFIG_OPTEE_CLIENT 131 static int do_mmc_test_secure_storage(cmd_tbl_t *cmdtp, 132 int flag, int argc, char * const argv[]) 133 { 134 #ifdef CONFIG_MMC 135 struct mmc *mmc; 136 137 if (curr_device < 0) { 138 if (get_mmc_num() > 0) { 139 puts("MMC device available\n"); 140 curr_device = 0; 141 } else { 142 puts("No MMC device available\n"); 143 return 1; 144 } 145 } 146 147 mmc = init_mmc_device(curr_device, false); 148 if (!mmc) 149 printf("No mmc device\n"); 150 #endif 151 152 int i, count = 100; 153 154 for (i = 1; i <= count; i++) { 155 if (test_secure_storage_default() == 0) { 156 printf("test_secure_storage_default success! %d/%d\n", i, count); 157 } else { 158 printf("test_secure_storage_default fail! %d/%d\n", i, count); 159 break; 160 } 161 if (test_secure_storage_security_partition() == 0) { 162 printf("test_secure_storage_security_partition success! %d/%d\n", i, count); 163 } else { 164 printf("test_secure_storage_security_partition fail! %d/%d\n", i, count); 165 break; 166 } 167 } 168 169 return CMD_RET_SUCCESS; 170 } 171 172 static int do_mmc_testefuse(cmd_tbl_t *cmdtp, 173 int flag, int argc, char * const argv[]) 174 { 175 uint32_t outbuf32[8]; 176 177 trusty_read_attribute_hash(outbuf32, 8); 178 179 printf(" 0x%x 0x%x 0x%x 0x%x \n", 180 outbuf32[0], outbuf32[1], outbuf32[2], outbuf32[3]); 181 printf(" 0x%x 0x%x 0x%x 0x%x \n", 182 outbuf32[4], outbuf32[5], outbuf32[6], outbuf32[7]); 183 184 return CMD_RET_SUCCESS; 185 } 186 187 #endif 188 189 #ifdef CONFIG_SUPPORT_EMMC_RPMB 190 char temp_original_part; 191 int init_rpmb(void) 192 { 193 struct mmc *mmc; 194 195 if (curr_device < 0) { 196 if (get_mmc_num() > 0) { 197 curr_device = 0; 198 } else { 199 printf("No MMC device available\n"); 200 return CMD_RET_FAILURE; 201 } 202 } 203 204 mmc = init_mmc_device(curr_device, false); 205 if (!mmc) 206 return CMD_RET_FAILURE; 207 208 if (!(mmc->version & MMC_VERSION_MMC)) { 209 printf("It is not a EMMC device\n"); 210 return CMD_RET_FAILURE; 211 } 212 if (mmc->version < MMC_VERSION_4_41) { 213 printf("RPMB not supported before version 4.41\n"); 214 return CMD_RET_FAILURE; 215 } 216 217 /* Switch to the RPMB partition */ 218 #ifndef CONFIG_BLK 219 temp_original_part = mmc->block_dev.hwpart; 220 debug("mmc->block_dev.hwpart\n"); 221 #else 222 temp_original_part = mmc_get_blk_desc(mmc)->hwpart; 223 debug("mmc_get_blk_desc(mmc)->hwpart\n"); 224 #endif 225 debug("init_rpmb temp_original_part = 0x%X\n", temp_original_part); 226 if (blk_select_hwpart_devnum 227 (IF_TYPE_MMC, curr_device, MMC_PART_RPMB) != 0) 228 return CMD_RET_FAILURE; 229 230 return CMD_RET_SUCCESS; 231 } 232 233 int finish_rpmb(void) 234 { 235 /* Return to original partition */ 236 debug("finish_rpmb temp_original_part = 0x%X\n", temp_original_part); 237 if (blk_select_hwpart_devnum 238 (IF_TYPE_MMC, curr_device, temp_original_part) != 0) 239 return CMD_RET_FAILURE; 240 241 return CMD_RET_SUCCESS; 242 } 243 244 int do_readcounter(struct s_rpmb *requestpackets) 245 { 246 int ret; 247 248 if (init_rpmb() != 0) 249 return -1; 250 251 struct mmc *mmc = find_mmc_device(curr_device); 252 if (!mmc) 253 return -1; 254 255 ret = read_counter(mmc, requestpackets); 256 257 if (finish_rpmb() != 0) 258 return -1; 259 260 return ret; 261 } 262 263 int do_programkey(struct s_rpmb *requestpackets) 264 { 265 int ret; 266 struct mmc *mmc = find_mmc_device(curr_device); 267 if (!mmc) 268 return -1; 269 270 if (init_rpmb() != 0) 271 return -1; 272 273 ret = program_key(mmc, requestpackets); 274 275 if (finish_rpmb() != 0) 276 return -1; 277 278 return ret; 279 } 280 281 int do_authenticatedread(struct s_rpmb *requestpackets, uint16_t block_count) 282 { 283 int ret; 284 struct mmc *mmc = find_mmc_device(curr_device); 285 if (!mmc) 286 return -1; 287 288 if (init_rpmb() != 0) 289 return -1; 290 291 ret = authenticated_read(mmc, requestpackets, block_count); 292 293 if (finish_rpmb() != 0) 294 return -1; 295 296 return ret; 297 } 298 299 int do_authenticatedwrite(struct s_rpmb *requestpackets) 300 { 301 int ret; 302 struct mmc *mmc = find_mmc_device(curr_device); 303 if (!mmc) 304 return -1; 305 306 if (init_rpmb() != 0) 307 return -1; 308 309 ret = authenticated_write(mmc, requestpackets); 310 311 if (finish_rpmb() != 0) 312 return -1; 313 314 return ret; 315 } 316 317 struct mmc *do_returnmmc(void) 318 { 319 struct mmc *mmc; 320 321 if (init_rpmb() != 0) 322 return NULL; 323 324 mmc = find_mmc_device(curr_device); 325 326 if (finish_rpmb() != 0) 327 return NULL; 328 329 return mmc; 330 } 331 332 static int confirm_key_prog(void) 333 { 334 puts("Warning: Programming authentication key can be done only once !\n" 335 " Use this command only if you are sure of what you are doing,\n" 336 "Really perform the key programming? <y/N> "); 337 if (confirm_yesno()) 338 return 1; 339 340 puts("Authentication key programming aborted\n"); 341 return 0; 342 } 343 static int do_mmcrpmb_key(cmd_tbl_t *cmdtp, int flag, 344 int argc, char * const argv[]) 345 { 346 void *key_addr; 347 struct mmc *mmc = find_mmc_device(curr_device); 348 349 if (argc != 2) 350 return CMD_RET_USAGE; 351 352 key_addr = (void *)simple_strtoul(argv[1], NULL, 16); 353 if (!confirm_key_prog()) 354 return CMD_RET_FAILURE; 355 if (mmc_rpmb_set_key(mmc, key_addr)) { 356 printf("ERROR - Key already programmed ?\n"); 357 return CMD_RET_FAILURE; 358 } 359 return CMD_RET_SUCCESS; 360 } 361 static int do_mmcrpmb_read(cmd_tbl_t *cmdtp, int flag, 362 int argc, char * const argv[]) 363 { 364 u16 blk, cnt; 365 void *addr; 366 int n; 367 void *key_addr = NULL; 368 struct mmc *mmc = find_mmc_device(curr_device); 369 370 if (argc < 4) 371 return CMD_RET_USAGE; 372 373 addr = (void *)simple_strtoul(argv[1], NULL, 16); 374 blk = simple_strtoul(argv[2], NULL, 16); 375 cnt = simple_strtoul(argv[3], NULL, 16); 376 377 if (argc == 5) 378 key_addr = (void *)simple_strtoul(argv[4], NULL, 16); 379 380 printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ", 381 curr_device, blk, cnt); 382 n = mmc_rpmb_read(mmc, addr, blk, cnt, key_addr); 383 384 printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 385 if (n != cnt) 386 return CMD_RET_FAILURE; 387 return CMD_RET_SUCCESS; 388 } 389 static int do_mmcrpmb_write(cmd_tbl_t *cmdtp, int flag, 390 int argc, char * const argv[]) 391 { 392 u16 blk, cnt; 393 void *addr; 394 int n; 395 void *key_addr; 396 struct mmc *mmc = find_mmc_device(curr_device); 397 398 if (argc != 5) 399 return CMD_RET_USAGE; 400 401 addr = (void *)simple_strtoul(argv[1], NULL, 16); 402 blk = simple_strtoul(argv[2], NULL, 16); 403 cnt = simple_strtoul(argv[3], NULL, 16); 404 key_addr = (void *)simple_strtoul(argv[4], NULL, 16); 405 406 printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ", 407 curr_device, blk, cnt); 408 n = mmc_rpmb_write(mmc, addr, blk, cnt, key_addr); 409 410 printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 411 if (n != cnt) 412 return CMD_RET_FAILURE; 413 return CMD_RET_SUCCESS; 414 } 415 static int do_mmcrpmb_counter(cmd_tbl_t *cmdtp, int flag, 416 int argc, char * const argv[]) 417 { 418 unsigned long counter; 419 struct mmc *mmc = find_mmc_device(curr_device); 420 421 if (mmc_rpmb_get_counter(mmc, &counter)) 422 return CMD_RET_FAILURE; 423 printf("RPMB Write counter= %lx\n", counter); 424 return CMD_RET_SUCCESS; 425 } 426 427 static cmd_tbl_t cmd_rpmb[] = { 428 U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""), 429 U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""), 430 U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""), 431 U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""), 432 }; 433 434 static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag, 435 int argc, char * const argv[]) 436 { 437 cmd_tbl_t *cp; 438 struct mmc *mmc; 439 char original_part; 440 int ret; 441 442 cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb)); 443 444 /* Drop the rpmb subcommand */ 445 argc--; 446 argv++; 447 448 if (cp == NULL || argc > cp->maxargs) 449 return CMD_RET_USAGE; 450 if (flag == CMD_FLAG_REPEAT && !cp->repeatable) 451 return CMD_RET_SUCCESS; 452 453 mmc = init_mmc_device(curr_device, false); 454 if (!mmc) 455 return CMD_RET_FAILURE; 456 457 if (!(mmc->version & MMC_VERSION_MMC)) { 458 printf("It is not a EMMC device\n"); 459 return CMD_RET_FAILURE; 460 } 461 if (mmc->version < MMC_VERSION_4_41) { 462 printf("RPMB not supported before version 4.41\n"); 463 return CMD_RET_FAILURE; 464 } 465 /* Switch to the RPMB partition */ 466 #ifndef CONFIG_BLK 467 original_part = mmc->block_dev.hwpart; 468 #else 469 original_part = mmc_get_blk_desc(mmc)->hwpart; 470 #endif 471 if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) != 472 0) 473 return CMD_RET_FAILURE; 474 ret = cp->cmd(cmdtp, flag, argc, argv); 475 476 /* Return to original partition */ 477 if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) != 478 0) 479 return CMD_RET_FAILURE; 480 return ret; 481 } 482 #endif 483 484 static int do_mmc_read(cmd_tbl_t *cmdtp, int flag, 485 int argc, char * const argv[]) 486 { 487 struct mmc *mmc; 488 u32 blk, cnt, n; 489 void *addr; 490 491 if (argc != 4) 492 return CMD_RET_USAGE; 493 494 addr = (void *)simple_strtoul(argv[1], NULL, 16); 495 blk = simple_strtoul(argv[2], NULL, 16); 496 cnt = simple_strtoul(argv[3], NULL, 16); 497 498 mmc = init_mmc_device(curr_device, false); 499 if (!mmc) 500 return CMD_RET_FAILURE; 501 502 printf("\nMMC read: dev # %d, block # %d, count %d ... ", 503 curr_device, blk, cnt); 504 505 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr); 506 printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 507 508 return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; 509 } 510 static int do_mmc_write(cmd_tbl_t *cmdtp, int flag, 511 int argc, char * const argv[]) 512 { 513 struct mmc *mmc; 514 u32 blk, cnt, n; 515 void *addr; 516 517 if (argc != 4) 518 return CMD_RET_USAGE; 519 520 addr = (void *)simple_strtoul(argv[1], NULL, 16); 521 blk = simple_strtoul(argv[2], NULL, 16); 522 cnt = simple_strtoul(argv[3], NULL, 16); 523 524 mmc = init_mmc_device(curr_device, false); 525 if (!mmc) 526 return CMD_RET_FAILURE; 527 528 printf("\nMMC write: dev # %d, block # %d, count %d ... ", 529 curr_device, blk, cnt); 530 531 if (mmc_getwp(mmc) == 1) { 532 printf("Error: card is write protected!\n"); 533 return CMD_RET_FAILURE; 534 } 535 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr); 536 printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 537 538 return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; 539 } 540 static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag, 541 int argc, char * const argv[]) 542 { 543 struct mmc *mmc; 544 u32 blk, cnt, n; 545 546 if (argc != 3) 547 return CMD_RET_USAGE; 548 549 blk = simple_strtoul(argv[1], NULL, 16); 550 cnt = simple_strtoul(argv[2], NULL, 16); 551 552 mmc = init_mmc_device(curr_device, false); 553 if (!mmc) 554 return CMD_RET_FAILURE; 555 556 printf("\nMMC erase: dev # %d, block # %d, count %d ... ", 557 curr_device, blk, cnt); 558 559 if (mmc_getwp(mmc) == 1) { 560 printf("Error: card is write protected!\n"); 561 return CMD_RET_FAILURE; 562 } 563 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt); 564 printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 565 566 return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; 567 } 568 static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag, 569 int argc, char * const argv[]) 570 { 571 struct mmc *mmc; 572 573 mmc = init_mmc_device(curr_device, true); 574 if (!mmc) 575 return CMD_RET_FAILURE; 576 577 return CMD_RET_SUCCESS; 578 } 579 static int do_mmc_part(cmd_tbl_t *cmdtp, int flag, 580 int argc, char * const argv[]) 581 { 582 struct blk_desc *mmc_dev; 583 struct mmc *mmc; 584 585 mmc = init_mmc_device(curr_device, false); 586 if (!mmc) 587 return CMD_RET_FAILURE; 588 589 mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device); 590 if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) { 591 part_print(mmc_dev); 592 return CMD_RET_SUCCESS; 593 } 594 595 puts("get mmc type error!\n"); 596 return CMD_RET_FAILURE; 597 } 598 static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag, 599 int argc, char * const argv[]) 600 { 601 int dev, part = 0, ret; 602 struct mmc *mmc; 603 604 /* If not boot from mmc devices, init mmc devices first. */ 605 ret = mmc_initialize(gd->bd); 606 if (ret) { 607 printf("Could not initialize mmc. error: %d\n", ret); 608 return ret; 609 } 610 611 if (argc == 1) { 612 dev = curr_device; 613 } else if (argc == 2) { 614 dev = simple_strtoul(argv[1], NULL, 10); 615 } else if (argc == 3) { 616 dev = (int)simple_strtoul(argv[1], NULL, 10); 617 part = (int)simple_strtoul(argv[2], NULL, 10); 618 if (part > PART_ACCESS_MASK) { 619 printf("#part_num shouldn't be larger than %d\n", 620 PART_ACCESS_MASK); 621 return CMD_RET_FAILURE; 622 } 623 } else { 624 return CMD_RET_USAGE; 625 } 626 627 mmc = init_mmc_device(dev, false); 628 if (!mmc) 629 return CMD_RET_FAILURE; 630 631 ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part); 632 printf("switch to partitions #%d, %s\n", 633 part, (!ret) ? "OK" : "ERROR"); 634 if (ret) 635 return 1; 636 637 curr_device = dev; 638 if (mmc->part_config == MMCPART_NOAVAILABLE) 639 printf("mmc%d is current device\n", curr_device); 640 else 641 printf("mmc%d(part %d) is current device\n", 642 curr_device, mmc_get_blk_desc(mmc)->hwpart); 643 644 return CMD_RET_SUCCESS; 645 } 646 static int do_mmc_list(cmd_tbl_t *cmdtp, int flag, 647 int argc, char * const argv[]) 648 { 649 print_mmc_devices('\n'); 650 do_mmc_rescan(cmdtp, flag, argc, argv); 651 return CMD_RET_SUCCESS; 652 } 653 654 static int parse_hwpart_user(struct mmc_hwpart_conf *pconf, 655 int argc, char * const argv[]) 656 { 657 int i = 0; 658 659 memset(&pconf->user, 0, sizeof(pconf->user)); 660 661 while (i < argc) { 662 if (!strcmp(argv[i], "enh")) { 663 if (i + 2 >= argc) 664 return -1; 665 pconf->user.enh_start = 666 simple_strtoul(argv[i+1], NULL, 10); 667 pconf->user.enh_size = 668 simple_strtoul(argv[i+2], NULL, 10); 669 i += 3; 670 } else if (!strcmp(argv[i], "wrrel")) { 671 if (i + 1 >= argc) 672 return -1; 673 pconf->user.wr_rel_change = 1; 674 if (!strcmp(argv[i+1], "on")) 675 pconf->user.wr_rel_set = 1; 676 else if (!strcmp(argv[i+1], "off")) 677 pconf->user.wr_rel_set = 0; 678 else 679 return -1; 680 i += 2; 681 } else { 682 break; 683 } 684 } 685 return i; 686 } 687 688 static int parse_hwpart_gp(struct mmc_hwpart_conf *pconf, int pidx, 689 int argc, char * const argv[]) 690 { 691 int i; 692 693 memset(&pconf->gp_part[pidx], 0, sizeof(pconf->gp_part[pidx])); 694 695 if (1 >= argc) 696 return -1; 697 pconf->gp_part[pidx].size = simple_strtoul(argv[0], NULL, 10); 698 699 i = 1; 700 while (i < argc) { 701 if (!strcmp(argv[i], "enh")) { 702 pconf->gp_part[pidx].enhanced = 1; 703 i += 1; 704 } else if (!strcmp(argv[i], "wrrel")) { 705 if (i + 1 >= argc) 706 return -1; 707 pconf->gp_part[pidx].wr_rel_change = 1; 708 if (!strcmp(argv[i+1], "on")) 709 pconf->gp_part[pidx].wr_rel_set = 1; 710 else if (!strcmp(argv[i+1], "off")) 711 pconf->gp_part[pidx].wr_rel_set = 0; 712 else 713 return -1; 714 i += 2; 715 } else { 716 break; 717 } 718 } 719 return i; 720 } 721 722 static int do_mmc_hwpartition(cmd_tbl_t *cmdtp, int flag, 723 int argc, char * const argv[]) 724 { 725 struct mmc *mmc; 726 struct mmc_hwpart_conf pconf = { }; 727 enum mmc_hwpart_conf_mode mode = MMC_HWPART_CONF_CHECK; 728 int i, r, pidx; 729 730 mmc = init_mmc_device(curr_device, false); 731 if (!mmc) 732 return CMD_RET_FAILURE; 733 734 if (argc < 1) 735 return CMD_RET_USAGE; 736 i = 1; 737 while (i < argc) { 738 if (!strcmp(argv[i], "user")) { 739 i++; 740 r = parse_hwpart_user(&pconf, argc-i, &argv[i]); 741 if (r < 0) 742 return CMD_RET_USAGE; 743 i += r; 744 } else if (!strncmp(argv[i], "gp", 2) && 745 strlen(argv[i]) == 3 && 746 argv[i][2] >= '1' && argv[i][2] <= '4') { 747 pidx = argv[i][2] - '1'; 748 i++; 749 r = parse_hwpart_gp(&pconf, pidx, argc-i, &argv[i]); 750 if (r < 0) 751 return CMD_RET_USAGE; 752 i += r; 753 } else if (!strcmp(argv[i], "check")) { 754 mode = MMC_HWPART_CONF_CHECK; 755 i++; 756 } else if (!strcmp(argv[i], "set")) { 757 mode = MMC_HWPART_CONF_SET; 758 i++; 759 } else if (!strcmp(argv[i], "complete")) { 760 mode = MMC_HWPART_CONF_COMPLETE; 761 i++; 762 } else { 763 return CMD_RET_USAGE; 764 } 765 } 766 767 puts("Partition configuration:\n"); 768 if (pconf.user.enh_size) { 769 puts("\tUser Enhanced Start: "); 770 print_size(((u64)pconf.user.enh_start) << 9, "\n"); 771 puts("\tUser Enhanced Size: "); 772 print_size(((u64)pconf.user.enh_size) << 9, "\n"); 773 } else { 774 puts("\tNo enhanced user data area\n"); 775 } 776 if (pconf.user.wr_rel_change) 777 printf("\tUser partition write reliability: %s\n", 778 pconf.user.wr_rel_set ? "on" : "off"); 779 for (pidx = 0; pidx < 4; pidx++) { 780 if (pconf.gp_part[pidx].size) { 781 printf("\tGP%i Capacity: ", pidx+1); 782 print_size(((u64)pconf.gp_part[pidx].size) << 9, 783 pconf.gp_part[pidx].enhanced ? 784 " ENH\n" : "\n"); 785 } else { 786 printf("\tNo GP%i partition\n", pidx+1); 787 } 788 if (pconf.gp_part[pidx].wr_rel_change) 789 printf("\tGP%i write reliability: %s\n", pidx+1, 790 pconf.gp_part[pidx].wr_rel_set ? "on" : "off"); 791 } 792 793 if (!mmc_hwpart_config(mmc, &pconf, mode)) { 794 if (mode == MMC_HWPART_CONF_COMPLETE) 795 puts("Partitioning successful, " 796 "power-cycle to make effective\n"); 797 return CMD_RET_SUCCESS; 798 } else { 799 puts("Failed!\n"); 800 return CMD_RET_FAILURE; 801 } 802 } 803 804 #ifdef CONFIG_SUPPORT_EMMC_BOOT 805 static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag, 806 int argc, char * const argv[]) 807 { 808 int dev; 809 struct mmc *mmc; 810 u8 width, reset, mode; 811 812 if (argc != 5) 813 return CMD_RET_USAGE; 814 dev = simple_strtoul(argv[1], NULL, 10); 815 width = simple_strtoul(argv[2], NULL, 10); 816 reset = simple_strtoul(argv[3], NULL, 10); 817 mode = simple_strtoul(argv[4], NULL, 10); 818 819 mmc = init_mmc_device(dev, false); 820 if (!mmc) 821 return CMD_RET_FAILURE; 822 823 if (IS_SD(mmc)) { 824 puts("BOOT_BUS_WIDTH only exists on eMMC\n"); 825 return CMD_RET_FAILURE; 826 } 827 828 /* acknowledge to be sent during boot operation */ 829 return mmc_set_boot_bus_width(mmc, width, reset, mode); 830 } 831 static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag, 832 int argc, char * const argv[]) 833 { 834 int dev; 835 struct mmc *mmc; 836 u32 bootsize, rpmbsize; 837 838 if (argc != 4) 839 return CMD_RET_USAGE; 840 dev = simple_strtoul(argv[1], NULL, 10); 841 bootsize = simple_strtoul(argv[2], NULL, 10); 842 rpmbsize = simple_strtoul(argv[3], NULL, 10); 843 844 mmc = init_mmc_device(dev, false); 845 if (!mmc) 846 return CMD_RET_FAILURE; 847 848 if (IS_SD(mmc)) { 849 printf("It is not a EMMC device\n"); 850 return CMD_RET_FAILURE; 851 } 852 853 if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) { 854 printf("EMMC boot partition Size change Failed.\n"); 855 return CMD_RET_FAILURE; 856 } 857 858 printf("EMMC boot partition Size %d MB\n", bootsize); 859 printf("EMMC RPMB partition Size %d MB\n", rpmbsize); 860 return CMD_RET_SUCCESS; 861 } 862 863 static int mmc_partconf_print(struct mmc *mmc) 864 { 865 u8 ack, access, part; 866 867 if (mmc->part_config == MMCPART_NOAVAILABLE) { 868 printf("No part_config info for ver. 0x%x\n", mmc->version); 869 return CMD_RET_FAILURE; 870 } 871 872 access = EXT_CSD_EXTRACT_PARTITION_ACCESS(mmc->part_config); 873 ack = EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config); 874 part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config); 875 876 printf("EXT_CSD[179], PARTITION_CONFIG:\n" 877 "BOOT_ACK: 0x%x\n" 878 "BOOT_PARTITION_ENABLE: 0x%x\n" 879 "PARTITION_ACCESS: 0x%x\n", ack, part, access); 880 881 return CMD_RET_SUCCESS; 882 } 883 884 static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag, 885 int argc, char * const argv[]) 886 { 887 int dev; 888 struct mmc *mmc; 889 u8 ack, part_num, access; 890 891 if (argc != 2 && argc != 5) 892 return CMD_RET_USAGE; 893 894 dev = simple_strtoul(argv[1], NULL, 10); 895 896 mmc = init_mmc_device(dev, false); 897 if (!mmc) 898 return CMD_RET_FAILURE; 899 900 if (IS_SD(mmc)) { 901 puts("PARTITION_CONFIG only exists on eMMC\n"); 902 return CMD_RET_FAILURE; 903 } 904 905 if (argc == 2) 906 return mmc_partconf_print(mmc); 907 908 ack = simple_strtoul(argv[2], NULL, 10); 909 part_num = simple_strtoul(argv[3], NULL, 10); 910 access = simple_strtoul(argv[4], NULL, 10); 911 912 /* acknowledge to be sent during boot operation */ 913 return mmc_set_part_conf(mmc, ack, part_num, access); 914 } 915 static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag, 916 int argc, char * const argv[]) 917 { 918 int dev; 919 struct mmc *mmc; 920 u8 enable; 921 922 /* 923 * Set the RST_n_ENABLE bit of RST_n_FUNCTION 924 * The only valid values are 0x0, 0x1 and 0x2 and writing 925 * a value of 0x1 or 0x2 sets the value permanently. 926 */ 927 if (argc != 3) 928 return CMD_RET_USAGE; 929 930 dev = simple_strtoul(argv[1], NULL, 10); 931 enable = simple_strtoul(argv[2], NULL, 10); 932 933 if (enable > 2) { 934 puts("Invalid RST_n_ENABLE value\n"); 935 return CMD_RET_USAGE; 936 } 937 938 mmc = init_mmc_device(dev, false); 939 if (!mmc) 940 return CMD_RET_FAILURE; 941 942 if (IS_SD(mmc)) { 943 puts("RST_n_FUNCTION only exists on eMMC\n"); 944 return CMD_RET_FAILURE; 945 } 946 947 return mmc_set_rst_n_function(mmc, enable); 948 } 949 #endif 950 static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag, 951 int argc, char * const argv[]) 952 { 953 struct mmc *mmc; 954 u32 val; 955 int ret; 956 957 if (argc != 2) 958 return CMD_RET_USAGE; 959 val = simple_strtoul(argv[1], NULL, 16); 960 961 mmc = find_mmc_device(curr_device); 962 if (!mmc) { 963 printf("no mmc device at slot %x\n", curr_device); 964 return CMD_RET_FAILURE; 965 } 966 ret = mmc_set_dsr(mmc, val); 967 printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR"); 968 if (!ret) { 969 mmc->has_init = 0; 970 if (mmc_init(mmc)) 971 return CMD_RET_FAILURE; 972 else 973 return CMD_RET_SUCCESS; 974 } 975 return ret; 976 } 977 978 #ifdef CONFIG_CMD_BKOPS_ENABLE 979 static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag, 980 int argc, char * const argv[]) 981 { 982 int dev; 983 struct mmc *mmc; 984 985 if (argc != 2) 986 return CMD_RET_USAGE; 987 988 dev = simple_strtoul(argv[1], NULL, 10); 989 990 mmc = init_mmc_device(dev, false); 991 if (!mmc) 992 return CMD_RET_FAILURE; 993 994 if (IS_SD(mmc)) { 995 puts("BKOPS_EN only exists on eMMC\n"); 996 return CMD_RET_FAILURE; 997 } 998 999 return mmc_set_bkops_enable(mmc); 1000 } 1001 #endif 1002 1003 static cmd_tbl_t cmd_mmc[] = { 1004 U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), 1005 U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""), 1006 U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""), 1007 U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""), 1008 U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""), 1009 U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""), 1010 U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""), 1011 U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""), 1012 U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""), 1013 #ifdef CONFIG_SUPPORT_EMMC_BOOT 1014 U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""), 1015 U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""), 1016 U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""), 1017 U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""), 1018 #endif 1019 #ifdef CONFIG_OPTEE_CLIENT 1020 U_BOOT_CMD_MKENT(testsecurestorage, 1, 0, do_mmc_test_secure_storage, "", ""), 1021 U_BOOT_CMD_MKENT(testefuse, 1, 0, do_mmc_testefuse, "", ""), 1022 #endif 1023 #ifdef CONFIG_SUPPORT_EMMC_RPMB 1024 U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), 1025 #endif 1026 U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), 1027 #ifdef CONFIG_CMD_BKOPS_ENABLE 1028 U_BOOT_CMD_MKENT(bkops-enable, 2, 0, do_mmc_bkops_enable, "", ""), 1029 #endif 1030 }; 1031 1032 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 1033 { 1034 cmd_tbl_t *cp; 1035 1036 cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc)); 1037 1038 /* Drop the mmc command */ 1039 argc--; 1040 argv++; 1041 1042 if (cp == NULL || argc > cp->maxargs) 1043 return CMD_RET_USAGE; 1044 if (flag == CMD_FLAG_REPEAT && !cp->repeatable) 1045 return CMD_RET_SUCCESS; 1046 1047 if (curr_device < 0) { 1048 if (get_mmc_num() > 0) { 1049 curr_device = 0; 1050 } else { 1051 puts("No MMC device available\n"); 1052 return CMD_RET_FAILURE; 1053 } 1054 } 1055 return cp->cmd(cmdtp, flag, argc, argv); 1056 } 1057 1058 U_BOOT_CMD( 1059 mmc, 29, 1, do_mmcops, 1060 "MMC sub system", 1061 "info - display info of the current MMC device\n" 1062 "mmc read addr blk# cnt\n" 1063 "mmc write addr blk# cnt\n" 1064 "mmc erase blk# cnt\n" 1065 "mmc rescan\n" 1066 "mmc part - lists available partition on current mmc device\n" 1067 "mmc dev [dev] [part] - show or set current mmc device [partition]\n" 1068 "mmc list - lists available devices\n" 1069 "mmc hwpartition [args...] - does hardware partitioning\n" 1070 " arguments (sizes in 512-byte blocks):\n" 1071 " [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n" 1072 " [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n" 1073 " [check|set|complete] - mode, complete set partitioning completed\n" 1074 " WARNING: Partitioning is a write-once setting once it is set to complete.\n" 1075 " Power cycling is required to initialize partitions after set to complete.\n" 1076 #ifdef CONFIG_SUPPORT_EMMC_BOOT 1077 "mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n" 1078 " - Set the BOOT_BUS_WIDTH field of the specified device\n" 1079 "mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n" 1080 " - Change sizes of boot and RPMB partitions of specified device\n" 1081 "mmc partconf dev [boot_ack boot_partition partition_access]\n" 1082 " - Show or change the bits of the PARTITION_CONFIG field of the specified device\n" 1083 "mmc rst-function dev value\n" 1084 " - Change the RST_n_FUNCTION field of the specified device\n" 1085 " WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n" 1086 #endif 1087 #ifdef CONFIG_OPTEE_CLIENT 1088 "mmc testsecurestorage - test CA call static TA to store data in security\n" 1089 "mmc testefuse - test CA call static TA,and TA read or write efuse\n" 1090 #endif 1091 #ifdef CONFIG_SUPPORT_EMMC_RPMB 1092 "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n" 1093 "mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n" 1094 "mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n" 1095 "mmc rpmb counter - read the value of the write counter\n" 1096 #endif 1097 "mmc setdsr <value> - set DSR register value\n" 1098 #ifdef CONFIG_CMD_BKOPS_ENABLE 1099 "mmc bkops-enable <dev> - enable background operations handshake on device\n" 1100 " WARNING: This is a write-once setting.\n" 1101 #endif 1102 ); 1103 1104 /* Old command kept for compatibility. Same as 'mmc info' */ 1105 U_BOOT_CMD( 1106 mmcinfo, 1, 0, do_mmcinfo, 1107 "display MMC info", 1108 "- display info of the current MMC device" 1109 ); 1110 1111