nand对flashlayout的解析

2019-07-14 08:39发布

一般嵌入式系统都会通过uboot或者lk将flashlayout的信息传递给kernel,kernel拿到这些flashlayout的信息后,将对应的每个partition mount成block device.
我们看看kernel这边的实现.
drivers/mtd/cmdlinepart.c
376 static int __init mtdpart_setup(char *s)
377 {
378         cmdline = s;
379         return 1;
380 }
381 
382 __setup("mtdparts=", mtdpart_setup);
可见uboot 那边传过来的flashlayout信息要以mtdparts开头,mtdpart_setup 只是将flashlayout的信息保存在cmdline 中.
这个函数被module_init调用的。
389 static int __init cmdline_parser_init(void)
390 {
391         if (mtdparts)
392                 mtdpart_setup(mtdparts);
393         register_mtd_parser(&cmdline_parser);
394         return 0;
395 }
其中391行mtdparts 是模块的参数,一般为null
 module_param(mtdparts, charp, 0);


所以这个函数就仅仅调用register_mtd_parser
740 int register_mtd_parser(struct mtd_part_parser *p, struct module *owner)
741 {
742         p->owner = owner;
743 
744         if (!p->cleanup)
745                 p->cleanup = &mtd_part_parser_cleanup_default;
746 
747         spin_lock(&part_parser_lock);
748         list_add(&p->list, &part_parsers);
749         spin_unlock(&part_parser_lock);
750 
751         return 0;
752 }
这个函数就是将cmdline_parser 添加到part_parsers 这个list中,这说明系统可以存在多个parse,由用户自己选择用哪个
384 static struct mtd_part_parser cmdline_parser = {
385         .parse_fn = parse_cmdline_partitions,
386         .name = "cmdlinepart",
387 };


我们在看看用户是如果选择parse的?
arch/mips/cavium-octeon/flash_setup.c
 22 static const char *part_probe_types[] = {
 23         "cmdlinepart",
 24 #ifdef CONFIG_MTD_REDBOOT_PARTS
 25         "RedBoot",
 26 #endif
 27         NULL
 28 };
 70 static int octeon_flash_probe(struct platform_device *pdev)
 71 {
110                 if (mymtd) {
111                         mymtd->owner = THIS_MODULE;
112                         mtd_device_parse_register(mymtd, part_probe_types,
113                                                   NULL, NULL, 0);
114                 } else {
115                         pr_err("Failed to register MTD device for flash ");
116                 }
117         }
118         return 0;
119 }
我们这个例子中是调用mtd_device_parse_register,而part_probe_types就是cmdlinepart。
794 int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
795                          struct mtd_partitions *pparts,
796                          struct mtd_part_parser_data *data)
797 {
798         struct mtd_part_parser *parser;
799         int ret, err = 0;
800 
801         if (!types)
802                 types = default_mtd_part_types;
803 
804         for ( ; *types; types++) {
805                 pr_debug("%s: parsing partitions %s ", master->name, *types);
806                 parser = mtd_part_parser_get(*types);
807                 if (!parser && !request_module("%s", *types))
808                         parser = mtd_part_parser_get(*types);
809                 pr_debug("%s: got parser %s ", master->name,
810                          parser ? parser->name : NULL);
811                 if (!parser)
812                         continue;
813                 ret = (*parser->parse_fn)(master, &pparts->parts, data);
814                 pr_debug("%s: parser %s: %i ",
815                          master->name, parser->name, ret);
816                 if (ret > 0) {
817                         printk(KERN_NOTICE "%d %s partitions found on MTD device %s ",
818                                ret, parser->name, master->name);
819                         pparts->nr_parts = ret;
820                         pparts->parser = parser;
821                         return 0;
822                 }
823                 mtd_part_parser_put(parser);
824                 /*
825                  * Stash the first error we see; only report it if no parser
826                  * succeeds
827                  */
828                 if (ret < 0 && !err)
829                         err = ret;
830         }
831         return err;
832 }
可知这个函数的813行会调用会调用cmdlineparts的parse_cmdline_partitions 函数来parse flashlayout