blob: 213c52972d614bd02d05728c4544c288dd622e20 [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>
yihui wu7935bce2024-12-17 01:17:08 +080012#include <amlogic/aml_mmc.h>
Bo Lv72d0e902023-01-02 14:27:34 +000013
14#define debugP(fmt...) //printf("Dbg[WRP]L%d:", __LINE__),printf(fmt)
15#define errorP(fmt...) printf("Err[WRP]L%d:", __LINE__),printf(fmt)
16#define wrnP(fmt...) printf("wrn:"fmt)
17#define MsgP(fmt...) printf("[WRP]"fmt)
18
19//change part logic offset to physical address for mtd, not changed if not MTD
20static int mtd_find_phy_off_by_lgc_off(const char* partName, const loff_t logicAddr, loff_t* phyAddr)
21{
22 if (!(BOOT_NAND_MTD == store_get_type() || BOOT_SNAND == store_get_type())) {
23 *phyAddr = logicAddr;
24 return 0;
25 }
26#ifndef CONFIG_CMD_MTD
27 MsgP("Exception, boottype is MTD or snand, BUT CMD_MTD not defined\n");
28#else
29 struct mtd_info * mtdPartInf = NULL;
30 mtdPartInf = get_mtd_device_nm(partName);
31 if (!mtdPartInf) {
32 errorP("device(%s) is null\n", partName);
33 return CMD_RET_FAILURE;
34 }
35
36 if (IS_ERR(mtdPartInf)) {
37 errorP("device(%s) is err\n", partName);
38 return CMD_RET_FAILURE;
39 }
40
41 const unsigned eraseSz = mtdPartInf->erasesize;
42 const unsigned offsetInBlk = logicAddr & (eraseSz - 1);
43 loff_t off = 0;
44 int canSpeedUp = 0;
45 static struct {
46 loff_t lastblkPhyOff;
47 loff_t lastblkLgcOff;
48 char partName[64];
49 }_map4SpeedUp = {0};
50 if ( !strcmp(partName, _map4SpeedUp.partName) && logicAddr >= _map4SpeedUp.lastblkLgcOff) {
51 canSpeedUp = 1;
52 } else {
53 _map4SpeedUp.lastblkLgcOff = _map4SpeedUp.lastblkPhyOff = 0;
54 strncpy(_map4SpeedUp.partName, partName, 63);
55 }
56
57 if ( canSpeedUp ) {
58 if ( logicAddr >= _map4SpeedUp.lastblkLgcOff &&
59 logicAddr < _map4SpeedUp.lastblkLgcOff + eraseSz) {
60 *phyAddr = _map4SpeedUp.lastblkPhyOff + offsetInBlk;
61 return 0;
62 }
63 _map4SpeedUp.lastblkPhyOff += eraseSz;
64 _map4SpeedUp.lastblkLgcOff += eraseSz;
65 off = _map4SpeedUp.lastblkPhyOff;
66 }
67 for (; off < mtdPartInf->size; off += eraseSz, _map4SpeedUp.lastblkPhyOff += eraseSz) {
68 if (mtd_block_isbad(mtdPartInf, off)) {
69 MsgP("bad blk at %08llx\n", (unsigned long long)off);
70 } else {
71 if ( logicAddr >= _map4SpeedUp.lastblkLgcOff &&
72 logicAddr < _map4SpeedUp.lastblkLgcOff + eraseSz) {
73 *phyAddr = _map4SpeedUp.lastblkPhyOff + offsetInBlk;
74 return 0;
75 }
76 _map4SpeedUp.lastblkLgcOff += eraseSz;
77 }
78 }
79#endif// #ifndef CONFIG_CMD_MTD
80 return __LINE__;
81}
82
83int store_logic_write(const char *name, loff_t off, size_t size, void *buf)
84{
85 loff_t phyAddr = 0;
86 if (mtd_find_phy_off_by_lgc_off(name, off, &phyAddr)) {
87 errorP("Fail find phy addr\n");
88 return -__LINE__;
89 }
90 return store_write(name, phyAddr, size, buf);
91}
92
93int store_logic_read(const char *name, loff_t off, size_t size, void *buf)
94{
95 loff_t phyAddr = 0;
96 if (mtd_find_phy_off_by_lgc_off(name, off, &phyAddr)) {
97 errorP("Fail find phy addr\n");
98 return -__LINE__;
99 }
100 return store_read(name, phyAddr, size, buf);
101}
102
103//get partition logic size
104u64 store_logic_cap(const char* partName)
105{
106 if (!(BOOT_NAND_MTD == store_get_type() || BOOT_SNAND == store_get_type())) {
107 return store_part_size(partName);
108 }
109
110#ifndef CONFIG_CMD_MTD
111 MsgP("Exception, boottype is MTD or snand, BUT CMD_MTD not defined\n");
112 return 0;
113#else
114 //get mtd part logic size (i.e, not including the bad blocks)
115 struct mtd_info * mtdPartInf = NULL;
116 uint64_t partSzLgc = 0;
117 loff_t off = 0;
118
119 mtdPartInf = get_mtd_device_nm(partName);
120 if (IS_ERR(mtdPartInf)) {
121 errorP("device(%s) is err\n", partName);
122 return CMD_RET_FAILURE;
123 }
124 const unsigned eraseSz = mtdPartInf->erasesize;
125 const uint64_t partSzPhy = mtdPartInf->size;
126
127 partSzLgc = partSzPhy;
128 for (; off < partSzPhy; off += eraseSz) {
129 if (mtd_block_isbad(mtdPartInf, off)) {
130 partSzLgc -= eraseSz;
131 }
132 }
133 return partSzLgc;
134#endif// #ifndef CONFIG_CMD_MTD
135}
136
137int store_gpt_ops(size_t sz, void *buf, int is_wr)
138{
139 int ret = 0;
140
141 if (!sz || sz >= 0x100000) {
142 errorP("sz 0x%zx to large\n", sz);
143 return -__LINE__;
144 }
145
146 if (is_wr)
147 ret = store_gpt_write(buf);
148 else
149 ret = store_gpt_read(buf);
150
151 return ret;
152}
153
yihui wu7935bce2024-12-17 01:17:08 +0800154#ifdef CONFIG_CMD_MMC
155static int _amlmmc_rdwr_bootloader(int dev, int map, unsigned int size, void *src, int iswrite)
156{
157 int ret = 0, i, count = 3;
158 unsigned long n;
159 char *partname[3] = {"user", "boot0", "boot1"};
160 struct mmc *mmc = NULL;
161 lbaint_t start = 1, blkcnt;
162
163 mmc = find_mmc_device(dev);
164 if (!mmc) {
165 printf("%s() %d: not valid emmc %d\n", __func__, __LINE__, dev);
166 return -1;
167 }
168 /* make sure mmc is initialized! */
169 ret = mmc_init(mmc);
170 if (ret) {
171 printf("%s() %d: emmc %d init %d\n", __func__, __LINE__, dev, ret);
172 return -2;
173 }
174
175 blkcnt = (size + mmc->read_bl_len - 1) / mmc->read_bl_len;
176
177 /* erase bootloader in user/boot0/boot1 */
178 for (i = 0; i < count; i++) {
179 if (map & (1 << i)) {
180 if (blk_select_hwpart_devnum(UCLASS_MMC, 1, i)) {
181 printf("%s() %d: switch dev %d to %s fail\n",
182 __func__, __LINE__, dev, partname[i]);
183 ret = -3;
184 break;
185 }
186
187 printf("To %s " LBAFU " blocks at " LBAFU " @%s\n",
188 iswrite ? "Write" : "Read", blkcnt, start, partname[i]);
189 if (iswrite)
190 n = blk_dwrite(mmc_get_blk_desc(mmc), start, blkcnt, src);
191 else
192 n = blk_dread(mmc_get_blk_desc(mmc), start, blkcnt, src);
193 if (n != blkcnt) {
194 printf("mmc rd/wr %s failed\n", partname[i]);
195 ret = -4;
196 break;
197 }
198 }
199 }
200
201 /* try to switch back to user. */
202 if (blk_select_hwpart_devnum(UCLASS_MMC, 1, 0)) {
203 errorP("Fail switch to user\n");
204 return -5;
205 }
206 return ret;
207}
208#else
209static int _amlmmc_rdwr_bootloader(int dev, int map, unsigned int size, void *src, int iswrite)
210{
211 errorP("MMC not enable\n");
212 return -1;
213}
214#endif// #ifdef CONFIG_CMD_MMC
215
216static int _amlmmc_write_bootloader(int dev, int map, unsigned int size, void *src)
217{
218 return _amlmmc_rdwr_bootloader(dev, map, size, src, 1);
219}
220
221static int _amlmmc_read_bootloader(int dev, int map, unsigned int size, void *src)
222{
223 return _amlmmc_rdwr_bootloader(dev, map, size, src, 0);
224}
225
226int store_bootloader_ops(int ops, const char *name, void *pdata, unsigned int szdata)
227{
228 int map = 0;
229 int cpy = 0;
230 int ret = -1;
231 const int DEV = 1;
232 const char *_names[] = {"bootloader-user", "bootloader-boot0", "bootloader-boot1"};
233
234 for (; cpy < ARRAY_SIZE(_names); ++cpy) {
235 if (!strcmp(_names[cpy], name))
236 break;
237 }
238 if (cpy > 2) {
239 errorP("inval cpy %d\n", cpy);
240 return -__LINE__;
241 }
242 map = (1<<cpy);
243 switch (ops) {
244 case _STORE_BOOT_OP_WRITE: {
245 ret = _amlmmc_write_bootloader(DEV, map, szdata, pdata);
246 break;
247 }
248 case _STORE_BOOT_OP_READ: {
249 ret = _amlmmc_read_bootloader(DEV, map, szdata, pdata);
250 break;
251 }
252 case _STORE_BOOT_OP_ERASE:
253 default:
254 errorP("inval op:%d\n", ops);
255 return -__LINE__;
256 }
257
258 return ret;
259}
260
Bo Lv72d0e902023-01-02 14:27:34 +0000261#ifndef CONFIG_AML_V3_FACTORY_BURN//storage wrapper
262#define FB_ERR(fmt ...) printf("[ERR]%s:L%d:", __func__, __LINE__), printf(fmt)
263#define FB_EXIT(fmt ...) do { FB_ERR(fmt); return -__LINE__; } while (0)
264#define FB_MSG(fmt ...) printf("[MSG]" fmt)
265#define FBS_EXIT(buf, fmt ...) do { FBS_ERR(buf, fmt); return -__LINE__; } while (0)
266
267int bootloader_copy_sz(void)
268{
269 return store_boot_copy_size("bootloader");
270}
271
272static int _bootloader_write(u8 *dataBuf, unsigned off, unsigned binSz, const char *bootName)
273{
274 int iCopy = 0;
275 const int bootCpyNum = store_boot_copy_num(bootName);
276 const int bootCpySz = (int)store_boot_copy_size(bootName);
277
278 FB_MSG("[%s] CpyNum %d, bootCpySz 0x%x\n", bootName, bootCpyNum, bootCpySz);
279 if (binSz + off > bootCpySz)
280 FB_EXIT("bootloader sz(0x%x) + off(0x%x) > bootCpySz 0x%x\n",
281 binSz, off, bootCpySz);
282
283 if (off) {
284 FB_ERR("current only 0 supported!\n");
285 return -__LINE__;
286 }
287
288 for (; iCopy < bootCpyNum; ++iCopy) {
289 int ret = store_boot_write(bootName, iCopy, binSz, dataBuf);
290
291 if (ret)
292 FB_EXIT("FAil in program[%s] at copy[%d]\n", bootName, iCopy);
293 }
294
295 return 0;
296}
297
298int bootloader_write(u8 *dataBuf, unsigned off, unsigned binSz)
299{
300 return _bootloader_write(dataBuf, off, binSz, "bootloader");
301}
302
303static int _bootloader_read(u8 *pBuf, unsigned off, unsigned binSz, const char *bootName)
304{
305 int iCopy = 0;
306 const int bootCpyNum = store_boot_copy_num(bootName);
307 const int bootCpySz = (int)store_boot_copy_size(bootName);
308 int validCpyNum = bootCpyNum;//at least valid cpy num
309 int actVldCpyNum = 0;//actual valid copy num
310
311 if (binSz + off > bootCpySz) {
312 FB_ERR("bootloader sz(0x%x) + off(0x%x) > bootCpySz 0x%x\n", binSz, off, bootCpySz);
313 return -__LINE__;
314 }
315 if (off)
316 FB_EXIT("current only 0 supported!\n");
317
318 for (iCopy = 0; iCopy < bootCpyNum; ++iCopy) {
319 void *dataBuf = iCopy ? pBuf + binSz : pBuf;
320 int ret = store_boot_read(bootName, iCopy, binSz, dataBuf);
321
322 if (ret) {
323 FB_ERR("Fail to read boot[%s] at copy[%d]\n", bootName, iCopy);
324 continue;
325 }
326 if (iCopy) {
327 if (!actVldCpyNum) {//NO valid cpy yet, so copy0 NOT valid also
328 memcpy(pBuf, dataBuf, binSz);
329 }
330 if (memcmp(pBuf, dataBuf, binSz)) {
331 FB_ERR("[%s] copy[%d] content NOT the same as copy[0]\n",
332 bootName, iCopy);//maybe ddr err as nand not err
333 memset(pBuf, 0, binSz);
334 return -__LINE__;
335 }
336 }
337 ++actVldCpyNum;
338 }
339 if (actVldCpyNum < validCpyNum) {
340 FB_ERR("[%s]actual valid copy num %d < configured num %d\n",
341 bootName, actVldCpyNum, validCpyNum);
342 memset(pBuf, 0, binSz);
343 return -__LINE__;
344 }
345
346 return 0;
347}
348
349int bootloader_read(u8 *pBuf, unsigned off, unsigned binSz)
350{
351 return _bootloader_read(pBuf, off, binSz, "bootloader");
352}
353#endif// #ifndef CONFIG_AML_V3_FACTORY_BURN//storage wrapper
354