linux MTD partitions方法大杂烩

一、总述

在linux中,我们一般会对flash进行一个分区,不同的地址空间存放不同的内容。一般我们只需要分3-4个区,第一个为boot区,一个为boot参数区(传递给内核的参数),一个为内核区,一个为文件系统区。而对于bootloader中只要能将内核下载到A~B区的A地址开始处就可以,C~D区的C起始地址下载文件系。这些起始地址在MTD的分区信息中能找到。所以bootloader对分区的概念不重要,只要它能把内核烧到A位置,把文件系统烧到C位置。所以,在bootloader对Flash进行操作时,哪块区域放什么是以内核为主。

但是在linux中如何来分区,分区的方式有几种呢?在网上可以看到好多关于这个问题的表述,这里我把各种说法整理一下,以方便学习.

一般在配置内核时我们会看到有三种方式:


linux MTD partitions方法大杂烩_第1张图片

1)、Redboot partition table parsing

2)、Kernel command-line partition table definition

3)、Board-specific mapping drivers

当然MTD还允许配置没有分区,在这种情况下,MTD简单地将整个闪存作为一个单一的设备访问。

下面就针对上面的三种方式来分别说明:

二、Redboot Partition Table Partitioning

首先说明redboot只是一个bootloader,不是什么一个奇怪的东东。从上面的标题也就可以明白,其实就是支持从redboot传来的分区参数信息了。一般我们不会用到redboot作为我们的bootloader,它大多用在ARM Xscale系统的平台上。redboot有多个命令可以用来创建和初始化各个分区。要内核中必须支持Redboot的FIS分区表
CONFIG_MTD_REDBOOT_PARTS=y
同时指定FIS分区表存放在flash倒数第几个block中
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2

同时使能 Device Drivers -> MTD ->RedBoot partition table parsing

如下是redboot启动时的输出信息:
Platform: ADI Coyote (XScale)
IDE/Parallel Port CPLD Version: 1.0
Copyright (C) 2000, 2001, 2002, Red Hat, Inc.

RAM: 0x00000000-0x04000000, 0x0001f960-0x03fd1000 available
FLASH: 0x50000000 - 0x51000000, 128 blocks of 0x00020000 bytes each.
...
我们可以看出,RAM是被映射到0x000000地址,flash被映射到物理地址0x50000000~0x51000000。同样也可以看到有128个block,每一个block是128kB
redboot探测分区信息的输出如下:
...
IXP4XX-Flash0: Found 1 x16 devices at 0x0 in 16-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 IXP4XX-Flash0 at offset 0xfe0000
3 RedBoot partitions found on MTD device IXP4XX-Flash0
Creating 3 MTD partitions on "IXP4XX-Flash0":
0x00000000-0x00060000: "RedBoot"
0x00fc0000-0x00fc1000: "RedBoot config"
0x00fe0000-0x01000000: "FIS directory"
...

第一句说明flash芯片已经探测到了它的一些信息也通过CFI读了出来。CFI是一个工业标准,可以在网上找一下相关的信息。这里我们要说明,如果我们的flash支持CFI我们必须使能MTD_CFI选项,只有这样,才可以成功的探测flash.

Redboot的启动脚本中传递命令行参数给内核如下:
使用exec -c 选项,例如:
fis load -d vmlinux
exec -c "console=ttyS0,115200 root=31:02 rootfstype=jffs2 mtdparts=ar7100-nor0:256k(boot),0x130000(kernel),0x600000(jffs2),-(config) init=/sbin/init"

三、Kernel Command Line Partitioning

利用内核cmdline来指定分区,是我们大家经常所用到的一种。如我们指定分区信息:
console=ttyS0,115200 root=31:02 rootfstype=jffs2 mtdparts=ar7100-nor0:256k(boot),0x130000(kernel),0x600000(jffs2),-(config) init=/sbin/init
这里指定root在MTD的第3个分区(31为MTD设备号,02表示第3个分区),rootfs的文件系统格式为jffs2,MTD分区为ar7100- nor0的Flash设
备,第一个分区为boot,大小为256k,第2个分区为kernel,大小为0x130000,第3个分区为jffs2文件系统,大小为 0x600000,剩下的为
config配置分区。
注意:指定这些分区大小时,要以Flash的block大小对齐,比如64k的Block大小就必须能被0x10000整除,否则内核启动后这些没有对
block对齐的分区将被限制为只读,以便擦除到别分区的内容。
需要打开内核编译选项:
CONFIG_MTD_CMDLINE_PARTS=y
也就是menuconfig中MTD下的“Command line partition table parsing ”

mtdparts的格式如下:
mtdparts=[; := :[,]
:= [@offset][][ro]
:= unique id used in mapping driver/device
:= standard linux memsize OR "-" to denote all remaining space
:= (NAME)
因此你在使用的时候需要按照下面的格式来设置:
mtdparts=mtd-id:@(),@()
这里面有几个必须要注意的:
a. mtd-id 必须要跟你当前平台的flash的mtd-id一致,不然整个mtdparts会失效 怎样获取到当前平台的flash的mtd-id?
在bootargs参数列表中可以指定当前flash的mtd-id,如指定 mtdids:nand0=gen_nand.1,前面的nand0则表示第一个flash
b. size在设置的时候可以为实际的size(xxM,xxk,xx),也可以为'-'这表示剩余的所有空间。
相关信息可以查看drivers/mtd/cmdlinepart.c中的注释找到相关描述。

四、Mapping Driver

而最后一种方法就是之前2410一直所用的方法,通过定义platform_device,同时定义它的parttition信息来分区flash。同时在 .../drivers/mtd/maps .这个目录下,我们也可以看到很多关于这种方法的例子。但是不同的平台,实现的具体细节有点不同、
.../drivers/mtd/maps/pq2fads.c
static struct mtd_partition pq2fads_partitions[] = {
       {
#ifdef CONFIG_ADS8272
             .name      = "HRCW",
             .size      = 0x40000,
             .offset      = 0,
             .mask_flags= MTD_WRITEABLE,  /* force read-only */
     }, {
            .name       = "User FS",
            .size       = 0x5c0000,
            .offset       = 0x40000,
#else
            .name       = "User FS",
            .size       = 0x600000,
            .offset       = 0,
#endif
     }, {
            .name       = "uImage",
            .size       = 0x100000,
            .offset       = 0x600000,
            .mask_flags = MTD_WRITEABLE,  /* force read-only */
     }, {
            .name       = "bootloader",
            .size       = 0x40000,
            .offset     = 0x700000,
            .mask_flags = MTD_WRITEABLE,  /* force read-only */
     }, {
            .name       = "bootloader env",
            .size       = 0x40000,
            .offset            = 0x740000,
            .mask_flags = MTD_WRITEABLE,  /* force read-only */
     }
};
/* pointer to MPC885ADS board info data */
extern unsigned char __res[];

static int __init init_pq2fads_mtd(void)
{
      bd_t *bd = (bd_t *)__res;
      physmap_configure(bd->bi_flashstart, bd->bi_flashsize,
                        PQ2FADS_BANK_WIDTH, NULL);

      physmap_set_partitions(pq2fads_partitions,
                       sizeof (pq2fads_partitions) /
                       sizeof (pq2fads_partitions[0]));
       return 0;
}

static void __exit cleanup_pq2fads_mtd(void)
{
}
module_init(init_pq2fads_mtd);
module_exit(cleanup_pq2fads_mtd);
有时mtd_partition不是定义在mtd driver下,而是在arch/arm/下相关的平台文件中。与下面的信息在同一个文件中:
static struct flash_platform_data coyote_flash_data = {
      .map_name  = "cfi_probe",
      .width     = 2,
};

static struct resource coyote_flash_resource = {
      .start             = COYOTE_FLASH_BASE,
      .end             = COYOTE_FLASH_BASE + COYOTE_FLASH_SIZE - 1,
      .flags             = IORESOURCE_MEM,
};

static struct platform_device coyote_flash = {
      .name        = "IXP4XX-Flash",//这个name一定上与上面的/drivers/mtd/maps/pq2fads.c中platform_driver的name一致
      .id          = 0,
      .dev         = {
             .platform_data = &coyote_flash_data,
      },
      .num_resources       = 1,
      .resource   = &coyote_flash_resource,
};

...

static struct platform_device *coyote_devices[] __initdata = {
       &coyote_flash,
       &coyote_uart
};

static void __init coyote_init(void)
{
      ...

      platform_add_devices(coyote_devices,
                               ARRAY_SIZE(coyote_devices));
}
...

 
   


你可能感兴趣的:(linux,uboot,linux内核分析)