blob: 69464a57d094ad83df22dda212f17f12e276e222 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <malloc.h>
8#include <command.h>
9#include <linux/ctype.h>
10#include <amlogic/mmc.h>
11#include "../drivers/mmc/mmc_private.h"
12#include <amlogic/partition_table.h>
13#include <amlogic/emmc_partitions.h>
14#include <asm/amlogic/arch/cpu_sdio.h>
15#include <asm/amlogic/arch/sd_emmc.h>
16#include <linux/sizes.h>
17#include <amlogic/cpu_id.h>
18#include <amlogic/aml_mmc.h>
19#include <linux/crc32.h>
20#include "../drivers/mtd/ubi/crc32.c"
21
22/* info system. */
23#define dtb_err(fmt, ...) printf( "%s()-%d: " fmt , \
24 __func__, __LINE__, ##__VA_ARGS__)
25
26#define dtb_wrn(fmt, ...) printf( "%s()-%d: " fmt , \
27 __func__, __LINE__, ##__VA_ARGS__)
28
29/* for detail debug info */
30#define dtb_info(fmt, ...) printf( "%s()-%d: " fmt , \
31 __func__, __LINE__, ##__VA_ARGS__)
32
33#define fb_err(fmt, ...) printf("%s()-%d: " fmt , \
34 __func__, __LINE__, ##__VA_ARGS__)
35#define CONFIG_SYS_MMC_ENV_DEV 1
36struct aml_dtb_rsv {
37 u8 data[DTB_BLK_SIZE*DTB_BLK_CNT - 4*sizeof(u32)];
38 u32 magic;
39 u32 version;
40 u32 timestamp;
41 u32 checksum;
42};
43
44struct aml_dtb_info {
45 u32 stamp[2];
46 u8 valid[2];
47};
48
49#define stamp_after(a,b) ((int)(b) - (int)(a) < 0)
50/* glb dtb infos */
51static struct aml_dtb_info dtb_infos = {{0, 0}, {0, 0}};
52
53#define CONFIG_SECURITYKEY
54
55#if !defined(CONFIG_SYS_MMC_BOOT_DEV)
56 #define CONFIG_SYS_MMC_BOOT_DEV (CONFIG_SYS_MMC_ENV_DEV)
57#endif
58
59#define GXB_START_BLK 0
60#define GXL_START_BLK 1
61
62/* max 2MB for emmc in blks */
63#define UBOOT_SIZE (0x1000)
64
65
66extern int mmc_key_write(unsigned char *buf, unsigned int size, uint32_t *actual_length);
67extern int mmc_key_read(unsigned char *buf, unsigned int size, uint32_t *actual_length);
68
69/* move this out to storage */
70//int info_disprotect = 0;
71
72
73int mmc_read_status(struct mmc *mmc, int timeout)
74{
75 struct mmc_cmd cmd;
76 int err, retries = 5;
77 int status;
78
79 cmd.cmdidx = MMC_CMD_SEND_STATUS;
80 cmd.resp_type = MMC_RSP_R1;
81 if (!mmc_host_is_spi(mmc))
82 cmd.cmdarg = mmc->rca << 16;
83 do {
84 err = mmc_send_cmd(mmc, &cmd, NULL);
85 if (!err) {
86 if ((cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) &&
87 (cmd.response[0] & MMC_STATUS_CURR_STATE) !=
88 MMC_STATE_PRG)
89 break;
90 else if (cmd.response[0] & MMC_STATUS_MASK) {
91 printf("Status Error: 0x%08X\n",
92 cmd.response[0]);
93 return -18;
94 }
95 } else if (--retries < 0)
96 return err;
97
98 udelay(1000);
99
100 } while (timeout--);
101
102 status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
103 printf("CURR STATE:%d, status = 0x%x\n", status, cmd.response[0]);
104
105 if (timeout <= 0) {
106 printf("read status Timeout waiting card ready\n");
107 return -19;
108 }
109 if (cmd.response[0] & MMC_STATUS_SWITCH_ERROR) {
110 printf("mmc status switch error status =0x%x\n", status);
111 return -21;
112 }
113 return 0;
114}
115
116bool emmckey_is_protected (struct mmc *mmc)
117{
118#ifdef CONFIG_STORE_COMPATIBLE
119#ifdef CONFIG_SECURITYKEY
120 if (info_disprotect & DISPROTECT_KEY) {
121 printf("%s(): disprotect\n", __func__);
122 return 0;
123 }else{
124 printf("%s(): protect\n", __func__);
125 return 1;
126 }
127#else
128 return 0;
129#endif
130#else
131#ifdef CONFIG_SECURITYKEY
132 //return mmc->key_protect;
133 return 0; /* fixme, */
134#else
135 return 0;
136#endif
137#endif
138}
139
140unsigned emmc_cur_partition = 0;
141
142
143static int get_off_size(struct mmc * mmc, char * name, uint64_t offset, uint64_t size, u64 * blk, u64 * cnt, u64 * sz_byte)
144{
145 struct partitions *part_info = NULL;
146 uint64_t off = 0;
147 int blk_shift = 0;
148
149 blk_shift = ffs(mmc->read_bl_len) - 1;
150 if (blk_shift < 0) {
151 printf("Bad shift.\n");
152 return 0;
153 }
154 // printf("blk_shift:%d , off:0x%llx , size:0x%llx.\n ",blk_shift,off,size );
155 part_info = find_mmc_partition_by_name(name);
156 if (part_info == NULL) {
157 printf("get partition info failed !!\n");
158 return -1;
159 }
160 off = part_info->offset + offset;
161
162 // printf("part_info->offset:0x%llx , off:0x%llx , size:0x%llx.\n",part_info->offset ,off,size);
163
164 *blk = off >> blk_shift;
165 *cnt = size >> blk_shift;
166 *sz_byte = size - ((*cnt) << blk_shift);
167
168 // printf("get_partition_off_size : blk:0x%llx , cnt:0x%llx.\n",*blk,*cnt);
169 return 0;
170}
171
172static int get_partition_size(unsigned char* name, uint64_t* addr)
173{
174 struct partitions *part_info = NULL;
175 part_info = find_mmc_partition_by_name((char *)name);
176 if (part_info == NULL) {
177 printf("get partition info failed !!\n");
178 return -1;
179 }
180
181 *addr = part_info->size >> 9; // unit: 512 bytes
182 return 0;
183}
184
185static inline int isstring(char *p)
186{
187 char *endptr = p;
188 while (*endptr != '\0') {
189 if (!(((*endptr >= '0') && (*endptr <= '9'))
190 || ((*endptr >= 'a') && (*endptr <= 'f'))
191 || ((*endptr >= 'A') && (*endptr <= 'F'))
192 || (*endptr == 'x') || (*endptr == 'X')))
193 return 1;
194 endptr++;
195 }
196
197 return 0;
198}
199
200/*
201 erase bootloader on user/boot0/boot1 which indicate by map.
202 bit 0: user
203 bit 1: boot0
204 bit 2: boot1
205*/
206int amlmmc_erase_bootloader(int dev, int map)
207{
208 int ret = 0, i, count = 3;
209 int blk_shift;
210 unsigned long n;
211 char *partname[3] = {"user", "boot0", "boot1"};
212 cpu_id_t cpu_id = get_cpu_id();
213 struct mmc *mmc = find_mmc_device(dev);
214
215 /* do nothing */
216 if (0 == map)
217 goto _out;
218
219 if (!mmc) {
220 printf("%s() %d: not valid emmc %d\n", __func__, __LINE__, dev);
221 ret = -1;
222 goto _out;
223 }
224 /* make sure mmc is initialized! */
225 ret = mmc_init(mmc);
226 if (ret) {
227 printf("%s() %d: emmc %d init %d\n", __func__, __LINE__, dev, ret);
228 ret = -2;
229 goto _out;
230 }
231
232 blk_shift = ffs(mmc->read_bl_len) -1;
233 if (blk_shift < 0) {
234 printf("bad shift.\n");
235 ret = -3;
236 goto _out;
237 }
238 /* erase bootloader in user/boot0/boot1 */
239 for (i = 0; i < count; i++) {
240 if (map & (0x1 << i)) {
241 if (!blk_select_hwpart_devnum(IF_TYPE_MMC, 1, i)) {
242 lbaint_t start = 0, blkcnt;
243
244 blkcnt = mmc->capacity >> blk_shift;
245 if (0 == i) {
246 struct partitions *part_info;
247 /* get info by partition */
248 part_info = find_mmc_partition_by_name(MMC_BOOT_NAME);
249 if (part_info == NULL) {
250 printf("%s() %d: error!!\n", __func__, __LINE__);
251 /* fixme, do somthing! */
252 continue;
253 } else {
254 start = part_info->offset >> blk_shift;
255 blkcnt = part_info->size >> blk_shift;
256 if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL) {
257 start = GXL_START_BLK;
258 blkcnt -= GXL_START_BLK;
259 }
260 }
261 }
262/* some customer may use boot1 higher 2M as private data. */
263#ifdef CONFIG_EMMC_BOOT1_TOUCH_REGION
264 if (2 == i && CONFIG_EMMC_BOOT1_TOUCH_REGION <= mmc->capacity) {
265 blkcnt = CONFIG_EMMC_BOOT1_TOUCH_REGION >> blk_shift;
266 }
267#endif/* CONFIG_EMMC_BOOT1_TOUCH_REGION */
268
269 if (i == 0 && (aml_gpt_valid(mmc) == 0))
270 continue;
271
272 printf("Erasing blocks " LBAFU " to " LBAFU " @ %s\n",
273 start, blkcnt, partname[i]);
274 n = blk_derase(mmc_get_blk_desc(mmc), start, blkcnt);
275 if (n != 0) {
276 printf("mmc erase %s failed\n", partname[i]);
277 ret = -3;
278 break;
279 }
280 } else
281 printf("%s() %d: switch dev %d to %s fail\n",
282 __func__, __LINE__, dev, partname[i]);
283 }
284 }
285 /* try to switch back to user. */
286 blk_select_hwpart(mmc->dev, 0);
287
288_out:
289 return ret;
290}
291
292/*
293 write bootloader on user/boot0/boot1 which indicate by map.
294 bit 0: user
295 bit 1: boot0
296 bit 2: boot1
297*/
298int amlmmc_write_bootloader(int dev, int map, unsigned int size, const void *src)
299{
300 int ret = 0, i, count = 3;
301 unsigned long n;
302 char *partname[3] = {"user", "boot0", "boot1"};
303 struct mmc *mmc = find_mmc_device(dev);
304 lbaint_t start = GXB_START_BLK, blkcnt;
305 cpu_id_t cpu_id = get_cpu_id();
306
307 /* do nothing */
308 if (0 == map)
309 goto _out;
310
311 if (!mmc) {
312 printf("%s() %d: not valid emmc %d\n", __func__, __LINE__, dev);
313 ret = -1;
314 goto _out;
315 }
316 /* make sure mmc is initialized! */
317 ret = mmc_init(mmc);
318 if (ret) {
319 printf("%s() %d: emmc %d init %d\n", __func__, __LINE__, dev, ret);
320 ret = -2;
321 goto _out;
322 }
323
324 if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL)
325 start = GXL_START_BLK;
326 blkcnt = (size + mmc->read_bl_len - 1) / mmc->read_bl_len;
327
328 /* erase bootloader in user/boot0/boot1 */
329 for (i = 0; i < count; i++) {
330 if (map & (0x1 << i)) {
331 if (!blk_select_hwpart_devnum(IF_TYPE_MMC, 1, i)) {
332/* some customer may use boot1 higher 2M as private data. */
333#ifdef CONFIG_EMMC_BOOT1_TOUCH_REGION
334 if (2 == i && CONFIG_EMMC_BOOT1_TOUCH_REGION <= size) {
335 printf("%s(), size %d exceeds TOUCH_REGION %d, skip\n",
336 __func__, size, CONFIG_EMMC_BOOT1_TOUCH_REGION);
337 break;
338 }
339#endif /* CONFIG_EMMC_BOOT1_TOUCH_REGION */
340 if (i == 0 && (aml_gpt_valid(mmc) == 0))
341 continue;
342
343 printf("Writing blocks " LBAFU " to " LBAFU " @ %s\n",
344 start, blkcnt, partname[i]);
345 n = blk_dwrite(mmc_get_blk_desc(mmc), start, blkcnt, src);
346 if (n != blkcnt) {
347 printf("mmc write %s failed\n", partname[i]);
348 ret = -3;
349 break;
350 }
351 } else
352 printf("%s() %d: switch dev %d to %s fail\n",
353 __func__, __LINE__, dev, partname[i]);
354 }
355 }
356 /* try to switch back to user. */
357 blk_select_hwpart(mmc->dev, 0);
358
359_out:
360 return ret;
361}
362
363static int amlmmc_erase_in_dev(int argc, char *const argv[])
364{
365 int dev = 0;
366 u64 cnt = 0, blk = 0, n = 0;
367 struct mmc *mmc;
368
369 dev = simple_strtoul(argv[2], NULL, 10);
370 blk = simple_strtoull(argv[3], NULL, 16);
371 cnt = simple_strtoull(argv[4], NULL, 16);
372
373 if (dev < 0) {
374 printf("Cannot find dev.\n");
375 return 1;
376 }
377
378 mmc = find_mmc_device(dev);
379
380 if (!mmc)
381 return 1;
382
383 printf("MMC erase: dev # %d, start_erase_address(in block) # %#llx,\
384 several blocks # %lld will be erased ...\n ",
385 dev, blk, cnt);
386
387 mmc_init(mmc);
388
389 if (cnt != 0)
390 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
391
392 printf("dev # %d, %s, several blocks erased %s\n",
393 dev, " ", (n == 0) ? "OK" : "ERROR");
394
395 return (n == 0) ? 0 : 1;
396}
397
398static int amlmmc_erase_in_card(int argc, char *const argv[])
399{
400 int dev = 0;
401 u64 cnt = 0, blk = 0, n = 0;
402 /*sz_byte =0;*/
403 char *name = NULL;
404 u64 offset_addr = 0, size = 0;
405 struct mmc *mmc;
406 int tmp_shift;
407
408 name = argv[2];
409 dev = find_dev_num_by_partition_name (name);
410 if (dev < 0) {
411 printf("Cannot find dev.\n");
412 return 1;
413 }
414 offset_addr = simple_strtoull(argv[3], NULL, 16);
415 size = simple_strtoull(argv[4], NULL, 16);
416 mmc = find_mmc_device(dev);
417 if (!mmc) {
418 printf("[%s] no mmc devices available\n", __func__);
419 return 1;
420 }
421
422 tmp_shift = ffs(mmc->read_bl_len) -1;
423 if (tmp_shift < 0) {
424 printf("bad shift.\n");
425 return 1;
426 }
427 cnt = size >> tmp_shift;
428 blk = offset_addr >> tmp_shift;
429 /* sz_byte = size - (cnt<<tmp_shift); */
430
431
432 mmc = find_mmc_device(dev);
433 if (!mmc) {
434 printf("[%s] no mmc devices available\n", __func__);
435 return 1;
436 }
437
438 printf("MMC erase: dev # %d, start_erase_address(in block) # %#llx,\
439 several blocks # %lld will be erased ...\n ",
440 dev, blk, cnt);
441
442 mmc_init(mmc);
443
444 if (cnt != 0)
445 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
446
447 printf("dev # %d, %s, several blocks erased %s\n",
448 dev, argv[2], (n == 0) ? "OK" : "ERROR");
449
450 return (n == 0) ? 0 : 1;
451}
452
453static int amlmmc_erase_in_part(int argc, char *const argv[])
454{
455 int dev = 0;
456 u64 cnt = 0, blk = 0, n = 0, sz_byte =0;
457 char *name = NULL;
458 u64 offset_addr = 0, size = 0;
459 struct mmc *mmc;
460 struct partitions *part_info;
461
462 name = argv[2];
463 dev = find_dev_num_by_partition_name(name);
464 if (dev < 0) {
465 printf("Cannot find dev.\n");
466 return 1;
467 }
468 offset_addr = simple_strtoull(argv[3], NULL, 16);
469 size = simple_strtoull(argv[4], NULL, 16);
470 part_info = find_mmc_partition_by_name(name);
471 if (part_info == NULL) {
472 printf("Bad part_info\n");
473 return 1;
474 }
475
476 mmc = find_mmc_device(dev);
477 if (!mmc)
478 return 1;
479
480 if (offset_addr >= part_info->size) {
481 printf("Start address out #%s# partition'address region,(addr_byte < 0x%llx)\n",
482 name, part_info->size);
483 return 1;
484 }
485 if ((offset_addr+size) > part_info->size) {
486 printf("End address exceeds #%s# partition,(offset = 0x%llx,size = 0x%llx)\n",
487 name, part_info->offset,part_info->size);
488 return 1;
489 }
490
491 get_off_size(mmc, name, offset_addr, size, &blk, &cnt, &sz_byte);
492 printf("MMC erase: dev # %d, start_erase_address(in block) # %#llx,\
493 several blocks # %lld will be erased ...\n ",
494 dev, blk, cnt);
495
496 mmc_init(mmc);
497
498 if (cnt != 0)
499 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
500
501 printf("dev # %d, %s, several blocks erased %s\n",
502 dev, argv[2], (n == 0) ? "OK" : "ERROR");
503 return (n == 0) ? 0 : 1;
504}
505
506static int amlmmc_erase_by_add(int argc, char *const argv[])
507{
508 int ret = 0;
509
510 if (argc != 5)
511 return CMD_RET_USAGE;
512
513 if (isdigit(argv[2][0]))
514 ret = amlmmc_erase_in_dev(argc, argv);
515 else if (strcmp(argv[2], "card") == 0)
516 ret = amlmmc_erase_in_card(argc, argv);
517 else if (isstring(argv[2]))
518 ret = amlmmc_erase_in_part(argc, argv);
519
520 return ret;
521}
522
523static int amlmmc_erase_non_loader(int argc, char *const argv[])
524{
525 int dev;
526 u32 n = 0;
527 int blk_shift;
528 u64 blk = 0, start_blk = 0;
529 struct partitions *part_info;
530 struct mmc *mmc;
531
532 dev = 1;
533 mmc = find_mmc_device(dev);
534 if (!mmc) {
535 printf("[%s] no mmc devices available\n", __func__);
536 return 1;
537 }
538
539 mmc_init(mmc);
540
541 blk_shift = ffs(mmc->read_bl_len) -1;
542 if (blk_shift < 0) {
543 printf("bad shift.\n");
544 return 1;
545 }
546 part_info = find_mmc_partition_by_name(MMC_BOOT_NAME);
547
548 if (part_info == NULL) {
549 start_blk = 0;
550 printf("no uboot partition for eMMC boot, just erase from 0\n");
551 }
552 else
553 start_blk = (part_info->offset + part_info->size) >> blk_shift;
554
555 if (emmckey_is_protected(mmc)) {
556 part_info = find_mmc_partition_by_name(MMC_RESERVED_NAME);
557 if (part_info == NULL) {
558 return 1;
559 }
560 blk = part_info->offset;
561 // it means: there should be other partitions before reserve-partition.
562 if (blk > 0)
563 blk -= PARTITION_RESERVED;
564 blk >>= blk_shift;
565 blk -= start_blk;
566 // (1) erase all the area before reserve-partition
567 if (blk > 0)
568 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, blk);
569 if (n == 0) { // not error
570 // (2) erase all the area after reserve-partition
571 start_blk = (part_info->offset + part_info->size + PARTITION_RESERVED)
572 >> blk_shift;
573 u64 erase_cnt = (mmc->capacity >> blk_shift) - start_blk;
574 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, erase_cnt);
575 }
576 } else {
577 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, 0); // erase the whole card
578 }
579 return (n == 0) ? 0 : 1;
580}
581
582static int amlmmc_erase_single_part(int argc, char *const argv[])
583{
584 char *name = NULL;
585 int dev;
586 u32 n = 0;
587 int blk_shift;
588 u64 cnt = 0, blk = 0;
589 struct partitions *part_info;
590 struct mmc *mmc;
591 name = argv[2];
592 dev = find_dev_num_by_partition_name(name);
593 if (dev < 0) {
594 printf("Cannot find dev.\n");
595 return 1;
596 }
597 mmc = find_mmc_device(dev);
598
599 if (!mmc)
600 return 1;
601
602 mmc_init(mmc);
603
604 blk_shift = ffs(mmc->read_bl_len) -1;
605 if (blk_shift < 0) {
606 printf("bad shift.\n");
607 return 1;
608 }
609 if (emmckey_is_protected(mmc)
610 && (strncmp(name, MMC_RESERVED_NAME, sizeof(MMC_RESERVED_NAME)) == 0x00)) {
611 printf("\"%s-partition\" is been protecting and should no be erased!\n",
612 MMC_RESERVED_NAME);
613 return 1;
614 }
615
616 part_info = find_mmc_partition_by_name(name);
617 if (part_info == NULL) {
618 return 1;
619 }
620
621 blk = part_info->offset >> blk_shift;
622 if (emmc_cur_partition && !strncmp(name, "bootloader", strlen("bootloader")))
623 cnt = 0;
624 else
625 cnt = part_info->size >> blk_shift;
626 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
627
628 return (n == 0) ? 0 : 1;
629}
630
631static int amlmmc_erase_whole(int argc, char *const argv[])
632{
633 char *name = NULL;
634 int dev;
635 u32 n = 0;
636 int blk_shift;
637 //u64 cnt = 0,
638 u64 blk = 0, start_blk = 0;
639 struct partitions *part_info;
640 struct mmc *mmc;
641 int map;
642
643 name = "logo";
644 dev = find_dev_num_by_partition_name(name);
645 if (dev < 0) {
646 printf("Cannot find dev.\n");
647 return 1;
648 }
649 mmc = find_mmc_device(dev);
650 if (!mmc)
651 return 1;
652 mmc_init(mmc);
653 blk_shift = ffs(mmc->read_bl_len) -1;
654 if (blk_shift < 0) {
655 printf("bad shift.\n");
656 return 1;
657 }
658 start_blk = 0;
659
660 if (emmckey_is_protected(mmc)) {
661 part_info = find_mmc_partition_by_name(MMC_RESERVED_NAME);
662 if (part_info == NULL) {
663 return 1;
664 }
665 blk = part_info->offset;
666 // it means: there should be other partitions before reserve-partition.
667 if (blk > 0)
668 blk -= PARTITION_RESERVED;
669 blk >>= blk_shift;
670 blk -= start_blk;
671 // (1) erase all the area before reserve-partition
672 if (blk > 0)
673 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, blk);
674 if (n == 0) { // not error
675 // (2) erase all the area after reserve-partition
676 start_blk = (part_info->offset + part_info->size + PARTITION_RESERVED)
677 >> blk_shift;
678 u64 erase_cnt = (mmc->capacity >> blk_shift) - start_blk;
679 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, erase_cnt);
680 }
681 } else {
682 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, 0); // erase the whole card
683 }
684 map = AML_BL_BOOT;
685 if (n == 0)
686 n = amlmmc_erase_bootloader(dev, map);
687 if (n)
688 printf("erase bootloader in boot partition failed\n");
689 return (n == 0) ? 0 : 1;
690}
691
692static int amlmmc_erase_non_cache(int arc, char *const argv[])
693{
694 char *name = NULL;
695 int dev;
696 u32 n = 0;
697 int blk_shift;
698 u64 blk = 0, start_blk = 0;
699 struct partitions *part_info;
700 struct mmc *mmc;
701 int map;
702
703 name = "logo";
704 dev = find_dev_num_by_partition_name(name);
705 if (dev < 0) {
706 printf("Cannot find dev.\n");
707 return 1;
708 }
709 mmc = find_mmc_device(dev);
710 if (!mmc)
711 return 1;
712 mmc_init(mmc);
713 blk_shift = ffs(mmc->read_bl_len) -1;
714 if (blk_shift < 0) {
715 printf("bad shift.\n");
716 return 1;
717 }
718 if (emmckey_is_protected(mmc)) {
719 part_info = find_mmc_partition_by_name(MMC_RESERVED_NAME);
720 if (part_info == NULL) {
721 return 1;
722 }
723
724 blk = part_info->offset;
725 // it means: there should be other partitions before reserve-partition.
726 if (blk > 0) {
727 blk -= PARTITION_RESERVED;
728 }
729 blk >>= blk_shift;
730 blk -= start_blk;
731 // (1) erase all the area before reserve-partition
732 if (blk > 0) {
733 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, blk);
734 // printf("(1) erase blk: 0 --> %llx %s\n", blk, (n == 0) ? "OK" : "ERROR");
735 }
736 if (n == 0) { // not error
737 // (2) erase all the area after reserve-partition
738 part_info = find_mmc_partition_by_name(MMC_CACHE_NAME);
739 if (part_info == NULL) {
740 return 1;
741 }
742 start_blk = (part_info->offset + part_info->size + PARTITION_RESERVED)
743 >> blk_shift;
744 u64 erase_cnt = (mmc->capacity >> blk_shift) - start_blk;
745 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, erase_cnt);
746 }
747 } else {
748 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, 0); // erase the whole card
749 }
750 map = AML_BL_BOOT;
751 if (n == 0) {
752 n = amlmmc_erase_bootloader(dev, map);
753 if (n)
754 printf("erase bootloader in boot partition failed\n");
755 }
756 return (n == 0) ? 0 : 1;
757}
758
759static int amlmmc_erase_dev(int argc, char *const argv[])
760{
761 return amlmmc_erase_whole(argc, argv);
762}
763
764static int amlmmc_erase_allbootloader(int argc, char*const argv[])
765{
766 int map;
767 int rc;
768 char *name = NULL;
769 int dev;
770 map = AML_BL_ALL;
771
772 name = "bootloader";
773 dev = find_dev_num_by_partition_name(name);
774
775 if (dev < 0) {
776 printf("Cannot find dev.\n");
777 return 1;
778 }
779
780 rc = amlmmc_erase_bootloader(dev, map);
781 return rc;
782}
783
784static int amlmmc_erase_by_part(int argc, char *const argv[])
785{
786 int ret = CMD_RET_USAGE;
787
788 if (argc != 3)
789 return ret;
790
791 if (isdigit(argv[2][0]))
792 ret = amlmmc_erase_dev(argc, argv);
793 else if (strcmp(argv[2], "whole") == 0)
794 ret = amlmmc_erase_whole(argc, argv);
795 else if (strcmp(argv[2], "non_cache") == 0)
796 ret = amlmmc_erase_non_cache(argc, argv);
797 else if (strcmp(argv[2], "non_loader") == 0)
798 ret = amlmmc_erase_non_loader(argc, argv);
799 else if (strcmp(argv[2], "allbootloader") == 0)
800 ret = amlmmc_erase_allbootloader(argc, argv);
801 else
802 ret = amlmmc_erase_single_part(argc, argv);
803 return ret;
804}
805
806static int do_amlmmc_erase(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
807{
808 int ret = CMD_RET_USAGE;
809
810 if (argc == 3)
811 ret = amlmmc_erase_by_part(argc, argv);
812 else if (argc == 5)
813 ret = amlmmc_erase_by_add(argc, argv);
814
815 return ret;
816}
817
818static int amlmmc_write_in_part(int argc, char *const argv[])
819{
820 int dev;
821 void *addr = NULL;
822 u64 cnt = 0, n = 0, blk = 0, sz_byte = 0;
823 char *name = NULL;
824 u64 offset = 0, size = 0;
825 cpu_id_t cpu_id = get_cpu_id();
826 struct mmc *mmc;
827
828 name = argv[2];
829 if (strcmp(name, "bootloader") == 0)
830 dev = CONFIG_SYS_MMC_BOOT_DEV;
831 else
832 dev = find_dev_num_by_partition_name (name);
833 addr = (void *)simple_strtoul(argv[3], NULL, 16);
834 offset = simple_strtoull(argv[4], NULL, 16);
835 size = simple_strtoull(argv[5], NULL, 16);
836 if (dev < 0) {
837 printf("Cannot find dev.\n");
838 return 1;
839 }
840 mmc = find_mmc_device(dev);
841 if (!mmc)
842 return 1;
843
844 if (strcmp(name, "bootloader") == 0) {
845 cnt = UBOOT_SIZE;
846 if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL) {
847 blk = GXL_START_BLK;
848 cnt -= GXL_START_BLK;
849 }
850 else
851 blk = GXB_START_BLK;
852 } else
853 get_off_size(mmc, name, offset, size, &blk, &cnt, &sz_byte);
854
855 mmc_init(mmc);
856 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
857 //write sz_byte bytes
858 if ((n == cnt) && (sz_byte != 0)) {
859 // printf("sz_byte=%#llx bytes\n",sz_byte);
860 void *addr_tmp = malloc(mmc->write_bl_len);
861 void *addr_byte = (void*)(addr+cnt*(mmc->write_bl_len));
862 ulong start_blk = blk+cnt;
863
864 if (addr_tmp == NULL) {
865 printf("mmc write: malloc fail\n");
866 return 1;
867 }
868
869 if (blk_dread(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // read 1 block
870 free(addr_tmp);
871 printf("mmc read 1 block fail\n");
872 return 1;
873 }
874
875 memcpy(addr_tmp, addr_byte, sz_byte);
876 if (blk_dwrite(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // write 1 block
877 free(addr_tmp);
878 printf("mmc write 1 block fail\n");
879 return 1;
880 }
881 free(addr_tmp);
882 }
883 //printf("%#llx blocks , %#llx bytes written: %s\n", n, sz_byte, (n==cnt) ? "OK" : "ERROR");
884 return (n == cnt) ? 0 : 1;
885}
886
887static int amlmmc_write_in_card(int argc, char *const argv[])
888{
889 int dev;
890 void *addr = NULL;
891 u64 cnt = 0, n = 0, blk = 0, sz_byte = 0;
892 char *name = NULL;
893 u64 offset = 0, size = 0;
894 struct mmc *mmc;
895
896 name = argv[2];
897 dev = find_dev_num_by_partition_name (name);
898 addr = (void *)simple_strtoul(argv[3], NULL, 16);
899 offset = simple_strtoull(argv[4], NULL, 16);
900 size = simple_strtoull(argv[5], NULL, 16);
901 if (dev < 0) {
902 printf("Cannot find dev.\n");
903 return 1;
904 }
905 mmc = find_mmc_device(dev);
906 if (!mmc)
907 return 1;
908
909 int blk_shift = ffs( mmc->read_bl_len) -1;
910 if (blk_shift < 0) {
911 printf("bad shift.\n");
912 return 1;
913 }
914 cnt = size >> blk_shift;
915 blk = offset >> blk_shift;
916 sz_byte = size - (cnt<<blk_shift);
917 mmc_init(mmc);
918
919 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
920
921 //write sz_byte bytes
922 if ((n == cnt) && (sz_byte != 0)) {
923 // printf("sz_byte=%#llx bytes\n",sz_byte);
924 void *addr_tmp = malloc(mmc->write_bl_len);
925 void *addr_byte = (void*)(addr+cnt*(mmc->write_bl_len));
926 ulong start_blk = blk+cnt;
927
928 if (addr_tmp == NULL) {
929 printf("mmc write: malloc fail\n");
930 return 1;
931 }
932
933 if (blk_dread(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // read 1 block
934 free(addr_tmp);
935 printf("mmc read 1 block fail\n");
936 return 1;
937 }
938
939 memcpy(addr_tmp, addr_byte, sz_byte);
940 if (blk_dwrite(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // write 1 block
941 free(addr_tmp);
942 printf("mmc write 1 block fail\n");
943 return 1;
944 }
945 free(addr_tmp);
946 }
947 //printf("%#llx blocks , %#llx bytes written: %s\n", n, sz_byte, (n==cnt) ? "OK" : "ERROR");
948 return (n == cnt) ? 0 : 1;
949}
950
951static int amlmmc_write_in_dev(int argc, char *const argv[])
952{
953 int dev;
954 void *addr = NULL;
955 u64 cnt = 0, n = 0, blk = 0;
956 struct mmc *mmc;
957 dev = simple_strtoul(argv[2], NULL, 10);
958 addr = (void *)simple_strtoul(argv[3], NULL, 16);
959 blk = simple_strtoull(argv[4], NULL, 16);
960 cnt = simple_strtoull(argv[5], NULL, 16);
961 if (dev < 0) {
962 printf("Cannot find dev.\n");
963 return 1;
964 }
965 mmc = find_mmc_device(dev);
966 if (!mmc)
967 return 1;
968
969 //printf("MMC write: dev # %d, block # %#llx, count # %#llx ... ",
970 //dev, blk, cnt);
971
972 mmc_init(mmc);
973
974 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
975 return (n == cnt) ? 0 : 1;
976}
977
978static int do_amlmmc_write(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
979{
980 int ret = 0;
981 if (argc != 6)
982 return CMD_RET_USAGE;
983
984 if (isdigit(argv[2][0]))
985 ret = amlmmc_write_in_dev(argc, argv);
986 else if (strcmp(argv[2], "card") == 0)
987 ret = amlmmc_write_in_card(argc, argv);
988 else if (isstring(argv[2]))
989 ret = amlmmc_write_in_part(argc, argv);
990
991 return ret;
992}
993
994static int amlmmc_read_in_dev(int argc, char *const argv[])
995{
996 int dev;
997 void *addr = NULL;
998 u64 cnt =0, n = 0, blk = 0;
999 struct mmc *mmc;
1000
1001 dev = simple_strtoul(argv[2], NULL, 10);
1002 addr = (void *)simple_strtoul(argv[3], NULL, 16);
1003 blk = simple_strtoull(argv[4], NULL, 16);
1004 cnt = simple_strtoull(argv[5], NULL, 16);
1005
1006 if (dev < 0) {
1007 printf("Cannot find dev.\n");
1008 return 1;
1009 }
1010
1011 mmc = find_mmc_device(dev);
1012 if (!mmc)
1013 return 1;
1014 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
1015 return (n == cnt) ? 0 : 1;
1016}
1017
1018static int amlmmc_read_in_card(int argc, char *const argv[])
1019{
1020 int dev;
1021 void *addr = NULL;
1022 //u32 flag =0;
1023 u64 cnt =0, n = 0, blk = 0, sz_byte = 0;
1024 char *name = NULL;
1025 u64 offset = 0, size = 0;
1026 int blk_shift;
1027 struct mmc *mmc;
1028 void *addr_tmp;
1029 void *addr_byte;
1030 ulong start_blk;
1031
1032 name = argv[2];
1033 dev = find_dev_num_by_partition_name (name);
1034 addr = (void *)simple_strtoul(argv[3], NULL, 16);
1035 size = simple_strtoull(argv[5], NULL, 16);
1036 offset = simple_strtoull(argv[4], NULL, 16);
1037
1038 if (dev < 0) {
1039 printf("Cannot find dev.\n");
1040 return 1;
1041 }
1042
1043 mmc = find_mmc_device(dev);
1044 if (!mmc)
1045 return 1;
1046
1047 blk_shift = ffs( mmc->read_bl_len) - 1;
1048 if (blk_shift < 0) {
1049 printf("bad shift.\n");
1050 return 1;
1051 }
1052 cnt = size >> blk_shift;
1053 blk = offset >> blk_shift;
1054 sz_byte = size - (cnt<<blk_shift);
1055
1056 mmc_init(mmc);
1057 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
1058
1059 //read sz_byte bytes
1060 if ((n == cnt) && (sz_byte != 0)) {
1061 addr_tmp = malloc(mmc->read_bl_len);
1062 addr_byte = (void *)(addr+cnt*(mmc->read_bl_len));
1063 start_blk = blk+cnt;
1064 if (addr_tmp == NULL) {
1065 printf("mmc read: malloc fail\n");
1066 return 1;
1067 }
1068 if (blk_dread(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // read 1 block
1069 free(addr_tmp);
1070 printf("mmc read 1 block fail\n");
1071 return 1;
1072 }
1073 memcpy(addr_byte, addr_tmp, sz_byte);
1074 free(addr_tmp);
1075 }
1076 return (n == cnt) ? 0 : 1;
1077}
1078
1079static int amlmmc_read_in_part(int argc, char *const argv[])
1080{
1081 int dev;
1082 void *addr = NULL;
1083 u64 cnt = 0, n = 0, blk = 0, sz_byte = 0;
1084 char *name = NULL;
1085 u64 offset = 0, size = 0;
1086 struct mmc *mmc;
1087 void *addr_tmp;
1088 void *addr_byte;
1089 ulong start_blk;
1090
1091 name = argv[2];
1092 dev = find_dev_num_by_partition_name (name);
1093 addr = (void *)simple_strtoul(argv[3], NULL, 16);
1094 offset = simple_strtoull(argv[4], NULL, 16);
1095 size = simple_strtoull(argv[5], NULL, 16);
1096
1097 if (dev < 0) {
1098 printf("Cannot find dev.\n");
1099 return 1;
1100 }
1101
1102 mmc = find_mmc_device(dev);
1103 if (!mmc)
1104 return 1;
1105
1106 get_off_size(mmc, name, offset, size, &blk, &cnt, &sz_byte);
1107 mmc_init(mmc);
1108 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
1109
1110 //read sz_byte bytes
1111 if ((n == cnt) && (sz_byte != 0)) {
1112 /*printf("sz_byte=%#llx bytes\n",sz_byte);*/
1113 addr_tmp = malloc(mmc->read_bl_len);
1114 addr_byte = (void *)(addr+cnt*(mmc->read_bl_len));
1115 start_blk = blk+cnt;
1116
1117 if (addr_tmp == NULL) {
1118 printf("mmc read: malloc fail\n");
1119 return 1;
1120 }
1121
1122 if (blk_dread(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // read 1 block
1123 free(addr_tmp);
1124 printf("mmc read 1 block fail\n");
1125 return 1;
1126 }
1127
1128 memcpy(addr_byte, addr_tmp, sz_byte);
1129 free(addr_tmp);
1130 }
1131 return (n == cnt) ? 0 : 1;
1132}
1133
1134static int do_amlmmc_read(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1135{
1136 int ret = 0;
1137 if (argc != 6)
1138 return CMD_RET_USAGE;
1139
1140 if (isdigit(argv[2][0]))
1141 ret = amlmmc_read_in_dev(argc, argv);
1142 else if (strcmp(argv[2], "card") == 0)
1143 ret = amlmmc_read_in_card(argc, argv);
1144 else if (isstring(argv[2]))
1145 ret = amlmmc_read_in_part(argc, argv);
1146
1147 return ret;
1148}
1149
1150static int do_amlmmc_env(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1151{
1152 printf("herh\n");
1153 env_relocate();
1154 return 0;
1155}
1156
1157static int do_amlmmc_list(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1158{
1159 print_mmc_devices('\n');
1160 return 0;
1161}
1162
1163static int do_amlmmc_size(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1164{
1165 char *name;
1166 uint64_t* addr = NULL;
1167 int dev;
1168 struct mmc *mmc = NULL;
1169
1170 if (argc != 4)
1171 return CMD_RET_USAGE;
1172
1173 name = argv[2];
1174 addr = (uint64_t *)simple_strtoul(argv[3], NULL, 16);
1175 if (!strcmp(name, "wholeDev")) {
1176 dev = CONFIG_SYS_MMC_BOOT_DEV;
1177 mmc = find_mmc_device(dev);
1178 if (!mmc) {
1179 puts("no mmc devices available\n");
1180 return 1;
1181 }
1182 mmc_init(mmc);
1183
1184 *addr = mmc->capacity >> 9; // unit: 512 bytes
1185 return 0;
1186 }
1187 return get_partition_size((unsigned char *)name, addr);
1188}
1189
1190static int amlmmc_get_ext_csd(int argc, char *const argv[])
1191{
1192 int ret= 0;
1193 u8 ext_csd[512] = {0};
1194 int dev, byte;
1195 struct mmc *mmc;
1196
1197 if (argc != 4)
1198 return CMD_RET_USAGE;
1199
1200 dev = simple_strtoul(argv[2], NULL, 10);
1201 byte = simple_strtoul(argv[3], NULL, 10);
1202 mmc = find_mmc_device(dev);
1203
1204 if (!mmc) {
1205 puts("no mmc devices available\n");
1206 return 1;
1207 }
1208 mmc_init(mmc);
1209 ret = mmc_get_ext_csd(mmc, ext_csd);
1210 printf("read EXT_CSD byte[%d] val[0x%x] %s\n",
1211 byte, ext_csd[byte], (ret == 0) ? "ok" : "fail");
1212 return ret;
1213}
1214
1215static int amlmmc_set_ext_csd(int argc, char *const argv[])
1216{
1217 int ret = 0;
1218 int dev, byte;
1219 struct mmc *mmc;
1220 int val;
1221
1222 if (argc != 5)
1223 return CMD_RET_USAGE;
1224
1225 dev = simple_strtoul(argv[2], NULL, 10);
1226 byte = simple_strtoul(argv[3], NULL, 10);
1227 val = simple_strtoul(argv[4], NULL, 16);
1228 if ((byte > 191) || (byte < 0)) {
1229 printf("byte is not able to write!\n");
1230 return 1;
1231 }
1232
1233 mmc = find_mmc_device(dev);
1234
1235 if (!mmc) {
1236 puts("no mmc devices available\n");
1237 return 1;
1238 }
1239
1240 mmc_init(mmc);
1241
1242 ret = mmc_set_ext_csd(mmc, byte, val);
1243 printf("write EXT_CSD byte[%d] val[0x%x] %s\n",
1244 byte, val, (ret == 0) ? "ok" : "fail");
1245 return ret;
1246}
1247
1248static int do_amlmmc_ext_csd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1249{
1250 int ret = CMD_RET_USAGE;
1251
1252 if (argc == 4)
1253 ret = amlmmc_get_ext_csd(argc,argv);
1254 else if (argc == 5)
1255 ret = amlmmc_set_ext_csd(argc,argv);
1256
1257 return ret;
1258}
1259
1260static int do_amlmmc_switch(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1261{
1262 int rc = 0;
1263 int dev;
1264 struct mmc *mmc;
1265
1266 if (argc != 4)
1267 return CMD_RET_USAGE;
1268
1269 dev = simple_strtoul(argv[2], NULL, 10);
1270 mmc = find_mmc_device(dev);
1271
1272 if (!mmc) {
1273 puts("no mmc devices available\n");
1274 return 1;
1275 }
1276
1277 mmc_init(mmc);
1278 printf("mmc switch to ");
1279
1280 if (strcmp(argv[3], "boot0") == 0) {
1281 rc = mmc_switch_part(mmc, 1);
1282 if (rc == 0) {
1283 emmc_cur_partition = 1;
1284 printf("boot0 success\n");
1285 } else {
1286 printf("boot0 failed\n");
1287 }
1288 }
1289 else if(strcmp(argv[3], "boot1") == 0) {
1290 rc = mmc_switch_part(mmc, 2);
1291 if (rc == 0) {
1292 emmc_cur_partition = 2;
1293 printf("boot1 success\n");
1294 } else {
1295 printf("boot1 failed\n");
1296 }
1297 }
1298 else if(strcmp(argv[3], "user") == 0) {
1299 rc = mmc_switch_part(mmc, 0);
1300 if (rc == 0) {
1301 emmc_cur_partition = 0;
1302 printf("user success\n");
1303 } else {
1304 printf("user failed\n");
1305 }
1306 }
1307#ifdef CONFIG_SUPPORT_EMMC_RPMB
1308 else if(strcmp(argv[3], "rpmb") == 0) {
1309 rc = mmc_switch_part(mmc, 3);
1310 if (rc == 0) {
1311 emmc_cur_partition = 3;
1312 printf("rpmb success\n");
1313 } else {
1314 printf("rpmb failed\n");
1315 }
1316 }
1317#endif
1318 else
1319 printf("%s failed\n", argv[3]);
1320 return rc;
1321}
1322
1323static int do_amlmmc_controller(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1324{
1325 /*int dev;
1326 struct mmc *mmc;
1327 struct aml_card_sd_info *aml_priv;
1328 struct sd_emmc_global_regs *sd_emmc_reg;
1329
1330 if (argc != 3)
1331 return CMD_RET_USAGE;
1332
1333 dev = simple_strtoul(argv[2], NULL, 10);
1334
1335 if (dev < 0) {
1336 printf("Cannot find dev.\n");
1337 return 1;
1338 }
1339
1340 mmc = find_mmc_device(dev);
1341
1342 if (!mmc)
1343 return 1;
1344
1345 aml_priv = mmc->priv;
1346 sd_emmc_reg = aml_priv->sd_emmc_reg;
1347
1348 printf("sd_emmc_reg->gclock = 0x%x\n", sd_emmc_reg->gclock);
1349 printf("sd_emmc_reg->gdelay = 0x%x\n", sd_emmc_reg->gdelay);
1350 printf("sd_emmc_reg->gadjust = 0x%x\n", sd_emmc_reg->gadjust);
1351 printf("sd_emmc_reg->gcalout = 0x%x\n", sd_emmc_reg->gcalout);
1352 if (!mmc->has_init) {
1353 printf("mmc dev %d has not been initialed\n", dev);
1354 return 1;
1355 }
1356 printf("sd_emmc_reg->gstart = 0x%x\n", sd_emmc_reg->gstart);
1357 printf("sd_emmc_reg->gcfg = 0x%x\n", sd_emmc_reg->gcfg);
1358 printf("sd_emmc_reg->gstatus = 0x%x\n", sd_emmc_reg->gstatus);
1359 printf("sd_emmc_reg->girq_en = 0x%x\n", sd_emmc_reg->girq_en);
1360 printf("sd_emmc_reg->gcmd_cfg = 0x%x\n", sd_emmc_reg->gcmd_cfg);
1361 printf("sd_emmc_reg->gcmd_arg = 0x%x\n", sd_emmc_reg->gcmd_arg);
1362 printf("sd_emmc_reg->gcmd_dat = 0x%x\n", sd_emmc_reg->gcmd_dat);
1363 printf("sd_emmc_reg->gcmd_rsp0 = 0x%x\n", sd_emmc_reg->gcmd_rsp0);
1364 printf("sd_emmc_reg->gcmd_rsp1 = 0x%x\n", sd_emmc_reg->gcmd_rsp1);
1365 printf("sd_emmc_reg->gcmd_rsp2 = 0x%x\n", sd_emmc_reg->gcmd_rsp2);
1366 printf("sd_emmc_reg->gcmd_rsp3 = 0x%x\n", sd_emmc_reg->gcmd_rsp3);*/
1367 return 0;
1368}
1369
1370static int do_amlmmc_response(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1371{
1372 /*int dev;
1373 struct mmc *mmc;
1374 struct aml_card_sd_info *aml_priv;
1375 struct sd_emmc_global_regs *sd_emmc_reg;
1376
1377 if (argc != 3)
1378 return CMD_RET_USAGE;
1379
1380 dev = simple_strtoul(argv[2], NULL, 10);
1381
1382 if (dev < 0) {
1383 printf("Cannot find dev.\n");
1384 return 1;
1385 }
1386
1387 mmc = find_mmc_device(dev);
1388
1389 if (!mmc)
1390 return 1;
1391 if (!mmc->has_init) {
1392 printf("mmc dev %d has not been initialed\n", dev);
1393 return 1;
1394 }
1395
1396 aml_priv = mmc->priv;
1397 sd_emmc_reg = aml_priv->sd_emmc_reg;
1398
1399 printf("last cmd = %d, response0 = 0x%x\n",
1400 (sd_emmc_reg->gcmd_cfg & 0x3f), sd_emmc_reg->gcmd_rsp0);*/
1401 return 0;
1402}
1403
1404static int do_amlmmc_status(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1405{
1406 int rc = 0;
1407 int dev;
1408 struct mmc *mmc;
1409
1410 if (argc != 3)
1411 return CMD_RET_USAGE;
1412
1413 dev = simple_strtoul(argv[2], NULL, 10);
1414
1415 if (dev < 0) {
1416 printf("Cannot find dev.\n");
1417 return 1;
1418 }
1419 mmc = find_mmc_device(dev);
1420
1421 if (!mmc)
1422 return 1;
1423 if (!mmc->has_init) {
1424 printf("mmc dev %d has not been initialed\n", dev);
1425 return 1;
1426 }
1427 rc = mmc_read_status(mmc, 1000);
1428 if (rc)
1429 return 1;
1430 else
1431 return 0;
1432}
1433
1434static int do_amlmmc_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1435{
1436 int dev;
1437 struct blk_desc *mmc_dev;
1438 struct mmc *mmc;
1439
1440 if (argc != 3)
1441 return CMD_RET_USAGE;
1442
1443 dev = simple_strtoul(argv[2], NULL, 10);
1444 mmc = find_mmc_device(dev);
1445
1446 if (!mmc) {
1447 puts("no mmc devices available\n");
1448 return 1;
1449 }
1450 mmc_init(mmc);
1451 mmc_dev = mmc_get_blk_desc(mmc);
1452 if (mmc_dev != NULL &&
1453 mmc_dev->type != DEV_TYPE_UNKNOWN) {
1454 part_print(mmc_dev);
1455 return 0;
1456 }
1457 puts("get mmc type error!\n");
1458 return 1;
1459}
1460
1461static int do_amlmmc_rescan(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1462{
1463 int dev;
1464 struct mmc *mmc;
1465
1466 if (argc != 3)
1467 return CMD_RET_USAGE;
1468
1469 dev = simple_strtoul(argv[2], NULL, 10);
1470
1471 if (dev < 0) {
1472 printf("Cannot find dev.\n");
1473 return 1;
1474 }
1475
1476 mmc = find_mmc_device(dev);
1477
1478 if (!mmc)
1479 return 1;
1480 mmc->has_init =0;
1481 return mmc_init(mmc);
1482}
1483
1484#ifdef CONFIG_SECURITYKEY
1485static int do_amlmmc_key(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1486{
1487 struct mmc *mmc;
1488 int dev;
1489
1490 //char *name = "logo";
1491 dev = CONFIG_SYS_MMC_BOOT_DEV;
1492 mmc = find_mmc_device(dev);
1493 if (!mmc) {
1494 printf("device %d is invalid\n",dev);
1495 return 1;
1496 }
1497 //mmc->key_protect = 0;
1498#ifdef CONFIG_STORE_COMPATIBLE
1499 info_disprotect |= DISPROTECT_KEY; //disprotect
1500 printf("emmc disprotect key\n");
1501#endif
1502 return 0;
1503}
1504#endif
1505
1506static int set_write_prot(struct mmc *mmc, u64 start)
1507{
1508 struct mmc_cmd cmd;
1509 int err;
1510
1511 cmd.cmdidx = MMC_CMD_SET_WRITE_PROTECT;
1512 cmd.cmdarg = start;
1513 cmd.resp_type = MMC_RSP_R1b;
1514
1515 err = mmc_send_cmd(mmc, &cmd, NULL);
1516 if (err)
1517 goto err_out;
1518
1519 return 0;
1520
1521err_out:
1522 puts("Failed: mmc write protect failed\n");
1523 return err;
1524}
1525
1526static int set_us_wp_en(struct mmc *mmc, u8 *ext_csd, u8 wp_enable_type)
1527{
1528 u8 index = EXT_CSD_USER_WP;
1529 u8 user_wp = ext_csd[index];
1530 user_wp = user_wp & (~WP_ENABLE_MASK);
1531 user_wp = user_wp | wp_enable_type;
1532 int err = 0;
1533 err = mmc_set_ext_csd(mmc, index, user_wp);
1534 if (err)
1535 printf("Failed: set write protect enable failed\n");
1536 return err;
1537}
1538
1539static int mmc_set_us_perm_wp_dis(struct mmc *mmc, u8 *ext_csd)
1540{
1541 u8 usr_wp = ext_csd[EXT_CSD_USER_WP];
1542 u8 perm_disable_bit = US_PERM_WP_DIS_BIT;
1543
1544 int err;
1545 if (usr_wp & perm_disable_bit)
1546 return 0;
1547
1548 usr_wp = usr_wp | perm_disable_bit;
1549 err = mmc_set_ext_csd(mmc, EXT_CSD_USER_WP, usr_wp);
1550 if (err) {
1551 printf("Failed: set permanent write protect disable failed\n");
1552 return 1;
1553 }
1554 return 0;
1555}
1556
1557static int mmc_is_us_pwr_wp_dis(u8 user_wp)
1558{
1559 return user_wp & US_PWR_WP_DIS_BIT;
1560}
1561
1562static int mmc_is_us_perm_wp_dis(u8 user_wp)
1563{
1564 return user_wp & US_PERM_WP_DIS_BIT;
1565}
1566
1567static int check_wp_type(u8 *addr, u8 wp_type, u64 set_protect_cnt)
1568{
1569 u8 type_mask = WP_TYPE_MASK;
1570 u64 cnt = set_protect_cnt;
1571 u8 times = 0;
1572 u8 index = 7;
1573 u8 cur_group_wp_type = addr[index];
1574
1575 while (cnt != 0) {
1576 if (wp_type != ((type_mask)&(cur_group_wp_type))) {
1577 return 1;
1578 }
1579 if (times == 3) {
1580 times = 0;
1581 index--;
1582 cur_group_wp_type = addr[index];
1583 }
1584 else {
1585 cur_group_wp_type = cur_group_wp_type >> 2;
1586 times++;
1587 }
1588 cnt--;
1589 }
1590 return 0;
1591}
1592
1593static int set_register_to_temporary(struct mmc *mmc, u8 *ext_csd)
1594{
1595 int err;
1596 u8 wp_enable_type = WP_TEMPORARY_EN_BIT;
1597 err = set_us_wp_en(mmc, ext_csd, wp_enable_type);
1598 if (err)
1599 printf("Failed: set temporary write protect failed\n");
1600 return err;
1601}
1602
1603static int set_register_to_pwr(struct mmc *mmc, u8 *ext_csd)
1604{
1605 int err;
1606 u8 user_wp = ext_csd[EXT_CSD_USER_WP];
1607 u8 wp_enable_type = WP_POWER_ON_EN_BIT;
1608 if (mmc_is_us_pwr_wp_dis(user_wp)) {
1609 printf("Failed: power on protection had been disabled\n");
1610 return 1;
1611 }
1612
1613 err = mmc_set_us_perm_wp_dis(mmc, ext_csd);
1614 if (err) {
1615 printf("Failed: set permanent protection disable failed\n");
1616 return 1;
1617 }
1618
1619 err = set_us_wp_en(mmc, ext_csd, wp_enable_type);
1620 if (err) {
1621 printf("Failed: set power on write protect enable failed\n");
1622 return 1;
1623 }
1624 return 0;
1625}
1626
1627static int set_register_to_perm(struct mmc *mmc, u8 *ext_csd)
1628{
1629 int err;
1630 u8 wp_enable_type = WP_PERM_EN_BIT;
1631 u8 user_wp = ext_csd[EXT_CSD_USER_WP];
1632
1633 if (mmc_is_us_perm_wp_dis(user_wp)) {
1634 printf("Failed: Permanent protection had been disabled\n");
1635 return 1;
1636 }
1637
1638 err = set_us_wp_en(mmc, ext_csd, wp_enable_type);
1639 if (err) {
1640 printf("Failed: set permanent write protect enable failed\n");
1641 return 1;
1642 }
1643 return 0;
1644}
1645
1646static int set_wp_register(struct mmc *mmc, u8 *ext_csd, u8 wp_type)
1647{
1648 int ret = 1;
1649 if (wp_type == WP_POWER_ON_TYPE)
1650 ret = set_register_to_pwr(mmc, ext_csd);
1651 else if (wp_type == WP_PERMANENT_TYPE)
1652 ret = set_register_to_perm(mmc, ext_csd);
1653 else if (wp_type == WP_TEMPORARY_TYPE)
1654 ret = set_register_to_temporary(mmc, ext_csd);
1655 return ret;
1656}
1657
1658static u64 write_protect_group_size(struct mmc *mmc, u8 *ext_csd)
1659{
1660 int erase_group_def = ext_csd[EXT_CSD_ERASE_GROUP_DEF];
1661 u64 write_protect_group_size;
1662 u64 wp_grp_size = mmc->csd[2] & WP_GRP_SIZE_MASK;
1663 u64 hc_wp_grp_size = ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
1664
1665 if (erase_group_def == 0)
1666 write_protect_group_size = (wp_grp_size + 1) * mmc->erase_grp_size;
1667 else
1668 write_protect_group_size = hc_wp_grp_size * mmc->erase_grp_size;
1669
1670 return write_protect_group_size;
1671}
1672
1673int is_write_protect_valid(u8 *ext_csd)
1674{
1675 u8 class_6_ctrl = ext_csd[EXT_CSD_CLASS_6_CTRL];
1676 if (class_6_ctrl == 0)
1677 return 1;
1678 return 0;
1679}
1680
1681static int compute_write_protect_range(struct mmc *mmc, char *name,
1682 u8 *ext_csd, u64 *wp_grp_size_addr, u64 *start_addr, u64 *end)
1683{
1684 int blk_shift;
1685 struct partitions *part_info;
1686 u64 cnt;
1687 u64 start = *start_addr;
1688 u64 align_start = *start_addr;
1689 u64 wp_grp_size = 0;
1690 u64 group_num;
1691 u64 partition_end;
1692
1693 wp_grp_size = write_protect_group_size(mmc, ext_csd);
1694 if (wp_grp_size == 0) {
1695 printf("bad wp_grp_size.\n");
1696 return 1;
1697 }
1698
1699 blk_shift = ffs(mmc->read_bl_len) -1;
1700 if (blk_shift < 0) {
1701 printf("bad shift.\n");
1702 return 1;
1703 }
1704
1705 part_info = find_mmc_partition_by_name(name);
1706 if (part_info == NULL)
1707 return 1;
1708
1709 start = part_info->offset >> blk_shift;
1710 printf("start:%d wp_grp_size:%d",(int)start,(int)wp_grp_size);
1711 if ((start % wp_grp_size)) {
1712 align_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
1713 printf("Caution! The partition start address isn't' aligned"
1714 "to group size\n"
1715 "the start address is change from 0x%llx to 0x%llx\n",
1716 start, align_start);
1717 } else {
1718 align_start = start;
1719 }
1720 if (emmc_cur_partition && !strncmp(name, "bootloader", strlen("bootloader")))
1721 cnt =0;
1722 else
1723 cnt = part_info->size >> blk_shift;
1724 if (cnt < wp_grp_size) {
1725 printf("Caution: The partition size is 0x%llx sector smaller than "
1726 "the group size 0x%llx sector, \n"
1727 "so the partition can't be protect\n", cnt, wp_grp_size);
1728 return 1;
1729 }
1730
1731 *start_addr = align_start;
1732 *wp_grp_size_addr = wp_grp_size;
1733 partition_end = start + cnt - 1;
1734 group_num = (cnt - (align_start - start)) / wp_grp_size;
1735 *end = align_start + group_num * wp_grp_size - 1;
1736
1737 if (partition_end != *end) {
1738 printf("Caution! The boundary of partition isn't aligned with write "
1739 "protected group,\n"
1740 "so the write protected boundary of the "
1741 "partition is 0x%llx, rather than 0x%llx\n",
1742 *end, partition_end);
1743 }
1744
1745 printf("write_protect group size is 0x%llx sector\n", wp_grp_size);
1746 printf("The %s partition write protect group number is %lld\n", name, group_num);
1747#ifdef WP_DEBUG
1748 printf("the start address is 0x%llx, group size is 0x%llx, end is 0x%llx\n",
1749 *start_addr, *wp_grp_size_addr, *end);
1750#endif
1751 return 0;
1752}
1753
1754static int send_wp_prot_type(struct mmc *mmc, void *dst, u64 blk)
1755{
1756 struct mmc_cmd cmd;
1757 int err;
1758 struct mmc_data data;
1759
1760 cmd.cmdidx = MMC_CMD_SEND_WRITE_PROT_TYPE;
1761 cmd.cmdarg = blk;
1762 cmd.resp_type = MMC_RSP_R1;
1763
1764 data.dest = (char* )dst;
1765 data.blocks = 1;
1766 data.blocksize = 8;
1767 data.flags = MMC_DATA_READ;
1768
1769 err = mmc_send_cmd(mmc, &cmd, &data);
1770 if (err)
1771 goto err_out;
1772
1773 return 0;
1774
1775err_out:
1776 puts("Failed: mmc send write protect type failed\n");
1777 return err;
1778}
1779
1780static int is_wp_set_failed(struct mmc *mmc, u8 wp_type, u64 start, u64 group_cnt)
1781{
1782 u8 *addr = NULL;
1783 u8 err = 0;
1784
1785 addr = malloc(sizeof(u64));
1786 if (addr == NULL) {
1787 printf("Failed: malloc failed\n");
1788 return 1;
1789 }
1790
1791 err = send_wp_prot_type(mmc, addr, start);
1792 if (err)
1793 goto err_out;
1794
1795#ifdef WP_DEBUG
1796 int i;
1797 for (i = 0; i < 8; i++)
1798 printf("write_protect status is %x\n", ((u8 *)addr)[i]);
1799#endif
1800 if (check_wp_type(addr, wp_type, group_cnt)) {
1801 printf("Failed: Write Protection set failed\n");
1802 goto err_out;
1803 }
1804 return 0;
1805
1806err_out:
1807 free(addr);
1808 return 1;
1809}
1810
1811static int send_part_wp_type(struct mmc *mmc, char *name)
1812{
1813 int err = 0;
1814 u8 ext_csd[512] = {0};
1815 u64 wp_grp_size, start = 0, part_end;
1816 u64 group_start;
1817 void *addr = NULL;
1818 int i;
1819 int ret;
1820
1821 ret = mmc_get_ext_csd(mmc, ext_csd);
1822 if (ret) {
1823 printf("Failed: get ext_csd failed\n");
1824 return 1;
1825 }
1826
1827 if (!is_write_protect_valid(ext_csd)) {
1828 printf("Failed: CLASS_6_CTRL isn't '0' "
1829 "write protect process is invalid\n");
1830 return 1;
1831 }
1832
1833 addr = (char* )malloc(sizeof(u64));
1834 if (addr == NULL) {
1835 printf("Failed: malloc failed\n");
1836 return 1;
1837 }
1838
1839 err = compute_write_protect_range(mmc, name, ext_csd,
1840 &wp_grp_size, &start, &part_end);
1841 if (err) {
1842 free(addr);
1843 return 1;
1844 }
1845
1846 group_start = start;
1847
1848 while ((group_start + wp_grp_size - 1) <= part_end) {
1849 err = send_wp_prot_type(mmc, addr, group_start);
1850 if (err) {
1851 free(addr);
1852 return 1;
1853 }
1854 printf("The write protect type for the 32 groups after 0x%llx is: \n0x",
1855 group_start);
1856 for (i = 0; i < 8; i++)
1857 printf("%02x", ((u8*)addr)[i]);
1858 printf("\n");
1859 group_start += 32 * wp_grp_size;
1860 }
1861
1862 free(addr);
1863 return 0;
1864}
1865
1866static int send_add_wp_type(struct mmc *mmc, u64 start, u64 cnt)
1867{
1868 u8 ext_csd[512] = {0};
1869 u64 wp_grp_size = 0;
1870 u64 part_end = 0;
1871 u64 group_start;
1872 u64 mmc_boundary;
1873 int blk_shift;
1874 void *addr = NULL;
1875 int i;
1876 int ret;
1877
1878 ret = mmc_get_ext_csd(mmc, ext_csd);
1879 if (ret) {
1880 printf("Failed: get ext_csd failed\n");
1881 return 1;
1882 }
1883
1884 if (!is_write_protect_valid(ext_csd)) {
1885 printf("Failed: CLASS_6_CTRL isn't '0' "
1886 "write protect process is invalid\n");
1887 return 1;
1888 }
1889
1890 addr = malloc(sizeof(u64));
1891 if (addr == NULL) {
1892 printf("Failed: malloc failed\n");
1893 return 1;
1894 }
1895
1896 wp_grp_size = write_protect_group_size(mmc, ext_csd);
1897
1898 if ((start % wp_grp_size)) {
1899 group_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
1900 printf("Caution! The partition start address isn't' aligned"
1901 "to group size\n"
1902 "the start address is change from 0x%llx to 0x%llx\n",
1903 start, group_start);
1904 part_end = group_start + (cnt - 1) * wp_grp_size - 1;
1905 printf("The write protect group number is 0x%llx, rather than 0x%lld\n",
1906 cnt - 1, cnt);
1907 } else {
1908 group_start = start;
1909 part_end = group_start + cnt * wp_grp_size - 1;
1910 }
1911
1912 blk_shift = ffs(mmc->read_bl_len) - 1;
1913 if (blk_shift < 0) {
1914 printf("bad shift.\n");
1915 free(addr);
1916 return 1;
1917 }
1918 mmc_boundary = mmc->capacity>>blk_shift;
1919
1920 if ((part_end + 1) > mmc_boundary) {
1921 printf("Error: the operation cross the boundary of mmc\n");
1922 free(addr);
1923 return 1;
1924 }
1925
1926 while ((group_start + wp_grp_size - 1) <= part_end) {
1927 ret = send_wp_prot_type(mmc, addr, group_start);
1928 if (ret) {
1929 free(addr);
1930 return 1;
1931 }
1932 printf("The write protect type for the 32 groups after 0x%llx is: \n0x",
1933 group_start);
1934 for (i = 0; i < 8; i++)
1935 printf("%02x", ((u8*)addr)[i]);
1936 printf("\n");
1937 group_start += 32 * wp_grp_size;
1938 }
1939
1940 free(addr);
1941 return 0;
1942}
1943
1944static int set_part_write_protect(struct mmc *mmc, u8 wp_type, char *name)
1945{
1946 int err = 0;
1947 u8 ext_csd[512] = {0};
1948 u8 group_num = 32;
1949 u64 wp_grp_size, start = 0, part_end;
1950 u64 group_start;
1951 u64 check_group_start;
1952 u64 set_protect_cnt = 0;
1953
1954 err = mmc_get_ext_csd(mmc, ext_csd);
1955 if (err) {
1956 printf("Failed: get ext_csd failed\n");
1957 return 1;
1958 }
1959
1960 if (!is_write_protect_valid(ext_csd)) {
1961 printf("Failed: CLASS_6_CTRL isn't '0' "
1962 "write protect process is invalid\n");
1963 return 1;
1964 }
1965
1966 err = compute_write_protect_range(mmc, name, ext_csd,
1967 &wp_grp_size, &start, &part_end);
1968 if (err)
1969 return 1;
1970
1971 group_start = start;
1972 err = set_wp_register(mmc, ext_csd, wp_type);
1973 if (err)
1974 return 1;
1975 while ((group_start + wp_grp_size - 1) <= part_end) {
1976 err = set_write_prot(mmc, group_start);
1977 if (err)
1978 return 1;
1979 group_start += wp_grp_size;
1980 set_protect_cnt++;
1981//check write protect type every 32 group
1982 if (set_protect_cnt % 32 == 0) {
1983 check_group_start = group_start - group_num * wp_grp_size;
1984 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
1985 if (err)
1986 return 1;
1987 }
1988 }
1989
1990 group_num = set_protect_cnt % 32;
1991 check_group_start = group_start - group_num * wp_grp_size;
1992
1993 if (group_num) {
1994 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
1995 if (err)
1996 return 1;
1997 }
1998
1999 return 0;
2000}
2001
2002static int set_add_write_protect(struct mmc *mmc, u8 wp_type, u64 start, u64 cnt)
2003{
2004 int err = 0;
2005 u8 ext_csd[512] = {0};
2006 int group_num = 32;
2007 u64 wp_grp_size, part_end;
2008 u64 group_start;
2009 u64 check_group_start;
2010 u64 set_protect_cnt = 0;
2011 u64 mmc_boundary = 0;
2012 int blk_shift;
2013 err = mmc_get_ext_csd(mmc, ext_csd);
2014
2015 if (err) {
2016 printf("Failed: get ext_csd failed\n");
2017 return 1;
2018 }
2019
2020 if (!is_write_protect_valid(ext_csd)) {
2021 printf("Failed: CLASS_6_CTRL isn't '0' "
2022 "write protect process is invalid\n");
2023 return 1;
2024 }
2025
2026 wp_grp_size = write_protect_group_size(mmc, ext_csd);
2027
2028 if ((start % wp_grp_size)) {
2029 group_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
2030 printf("Caution! The partition start address isn't' aligned"
2031 "to group size\n"
2032 "the start address is change from 0x%llx to 0x%llx\n",
2033 start, group_start);
2034 part_end = group_start + (cnt - 1) * wp_grp_size - 1;
2035 printf("The write protect group number is 0x%llx, rather than 0x%lld\n",
2036 cnt - 1, cnt);
2037 } else {
2038 group_start = start;
2039 part_end = group_start + cnt * wp_grp_size - 1;
2040 }
2041
2042 blk_shift = ffs(mmc->read_bl_len) - 1;
2043 if (blk_shift < 0) {
2044 printf("bad shift.\n");
2045 return 1;
2046 }
2047 mmc_boundary = mmc->capacity>>blk_shift;
2048
2049 if ((part_end + 1) > mmc_boundary) {
2050 printf("Error: the operation cross the boundary of mmc\n");
2051 return 1;
2052 }
2053
2054 err = set_wp_register(mmc, ext_csd, wp_type);
2055 if (err)
2056 return 1;
2057
2058 while ((group_start + wp_grp_size - 1) <= part_end) {
2059 err = set_write_prot(mmc, group_start);
2060 if (err)
2061 return 1;
2062 group_start += wp_grp_size;
2063 set_protect_cnt++;
2064//check write protect type every 32 group
2065 if (set_protect_cnt % 32 == 0) {
2066 check_group_start = group_start - group_num * wp_grp_size;
2067 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2068 if (err)
2069 return 1;
2070 }
2071 }
2072
2073 group_num = set_protect_cnt % 32;
2074 check_group_start = group_start - group_num * wp_grp_size;
2075
2076 if (group_num) {
2077 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2078 if (err)
2079 return 1;
2080 }
2081
2082 return 0;
2083}
2084
2085static int do_amlmmc_write_protect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2086{
2087 int ret = CMD_RET_USAGE;
2088 struct mmc *mmc;
2089 int dev = 1;
2090 char *name = NULL;
2091 char *wp_type_str = NULL;
2092 u8 write_protect_type;
2093 u64 start, cnt;
2094
2095 if (argc > 5 || argc < 4)
2096 return ret;
2097 if (argc == 4) {
2098 name = argv[2];
2099 wp_type_str = argv[3];
2100 dev = find_dev_num_by_partition_name(name);
2101 if (dev < 0) {
2102 printf("Error: Cannot find dev.\n");
2103 return CMD_RET_USAGE;
2104 }
2105 } else {
2106 start = simple_strtoull(argv[2], NULL, 16);
2107 cnt = simple_strtoull(argv[3], NULL, 0);
2108 wp_type_str = argv[4];
2109 }
2110
2111 mmc = find_mmc_device(dev);
2112 if (!mmc) {
2113 printf("[%s] no mmc devices available\n", __func__);
2114 return 1;
2115 }
2116
2117 if (IS_SD(mmc)) {
2118 mmc = find_mmc_device(~dev);
2119 if (mmc && IS_SD(mmc)) {
2120 printf("SD card can not be write protect\n");
2121 return 1;
2122 }
2123 }
2124
2125 mmc_init(mmc);
2126
2127 if (strcmp(wp_type_str, "temporary") == 0)
2128 write_protect_type = WP_TEMPORARY_TYPE;
2129 else if (strcmp(wp_type_str, "power_on") == 0 )
2130 write_protect_type = WP_POWER_ON_TYPE;
2131 else if (strcmp(wp_type_str, "permanent") == 0)
2132 write_protect_type = WP_PERMANENT_TYPE;
2133 else
2134 return ret;
2135
2136 if (argc == 4)
2137 ret = set_part_write_protect(mmc, write_protect_type, name);
2138 else
2139 ret = set_add_write_protect(mmc, write_protect_type, start, cnt);
2140
2141 return ret;
2142}
2143
2144static int do_amlmmc_boot_wp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2145{
2146 int ret = CMD_RET_USAGE;
2147 u8 ext_csd[512] = {0};
2148 char *name = NULL;
2149 char *type = NULL;
2150 struct mmc *mmc;
2151 int dev = 1;
2152 u8 boot_wp = 0;
2153 u8 boot_wp_status = 0;
2154 u8 perm_dis = 0;
2155 u8 perm_en = 0;
2156
2157 if (argc != 4)
2158 return ret;
2159
2160 name = argv[2];
2161 type = argv[3];
2162 mmc = find_mmc_device(dev);
2163 if (!mmc)
2164 return 1;
2165
2166 if (IS_SD(mmc)) {
2167 mmc = find_mmc_device(~dev);
2168 if (!mmc)
2169 return 1;
2170 if (IS_SD(mmc)) {
2171 printf("SD card can not be write protect\n");
2172 return 1;
2173 }
2174 }
2175
2176 mmc_init(mmc);
2177
2178 ret = mmc_get_ext_csd(mmc, ext_csd);
2179 if (ret)
2180 printf("get ext_csd failed\n");
2181
2182 boot_wp = ext_csd[EXT_CSD_BOOT_WP];
2183 boot_wp_status = ext_csd[EXT_CSD_BOOT_WP_STATUS];
2184
2185 perm_dis = boot_wp & 0x10;
2186 perm_en = boot_wp & 0x4;
2187
2188 if (!strcmp(type, "permanent") && perm_dis == 0) {
2189 if (!strcmp(name, "both"))
2190 boot_wp = 0x4;
2191 else if (!strcmp(name, "boot0"))
2192 boot_wp = 0x84;
2193 else if (!strcmp(name, "boot1"))
2194 boot_wp = 0x8c;
2195 else
2196 return -1;
2197 }
2198
2199 if (!strcmp(type, "poweron")) {
2200 if (!strcmp(name, "both") && perm_en == 0) {
2201 boot_wp |= 0x1;
2202 } else if (!strcmp(name, "boot0")) {
2203 boot_wp |= 0x81;
2204 boot_wp |= boot_wp_status & 0x8;
2205 } else if (!strcmp(name, "boot1")) {
2206 boot_wp |= 0x83;
2207 } else {
2208 return -1;
2209 }
2210 }
2211
2212 printf("boot_wp is 0x%x\n", boot_wp);
2213
2214 ret = mmc_set_ext_csd(mmc, EXT_CSD_BOOT_WP, boot_wp);
2215 if (ret) {
2216 printf("set ext_csd boot_wp field failed\n");
2217 return ret;
2218 }
2219
2220 return ret;
2221}
2222
2223static int do_amlmmc_boot_wp_status(cmd_tbl_t *cmdtp,
2224 int flag, int argc, char *const argv[])
2225{
2226 int ret = CMD_RET_USAGE;
2227 u8 ext_csd[512] = {0};
2228 u8 boot_wp_status;
2229 struct mmc *mmc;
2230 int dev = 1;
2231
2232 if (argc != 2)
2233 return ret;
2234
2235 mmc = find_mmc_device(dev);
2236 if (!mmc)
2237 return ret;
2238
2239 if (IS_SD(mmc)) {
2240 mmc = find_mmc_device(~dev);
2241 if (!mmc)
2242 return ret;
2243 if (IS_SD(mmc)) {
2244 printf("SD card can not be write protect\n");
2245 return 1;
2246 }
2247 }
2248
2249 mmc_init(mmc);
2250 ret = mmc_get_ext_csd(mmc, ext_csd);
2251 if (ret)
2252 printf("get ext_csd failed\n");
2253 boot_wp_status = ext_csd[EXT_CSD_BOOT_WP_STATUS];
2254
2255 if ((boot_wp_status & 0x3) == 0)
2256 printf("boot0 is not protected\n");
2257 else if ((boot_wp_status & 0x3) == 1)
2258 printf("boot0 is power on protected\n");
2259 else if ((boot_wp_status & 0x3) == 2)
2260 printf("boot0 is permanently protected\n");
2261
2262 if ((boot_wp_status & 0xc) == 0)
2263 printf("boot1 is not protected\n");
2264 else if ((boot_wp_status & 0xc) == 4)
2265 printf("boot1 is power on protected\n");
2266 else if ((boot_wp_status & 0xc) == 8)
2267 printf("boot1 is permanently protected\n");
2268
2269 return ret;
2270}
2271
2272static int clear_write_prot_per_group(struct mmc *mmc, u64 blk)
2273{
2274 struct mmc_cmd cmd;
2275 int err;
2276
2277 cmd.cmdidx = MMC_CMD_CLR_WRITE_PROT;
2278 cmd.cmdarg = blk;
2279 cmd.resp_type = MMC_RSP_R1b;
2280
2281 err = mmc_send_cmd(mmc, &cmd, NULL);
2282
2283 return err;
2284}
2285
2286static int set_part_clear_wp(struct mmc *mmc, char *name)
2287{
2288 int err = 0;
2289 u8 ext_csd[512] = {0};
2290 u8 group_num = 32;
2291 u64 wp_grp_size, start = 0, part_end;
2292 u64 group_start;
2293 u64 check_group_start;
2294 u64 set_protect_cnt = 0;
2295 u8 wp_type = WP_CLEAR_TYPE;
2296
2297 err = mmc_get_ext_csd(mmc, ext_csd);
2298 if (err) {
2299 printf("get ext_csd failed\n");
2300 return 1;
2301 }
2302
2303 if (!is_write_protect_valid(ext_csd)) {
2304 printf("CLASS_6_CTRL isn't '0' write protect process is invalid\n");
2305 return 1;
2306 }
2307
2308 err = compute_write_protect_range(mmc, name, ext_csd,
2309 &wp_grp_size, &start, &part_end);
2310 if (err)
2311 return 1;
2312
2313 group_start = start;
2314/*
2315 if (!is_wp_type_temporary(ext_csd)) {
2316 printf("The write protect can't be clear\n");
2317 return 1;
2318 }
2319*/
2320 while ((group_start + wp_grp_size - 1) <= part_end) {
2321 err = clear_write_prot_per_group(mmc, group_start);
2322 if (err) {
2323 printf("Error: The write protect can't be clear\n");
2324 return 1;
2325 }
2326 group_start += wp_grp_size;
2327 set_protect_cnt++;
2328//check write protect type every 32 group
2329 if (set_protect_cnt % 32 == 0) {
2330 check_group_start = group_start - group_num * wp_grp_size;
2331 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2332 if (err)
2333 return 1;
2334 }
2335 }
2336
2337 group_num = set_protect_cnt % 32;
2338 check_group_start = group_start - group_num * wp_grp_size;
2339
2340 if (group_num) {
2341 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2342 if (err)
2343 return 1;
2344 }
2345
2346 return 0;
2347}
2348
2349static int set_add_clear_wp(struct mmc *mmc, u64 start, u64 cnt)
2350{
2351 int err = 0;
2352 u8 ext_csd[512] = {0};
2353 u8 group_num = 32;
2354 u64 wp_grp_size, part_end;
2355 u64 group_start;
2356 u64 check_group_start;
2357 u64 set_protect_cnt = 0;
2358 u8 wp_type = WP_CLEAR_TYPE;
2359 int blk_shift;
2360 u64 mmc_boundary;
2361
2362 err = mmc_get_ext_csd(mmc, ext_csd);
2363 if (err) {
2364 printf("get ext_csd failed\n");
2365 return 1;
2366 }
2367
2368 if (!is_write_protect_valid(ext_csd)) {
2369 printf("CLASS_6_CTRL isn't '0' write protect process is invalid\n");
2370 return 1;
2371 }
2372
2373 wp_grp_size = write_protect_group_size(mmc, ext_csd);
2374
2375 if ((start % wp_grp_size)) {
2376 group_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
2377 printf("Caution! The partition start address isn't' aligned"
2378 "to group size\n"
2379 "the start address is change from 0x%llx to 0x%llx\n",
2380 start, group_start);
2381 part_end = group_start + (cnt - 1) * wp_grp_size - 1;
2382 printf("The write protect group number is 0x%llx, rather than 0x%lld\n",
2383 cnt - 1, cnt);
2384 } else {
2385 group_start = start;
2386 part_end = group_start + cnt * wp_grp_size - 1;
2387 }
2388
2389 blk_shift = ffs(mmc->read_bl_len) - 1;
2390 if (blk_shift < 0) {
2391 printf("bad shift.\n");
2392 return 1;
2393 }
2394 mmc_boundary = mmc->capacity>>blk_shift;
2395
2396 if ((part_end + 1) > mmc_boundary) {
2397 printf("Error: the operation cross the boundary of mmc\n");
2398 return 1;
2399 }
2400
2401 while ((group_start + wp_grp_size - 1) <= part_end) {
2402 err = clear_write_prot_per_group(mmc, group_start);
2403 if (err) {
2404 printf("Error: The write protect can't be clear\n");
2405 return 1;
2406 }
2407 group_start += wp_grp_size;
2408 set_protect_cnt++;
2409//check write protect type every 32 group
2410 if (set_protect_cnt % 32 == 0) {
2411 check_group_start = group_start - group_num * wp_grp_size;
2412 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2413 if (err)
2414 return 1;
2415 }
2416 }
2417
2418 group_num = set_protect_cnt % 32;
2419 check_group_start = group_start - group_num * wp_grp_size;
2420
2421 if (group_num) {
2422 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2423 if (err)
2424 return 1;
2425 }
2426
2427 return 0;
2428}
2429
2430static int do_amlmmc_clear_wp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2431{
2432 int ret = CMD_RET_USAGE;
2433 struct mmc *mmc;
2434 int dev = 1;
2435 char *name = NULL;
2436 u64 start, cnt;
2437
2438 if (argc < 3 || argc > 4)
2439 return ret;
2440
2441 if (argc == 3) {
2442 name = argv[2];
2443 dev = find_dev_num_by_partition_name(name);
2444 if (dev < 0) {
2445 printf("Error: Cannot find dev.\n");
2446 return CMD_RET_USAGE;
2447 }
2448 } else {
2449 start = simple_strtoull(argv[2], NULL, 16);
2450 cnt = simple_strtoull(argv[3], NULL, 10);
2451 }
2452
2453 mmc = find_mmc_device(dev);
2454 if (!mmc)
2455 return 1;
2456
2457 if (IS_SD(mmc)) {
2458 mmc = find_mmc_device(~dev);
2459 if (mmc && IS_SD(mmc)) {
2460 printf("SD card can not be write protect\n");
2461 return 1;
2462 }
2463 }
2464
2465 mmc_init(mmc);
2466
2467 if (argc == 3)
2468 ret = set_part_clear_wp(mmc, name);
2469 else
2470 ret = set_add_clear_wp(mmc, start, cnt);
2471
2472 return ret;
2473}
2474
2475static int send_write_prot_status_group(struct mmc *mmc, u64 blk)
2476{
2477 struct mmc_cmd cmd;
2478 struct mmc_data data;
2479 int err;
2480 void *addr = NULL;
2481 int i = 0;
2482 addr = malloc(4*sizeof(u8));
2483
2484 if (addr == NULL) {
2485 printf("Failed: malloc failed\n");
2486 return 1;
2487 }
2488
2489 cmd.cmdidx = MMC_CMD_SEND_WRITE_PROT;
2490 cmd.cmdarg = blk;
2491 cmd.resp_type = MMC_RSP_R1;
2492
2493 data.dest = addr;
2494 data.blocks = 1;
2495 data.blocksize = 4;
2496 data.flags = MMC_DATA_READ;
2497
2498 err = mmc_send_cmd(mmc, &cmd, &data);
2499 if (err)
2500 goto err_out;
2501
2502 printf("The write protect type for the 32 groups after 0x%llx is:\n0x",
2503 blk);
2504 for (i = 0 ; i < 4; i++)
2505 printf("%02x", ((u8 *)addr)[i]);
2506 printf("\n");
2507
2508 free(addr);
2509 return 0;
2510err_out:
2511 free(addr);
2512 return 1;
2513}
2514
2515static int send_part_wp_status(struct mmc *mmc, char *name)
2516{
2517 int err = 0;
2518 u8 ext_csd[512] = {0};
2519 u64 wp_grp_size, start = 0, part_end;
2520 u64 group_start;
2521
2522 err = mmc_get_ext_csd(mmc, ext_csd);
2523 if (err) {
2524 printf("Failed: get ext_csd failed\n");
2525 return 1;
2526 }
2527
2528 if (!is_write_protect_valid(ext_csd)) {
2529 printf("Failed: CLASS_6_CTRL isn't '0' "
2530 "write protect process is invalid\n");
2531 return 1;
2532 }
2533
2534 err = compute_write_protect_range(mmc, name, ext_csd,
2535 &wp_grp_size, &start, &part_end);
2536 if (err)
2537 return 1;
2538
2539 group_start = start;
2540
2541 while ((group_start + wp_grp_size - 1) <= part_end) {
2542 err = send_write_prot_status_group(mmc, group_start);
2543 if (err)
2544 return 1;
2545 group_start += 32 * wp_grp_size;
2546 }
2547
2548 return 0;
2549}
2550
2551static int send_add_wp_status(struct mmc *mmc, u64 start, u64 cnt)
2552{
2553 int err = 0;
2554 u8 ext_csd[512] = {0};
2555 u64 wp_grp_size, part_end;
2556 u64 group_start;
2557 int blk_shift;
2558 u64 mmc_boundary;
2559 err = mmc_get_ext_csd(mmc, ext_csd);
2560 if (err) {
2561 printf("Failed: get ext_csd failed\n");
2562 return 1;
2563 }
2564
2565 if (!is_write_protect_valid(ext_csd)) {
2566 printf("Failed: CLASS_6_CTRL isn't '0' "
2567 "write protect process is invalid\n");
2568 return 1;
2569 }
2570
2571 wp_grp_size = write_protect_group_size(mmc, ext_csd);
2572
2573 if ((start % wp_grp_size)) {
2574 group_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
2575 printf("Caution! The partition start address isn't' aligned"
2576 "to group size\n"
2577 "the start address is change from 0x%llx to 0x%llx\n",
2578 start, group_start);
2579 part_end = group_start + (cnt - 1) * wp_grp_size - 1;
2580 printf("The write protect group number is 0x%llx, rather than 0x%lld\n",
2581 cnt - 1, cnt);
2582 } else {
2583 group_start = start;
2584 part_end = group_start + cnt * wp_grp_size - 1;
2585 }
2586
2587 blk_shift = ffs(mmc->read_bl_len) - 1;
2588 if (blk_shift < 0) {
2589 printf("bad shift.\n");
2590 return 1;
2591 }
2592 mmc_boundary = mmc->capacity>>blk_shift;
2593
2594 if ((part_end + 1) > mmc_boundary) {
2595 printf("Error: the operation cross the boundary of mmc\n");
2596 return 1;
2597 }
2598
2599 while ((group_start + wp_grp_size - 1) <= part_end) {
2600 err = send_write_prot_status_group(mmc, group_start);
2601 if (err)
2602 return 1;
2603 group_start += 32 * wp_grp_size;
2604 }
2605
2606 return 0;
2607}
2608
2609static int do_amlmmc_send_wp_status(cmd_tbl_t *cmdtp,
2610 int flag, int argc, char *const argv[])
2611{
2612 int ret = CMD_RET_USAGE;
2613 struct mmc *mmc;
2614 int dev = 1;
2615 char *name = NULL;
2616 u64 start, cnt;
2617
2618 if (argc < 3 || argc > 4)
2619 return ret;
2620
2621 if (argc == 3) {
2622 name = argv[2];
2623 dev = find_dev_num_by_partition_name(name);
2624 if (dev < 0) {
2625 printf("Error: Cannot find dev.\n");
2626 return 1;
2627 }
2628 } else {
2629 start = simple_strtoull(argv[2], NULL, 16);
2630 cnt = simple_strtoull(argv[3], NULL, 0);
2631 }
2632
2633 mmc = find_mmc_device(dev);
2634 if (!mmc) {
2635 printf("[%s] no mmc devices available\n", __func__);
2636 return 1;
2637 }
2638
2639 if (IS_SD(mmc)) {
2640 mmc = find_mmc_device(~dev);
2641 if (mmc && IS_SD(mmc)) {
2642 printf("SD card can not be write protect\n");
2643 return 1;
2644 }
2645 }
2646
2647 mmc_init(mmc);
2648
2649 if (argc == 3)
2650 ret = send_part_wp_status(mmc, name);
2651 else
2652 ret = send_add_wp_status(mmc, start, cnt);
2653
2654 if (ret) {
2655 printf("Failed: send partition write protect status failed\n");
2656 }
2657
2658 return ret;
2659}
2660
2661static int do_amlmmc_send_wp_type(cmd_tbl_t *cmdtp,
2662 int flag, int argc, char *const argv[])
2663{
2664 int ret = CMD_RET_USAGE;
2665 struct mmc *mmc;
2666 int dev = 1;
2667 char *name = NULL;
2668 u64 start, cnt;
2669
2670 if (argc < 3 || argc > 4)
2671 return ret;
2672
2673 if (argc == 3) {
2674 name = argv[2];
2675 dev = find_dev_num_by_partition_name(name);
2676 if (dev < 0) {
2677 printf("Error: Cannot find dev.\n");
2678 return 1;
2679 }
2680 } else {
2681 start = simple_strtoull(argv[2], NULL, 16);
2682 cnt = simple_strtoull(argv[3], NULL, 0);
2683 }
2684
2685 mmc = find_mmc_device(dev);
2686 if (!mmc) {
2687 printf("[%s] no mmc devices available\n", __func__);
2688 return 1;
2689 }
2690
2691 if (IS_SD(mmc)) {
2692 mmc = find_mmc_device(~dev);
2693 if (mmc && IS_SD(mmc)) {
2694 printf("SD card can not be write protect\n");
2695 return 1;
2696 }
2697 }
2698
2699 mmc_init(mmc);
2700
2701 if (argc == 3)
2702 ret = send_part_wp_type(mmc, name);
2703 else
2704 ret = send_add_wp_type(mmc, start, cnt);
2705
2706 if (ret) {
2707 printf("Failed: send partitions write protect type failed\n");
2708 }
2709
2710 return ret;
2711}
2712
2713static int set_driver_strength(struct mmc *mmc, int strength)
2714{
2715 int ret = 0;
2716 u8 ext_csd[512] = {0};
2717 u8 strength_type = 0;
2718 u8 driver_strength;
2719 u8 hs_timing = 0;
2720 ret = mmc_get_ext_csd(mmc, ext_csd);
2721 if (ret) {
2722 printf("get ext_csd failed\n");
2723 return ret;
2724 }
2725 strength_type = 1 << strength;
2726 driver_strength = ext_csd[EXT_CSD_DRIVER_STRENGTH];
2727 if (0 == (strength_type & driver_strength)) {
2728 printf("Failed: This device didn't support strength type %d\n", strength);
2729 return 1;
2730 }
2731
2732 hs_timing = ext_csd[EXT_CSD_HS_TIMING];
2733 if ((hs_timing >> 4) > 0) {
2734 printf("Failed: The driver strength has been set already, \
2735 please reset the device\n");
2736 return 1;
2737 }
2738
2739 hs_timing = hs_timing | (strength << 4);
2740
2741 ret = mmc_set_ext_csd(mmc, EXT_CSD_HS_TIMING, hs_timing);
2742 if (ret) {
2743 printf("set ext_csd hs_timing field failed\n");
2744 return ret;
2745 }
2746 ret = mmc_get_ext_csd(mmc, ext_csd);
2747 if (ret) {
2748 printf("get ext_csd failed\n");
2749 return ret;
2750 }
2751 printf("The ext_csd[HS_TIMING] has been set to 0x%x\n",
2752 ext_csd[EXT_CSD_HS_TIMING]);
2753 return ret;
2754}
2755
2756static int get_driver_strength(struct mmc *mmc)
2757{
2758 int ret = 0;
2759 u8 ext_csd[512] = {0};
2760 u8 support_ds_type = 0;
2761 u8 cur_driver_strength;
2762 u8 hs_timing = 0;
2763 ret = mmc_get_ext_csd(mmc, ext_csd);
2764 if (ret) {
2765 printf("get ext_csd failed\n");
2766 return ret;
2767 }
2768
2769 support_ds_type = ext_csd[EXT_CSD_DRIVER_STRENGTH];
2770
2771 hs_timing = ext_csd[EXT_CSD_HS_TIMING];
2772 cur_driver_strength = hs_timing >> 4;
2773
2774 printf("current strength type is: ");
2775 int strength_type = 0;
2776 while (support_ds_type) {
2777 if (support_ds_type & 1) {
2778 if (cur_driver_strength == strength_type)
2779 printf("[%d] ", strength_type);
2780 else
2781 printf("%d ", strength_type);
2782 }
2783 strength_type++;
2784 support_ds_type = support_ds_type >> 1;
2785 }
2786 printf("\n");
2787 return ret;
2788}
2789
2790static int amlmmc_set_driver_strength(int argc, char *const argv[])
2791{
2792 int ret = CMD_RET_USAGE;
2793 int dev, strength;
2794 struct mmc *mmc;
2795
2796 if (argc != 4)
2797 return CMD_RET_USAGE;
2798
2799 dev = simple_strtoul(argv[2], NULL, 10);
2800 strength = simple_strtoul(argv[3], NULL, 10);
2801 mmc = find_mmc_device(dev);
2802 if (!mmc) {
2803 puts("no mmc devices available\n");
2804 return 1;
2805 }
2806 mmc_init(mmc);
2807
2808 ret = set_driver_strength(mmc, strength);
2809
2810 return ret;
2811}
2812
2813static int amlmmc_get_driver_strength(int argc, char *const argv[])
2814{
2815 int ret = CMD_RET_USAGE;
2816 int dev;
2817 struct mmc *mmc;
2818
2819 if (argc != 3)
2820 return CMD_RET_USAGE;
2821
2822 dev = simple_strtoul(argv[2], NULL, 10);
2823 mmc = find_mmc_device(dev);
2824 if (!mmc) {
2825 puts("no mmc devices available\n");
2826 return 1;
2827 }
2828 mmc_init(mmc);
2829
2830 ret = get_driver_strength(mmc);
2831
2832 return ret;
2833}
2834
2835static int do_amlmmc_driver_strength(cmd_tbl_t *cmdtp,
2836 int flag, int argc, char *const argv[])
2837{
2838 int ret = CMD_RET_USAGE;
2839
2840 if (argc == 3)
2841 ret = amlmmc_get_driver_strength(argc,argv);
2842 else if (argc == 4)
2843 ret = amlmmc_set_driver_strength(argc,argv);
2844
2845 return ret;
2846}
2847
2848static cmd_tbl_t cmd_amlmmc[] = {
2849 U_BOOT_CMD_MKENT(read, 6, 0, do_amlmmc_read, "", ""),
2850 U_BOOT_CMD_MKENT(write, 6, 0, do_amlmmc_write, "", ""),
2851 U_BOOT_CMD_MKENT(erase, 5, 0, do_amlmmc_erase, "", ""),
2852 U_BOOT_CMD_MKENT(rescan, 3, 0, do_amlmmc_rescan, "", ""),
2853 U_BOOT_CMD_MKENT(part, 3, 0, do_amlmmc_part, "", ""),
2854 U_BOOT_CMD_MKENT(list, 2, 0, do_amlmmc_list, "", ""),
2855 U_BOOT_CMD_MKENT(switch, 4, 0, do_amlmmc_switch, "", ""),
2856 U_BOOT_CMD_MKENT(status, 3, 0, do_amlmmc_status, "", ""),
2857 U_BOOT_CMD_MKENT(ext_csd, 5, 0, do_amlmmc_ext_csd, "", ""),
2858 U_BOOT_CMD_MKENT(response, 3, 0, do_amlmmc_response, "", ""),
2859 U_BOOT_CMD_MKENT(controller, 3, 0, do_amlmmc_controller, "", ""),
2860 U_BOOT_CMD_MKENT(size, 4, 0, do_amlmmc_size, "", ""),
2861 U_BOOT_CMD_MKENT(env, 2, 0, do_amlmmc_env, "", ""),
2862 U_BOOT_CMD_MKENT(write_protect, 5, 0, do_amlmmc_write_protect, "", ""),
2863 U_BOOT_CMD_MKENT(send_wp_status, 4, 0, do_amlmmc_send_wp_status, "", ""),
2864 U_BOOT_CMD_MKENT(send_wp_type, 4, 0, do_amlmmc_send_wp_type, "", ""),
2865 U_BOOT_CMD_MKENT(clear_wp, 4, 0, do_amlmmc_clear_wp, "", ""),
2866 U_BOOT_CMD_MKENT(boot_wp, 4, 0, do_amlmmc_boot_wp, "", ""),
2867 U_BOOT_CMD_MKENT(boot_wp_status, 2, 0, do_amlmmc_boot_wp_status, "", ""),
2868 U_BOOT_CMD_MKENT(ds, 4, 0, do_amlmmc_driver_strength, "", ""),
2869#ifdef CONFIG_SECURITYKEY
2870 U_BOOT_CMD_MKENT(key, 2, 0, do_amlmmc_key, "", ""),
2871#endif
2872};
2873
2874static int do_amlmmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2875{
2876 cmd_tbl_t *cp;
2877
2878 cp = find_cmd_tbl(argv[1], cmd_amlmmc, ARRAY_SIZE(cmd_amlmmc));
2879
2880 if (cp == NULL || argc > cp->maxargs)
2881 return CMD_RET_USAGE;
2882
2883 if (flag == CMD_FLAG_REPEAT && !cp->cmd_rep)
2884 return CMD_RET_SUCCESS;
2885
2886 return cp->cmd(cmdtp, flag, argc, argv);
2887}
2888
2889U_BOOT_CMD(
2890 amlmmc, 6, 1, do_amlmmcops,
2891 "AMLMMC sub system",
2892 "read <partition_name> ram_addr addr_byte# cnt_byte\n"
2893 "amlmmc write <partition_name> ram_addr addr_byte# cnt_byte\n"
2894 "amlmmc erase <partition_name> addr_byte# cnt_byte\n"
2895 "amlmmc erase <partition_name>/<device num>\n"
2896 "amlmmc rescan <device_num>\n"
2897 "amlmmc part <device_num> - show partition information of mmc\n"
2898 "amlmmc list - lists available devices\n"
2899 "amlmmc env - display env partition offset\n"
2900 "amlmmc switch <device_num> <part name> - part name : boot0, boot1, user\n"
2901 "amlmmc status <device_num> - read sd/emmc device status\n"
2902 "amlmmc ext_csd <device_num> <byte> - read sd/emmc device EXT_CSD [byte]\n"
2903 "amlmmc ext_csd <device_num> <byte> <value> - write sd/emmc device EXT_CSD [byte] value\n"
2904 "amlmmc response <device_num> - read sd/emmc last command response\n"
2905 "amlmmc controller <device_num> - read sd/emmc controller register\n"
2906 "amlmmc write_protect <partition_name> <write_protect_type>\n"
2907 " - set write protect on partition through power_on or temporary\n"
2908 "amlmmc write_protect <addr_base16> <cnt_base10> <write_protect_type>\n"
2909 " - set write protect on specified address through power_on or temporary\n"
2910 "amlmmc send_wp_status <partition_name> send protect status of partition\n"
2911 "amlmmc send_wp_status <addr_base16> <cnt_base10> send protect status on specified address\n"
2912 "amlmmc send_wp_type <partition_name> send protect type of partition\n"
2913 "amlmmc send_wp_type <addr_base16> <cnt_base10> send protect type on specified address\n"
2914 "amlmmc clear_wp <partition_name> clear write protect of partition\n"
2915 "amlmmc clear_wp <addr_base16> <cnt_base10> clear write protect on specified address\n"
2916 "amlmmc boot_wp <boot number> <write protect type> boot0/boot1/both, /poweron/permanent\n"
2917 "amlmmc boot_wp_status send boot write protect status\n"
2918 "amlmmc ds <dev_num> <val> set driver strength\n"
2919#ifdef CONFIG_SECURITYKEY
2920 "amlmmc key - disprotect key partition\n"
2921#endif
2922);
2923
2924/* dtb read&write operation with backup updates */
2925static u32 _calc_dtb_checksum(struct aml_dtb_rsv * dtb)
2926{
2927 int i = 0;
2928 int size = sizeof(struct aml_dtb_rsv) - sizeof(u32);
2929 u32 * buffer;
2930 u32 checksum = 0;
2931
2932 if ((u64)dtb % 4 != 0) {
2933 BUG();
2934 }
2935
2936 size = size >> 2;
2937 buffer = (u32*) dtb;
2938 while (i < size)
2939 checksum += buffer[i++];
2940
2941 return checksum;
2942}
2943
2944static int _verify_dtb_checksum(struct aml_dtb_rsv * dtb)
2945{
2946 u32 checksum;
2947
2948 checksum = _calc_dtb_checksum(dtb);
2949 dtb_info("calc %x, store %x\n", checksum, dtb->checksum);
2950
2951 return !(checksum == dtb->checksum);
2952}
2953
2954static int _dtb_read(struct mmc *mmc, u64 blk, u64 cnt, void * addr)
2955{
2956 int dev = EMMC_DTB_DEV;
2957 u64 n;
2958 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
2959 if (n != cnt) {
2960 dtb_err("%s: dev # %d, block # %#llx, count # %#llx ERROR!\n",
2961 __func__, dev, blk, cnt);
2962 }
2963
2964 return (n != cnt);
2965}
2966
2967static int _dtb_write(struct mmc *mmc, u64 blk, u64 cnt, void * addr)
2968{
2969 int dev = EMMC_DTB_DEV;
2970 u64 n;
2971 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
2972 if (n != cnt) {
2973 dtb_err("%s: dev # %d, block # %#llx, count # %#llx ERROR!\n",
2974 __func__, dev, blk, cnt);
2975 }
2976
2977 return (n != cnt);
2978}
2979
2980static struct mmc *_dtb_init(void)
2981{
2982 struct mmc *mmc = find_mmc_device(EMMC_DTB_DEV);
2983 if (!mmc) {
2984 dtb_err("not find mmc\n");
2985 return NULL;
2986 }
2987
2988 if (mmc_init(mmc)) {
2989 dtb_err("mmc init failed\n");
2990 return NULL;
2991 }
2992 return mmc;
2993}
2994
2995static int dtb_read_shortcut(struct mmc * mmc, void *addr)
2996{
2997 u64 blk, cnt, dtb_glb_offset;
2998 int dev = EMMC_DTB_DEV;
2999 struct aml_dtb_info *info = &dtb_infos;
3000 struct partitions * part = NULL;
3001 struct virtual_partition *vpart = NULL;
3002 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3003 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3004 dtb_glb_offset = part->offset + vpart->offset;
3005 /* short cut */
3006 if (info->valid[0]) {
3007 dtb_info("short cut in...\n");
3008 blk = dtb_glb_offset / mmc->read_bl_len;
3009 cnt = vpart->size / mmc->read_bl_len;
3010 if (_dtb_read(mmc, blk, cnt, addr)) {
3011 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3012 __func__, dev, blk, cnt);
3013 /*try dtb2 if it's valid */
3014 if (info->valid[1]) {
3015 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3016 cnt = vpart->size / mmc->read_bl_len;
3017 if (_dtb_read(mmc, blk, cnt, addr)) {
3018 dtb_err("%s: dev # %d, block # %#llx, cnt # %#llx ERROR!\n",
3019 __func__, dev, blk, cnt);
3020 return -1;
3021 }
3022 }
3023 }
3024 return 0;
3025 }
3026 return -2;
3027}
3028
3029static int update_dtb_info(struct mmc *mmc, void *addr)
3030{
3031 int ret = 0, dev = EMMC_DTB_DEV;
3032 u64 blk, cnt, dtb_glb_offset;
3033 struct aml_dtb_rsv * dtb = (struct aml_dtb_rsv *) addr;
3034 struct aml_dtb_info *info = &dtb_infos;
3035 int cpy = 1, valid = 0;
3036 struct partitions * part = NULL;
3037 struct virtual_partition *vpart = NULL;
3038 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3039 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3040 dtb_glb_offset = part->offset + vpart->offset;
3041
3042 while (cpy >= 0) {
3043 blk = (dtb_glb_offset + cpy * (vpart->size)) / mmc->read_bl_len;
3044 cnt = vpart->size / mmc->read_bl_len;
3045 ret = _dtb_read(mmc, blk, cnt, addr);
3046 if (ret) {
3047 dtb_err("%s: dev # %d, block # %#llx, cnt # %#llx ERROR!\n",
3048 __func__, dev, blk, cnt);
3049 } else {
3050 ret = _verify_dtb_checksum(dtb);
3051 /* check magic avoid whole 0 issue */
3052 if (!ret && (dtb->magic != 0)) {
3053 info->stamp[cpy] = dtb->timestamp;
3054 info->valid[cpy] = 1;
3055 }
3056 else
3057 dtb_wrn("cpy %d is not valid\n", cpy);
3058 }
3059 valid += info->valid[cpy];
3060 cpy --;
3061 }
3062 return valid;
3063}
3064
3065static int update_invalid_dtb(struct mmc *mmc, void *addr)
3066{
3067 int ret = 0, dev = EMMC_DTB_DEV;
3068 u64 blk, cnt, dtb_glb_offset;
3069 struct aml_dtb_rsv * dtb = (struct aml_dtb_rsv *) addr;
3070 struct aml_dtb_info *info = &dtb_infos;
3071 struct partitions * part = NULL;
3072 struct virtual_partition *vpart = NULL;
3073 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3074 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3075 dtb_glb_offset = part->offset + vpart->offset;
3076 cnt = vpart->size / mmc->read_bl_len;
3077
3078 if (info->valid[1]) {
3079 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3080 if (_dtb_read(mmc, blk, cnt, addr)) {
3081 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3082 __func__, dev, blk, cnt);
3083 ret = -2;
3084 }
3085 /* fixme, update the invalid one - dtb1 */
3086 blk = (dtb_glb_offset) / mmc->read_bl_len;
3087 if (_dtb_write(mmc, blk, cnt, addr)) {
3088 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3089 __func__, dev, blk, cnt);
3090 ret = -2;
3091 }
3092 info->valid[0] = 1;
3093 info->stamp[0] = dtb->timestamp;
3094 } else {
3095 dtb_info("update dtb2");
3096 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3097 if (_dtb_write(mmc, blk, cnt, addr)) {
3098 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3099 __func__, dev, blk, cnt);
3100 ret = -2;
3101 }
3102 info->valid[1] = 1;
3103 info->stamp[1] = dtb->timestamp;
3104 }
3105 return ret;
3106}
3107
3108int update_old_dtb(struct mmc *mmc, void *addr)
3109{
3110 int ret = 0, dev = EMMC_DTB_DEV;
3111 u64 blk, cnt, dtb_glb_offset;
3112 struct aml_dtb_rsv * dtb = (struct aml_dtb_rsv *) addr;
3113 struct aml_dtb_info *info = &dtb_infos;
3114 struct partitions * part = NULL;
3115 struct virtual_partition *vpart = NULL;
3116 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3117 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3118 dtb_glb_offset = part->offset + vpart->offset;
3119 cnt = vpart->size / mmc->read_bl_len;
3120 if (stamp_after(info->stamp[1], info->stamp[0])) {
3121 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3122 if (_dtb_read(mmc, blk, cnt, addr)) {
3123 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3124 __func__, dev, blk, cnt);
3125 ret = -3;
3126 }
3127 /*update dtb1*/
3128 blk = dtb_glb_offset / mmc->read_bl_len;
3129 if (_dtb_write(mmc, blk, cnt, addr)) {
3130 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3131 __func__, dev, blk, cnt);
3132 ret = -3;
3133 }
3134 info->stamp[0] = dtb->timestamp;
3135 } else if (stamp_after(info->stamp[0], info->stamp[1])) {
3136 /*update dtb2*/
3137 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3138 if (_dtb_write(mmc, blk, cnt, addr)) {
3139 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3140 __func__, dev, blk, cnt);
3141 ret = -3;
3142 }
3143 info->stamp[1] = dtb->timestamp;
3144 } else {
3145 dtb_info("do nothing\n");
3146 }
3147 return ret;
3148}
3149
3150int dtb_read(void *addr)
3151{
3152 int ret = 0;
3153 int valid = 0;
3154 struct mmc *mmc;
3155
3156 mmc = _dtb_init();
3157 if (mmc == NULL)
3158 return -10;
3159
3160 if (dtb_read_shortcut(mmc, addr) == 0)
3161 return ret;
3162
3163 valid = update_dtb_info(mmc, addr);
3164 dtb_info("total valid %d\n", valid);
3165 /* check valid */
3166 switch (valid) {
3167 /* none is valid, using the 1st one for compatibility*/
3168 case 0:
3169 ret = -1;
3170 goto _out;
3171 break;
3172 /* only 1 is valid, using the valid one */
3173 case 1:
3174 update_invalid_dtb(mmc, addr);
3175 break;
3176 /* both are valid, pickup new one. */
3177 case 2:
3178 update_old_dtb(mmc, addr);
3179 break;
3180 default:
3181 dtb_err("impossible valid values.\n");
3182 BUG();
3183 break;
3184 }
3185_out:
3186 return ret;
3187}
3188
3189
3190int dtb_write(void *addr)
3191{
3192 int ret = 0;
3193 struct aml_dtb_rsv * dtb = (struct aml_dtb_rsv *) addr;
3194 struct aml_dtb_info *info = &dtb_infos;
3195 u64 blk, cnt, dtb_glb_offset;
3196 int cpy, valid;
3197 struct mmc * mmc;
3198 struct partitions * part = NULL;
3199 struct virtual_partition *vpart = NULL;
3200 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3201 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3202 dtb_glb_offset = part->offset + vpart->offset;
3203
3204 mmc = _dtb_init();
3205 if (NULL == mmc)
3206 return -10;
3207
3208 /* stamp */
3209 valid = info->valid[0] + info->valid[1];
3210 dtb_info("valid %d\n", valid);
3211 if (0 == valid)
3212 dtb->timestamp = 0;
3213 else if (1 == valid) {
3214 dtb->timestamp = 1 + info->stamp[info->valid[0]?0:1];
3215 } else {
3216 /* both are valid */
3217 if (info->stamp[0] != info->stamp[1]) {
3218 dtb_wrn("timestamp are not same %d:%d\n",
3219 info->stamp[0], info->stamp[1]);
3220 dtb->timestamp = 1 + (stamp_after(info->stamp[1], info->stamp[0])?
3221 info->stamp[1]:info->stamp[0]);
3222 } else
3223 dtb->timestamp = 1 + info->stamp[0];
3224 }
3225 /*setting version and magic*/
3226 dtb->version = 1; /* base version */
3227 dtb->magic = 0x00447e41; /*A~D\0*/
3228 dtb->checksum = _calc_dtb_checksum(dtb);
3229 dtb_info("new stamp %d, checksum 0x%x, version %d, magic %s\n",
3230 dtb->timestamp, dtb->checksum, dtb->version, (char *)&dtb->magic);
3231
3232 for (cpy = 0; cpy < DTB_COPIES; cpy++) {
3233 blk = (dtb_glb_offset + cpy * (vpart->size)) / mmc->read_bl_len;
3234 cnt = vpart->size / mmc->read_bl_len;
3235 ret |= _dtb_write(mmc, blk, cnt, addr);
3236 info->valid[cpy] = 1;
3237 info->stamp[cpy] = dtb->timestamp;
3238 }
3239
3240 return ret;
3241}
3242
3243extern int check_valid_dts(unsigned char *buffer);
3244int renew_partition_tbl(unsigned char *buffer)
3245{
3246 int ret = 0;
3247
3248 unsigned char *temp = NULL;
3249 if (!buffer)
3250 return 1;
3251 temp = malloc (AML_DTB_IMG_MAX_SZ);
3252 if (!temp)
3253 return 1;
3254 memcpy(temp, buffer, AML_DTB_IMG_MAX_SZ);
3255 /* todo, check new dts imcoming.... */
3256 ret = check_valid_dts(temp);
3257 free(temp);
3258 /* todo, check new dts imcoming.... */
3259/* ret = check_valid_dts(buffer);*/
3260 /* only the dts new is valid */
3261 if (!ret) {
3262 free_partitions();
3263 ret = get_partition_from_dts(buffer);
3264 if (ret) {
3265 printf("Fail to get partition table from dts\n");
3266 goto _out;
3267 }
3268 if (0 == mmc_device_init(_dtb_init())) {
3269 printf("partition table success\n");
3270 ret = 0;
3271 goto _out;
3272 }
3273 printf("partition table error\n");
3274 ret = 1;
3275 }
3276
3277_out:
3278 return ret;
3279}
3280
3281int do_amlmmc_dtb_key(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3282{
3283 int dev, ret = 0;
3284 void *addr = NULL;
3285 u64 cnt = 0, n = 0, blk = 0;
3286 //u64 size;
3287 struct partitions *part = NULL;
3288 struct virtual_partition *vpart = NULL;
3289 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3290 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3291
3292 switch (argc) {
3293 case 3:
3294 if (strcmp(argv[1], "erase") == 0) {
3295 if (strcmp(argv[2], "dtb") == 0) {
3296 printf("start erase dtb......\n");
3297 dev = EMMC_DTB_DEV;
3298 struct mmc *mmc = find_mmc_device(dev);
3299 if (!mmc) {
3300 printf("not find mmc\n");
3301 return 1;
3302 }
3303 blk = (part->offset + vpart->offset) / mmc->read_bl_len;
3304 cnt = (vpart->size * 2) / mmc->read_bl_len;
3305 if (cnt != 0)
3306 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
3307 printf("dev # %d, %s, several blocks erased %s\n",
3308 dev, (flag == 0) ? " ":(argv[2]),(n == 0) ? "OK" : "ERROR");
3309 return (n == 0) ? 0 : 1;
3310 }else if (strcmp(argv[2], "key") == 0){
3311 printf("start erase key......\n");
3312 dev = 1;
3313 struct mmc *mmc = find_mmc_device(dev);
3314 if (!mmc) {
3315 printf("not find mmc\n");
3316 return 1;
3317 }
3318 n = mmc_key_erase();
3319 printf("dev # %d, %s, several blocks erased %s\n",
3320 dev, (flag == 0) ? " ":(argv[2]),(n == 0) ? "OK" : "ERROR");
3321 return (n == 0) ? 0 : 1;
3322 }
3323 } else if (strcmp(argv[1], "cali_pattern") == 0) {
3324
3325 if (strcmp(argv[2], "write") == 0) {
3326 dev = EMMC_DTB_DEV;
3327 struct mmc *mmc = find_mmc_device(dev);
3328 if (!mmc) {
3329 printf("not find mmc\n");
3330 return 1;
3331 }
3332 vpart = aml_get_virtual_partition_by_name(MMC_PATTERN_NAME);
3333 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3334 addr = (void *)malloc(vpart->size);
3335 if (addr == NULL) {
3336 printf("cali_pattern malloc fail\n");
3337 return 1;
3338 }
3339 mmc_write_cali_mattern(addr);
3340 blk = (part->offset + vpart->offset) / mmc->read_bl_len;
3341 cnt = vpart->size / mmc->read_bl_len;
3342 if (cnt != 0)
3343 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
3344 printf("dev # %d, %s, several calibration pattern blocks write %s\n",
3345 dev, (flag == 0) ? " ":(argv[2]),(n == cnt) ? "OK" : "ERROR");
3346 free(addr);
3347 return (n == cnt) ? 0 : 1;
3348 }
3349 }
3350 break;
3351 case 4:
3352 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3353 if (strcmp(argv[1], "dtb_read") == 0) {
3354 /* fixme, */
3355 ret = dtb_read(addr);
3356 return 0;
3357
3358 } else if (strcmp(argv[1], "dtb_write") == 0) {
3359 /* fixme, should we check the return value? */
3360 ret = dtb_write(addr);
3361 ret |= renew_partition_tbl(addr);
3362 return ret;
3363 }
3364 return 0;
3365 default:
3366 break;
3367 }
3368 return 1;
3369}
3370
3371/* update partition table in reserved partition. */
3372__weak int emmc_update_ept(unsigned char *buffer)
3373{
3374 int ret = 0;
3375
3376#ifndef DTB_BIND_KERNEL
3377 dtb_write(buffer);
3378#endif
3379 ret = renew_partition_tbl(buffer);
3380 return ret;
3381}
3382
3383/* fixme, should use renew_partition_tbl here! */
3384__weak int emmc_update_mbr(unsigned char *buffer)
3385{
3386 int ret = 0;
3387 cpu_id_t cpu_id = get_cpu_id();
3388
3389 if (cpu_id.family_id < MESON_CPU_MAJOR_ID_GXL) {
3390 ret = -1;
3391 printf("MBR not support, try dtb\n");
3392 goto _out;
3393 }
3394#ifndef DTB_BIND_KERNEL
3395 dtb_write(buffer);
3396#endif
3397 ret = get_partition_from_dts(buffer);
3398 if (ret) {
3399 printf("Fail to get partition table from dts\n");
3400 goto _out;
3401 }
3402 ret = mmc_device_init(_dtb_init());
3403 printf("%s: update mbr %s\n", __func__, ret?"Fail":"Success");
3404_out:
3405 return ret;
3406}
3407
3408int emmc_erase_rsv(struct mmc *mmc, char *rsv_part)
3409{
3410 u64 cnt = 0, n = 0, blk = 0;
3411 struct partitions *part = NULL;
3412 struct virtual_partition *vpart = NULL;
3413
3414 if (rsv_part == NULL)
3415 return -1;
3416
3417 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3418 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3419 if (strcmp(rsv_part, "dtb") == 0) {
3420 blk = (part->offset + vpart->offset) / mmc->read_bl_len;
3421 cnt = (vpart->size * 2) / mmc->read_bl_len;
3422 if (cnt != 0)
3423 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
3424 printf("%s is erased %s\n",
3425 rsv_part, (n == 0) ? "OK" : "ERROR");
3426 return (n == 0) ? 0 : 1;
3427 } else if (strcmp(rsv_part, "key") == 0) {
3428 n = mmc_key_erase();
3429 printf("%s is erased %s\n",
3430 rsv_part, (n == 0) ? "OK" : "ERROR");
3431 return (n == 0) ? 0 : 1;
3432 }
3433 return 1;
3434}
3435
3436int do_emmc_erase(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3437{
3438 int dev;
3439 u64 cnt = 0, n = 0, blk = 0;
3440 //u64 size;
3441 struct partitions *part = NULL;
3442 struct virtual_partition *vpart = NULL;
3443 struct mmc *mmc;
3444 if (argc != 3)
3445 return CMD_RET_USAGE;
3446
3447 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3448 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3449 if (strcmp(argv[2], "dtb") == 0) {
3450 printf("start erase dtb......\n");
3451 dev = EMMC_DTB_DEV;
3452 mmc = find_mmc_device(dev);
3453 if (!mmc) {
3454 printf("not find mmc\n");
3455 return 1;
3456 }
3457 blk = (part->offset + vpart->offset) / mmc->read_bl_len;
3458 cnt = (vpart->size * 2) / mmc->read_bl_len;
3459 if (cnt != 0)
3460 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
3461 printf("dev # %d, %s, several blocks erased %s\n",
3462 dev, (flag == 0) ? " ":(argv[2]),(n == 0) ? "OK" : "ERROR");
3463 return (n == 0) ? 0 : 1;
3464 } else if (strcmp(argv[2], "key") == 0) {
3465 printf("start erase key......\n");
3466 dev = 1;
3467 mmc = find_mmc_device(dev);
3468 if (!mmc) {
3469 printf("not find mmc\n");
3470 return 1;
3471 }
3472 n = mmc_key_erase();
3473 printf("dev # %d, %s, several blocks erased %s\n",
3474 dev, (flag == 0) ? " ":(argv[2]),(n == 0) ? "OK" : "ERROR");
3475 return (n == 0) ? 0 : 1;
3476 }
3477 return 1;
3478}
3479
3480int do_emmc_dtb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3481{
3482 int ret = 0;
3483 void *addr = NULL;
3484
3485 if (argc != 4)
3486 return CMD_RET_USAGE;
3487
3488 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3489 ret = dtb_read(addr);
3490 return ret;
3491}
3492
3493int do_emmc_dtb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3494{
3495 int ret = 0;
3496 void *addr = NULL;
3497
3498 if (argc != 4)
3499 return CMD_RET_USAGE;
3500
3501 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3502 ret = dtb_write(addr);
3503 ret |= renew_partition_tbl(addr);
3504 return ret;
3505}
3506
3507static int _fastboot_context_read(struct mmc *mmc, u64 blk,
3508 u64 cnt, void *addr)
3509{
3510 int dev = EMMC_FASTBOOT_CONTEXT_DEV;
3511 u64 n;
3512
3513 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
3514 if (n != cnt) {
3515 fb_err("%s: dev # %d, block # %#llx, count # %#llx ERROR!\n",
3516 __func__, dev, blk, cnt);
3517 }
3518
3519 return n != cnt;
3520}
3521
3522int fastboot_context_read(void *buf, size_t size)
3523{
3524 uint32_t crc_result;
3525 struct mmc *mmc;
3526 struct FastbootContext *fb_cont;
3527 int fb_size = sizeof(struct FastbootContext);
3528 u64 blk, cnt, fb_glb_offset;
3529 int dev = EMMC_FASTBOOT_CONTEXT_DEV;
3530 struct partitions *part = NULL;
3531 struct virtual_partition *vpart = NULL;
3532
3533 mmc = find_mmc_device(dev);
3534 if (!mmc) {
3535 puts("no mmc devices available\n");
3536 return 1;
3537 }
3538
3539 if (mmc_init(mmc)) {
3540 printf("%s() %d: emmc init failed\n", __func__, __LINE__);
3541 return 1;
3542 }
3543
3544 vpart = aml_get_virtual_partition_by_name(MMC_FASTBOOT_CONTEXT_NAME);
3545 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3546 fb_glb_offset = part->offset + vpart->offset;
3547
3548 blk = fb_glb_offset / mmc->read_bl_len;
3549 cnt = size / mmc->read_bl_len;
3550
3551 if (_fastboot_context_read(mmc, blk, cnt, buf))
3552 return 1;
3553
3554 fb_cont = (struct FastbootContext *)buf;
3555 crc_result = crc32(0, buf, fb_size - 4);
3556
3557 if (crc_result != fb_cont->crc32) {
3558 printf("%s %d: crc checksum ERROR!\n", __func__, __LINE__);
3559 return 1;
3560 }
3561 return 0;
3562}
3563
3564
3565int do_emmc_fb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3566{
3567 int ret = 0;
3568 void *addr = NULL;
3569 u64 size;
3570
3571 if (argc != 4)
3572 return CMD_RET_USAGE;
3573
3574 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3575 size = simple_strtoull(argv[3], NULL, 16);
3576 ret = fastboot_context_read(addr, size);
3577 return ret;
3578}
3579
3580static int _fastboot_context_write(struct mmc *mmc, u64 blk,
3581 u64 cnt, void *addr)
3582{
3583 int dev = EMMC_FASTBOOT_CONTEXT_DEV;
3584 int n;
3585
3586 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
3587
3588 if (n != cnt) {
3589 fb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3590 __func__, dev, blk, cnt);
3591 }
3592
3593 return n != cnt;
3594}
3595
3596int fastboot_context_write(void *buf, size_t size)
3597{
3598 int ret = 0;
3599 struct FastbootContext *fb_cont = (struct FastbootContext *)buf;
3600 u64 blk, cnt, fb_glb_offset;
3601 struct mmc *mmc;
3602 struct partitions *part = NULL;
3603 struct virtual_partition *vpart = NULL;
3604 int dev = EMMC_FASTBOOT_CONTEXT_DEV;
3605 int fb_size = sizeof(struct FastbootContext);
3606
3607 mmc = find_mmc_device(dev);
3608 if (!mmc) {
3609 puts("no mmc devices available\n");
3610 return 1;
3611 }
3612
3613 ret = mmc_init(mmc);
3614 if (ret) {
3615 printf("%s() %d: emmc init failed\n", __func__, __LINE__);
3616 return 1;
3617 }
3618
3619 vpart = aml_get_virtual_partition_by_name(MMC_FASTBOOT_CONTEXT_NAME);
3620 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3621 fb_glb_offset = part->offset + vpart->offset;
3622 fb_cont->crc32 = crc32(0, buf, fb_size - 4);
3623 blk = fb_glb_offset / mmc->read_bl_len;
3624 cnt = size / mmc->read_bl_len;
3625 ret = _fastboot_context_write(mmc, blk, cnt, buf);
3626
3627 return ret;
3628}
3629
3630int do_emmc_fb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3631{
3632 int ret = 0;
3633 void *addr = NULL;
3634 u64 size;
3635
3636 if (argc != 4)
3637 return CMD_RET_USAGE;
3638
3639 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3640 size = simple_strtoull(argv[3], NULL, 16);
3641 ret = fastboot_context_write(addr, size);
3642 return ret;
3643}
3644
3645int do_emmc_key_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3646{
3647 int ret = 0;
3648 void *addr = NULL;
3649 u64 size;
3650 uint32_t actual_length = 0;
3651
3652 if (argc != 4)
3653 return CMD_RET_USAGE;
3654
3655 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3656 size = simple_strtoull(argv[3], NULL, 16);
3657 printf("enter emmc key read !!\n");
3658 printf("addr:%p size:%llx\n",addr,size);
3659 ret = mmc_key_read(addr, size, &actual_length);
3660 printf("ret:%d\n",ret);
3661 return ret;
3662}
3663
3664int do_emmc_key_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
3665
3666 int ret = 0;
3667 void *addr = NULL;
3668 u64 size;
3669 uint32_t *actual_length=0;
3670
3671 if (argc != 4)
3672 return CMD_RET_USAGE;
3673
3674 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3675 size = simple_strtoull(argv[3], NULL, 16);
3676 ret = mmc_key_write(addr, size,actual_length);
3677 return ret;
3678}
3679
3680static cmd_tbl_t cmd_emmc[] = {
3681 U_BOOT_CMD_MKENT(dtb_read, 4, 0, do_emmc_dtb_read, "", ""),
3682 U_BOOT_CMD_MKENT(dtb_write, 4, 0, do_emmc_dtb_write, "", ""),
3683 U_BOOT_CMD_MKENT(erase, 3, 0, do_emmc_erase, "", ""),
3684 U_BOOT_CMD_MKENT(fastboot_read, 4, 0, do_emmc_fb_read, "", ""),
3685 U_BOOT_CMD_MKENT(fastboot_write, 4, 0, do_emmc_fb_write, "", ""),
3686 U_BOOT_CMD_MKENT(key_read, 4, 0, do_emmc_key_read, "", ""),
3687 U_BOOT_CMD_MKENT(key_write, 4, 0, do_emmc_key_write, "", ""),
3688};
3689
3690static int do_emmc_dtb_key(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3691{
3692 cmd_tbl_t *cp;
3693
3694 cp = find_cmd_tbl(argv[1], cmd_emmc, ARRAY_SIZE(cmd_emmc));
3695
3696 if (cp == NULL || argc > cp->maxargs)
3697 return CMD_RET_USAGE;
3698 if (flag == CMD_FLAG_REPEAT && !cp->cmd_rep)
3699 return CMD_RET_SUCCESS;
3700 return cp->cmd(cmdtp, flag, argc, argv);
3701}
3702
3703
3704U_BOOT_CMD(
3705 emmc, 4, 1, do_emmc_dtb_key,
3706 "EMMC sub system",
3707 "dtb_read addr size\n"
3708 "emmc dtb_write addr size\n"
3709 "emmc erase dtb\n"
3710 "emmc erase key\n"
3711 "emmc fastboot_read addr size\n"
3712 "emmc fastboot_write addr size\n"
3713 "emmc key_read addr size\n"
3714 "emmc key_write addr size\n"
3715);
3716