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