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