1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "mtd_core.h"
10 #include "securec.h"
11 
12 #include "hdf_log.h"
13 #include "mtd_block.h"
14 #include "mtd_char.h"
15 #include "platform_core.h"
16 
MtdDeviceCheckParms(struct MtdDevice * mtdDevice)17 static int32_t MtdDeviceCheckParms(struct MtdDevice *mtdDevice)
18 {
19     if (mtdDevice->index < 0 || mtdDevice->index >= MTD_DEVICE_NUM_MAX) {
20         HDF_LOGE("MtdDeviceCheckParms: invalid index: %d!", mtdDevice->index);
21         return HDF_ERR_INVALID_OBJECT;
22     }
23 
24     if (mtdDevice->name == NULL) {
25         HDF_LOGE("MtdDeviceCheckParms: name is null!");
26         return HDF_ERR_INVALID_OBJECT;
27     }
28 
29     if (mtdDevice->type >= MTD_TYPE_MAX) {
30         HDF_LOGE("MtdDeviceCheckParms: invalid mtd type:%d!", mtdDevice->type);
31         return HDF_ERR_INVALID_OBJECT;
32     }
33 
34     if (mtdDevice->idLen > MTD_FLASH_ID_LEN_MAX) {
35         HDF_LOGE("MtdDeviceCheckParms: invalid idLen:%u!", mtdDevice->idLen);
36         return HDF_ERR_INVALID_OBJECT;
37     }
38 
39     if (mtdDevice->capacity == 0) {
40         HDF_LOGE("MtdDeviceCheckParms: invalid capacity:%zu!", mtdDevice->capacity);
41         return HDF_ERR_INVALID_OBJECT;
42     }
43 
44     if (mtdDevice->eraseSize == 0) {
45         HDF_LOGE("MtdDeviceCheckParms: invalid erase size:%zu!", mtdDevice->eraseSize);
46         return HDF_ERR_INVALID_OBJECT;
47     }
48 
49     if (mtdDevice->writeSize == 0) {
50         HDF_LOGE("MtdDeviceCheckParms: invalid write size:%zu!", mtdDevice->writeSize);
51         return HDF_ERR_INVALID_OBJECT;
52     }
53 
54     if (mtdDevice->readSize == 0) {
55         HDF_LOGE("MtdDeviceCheckParms: invalid read size:%zu!", mtdDevice->readSize);
56         return HDF_ERR_INVALID_OBJECT;
57     }
58 
59     return HDF_SUCCESS;
60 }
61 
MtdDeviceDumpDefault(struct MtdDevice * mtdDevice)62 static void MtdDeviceDumpDefault(struct MtdDevice *mtdDevice)
63 {
64     if (mtdDevice != NULL) {
65         MTD_DEVICE_DUMP(mtdDevice);
66     }
67     return;
68 }
69 
MtdDeviceDump(struct MtdDevice * mtdDevice)70 static void MtdDeviceDump(struct MtdDevice *mtdDevice)
71 {
72     if (mtdDevice != NULL && mtdDevice->ops != NULL && mtdDevice->ops->dump != NULL) {
73         mtdDevice->ops->dump(mtdDevice);
74     }
75     return;
76 }
77 
MtdDeviceLockDefault(struct MtdDevice * mtdDevice)78 static int32_t MtdDeviceLockDefault(struct MtdDevice *mtdDevice)
79 {
80     if (mtdDevice == NULL) {
81         HDF_LOGE("MtdDeviceLockDefault: mtdDevice is null!");
82         return HDF_ERR_INVALID_OBJECT;
83     }
84     return OsalMutexLock(&mtdDevice->lock);
85 }
86 
MtdDeviceUnlockDefault(struct MtdDevice * mtdDevice)87 static void MtdDeviceUnlockDefault(struct MtdDevice *mtdDevice)
88 {
89     if (mtdDevice != NULL) {
90         OsalMutexUnlock(&mtdDevice->lock);
91     }
92     return;
93 }
94 
MtdManagerGet(void)95 struct PlatformManager *MtdManagerGet(void)
96 {
97     int32_t ret;
98     static struct PlatformManager *g_mtdManager = NULL;
99 
100     if (g_mtdManager == NULL) {
101         ret = PlatformManagerCreate("STORAGE_MTD", &g_mtdManager);
102         if (ret != HDF_SUCCESS) {
103             HDF_LOGE("MtdManagerGet: create manager fail, ret: %d!", ret);
104             return NULL;
105         }
106     }
107     return g_mtdManager;
108 }
109 
MtdDeviceAdd(struct MtdDevice * mtdDevice)110 int32_t MtdDeviceAdd(struct MtdDevice *mtdDevice)
111 {
112     int32_t ret;
113 
114     if (mtdDevice == NULL || mtdDevice->ops == NULL) {
115         HDF_LOGE("MtdDeviceAdd: mtdDevice or ops is null!");
116         return HDF_ERR_INVALID_OBJECT;
117     }
118 
119     ret = MtdDeviceCheckParms(mtdDevice);
120     if (ret != HDF_SUCCESS) {
121         HDF_LOGE("MtdDeviceAdd: mtd device check parms fail!");
122         return HDF_ERR_INVALID_OBJECT;
123     }
124 
125     ret = OsalMutexInit(&mtdDevice->lock);
126     if (ret != HDF_SUCCESS) {
127         HDF_LOGE("MtdDeviceAdd: mutex init fail, ret: %d!", ret);
128         return ret;
129     }
130 
131     if (mtdDevice->ops->dump == NULL) {
132         mtdDevice->ops->dump = MtdDeviceDumpDefault;
133     }
134 
135     if (mtdDevice->ops->lock == NULL || mtdDevice->ops->unlock == NULL) {
136         mtdDevice->ops->lock = MtdDeviceLockDefault;
137         mtdDevice->ops->unlock = MtdDeviceUnlockDefault;
138     }
139 
140     mtdDevice->device.manager = MtdManagerGet();
141     mtdDevice->device.number = mtdDevice->index;
142     ret = PlatformDeviceAdd(&mtdDevice->device);
143     if (ret != HDF_SUCCESS) {
144         HDF_LOGE("MtdDeviceAdd: mtd device add fail!, ret: %d!", ret);
145         return ret;
146     }
147 
148     MtdDeviceDump(mtdDevice);
149 
150     ret = MtdCharInit(mtdDevice);
151     if (ret != HDF_SUCCESS) {
152         HDF_LOGE("MtdDeviceAdd: mtd char init fail, ret: %d!", ret);
153         PlatformDeviceDel(&mtdDevice->device);
154         return ret;
155     }
156 
157     ret = MtdBlockInit(mtdDevice);
158     if (ret != HDF_SUCCESS) {
159         HDF_LOGE("MtdDeviceAdd: mtd block init fail, ret: %d!", ret);
160         PlatformDeviceDel(&mtdDevice->device);
161         return ret;
162     }
163 
164     return HDF_SUCCESS;
165 }
166 
MtdDeviceDel(struct MtdDevice * mtdDevice)167 void MtdDeviceDel(struct MtdDevice *mtdDevice)
168 {
169     if (mtdDevice != NULL) {
170         MtdCharUninit(mtdDevice);
171         MtdBlockUninit(mtdDevice);
172         PlatformDeviceDel(&mtdDevice->device);
173         (void)OsalMutexDestroy(&mtdDevice->lock);
174     }
175 }
176 
MtdDeviceLock(struct MtdDevice * mtdDevice)177 int32_t MtdDeviceLock(struct MtdDevice *mtdDevice)
178 {
179     int32_t ret;
180 
181     if (mtdDevice == NULL || mtdDevice->ops == NULL) {
182         HDF_LOGE("MtdDeviceLock: mtdDevice or ops is null!");
183         return HDF_ERR_INVALID_OBJECT;
184     }
185 
186     if (mtdDevice->ops->lock == NULL) {
187         HDF_LOGE("MtdDeviceLock: lock is null!");
188         return HDF_ERR_NOT_SUPPORT;
189     }
190 
191     ret = mtdDevice->ops->lock(mtdDevice);
192     if (ret != HDF_SUCCESS) {
193         HDF_LOGE("MtdDeviceLock: lock mtd device fail, ret: %d!", ret);
194     }
195     return ret;
196 }
197 
MtdDeviceUnlock(struct MtdDevice * mtdDevice)198 void MtdDeviceUnlock(struct MtdDevice *mtdDevice)
199 {
200     if (mtdDevice != NULL && mtdDevice->ops != NULL && mtdDevice->ops->unlock != NULL) {
201         mtdDevice->ops->unlock(mtdDevice);
202     }
203     return;
204 }
205 
MtdDumpBuf(uint8_t * buf,size_t len)206 static void MtdDumpBuf(uint8_t *buf, size_t len)
207 {
208     int ret;
209     size_t i;
210     size_t idx;
211     size_t lidx;
212     size_t line;
213 #define MTD_DUMP_SIGLE_WIDTH  2
214 #define MTD_DUMP_LINE_LEN     32
215 #define MTD_DUMP_BUF_LEN    (MTD_DUMP_LINE_LEN * MTD_DUMP_SIGLE_WIDTH + 1)
216     char lineBuf[MTD_DUMP_BUF_LEN];
217     idx = 0;
218     while (idx < len) {
219         line = (MTD_DUMP_LINE_LEN <= (len - idx)) ? MTD_DUMP_LINE_LEN : (len - idx);
220         for (i = 0, lidx = 0; i < line; i++, lidx += MTD_DUMP_SIGLE_WIDTH, buf++) {
221             ret = snprintf_s(lineBuf + lidx, MTD_DUMP_SIGLE_WIDTH + 1, MTD_DUMP_SIGLE_WIDTH, "%02x", *buf);
222             if (ret < 0) {
223                 HDF_LOGD("MtdDumpBuf: format string fail, ret: %d!", ret);
224                 return;
225             }
226         }
227         HDF_LOGD("MtdDumpBuf: 0x%08zx : %s", idx, lineBuf);
228         idx += line;
229     }
230     return;
231 }
232 
MtdDeviceEraseUnlock(struct MtdDevice * mtdDevice,off_t addr,size_t len,off_t * faddr)233 static int32_t MtdDeviceEraseUnlock(struct MtdDevice *mtdDevice, off_t addr, size_t len, off_t *faddr)
234 {
235     int32_t ret;
236 
237     if (mtdDevice == NULL || mtdDevice->ops == NULL) {
238         HDF_LOGE("MtdDeviceEraseUnlock: mtdDevice or ops is null!");
239         return HDF_ERR_INVALID_OBJECT;
240     }
241 
242     if (mtdDevice->ops->erase == NULL) {
243         HDF_LOGE("MtdDeviceEraseUnlock: erase is null!");
244         return HDF_ERR_NOT_SUPPORT;
245     }
246 
247     ret = mtdDevice->ops->erase(mtdDevice, addr, len, faddr);
248     if (ret != HDF_SUCCESS) {
249         HDF_LOGE("MtdDeviceEraseUnlock: erase mtd device fail, addr: %jx, ret: %d!", addr, ret);
250     }
251     return ret;
252 }
253 
MtdDeviceErase(struct MtdDevice * mtdDevice,off_t addr,size_t len,off_t * failAddr)254 ssize_t MtdDeviceErase(struct MtdDevice *mtdDevice, off_t addr, size_t len, off_t *failAddr)
255 {
256     int32_t ret;
257 
258     if ((ret = MtdDeviceLock(mtdDevice)) != HDF_SUCCESS) {
259         HDF_LOGE("MtdDeviceErase: mtd device lock fail!");
260         return ret;
261     }
262     ret = MtdDeviceEraseUnlock(mtdDevice, addr, len, failAddr);
263     MtdDeviceUnlock(mtdDevice);
264     return ret;
265 }
266 
MtdDeviceIsBadBlockUnlocked(struct MtdDevice * mtdDevice,off_t addr)267 static bool MtdDeviceIsBadBlockUnlocked(struct MtdDevice *mtdDevice, off_t addr)
268 {
269     if (mtdDevice != NULL && mtdDevice->ops != NULL && mtdDevice->ops->isBadBlock != NULL) {
270         return mtdDevice->ops->isBadBlock(mtdDevice, addr);
271     }
272     return false;
273 }
274 
MtdDeviceMarkBadBlockUnlocked(struct MtdDevice * mtdDevice,off_t addr)275 static int32_t MtdDeviceMarkBadBlockUnlocked(struct MtdDevice *mtdDevice, off_t addr)
276 {
277     int32_t ret;
278 
279     if (mtdDevice == NULL) {
280         HDF_LOGE("MtdDeviceMarkBadBlockUnlocked: mtdDevice is null!");
281         return HDF_ERR_INVALID_OBJECT;
282     }
283     if (mtdDevice->ops == NULL || mtdDevice->ops->markBadBlock == NULL) {
284         HDF_LOGE("MtdDeviceMarkBadBlockUnlocked: ops or markBadBlock is null!");
285         return HDF_ERR_NOT_SUPPORT;
286     }
287     ret = mtdDevice->ops->markBadBlock(mtdDevice, addr);
288     if (ret != HDF_SUCCESS) {
289         HDF_LOGE("MtdDeviceMarkBadBlockUnlocked: mark bad block fail, addr: %jx, ret: %d!", addr, ret);
290     }
291     return ret;
292 }
293 
MtdDeviceIsBadBlock(struct MtdDevice * mtdDevice,off_t addr)294 bool MtdDeviceIsBadBlock(struct MtdDevice *mtdDevice, off_t addr)
295 {
296     bool ret = false;
297 
298     if (MtdDeviceLock(mtdDevice) != HDF_SUCCESS) {
299         HDF_LOGE("MtdDeviceIsBadBlock: mtd device lock fail!");
300         return false;
301     }
302     ret = MtdDeviceIsBadBlockUnlocked(mtdDevice, addr);
303     MtdDeviceUnlock(mtdDevice);
304     return ret;
305 }
306 
MtdDeviceMarkBadBlock(struct MtdDevice * mtdDevice,off_t addr)307 int32_t MtdDeviceMarkBadBlock(struct MtdDevice *mtdDevice, off_t addr)
308 {
309     int32_t ret;
310 
311     if ((ret = MtdDeviceLock(mtdDevice)) != HDF_SUCCESS) {
312         HDF_LOGE("MtdDeviceMarkBadBlock: mtd device lock fail!");
313         return ret;
314     }
315     ret = MtdDeviceMarkBadBlockUnlocked(mtdDevice, addr);
316     MtdDeviceUnlock(mtdDevice);
317     return ret;
318 }
319 
MtdDevicePageTransferUnlocked(struct MtdDevice * mtdDevice,struct MtdPage * mtdPage)320 static int32_t MtdDevicePageTransferUnlocked(struct MtdDevice *mtdDevice, struct MtdPage *mtdPage)
321 {
322     int32_t ret;
323 
324     if (mtdDevice == NULL) {
325         HDF_LOGE("MtdDevicePageTransferUnlocked: mtdDevice is null!");
326         return HDF_ERR_INVALID_OBJECT;
327     }
328 
329     if (mtdDevice->ops == NULL || mtdDevice->ops->pageTransfer == NULL) {
330         HDF_LOGE("MtdDevicePageTransferUnlocked: ops or pageTransfer is null!");
331         return HDF_ERR_NOT_SUPPORT;
332     }
333 
334 #ifdef MTD_DEBUG
335     HDF_LOGD("MtdDevicePageTransferUnlocked: mtdPage-> type=%d, datalen=%zu, ooblen=%zu",
336         mtdPage->type, mtdPage->dataLen, mtdPage->oobLen);
337 #endif
338 
339     ret = mtdDevice->ops->pageTransfer(mtdDevice, mtdPage);
340     if (ret != HDF_SUCCESS) {
341         HDF_LOGE("MtdDevicePageTransferUnlocked: do page transfer fail, ret: %d, addr: 0x%jx!", ret, mtdPage->addr);
342     }
343     return ret;
344 }
345 
MtdDeviceCheckMsg(struct MtdDevice * mtdDevice,struct MtdMsg * msg)346 static int32_t MtdDeviceCheckMsg(struct MtdDevice *mtdDevice, struct MtdMsg *msg)
347 {
348     size_t oobSize;
349 
350     if (mtdDevice == NULL) {
351         HDF_LOGE("MtdDeviceCheckMsg: mtdDevice is null!");
352         return HDF_ERR_INVALID_OBJECT;
353     }
354 
355     if (msg == NULL) {
356         HDF_LOGE("MtdDeviceCheckMsg: msg is null!");
357         return HDF_ERR_INVALID_PARAM;
358     }
359 
360     if (msg->buf == NULL) {
361         HDF_LOGE("MtdDeviceCheckMsg: buf is null!");
362         return HDF_ERR_INVALID_PARAM;
363     }
364 
365     if ((msg->addr + msg->len) > mtdDevice->capacity) {
366         HDF_LOGE("MtdDeviceCheckMsg: over range, len=%zu!", msg->len);
367         return HDF_ERR_INVALID_PARAM;
368     }
369 
370     if (msg->type == MTD_MSG_TYPE_ERASE) {
371         if ((msg->addr % mtdDevice->eraseSize) != 0) {
372             HDF_LOGE("MtdDeviceCheckMsg: not erase size aligned, addr=%jd, erase size=%zu!",
373                 msg->addr, mtdDevice->eraseSize);
374             return HDF_ERR_INVALID_PARAM;
375         }
376         return HDF_SUCCESS;
377     }
378 
379     oobSize = (msg->withOob) ? mtdDevice->oobSize : 0;
380     if ((msg->addr % mtdDevice->writeSize) != 0 || (msg->len % (mtdDevice->writeSize + oobSize)) != 0) {
381         if (msg->type != MTD_MSG_TYPE_READ || msg->withOob) {
382             HDF_LOGE("MtdDeviceCheckMsg: not page aligned, addr=%jd, type=%d, withOob=%d!",
383                 msg->addr, msg->type, msg->withOob);
384             return HDF_ERR_INVALID_PARAM;
385         }
386         return HDF_SUCCESS;
387     }
388 
389     return HDF_SUCCESS;
390 }
391 
MtdDeviceWriteReadByPageUnlock(struct MtdDevice * mtdDevice,struct MtdMsg * msg)392 static int32_t MtdDeviceWriteReadByPageUnlock(struct MtdDevice *mtdDevice, struct MtdMsg *msg)
393 {
394     int32_t ret;
395     off_t addr;
396     uint8_t *buf = NULL;
397     size_t dataLenLeft;
398     size_t blockSize;
399     off_t eraseOffset;
400     struct MtdPage mtdPage;
401 
402     dataLenLeft = msg->withOob ?
403         (msg->len / (mtdDevice->writeSize + mtdDevice->oobSize)) * mtdDevice->writeSize : msg->len;
404     for (addr = msg->addr, buf = msg->buf; (dataLenLeft > 0) && addr < mtdDevice->capacity;) {
405         if (MtdDeviceIsBadBlockUnlocked(mtdDevice, addr)) {
406             if (!msg->skipBad) {
407                 HDF_LOGE("MtdDeviceWriteReadByPageUnlock: failed on bad block @0x%jx!", addr);
408                 return HDF_ERR_IO;
409             }
410             HDF_LOGW("MtdDeviceWriteReadByPageUnlock: skip bad block @0x%jx!", addr);
411             addr = (addr & ~(mtdDevice->eraseSize - 1)) + mtdDevice->eraseSize;
412             continue;
413         }
414         eraseOffset = addr & (mtdDevice->eraseSize - 1);
415         blockSize = (dataLenLeft < (mtdDevice->eraseSize - eraseOffset)) ?
416                     dataLenLeft : (mtdDevice->eraseSize - eraseOffset);
417         // no more than one block at once
418         mtdPage.type = msg->type;
419         while (blockSize > 0) {
420             mtdPage.addr = addr;
421             mtdPage.dataBuf = (uint8_t *)buf;
422             mtdPage.dataLen = mtdDevice->writeSize - (addr & (mtdDevice->writeSize - 1));
423             if (mtdPage.dataLen > blockSize) {
424                 mtdPage.dataLen = blockSize;
425             }
426             mtdPage.oobBuf = msg->withOob ? (buf + mtdPage.dataLen) : NULL;
427             mtdPage.oobLen = msg->withOob ? mtdDevice->oobSize : 0;
428             ret = MtdDevicePageTransferUnlocked(mtdDevice, &mtdPage);
429             if (ret != HDF_SUCCESS) {
430                 MtdDumpBuf(mtdPage.dataBuf, mtdPage.dataLen + mtdPage.oobLen);
431                 return ret;
432             }
433             buf += mtdPage.dataLen + mtdPage.oobLen;
434             addr += mtdPage.dataLen;
435             blockSize -= mtdPage.dataLen;
436             dataLenLeft -= mtdPage.dataLen;
437         }
438     }
439 
440     if (dataLenLeft > 0) {
441         HDF_LOGE("MtdDeviceWriteReadByPageUnlock: no enough space, dataLenLeft=%zu, addr=0x%jx!", dataLenLeft, addr);
442         return HDF_ERR_IO;
443     }
444     return HDF_SUCCESS;
445 }
446 
MtdDeviceRequest(struct MtdDevice * mtdDevice,struct MtdMsg * msg)447 static int32_t MtdDeviceRequest(struct MtdDevice *mtdDevice, struct MtdMsg *msg)
448 {
449     int32_t ret;
450 
451     ret = MtdDeviceCheckMsg(mtdDevice, msg);
452     if (ret != HDF_SUCCESS) {
453         HDF_LOGE("MtdDeviceRequest: mtd device check msg fail, ret: %d!", ret);
454         return ret;
455     }
456 
457     if ((ret = MtdDeviceLock(mtdDevice)) != HDF_SUCCESS) {
458         HDF_LOGE("MtdDeviceRequest: mtd device lock fail, ret: %d!", ret);
459         return ret;
460     }
461 
462     switch (msg->type) {
463         case MTD_MSG_TYPE_READ:
464         case MTD_MSG_TYPE_WRITE:
465             ret = MtdDeviceWriteReadByPageUnlock(mtdDevice, msg);
466             break;
467         case MTD_MSG_TYPE_ERASE:
468             ret = MtdDeviceEraseUnlock(mtdDevice, msg->addr, msg->len, &msg->faddr);
469             break;
470         default:
471             HDF_LOGE("MtdDeviceRequest: type is not support!");
472             ret = HDF_ERR_NOT_SUPPORT;
473             break;
474     }
475 
476     MtdDeviceUnlock(mtdDevice);
477     return ret;
478 }
479 
MtdDeviceWrite(struct MtdDevice * mtdDevice,off_t to,size_t len,const uint8_t * buf)480 ssize_t MtdDeviceWrite(struct MtdDevice *mtdDevice, off_t to, size_t len, const uint8_t *buf)
481 {
482     int32_t ret;
483     struct MtdMsg msg;
484 
485     if (mtdDevice == NULL) {
486         HDF_LOGE("MtdDeviceWrite: mtdDevice is null!");
487         return HDF_ERR_INVALID_OBJECT;
488     }
489 
490     if (mtdDevice->ops == NULL) {
491         HDF_LOGE("MtdDeviceWrite: ops is null!");
492         return HDF_ERR_NOT_SUPPORT;
493     }
494 
495     if (mtdDevice->ops->write != NULL) {
496         if ((ret = MtdDeviceLock(mtdDevice)) != HDF_SUCCESS) {
497             HDF_LOGE("MtdDeviceWrite: mtd device lock fail, ret: %d!", ret);
498             return ret;
499         }
500         ret = mtdDevice->ops->write(mtdDevice, to, len, buf);
501         MtdDeviceUnlock(mtdDevice);
502     } else {
503         msg.type = MTD_MSG_TYPE_WRITE;
504         msg.addr = to;
505         msg.buf = (uint8_t *)buf;
506         msg.len = len;
507         msg.withOob = false;
508         msg.skipBad = true;
509         ret = MtdDeviceRequest(mtdDevice, &msg);
510     }
511 
512     return (ret == HDF_SUCCESS) ? len : ret;
513 }
514 
MtdDeviceRead(struct MtdDevice * mtdDevice,off_t from,size_t len,uint8_t * buf)515 ssize_t MtdDeviceRead(struct MtdDevice *mtdDevice, off_t from, size_t len, uint8_t *buf)
516 {
517     int32_t ret;
518     struct MtdMsg msg;
519 
520     if (mtdDevice == NULL) {
521         HDF_LOGE("MtdDeviceRead: mtdDevice is null!");
522         return HDF_ERR_INVALID_OBJECT;
523     }
524 
525     if (mtdDevice->ops == NULL) {
526         HDF_LOGE("MtdDeviceRead: ops is null!");
527         return HDF_ERR_NOT_SUPPORT;
528     }
529 
530     if (mtdDevice->ops->read != NULL) {
531         if ((ret = MtdDeviceLock(mtdDevice)) != HDF_SUCCESS) {
532             HDF_LOGE("MtdDeviceRead: mtd device lock fail, ret: %d!", ret);
533             return ret;
534         }
535         ret = mtdDevice->ops->read(mtdDevice, from, len, buf);
536         MtdDeviceUnlock(mtdDevice);
537     } else {
538         msg.type = MTD_MSG_TYPE_READ;
539         msg.addr = from;
540         msg.buf = (uint8_t *)buf;
541         msg.len = len;
542         msg.withOob = false;
543         msg.skipBad = true;
544         ret = MtdDeviceRequest(mtdDevice, &msg);
545     }
546 
547     return (ret == HDF_SUCCESS) ? len : ret;
548 }
549 
MtdDeviceWriteWithOob(struct MtdDevice * mtdDevice,off_t to,size_t len,const uint8_t * buf)550 ssize_t MtdDeviceWriteWithOob(struct MtdDevice *mtdDevice, off_t to, size_t len, const uint8_t *buf)
551 {
552     int32_t ret;
553     struct MtdMsg msg;
554 
555     msg.type = MTD_MSG_TYPE_WRITE;
556     msg.addr = to;
557     msg.buf = (uint8_t *)buf;
558     msg.len = len;
559     msg.withOob = true;
560     msg.skipBad = true;
561     ret = MtdDeviceRequest(mtdDevice, &msg);
562     return (ret == HDF_SUCCESS) ? len : ret;
563 }
564 
MtdDeviceReadWithOob(struct MtdDevice * mtdDevice,off_t from,size_t len,uint8_t * buf)565 ssize_t MtdDeviceReadWithOob(struct MtdDevice *mtdDevice, off_t from, size_t len, uint8_t *buf)
566 {
567     int32_t ret;
568     struct MtdMsg msg;
569 
570     msg.type = MTD_MSG_TYPE_READ;
571     msg.addr = from;
572     msg.buf = (uint8_t *)buf;
573     msg.len = len;
574     msg.withOob = true;
575     msg.skipBad = true;
576     ret = MtdDeviceRequest(mtdDevice, &msg);
577     return (ret == HDF_SUCCESS) ? len : ret;
578 }
579 
580 
581 #define MTD_FFS_SHIFT_16BIT     16
582 #define MTD_FFS_SHIFT_8BIT      8
583 #define MTD_FFS_SHIFT_4BIT      4
584 #define MTD_FFS_SHIFT_2BIT      2
585 
MtdFfs(int x)586 int MtdFfs(int x)
587 {
588     int r = 1;
589     unsigned int f = (unsigned int)x;
590 
591     if (f == 0) {
592         return 0;
593     }
594 
595     if ((f & 0xffff) == 0) {
596         f >>= MTD_FFS_SHIFT_16BIT;
597         r += MTD_FFS_SHIFT_16BIT;
598     }
599 
600     if ((f & 0xff) == 0) {
601         f >>= MTD_FFS_SHIFT_8BIT;
602         r += MTD_FFS_SHIFT_8BIT;
603     }
604 
605     if ((f & 0xf) == 0) {
606         f >>= MTD_FFS_SHIFT_4BIT;
607         r += MTD_FFS_SHIFT_4BIT;
608     }
609 
610     if ((f & 0x3) == 0) {
611         f >>= MTD_FFS_SHIFT_2BIT;
612         r += MTD_FFS_SHIFT_2BIT;
613     }
614 
615     if ((f & 0x1) == 0) {
616         r += 1;
617     }
618 
619     return r;
620 }
621