更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
mtd_partition.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "mtd_partition.h"
33#include "stdlib.h"
34#include "stdio.h"
35#include "pthread.h"
36#include "mtd_list.h"
37#include "los_config.h"
38#include "los_mux.h"
39#include "fs/driver.h"
40#include "mtd/mtd_legacy_lite.h"
41
42#ifdef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
43#include "cfiflash.h"
44#endif
45
46
47#define DRIVER_NAME_ADD_SIZE 3 // 0p0 所以加三个字节
48pthread_mutex_t g_mtdPartitionLock = PTHREAD_MUTEX_INITIALIZER;
49
50//通常在NorFlash上会选取jffs及jffs2文件系统
51/*
52* GCC使用__attribute__关键字来描述函数,变量和数据类型的属性,用于编译器对源代码的优化
53* 对外部目标文件的符号引用在目标文件被最终链接成可执行文件时,它们须要被正确决议,如果没有找到该符号的定义,
54链接器就会报符号未定义错误,这种被称为强引用(Strong Reference)。
55
56* 与之相对应还有一种弱引用(Weak Reference),在处理弱引用时,如果该符号有定义,则链接器将该符号的引用决议;
57如果该符号未被定义,则链接器对于该引用不报错。
58
59* 链接器处理强引用和弱引用的过程几乎一样,只是对于未定义的弱引用,链接器不认为它是一个错误。一般对于未定义的弱引用,
60链接器默认其为0,或者是一个特殊的值,以便于程序代码能够识别。
61* 在GCC中,我们可以通过使用"__attribute__((weakref("..."))"这个扩展关键字来声明对一个外部函数的引用为弱引用,
62参考: https://www.cnblogs.com/pengdonglin137/p/3615345.html
63*/
64static VOID YaffsLockInit(VOID) __attribute__((weakref("yaffsfs_OSInitialisation")));
65static VOID YaffsLockDeinit(VOID) __attribute__((weakref("yaffsfs_OsDestroy")));
66static INT32 Jffs2LockInit(VOID) __attribute__((weakref("Jffs2MutexCreate")));//弱引用 Jffs2MutexCreate
67static VOID Jffs2LockDeinit(VOID) __attribute__((weakref("Jffs2MutexDelete")));
68
69partition_param *g_nandPartParam = NULL; //nand flash 分区参数
70partition_param *g_spinorPartParam = NULL; //nor flash 分区参数
71mtd_partition *g_spinorPartitionHead = NULL; //spi nor flash分区头结点,上面将挂所有 spi nor分区结点
72mtd_partition *g_nandPartitionHead = NULL; //nand flash 分区头结点,上面将挂所有 nand分区结点
73
74#define RWE_RW_RW 0755 //文件读/写/执权限,chmod 755
75
77{
78 return g_nandPartParam;
79}
80
82{
83 return g_spinorPartParam;
84}
85
87{
88 return g_spinorPartitionHead;
89}
90
91//nand flash 参数初始化,本函数只会被调用一次
92static VOID MtdNandParamAssign(partition_param *nandParam, const struct MtdDev *nandMtd)
93{
94 LOS_ListInit(&g_nandPartitionHead->node_info);//初始化全局链表
95 /*
96 * If the user do not want to use block mtd or char mtd ,
97 * you can change the NANDBLK_NAME or NANDCHR_NAME to NULL.
98 */
99 nandParam->flash_mtd = (struct MtdDev *)nandMtd;
100 nandParam->flash_ops = GetDevNandOps(); //获取块设备操作方法
101 nandParam->char_ops = GetMtdCharFops(); //获取字符设备操作方法
102 nandParam->blockname = NANDBLK_NAME; // /dev/nandblk
103 nandParam->charname = NANDCHR_NAME; // /dev/nandchr
104 nandParam->partition_head = g_nandPartitionHead;//头分区节点
105 nandParam->block_size = nandMtd->eraseSize;//4K
106}
107///反初始化
108static VOID MtdDeinitNandParam(VOID)
109{
110 if (YaffsLockDeinit != NULL) {
111 YaffsLockDeinit();
112 }
113}
114///nand flash 初始化
116{
117 struct MtdDev *nandMtd = GetMtd("nand");
118 if (nandMtd == NULL) {
119 return NULL;
120 }
121 if (nandParam == NULL) {
122 if (YaffsLockInit != NULL) {
123 YaffsLockInit(); //加锁
124 }
125 nandParam = (partition_param *)zalloc(sizeof(partition_param));
126 if (nandParam == NULL) {
128 return NULL;
129 }
130 g_nandPartitionHead = (mtd_partition *)zalloc(sizeof(mtd_partition));
131 if (g_nandPartitionHead == NULL) {
133 free(nandParam);
134 return NULL;
135 }
136
137 MtdNandParamAssign(nandParam, nandMtd);
138 }
139
140 return nandParam;
141}
142///nor flash 初始化,本函数只会被调用一次
143static VOID MtdNorParamAssign(partition_param *spinorParam, const struct MtdDev *spinorMtd)
144{
145 LOS_ListInit(&g_spinorPartitionHead->node_info);//初始化全局链表,所有spi nor 分区节点都将挂上来
146 /*
147 * If the user do not want to use block mtd or char mtd ,
148 * you can change the SPIBLK_NAME or SPICHR_NAME to NULL.
149 *///如果用户不想使用 block mtd 或 char mtd ,您可以将 SPIBLK_NAME 或 SPICHR_NAME 更改为 NULL。
150 spinorParam->flash_mtd = (struct MtdDev *)spinorMtd;
151#ifndef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7 //QEMU开关
152 spinorParam->flash_ops = GetDevSpinorOps();//块操作
153 spinorParam->char_ops = GetMtdCharFops();//字符操作
154 spinorParam->blockname = SPIBLK_NAME;
155 spinorParam->charname = SPICHR_NAME;
156#else
157 spinorParam->flash_ops = GetCfiBlkOps();
158 spinorParam->char_ops = NULL;
159 spinorParam->blockname = CFI_DRIVER;
160 spinorParam->charname = NULL;
161#endif
162 spinorParam->partition_head = g_spinorPartitionHead;//头分区节点
163 spinorParam->block_size = spinorMtd->eraseSize;//4K, 读/写/擦除 的最小单位
164}
165
166static VOID MtdDeinitSpinorParam(VOID)
167{
168 if (Jffs2LockDeinit != NULL) {
169 Jffs2LockDeinit();
170 }
171}
172///spi nor flash 参数初始化
174{
175#ifndef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7 //
176 struct MtdDev *spinorMtd = GetMtd("spinor");
177#else
178 struct MtdDev *spinorMtd = GetCfiMtdDev();
179#endif
180 if (spinorMtd == NULL) {
181 return NULL;
182 }
183 if (spinorParam == NULL) {
184 if (Jffs2LockInit != NULL) {
185 if (Jffs2LockInit() != 0) { /* create jffs2 lock failed */
186 return NULL;
187 }
188 }
189 spinorParam = (partition_param *)zalloc(sizeof(partition_param));
190 if (spinorParam == NULL) {
191 PRINT_ERR("%s, partition_param malloc failed\n", __FUNCTION__);
193 return NULL;
194 }
195 g_spinorPartitionHead = (mtd_partition *)zalloc(sizeof(mtd_partition));
196 if (g_spinorPartitionHead == NULL) {
197 PRINT_ERR("%s, mtd_partition malloc failed\n", __FUNCTION__);
199 free(spinorParam);
200 return NULL;
201 }
202
203 MtdNorParamAssign(spinorParam, spinorMtd);
204 }
205
206 return spinorParam;
207}
208///根据 flash-type 来初始化分区的参数, Fspar 是不是 flash partition 的意思? 这名字取得有点费解 @note_thinking
209/* According the flash-type to init the param of the partition. */
210static INT32 MtdInitFsparParam(const CHAR *type, partition_param **fsparParam)
211{
212 if (strcmp(type, "nand") == 0) {// nand flash 的处理
213 g_nandPartParam = MtdInitNandParam(g_nandPartParam);//初始化全局变量
214 *fsparParam = g_nandPartParam;//参数接走全局变量
215 } else if (strcmp(type, "spinor") == 0 || strcmp(type, "cfi-flash") == 0) { //nor flash的处理
216 g_spinorPartParam = MtdInitSpinorParam(g_spinorPartParam);//初始化全局变量
217 *fsparParam = g_spinorPartParam;//参数接走全局变量
218 } else {
219 return -EINVAL;
220 }
221
222 if ((*fsparParam == NULL) || ((VOID *)((*fsparParam)->flash_mtd) == NULL)) {
223 return -ENODEV;
224 }
225
226 return ENOERR;
227}
228///根据flash-type 去初始化 分区的参数。
229/* According the flash-type to deinit the param of the partition. */
231{
232 if (strcmp(type, "nand") == 0) {
233 MtdDeinitNandParam();//去初始化(析构) Nand flash 参数
234 g_nandPartParam = NULL;
235 } else if (strcmp(type, "spinor") == 0 || strcmp(type, "cfi-flash") == 0) {
236 MtdDeinitSpinorParam();//去初始化(析构) Nor flash 参数, 注 : .h 文件有 spi 和 cfi 的区别介绍
237 g_spinorPartParam = NULL;
238 } else {
239 return -EINVAL;
240 }
241
242 return ENOERR;
243}
244///增加MTD分区参数检查
245static INT32 AddParamCheck(UINT32 startAddr,
246 const partition_param *param,
247 UINT32 partitionNum,
248 UINT32 length)
249{
250 UINT32 startBlk, endBlk;
251 mtd_partition *node = NULL;
252 if ((param->blockname == NULL) && (param->charname == NULL)) {//块/字符设备名称至少有一个
253 return -EINVAL;
254 }
255
256 if ((length == 0) || (length < param->block_size) ||
257 (((UINT64)(startAddr) + length) > param->flash_mtd->size)) {
258 return -EINVAL;
259 }
260
261 ALIGN_ASSIGN(length, startAddr, startBlk, endBlk, param->block_size);
262
263 if (startBlk > endBlk) {
264 return -EINVAL;
265 }
266 LOS_DL_LIST_FOR_EACH_ENTRY(node, &param->partition_head->node_info, mtd_partition, node_info) {//遍历分区节点
267 if ((node->start_block != 0) && (node->patitionnum == partitionNum)) {
268 return -EINVAL;
269 }
270 if ((startBlk > node->end_block) || (endBlk < node->start_block)) {
271 continue;
272 }
273 return -EINVAL;
274 }
275
276 return ENOERR;
277}
278///注册块设备,此函数之后设备将支持VFS访问
280 const partition_param *param,
281 UINT32 partitionNum)
282{
283 INT32 ret;
284 size_t driverNameSize;
285
286 if (param->blockname != NULL) {
287 driverNameSize = strlen(param->blockname) + DRIVER_NAME_ADD_SIZE; // 设备名称长度增加3个字节
288 newNode->blockdriver_name = (CHAR *)malloc(driverNameSize);
289 if (newNode->blockdriver_name == NULL) {
290 return -ENOMEM;
291 }
292
293 ret = snprintf_s(newNode->blockdriver_name, driverNameSize,
294 driverNameSize - 1, "%s%u", param->blockname, partitionNum);
295 if (ret < 0) {
296 free(newNode->blockdriver_name);
297 newNode->blockdriver_name = NULL;
298 return -ENAMETOOLONG;
299 }
300 //在伪文件系统中注册块驱动程序,对节点数据以块方式访问
301 ret = register_blockdriver(newNode->blockdriver_name, param->flash_ops,
302 RWE_RW_RW, newNode);
303 if (ret) {
304 free(newNode->blockdriver_name);
305 newNode->blockdriver_name = NULL;
306 PRINT_ERR("register blkdev partition error\n");
307 return ret;
308 }
309 } else {
310 newNode->blockdriver_name = NULL;
311 }
312 return ENOERR;
313}
314///注册字符设备,此函数之后设备将支持VFS访问
316 const partition_param *param,
317 UINT32 partitionNum)
318{
319 INT32 ret;
320 size_t driverNameSize;
321
322 if (param->charname != NULL) {
323 driverNameSize = strlen(param->charname) + DRIVER_NAME_ADD_SIZE;
324 newNode->chardriver_name = (CHAR *)malloc(driverNameSize);
325 if (newNode->chardriver_name == NULL) {
326 return -ENOMEM;
327 }
328
329 ret = snprintf_s(newNode->chardriver_name, driverNameSize,
330 driverNameSize - 1, "%s%u", param->charname, partitionNum);
331 if (ret < 0) {
332 free(newNode->chardriver_name);
333 newNode->chardriver_name = NULL;
334 return -ENAMETOOLONG;
335 }
336 //在伪文件系统中注册字符驱动程序,以字符设备的方式访问数据
337 ret = register_driver(newNode->chardriver_name, param->char_ops, RWE_RW_RW, newNode);
338 if (ret) {
339 PRINT_ERR("register chardev partition error\n");
340 free(newNode->chardriver_name);
341 newNode->chardriver_name = NULL;
342 return ret;
343 }
344 } else {
345 newNode->chardriver_name = NULL;
346 }
347 return ENOERR;
348}
349///注销块设备驱动
351{
352 INT32 ret;
353
354 if (node->blockdriver_name != NULL) {
355 ret = unregister_blockdriver(node->blockdriver_name);
356 if (ret == -EBUSY) {
357 PRINT_ERR("unregister blkdev partition error:%d\n", ret);
358 return ret;
359 }
360 free(node->blockdriver_name);
361 node->blockdriver_name = NULL;
362 }
363 return ENOERR;
364}
365///注销字符设备驱动
367{
368 INT32 ret;
369
370 if (node->chardriver_name != NULL) {
371 ret = unregister_driver(node->chardriver_name);
372 if (ret == -EBUSY) {
373 PRINT_ERR("unregister chardev partition error:%d\n", ret);
374 return ret;
375 }
376 free(node->chardriver_name);//名称占用的内核空间,所以必须释放.
377 node->chardriver_name = NULL;
378 }
379
380 return ENOERR;
381}
382
383/*
384 * Attention: both startAddr and length should be aligned with block size.
385 * If not, the actual start address and length won't be what you expected.
386 *///注意:startAddr 和length 都应该与block size 对齐。如果不是,实际的起始地址和长度将不是你所期望的
387 /*
388add_mtd_partition函数有四个参数,
389 第一个参数表示介质,有“nand”和“spinor”两种,JFFS2分区在“spinor”上使用,而“nand”是提供给YAFFS2使用的。
390 第二个参数表示起始地址,
391 第三个参数表示分区大小,这两个参数都以16进制的形式传入。
392 最后一个参数表示分区号,有效值为0~19
393 */
395 UINT32 length, UINT32 partitionNum)
396{
397 INT32 ret;
398 mtd_partition *newNode = NULL;
399 partition_param *param = NULL;
400
401 if ((partitionNum >= CONFIG_MTD_PATTITION_NUM) || (type == NULL)) {
402 return -EINVAL;
403 }
404
406 if (ret != ENOERR) {
407 PRINT_ERR("%s %d, mutex lock failed, error:%d\n", __FUNCTION__, __LINE__, ret);
408 }
409
410 ret = MtdInitFsparParam(type, &param);//初始化 flash 分区参数
411 if (ret != ENOERR) {
412 goto ERROR_OUT;
413 }
414 //参数检查
415 ret = AddParamCheck(startAddr, param, partitionNum, length);
416 if (ret != ENOERR) {
417 goto ERROR_OUT;
418 }
419
420 newNode = (mtd_partition *)zalloc(sizeof(mtd_partition));//分配一个分区节点
421 if (newNode == NULL) {
423 return -ENOMEM;
424 }
425 //分区对齐
426 PAR_ASSIGNMENT(newNode, length, startAddr, partitionNum, param->flash_mtd, param->block_size);
427 //注册块设备驱动程序
428 ret = BlockDriverRegisterOperate(newNode, param, partitionNum);
429 if (ret) {
430 goto ERROR_OUT1;
431 }
432 //注册字符设备驱动程序
433 ret = CharDriverRegisterOperate(newNode, param, partitionNum);
434 if (ret) {
435 goto ERROR_OUT2;
436 }
437
438 LOS_ListTailInsert(&param->partition_head->node_info, &newNode->node_info);//挂到全局分区链表上
439 (VOID)LOS_MuxInit(&newNode->lock, NULL);//初始化锁,每个分区节点都有自己的互斥锁
440
442 if (ret != ENOERR) {
443 PRINT_ERR("%s %d, mutex unlock failed, error:%d\n", __FUNCTION__, __LINE__, ret);
444 }
445
446 return ENOERR;
447ERROR_OUT2:
448 (VOID)BlockDriverUnregister(newNode);
449ERROR_OUT1:
450 free(newNode);
451ERROR_OUT:
453 return ret;
454}
455///检查分区参数
456static INT32 DeleteParamCheck(UINT32 partitionNum,
457 const CHAR *type,
458 partition_param **param)
459{
460 if (strcmp(type, "nand") == 0) {
461 *param = g_nandPartParam;
462 } else if (strcmp(type, "spinor") == 0 || strcmp(type, "cfi-flash") == 0) {
463 *param = g_spinorPartParam;
464 } else {
465 PRINT_ERR("type error \n");
466 return -EINVAL;
467 }
468
469 if ((partitionNum >= CONFIG_MTD_PATTITION_NUM) ||
470 ((*param) == NULL) || ((*param)->flash_mtd == NULL)) {
471 return -EINVAL;
472 }
473 return ENOERR;
474}
475///删除分区驱动程序,注意每个分区的文件系统都可以不一样,驱动程序也都不同
477{
478 INT32 ret;
479
480 ret = BlockDriverUnregister(node);//注销块设备驱动程序
481 if (ret == -EBUSY) {
482 return ret;
483 }
484
485 ret = CharDriverUnregister(node);//注销字符设备驱动程序
486 if (ret == -EBUSY) {
487 return ret;
488 }
489
490 return ENOERR;
491}
492///获取分区链表节点
493static INT32 OsNodeGet(mtd_partition **node, UINT32 partitionNum, const partition_param *param)
494{ //遍历链表
495 LOS_DL_LIST_FOR_EACH_ENTRY(*node, &param->partition_head->node_info, mtd_partition, node_info) {
496 if ((*node)->patitionnum == partitionNum) {//找到分区ID
497 break;
498 }
499 }
500 if ((*node == NULL) || ((*node)->patitionnum != partitionNum) ||
501 ((*node)->mountpoint_name != NULL)) {
502 return -EINVAL;
503 }
504
505 return ENOERR;
506}
507///释放分区链表节点所占内存 sizeof(mtd_partition)
509{
510 (VOID)LOS_MuxDestroy(&node->lock);
511 LOS_ListDelete(&node->node_info);//将自己摘掉
512 (VOID)memset_s(node, sizeof(mtd_partition), 0, sizeof(mtd_partition));
513 free(node);
514 (VOID)FreeMtd(param->flash_mtd);//释放MTD
515 if (LOS_ListEmpty(&param->partition_head->node_info)) {//如果是最后一个
516 free(param->partition_head);//释放头节点内存
517 param->partition_head = NULL;
518 free(param);
519
520 if (MtdDeinitFsparParam(type) != ENOERR) {
521 return -EINVAL;
522 }
523 }
524 return ENOERR;
525}
526///删除MTD分区
528{
529 INT32 ret;
530 mtd_partition *node = NULL;
531 partition_param *param = NULL;
532
533 if (type == NULL) {
534 return -EINVAL;
535 }
536
538 if (ret != ENOERR) {
539 PRINT_ERR("%s %d, mutex lock failed, error:%d\n", __FUNCTION__, __LINE__, ret);
540 }
541
542 ret = DeleteParamCheck(partitionNum, type, &param);//删除操作时的参数检查
543 if (ret) {
544 PRINT_ERR("delete_mtd_partition param invalid\n");
546 return ret;
547 }
548
549 ret = OsNodeGet(&node, partitionNum, param);
550 if (ret) {
552 return ret;
553 }
554
555 ret = DeletePartitionUnregister(node);
556 if (ret) {
557 PRINT_ERR("DeletePartitionUnregister error:%d\n", ret);
559 return ret;
560 }
561
562 ret = OsResourceRelease(node, type, param);
563 if (ret) {
564 PRINT_ERR("DeletePartitionUnregister error:%d\n", ret);
566 return ret;
567 }
568
570 if (ret != ENOERR) {
571 PRINT_ERR("%s %d, mutex unlock failed, error:%d\n", __FUNCTION__, __LINE__, ret);
572 }
573 return ENOERR;
574}
575
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a node to the tail of a doubly linked list.
Definition: los_list.h:244
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
Definition: los_list.h:321
LITE_OS_SEC_TEXT UINT32 LOS_MuxInit(LosMux *mutex, const LosMuxAttr *attr)
初始化互斥锁
Definition: los_mux.c:262
LITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy(LosMux *mutex)
销毁互斥锁
Definition: los_mux.c:289
INT32 add_mtd_partition(const CHAR *type, UINT32 startAddr, UINT32 length, UINT32 partitionNum)
Add a partition.
INT32 delete_mtd_partition(UINT32 partitionNum, const CHAR *type)
删除MTD分区
__attribute__((aligned(MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS)))
Definition: los_arch_mmu.c:98
signed int INT32
Definition: los_typedef.h:60
long unsigned int UINT64
Definition: los_typedef.h:66
unsigned int UINT32
Definition: los_typedef.h:57
char CHAR
Definition: los_typedef.h:63
void * zalloc(size_t size)
Definition: malloc.c:91
void * malloc(size_t size)
动态分配内存块大小
Definition: malloc.c:81
void free(void *ptr)
释放ptr所指向的内存空间
Definition: malloc.c:66
void * GetMtd(const char *type)
int FreeMtd(struct MtdDev *mtd)
static VOID YaffsLockInit(VOID)
Definition: mtd_partition.c:64
static VOID MtdDeinitSpinorParam(VOID)
static partition_param * MtdInitSpinorParam(partition_param *spinorParam)
spi nor flash 参数初始化
static INT32 BlockDriverUnregister(mtd_partition *node)
注销块设备驱动
static INT32 DeleteParamCheck(UINT32 partitionNum, const CHAR *type, partition_param **param)
检查分区参数
static INT32 AddParamCheck(UINT32 startAddr, const partition_param *param, UINT32 partitionNum, UINT32 length)
增加MTD分区参数检查
static VOID MtdNandParamAssign(partition_param *nandParam, const struct MtdDev *nandMtd)
Definition: mtd_partition.c:92
static INT32 DeletePartitionUnregister(mtd_partition *node)
删除分区驱动程序,注意每个分区的文件系统都可以不一样,驱动程序也都不同
mtd_partition * GetSpinorPartitionHead(VOID)
Definition: mtd_partition.c:86
static VOID MtdNorParamAssign(partition_param *spinorParam, const struct MtdDev *spinorMtd)
nor flash 初始化,本函数只会被调用一次
static partition_param * MtdInitNandParam(partition_param *nandParam)
nand flash 初始化
pthread_mutex_t g_mtdPartitionLock
Definition: mtd_partition.c:48
static INT32 BlockDriverRegisterOperate(mtd_partition *newNode, const partition_param *param, UINT32 partitionNum)
注册块设备,此函数之后设备将支持VFS访问
static VOID MtdDeinitNandParam(VOID)
反初始化
static INT32 OsResourceRelease(mtd_partition *node, const CHAR *type, partition_param *param)
释放分区链表节点所占内存 sizeof(mtd_partition)
static INT32 CharDriverUnregister(mtd_partition *node)
注销字符设备驱动
partition_param * GetSpinorPartParam(VOID)
Definition: mtd_partition.c:81
static INT32 MtdInitFsparParam(const CHAR *type, partition_param **fsparParam)
根据 flash-type 来初始化分区的参数, Fspar 是不是 flash partition 的意思? 这名字取得有点费解 @note_thinking
static INT32 OsNodeGet(mtd_partition **node, UINT32 partitionNum, const partition_param *param)
获取分区链表节点
static INT32 MtdDeinitFsparParam(const CHAR *type)
根据flash-type 去初始化 分区的参数。
static INT32 CharDriverRegisterOperate(mtd_partition *newNode, const partition_param *param, UINT32 partitionNum)
注册字符设备,此函数之后设备将支持VFS访问
partition_param * GetNandPartParam(VOID)
struct mtd_node mtd_partition
通过mknod在/dev子目录下建立MTD块设备节点(主设备号为31)和MTD字符设备节点(主设备号为90)
int pthread_mutex_lock(pthread_mutex_t *mutex)
互斥锁加锁操作
int pthread_mutex_unlock(pthread_mutex_t *mutex)
解锁互斥锁
flash MTD 层 描述符
Definition: mtd_dev.h:76
UINT32 eraseSize
4K, 跟PAGE_CACHE_SIZE对应
Definition: mtd_dev.h:81
UINT32 type
Definition: mtd_dev.h:78
UINT64 size
Definition: mtd_dev.h:80
通过mknod在/dev子目录下建立MTD块设备节点(主设备号为31)和MTD字符设备节点(主设备号为90)
CHAR * blockdriver_name
块设备驱动名称 例如: /dev/spinorblk0p0
LosMux lock
每个分区都有自己的互斥锁
UINT32 patitionnum
分区编号
CHAR * chardriver_name
字符设备驱动名称 例如: /dev/nandchr0p2
UINT32 end_block
结束块索引
UINT32 start_block
开始块索引
LOS_DL_LIST node_info
双循环节点,挂在首个分区节点上
分区参数描述符,一个分区既可支持按块访问也可以支持按字符访问,只要有驱动程序就阔以
CHAR * blockname
块设备名称
const struct file_operations_vfs * char_ops
字符方式的操作数据
CHAR * charname
字符设备名称
mtd_partition * partition_head
首个分区,其他分区都挂在.node_info节点上
const struct block_operations * flash_ops
块方式的操作数据
struct MtdDev * flash_mtd
flash设备描述符,属于硬件驱动层
UINT32 block_size
块单位(4K),对文件系统而言是按块读取数据,方便和内存页置换