Create Jffs2 for Linux Kernel 2.6

工作前准备:

1.构建交叉编译环境:请参考其它文章,建议读者直接从网上down一个已经做好的cross或者用eldk编译一个cross,在现在这个讲效率的时代,我想我们应该搞清楚重点,毕竟我们的重点工作并不是制作环境变量,而是系统构建。

2.Jffs2文件映像制作:

编译安装mtd-utils工具,用于jffs2映像制作。

如果要把ramdisk作为根文件系统,请参考另一篇文章的讲解。假设你已经

做好的你的文件系统,包括命令,库,设备文件等等。就可以使用mkfs.jffs2进行jffs2文件格式制作了。为了你的查阅方便我这里列出mkfs.jffs2常用的命令参数:

-p, --pad[=SIZE]        16進制來表示所要輸出檔案的大小,也就是root.jffs2size

                                       很重要的是, 為了不浪費flash空間, 這個值最好符合flash driver所規劃的區塊大小。

                                       如果不足则使用0xff来填充补满。

-r, -d, --root=DIR      指定要做成image的源資料夾.(默认:当前文件夹)

-s, --pagesize=SIZE     节点页大小(默认: 4KiB)

-e, --eraseblock=SIZE   设定擦除块的大小为(默认: 64KiB)

-c, --cleanmarker=SIZE Size of cleanmarker (default 12)

-m, --compr-mode=MODE   Select compression mode (default: priortiry)

-x, --disable-compressor=COMPRESSOR_NAME

                          Disable a compressor

-X, --enable-compressor=COMPRESSOR_NAME

                          Enable a compressor

-y, --compressor-priority=PRIORITY:COMPRESSOR_NAME

                          Set the priority of a compressor

-L, --list-compressors Show the list of the avaiable compressors

-t, --test-compression Call decompress and compare with the original (for test)

-n, --no-cleanmarkers   指明不添加清楚标记(nand flash 有自己的校检块,存放相关的信息。)

                          如果挂载后会出现类似:

                          CLEANMARKER node found at 0x0042c000 has totlen 0xc != normal 0x0

                          的警告,则加上-n 就会消失。

-o, --output=FILE       指定輸出image檔案的文件名.(default: stdout)

-l, --little-endian     指定使用小端格式

-b, --big-endian        指定使用大端格式

-D, --devtable=FILE     Use the named FILE as a device table file

-f, --faketime          Change all file times to '0' for regression testing

-q, --squash            Squash permissions and owners making all files be owned by root

-U, --squash-uids       将所有文件的拥有者设为root用户

-P, --squash-perms      Squash permissions on all files

      --with-xattr        stuff all xattr entries into image

      --with-selinux      stuff only SELinux Labels into jffs2 image

      --with-posix-acl    stuff only POSIX ACL entries into jffs2 image

-h, --help              显示这些文字

-v, --verbose           Verbose operation

-V, --version           显示版本

-i, --incremental=FILE Parse FILE and generate appendage output for it

 

 

制作好的jffs2.img,我们就可以在uboot中直接cp.b到相应的分区中了。

Protect off all

Erase 0x10340000(jffs2文件分区起始地址) 0x103fffffjffs2文件分区结束地址)

Tftp 0x20000000(下载jffs2.img映像到ram中) jffs2.img

Cp.b 0x20000000 0x10340000 0xdc(将刚才下载到ram jffs2映像写入到flash相应分区中,0xdcjffs2的大小)

Protect on all

 

 

3. 创建相应的/dev设备文件

# mknod -m 666 mtd0 c 90 0
# mknod -m 666 mtd1 c 90 2
# mknod -m 666 mtd2 c 90 4
# mknod -m 666 mtd3 c 90 6
# mknod -m 666 mtd4 c 90 8
# mknod -m 666 mtd5 c 90 10

 

# mknod -m 666 mtdblock0 b 31 0
# mknod -m 666 mtdblock1 b 31 1
# mknod -m 666 mtdblock2 b 31 2
# mknod -m 666 mtdblock3 b 31 3
# mknod -m 666 mtdblock4 b 31 4
# mknod -m 666 mtdblock5 b 31 5

这里有可能只需要后面一部分,视具体内核驱动代码而定。如果我们使用mdev 或者devfs进行设备文件创建的话,就不必进行设备创建了,但是让我很恼火的是mdev创建了众多的文件,让我的ram难的承受,(更确切的讲,应该是让我很难承受),如果你也无法接受的话,你可以手动创建必要文件。

这里如果要用mdev自动创建设备文件的话,我们需要在我们的启动脚本里做出如下动作:

/sbin/init ->/etc/inittab->/etc/init.d/rcS (自定义)

rcS中我们添加如下命令:

#!/bin/sh

mount -a

mkdir /dev/pts

mount -t devpts devpts /dev/pts

echo /sbin/mdev > /proc/sys/kernel/hotplug

mdev -s

 

#mount -t jffs2 /dev/mtdblock5 /mnt/

 

 

当然这里执行了mount -a自然要转向/etc/fstab中执行挂载命令:

fstab中的内容如下(当然你也可以选择你需要的文件系统进行挂载):

tmpfs                   /dev/shm                tmpfs   defaults        0 0

devpts                  /dev/pts                devpts  gid=5,mode=620  0 0

sysfs                   /sys                    sysfs   defaults        0 0

proc                    /proc                   proc    defaults        0 0

 

 

 

4.如果系统启动停止在uncompress ramdisk处就说明init进程没有正常启动,可能是busybox编译生成的/sbin/init文件不对或者其它问题。

5.还需要要注意的是init=linuxrcram0的区别。

6.下面我们参考 一位网友的文章 进行实际移植操作:

 

1)构建配置选项

首先,由于kernel2.6的数据结构关系复杂,这里我们只需要照着例子做就行了,选择一个比较相似的驱动文件,根据edb7312.c构建自己的mtd分区表驱动。

$cd drivers/mtd/maps/
$cp edb7312.c at91rm9200.c


然后,修改Kconfig,增加自己的配置选项。

//拷贝EDB7312稍作修改即可
config MTD_AT91RM9200
tristate "CFI Flash device mapped on AT91RM9200"
depends on ARM && MTD_CFI
help
This enables access to the CFI Flash on the ATMEL AT91RM9200DK board.
If you have such a board, say 'Y' here.


最后,修改Makefile,增加编译项目。

obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_AT91RM9200) += at91rm9200.o


这里的at91rm9200.o来源于以下源文件at91rm9200.c,这样,自己建立的MTD分区表驱动就可以编译进内核了。



因为第一步的工作中,at91rm9200.c实际上还是edb7312.c的内容,所以需要根据自己的开发板nor flash的配置做一下修改。

/*

 * $Id: physmap.c,v 0.1.0 2009/05/15 09:14:50 mag Exp $

 *

 * Normal mappings of chips in physical memory

 */

/**************************************************

*     Add for Olp by guohui luo 2009/5/15

*

***************************************************/

 

#include <linux/module.h>

#include <linux/types.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <asm/io.h>

#include <linux/mtd/mtd.h>

#include <linux/mtd/map.h>

 

#ifdef CONFIG_MTD_PARTITIONS

#include <linux/mtd/partitions.h>

#endif

 

#define WINDOW_ADDR 0x10000000      /* physical properties of flash */

#define WINDOW_SIZE 0x00400000

#define BUSWIDTH    2

/*

#define FLASH_BLOCKSIZE_MAIN    0x20000

#define FLASH_NUMBLOCKS_MAIN 128

*/

/* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */

#define PROBETYPES { "cfi_probe", NULL }

 

#define MSG_PREFIX "AT91RM9200-NOR:"   /* prefix for our printk()'s */

#define MTDID      "at91rm9200-%d"    /* for mtdparts= partitioning */

 

static struct mtd_info *mymtd;

 

struct map_info at91rm9200nor_map = {

       .name = "NOR flash on AT91RM9200DK",

       .size = WINDOW_SIZE,

       .bankwidth = BUSWIDTH,

       .phys = WINDOW_ADDR,

};

 

#ifdef CONFIG_MTD_PARTITIONS

 

/*

 * MTD partitioning stuff

 */

static struct mtd_partition at91rm9200nor_partitions[6] =

{

       {/*1*/

              .name = "Boot for AT9200",/* boot for uboot */

             .size = 0x00020000,/*  1*128KB */

            .offset = 0x00000000

       },

       {/*2*/

              .name = "U-Boot",/* U-Boot firmware */

             .size = 0x00020000,/*  1*128KB */

             .offset = 0x00020000

       },

       {/*3*/

              .name = "Environment", /* default env */

              .size = 0x00020000, /* 1*128kb */

              .offset = 0x00040000

       },

       {/*4*/

              .name = "Linux Kernel", /* default kernel image */

              .size = 0x00100000, /*8x128k=640k*/

              .offset = 0x00060000         

       },

       {/*5*/

              .name = " rootfs ramdisk",    /* default root filesystem */

              //.size = 0x002c0000,/*22*128KB=2816KB*/

              .size = 0x001e0000,/*15*128kb=2304kb*/

              .offset = 0x00160000 

       },

       {/*6*/

              .name = "Jffs2",     /* writen filesystem */

              //.size = 0x00040000,/* 2*128KB=256KB */

              //.offset = 0x003c0000,      

              .size = 0x000c0000,/*6*128k=768k*/

              .offset = 0x00340000

       }

};

 

//static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };

static const char *probes[] = { NULL };

 

#endif

 

static int                   mtd_parts_nb = 0;

static struct mtd_partition *mtd_parts    = 0;

 

int __init init_at91rm9200nor(void)

{

       static const char *rom_probe_types[] = PROBETYPES;

       const char **type;

       const char *part_type = 0;

 

         printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x/n",

              WINDOW_SIZE, WINDOW_ADDR);

       at91rm9200nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);

 

       if (!at91rm9200nor_map.virt) {

              printk(MSG_PREFIX "failed to ioremap/n");

              return -EIO;

       }

 

       simple_map_init(&at91rm9200nor_map);

 

       mymtd = 0;

       type = rom_probe_types;

       for(; !mymtd && *type; type++) {

              mymtd = do_map_probe(*type, &at91rm9200nor_map);

       }

       if (mymtd) {

              mymtd->owner = THIS_MODULE;

 

#ifdef CONFIG_MTD_PARTITIONS

              mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);

              if (mtd_parts_nb > 0)

                part_type = "detected";

 

              if (mtd_parts_nb == 0)

              {

                     mtd_parts = at91rm9200nor_partitions;

                     mtd_parts_nb = ARRAY_SIZE(at91rm9200nor_partitions);

                     part_type = "static";

              }

#endif

              add_mtd_device(mymtd);

              if (mtd_parts_nb == 0)

                printk(KERN_NOTICE MSG_PREFIX "no partition info available/n");

              else

              {

                     printk(KERN_NOTICE MSG_PREFIX

                            "using %s partition definition/n", part_type);

                     add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb);

              }

              return 0;

       }

 

       iounmap((void *)at91rm9200nor_map.virt);

       return -ENXIO;

}

 

static void __exit cleanup_at91rm9200nor(void)

{

       if (mymtd) {

              del_mtd_device(mymtd);

              map_destroy(mymtd);

       }

       if (at91rm9200nor_map.virt) {

              iounmap((void *)at91rm9200nor_map.virt);

              at91rm9200nor_map.virt = 0;

       }

}

 

module_init(init_at91rm9200nor);

module_exit(cleanup_at91rm9200nor);

 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Marius Groeger <[email protected]> ");

MODULE_DESCRIPTION("Generic configurable MTD map driver");

 

 



增加MTD,和相应的文件系统的支持。

Devices Drivers --->
Memory Technology Devices (MTD) --->
<*> Memory Technology Device(MTD) support
<*> MTD partitioning support
<*> Direct char device access to MTD devices
<*> Caching block device access to MTD devices
RAM/ROM/Flash chip drivers --->
<*> Detect flash chips by Common Flash Interface(CFI) probe
<*> Support for Intel/Sharp flash chips
Mapping drivers for chip access --->
<*> CFI Flash device mapped on AT91RM9200

File Systems --->
Miscellaneous filesystems --->


这里选择Jffs2的支持。

 

 


(4)
编译,加载

make Image编译,然后制作成uImage

可以修改Makefile 文件,添加cross工具和uboot工具处理命令。

TOPDIR=$($(which pwd))
TMP=$TOPDIR/linux.bin
TARGET=$TOPDIR/uImage

arm-linux-objcopy -O binary -S vmlinux $TMP && gzip -v9 $TMP && /
mkimage -n 'RAM disk' -A arm -O linux -T kernel -C gzip /
-a 0x20008000 -e 0x20008000 -d $TMP.gz $TARGET && /
cp $TARGET /mnt/hgfs/common && /
rm -f $TMP*


或者直接按照Olp嵌入式系统构建中讲到的方法进行uImage 文件生成,uImage格式要比其它其中映像格式灵活,所以我们一向选择uImage

系统启动过程中Jffs2信息:

AT91RM9200-NOR:0x00400000 at 0x10000000

NOR flash on AT91RM9200DK: 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

mtd: Giving out device 0 to NOR flash on AT91RM9200DK

AT91RM9200-NOR:using static partition definition

Creating 6 MTD partitions on "NOR flash on AT91RM9200DK":

0x00000000-0x00020000 : "Boot for AT9200"

mtd: Giving out device 1 to Boot for AT9200

0x00020000-0x00040000 : "U-Boot"

mtd: Giving out device 2 to U-Boot

0x00040000-0x00060000 : "Environment"

mtd: Giving out device 3 to Environment

0x00060000-0x00160000 : "Linux Kernel"

mtd: Giving out device 4 to Linux Kernel

0x00160000-0x00340000 : " rootfs ramdisk"

mtd: Giving out device 5 to  rootfs ramdisk

0x00340000-0x00400000 : "Jffs2"

mtd: Giving out device 6 to Jffs2

 

 

 

 

 

 

 

 

查看/proc文件系统中mtd信息:

# cat /proc/mtd                                                                

dev:    size   erasesize  name                                                 

mtd0: 00400000 00020000 "NOR flash on AT91RM9200DK"                             

mtd1: 00020000 00020000 "Boot for AT9200"                                      

mtd2: 00020000 00020000 "U-Boot"                                               

mtd3: 00020000 00020000 "Environment"                                          

mtd4: 00100000 00020000 "Linux Kernel"                                         

mtd5: 001e0000 00020000 " rootfs ramdisk"                                      

mtd6: 000c0000 00020000 "Jffs2"         

 

这里需要注意的是:

 我们需要挂载mede生成 dev设备,不然,后面的terminal 和设备都会找不到,当然如果你不选择用mdev或者devfs创建设备的话,就没有必要按下面的方式进行挂载,不过我不太喜欢medv创建的设备,实在是太多了,大大占用了我可贵的ram资源.

 

mkdir /dev/pts

mount -t devpts devpts /dev/pts

echo /sbin/mdev > /proc/sys/kernel/hotplug

mdev -s

 

mount -t jffs2 /dev/mtdblock5 /mnt/

 

(5)Jffs2文件系统测试

挂载Jffs2文件分区:

Mount -t jffs2 /dev/mtdblock5 /mnt

 

Vi /mnt/test.txt

写入一段文字,然后umount /mnt ,再挂载,看一下刚才写入的文件是否存在,再掉电重启一下系统,确认jffs2文件系统支持良好。

 

 

 

 

你可能感兴趣的:(Create Jffs2 for Linux Kernel 2.6)