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