一般嵌入式系统都会通过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