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