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 struct mmc *mmc = find_mmc_device(curr_device); 248 if (!mmc) 249 return -1; 250 251 if (init_rpmb() != 0) 252 return -1; 253 254 ret = read_counter(mmc, requestpackets); 255 256 if (finish_rpmb() != 0) 257 return -1; 258 259 return ret; 260 } 261 262 int do_programkey(struct s_rpmb *requestpackets) 263 { 264 int ret; 265 struct mmc *mmc = find_mmc_device(curr_device); 266 if (!mmc) 267 return -1; 268 269 if (init_rpmb() != 0) 270 return -1; 271 272 ret = program_key(mmc, requestpackets); 273 274 if (finish_rpmb() != 0) 275 return -1; 276 277 return ret; 278 } 279 280 int do_authenticatedread(struct s_rpmb *requestpackets, uint16_t block_count) 281 { 282 int ret; 283 struct mmc *mmc = find_mmc_device(curr_device); 284 if (!mmc) 285 return -1; 286 287 if (init_rpmb() != 0) 288 return -1; 289 290 ret = authenticated_read(mmc, requestpackets, block_count); 291 292 if (finish_rpmb() != 0) 293 return -1; 294 295 return ret; 296 } 297 298 int do_authenticatedwrite(struct s_rpmb *requestpackets) 299 { 300 int ret; 301 struct mmc *mmc = find_mmc_device(curr_device); 302 if (!mmc) 303 return -1; 304 305 if (init_rpmb() != 0) 306 return -1; 307 308 ret = authenticated_write(mmc, requestpackets); 309 310 if (finish_rpmb() != 0) 311 return -1; 312 313 return ret; 314 } 315 316 struct mmc *do_returnmmc(void) 317 { 318 struct mmc *mmc; 319 320 if (init_rpmb() != 0) 321 return NULL; 322 323 mmc = find_mmc_device(curr_device); 324 325 if (finish_rpmb() != 0) 326 return NULL; 327 328 return mmc; 329 } 330 331 static int confirm_key_prog(void) 332 { 333 puts("Warning: Programming authentication key can be done only once !\n" 334 " Use this command only if you are sure of what you are doing,\n" 335 "Really perform the key programming? <y/N> "); 336 if (confirm_yesno()) 337 return 1; 338 339 puts("Authentication key programming aborted\n"); 340 return 0; 341 } 342 static int do_mmcrpmb_key(cmd_tbl_t *cmdtp, int flag, 343 int argc, char * const argv[]) 344 { 345 void *key_addr; 346 struct mmc *mmc = find_mmc_device(curr_device); 347 348 if (argc != 2) 349 return CMD_RET_USAGE; 350 351 key_addr = (void *)simple_strtoul(argv[1], NULL, 16); 352 if (!confirm_key_prog()) 353 return CMD_RET_FAILURE; 354 if (mmc_rpmb_set_key(mmc, key_addr)) { 355 printf("ERROR - Key already programmed ?\n"); 356 return CMD_RET_FAILURE; 357 } 358 return CMD_RET_SUCCESS; 359 } 360 static int do_mmcrpmb_read(cmd_tbl_t *cmdtp, int flag, 361 int argc, char * const argv[]) 362 { 363 u16 blk, cnt; 364 void *addr; 365 int n; 366 void *key_addr = NULL; 367 struct mmc *mmc = find_mmc_device(curr_device); 368 369 if (argc < 4) 370 return CMD_RET_USAGE; 371 372 addr = (void *)simple_strtoul(argv[1], NULL, 16); 373 blk = simple_strtoul(argv[2], NULL, 16); 374 cnt = simple_strtoul(argv[3], NULL, 16); 375 376 if (argc == 5) 377 key_addr = (void *)simple_strtoul(argv[4], NULL, 16); 378 379 printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ", 380 curr_device, blk, cnt); 381 n = mmc_rpmb_read(mmc, addr, blk, cnt, key_addr); 382 383 printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 384 if (n != cnt) 385 return CMD_RET_FAILURE; 386 return CMD_RET_SUCCESS; 387 } 388 static int do_mmcrpmb_write(cmd_tbl_t *cmdtp, int flag, 389 int argc, char * const argv[]) 390 { 391 u16 blk, cnt; 392 void *addr; 393 int n; 394 void *key_addr; 395 struct mmc *mmc = find_mmc_device(curr_device); 396 397 if (argc != 5) 398 return CMD_RET_USAGE; 399 400 addr = (void *)simple_strtoul(argv[1], NULL, 16); 401 blk = simple_strtoul(argv[2], NULL, 16); 402 cnt = simple_strtoul(argv[3], NULL, 16); 403 key_addr = (void *)simple_strtoul(argv[4], NULL, 16); 404 405 printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ", 406 curr_device, blk, cnt); 407 n = mmc_rpmb_write(mmc, addr, blk, cnt, key_addr); 408 409 printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 410 if (n != cnt) 411 return CMD_RET_FAILURE; 412 return CMD_RET_SUCCESS; 413 } 414 static int do_mmcrpmb_counter(cmd_tbl_t *cmdtp, int flag, 415 int argc, char * const argv[]) 416 { 417 unsigned long counter; 418 struct mmc *mmc = find_mmc_device(curr_device); 419 420 if (mmc_rpmb_get_counter(mmc, &counter)) 421 return CMD_RET_FAILURE; 422 printf("RPMB Write counter= %lx\n", counter); 423 return CMD_RET_SUCCESS; 424 } 425 426 static cmd_tbl_t cmd_rpmb[] = { 427 U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""), 428 U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""), 429 U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""), 430 U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""), 431 }; 432 433 static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag, 434 int argc, char * const argv[]) 435 { 436 cmd_tbl_t *cp; 437 struct mmc *mmc; 438 char original_part; 439 int ret; 440 441 cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb)); 442 443 /* Drop the rpmb subcommand */ 444 argc--; 445 argv++; 446 447 if (cp == NULL || argc > cp->maxargs) 448 return CMD_RET_USAGE; 449 if (flag == CMD_FLAG_REPEAT && !cp->repeatable) 450 return CMD_RET_SUCCESS; 451 452 mmc = init_mmc_device(curr_device, false); 453 if (!mmc) 454 return CMD_RET_FAILURE; 455 456 if (!(mmc->version & MMC_VERSION_MMC)) { 457 printf("It is not a EMMC device\n"); 458 return CMD_RET_FAILURE; 459 } 460 if (mmc->version < MMC_VERSION_4_41) { 461 printf("RPMB not supported before version 4.41\n"); 462 return CMD_RET_FAILURE; 463 } 464 /* Switch to the RPMB partition */ 465 #ifndef CONFIG_BLK 466 original_part = mmc->block_dev.hwpart; 467 #else 468 original_part = mmc_get_blk_desc(mmc)->hwpart; 469 #endif 470 if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) != 471 0) 472 return CMD_RET_FAILURE; 473 ret = cp->cmd(cmdtp, flag, argc, argv); 474 475 /* Return to original partition */ 476 if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) != 477 0) 478 return CMD_RET_FAILURE; 479 return ret; 480 } 481 #endif 482 483 static int do_mmc_read(cmd_tbl_t *cmdtp, int flag, 484 int argc, char * const argv[]) 485 { 486 struct mmc *mmc; 487 u32 blk, cnt, n; 488 void *addr; 489 490 if (argc != 4) 491 return CMD_RET_USAGE; 492 493 addr = (void *)simple_strtoul(argv[1], NULL, 16); 494 blk = simple_strtoul(argv[2], NULL, 16); 495 cnt = simple_strtoul(argv[3], NULL, 16); 496 497 mmc = init_mmc_device(curr_device, false); 498 if (!mmc) 499 return CMD_RET_FAILURE; 500 501 printf("\nMMC read: dev # %d, block # %d, count %d ... ", 502 curr_device, blk, cnt); 503 504 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr); 505 printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 506 507 return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; 508 } 509 static int do_mmc_write(cmd_tbl_t *cmdtp, int flag, 510 int argc, char * const argv[]) 511 { 512 struct mmc *mmc; 513 u32 blk, cnt, n; 514 void *addr; 515 516 if (argc != 4) 517 return CMD_RET_USAGE; 518 519 addr = (void *)simple_strtoul(argv[1], NULL, 16); 520 blk = simple_strtoul(argv[2], NULL, 16); 521 cnt = simple_strtoul(argv[3], NULL, 16); 522 523 mmc = init_mmc_device(curr_device, false); 524 if (!mmc) 525 return CMD_RET_FAILURE; 526 527 printf("\nMMC write: dev # %d, block # %d, count %d ... ", 528 curr_device, blk, cnt); 529 530 if (mmc_getwp(mmc) == 1) { 531 printf("Error: card is write protected!\n"); 532 return CMD_RET_FAILURE; 533 } 534 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr); 535 printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 536 537 return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; 538 } 539 static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag, 540 int argc, char * const argv[]) 541 { 542 struct mmc *mmc; 543 u32 blk, cnt, n; 544 545 if (argc != 3) 546 return CMD_RET_USAGE; 547 548 blk = simple_strtoul(argv[1], NULL, 16); 549 cnt = simple_strtoul(argv[2], NULL, 16); 550 551 mmc = init_mmc_device(curr_device, false); 552 if (!mmc) 553 return CMD_RET_FAILURE; 554 555 printf("\nMMC erase: dev # %d, block # %d, count %d ... ", 556 curr_device, blk, cnt); 557 558 if (mmc_getwp(mmc) == 1) { 559 printf("Error: card is write protected!\n"); 560 return CMD_RET_FAILURE; 561 } 562 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt); 563 printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR"); 564 565 return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; 566 } 567 static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag, 568 int argc, char * const argv[]) 569 { 570 struct mmc *mmc; 571 572 mmc = init_mmc_device(curr_device, true); 573 if (!mmc) 574 return CMD_RET_FAILURE; 575 576 return CMD_RET_SUCCESS; 577 } 578 static int do_mmc_part(cmd_tbl_t *cmdtp, int flag, 579 int argc, char * const argv[]) 580 { 581 struct blk_desc *mmc_dev; 582 struct mmc *mmc; 583 584 mmc = init_mmc_device(curr_device, false); 585 if (!mmc) 586 return CMD_RET_FAILURE; 587 588 mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device); 589 if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) { 590 part_print(mmc_dev); 591 return CMD_RET_SUCCESS; 592 } 593 594 puts("get mmc type error!\n"); 595 return CMD_RET_FAILURE; 596 } 597 static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag, 598 int argc, char * const argv[]) 599 { 600 int dev, part = 0, ret; 601 struct mmc *mmc; 602 603 /* If not boot from mmc devices, init mmc devices first. */ 604 ret = mmc_initialize(gd->bd); 605 if (ret) { 606 printf("Could not initialize mmc. error: %d\n", ret); 607 return ret; 608 } 609 610 if (argc == 1) { 611 dev = curr_device; 612 } else if (argc == 2) { 613 dev = simple_strtoul(argv[1], NULL, 10); 614 } else if (argc == 3) { 615 dev = (int)simple_strtoul(argv[1], NULL, 10); 616 part = (int)simple_strtoul(argv[2], NULL, 10); 617 if (part > PART_ACCESS_MASK) { 618 printf("#part_num shouldn't be larger than %d\n", 619 PART_ACCESS_MASK); 620 return CMD_RET_FAILURE; 621 } 622 } else { 623 return CMD_RET_USAGE; 624 } 625 626 mmc = init_mmc_device(dev, false); 627 if (!mmc) 628 return CMD_RET_FAILURE; 629 630 ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part); 631 printf("switch to partitions #%d, %s\n", 632 part, (!ret) ? "OK" : "ERROR"); 633 if (ret) 634 return 1; 635 636 curr_device = dev; 637 if (mmc->part_config == MMCPART_NOAVAILABLE) 638 printf("mmc%d is current device\n", curr_device); 639 else 640 printf("mmc%d(part %d) is current device\n", 641 curr_device, mmc_get_blk_desc(mmc)->hwpart); 642 643 return CMD_RET_SUCCESS; 644 } 645 static int do_mmc_list(cmd_tbl_t *cmdtp, int flag, 646 int argc, char * const argv[]) 647 { 648 print_mmc_devices('\n'); 649 return CMD_RET_SUCCESS; 650 } 651 652 static int parse_hwpart_user(struct mmc_hwpart_conf *pconf, 653 int argc, char * const argv[]) 654 { 655 int i = 0; 656 657 memset(&pconf->user, 0, sizeof(pconf->user)); 658 659 while (i < argc) { 660 if (!strcmp(argv[i], "enh")) { 661 if (i + 2 >= argc) 662 return -1; 663 pconf->user.enh_start = 664 simple_strtoul(argv[i+1], NULL, 10); 665 pconf->user.enh_size = 666 simple_strtoul(argv[i+2], NULL, 10); 667 i += 3; 668 } else if (!strcmp(argv[i], "wrrel")) { 669 if (i + 1 >= argc) 670 return -1; 671 pconf->user.wr_rel_change = 1; 672 if (!strcmp(argv[i+1], "on")) 673 pconf->user.wr_rel_set = 1; 674 else if (!strcmp(argv[i+1], "off")) 675 pconf->user.wr_rel_set = 0; 676 else 677 return -1; 678 i += 2; 679 } else { 680 break; 681 } 682 } 683 return i; 684 } 685 686 static int parse_hwpart_gp(struct mmc_hwpart_conf *pconf, int pidx, 687 int argc, char * const argv[]) 688 { 689 int i; 690 691 memset(&pconf->gp_part[pidx], 0, sizeof(pconf->gp_part[pidx])); 692 693 if (1 >= argc) 694 return -1; 695 pconf->gp_part[pidx].size = simple_strtoul(argv[0], NULL, 10); 696 697 i = 1; 698 while (i < argc) { 699 if (!strcmp(argv[i], "enh")) { 700 pconf->gp_part[pidx].enhanced = 1; 701 i += 1; 702 } else if (!strcmp(argv[i], "wrrel")) { 703 if (i + 1 >= argc) 704 return -1; 705 pconf->gp_part[pidx].wr_rel_change = 1; 706 if (!strcmp(argv[i+1], "on")) 707 pconf->gp_part[pidx].wr_rel_set = 1; 708 else if (!strcmp(argv[i+1], "off")) 709 pconf->gp_part[pidx].wr_rel_set = 0; 710 else 711 return -1; 712 i += 2; 713 } else { 714 break; 715 } 716 } 717 return i; 718 } 719 720 static int do_mmc_hwpartition(cmd_tbl_t *cmdtp, int flag, 721 int argc, char * const argv[]) 722 { 723 struct mmc *mmc; 724 struct mmc_hwpart_conf pconf = { }; 725 enum mmc_hwpart_conf_mode mode = MMC_HWPART_CONF_CHECK; 726 int i, r, pidx; 727 728 mmc = init_mmc_device(curr_device, false); 729 if (!mmc) 730 return CMD_RET_FAILURE; 731 732 if (argc < 1) 733 return CMD_RET_USAGE; 734 i = 1; 735 while (i < argc) { 736 if (!strcmp(argv[i], "user")) { 737 i++; 738 r = parse_hwpart_user(&pconf, argc-i, &argv[i]); 739 if (r < 0) 740 return CMD_RET_USAGE; 741 i += r; 742 } else if (!strncmp(argv[i], "gp", 2) && 743 strlen(argv[i]) == 3 && 744 argv[i][2] >= '1' && argv[i][2] <= '4') { 745 pidx = argv[i][2] - '1'; 746 i++; 747 r = parse_hwpart_gp(&pconf, pidx, argc-i, &argv[i]); 748 if (r < 0) 749 return CMD_RET_USAGE; 750 i += r; 751 } else if (!strcmp(argv[i], "check")) { 752 mode = MMC_HWPART_CONF_CHECK; 753 i++; 754 } else if (!strcmp(argv[i], "set")) { 755 mode = MMC_HWPART_CONF_SET; 756 i++; 757 } else if (!strcmp(argv[i], "complete")) { 758 mode = MMC_HWPART_CONF_COMPLETE; 759 i++; 760 } else { 761 return CMD_RET_USAGE; 762 } 763 } 764 765 puts("Partition configuration:\n"); 766 if (pconf.user.enh_size) { 767 puts("\tUser Enhanced Start: "); 768 print_size(((u64)pconf.user.enh_start) << 9, "\n"); 769 puts("\tUser Enhanced Size: "); 770 print_size(((u64)pconf.user.enh_size) << 9, "\n"); 771 } else { 772 puts("\tNo enhanced user data area\n"); 773 } 774 if (pconf.user.wr_rel_change) 775 printf("\tUser partition write reliability: %s\n", 776 pconf.user.wr_rel_set ? "on" : "off"); 777 for (pidx = 0; pidx < 4; pidx++) { 778 if (pconf.gp_part[pidx].size) { 779 printf("\tGP%i Capacity: ", pidx+1); 780 print_size(((u64)pconf.gp_part[pidx].size) << 9, 781 pconf.gp_part[pidx].enhanced ? 782 " ENH\n" : "\n"); 783 } else { 784 printf("\tNo GP%i partition\n", pidx+1); 785 } 786 if (pconf.gp_part[pidx].wr_rel_change) 787 printf("\tGP%i write reliability: %s\n", pidx+1, 788 pconf.gp_part[pidx].wr_rel_set ? "on" : "off"); 789 } 790 791 if (!mmc_hwpart_config(mmc, &pconf, mode)) { 792 if (mode == MMC_HWPART_CONF_COMPLETE) 793 puts("Partitioning successful, " 794 "power-cycle to make effective\n"); 795 return CMD_RET_SUCCESS; 796 } else { 797 puts("Failed!\n"); 798 return CMD_RET_FAILURE; 799 } 800 } 801 802 #ifdef CONFIG_SUPPORT_EMMC_BOOT 803 static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag, 804 int argc, char * const argv[]) 805 { 806 int dev; 807 struct mmc *mmc; 808 u8 width, reset, mode; 809 810 if (argc != 5) 811 return CMD_RET_USAGE; 812 dev = simple_strtoul(argv[1], NULL, 10); 813 width = simple_strtoul(argv[2], NULL, 10); 814 reset = simple_strtoul(argv[3], NULL, 10); 815 mode = simple_strtoul(argv[4], NULL, 10); 816 817 mmc = init_mmc_device(dev, false); 818 if (!mmc) 819 return CMD_RET_FAILURE; 820 821 if (IS_SD(mmc)) { 822 puts("BOOT_BUS_WIDTH only exists on eMMC\n"); 823 return CMD_RET_FAILURE; 824 } 825 826 /* acknowledge to be sent during boot operation */ 827 return mmc_set_boot_bus_width(mmc, width, reset, mode); 828 } 829 static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag, 830 int argc, char * const argv[]) 831 { 832 int dev; 833 struct mmc *mmc; 834 u32 bootsize, rpmbsize; 835 836 if (argc != 4) 837 return CMD_RET_USAGE; 838 dev = simple_strtoul(argv[1], NULL, 10); 839 bootsize = simple_strtoul(argv[2], NULL, 10); 840 rpmbsize = simple_strtoul(argv[3], NULL, 10); 841 842 mmc = init_mmc_device(dev, false); 843 if (!mmc) 844 return CMD_RET_FAILURE; 845 846 if (IS_SD(mmc)) { 847 printf("It is not a EMMC device\n"); 848 return CMD_RET_FAILURE; 849 } 850 851 if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) { 852 printf("EMMC boot partition Size change Failed.\n"); 853 return CMD_RET_FAILURE; 854 } 855 856 printf("EMMC boot partition Size %d MB\n", bootsize); 857 printf("EMMC RPMB partition Size %d MB\n", rpmbsize); 858 return CMD_RET_SUCCESS; 859 } 860 861 static int mmc_partconf_print(struct mmc *mmc) 862 { 863 u8 ack, access, part; 864 865 if (mmc->part_config == MMCPART_NOAVAILABLE) { 866 printf("No part_config info for ver. 0x%x\n", mmc->version); 867 return CMD_RET_FAILURE; 868 } 869 870 access = EXT_CSD_EXTRACT_PARTITION_ACCESS(mmc->part_config); 871 ack = EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config); 872 part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config); 873 874 printf("EXT_CSD[179], PARTITION_CONFIG:\n" 875 "BOOT_ACK: 0x%x\n" 876 "BOOT_PARTITION_ENABLE: 0x%x\n" 877 "PARTITION_ACCESS: 0x%x\n", ack, part, access); 878 879 return CMD_RET_SUCCESS; 880 } 881 882 static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag, 883 int argc, char * const argv[]) 884 { 885 int dev; 886 struct mmc *mmc; 887 u8 ack, part_num, access; 888 889 if (argc != 2 && argc != 5) 890 return CMD_RET_USAGE; 891 892 dev = simple_strtoul(argv[1], NULL, 10); 893 894 mmc = init_mmc_device(dev, false); 895 if (!mmc) 896 return CMD_RET_FAILURE; 897 898 if (IS_SD(mmc)) { 899 puts("PARTITION_CONFIG only exists on eMMC\n"); 900 return CMD_RET_FAILURE; 901 } 902 903 if (argc == 2) 904 return mmc_partconf_print(mmc); 905 906 ack = simple_strtoul(argv[2], NULL, 10); 907 part_num = simple_strtoul(argv[3], NULL, 10); 908 access = simple_strtoul(argv[4], NULL, 10); 909 910 /* acknowledge to be sent during boot operation */ 911 return mmc_set_part_conf(mmc, ack, part_num, access); 912 } 913 static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag, 914 int argc, char * const argv[]) 915 { 916 int dev; 917 struct mmc *mmc; 918 u8 enable; 919 920 /* 921 * Set the RST_n_ENABLE bit of RST_n_FUNCTION 922 * The only valid values are 0x0, 0x1 and 0x2 and writing 923 * a value of 0x1 or 0x2 sets the value permanently. 924 */ 925 if (argc != 3) 926 return CMD_RET_USAGE; 927 928 dev = simple_strtoul(argv[1], NULL, 10); 929 enable = simple_strtoul(argv[2], NULL, 10); 930 931 if (enable > 2) { 932 puts("Invalid RST_n_ENABLE value\n"); 933 return CMD_RET_USAGE; 934 } 935 936 mmc = init_mmc_device(dev, false); 937 if (!mmc) 938 return CMD_RET_FAILURE; 939 940 if (IS_SD(mmc)) { 941 puts("RST_n_FUNCTION only exists on eMMC\n"); 942 return CMD_RET_FAILURE; 943 } 944 945 return mmc_set_rst_n_function(mmc, enable); 946 } 947 #endif 948 static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag, 949 int argc, char * const argv[]) 950 { 951 struct mmc *mmc; 952 u32 val; 953 int ret; 954 955 if (argc != 2) 956 return CMD_RET_USAGE; 957 val = simple_strtoul(argv[1], NULL, 16); 958 959 mmc = find_mmc_device(curr_device); 960 if (!mmc) { 961 printf("no mmc device at slot %x\n", curr_device); 962 return CMD_RET_FAILURE; 963 } 964 ret = mmc_set_dsr(mmc, val); 965 printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR"); 966 if (!ret) { 967 mmc->has_init = 0; 968 if (mmc_init(mmc)) 969 return CMD_RET_FAILURE; 970 else 971 return CMD_RET_SUCCESS; 972 } 973 return ret; 974 } 975 976 #ifdef CONFIG_CMD_BKOPS_ENABLE 977 static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag, 978 int argc, char * const argv[]) 979 { 980 int dev; 981 struct mmc *mmc; 982 983 if (argc != 2) 984 return CMD_RET_USAGE; 985 986 dev = simple_strtoul(argv[1], NULL, 10); 987 988 mmc = init_mmc_device(dev, false); 989 if (!mmc) 990 return CMD_RET_FAILURE; 991 992 if (IS_SD(mmc)) { 993 puts("BKOPS_EN only exists on eMMC\n"); 994 return CMD_RET_FAILURE; 995 } 996 997 return mmc_set_bkops_enable(mmc); 998 } 999 #endif 1000 1001 static cmd_tbl_t cmd_mmc[] = { 1002 U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), 1003 U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""), 1004 U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""), 1005 U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""), 1006 U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""), 1007 U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""), 1008 U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""), 1009 U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""), 1010 U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""), 1011 #ifdef CONFIG_SUPPORT_EMMC_BOOT 1012 U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""), 1013 U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""), 1014 U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""), 1015 U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""), 1016 #endif 1017 #ifdef CONFIG_OPTEE_CLIENT 1018 U_BOOT_CMD_MKENT(testsecurestorage, 1, 0, do_mmc_test_secure_storage, "", ""), 1019 U_BOOT_CMD_MKENT(testefuse, 1, 0, do_mmc_testefuse, "", ""), 1020 #endif 1021 #ifdef CONFIG_SUPPORT_EMMC_RPMB 1022 U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), 1023 #endif 1024 U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), 1025 #ifdef CONFIG_CMD_BKOPS_ENABLE 1026 U_BOOT_CMD_MKENT(bkops-enable, 2, 0, do_mmc_bkops_enable, "", ""), 1027 #endif 1028 }; 1029 1030 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 1031 { 1032 cmd_tbl_t *cp; 1033 1034 cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc)); 1035 1036 /* Drop the mmc command */ 1037 argc--; 1038 argv++; 1039 1040 if (cp == NULL || argc > cp->maxargs) 1041 return CMD_RET_USAGE; 1042 if (flag == CMD_FLAG_REPEAT && !cp->repeatable) 1043 return CMD_RET_SUCCESS; 1044 1045 if (curr_device < 0) { 1046 if (get_mmc_num() > 0) { 1047 curr_device = 0; 1048 } else { 1049 puts("No MMC device available\n"); 1050 return CMD_RET_FAILURE; 1051 } 1052 } 1053 return cp->cmd(cmdtp, flag, argc, argv); 1054 } 1055 1056 U_BOOT_CMD( 1057 mmc, 29, 1, do_mmcops, 1058 "MMC sub system", 1059 "info - display info of the current MMC device\n" 1060 "mmc read addr blk# cnt\n" 1061 "mmc write addr blk# cnt\n" 1062 "mmc erase blk# cnt\n" 1063 "mmc rescan\n" 1064 "mmc part - lists available partition on current mmc device\n" 1065 "mmc dev [dev] [part] - show or set current mmc device [partition]\n" 1066 "mmc list - lists available devices\n" 1067 "mmc hwpartition [args...] - does hardware partitioning\n" 1068 " arguments (sizes in 512-byte blocks):\n" 1069 " [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n" 1070 " [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n" 1071 " [check|set|complete] - mode, complete set partitioning completed\n" 1072 " WARNING: Partitioning is a write-once setting once it is set to complete.\n" 1073 " Power cycling is required to initialize partitions after set to complete.\n" 1074 #ifdef CONFIG_SUPPORT_EMMC_BOOT 1075 "mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n" 1076 " - Set the BOOT_BUS_WIDTH field of the specified device\n" 1077 "mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n" 1078 " - Change sizes of boot and RPMB partitions of specified device\n" 1079 "mmc partconf dev [boot_ack boot_partition partition_access]\n" 1080 " - Show or change the bits of the PARTITION_CONFIG field of the specified device\n" 1081 "mmc rst-function dev value\n" 1082 " - Change the RST_n_FUNCTION field of the specified device\n" 1083 " WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n" 1084 #endif 1085 #ifdef CONFIG_OPTEE_CLIENT 1086 "mmc testsecurestorage - test CA call static TA to store data in security\n" 1087 "mmc testefuse - test CA call static TA,and TA read or write efuse\n" 1088 #endif 1089 #ifdef CONFIG_SUPPORT_EMMC_RPMB 1090 "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n" 1091 "mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n" 1092 "mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n" 1093 "mmc rpmb counter - read the value of the write counter\n" 1094 #endif 1095 "mmc setdsr <value> - set DSR register value\n" 1096 #ifdef CONFIG_CMD_BKOPS_ENABLE 1097 "mmc bkops-enable <dev> - enable background operations handshake on device\n" 1098 " WARNING: This is a write-once setting.\n" 1099 #endif 1100 ); 1101 1102 /* Old command kept for compatibility. Same as 'mmc info' */ 1103 U_BOOT_CMD( 1104 mmcinfo, 1, 0, do_mmcinfo, 1105 "display MMC info", 1106 "- display info of the current MMC device" 1107 ); 1108 1109