1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "mtd_legacy_lite.h"
32 #include "hdf_log.h"
33 #include "mtd_core.h"
34 #include "mtd_list.h"
35 #include "osal_mem.h"
36 #include "string.h"
37 
38 struct MtdDevNode {
39     char *type;
40     int status;
41     struct MtdDev *mtdDev;
42     struct MtdDevNode *next;
43 };
44 
45 static struct MtdDevNode g_mtdHead;
46 
GetMtd(const char * type)47 void *GetMtd(const char *type)
48 {
49     struct MtdDevNode *p = NULL;
50 
51     if (type == NULL) {
52         return NULL;
53     }
54 
55     for (p = g_mtdHead.next; p != NULL; p = p->next) {
56         if (strcmp(type, p->type) == 0) {
57             p->status++;
58             return p->mtdDev;
59         }
60     }
61     return NULL;
62 }
63 
GetMtdInfo(const char * type)64 int GetMtdInfo(const char *type)
65 {
66     struct MtdDevNode *p = NULL;
67 
68     if (type == NULL) {
69         return -1;
70     }
71 
72     for (p = g_mtdHead.next; p != NULL; p = p->next) {
73         if (strcmp(type, p->type) == 0) {
74             return 0;
75         }
76     }
77     return -1;
78 }
79 
FreeMtd(struct MtdDev * mtdDev)80 int FreeMtd(struct MtdDev *mtdDev)
81 {
82     struct MtdDevNode *p = NULL;
83 
84     if (mtdDev == NULL) {
85         return -1;
86     }
87 
88     for (p = g_mtdHead.next; p != NULL; p = p->next) {
89         if (p->mtdDev == mtdDev) {
90             p->status--;
91             return 0;
92         }
93     }
94 
95     return -1;
96 }
97 
DelMtdList(struct MtdDev * mtdDev)98 int DelMtdList(struct MtdDev *mtdDev)
99 {
100     struct MtdDevNode *p = NULL;
101     struct MtdDevNode *q = NULL;
102 
103     if (mtdDev == NULL) {
104         return -1;
105     }
106 
107     for (p = g_mtdHead.next, q = &g_mtdHead; p != NULL; q = p, p = p->next) {
108         if (p->mtdDev == mtdDev) {
109             if (p->status == 0) {
110                 q->next = p->next;
111                 free(p);
112                 return 0;
113             }
114             return -1;
115         }
116     }
117     return -1;
118 }
119 
AddMtdList(char * type,struct MtdDev * mtdDev)120 void AddMtdList(char *type, struct MtdDev *mtdDev)
121 {
122     struct MtdDevNode *p = NULL;
123     struct MtdDevNode *q = NULL;
124 
125     if (type == NULL || mtdDev == NULL) {
126         return;
127     }
128 
129     p = g_mtdHead.next;
130     q = (struct MtdDevNode *)OsalMemCalloc(sizeof(*q));
131     if (q == NULL) {
132         return;
133     }
134 
135     q->type = type;
136     q->mtdDev = mtdDev;
137     q->status = 0;
138     g_mtdHead.next = q;
139     q->next = p;
140 }
141 
142 MtdInfoLegacy g_mtdInfo;
143 MtdInfoLegacy *nand_mtd;
144 struct MtdDevice *g_nandMtd;
145 /************** compatibale of old hisi interfaces ***************************/
146 // from device/hisilicon/drivers/xxxx/mtd/nand/src/common/nand.c
nand_init(void)147 int nand_init(void)
148 {
149     HDF_LOGI("nand_init: this is a stub cause new mtd drivers has been used!");
150     return 0;
151 }
152 
153 // form device/hisilicon/drivers/xxxx/mtd/nand/src/common/nand_utils.c
hinand_read(void * memaddr,unsigned long start,unsigned long size)154 int hinand_read(void *memaddr, unsigned long start, unsigned long size)
155 {
156     int32_t ret;
157 
158     if (g_nandMtd == NULL) {
159         HDF_LOGE("hinand_read: g_nandMtd is null!");
160         return -ENODEV;
161     }
162     ret = MtdDeviceRead(g_nandMtd, (off_t)start, (size_t)size, (uint8_t *)memaddr);
163     if ((unsigned long)ret != size) {
164         HDF_LOGE("hinand_read: ret=%d, size=%lu!", ret, size);
165     }
166     return ((unsigned long)ret == size) ? HDF_SUCCESS : ret;
167 }
168 
hinand_write(void * memaddr,unsigned long start,unsigned long size)169 int hinand_write(void *memaddr, unsigned long start, unsigned long size)
170 {
171     int32_t ret;
172 
173     if (g_nandMtd == NULL) {
174         HDF_LOGE("hinand_write: g_nandMtd is null!");
175         return -ENODEV;
176     }
177     ret = MtdDeviceWrite(g_nandMtd, (off_t)start, (size_t)size, (const uint8_t *)memaddr);
178     if ((unsigned long)ret != size) {
179         HDF_LOGE("hinand_write: ret=%d, size=%lu!", ret, size);
180     }
181     return ((unsigned long)ret == size) ? HDF_SUCCESS : ret;
182 }
183 
hinand_erase(unsigned long start,unsigned long size)184 int hinand_erase(unsigned long start, unsigned long size)
185 {
186     int ret;
187     off_t failAddr;
188 
189     if (g_nandMtd == NULL) {
190         HDF_LOGE("hinand_erase: g_nandMtd is null!");
191         return -ENODEV;
192     }
193     ret = MtdDeviceErase(g_nandMtd, (off_t)start, (size_t)size, &failAddr);
194     if (ret != 0) {
195         HDF_LOGE("hinand_erase: MtdDeviceErase fail, ret= %d!", ret);
196     }
197     return ret;
198 }
199 
hinand_yaffs_read(void * memaddr,unsigned long start,unsigned long size)200 int hinand_yaffs_read(void *memaddr, unsigned long start, unsigned long size)
201 {
202     int32_t ret;
203 
204     if (g_nandMtd == NULL) {
205         HDF_LOGE("hinand_yaffs_read: g_nandMtd is null!");
206         return -ENODEV;
207     }
208     ret = MtdDeviceReadWithOob(g_nandMtd, (off_t)start, (size_t)size, (uint8_t *)memaddr);
209     if ((unsigned long)ret != size) {
210         HDF_LOGE("hinand_yaffs_read: ret=%d, size=%lu!", ret, size);
211     }
212     return ((unsigned long)ret == size) ? HDF_SUCCESS : ret;
213 }
214 
hinand_yaffs_write(void * memaddr,unsigned long start,unsigned long size)215 int hinand_yaffs_write(void *memaddr, unsigned long start, unsigned long size)
216 {
217     int32_t ret;
218 
219     if (g_nandMtd == NULL) {
220         HDF_LOGE("hinand_yaffs_write: g_nandMtd is null!");
221         return -ENODEV;
222     }
223     ret = MtdDeviceWriteWithOob(g_nandMtd, (off_t)start, (size_t)size, (uint8_t *)memaddr);
224     if ((unsigned long)ret != size) {
225         HDF_LOGE("hinand_yaffs_write: ret=%d, size=%lu!", ret, size);
226     }
227     return ((unsigned long)ret == size) ? HDF_SUCCESS : ret;
228 }
229 
hinand_yaffs_nand_block_isbad(loff_t ofs)230 int hinand_yaffs_nand_block_isbad(loff_t ofs)
231 {
232     return MtdDeviceIsBadBlock(g_nandMtd, ofs);
233 }
234 
hinand_yaffs_nand_block_markbad(loff_t ofs)235 int hinand_yaffs_nand_block_markbad(loff_t ofs)
236 {
237     return MtdDeviceMarkBadBlock(g_nandMtd, ofs);
238 }
239 
spinor_init(void)240 int spinor_init(void)
241 {
242     HDF_LOGI("spinor_init: this function has been hacked ...");
243     return HDF_SUCCESS;
244 }
245 
MtdDeviceLegacyNandErase(MtdInfoLegacy * mtd,EraseInfoLegacy * ops)246 static int MtdDeviceLegacyNandErase(MtdInfoLegacy *mtd, EraseInfoLegacy *ops)
247 {
248     int ret;
249     off_t failAddr;
250 
251     if (mtd == NULL || ops == NULL) {
252         HDF_LOGE("MtdDeviceLegacyNandErase: mtd or ops is null!");
253         return -EINVAL;
254     }
255     ops->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
256 
257     ret = MtdDeviceErase((struct MtdDevice *)mtd->priv, (off_t)ops->addr, (size_t)ops->len, &failAddr);
258     if (ret != HDF_SUCCESS) {
259         ops->fail_addr = failAddr;
260     }
261     return ret;
262 }
263 
MtdDeviceLegacyNandRead(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,char * buf)264 static int MtdDeviceLegacyNandRead(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, char *buf)
265 {
266     int ret;
267 
268     if (mtd == NULL || mtd->priv == NULL || retlen == NULL || buf == NULL) {
269         HDF_LOGE("MtdDeviceLegacyNandRead: function parameter is null!");
270         return -EINVAL;
271     }
272 
273     ret = MtdDeviceRead((struct MtdDevice *)mtd->priv, addr, len, (uint8_t *)buf);
274     *retlen = (ret == HDF_SUCCESS) ? len : 0;
275     return ret;
276 }
277 
MtdDeviceLegacyNandWrite(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,const char * buf)278 static int MtdDeviceLegacyNandWrite(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, const char *buf)
279 {
280     int ret;
281 
282     if (mtd == NULL || retlen == NULL) {
283         HDF_LOGE("MtdDeviceLegacyNandWrite: function parameter is null!");
284         return -EINVAL;
285     }
286 
287     ret = MtdDeviceWrite((struct MtdDevice *)mtd->priv, addr, len, (const uint8_t *)buf);
288     *retlen = (ret == HDF_SUCCESS) ? len : 0;
289     return ret;
290 }
291 
MtdDeviceLegacyNandReadOob(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,char * buf)292 static int MtdDeviceLegacyNandReadOob(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, char *buf)
293 {
294     int ret;
295 
296     if (mtd == NULL || retlen == NULL) {
297         HDF_LOGE("MtdDeviceLegacyNandReadOob: function parameter is null!");
298         return -EINVAL;
299     }
300 
301     ret = MtdDeviceReadWithOob((struct MtdDevice *)mtd->priv, addr, len, (uint8_t *)buf);
302     *retlen = (ret == HDF_SUCCESS) ? len : 0;
303     return ret;
304 }
305 
MtdDeviceLegacyNandWriteOob(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,const char * buf)306 static int MtdDeviceLegacyNandWriteOob(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, const char *buf)
307 {
308     int ret;
309 
310     if (mtd == NULL || retlen == NULL) {
311         HDF_LOGE("MtdDeviceLegacyNandWriteOob: function parameter is null!");
312         return -EINVAL;
313     }
314 
315     ret = MtdDeviceWriteWithOob((struct MtdDevice *)mtd->priv, addr, len, (const uint8_t *)buf);
316     *retlen = (ret == HDF_SUCCESS) ? len : 0;
317     return ret;
318 }
319 
MtdDeviceLegacyBlockIsBad(MtdInfoLegacy * mtd,off_t ofs)320 static int MtdDeviceLegacyBlockIsBad(MtdInfoLegacy *mtd, off_t ofs)
321 {
322     if (mtd == NULL) {
323         HDF_LOGE("MtdDeviceLegacyBlockIsBad: mtd is null!");
324         return -EINVAL;
325     }
326 
327     return (int)MtdDeviceIsBadBlock((struct MtdDevice *)mtd->priv, ofs);
328 }
329 
MtdDeviceLegacyBlockMarkBad(MtdInfoLegacy * mtd,off_t ofs)330 static int MtdDeviceLegacyBlockMarkBad(MtdInfoLegacy *mtd, off_t ofs)
331 {
332     if (mtd == NULL) {
333         HDF_LOGE("MtdDeviceLegacyBlockMarkBad: mtd is null!");
334         return -EINVAL;
335     }
336 
337     return (int)MtdDeviceMarkBadBlock((struct MtdDevice *)mtd->priv, ofs);
338 }
339 
MtdDeviceLegacyFillMtdInfo(struct MtdDevice * mtdDevice)340 void MtdDeviceLegacyFillMtdInfo(struct MtdDevice *mtdDevice)
341 {
342     if (mtdDevice == NULL) {
343         HDF_LOGE("MtdDeviceLegacyFillMtdInfo: mtdDevice is null!");
344         return;
345     }
346     nand_mtd = &g_mtdInfo;
347 
348     nand_mtd->size = mtdDevice->capacity;
349     nand_mtd->erasesize = mtdDevice->eraseSize;
350     nand_mtd->writesize = mtdDevice->writeSize;
351     nand_mtd->oobsize = mtdDevice->oobSize;
352     nand_mtd->name = "nand";
353     nand_mtd->type = MTD_NANDFLASH;
354     nand_mtd->flags = MTD_CAP_NANDFLASH;
355 
356     nand_mtd->erase = MtdDeviceLegacyNandErase;
357     nand_mtd->read = MtdDeviceLegacyNandRead;
358     nand_mtd->write = MtdDeviceLegacyNandWrite;
359     nand_mtd->read_oob = MtdDeviceLegacyNandReadOob;
360     nand_mtd->write_oob = MtdDeviceLegacyNandWriteOob;
361     nand_mtd->block_isbad = MtdDeviceLegacyBlockIsBad;
362     nand_mtd->block_markbad = MtdDeviceLegacyBlockMarkBad;
363     nand_mtd->priv = mtdDevice;
364 
365     g_nandMtd = mtdDevice;
366 }
367