blob: c07f6d301e50f2296e710ce661a430a0b054bee7 [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 <amlogic/storage.h>
8#include <linux/mtd/mtd.h>
9#include <asm/amlogic/arch/cpu_config.h>
10#include <amlogic/store_wrapper.h>
11#include <u-boot/sha256.h>
12
13#define debugP(fmt...) //printf("Dbg[WRP]L%d:", __LINE__),printf(fmt)
14#define errorP(fmt...) printf("Err[WRP]L%d:", __LINE__),printf(fmt)
15#define wrnP(fmt...) printf("wrn:"fmt)
16#define MsgP(fmt...) printf("[WRP]"fmt)
17
18//change part logic offset to physical address for mtd, not changed if not MTD
19static int mtd_find_phy_off_by_lgc_off(const char* partName, const loff_t logicAddr, loff_t* phyAddr)
20{
21 if (!(BOOT_NAND_MTD == store_get_type() || BOOT_SNAND == store_get_type())) {
22 *phyAddr = logicAddr;
23 return 0;
24 }
25#ifndef CONFIG_CMD_MTD
26 MsgP("Exception, boottype is MTD or snand, BUT CMD_MTD not defined\n");
27#else
28 struct mtd_info * mtdPartInf = NULL;
29 mtdPartInf = get_mtd_device_nm(partName);
30 if (!mtdPartInf) {
31 errorP("device(%s) is null\n", partName);
32 return CMD_RET_FAILURE;
33 }
34
35 if (IS_ERR(mtdPartInf)) {
36 errorP("device(%s) is err\n", partName);
37 return CMD_RET_FAILURE;
38 }
39
40 const unsigned eraseSz = mtdPartInf->erasesize;
41 const unsigned offsetInBlk = logicAddr & (eraseSz - 1);
42 loff_t off = 0;
43 int canSpeedUp = 0;
44 static struct {
45 loff_t lastblkPhyOff;
46 loff_t lastblkLgcOff;
47 char partName[64];
48 }_map4SpeedUp = {0};
49 if ( !strcmp(partName, _map4SpeedUp.partName) && logicAddr >= _map4SpeedUp.lastblkLgcOff) {
50 canSpeedUp = 1;
51 } else {
52 _map4SpeedUp.lastblkLgcOff = _map4SpeedUp.lastblkPhyOff = 0;
53 strncpy(_map4SpeedUp.partName, partName, 63);
54 }
55
56 if ( canSpeedUp ) {
57 if ( logicAddr >= _map4SpeedUp.lastblkLgcOff &&
58 logicAddr < _map4SpeedUp.lastblkLgcOff + eraseSz) {
59 *phyAddr = _map4SpeedUp.lastblkPhyOff + offsetInBlk;
60 return 0;
61 }
62 _map4SpeedUp.lastblkPhyOff += eraseSz;
63 _map4SpeedUp.lastblkLgcOff += eraseSz;
64 off = _map4SpeedUp.lastblkPhyOff;
65 }
66 for (; off < mtdPartInf->size; off += eraseSz, _map4SpeedUp.lastblkPhyOff += eraseSz) {
67 if (mtd_block_isbad(mtdPartInf, off)) {
68 MsgP("bad blk at %08llx\n", (unsigned long long)off);
69 } else {
70 if ( logicAddr >= _map4SpeedUp.lastblkLgcOff &&
71 logicAddr < _map4SpeedUp.lastblkLgcOff + eraseSz) {
72 *phyAddr = _map4SpeedUp.lastblkPhyOff + offsetInBlk;
73 return 0;
74 }
75 _map4SpeedUp.lastblkLgcOff += eraseSz;
76 }
77 }
78#endif// #ifndef CONFIG_CMD_MTD
79 return __LINE__;
80}
81
82int store_logic_write(const char *name, loff_t off, size_t size, void *buf)
83{
84 loff_t phyAddr = 0;
85 if (mtd_find_phy_off_by_lgc_off(name, off, &phyAddr)) {
86 errorP("Fail find phy addr\n");
87 return -__LINE__;
88 }
89 return store_write(name, phyAddr, size, buf);
90}
91
92int store_logic_read(const char *name, loff_t off, size_t size, void *buf)
93{
94 loff_t phyAddr = 0;
95 if (mtd_find_phy_off_by_lgc_off(name, off, &phyAddr)) {
96 errorP("Fail find phy addr\n");
97 return -__LINE__;
98 }
99 return store_read(name, phyAddr, size, buf);
100}
101
102//get partition logic size
103u64 store_logic_cap(const char* partName)
104{
105 if (!(BOOT_NAND_MTD == store_get_type() || BOOT_SNAND == store_get_type())) {
106 return store_part_size(partName);
107 }
108
109#ifndef CONFIG_CMD_MTD
110 MsgP("Exception, boottype is MTD or snand, BUT CMD_MTD not defined\n");
111 return 0;
112#else
113 //get mtd part logic size (i.e, not including the bad blocks)
114 struct mtd_info * mtdPartInf = NULL;
115 uint64_t partSzLgc = 0;
116 loff_t off = 0;
117
118 mtdPartInf = get_mtd_device_nm(partName);
119 if (IS_ERR(mtdPartInf)) {
120 errorP("device(%s) is err\n", partName);
121 return CMD_RET_FAILURE;
122 }
123 const unsigned eraseSz = mtdPartInf->erasesize;
124 const uint64_t partSzPhy = mtdPartInf->size;
125
126 partSzLgc = partSzPhy;
127 for (; off < partSzPhy; off += eraseSz) {
128 if (mtd_block_isbad(mtdPartInf, off)) {
129 partSzLgc -= eraseSz;
130 }
131 }
132 return partSzLgc;
133#endif// #ifndef CONFIG_CMD_MTD
134}
135
136int store_gpt_ops(size_t sz, void *buf, int is_wr)
137{
138 int ret = 0;
139
140 if (!sz || sz >= 0x100000) {
141 errorP("sz 0x%zx to large\n", sz);
142 return -__LINE__;
143 }
144
145 if (is_wr)
146 ret = store_gpt_write(buf);
147 else
148 ret = store_gpt_read(buf);
149
150 return ret;
151}
152
153#ifndef CONFIG_AML_V3_FACTORY_BURN//storage wrapper
154#define FB_ERR(fmt ...) printf("[ERR]%s:L%d:", __func__, __LINE__), printf(fmt)
155#define FB_EXIT(fmt ...) do { FB_ERR(fmt); return -__LINE__; } while (0)
156#define FB_MSG(fmt ...) printf("[MSG]" fmt)
157#define FBS_EXIT(buf, fmt ...) do { FBS_ERR(buf, fmt); return -__LINE__; } while (0)
158
159int bootloader_copy_sz(void)
160{
161 return store_boot_copy_size("bootloader");
162}
163
164static int _bootloader_write(u8 *dataBuf, unsigned off, unsigned binSz, const char *bootName)
165{
166 int iCopy = 0;
167 const int bootCpyNum = store_boot_copy_num(bootName);
168 const int bootCpySz = (int)store_boot_copy_size(bootName);
169
170 FB_MSG("[%s] CpyNum %d, bootCpySz 0x%x\n", bootName, bootCpyNum, bootCpySz);
171 if (binSz + off > bootCpySz)
172 FB_EXIT("bootloader sz(0x%x) + off(0x%x) > bootCpySz 0x%x\n",
173 binSz, off, bootCpySz);
174
175 if (off) {
176 FB_ERR("current only 0 supported!\n");
177 return -__LINE__;
178 }
179
180 for (; iCopy < bootCpyNum; ++iCopy) {
181 int ret = store_boot_write(bootName, iCopy, binSz, dataBuf);
182
183 if (ret)
184 FB_EXIT("FAil in program[%s] at copy[%d]\n", bootName, iCopy);
185 }
186
187 return 0;
188}
189
190int bootloader_write(u8 *dataBuf, unsigned off, unsigned binSz)
191{
192 return _bootloader_write(dataBuf, off, binSz, "bootloader");
193}
194
195static int _bootloader_read(u8 *pBuf, unsigned off, unsigned binSz, const char *bootName)
196{
197 int iCopy = 0;
198 const int bootCpyNum = store_boot_copy_num(bootName);
199 const int bootCpySz = (int)store_boot_copy_size(bootName);
200 int validCpyNum = bootCpyNum;//at least valid cpy num
201 int actVldCpyNum = 0;//actual valid copy num
202
203 if (binSz + off > bootCpySz) {
204 FB_ERR("bootloader sz(0x%x) + off(0x%x) > bootCpySz 0x%x\n", binSz, off, bootCpySz);
205 return -__LINE__;
206 }
207 if (off)
208 FB_EXIT("current only 0 supported!\n");
209
210 for (iCopy = 0; iCopy < bootCpyNum; ++iCopy) {
211 void *dataBuf = iCopy ? pBuf + binSz : pBuf;
212 int ret = store_boot_read(bootName, iCopy, binSz, dataBuf);
213
214 if (ret) {
215 FB_ERR("Fail to read boot[%s] at copy[%d]\n", bootName, iCopy);
216 continue;
217 }
218 if (iCopy) {
219 if (!actVldCpyNum) {//NO valid cpy yet, so copy0 NOT valid also
220 memcpy(pBuf, dataBuf, binSz);
221 }
222 if (memcmp(pBuf, dataBuf, binSz)) {
223 FB_ERR("[%s] copy[%d] content NOT the same as copy[0]\n",
224 bootName, iCopy);//maybe ddr err as nand not err
225 memset(pBuf, 0, binSz);
226 return -__LINE__;
227 }
228 }
229 ++actVldCpyNum;
230 }
231 if (actVldCpyNum < validCpyNum) {
232 FB_ERR("[%s]actual valid copy num %d < configured num %d\n",
233 bootName, actVldCpyNum, validCpyNum);
234 memset(pBuf, 0, binSz);
235 return -__LINE__;
236 }
237
238 return 0;
239}
240
241int bootloader_read(u8 *pBuf, unsigned off, unsigned binSz)
242{
243 return _bootloader_read(pBuf, off, binSz, "bootloader");
244}
245#endif// #ifndef CONFIG_AML_V3_FACTORY_BURN//storage wrapper
246