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 return CMD_RET_SUCCESS; 651 } 652 653 static int parse_hwpart_user(struct mmc_hwpart_conf *pconf, 654 int argc, char * const argv[]) 655 { 656 int i = 0; 657 658 memset(&pconf->user, 0, sizeof(pconf->user)); 659 660 while (i < argc) { 661 if (!strcmp(argv[i], "enh")) { 662 if (i + 2 >= argc) 663 return -1; 664 pconf->user.enh_start = 665 simple_strtoul(argv[i+1], NULL, 10); 666 pconf->user.enh_size = 667 simple_strtoul(argv[i+2], NULL, 10); 668 i += 3; 669 } else if (!strcmp(argv[i], "wrrel")) { 670 if (i + 1 >= argc) 671 return -1; 672 pconf->user.wr_rel_change = 1; 673 if (!strcmp(argv[i+1], "on")) 674 pconf->user.wr_rel_set = 1; 675 else if (!strcmp(argv[i+1], "off")) 676 pconf->user.wr_rel_set = 0; 677 else 678 return -1; 679 i += 2; 680 } else { 681 break; 682 } 683 } 684 return i; 685 } 686 687 static int parse_hwpart_gp(struct mmc_hwpart_conf *pconf, int pidx, 688 int argc, char * const argv[]) 689 { 690 int i; 691 692 memset(&pconf->gp_part[pidx], 0, sizeof(pconf->gp_part[pidx])); 693 694 if (1 >= argc) 695 return -1; 696 pconf->gp_part[pidx].size = simple_strtoul(argv[0], NULL, 10); 697 698 i = 1; 699 while (i < argc) { 700 if (!strcmp(argv[i], "enh")) { 701 pconf->gp_part[pidx].enhanced = 1; 702 i += 1; 703 } else if (!strcmp(argv[i], "wrrel")) { 704 if (i + 1 >= argc) 705 return -1; 706 pconf->gp_part[pidx].wr_rel_change = 1; 707 if (!strcmp(argv[i+1], "on")) 708 pconf->gp_part[pidx].wr_rel_set = 1; 709 else if (!strcmp(argv[i+1], "off")) 710 pconf->gp_part[pidx].wr_rel_set = 0; 711 else 712 return -1; 713 i += 2; 714 } else { 715 break; 716 } 717 } 718 return i; 719 } 720 721 static int do_mmc_hwpartition(cmd_tbl_t *cmdtp, int flag, 722 int argc, char * const argv[]) 723 { 724 struct mmc *mmc; 725 struct mmc_hwpart_conf pconf = { }; 726 enum mmc_hwpart_conf_mode mode = MMC_HWPART_CONF_CHECK; 727 int i, r, pidx; 728 729 mmc = init_mmc_device(curr_device, false); 730 if (!mmc) 731 return CMD_RET_FAILURE; 732 733 if (argc < 1) 734 return CMD_RET_USAGE; 735 i = 1; 736 while (i < argc) { 737 if (!strcmp(argv[i], "user")) { 738 i++; 739 r = parse_hwpart_user(&pconf, argc-i, &argv[i]); 740 if (r < 0) 741 return CMD_RET_USAGE; 742 i += r; 743 } else if (!strncmp(argv[i], "gp", 2) && 744 strlen(argv[i]) == 3 && 745 argv[i][2] >= '1' && argv[i][2] <= '4') { 746 pidx = argv[i][2] - '1'; 747 i++; 748 r = parse_hwpart_gp(&pconf, pidx, argc-i, &argv[i]); 749 if (r < 0) 750 return CMD_RET_USAGE; 751 i += r; 752 } else if (!strcmp(argv[i], "check")) { 753 mode = MMC_HWPART_CONF_CHECK; 754 i++; 755 } else if (!strcmp(argv[i], "set")) { 756 mode = MMC_HWPART_CONF_SET; 757 i++; 758 } else if (!strcmp(argv[i], "complete")) { 759 mode = MMC_HWPART_CONF_COMPLETE; 760 i++; 761 } else { 762 return CMD_RET_USAGE; 763 } 764 } 765 766 puts("Partition configuration:\n"); 767 if (pconf.user.enh_size) { 768 puts("\tUser Enhanced Start: "); 769 print_size(((u64)pconf.user.enh_start) << 9, "\n"); 770 puts("\tUser Enhanced Size: "); 771 print_size(((u64)pconf.user.enh_size) << 9, "\n"); 772 } else { 773 puts("\tNo enhanced user data area\n"); 774 } 775 if (pconf.user.wr_rel_change) 776 printf("\tUser partition write reliability: %s\n", 777 pconf.user.wr_rel_set ? "on" : "off"); 778 for (pidx = 0; pidx < 4; pidx++) { 779 if (pconf.gp_part[pidx].size) { 780 printf("\tGP%i Capacity: ", pidx+1); 781 print_size(((u64)pconf.gp_part[pidx].size) << 9, 782 pconf.gp_part[pidx].enhanced ? 783 " ENH\n" : "\n"); 784 } else { 785 printf("\tNo GP%i partition\n", pidx+1); 786 } 787 if (pconf.gp_part[pidx].wr_rel_change) 788 printf("\tGP%i write reliability: %s\n", pidx+1, 789 pconf.gp_part[pidx].wr_rel_set ? "on" : "off"); 790 } 791 792 if (!mmc_hwpart_config(mmc, &pconf, mode)) { 793 if (mode == MMC_HWPART_CONF_COMPLETE) 794 puts("Partitioning successful, " 795 "power-cycle to make effective\n"); 796 return CMD_RET_SUCCESS; 797 } else { 798 puts("Failed!\n"); 799 return CMD_RET_FAILURE; 800 } 801 } 802 803 #ifdef CONFIG_SUPPORT_EMMC_BOOT 804 static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag, 805 int argc, char * const argv[]) 806 { 807 int dev; 808 struct mmc *mmc; 809 u8 width, reset, mode; 810 811 if (argc != 5) 812 return CMD_RET_USAGE; 813 dev = simple_strtoul(argv[1], NULL, 10); 814 width = simple_strtoul(argv[2], NULL, 10); 815 reset = simple_strtoul(argv[3], NULL, 10); 816 mode = simple_strtoul(argv[4], NULL, 10); 817 818 mmc = init_mmc_device(dev, false); 819 if (!mmc) 820 return CMD_RET_FAILURE; 821 822 if (IS_SD(mmc)) { 823 puts("BOOT_BUS_WIDTH only exists on eMMC\n"); 824 return CMD_RET_FAILURE; 825 } 826 827 /* acknowledge to be sent during boot operation */ 828 return mmc_set_boot_bus_width(mmc, width, reset, mode); 829 } 830 static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag, 831 int argc, char * const argv[]) 832 { 833 int dev; 834 struct mmc *mmc; 835 u32 bootsize, rpmbsize; 836 837 if (argc != 4) 838 return CMD_RET_USAGE; 839 dev = simple_strtoul(argv[1], NULL, 10); 840 bootsize = simple_strtoul(argv[2], NULL, 10); 841 rpmbsize = simple_strtoul(argv[3], NULL, 10); 842 843 mmc = init_mmc_device(dev, false); 844 if (!mmc) 845 return CMD_RET_FAILURE; 846 847 if (IS_SD(mmc)) { 848 printf("It is not a EMMC device\n"); 849 return CMD_RET_FAILURE; 850 } 851 852 if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) { 853 printf("EMMC boot partition Size change Failed.\n"); 854 return CMD_RET_FAILURE; 855 } 856 857 printf("EMMC boot partition Size %d MB\n", bootsize); 858 printf("EMMC RPMB partition Size %d MB\n", rpmbsize); 859 return CMD_RET_SUCCESS; 860 } 861 862 static int mmc_partconf_print(struct mmc *mmc) 863 { 864 u8 ack, access, part; 865 866 if (mmc->part_config == MMCPART_NOAVAILABLE) { 867 printf("No part_config info for ver. 0x%x\n", mmc->version); 868 return CMD_RET_FAILURE; 869 } 870 871 access = EXT_CSD_EXTRACT_PARTITION_ACCESS(mmc->part_config); 872 ack = EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config); 873 part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config); 874 875 printf("EXT_CSD[179], PARTITION_CONFIG:\n" 876 "BOOT_ACK: 0x%x\n" 877 "BOOT_PARTITION_ENABLE: 0x%x\n" 878 "PARTITION_ACCESS: 0x%x\n", ack, part, access); 879 880 return CMD_RET_SUCCESS; 881 } 882 883 static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag, 884 int argc, char * const argv[]) 885 { 886 int dev; 887 struct mmc *mmc; 888 u8 ack, part_num, access; 889 890 if (argc != 2 && argc != 5) 891 return CMD_RET_USAGE; 892 893 dev = simple_strtoul(argv[1], NULL, 10); 894 895 mmc = init_mmc_device(dev, false); 896 if (!mmc) 897 return CMD_RET_FAILURE; 898 899 if (IS_SD(mmc)) { 900 puts("PARTITION_CONFIG only exists on eMMC\n"); 901 return CMD_RET_FAILURE; 902 } 903 904 if (argc == 2) 905 return mmc_partconf_print(mmc); 906 907 ack = simple_strtoul(argv[2], NULL, 10); 908 part_num = simple_strtoul(argv[3], NULL, 10); 909 access = simple_strtoul(argv[4], NULL, 10); 910 911 /* acknowledge to be sent during boot operation */ 912 return mmc_set_part_conf(mmc, ack, part_num, access); 913 } 914 static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag, 915 int argc, char * const argv[]) 916 { 917 int dev; 918 struct mmc *mmc; 919 u8 enable; 920 921 /* 922 * Set the RST_n_ENABLE bit of RST_n_FUNCTION 923 * The only valid values are 0x0, 0x1 and 0x2 and writing 924 * a value of 0x1 or 0x2 sets the value permanently. 925 */ 926 if (argc != 3) 927 return CMD_RET_USAGE; 928 929 dev = simple_strtoul(argv[1], NULL, 10); 930 enable = simple_strtoul(argv[2], NULL, 10); 931 932 if (enable > 2) { 933 puts("Invalid RST_n_ENABLE value\n"); 934 return CMD_RET_USAGE; 935 } 936 937 mmc = init_mmc_device(dev, false); 938 if (!mmc) 939 return CMD_RET_FAILURE; 940 941 if (IS_SD(mmc)) { 942 puts("RST_n_FUNCTION only exists on eMMC\n"); 943 return CMD_RET_FAILURE; 944 } 945 946 return mmc_set_rst_n_function(mmc, enable); 947 } 948 #endif 949 static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag, 950 int argc, char * const argv[]) 951 { 952 struct mmc *mmc; 953 u32 val; 954 int ret; 955 956 if (argc != 2) 957 return CMD_RET_USAGE; 958 val = simple_strtoul(argv[1], NULL, 16); 959 960 mmc = find_mmc_device(curr_device); 961 if (!mmc) { 962 printf("no mmc device at slot %x\n", curr_device); 963 return CMD_RET_FAILURE; 964 } 965 ret = mmc_set_dsr(mmc, val); 966 printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR"); 967 if (!ret) { 968 mmc->has_init = 0; 969 if (mmc_init(mmc)) 970 return CMD_RET_FAILURE; 971 else 972 return CMD_RET_SUCCESS; 973 } 974 return ret; 975 } 976 977 #ifdef CONFIG_CMD_BKOPS_ENABLE 978 static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag, 979 int argc, char * const argv[]) 980 { 981 int dev; 982 struct mmc *mmc; 983 984 if (argc != 2) 985 return CMD_RET_USAGE; 986 987 dev = simple_strtoul(argv[1], NULL, 10); 988 989 mmc = init_mmc_device(dev, false); 990 if (!mmc) 991 return CMD_RET_FAILURE; 992 993 if (IS_SD(mmc)) { 994 puts("BKOPS_EN only exists on eMMC\n"); 995 return CMD_RET_FAILURE; 996 } 997 998 return mmc_set_bkops_enable(mmc); 999 } 1000 #endif 1001 1002 static cmd_tbl_t cmd_mmc[] = { 1003 U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), 1004 U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""), 1005 U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""), 1006 U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""), 1007 U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""), 1008 U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""), 1009 U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""), 1010 U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""), 1011 U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""), 1012 #ifdef CONFIG_SUPPORT_EMMC_BOOT 1013 U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""), 1014 U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""), 1015 U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""), 1016 U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""), 1017 #endif 1018 #ifdef CONFIG_OPTEE_CLIENT 1019 U_BOOT_CMD_MKENT(testsecurestorage, 1, 0, do_mmc_test_secure_storage, "", ""), 1020 U_BOOT_CMD_MKENT(testefuse, 1, 0, do_mmc_testefuse, "", ""), 1021 #endif 1022 #ifdef CONFIG_SUPPORT_EMMC_RPMB 1023 U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), 1024 #endif 1025 U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), 1026 #ifdef CONFIG_CMD_BKOPS_ENABLE 1027 U_BOOT_CMD_MKENT(bkops-enable, 2, 0, do_mmc_bkops_enable, "", ""), 1028 #endif 1029 }; 1030 1031 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 1032 { 1033 cmd_tbl_t *cp; 1034 1035 cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc)); 1036 1037 /* Drop the mmc command */ 1038 argc--; 1039 argv++; 1040 1041 if (cp == NULL || argc > cp->maxargs) 1042 return CMD_RET_USAGE; 1043 if (flag == CMD_FLAG_REPEAT && !cp->repeatable) 1044 return CMD_RET_SUCCESS; 1045 1046 if (curr_device < 0) { 1047 if (get_mmc_num() > 0) { 1048 curr_device = 0; 1049 } else { 1050 puts("No MMC device available\n"); 1051 return CMD_RET_FAILURE; 1052 } 1053 } 1054 return cp->cmd(cmdtp, flag, argc, argv); 1055 } 1056 1057 U_BOOT_CMD( 1058 mmc, 29, 1, do_mmcops, 1059 "MMC sub system", 1060 "info - display info of the current MMC device\n" 1061 "mmc read addr blk# cnt\n" 1062 "mmc write addr blk# cnt\n" 1063 "mmc erase blk# cnt\n" 1064 "mmc rescan\n" 1065 "mmc part - lists available partition on current mmc device\n" 1066 "mmc dev [dev] [part] - show or set current mmc device [partition]\n" 1067 "mmc list - lists available devices\n" 1068 "mmc hwpartition [args...] - does hardware partitioning\n" 1069 " arguments (sizes in 512-byte blocks):\n" 1070 " [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n" 1071 " [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n" 1072 " [check|set|complete] - mode, complete set partitioning completed\n" 1073 " WARNING: Partitioning is a write-once setting once it is set to complete.\n" 1074 " Power cycling is required to initialize partitions after set to complete.\n" 1075 #ifdef CONFIG_SUPPORT_EMMC_BOOT 1076 "mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n" 1077 " - Set the BOOT_BUS_WIDTH field of the specified device\n" 1078 "mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n" 1079 " - Change sizes of boot and RPMB partitions of specified device\n" 1080 "mmc partconf dev [boot_ack boot_partition partition_access]\n" 1081 " - Show or change the bits of the PARTITION_CONFIG field of the specified device\n" 1082 "mmc rst-function dev value\n" 1083 " - Change the RST_n_FUNCTION field of the specified device\n" 1084 " WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n" 1085 #endif 1086 #ifdef CONFIG_OPTEE_CLIENT 1087 "mmc testsecurestorage - test CA call static TA to store data in security\n" 1088 "mmc testefuse - test CA call static TA,and TA read or write efuse\n" 1089 #endif 1090 #ifdef CONFIG_SUPPORT_EMMC_RPMB 1091 "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n" 1092 "mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n" 1093 "mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n" 1094 "mmc rpmb counter - read the value of the write counter\n" 1095 #endif 1096 "mmc setdsr <value> - set DSR register value\n" 1097 #ifdef CONFIG_CMD_BKOPS_ENABLE 1098 "mmc bkops-enable <dev> - enable background operations handshake on device\n" 1099 " WARNING: This is a write-once setting.\n" 1100 #endif 1101 ); 1102 1103 /* Old command kept for compatibility. Same as 'mmc info' */ 1104 U_BOOT_CMD( 1105 mmcinfo, 1, 0, do_mmcinfo, 1106 "display MMC info", 1107 "- display info of the current MMC device" 1108 ); 1109 1110