linux MTD partitions方法大雜燴

一、總述

在linux中,我們一般會對flash進行一個分區,不同的地址空間存放不同的內容。一般我們只需要分3-4個區,第一個爲boot區,一個爲boot參數區(傳遞給內核的參數),一個爲內核區,一個爲文件系統區。而對於bootloader中只要能將內核下載到A~B區的A地址開始處就可以,C~D區的C起始地址下載文件系。這些起始地址在MTD的分區信息中能找到。所以bootloader對分區的概念不重要,只要它能把內核燒到A位置,把文件系統燒到C位置。所以,在bootloader對Flash進行操作時,哪塊區域放什麼是以內核爲主。

但是在linux中如何來分區,分區的方式有幾種呢?在網上可以看到好多關於這個問題的表述,這裏我把各種說法整理一下,以方便學習.

一般在配置內核時我們會看到有三種方式:



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=<mtddef>[;<mtddef]
<mtddef> := <mtd-id>:<partdef>[,<partdef>]
<partdef> := <size>[@offset][<name>][ro]
<mtd-id> := unique id used in mapping driver/device
<size> := standard linux memsize OR "-" to denote all remaining space
<name> := (NAME)
因此你在使用的時候需要按照下面的格式來設置:
mtdparts=mtd-id:<size1>@<offset1>(<name1>),<size2>@<offset2>(<name2>)
這裏面有幾個必須要注意的:
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));
}
...


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章