what is linux mtd

青灯夜游
青灯夜游Original
2022-05-11 17:22:484688browse

In Linux, mtd refers to "memory technology device" and is a subsystem in the storage device. The MTD system was introduced into Linux to provide a unified interface for NOR FLASH and NAND FLASH devices. MTD devices can usually be divided into four layers: device node, MTD device layer, MTD original device layer, and hardware driver layer.

what is linux mtd

#The operating environment of this tutorial: linux5.9.8 system, Dell G3 computer.

What is Linux MTD?

MTD stands for "Memory Technology Device", which means "memory technology device" and is a subsystem of Linux storage devices.

In the Linux kernel, the MTD layer is introduced to provide a unified interface for NOR FLASH and NAND FLASH devices. MTD isolates the file system from the underlying FLASH memory.

The purpose of designing this MTD system is to provide an abstraction layer and an interface for memory-type devices, so that hardware driver designers only need to provide the simplest underlying hardware devices. The read/write/erase function is enough. How the data is represented to upper-level users does not matter, because the MTD storage device subsystem has done it for you.

MTD framework

The MTD device of Linux is located under drivers/mtd/.

The content under the MTD file is as follows:

what is linux mtd

MTD equipment can usually be divided into four layers

From top to bottom are: device nodes , MTD device layer, MTD original device layer and hardware driver layer.

what is linux mtd

1.cmdlinepart.c

When the mtd partition table is transmitted to linux by u-boot through the cmd parameter, the linux kernel can There is no need to register and add mtdparts. You only need to turn on the command line partition option in MTD. To use this method, u-boot needs to support MTD, and the transmitted mtd partition parameters must meet the format requirements.

2.devices folder

When we have a spi flash device and want to use mtd to manage it, we usually put it under the devices folder. For example, m25p80.c under the devices folder is a typical spi flash device.

3.chips/nand/onenand folder

nand flash driver is under the nand folder;

onenand flash driver is under the onenand folder ;

nor flash is relatively complicated, and it will be found in the following files:

chips:cfi/jedec interface universal driver

devices:nor flash bottom driver (spi flash)

maps:nor flash mapping relationship related functions

4. Core file

mtdchar.c: MTD character device interface related implementation, device number 31 ;

mtdblock.c: MTD block device interface related implementation, device number 90,;

mtdcore.c: MTD original device interface related implementation;

mtdpart.c: MTD partition interface related implementation.

5.ubi

The support layer of ubifs files. When using ubifs file system, you need to change Device Drivers -> Memory Technology Device (MTD) support -> ; Enable UBI in UBI -Unsorted block image is selected.

Select UBIFS file system support in File systems -> Miscellaneous filesystems.

Implementation of MTD partition table

During the boot process, you can often see information similar to the following from the console,

0x000000000000-0x000000100000 : "Bootloade"
0x000000100000-0x000002000000 : "Kernel"
0x000002000000-0x000003000000 : "User"
0x000003000000-0x000008000000 : "File System"

This is the most intuitive representation that MTD gives us, showing us the partition structure of each module in the memory, but how are these partitions implemented? There are several ways to implement the partition table, which are explained below:

Note: The prerequisite for the partition table implementation is that the MTD device driver has been successful, otherwise there will be no partition to talk about even if the driver is not successful. .

1. Adding to the kernel

Adding to the kernel is a frequently used method and should be found in any driver transplantation book. , the main thing is to add mtd_partition in the platform device, add information similar to the following, there will be no more description here

struct mtd_partition s3c_nand_part[] = {
    {
        .name       = "Bootloader",
        .offset     = 0,
        .size       = (1 * SZ_1M),
        .mask_flags = MTD_CAP_NANDFLASH,
    },
    {
        .name       = "Kernel",
        .offset     = (1 * SZ_1M),
        .size       = (31 * SZ_1M) ,
        .mask_flags = MTD_CAP_NANDFLASH,
    },
    {
        .name       = "User",
        .offset     = (32 * SZ_1M),
        .size       = (16 * SZ_1M) ,
    },
    {
        .name       = "File System",
        .offset     = (48 * SZ_1M),
        .size       = (96 * SZ_1M),
    }
};

static struct s3c_nand_set s3c_nand_sets[] = {
    [0] = {
        .name       = "nand",
        .nr_chips   = 1,
        .nr_partitions  = ARRAY_SIZE(s3c_nand_part),
        .partitions = ok6410_nand_part,
    },
};

static struct s3c_platform_nand s3c_nand_info = {
    .tacls      = 25,
    .twrph0     = 55,
    .twrph1     = 40,
    .nr_sets    = ARRAY_SIZE(s3c_nand_sets),
    .sets       = ok6410_nand_sets,
};

static void __init s3c_machine_init(void)
{
    s3c_nand_set_platdata(&s3c_nand_info); 
}

Because our MTD driver has been completed, when the device and driver match, the probe in the driver will be called Interface function, we need to call add_mtd_partitions(s3c_mtd, sets->partitions, sets->nr_partitions); in the probe function to add the partition table.

2.u-boot parameter transfer

Under u-boot, you can add mtdparts information to bootargs. After u-boot starts, the information in bootargs will be Sent to the kernel, the kernel will parse the mtdparts part of bootargs when it starts. Here is an example:

mtdparts=nand.0:1M(Bootloader)ro,31M(Kernel)ro ,16M(User),96M(File System), for more specific mtdparts format, you can check the relevant information.

In order for the kernel to parse mtdparts information, we need to enable the Device Drivers -> Memory Technology Device (MTD) support ->Command line partition table parsing option in the kernel, as mentioned above.

在内核中添加分区表的时候,我们是在平台设备里面加入mtd_partition信息。这边通过u-boot传参则取消平台设备里面的partition信息,那我们需要怎样解析u-boot的传过来的mtdparts呢。

u-boot传参过来后,cmdlinepart.c中会将这些参数解析好,存在里面LIST_HEAD(part_parsers)链表里面,然后我们在驱动的probe函数中,通过调用mtd_device_parse_register(mtd, probe_types,&ppdata, NULL, 0);函数。

mtd_device_parse_register()函数位于drivers/mtd/mtdcore.c 中,内容如下:

int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
                  struct mtd_part_parser_data *parser_data,
                  const struct mtd_partition *parts,
                  int nr_parts)
{
    int err;
    struct mtd_partition *real_parts;

    err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
    if (err <= 0 && nr_parts && parts) {
        real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
                     GFP_KERNEL);
        if (!real_parts)
            err = -ENOMEM;
        else
            err = nr_parts;
    }

    if (err > 0) {
        err = add_mtd_partitions(mtd, real_parts, err);
        kfree(real_parts);
    } else if (err == 0) {
        err = add_mtd_device(mtd);
        if (err == 1)
            err = -ENODEV;
    }

    return err;
}

可以看到该函数会先执行parse_mtd_partitions(mtd, types, &real_parts, parser_data);函数,后面还是通过add_mtd_partitions()函数来实现分区表的添加。

parse_mtd_partitions()函数位于drivers/mtd/mtdpart.c中,内容如下:

int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
             struct mtd_partition **pparts,
             struct mtd_part_parser_data *data)
{
    struct mtd_part_parser *parser;
    int ret = 0;

    if (!types)
        types = default_mtd_part_types;

    for ( ; ret <= 0 && *types; types++) {
        parser = get_partition_parser(*types);
        if (!parser && !request_module("%s", *types))
            parser = get_partition_parser(*types);
        if (!parser)
            continue;
        ret = (*parser->parse_fn)(master, pparts, data);
        put_partition_parser(parser);
        if (ret > 0) {
            printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
                   ret, parser->name, master->name);
            break;
        }
    }
    return ret;
}

进入parse_mtd_partitions()函数会先判断types的类型,如果为空则给默认值,types的类型一般就两种,如下:

static const char * const default_mtd_part_types[] = {
    "cmdlinepart",
    "ofpart",
    NULL
};

第一个"cmdlinepart"即u-boot传参的方式,第二个"ofpart"即下面要讲到的使用dts传参的方式,判断完类型后,就通过get_partition_parser去解析part_parsers链表里面的数据,这样就完成u-boot参数的解析。

3.dts传参

在Linux3.14以后的linux版本中,加入一个新的知识DTS(Device tree),dts其实就是为了解决ARM Linux中的冗余代码,在Linux2.6版本的arch/arm/plat.xxx和arch/arm/mach.xxx中充斥着大量的垃圾代码,采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码,关于dts可以自行查阅资料。

dts传参的原理其实和u-boot一样,区别在于:u-boot的时候是通过cmdlinepart.c文件实现分区信息写入LIST_HEAD(part_parsers)链表,dts则是用过ofpart.c文件实现分区信息写入LIST_HEAD(part_parsers)链表,所以同样要把ofpart.c文件的宏打开,在调用mtd_device_parse_register(mtd, probe_types,&ppdata, NULL, 0);函数的时候types要设置成ofpart。

如果去对比Linux2.6版本和Linux3.14版本,会发现drivers/mtd/ofpart.c和drivers/mtd/mtdpart.c文件有所不同,Linux3.8版本里面多了Device tree这一部分的内容,感兴趣的可以自己深究下。

这边举个dts的例子:

 pinctrl-0 = <&s3c_nand_flash>;
    ranges = <0 0 0x000000000000 0x000008000000>;   /* CS0: NAND */
    nand@0,0 {
        partition@1 {
            label = "Bootloader";
            reg = <0x000000000000 0x000000100000>;
        };
        partition@2 {
            label = "Kernel";
            reg = <0x000000100000 0x000002000000>;
        };
        partition@3 {
            label = "User";
            reg = <0x000002000000 0x000003000000>;
        };
        partition@4 {
            label = "File System";
            reg = <0x000003000000 0x000008000000>;
        };
    };

Linux mtd system的分析就到这边,有感悟时会持续会更新。

相关推荐:《Linux视频教程

The above is the detailed content of what is linux mtd. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn