如下为kernel打印的log信息:
physmap platform flash device: 02000000 at 60000000
physmap-flash.0: Found 2 x16 devices at 0x0 in 32-bit bank
Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
cfi_cmdset_0001: Erase suspend on write enabled
Searching for RedBoot partition table in physmap-flash.0 at offset 0x1fc0000
5 RedBoot partitions found on MTD device physmap-flash.0
Creating 5 MTD partitions on "physmap-flash.0":
0x000000000000-0x000000040000 : "RedBoot"
0x000000040000-0x000000600000 : "ramdisk"
0x000000600000-0x000000700000 : "zImage"
0x000001f80000-0x000001f81000 : "RedBoot config"
文件:drivers/mtd/redboot.c
module_init(redboot_parser_init);
static struct mtd_part_parser redboot_parser = {
.owner = THIS_MODULE,
.parse_fn = parse_redboot_partitions, // 该函数将打印上面的log信息
.name = "RedBoot",
};
static int __init redboot_parser_init(void)
{
return register_mtd_parser(&redboot_parser);
}
调用register_mtd_parser注册本parser解释器
文件:drivers/mtd/mtdpart.c
static LIST_HEAD(part_parsers);
int register_mtd_parser(struct mtd_part_parser *p)
{
spin_lock(&part_parser_lock);
list_add(&p->list, &part_parsers); // 将redboot_parser解释器追加到part_parsers解释器链表上[luther.gliethttp]
spin_unlock(&part_parser_lock);
return 0;
}
那part_parsers解释器链表上注册的众多mtd分区解释器什么时候被引用呢,以及通过什么接口被引用呢,
答案是:parse_mtd_partitions
来看看,首先是接口get_partition_parser(parser_name),它会根据传进的parser_name参数,
返回part_parsers解释器链表上名为parser_name的解释器,我们这里当然查询的是名为"RedBoot"的redboot_parser解释器了[luther.gliethttp]
static struct mtd_part_parser *get_partition_parser(const char *name)
{
struct mtd_part_parser *p, *ret = NULL;
spin_lock(&part_parser_lock);
list_for_each_entry(p, &part_parsers, list)
if (!strcmp(p->name, name) && try_module_get(p->owner)) {
ret = p;
break;
}
spin_unlock(&part_parser_lock);
return ret;
}
int parse_mtd_partitions(struct mtd_info *master, const char **types,
struct mtd_partition **pparts, unsigned long origin)
{
struct mtd_part_parser *parser;
int ret = 0;
for ( ; ret <= 0 && *types; types++) {
parser = get_partition_parser(*types); // *types等于"RedBoot",返回redboot_parser
if (!parser && !request_module("%s", *types))
parser = get_partition_parser(*types);
if (!parser) {
printk(KERN_NOTICE "%s partition parsing not available\n",
*types);
continue;
}
ret = (*parser->parse_fn)(master, pparts, origin); // 执行parse_redboot_partitions
if (ret > 0) {
printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
ret, parser->name, master->name);
}
put_partition_parser(parser);
}
return ret;
}
EXPORT_SYMBOL_GPL(parse_mtd_partitions); // 导出,以供其他驱动调用该函数
对于2.6.30.4内核支持的ep9312开发板设备注册[luther.gliethttp].
可以先参考
浅析开发板相关函数init_machine即edb9312_init_machine什么时候执行文件:arch/arm/mach-ep93xx/edb9312.c
static struct physmap_flash_data edb9312_flash_data = {
.width = 4,
};
#define EP93XX_CS6_PHYS_BASE 0x60000000
#define SZ_32M 0x02000000
static struct resource edb9312_flash_resource = {
.start = EP93XX_CS6_PHYS_BASE, // 物理起始地址0x60000000
.end = EP93XX_CS6_PHYS_BASE + SZ_32M - 1, // nor flash大小32M
.flags = IORESOURCE_MEM,
};
static struct platform_device edb9312_flash = {
.name = "physmap-flash", // 将由同名的"physmap-flash"驱动程序physmap_flash_driver管理[luther.gliethttp].
.id = 0,
.dev = {
.platform_data = &edb9312_flash_data,
},
.num_resources = 1,
.resource = &edb9312_flash_resource,
};
static void __init edb9312_init_machine(void)
{
ep93xx_init_devices();
platform_device_register(&edb9312_flash);
ep93xx_register_eth(&edb9312_eth_data, 1);
}
MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
/* Maintainer: Toufeeq Hussain
*/
.phys_io = EP93XX_APB_PHYS_BASE,
.io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
.init_machine = edb9312_init_machine,
MACHINE_END
对于2.6.30.4内核支持的ep9312开发板驱动接管设备[luther.gliethttp].
文件:drivers/mtd/maps/physmap.c
static struct platform_driver physmap_flash_driver = {
.probe = physmap_flash_probe,
.remove = physmap_flash_remove,
.suspend = physmap_flash_suspend,
.resume = physmap_flash_resume,
.shutdown = physmap_flash_shutdown,
.driver = {
.name = "physmap-flash",
.owner = THIS_MODULE,
},
};
static int __init physmap_init(void)
{
int err;
err = platform_driver_register(&physmap_flash_driver); // 名为"physmap-flash"的flash设备将使用该驱动[luther.gliethttp].
#ifdef CONFIG_MTD_PHYSMAP_COMPAT
if (err == 0)
platform_device_register(&physmap_flash);
#endif
return err;
}
module_init(physmap_init);
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };// 使用RedBoot解释器redboot_parser
#endif
static int physmap_flash_probe(struct platform_device *dev)
{
for (i = 0; i < dev->num_resources; i++) {
printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
(unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1),
(unsigned long long)dev->resource[i].start);
......
}
#ifdef CONFIG_MTD_PARTITIONS
err = parse_mtd_partitions(info->cmtd, part_probe_types,// 寻找名为"RedBoot"的mtd分区parser解释器,然后执行它解释分区[luther.gliethttp].
&info->parts, 0);
if (err > 0) {
add_mtd_partitions(info->cmtd, info->parts, err); // 这样/proc/mtd下面就可以读到redboot烧写的分区了.
info->nr_parts = err;
return 0;
}
if (physmap_data->nr_parts) {
printk(KERN_NOTICE "Using physmap partition information\n");
add_mtd_partitions(info->cmtd, physmap_data->parts,
physmap_data->nr_parts);
return 0;
}
#endif
add_mtd_device(info->cmtd);
return 0;
}