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