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