The Linux MTD, JFFS HOWTO - (第1部分) HOWTO

2019-07-12 16:57发布

[译者序]

在学习嵌入式Linux时看到本文,尚未发现中文译本,因此将其翻译出来,希望对大家有所帮助。
版权请参见原文。译文可自由用于非商业用途。
本文将随原文更新而更新,或者因修正翻译失误而更新,因此,请尽量不要转载,避免其它人因为看到不同的版本而产生迷惑。
如确需转载,请保留译者序部分。
译文原文链接:
http://blog.csdn.net/easwy/

英文水平有限,如发现存在翻译错误,请反馈给我,我将及时修改。
联系方式: easwy.mail at gmail dot com
                                                         Easwy
                                                         2006/7/31
==================================================================

#
# ftp://ftp.uk.linux.org/pub/people/dwmw2/mtd/cvs/mtd/mtd-jffs-HOWTO.txt
#
                      ***  The Linux MTD, JFFS HOWTO ***
                      (正在编写中,请贡献你所知道的)

$Id: mtd-jffs-HOWTO.txt,v 1.16 2001/08/13 23:17:55 dwmw2 Exp $
最后更新: <见上面的CVS Id>
编辑: Vipin Malik (vipin@embeddedLinuxWorks.com)
其它作者的贡献见文档中的注释。

[关于]

本文致力于描述在Linux 2.2.x和2.4.x中设置MTD(Memory Technology Devices), DOC, CFI和JFFS (Journaling Flash File System)的方法。
本文整理工作正在进行中,(希望)在MTD和JFFS邮件列表中其它人的帮助下,本文能够成为一个相当全面的文档。
请将任何注释、更正、贡献发送到:vipin@embeddedLinuxWorks.com
请不要直接向此邮箱发送你的疑问,疑问应发送到邮件列表(见后)。

**************************** NO WARRANTY *****************************

# This HOWTO is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# If you break something you get to keep both parts! Follow these
# directions at YOUR OWN RISK.
# See the GNU General Public License for more details.

**********************************************************************

[开始]

如果你想使用MTD/JFFS认真设计一个项目,请定阅相应的邮件列表。这两个邮件列表都是由majordomo管理的。

MTD:
    要定阅此列表,请到 ftp.kernel.org下载的标准Linux内核。

2. 知道如何初始化你的处理器和芯片组。这包括,内存映射(和片选解码寄存器等)。你应该可以使用一个你或你们硬件工程师写的“简单”的初始化程序来测试你的板子。(注意:如果你打算使用BIOS,那么这个限制就消失了)。

3. 如果你的目标平台支持IDE硬盘的话,你已经在这场游戏中领先了(注意:这仅仅是在开发阶段,我们不打算在最终发布时包含硬盘)。这并不是没理由的要求。至少你能够买到支持你的目标处理器的,并且具有BIOS,支持IDE硬盘和串口的试验板或开发板。

4. 你不会把100次甚至200次的编译内核看做是一件辛苦的事。 :)

* 概述

我们将做下列几步:

1. 使用一个硬盘来在目标平台上设置并启动linux。

2. 喝瓶啤酒休息一下,带上你的伴侣(男朋友/女朋友)出去吃顿晚餐,因为他/她们将有一段时间不会再见到你。

3. 配置MTD驱动,这样你就能读/写flash以及mount一个jffs文件系统在上面。在这一步我们将使用modules。

4. 一旦开心舒适的完成了上面的第3步,我们开始编译MTD/jffs到内核中,准备引导。这一步我们将把内核安装到硬盘,把压缩文件系统放在MTD块设备上,然后引导它。接下来我们将根据你的喜好,进行5a或者5b。

5a. 在MTD设备上的非压缩root文件系统

    一旦我们成功的完成了第4步,我们将安装一个jffs文件系统到mtdbolck,并且mount成root(这很简单)。如果你想通过(简单)的拷贝单个文件来更改你的root文件系统的话,你可能想这样做。这样做的缺点是文件系统没有经过压缩。而flash一般比DRAM要贵3倍,其实你可以简单的把root文件系统压缩到FLASH上然后把它解压到更便宜的DRAM中(见下面5b)。

5b. 在MTD设备上的压缩root文件系统

    或者我们可以跳过上面简单的步骤,直接安装一个压缩的root文件系统到MTD设备上,然后在引导时把它解压缩到ramdisk(在DRAM中)并把这个ramdisk mount成root。(在我心里)这更好一些,因为DRAM通常要比FLASH更快。
    如果你的处理器支持DRAM控制器,那么它可能有read ahead和write combining,这将把性能提高一大截。如果你想写flash的话你需要把在flash地址上把这两个功能关闭。
    如果你的处理器有cache,那么你能更快的访问DRAM,因为这个区域可以被缓存。如果你要写flash的话,确保你关闭了cache功能(否则写操作将会失败。在C语言操作符中,应该把FLASH内存区域定义为"volatile")。

    一旦我们把压缩文件系统mount为root,我们可以很容易的mount一个MTD flash分区到一个root分区的一个目录,用于保存配置文件、日志,或更新root文件系统。

6. 噩梦到来了!通过flash引导kernel (注意:它可能是MTD flash的一个部分,不需要对MTD进行什么操作,但MTD要从kernel保留区域后面开始)。
   这是最难解决的问题,但现在已经解决了。看下面。

   让我们开始工作吧:
   这是现在x86系统上可能的bzImage kernel,点下面的链接查看详细内容:

   http://www.EmbeddedLinuxWorks.com/articles/rolo_guide.html

[本文第2部分]   The Linux MTD, JFFS HOWTO - (第2部分) FAQ 
注意:上面命令使用了/dev/mtdblock0而不是/dev/mtd0。"mount"命令需要块设备接口,/dev/mtdblock0,1,2,3...就是为这个目的提供的。/dev/mtd0,1,2,3是字符设备,提供它们是为了处理像拷贝二进制映像文件到原始FLASH设备上这类操作的。


[在CFI FLASH上创建分区,以及使用多片FLASH芯片]

不像一般的块设备,你不能在/dev/mtdblock0,1,2,3...上使用fdisk并创建分区。
(就我所知)CFI flash的分区必须在physmap.c文件中创建并编译进驱动。
对多片FLASH也说也是一样的。(正确与否?确认并更正)
可以在文件mtd/kernel/sbc_mediagx.c中找到创建分区的一个例子。
可以在文件mtd/kernel/octagon_5066.c中找到把多片FLASH芯片映射成单独的/dev/mtdn设备的例子(特别需要注意的,是在"init_oct5066()"函数中注册mtd设备时所采用多重循环)。你也可以为每个bank增加分区,参见mtd/kernel/sbc_mediagx.c的代码。

[Mount JFFS文件系统做为root分区]

这非常简单。

注意:这里假设你能够用某种方法引导你的内核。这一节并不涉及从一个MTD分区(或设备)上引导你的内核。

你可以通过IDE flash盘/CF盘等来引导内核,使用lilo。
不管你通过什么方式来引导内核(甚至你想直接从FLASH来引导),下面的步骤是相同的。这次你只是把内核烧进原始FLASH设备中(在下面的"rdev"步骤完成之后)。

1. 保证你能够检测到你的flash设备,并且可以通过MTD设备文件(/dev/mtd*)读写它们。
2. 保证你能够mount所需要的JFFS(1或2)文件系统到你的flash设备上,向它拷贝文件,unmount,重启,再mount,你的文件仍然在那儿(也要在一组文件上运行 "diff",保证数据没有被损坏)。
3. 把所有必需的MTD/JFFS(1/2)功能编译到内核中(使用模块来mount root文件系统留给读者做练习)。
4. 告诉内核将用什么做为你的root分区,使用下面的命令:   # rdev <你的flash映像> /dev/mtdblock
   mtdblock是你要在上面构建你的root文件系统的设备,它在重启后将被mount为root分区。
5. 运行boot loader的初始化程序(对LILO引导程序来说,是lilo)。
6. 重启。你的jffs mtdblock分区将被mount为root分区。

[Mount MTD分区(或设备)上经过压缩的ext2文件系统做为root分区]

啊哈~~~这非常有趣(并且很复杂)。

先决条件:
a. 你的开发系统的内核必须支持ramdisk,而且它的大小至少要与你所mount的root文件系统的大小相等。这只是为了压缩root文件系统。如果你已经有了一个压缩的root文件系统,那么你可以跳过这一步。

步骤:
1. 在你的支持mtd的开发系统上制作一个root文件系统。(支持MTD意味着你的开发系统内核必须支持MTD,而且你能够从你的开发系统上烧写你的MTD flash设备)。
制作root文件系统的工作留给读者完成。在网络上有大量已经做好的root文件系统,你可以使用其中任何一个,或者制作你自己的(这不是必要的娱乐,如果你之前从未制作过的话)。

2. 在ramdisk中制作一个ext2文件系统,大小和未压缩过的root文件系统相同。通过以下命令: #mke2fs /dev/ram0 size_of_root_fs
size_of_root_fs:你的root文件系统大小,以1k为单位

3. 把这个空的文件系统mount到/mnt目录下的一个空闲目录中: #mount -t ext2 /dev/ram0 /mnt/ramdisk
4. 把你小心翼翼制作出来的root文件系统目录拷贝到这个ramdisk中: #cp -af /tmp/my_final_root_fs_files/* /mnt/ramdisk
5. 如果你的操作正确,那么通过如下命令,你现在可以看到根目录了(etc, root, bin, lib, sbin等等): # ls -ld /mnt/ramdisk
6. 现在umount并且压缩这个文件系统:  #umount /mnt/ramdisk
 #dd if=/dev/ram0 bs=1k count= | gzip /
         -9 > /tmp/compressedRootFS.gz
7. 现在,我们要告诉即将使用此压缩文件的内核:这是一个压缩文件系统,并且要在MTD设备上找到它。
   确信MTD支持已经被编译进此内核。另外,你还需对此内核做下面这两个修改(对2.2.x和2.4.x内核都适用):

   A. 在drivers/block/rd.c文件中,你需要把检测ROOT_DEV是软驱的代码注释掉。这段代码通常看起来是这样的:         if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR
#ifdef CONFIG_BLK_DEV_INITRD
                && MAJOR(real_root_dev) != FLOPPY_MAJOR
#endif
        )
                return;

      一定不要在此处返回,因为你的ROOT_DEV不是软驱,而是MTD块设备。

    B. 因为对rd_load()函数(此函数用于装载任何压缩文件系统到ramdisk)的调用发生在MTD驱动有机会注册MTD块设备之前,这将导致rd_load()不能找到你的root设备,也就无法从root设备上装载压缩文件系统。
    尽管这个问题在内核中已经得到修正,你仍需修改main.c文件,在mount_root()调用之前,显式的调用一次rd_load()函数。所以,在init/main.c文件中,在mount_root()前加入一个rd_load()调用。

    C. 现在编译内核,加入MTD和ext2支持(不要作为modules)。

8. 在你把内核烧写到目标板前,需要告诉它,你想要装载一个压缩的root文件系统,以及这个压缩的映像在哪儿。 有两种方法可以做到:简单的方法(使用命令行参数)和复杂的方法。 我们将通过复杂的方法来做。运用简单方法将留给读者做为练习。 不,我通常不会仅仅为了乐趣而选择复杂的方法来做事情的,这背后是有原因的。 我正要做的,是直接在flash上引导Linux内核,不需要安装boot loader。在这种情况下,没有任何办法向内核传递命令行参数。

   像下面这样告诉目标板的内核,你想加载一个压缩的文件系统,以及到哪里去找到这个文件系统:    #rdev -r
   按下面的方法计算:
   这个数字是一串包含多个bit的二进制数字的十进制表示方式。
   Bit 0-9指出到root设备起始地址的偏移,以1KB块为单位。
   Bit 14表示是否需要装载一个ramdisk(在我们的例子中是经过压缩的ramdisk) --- 当然要选择yes。不然你为什么要看这段呢!
   其它Bit:设为0。

作为下面的例子,17408是你应该在上面的rdev -r命令中键入的第二个参数。
这个数字告诉内核,偏移是1024个1K块(也就是说,应该在距MTD设备起始为1M字节的偏移查找并装载这个压缩的映像,并把它mount成root设备)。

注意:如果这个bit定义发生了变化,或者你怀疑我的正确性,请打开arch/i386/kernel/setup.c文件,查看这个文件的宏定义。这个文件是这些bit掩码定义的地方。

9. 现在告诉你的目标板内核你的root设备是什么: #rdev /dev/mtdblock<0,1,2....n>
10. 当然,你需要把你的压缩文件系统拷贝到MTD设备的正确偏移上。首先确保你的目标设备已经被擦除了:   #dd if=/tmp/compressedRootFS.gz bs=1k of=/dev/mtd<0,1,2....n> seek=seek_offset
    seek_offset:1K块的数目,以KB为单位。这个偏移是你在第8步中告诉内核的。

    所以,对1M字节的偏移,你应该取“seek=1024”。

注意:"dd"可能会打印"operation not permitted"或一些这样信息,忽略它们!dd会试图截短被操作的设备,但MTD当然不会允许"dd"这样的命令截短它。拷贝操作将会像你看到的那样继续进行(不会受这些错误信息的影响)。

11. 完整性检查 (多年来的教训告诉我每一步都要检查两次,甚至三次)
    让我们确定你的压缩映像是正确的!

12. 我们将查看映像前若干字节以确定它们是正确的。你也可以"dd"目标映像回一个文件并比较它和原文件(留给读者做实验)。   #dd if=/dev/mtd<0,1,2...n> bs=1k skip=1024 (或者是你的偏移,以KB为单位)  | od -Ax -tx1 |less
    记下前面几行。(注意上面"skip"的用法,不是"seek")

    现在让我们查看你硬盘上的压缩root文件系统:   #dd if=/tmp/compressedRootFS.gz | od -Ax -tx1 | less
    和你前面记下的进行比较,它们应该是相同的(我需要说这个吗?)

13. 安装内核,不管你是打算如何引导它(如果你打算用LILO引导,运行lilo)或把它放在其它boot loader所能引导的位置(或者直接从flash引导)。

14. 重启(目标板)。现在,你应该看到ramdisk启动代码执行两次,并且在第两次会找到压缩映像并把它mount成root文件系统。

15. 跳过这步。申请加薪吧(并且也要寄一点给我)!

[在一个没有BIOS的MTD设备上引导Linux内核,并且mount此设备上的压缩root文件系统]

这是嵌入式Linux的圣杯!:) 我将试图讲解怎么做。但最好只把它当做一个指南,因为嵌入式系统间相互的差异是非常大的,不仅仅指内存映射,而且包括处理器的类型,flash的类型,RAM的数量等等。

* 假设:
如果你的需求符合下面所讲,这将(或者可能)帮到你:

你想要:
1. 使用你在