blob: d6f4aa513ed884da4878d7c196a89ddd06b32e3a [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 <amlogic/storage.h>
7#include <div64.h>
8#include <linux/math64.h>
9#include <amlogic/cpu_id.h>
10#include <amlogic/store_wrapper.h>
11#include <asm/amlogic/arch/register.h>
12#include <asm/amlogic/arch/bl31_apis.h>
13#include <amlogic/aml_efuse.h>
14#include <asm/amlogic/arch/cpu_config.h>
15#include <asm/amlogic/arch/romboot.h>
16#include <asm/amlogic/arch/secure_apb.h>
17#include <amlogic/blxx2bl33_param.h>
18#include <amlogic/aml_mtd.h>
19#include <mmc.h>
20
21#include <display_options.h>
22
Liang Yang51736e42024-10-09 19:03:13 +080023#define ALIGN_SIZE (4096)
24
Bo Lv72d0e902023-01-02 14:27:34 +000025#ifdef CONFIG_SPI_FLASH_MTD
26extern int spi_nor_pre(void);
27extern int spi_nor_probe(u32 init_flag);
28#endif
29
Bo Lv72d0e902023-01-02 14:27:34 +000030#ifdef CONFIG_MTD_SPI_NAND
31extern int spi_nand_pre(void);
32extern int spi_nand_probe(u32 init_flag);
33#endif
34
Bo Lv72d0e902023-01-02 14:27:34 +000035#ifdef CONFIG_MESON_NFC
36extern int nand_pre(void);
37extern int nand_probe(uint32_t init_flag);
38#endif
39
40#ifdef CONFIG_MMC_MESON_GX
41extern int emmc_pre(void);
42extern int emmc_probe(u32 init_flag);
43#endif
44
45#ifdef CONFIG_MMC_MESON_GX
46extern int sdcard_pre(void);
47extern int sdcard_probe(u32 init_flag);
48#endif
49/* for info protect, fixme later */
50int info_disprotect = 0;
51
52static struct storage_t *current;
53static struct device_node_t device_list[] = {
54#ifdef CONFIG_MESON_NFC
55 {BOOT_NAND_MTD, "mtd", nand_pre, nand_probe},
56#endif
Bo Lv72d0e902023-01-02 14:27:34 +000057#ifdef CONFIG_MTD_SPI_NAND
58 {BOOT_SNAND, "spi-nand", spi_nand_pre, spi_nand_probe},
59#endif
60#ifdef CONFIG_SPI_FLASH_MTD
61 {BOOT_SNOR, "spi-nor", spi_nor_pre, spi_nor_probe},
62#endif
63#if 0
64 {BOOT_SD, "sd", sdcard_pre, sdcard_probe},
65#endif
66
67#ifdef CONFIG_MMC_MESON_GX
68 {BOOT_EMMC, "emmc", emmc_pre, emmc_probe},
69#endif
70
71};
72
73int store_register(struct storage_t *store_dev)
74{
75 if (!store_dev)
76 return 1;
77 if (!current) {
78 INIT_LIST_HEAD(&store_dev->list);
79 current = store_dev;
80 return 0;
81 }
82 /**
83 * the head node will not be a valid node
84 * usually when we use the list, but in storage
85 * interface module, we init the device node as
86 * a head instead a global list_head pointer,
87 * it should be traver scaled.
88 */
89 if (store_dev == current)
90 return 0;
91 struct storage_t *dev;
92
93 if (store_dev->type == current->type)
94 return 1;
95 list_for_each_entry(dev, &current->list, list) {
96 if (dev == store_dev)
97 return 0;
98 else if (dev->type == store_dev->type)
99 return 1;
100 }
101 list_add_tail(&store_dev->list, &current->list);
102 current = store_dev;
103 return 0;
104}
105
106void store_unregister(struct storage_t *store_dev)
107{
108 if (store_dev == current) {
109 if (list_empty_careful(&store_dev->list)) {
110 current = NULL;
111 } else {
112 current = list_entry((current->list).next,
113 struct storage_t, list);
114 list_del_init(&store_dev->list);
115 }
116 } else {
117 list_del_init(&store_dev->list);
118 }
119}
120
Bo Lv72d0e902023-01-02 14:27:34 +0000121int store_init(u32 init_flag)
122{
123 int i, ret = 0;
124 u8 record = 0;
125
126 /*1. pre scan*/
127 for (i = 0; i < ARRAY_SIZE(device_list); i++) {
zhikui.cuib9512f12024-09-26 12:29:17 +0000128 if ((record & BOOT_NAND_MTD) &&
129 ((device_list[i].index & BOOT_SNAND) ||
130 (device_list[i].index & BOOT_SNOR)))
131 continue;
Bo Lv72d0e902023-01-02 14:27:34 +0000132 if (!device_list[i].pre()) {
zhikui.cuib9512f12024-09-26 12:29:17 +0000133 record |= device_list[i].index;
Bo Lv72d0e902023-01-02 14:27:34 +0000134 }
135 }
136
Bichao Zheng8951e442023-07-13 13:21:29 +0800137 pr_info("record = 0x%x\n", record);
138
Bo Lv72d0e902023-01-02 14:27:34 +0000139 if (!record) {
140 pr_info("No Valid storage device\n");
141 return record;
142 }
143
Bo Lv72d0e902023-01-02 14:27:34 +0000144 /*2. Enter the probe of the valid device*/
145 for (i = 0; i < ARRAY_SIZE(device_list); i++) {
zhikui.cuib9512f12024-09-26 12:29:17 +0000146 if (record & device_list[i].index) {
Bo Lv72d0e902023-01-02 14:27:34 +0000147 ret = device_list[i].probe(init_flag);
148 if (ret)
149 pr_info("the 0x%x storage device probe failed\n",
150 device_list[i].index);
151 }
152 }
153
154 return record;
155}
156
157static struct storage_t *store_get_current(void)
158{
159 return current;
160}
161
162int store_set_device(enum boot_type_e type)
163{
164 struct list_head *entry;
165 struct storage_t *dev, *store_dev = store_get_current();
166
167 if (!store_dev) {
168 pr_info("%s %d no current device\n", __func__, __LINE__);
169 return 1;
170 }
171 if (store_dev->type == type)
172 return 0;
173 list_for_each(entry, &store_dev->list) {
174 dev = list_entry(entry, struct storage_t, list);
175 if (dev->type == type) {
176 current = dev;
177 return 0;
178 }
179 }
180 pr_info("%s %d please confirm the %d device is valid\n",
181 __func__, __LINE__, type);
182 return 1;
183}
184
185enum boot_type_e store_get_type(void)
186{
187 struct storage_t *store = store_get_current();
188
189 if (!store) {
190 pr_info("%s %d please init storage device first\n",
191 __func__, __LINE__);
192 return BOOT_NONE;
193 }
194
195 return store->type;
196}
197
198int store_get_device_info(struct storage_info_t *info)
199{
200 struct storage_t *store = store_get_current();
201
202 if (!store) {
203 pr_info("%s %d please init storage device first\n",
204 __func__, __LINE__);
205 return 1;
206 }
207
208 memcpy((char *)info, (char *)&store->info,
209 sizeof(struct storage_info_t));
210 return 0;
211}
212
213int store_get_device_bootloader_mode(void)
214{
215 struct storage_t *store = store_get_current();
216
217 if (!store) {
218 pr_info("%s %d please init storage device first\n",
219 __func__, __LINE__);
220 return -1;
221 }
222 return store->info.mode;
223}
224
225int store_read(const char *name, loff_t off, size_t size, void *buf)
226{
227 struct storage_t *store = store_get_current();
228
229 if (!store) {
230 pr_info("%s %d please init storage device first\n",
231 __func__, __LINE__);
232 return 1;
233 }
234 return store->read(name, off, size, buf);
235}
236
237int store_write(const char *name, loff_t off, size_t size, void *buf)
238{
239 struct storage_t *store = store_get_current();
240
241 if (!store) {
242 pr_info("%s %d please init storage device first\n",
243 __func__, __LINE__);
244 return 1;
245 }
246 return store->write(name, off, size, buf);
247}
248
249int store_erase(const char *name, loff_t off, size_t size, int scrub)
250{
251 struct storage_t *store = store_get_current();
252
253 if (!store) {
254 pr_info("%s %d please init storage device first\n",
255 __func__, __LINE__);
256 return 1;
257 }
258 return store->erase(name, off, size, scrub);
259}
260
261u64 store_part_size(const char *name)
262{
263 struct storage_t *store = store_get_current();
264
265 if (!store) {
266 pr_info("%s %d please init storage device first\n",
267 __func__, __LINE__);
268 return 1;
269 }
270 return store->get_part_size(name);
271}
272
273u8 store_boot_copy_num(const char *name)
274{
275 struct storage_t *store = store_get_current();
276
277 if (!store) {
278 pr_info("%s %d please init storage device first\n",
279 __func__, __LINE__);
280 return 1;
281 }
282 return store->get_copies(name);
283}
284
Liang Yang51736e42024-10-09 19:03:13 +0800285u8 emmc_boot_seqs_tbl[8][2] = {
286 {0, 3}, {0, 2}, {0, 3}, {0, 1},
287 {1, 2}, {1, 1}, {2, 1}, {0, 0}
288 };
289
290static int _get_emmc_boot_seqs(void)
291{
292 u8 ebcfg = 0;
293
294 if (IS_FEAT_DIS_EMMC_USER())
295 ebcfg |= (1 << 2);
296 if (IS_FEAT_DIS_EMMC_BOOT_0())
297 ebcfg |= (1 << 1);
298 if (IS_FEAT_DIS_EMMC_BOOT_1())
299 ebcfg |= (1 << 0);
300
301 return ebcfg;
302}
303
304static int storage_get_emmc_boot_start(void)
305{
306 return emmc_boot_seqs_tbl[_get_emmc_boot_seqs()][0];
307}
Bo Lv72d0e902023-01-02 14:27:34 +0000308
309#ifndef SYSCTRL_SEC_STATUS_REG2
310static u32 fake_reg = 0;
311#define SYSCTRL_SEC_STATUS_REG2 (&fake_reg)
312#endif
313u8 store_boot_copy_start(void)
314{
315 struct storage_t *store = store_get_current();
316
317 if (!store) {
318 pr_info("%s %d please init storage device first\n",
319 __func__, __LINE__);
320 return 0;
321 }
322 if (store->type != BOOT_EMMC)
323 return 0;
324 /* new arch since sc2 */
325 if (BOOTLOADER_MODE_ADVANCE_INIT)
326 return storage_get_emmc_boot_start();
327 return 0;
328}
329
330u8 store_bootup_bootidx(const char *name)
331{
332 u8 bl2_idx = 0, fip_idx = 0;
333 u32 val = 0;
334
335 /* new arch since sc2 */
336 if (BOOTLOADER_MODE_ADVANCE_INIT) {
337 bl2_idx = readl(SYSCTRL_SEC_STATUS_REG2) & 0xF;
338 //TODO: fixme after robust devfip is finished.
339 fip_idx = bl2_idx;
340 } else {
341 /* according to the:
342 commit 975b4acbcfa686601999d56843471d98e9c0a2cd
343 storage: robust boot: record bootlog in SEC_AO_SEC_GP_CFG2 [1/2]
344 PD#SWPL-4850
345 ...
346 record the bootup bl2/fip into SEC_AO_SEC_GP_CFG2
347 bit[27-25] bl2
348 bit[24-22] fip
349 */
350 val = readl(SEC_AO_SEC_GP_CFG2);
351 bl2_idx = (val >> 25) & 0x7;
352 fip_idx = (val >> 22) & 0x7;
353 }
354 if (!strncmp(name, "bl2", sizeof("bl2")) ||
355 !strncmp(name, "spl", sizeof("spl")))
356 return bl2_idx;
357 else
358 return fip_idx;
359}
360
361void store_restore_bootidx(void)
362{
363 /* new arch since sc2 */
364 if (BOOTLOADER_MODE_ADVANCE_INIT) {
365 extern void aml_set_bootsequence(uint32_t val);
366 aml_set_bootsequence(0x55);
367 }
368 return;
369}
370
371u64 store_boot_copy_size(const char *name)
372{
373 struct storage_t *store = store_get_current();
374
Bo Lv72d0e902023-01-02 14:27:34 +0000375 return store->get_copy_size(name);
376}
377
zhikui.cui31f7eab2024-05-17 09:11:12 +0000378static int _store_boot_read(const char *part_name, u8 cpy, size_t size, void *addr)
379{
380 struct storage_t *store = store_get_current();
Liang Yang51736e42024-10-09 19:03:13 +0800381 size_t bl2_align_size = ALIGN(BL2_SIZE, ALIGN_SIZE);
382 u_char *buffer = (u_char *)addr;
383 int ret;
zhikui.cui31f7eab2024-05-17 09:11:12 +0000384
385 if (store_get_device_bootloader_mode() == COMPACT_BOOTLOADER)
Liang Yang51736e42024-10-09 19:03:13 +0800386 return store->boot_read(part_name, cpy, size, buffer);
zhikui.cui31f7eab2024-05-17 09:11:12 +0000387
Liang Yang51736e42024-10-09 19:03:13 +0800388 ret = store->boot_read(BOOT_BL2, cpy, BL2_SIZE, buffer);
389 if (ret)
390 return ret;
zhikui.cui31f7eab2024-05-17 09:11:12 +0000391
Liang Yang51736e42024-10-09 19:03:13 +0800392 return store->boot_read(BOOT_TPL, cpy,
393 size - bl2_align_size,
394 buffer + bl2_align_size);
zhikui.cui31f7eab2024-05-17 09:11:12 +0000395}
396
Bo Lv72d0e902023-01-02 14:27:34 +0000397int store_boot_read(const char *name, u8 copy, size_t size, void *buf)
398{
Liang Yang51736e42024-10-09 19:03:13 +0800399 return _store_boot_read(name, copy, size, buf);
Bo Lv72d0e902023-01-02 14:27:34 +0000400
zhikui.cui31f7eab2024-05-17 09:11:12 +0000401}
402
403static int _store_boot_write(const char *part_name, u8 cpy, size_t size, void *addr)
404{
zhikui.cui31f7eab2024-05-17 09:11:12 +0000405 struct storage_t *store = store_get_current();
Liang Yang51736e42024-10-09 19:03:13 +0800406 int ret = 0;
407 u_char *buffer = (u_char *)addr;
408 size_t bl2_align_size = ALIGN(BL2_SIZE, ALIGN_SIZE);
zhikui.cui31f7eab2024-05-17 09:11:12 +0000409
410 if (store_get_device_bootloader_mode() == COMPACT_BOOTLOADER)
Liang Yang51736e42024-10-09 19:03:13 +0800411 return store->boot_write(part_name, cpy, size, buffer);
zhikui.cui31f7eab2024-05-17 09:11:12 +0000412
Liang Yang51736e42024-10-09 19:03:13 +0800413 ret = store->boot_write("bl2", cpy, BL2_SIZE, buffer);
414 if (ret)
415 return ret;
zhikui.cui31f7eab2024-05-17 09:11:12 +0000416
Liang Yang51736e42024-10-09 19:03:13 +0800417 return store->boot_write("tpl", cpy,
418 size - bl2_align_size,
419 buffer + bl2_align_size);
zhikui.cui31f7eab2024-05-17 09:11:12 +0000420}
421
Bo Lv72d0e902023-01-02 14:27:34 +0000422int store_boot_write(const char *name, u8 copy, size_t size, void *buf)
423{
Liang Yang51736e42024-10-09 19:03:13 +0800424 return _store_boot_write(name, copy, size, buf);
Bo Lv72d0e902023-01-02 14:27:34 +0000425}
426
427int store_boot_erase(const char *name, u8 copy)
428{
429 struct storage_t *store = store_get_current();
430
Bo Lv72d0e902023-01-02 14:27:34 +0000431 return store->boot_erase(name, copy);
432}
433
434int store_gpt_read(void *buf)
435{
436 struct storage_t *store = store_get_current();
437
Bo Lv72d0e902023-01-02 14:27:34 +0000438 if (!store->gpt_read)
439 return 1;
Liang Yang51736e42024-10-09 19:03:13 +0800440
Bo Lv72d0e902023-01-02 14:27:34 +0000441 return store->gpt_read(buf);
442}
443
444int store_gpt_write(void *buf)
445{
446 struct storage_t *store = store_get_current();
447
Bo Lv72d0e902023-01-02 14:27:34 +0000448 if (!store->gpt_write)
449 return 1;
Liang Yang51736e42024-10-09 19:03:13 +0800450
Bo Lv72d0e902023-01-02 14:27:34 +0000451 return store->gpt_write(buf);
452}
453
454int store_gpt_erase(void)
455{
456 struct storage_t *store = store_get_current();
457
Bo Lv72d0e902023-01-02 14:27:34 +0000458 if (!store->gpt_erase)
459 return 1;
Liang Yang51736e42024-10-09 19:03:13 +0800460
Bo Lv72d0e902023-01-02 14:27:34 +0000461 return store->gpt_erase();
462}
463
jinbiaod6719f12023-12-22 05:34:45 +0000464int store_boot_copy_enable(int index)
465{
466 struct storage_t *store = store_get_current();
467
jinbiaod6719f12023-12-22 05:34:45 +0000468 if (!store->boot_copy_enable)
469 return -1;
Liang Yang51736e42024-10-09 19:03:13 +0800470
jinbiaod6719f12023-12-22 05:34:45 +0000471 return store->boot_copy_enable(index);
472}
473
Bo Lv72d0e902023-01-02 14:27:34 +0000474u32 store_rsv_size(const char *name)
475{
476 struct storage_t *store = store_get_current();
477
Bo Lv72d0e902023-01-02 14:27:34 +0000478 return store->get_rsv_size(name);
479}
480
481int store_rsv_read(const char *name, size_t size, void *buf)
482{
483 struct storage_t *store = store_get_current();
484
Bo Lv72d0e902023-01-02 14:27:34 +0000485 return store->read_rsv(name, size, buf);
486}
487
488int store_rsv_write(const char *name, size_t size, void *buf)
489{
490 struct storage_t *store = store_get_current();
491
Bo Lv72d0e902023-01-02 14:27:34 +0000492 return store->write_rsv(name, size, buf);
493}
494
495int store_rsv_erase(const char *name)
496{
497 struct storage_t *store = store_get_current();
498
Bo Lv72d0e902023-01-02 14:27:34 +0000499 return store->erase_rsv(name);
500}
501
502int store_rsv_protect(const char *name, bool ops)
503{
504 struct storage_t *store = store_get_current();
505
Bo Lv72d0e902023-01-02 14:27:34 +0000506 return store->protect_rsv(name, ops);
507}
508
509static int do_store_init(cmd_tbl_t *cmdtp,
510 int flag, int argc, char * const argv[])
511{
512 u32 init_flag = 1;
513 u8 ret = 0;
514
515 if (unlikely(argc != 2 && argc != 3))
516 return CMD_RET_USAGE;
517
518 if (argc == 3)
519 init_flag = simple_strtoul(argv[2], NULL, 10);
520
521 /*Returns a nonzero value: device index*/
522 if (store_init(init_flag))
523 ret = 0;
524 else ret = 1;
525 return ret;
526}
527
528void store_print_device(struct storage_t *store_dev)
529{
530 int i;
531
532 for (i = 0; i < ARRAY_SIZE(device_list); i++)
533 if (store_dev->type & device_list[i].index)
534 pr_info("device type: [%s]\n", device_list[i].type);
535 pr_info("name %s\n", store_dev->info.name);
536 pr_info("id :");
537 for (i = 0; i < ARRAY_SIZE(store_dev->info.id); i++)
538 pr_info(" 0x%x", store_dev->info.id[i]);
539 pr_info("\n");
540 pr_info("read unit %d\n", store_dev->info.read_unit);
541 pr_info("write unit %d\n", store_dev->info.write_unit);
542 pr_info("erase unit %d\n", store_dev->info.erase_unit);
543 pr_info("total size %lld\n", store_dev->info.caps);
544 if (store_dev->info.mode)
545 pr_info("bootloader in discrete mode : %d\n",
546 store_dev->info.mode);
547 else
548 pr_info("bootloader in compact mode : %d\n",
549 store_dev->info.mode);
550}
551
552static int do_store_device(cmd_tbl_t *cmdtp,
553 int flag, int argc, char * const argv[])
554{
555 if (argc == 2) {
556 struct storage_t *store_dev, *dev;
557 struct list_head *entry;
558
559 store_dev = store_get_current();
560 pr_info("current device:\n");
561 pr_info("----------------------------------\n");
562 store_print_device(store_dev);
563 pr_info("----------------------------------\n");
564 list_for_each(entry, &store_dev->list) {
565 dev = list_entry(entry, struct storage_t, list);
566 pr_info("valid device:\n");
567 pr_info("----------------------------------\n");
568 store_print_device(dev);
569 pr_info("----------------------------------\n");
570 }
571 return 0;
572 } else if (argc == 3) {
573 char *name = NULL;
574 int i = 0, ret = 0;
575 name = argv[2];
576 for (i = 0; i < ARRAY_SIZE(device_list); i++)
577 if (!strcmp(name, device_list[i].type)) {
578
579 ret = store_set_device(device_list[i].index);
580 if (!ret) {
581 pr_info("now current device is: %s\n",
582 name);
583 return 0;
584 }
585 }
586 pr_info("%s %d no such device: %s\n",
587 __func__, __LINE__, name);
588 return ret;
589 }
590 return CMD_RET_USAGE;
591}
592
593static int do_store_partition(cmd_tbl_t *cmdtp,
594 int flag, int argc, char * const argv[])
595{
596 struct storage_t *store_dev;
597 int i = 0, partitions = 0;
598 int ret = 0;
599 char name[16];
600
601 if (argc > 2)
602 return CMD_RET_USAGE;
603 else {
604 store_dev = store_get_current();
605 if (store_dev->get_part_count)
606 partitions = store_dev->get_part_count();
Bichao Zheng08cfb892024-08-27 08:38:08 +0800607 pr_err("%d partitions of device %s:\n",
608 partitions, store_dev->info.name);
Bo Lv72d0e902023-01-02 14:27:34 +0000609
610 if (store_dev->list_part_name)
611 ret = store_dev->list_part_name(i, name);
612
613 return ret;
614 }
615}
616
617#ifdef CONFIG_AML_MTD
618extern int is_mtd_store_boot_area(const char *part_name);
619#endif
620static int do_store_erase(cmd_tbl_t *cmdtp,
621 int flag, int argc, char * const argv[])
622{
623 struct storage_t *store = store_get_current();
624 unsigned long offset;
625 size_t size = 0;
626 char *name = NULL;
627 char *s;
628 int erase_flag = 0, ret;
629 unsigned long time;
630
631 const char *scrub =
632 "Warning: scrub_flag is 1!!!!"
633 "scrub operation!!!\n"
634 "will erase oob area\n"
635 "There is no reliable way to recover them.\n"
636 " "
637 "are sure of what you are doing!\n"
638 "\nReally erase this NAND flash? <y/N>\n";
639
640 if (!store) {
641 pr_info("%s %d please init your storage device first!\n",
642 __func__, __LINE__);
643 return CMD_RET_FAILURE;
644 }
645
646 if (!strncmp(argv[1], "scrub", 5)) {
647 erase_flag |= STORE_SCRUB;
648 puts(scrub);
649 if (!confirm_yesno()) {
650 printf("erase aborted\n");
651 return 1;
652 }
653 }
654
655 /*store erase.chip*/
656 s = strchr(argv[1], '.');
657 if (s != NULL && strcmp(s, ".chip") == 0) {
658 if (argc == 3 && !simple_strtoul(argv[argc - 1], NULL, 16))
659 erase_flag |= STORE_ERASE_DATA;
660 else if ((argc == 3) && (simple_strtoul(argv[argc - 1], NULL, 16) == 1))
661 erase_flag |= STORE_ERASE_RSV;
662 else if (argc == 3)
663 return CMD_RET_USAGE;
664
665 offset = 0;
666 } else {
667 /*store erase normal, partition name can't NULL*/
668 if (unlikely(argc != 5))
669 return CMD_RET_USAGE;
670
671 size = (size_t)simple_strtoul(argv[argc - 1], NULL, 16);
672 offset = simple_strtoul(argv[argc - 2], NULL, 16);
673 name = argv[2];
674#ifdef CONFIG_AML_MTD
675 if (is_mtd_store_boot_area(name)) {
676 pr_info("%s %d please enter normal partition name except tpl area!\n",
677 __func__, __LINE__);
678 return CMD_RET_FAILURE;
679 }
680#endif
681 }
682
683 time = get_timer(0);
684 ret = store->erase(name, offset, size, erase_flag);
685 time = get_timer(time);
686
687 if (size != 0)
688 printf("%lu bytes ", size);
689
690 printf("erased in %lu ms", time);
691 if ((time > 0) && (size != 0)) {
692 puts(" (");
693 print_size(div_u64(size, time) * 1000, "/s");
694 puts(")");
695 }
696 puts("\n");
697
698 return ret;
699}
700
701static int do_store_read(cmd_tbl_t *cmdtp,
702 int flag, int argc, char * const argv[])
703{
704 struct storage_t *store = store_get_current();
705 unsigned long offset, addr, time;
706 size_t size;
707 char *name = NULL;
708 int ret;
709
710 if (!store) {
711 pr_info("%s %d please init your storage device first!\n",
712 __func__, __LINE__);
713 return CMD_RET_FAILURE;
714 }
715
716 if (unlikely(argc != 5 && argc != 6))
717 return CMD_RET_USAGE;
718
719 addr = simple_strtoul(argv[2], NULL, 16);
720 size = (size_t)simple_strtoul(argv[argc - 1], NULL, 16);
721 offset = simple_strtoul(argv[argc - 2], NULL, 16);
722 if (argc == 6)
723 name = argv[3];
724#ifdef CONFIG_AML_MTD
725 if (is_mtd_store_boot_area(name)) {
726 pr_info("%s %d please enter normal partition name except tpl area!\n",
727 __func__, __LINE__);
728 return CMD_RET_FAILURE;
729 }
730#endif
731 time = get_timer(0);
732 ret = store->read(name, offset, size, (u_char *)addr);
733 time = get_timer(time);
734
735 if (size != 0)
jinbiaodca5d7c2024-11-05 19:08:30 +0800736 printf("%lu %s ", size, (argc == 6) ? "bytes" : "blocks");
Bo Lv72d0e902023-01-02 14:27:34 +0000737
jinbiaodca5d7c2024-11-05 19:08:30 +0800738 printf("read in %lu ms", time);
Bo Lv72d0e902023-01-02 14:27:34 +0000739 if ((time > 0) && (size != 0)) {
740 puts(" (");
741 print_size(div_u64(size, time) * 1000, "/s");
742 puts(")");
743 }
744 puts("\n");
745
746 return ret;
747}
748
Bo Lv72d0e902023-01-02 14:27:34 +0000749static int do_store_write(cmd_tbl_t *cmdtp,
750 int flag, int argc, char * const argv[])
751{
752 struct storage_t *store = store_get_current();
753 unsigned long offset, addr, time;
754 size_t size;
755 char *name = NULL;
756 int ret;
757
758 if (!store) {
759 pr_info("%s %d please init your storage device first!\n",
760 __func__, __LINE__);
761 return CMD_RET_FAILURE;
762 }
763
764 if (unlikely(argc != 5 && argc != 6))
765 return CMD_RET_USAGE;
766
767 addr = simple_strtoul(argv[2], NULL, 16);
768 offset = simple_strtoul(argv[argc - 2], NULL, 16);
769 size = (size_t)simple_strtoul(argv[argc - 1], NULL, 16);
770 if (argc == 6)
771 name = argv[3];
772#ifdef CONFIG_AML_MTD
773 if (is_mtd_store_boot_area(name)) {
774 pr_info("%s %d please enter normal partition name except tpl area!\n",
775 __func__, __LINE__);
776 return CMD_RET_FAILURE;
777 }
778#endif
779 time = get_timer(0);
780 ret = store->write(name, offset, size, (u_char *)addr);
781 time = get_timer(time);
782
783 if (size != 0)
jinbiaodca5d7c2024-11-05 19:08:30 +0800784 printf("%lu %s ", size, (argc == 6) ? "bytes" : "blocks");
Bo Lv72d0e902023-01-02 14:27:34 +0000785
786 printf("write in %lu ms", time);
787 if ((time > 0) && (size != 0)) {
788 puts(" (");
789 print_size(div_u64(size, time) * 1000, "/s");
790 puts(")");
791 }
792 puts("\n");
793
794 return ret;
795}
796
797static int do_store_boot_read(cmd_tbl_t *cmdtp,
798 int flag, int argc, char * const argv[])
799{
800 struct storage_t *store = store_get_current();
801 unsigned long addr;
802 size_t size;
803 u8 cpy;
804 char *name;
805
806 if (!store) {
807 pr_info("%s %d please init your storage device first!\n",
808 __func__, __LINE__);
809 return CMD_RET_FAILURE;
810 }
811
812 if (unlikely(argc != 6))
813 return CMD_RET_USAGE;
814
815 name = argv[2];
816 addr = (unsigned long)simple_strtoul(argv[3], NULL, 16);
817 cpy = (u8)simple_strtoul(argv[4], NULL, 16);
818 size = (size_t)simple_strtoul(argv[5], NULL, 16);
819
820 return store->boot_read(name, cpy, size, (u_char *)addr);
821}
822
Bo Lv72d0e902023-01-02 14:27:34 +0000823static int do_store_boot_write(cmd_tbl_t *cmdtp,
824 int flag, int argc, char * const argv[])
825{
826 struct storage_t *store = store_get_current();
827 unsigned long addr;
828 size_t size;
829 u8 cpy = BOOT_OPS_ALL;
830 char *name;
831
832 if (!store) {
833 pr_info("%s %d please init your storage device first!\n",
834 __func__, __LINE__);
835 return CMD_RET_FAILURE;
836 }
837
838 if (unlikely(argc != 5 && argc != 6))
839 return CMD_RET_USAGE;
840
841 name = argv[2];
842 addr = (unsigned long)simple_strtoul(argv[3], NULL, 16);
843 size = (size_t)simple_strtoul(argv[argc - 1], NULL, 16);
844 if (argc == 6)
845 cpy = (u8)simple_strtoul(argv[4], NULL, 16);
846
847 if (strcmp(name, "bootloader") == 0) {
848 return _store_boot_write(name, cpy, size, (u_char *)addr);
849 }
850
851 return store->boot_write(name, cpy, size, (u_char *)addr);
852}
853
854static int do_store_boot_erase(cmd_tbl_t *cmdtp,
855 int flag, int argc, char * const argv[])
856{
857 struct storage_t *store = store_get_current();
858 u8 cpy = BOOT_OPS_ALL;
859 char *name;
860
861 if (!store) {
862 pr_info("%s %d please init your storage device first!\n",
863 __func__, __LINE__);
864 return CMD_RET_FAILURE;
865 }
866
867 if (unlikely(argc != 3 && argc != 4))
868 return CMD_RET_USAGE;
869
870 name = argv[2];
871 if (argc == 4)
872 cpy = (u8)simple_strtoul(argv[3], NULL, 16);
873
874 return store->boot_erase(name, cpy);
875}
876
877static int do_store_gpt_read(cmd_tbl_t *cmdtp,
878 int flag, int argc, char * const argv[])
879{
880 struct storage_t *store = store_get_current();
881 unsigned long addr;
882 int ret;
883
884 if (!store) {
885 pr_info("%s %d please init your storage device first!\n",
886 __func__, __LINE__);
887 return CMD_RET_FAILURE;
888 }
889
890 if (unlikely(argc != 3))
891 return CMD_RET_USAGE;
892
893 addr = simple_strtoul(argv[2], NULL, 16);
894
895 if (store->gpt_read) {
896 ret = store->gpt_read((u_char *)addr);
897 return ret;
898 }
899
900 printf("read gpt is not prepared\n");
901 return CMD_RET_USAGE;
902}
903
904static int do_store_gpt_write(cmd_tbl_t *cmdtp,
905 int flag, int argc, char * const argv[])
906{
907 struct storage_t *store = store_get_current();
908 unsigned long addr;
909 int ret;
910
911 if (!store) {
912 pr_info("%s %d please init your storage device first!\n",
913 __func__, __LINE__);
914 return CMD_RET_FAILURE;
915 }
916
917 if (unlikely(argc != 3))
918 return CMD_RET_USAGE;
919
920 addr = simple_strtoul(argv[2], NULL, 16);
921
922 if (store->gpt_write) {
923 ret = store->gpt_write((u_char *)addr);
924 return ret;
925 }
926
927 printf("write gpt is not prepared\n");
928 return CMD_RET_USAGE;
929}
930
931static int do_store_gpt_erase(cmd_tbl_t *cmdtp,
932 int flag, int argc, char * const argv[])
933{
934 struct storage_t *store = store_get_current();
935 int ret;
936
937 if (!store) {
938 pr_info("%s %d please init your storage device first!\n",
939 __func__, __LINE__);
940 return CMD_RET_FAILURE;
941 }
942
943 if (unlikely(argc != 2))
944 return CMD_RET_USAGE;
945
946 if (store->gpt_erase) {
947 ret = store->gpt_erase();
948 return ret;
949 }
950
951 printf("erase gpt is not prepared\n");
952 return CMD_RET_USAGE;
953}
954
jinbiaod6719f12023-12-22 05:34:45 +0000955/*
956 * Check whether the current boot can be written
957 * ret: 0 disable; 1: enable
958 */
959static int do_store_boot_copy_enable(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
960{
961 enum boot_type_e medium_type = store_get_type();
962 struct storage_t *store = store_get_current();
jinbiao325839f2024-03-29 09:34:08 +0000963 int ret = CMD_RET_USAGE, index;
jinbiaod6719f12023-12-22 05:34:45 +0000964
965 if (!store) {
966 pr_info("%s %d please init your storage device first!\n",
967 __func__, __LINE__);
jinbiao325839f2024-03-29 09:34:08 +0000968 return ret;
jinbiaod6719f12023-12-22 05:34:45 +0000969 }
970
971 if (unlikely(argc != 3))
jinbiao325839f2024-03-29 09:34:08 +0000972 return ret;
jinbiaod6719f12023-12-22 05:34:45 +0000973
974 if (medium_type != BOOT_EMMC) {
975 printf("%s %d not eMMC boot\n", __func__, __LINE__);
jinbiao325839f2024-03-29 09:34:08 +0000976 return ret;
jinbiaod6719f12023-12-22 05:34:45 +0000977 }
978
979 index = simple_strtoul(argv[2], NULL, 16);
980 if (store->boot_copy_enable) {
981 ret = store->boot_copy_enable(index);
jinbiao325839f2024-03-29 09:34:08 +0000982 printf("%s\n", ret ? "enable" : "disable");
983 } else
984 printf("boot copy enable is not prepared\n");
jinbiaod6719f12023-12-22 05:34:45 +0000985
jinbiao325839f2024-03-29 09:34:08 +0000986 return ret;
jinbiaod6719f12023-12-22 05:34:45 +0000987}
988
Bo Lv72d0e902023-01-02 14:27:34 +0000989static int do_store_rsv_ops(cmd_tbl_t *cmdtp,
990 int flag, int argc, char * const argv[])
991{
992 struct storage_t *store = store_get_current();
993 char *name = NULL;
994
995 if (!store) {
996 pr_info("%s %d please init your storage device first!\n",
997 __func__, __LINE__);
998 return CMD_RET_FAILURE;
999 }
1000
1001 if (!strcmp(argv[2], "erase")) {
1002 if (argc == 3)
1003 ;
1004 else if (argc == 4)
1005 name = argv[3];
1006 else
1007 return CMD_RET_USAGE;
1008 return store->erase_rsv(name);
1009 } else if (!strcmp(argv[2], "read") ||
1010 !strcmp(argv[2], "write")) {
1011 u8 cmd = strcmp(argv[2], "read") ? 0 : 1;
1012 unsigned long addr = simple_strtoul(argv[4], NULL, 16);
1013 size_t size = (size_t)simple_strtoul(argv[5], NULL, 16);
1014
1015 name = argv[3];
1016 if (unlikely(argc != 6))
1017 return CMD_RET_USAGE;
1018 if (cmd)
1019 return store->read_rsv(name, size, (u_char *)addr);
1020 else
1021 return store->write_rsv(name, size, (u_char *)addr);
1022 } else if (!strcmp(argv[2], "protect")) {
1023 char *ops;
1024 flag = false;
1025
1026 if (unlikely(argc != 4 && argc != 5))
1027 return CMD_RET_USAGE;
1028
1029 name = (argc == 4) ? NULL : argv[3];
1030 ops = argv[argc - 1];
1031 if (!strcmp(ops, "on"))
1032 flag = true;
1033 else if (!strcmp(ops, "off"))
1034 flag = false;
1035 return store->protect_rsv(name, flag);
1036 }
1037 return CMD_RET_USAGE;
1038}
1039
1040static int do_store_param_ops(cmd_tbl_t *cmdtp,
1041 int flag, int argc, char * const argv[])
1042{
Bichao Zheng5ced7b52023-07-25 15:20:20 +08001043 struct storage_t *store = store_get_current();
Bo Lv72d0e902023-01-02 14:27:34 +00001044
Bichao Zheng050532c2024-01-09 10:24:31 +08001045 if (!store) {
1046 pr_info("%s %d please init your storage device first!\n",
1047 __func__, __LINE__);
1048 return CMD_RET_FAILURE;
1049 }
1050
Bichao Zheng5ced7b52023-07-25 15:20:20 +08001051 if (store->param_ops)
1052 return store->param_ops();
Bo Lv72d0e902023-01-02 14:27:34 +00001053
1054 return 0;
1055}
1056
jinbiao1c8ee412024-12-16 16:42:58 +08001057static int do_store_ffu_op(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1058{
1059 struct storage_t *store = store_get_current();
1060 u64 ver, cnt;
1061 int ret = CMD_RET_FAILURE;
1062 void *addr;
1063
1064 if (argc != 4)
1065 return CMD_RET_USAGE;
1066
1067 ver = simple_strtoul(argv[1], NULL, 16);
1068 addr = (void *)simple_strtoul(argv[2], NULL, 16);
1069 cnt = simple_strtoul(argv[3], NULL, 16);
1070
1071 if (store->ffu_op)
1072 ret = store->ffu_op(ver, addr, cnt);
1073
1074 return (ret == 0) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
1075}
1076
Bo Lv72d0e902023-01-02 14:27:34 +00001077static cmd_tbl_t cmd_store_sub[] = {
1078 U_BOOT_CMD_MKENT(init, 4, 0, do_store_init, "", ""),
1079 U_BOOT_CMD_MKENT(device, 4, 0, do_store_device, "", ""),
1080 U_BOOT_CMD_MKENT(partition, 3, 0, do_store_partition, "", ""),
1081 U_BOOT_CMD_MKENT(scrub, 5, 0, do_store_erase, "", ""),
1082 U_BOOT_CMD_MKENT(erase, 5, 0, do_store_erase, "", ""),
1083 U_BOOT_CMD_MKENT(read, 6, 0, do_store_read, "", ""),
1084 U_BOOT_CMD_MKENT(write, 7, 0, do_store_write, "", ""),
1085 U_BOOT_CMD_MKENT(write_gpt, 3, 0, do_store_gpt_write, "", ""),
1086 U_BOOT_CMD_MKENT(read_gpt, 3, 0, do_store_gpt_read, "", ""),
1087 U_BOOT_CMD_MKENT(erase_gpt, 2, 0, do_store_gpt_erase, "", ""),
Bo Lv72d0e902023-01-02 14:27:34 +00001088 U_BOOT_CMD_MKENT(boot_read, 6, 0, do_store_boot_read, "", ""),
1089 U_BOOT_CMD_MKENT(boot_write, 6, 0, do_store_boot_write, "", ""),
1090 U_BOOT_CMD_MKENT(boot_erase, 4, 0, do_store_boot_erase, "", ""),
1091 U_BOOT_CMD_MKENT(rsv, 6, 0, do_store_rsv_ops, "", ""),
1092 U_BOOT_CMD_MKENT(param, 2, 0, do_store_param_ops, "", ""),
jinbiaod6719f12023-12-22 05:34:45 +00001093 U_BOOT_CMD_MKENT(boot_copy_enable, 3, 0, do_store_boot_copy_enable, "", ""),
jinbiao1c8ee412024-12-16 16:42:58 +08001094 U_BOOT_CMD_MKENT(ffu_op, 4, 0, do_store_ffu_op, "", ""),
Bo Lv72d0e902023-01-02 14:27:34 +00001095};
1096
1097static int do_store(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1098{
1099 cmd_tbl_t *c;
1100
1101 if (argc < 2)
1102 return CMD_RET_USAGE;
1103
1104 c = find_cmd_tbl(argv[1], cmd_store_sub, ARRAY_SIZE(cmd_store_sub));
1105 if (c)
1106 return c->cmd(cmdtp, flag, argc, argv);
1107
1108 return CMD_RET_USAGE;
1109}
1110
1111U_BOOT_CMD(store, CONFIG_SYS_MAXARGS, 1, do_store,
1112 "STORE sub-system:",
1113 "store init [flag]\n"
1114 " init storage device\n"
1115 "store device [name]\n"
1116 " show or set storage device\n"
1117 " 'store device' command will list\n"
1118 " all valid storage device and print.\n"
1119 " 'store device [name]' will set the\n"
1120 " [name] device to the current device\n"
1121 "store partition\n"
1122 " show partitions of current device\n"
1123 "store read addr [partition name] off size\n"
1124 " read 'size' bytes from offset 'off'\n"
1125 " of device/partition 'partition name' to.\n"
1126 " address 'addr' of memory.\n"
1127 " if partition name not value. read start with\n"
1128 " offset in normal logic area,if tpl area exist\n"
1129 " read offset at end of tpl area\n"
1130 "store write addr [partition name] off size\n"
1131 " write 'size' bytes to offset 'off' of\n"
1132 " device/partition [partition name] from\n"
1133 " address 'addr' of memory.\n"
1134 " if partition name not value. write start with\n"
1135 " offset in normal logic area,if tpl area exist\n"
1136 " write offset at end of tpl area\n"
1137 "store write_gpt addr\n"
1138 " write gpt from address 'addr'\n"
1139 "store read_gpt addr\n"
1140 " read gpt to address 'addr'\n"
1141 "store erase_gpt\n"
1142 " erase primary and secondary gpt\n"
1143 "store erase partition name off size.\n"
1144 " erase 'size' bytes from offset 'off'\n"
1145 " of device/partition [partition name]\n"
1146 " partition name must't NULL\n"
1147 "store scrub partition name off size.\n"
1148 " erase 'size' bytes from offset 'off'\n"
1149 " of device/partition [partition name]\n"
1150 " includes oob area if the device has.\n"
1151 " partition name must't NULL\n"
1152 "store erase.chip [flag]\n"
1153 " erase all nand chip,except bad block\n"
1154 " flag 0 erase all nand chip,except bootloader&rsv\n"
1155 " flag 1 erase rsv\n"
1156 "store scrub.chip\n"
1157 " erase all nand chip,include bad block\n"
1158 "store boot_read name addr copy size\n"
1159 " read 'size' bytes from 'copy'th backup\n"
1160 " in name partition, 'copy' can't be null.\n"
1161 " name:\n"
1162 " in discrete mode: 'bl2'/'tpl'(fip)\n"
1163 " in compact mode: 'bootloader'\n"
1164 "store boot_write name addr [copy] size\n"
1165 " write 'size' bytes to 'copy'th backup\n"
1166 " in [name] partition from address\n"
1167 " 'addr' of memory. when the optional 'copy'\n"
1168 " is null, it will writes to all copies\n"
1169 " name:\n"
1170 " in discrete mode:\n"
1171 " 'bl2/bl2e/bl2x/ddrfip/tpl(fip), only update part\n"
1172 " 'bootloader', update whole uboot.bin, in this case\n"
1173 " @copy:if used, must < min(tplCpyNum, Bl2CpyNum), update only the specified copy\n"
1174 " if not used, update all the copies of bl2 bl2e bl2x ddrfip tpl!\n"
1175 " in compact mode: 'bootloader'\n"
1176 "store boot_erase name [copy]\n"
1177 " erase the name info from 'copy'th backup\n"
1178 " when the optional 'copy' not value, it\n"
1179 " will erase all copies.\n"
1180 " name:\n"
1181 " in discrete mode: \n"
1182 " 'bl2'/'tpl'(fip): erase bl2/tpl partition\n"
1183 " 'bootloader':erase bl2 + tpl partition\n"
1184 " in compact mode: 'bootloader'\n"
1185 "store rsv read name addr size\n"
1186 " read 'size' bytes 'name' rsv info\n"
1187 " to address 'addr' of memory\n"
1188 " 'name' could be key/dtb/env etc...\n"
1189 "store rsv write name addr size\n"
1190 " write 'size' bytes 'name' rsv info\n"
1191 " from address 'addr' of memory\n"
1192 "store rsv erase name\n"
1193 " erase 'name' rsv info\n"
1194 " name must't null\n"
1195 "store rsv protect name on/off\n"
1196 " turn on/off the rsv info protection\n"
1197 " name must't null\n"
1198 "store param\n"
jinbiaod6719f12023-12-22 05:34:45 +00001199 " transfer bl2e/x ddrfip devfip size to kernel in such case like sc2\n"
1200 "store boot_copy_enable [boot_index]\n"
jinbiao1c8ee412024-12-16 16:42:58 +08001201 " check bootloader_x whether enable\n"
1202 "store ffu [version] [addr] [cnt]\n"
1203 " update ffu fw\n"
Bo Lv72d0e902023-01-02 14:27:34 +00001204);