redboot下jffs2文件系统详解

来源:互联网 发布:js正则表达式\< 编辑:程序博客网 时间:2024/04/29 08:50

1 引导过程:FLASH根文件系统  
# 使用 mkfs.jffs2 工具,制作根文件系统映像
# -d fakeroot   :根文件系统的内容放在fakeroot目录中
# -e 0x20000    :FLASH的eraseblock大小为0x20000字节
# -p                :以0xff填充文件尾部的空间对齐eraseblock
# -o fakeroot.jffs2.img :输出映像文件名
[root@lips arm]# mkfs.jffs2 -d fakeroot -e 0x20000 -p -o fakeroot.jffs2.
img
# 将映像文件复制到TFTP服务器的根目录(这里是/root/arm/boot/)
[root@lips arm]# cp fakeroot.jffs2.img boot/
[root@lips arm]#
# 查看一下当前FLASH的布局,确定空闲空间的地址
RedBoot> fis list
Name              FLASH addr  Mem addr    Length      Entry point
RedBoot           0xF0000000  0xF0000000  0x00040000  0x00000000
RedBoot config    0xF07C0000  0xF07C0000  0x00001000  0x00000000
FIS directory     0xF07E0000  0xF07E0000  0x00020000  0x00000000
kernel            0xF0040000  0x00100000  0x000E0000  0x00100000
RedBoot> fis free
  0xF0120000 .. 0xF07C0000
# 通过网络从主机TFTP服务器下载fakeroot.jffs2.img文件,并装入内存地址0x10
0000
# 这里几个参数的意义可以参考上一节
# -b 0x100000   :确定该值的原则与下载内核文件时相同,并且可以使用一个不一
样的地址
RedBoot> load -r -b 0x100000 -h 192.168.0.20 fakeroot.jffs2.img
Raw file loaded 0x00100000-0x0023ffff, assumed entry at 0x00100000
# 用fis工具的erase命令擦除指定的FLASH区域
# 擦除之后的区域被填充为0xFF,这样做是为了保证没有写有效数据的空间是“干
净”的,从而避免因为文件尾部有垃圾数据而导致的错误。这个步骤并非必须执行

RedBoot> fis erase -f 0xf0120000 -l 0x140000
# 用fis工具的write命令将内存中的内容写入FLASH
# -b 0x100000   :数据在内存中的地址
# -f 0xf0120000 :数据写入FLASH的地址(怎么确定这个地址?从上面的fis fre
e命令可以知道当前可用空间的起始地址,从而确定这个地址。当然也可以靠后一些
,比如0xf0200000,不过要注意这样的话就会出现一个空闲空间的空洞,并且会影
响根设备的编号,即/dev/mtdblock?。)
# -l 0x140000   :数据块的长度(怎么确定这个长度?从load命令的返回信息知道
映像文件的大小,然后取一个稍大并且对齐erase block size 0x20000的值。)
RedBoot> fis write -b 0x100000 -f 0xf0120000 -l 0x140000
* CAUTION * about to program FLASH
            at 0xf0120000..0xf025ffff from 0x00100000 - continue (y/n)?
y
... Erase from 0xf0120000-0xf0260000: ..........
... Program from 0x00100000-0x00240000 at 0xf0120000: ..........
# 用fis工具的create命令命名刚才写入的内容为fakeroot
# -n    :该参数指定仅创建了目录节点
RedBoot> fis create -f 0xf0120000 -l 0x140000 -n fakeroot
... Unlock from 0xf07e0000-0xf0800000: .
... Erase from 0xf07e0000-0xf0800000: .
... Program from 0x01fdf000-0x01fff000 at 0xf07e0000: .
... Lock from 0xf07e0000-0xf0800000: .
# 查看一下,确认写入成功
RedBoot> fis list
Name              FLASH addr  Mem addr    Length      Entry point
RedBoot           0xF0000000  0xF0000000  0x00040000  0x00000000
RedBoot config    0xF07C0000  0xF07C0000  0x00001000  0x00000000
FIS directory     0xF07E0000  0xF07E0000  0x00020000  0x00000000
kernel            0xF0040000  0x00100000  0x000E0000  0x00100000
fakeroot          0xF0120000  0xF0120000  0x00140000  0x00100000
RedBoot> fis free
  0xF0260000 .. 0xF07C0000
# 从FLASH加载内核
RedBoot> fis load kernel
# exec命令执行内核,-c指定引导参数
# console=ttyS0,115200  :设置串口控制台
# root=/dev/mtdblock2   :设置根文件系统为/dev/mtdblock2
# 这个“/dev/mtdblock2”是怎么确定的?我们已经创建了设备节点mtdblock0~m
tdblock7,这里要确定写入FLASH的jffs2文件系统对应哪个设备。方法是,从FLAS
H的起始地址往后数,看写入的jffs2位于第几个分区;计数从0开始;在IQ80321板
子上第一个分区是RedBoot;”unallocated space”也要算。准确的信息可以在引
导过程中看到,比如下面的”Creating 6 MTD partitions on IOP3xx Flash:”;
或者在引导成功后的/proc/mtd文件中也可以看到。
RedBoot> exec -c "console=ttyS0,115200 root=/dev/mtdblock2"
Using base address 0x00100000 and length 0x000e0000
Uncompressing Linux.....................................................
.... done, booting the kernel.
Linux version 2.4.21-rmk1-ds0-dj9 (root@lips) (gcc version 2.95.3 200103
15 (release)) #1 Mon Jul 5 14:34:15 CST 2004
CPU: XScale-IOP80321 revision 2
Machine: Intel IQ80321
alloc_bootmem_low
memtable_init
On node 0 totalpages: 16384
zone(0): 16384 pages.
zone(1): 0 pages.
zone(2): 0 pages.
Kernel command line: console=ttyS0,115200 root=/dev/mtdblock2
Calibrating delay loop... 599.65 BogoMIPS
Memory: 64MB = 64MB total
Memory: 62904KB available (1398K code, 261K data, 232K init)
XScale Cache/TLB Locking Copyright(c) 2001 MontaVista Software, Inc.
Dentry cache hash table entries: 8192 (order: 4, 65536 bytes)
Inode cache hash table entries: 4096 (order: 3, 32768 bytes)
Mount cache hash table entries: 512 (order: 0, 4096 bytes)
Buffer-cache hash table entries: 4096 (order: 2, 16384 bytes)
Page-cache hash table entries: 16384 (order: 4, 65536 bytes)
POSIX conformance testing by UNIFIX
PCI: bus0: Fast back to back transfers disabled
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
Initializing RT netlink socket
Intel IOP3xx AAU RAID Copyright(c) 2003 Intel Corporation
Starting kswapd
JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communicatio
ns AB.
pty: 256 Unix98 ptys configured
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIA
L_PCI enabled
ttyS00 at 0xfe800000x (irq = 28) is a 16550A
Real Time Clock Driver v1.10e
RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize
Intel(R) PRO/1000 Network Driver - version 5.0.43-k1
Copyright (c) 1999-2003 Intel Corporation.
eth0: Intel(R) PRO/1000 Network Connection
Uniform Multi-Platform E-IDE driver Revision: 7.00beta4-2.4
ide: Assuming 33MHz system bus speed for PIO modes; override with idebus
=xx
cfi_cmdset_0001: Erase suspend on write enabled
Using buffer write method
Using RedBoot partition definition
Creating 6 MTD partitions on "IOP3xx Flash":
0x00000000-0x00040000 : "RedBoot"
0x00040000-0x00120000 : "kernel"
0x00120000-0x00260000 : "fakeroot"
0x00260000-0x007c0000 : "unallocated space"
0x007c0000-0x007c1000 : "RedBoot config"
mtd: partition "RedBoot config" doesn't end on an erase block -- force r
ead-only
0x007e0000-0x00800000 : "FIS directory"
md: raid5 personality registered as nr 4
raid5: measuring checksumming speed
   iop3xx_aau:   223.200 MB/sec
raid5: using function: iop3xx_aau (223.200 MB/sec)
md: md driver 0.90.0 MAX_MD_DEVS=256, MD_SB_DISKS=27
md: Autodetecting RAID arrays.
md: autorun ...
md: ... autorun DONE.
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 4096 bind 4096)
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
NetWinder Floating Point Emulator V0.97 (double precision)
VFS: Mounted root (jffs2 filesystem).
Freeing init memory: 232K
Setting hostname iq80321:
Mounting proc filesystem:
mount: Mounting none on /proc failed: Device or resource busy
Please press Enter to activate this console.
BusyBox v1.00-pre10 (2004.04.27-01:28+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
# 得到shell提示符,引导成功!
/ #
# 前面我们使用erase/write/create连续三个命令完成了jffs2映像根文件系统的写
入,主要是为了保证0xff填充非有效数据的空间,如果能够保证这一点的话,使用
create命令直接写入FLASH也是可以的。怎么保证0xff填充呢?经验是,执行 fis
init –f 命令对FLASH完全初始化之后,空闲空间以0xFF填充;或者用 fis erase
命令擦除FLASH;或者用 mfill 命令将一段内存区域填充为0xFF之后再load文件至
该区域;必要的话可以用 dump 命令查看确认一下FLASH的内容。总之,理解了“为
什么”就可以灵活使用这些命令,而不必拘泥于文档中的演示。
# 下面是测试过程:
RedBoot> fis free
  0xF0260000 .. 0xF07C0000
RedBoot> load -r -b 0x200000 -h 192.168.0.20 fakeroot.jffs2.img
Raw file loaded 0x00200000-0x0033ffff, assumed entry at 0x00200000
RedBoot> fis create -b 0x200000 -f 0xf0260000 -l 0x140000 fakeroot2
... Erase from 0xf0260000-0xf03a0000: ..........
... Program from 0x00200000-0x00340000 at 0xf0260000: ..........
... Unlock from 0xf07e0000-0xf0800000: .
... Erase from 0xf07e0000-0xf0800000: .
... Program from 0x01fdf000-0x01fff000 at 0xf07e0000: .
... Lock from 0xf07e0000-0xf0800000: .
RedBoot> fis list
Name              FLASH addr  Mem addr    Length      Entry point
RedBoot           0xF0000000  0xF0000000  0x00040000  0x00000000
RedBoot config    0xF07C0000  0xF07C0000  0x00001000  0x00000000
FIS directory     0xF07E0000  0xF07E0000  0x00020000  0x00000000
kernel            0xF0040000  0x00100000  0x000E0000  0x00100000
fakeroot          0xF0120000  0xF0120000  0x00140000  0x00100000
fakeroot2         0xF0260000  0xF0260000  0x00140000  0x00200000
RedBoot> fis free
  0xF03A0000 .. 0xF07C0000
RedBoot> dump -b 0xf025ff00
F025FF00: FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF  |...........
.....|
F025FF10: FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF  |...........
.....|
RedBoot> fis load kernel
RedBoot> exec -c "console=ttyS0,115200 root=/dev/mtdblock3"
Using base address 0x00100000 and length 0x000e0000
Uncompressing Linux.....................................................
....
/ # cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00040000 00020000 "RedBoot"
mtd1: 000e0000 00020000 "kernel"
mtd2: 00140000 00020000 "fakeroot"
mtd3: 00140000 00020000 "fakeroot2"
mtd4: 00420000 00020000 "unallocated space"
mtd5: 00001000 00020000 "RedBoot config"
mtd6: 00020000 00020000 "FIS directory"
/ # mount
/dev/mtdblock3 on / type jffs2 (rw)
/proc on /proc type proc (rw)
/ #
  
5.8 FLASH存储空间分布
  RAM: 0x00000000-0x08000000, 0x0001b488-0x01fd1000 available
  FLASH: 0xf0000000 - 0xf0800000, 64 blocks of 0x00020000 bytes each.
  
Name
FLASH addr
Length
0
RedBoot
0xF0000000
0x00040000
1
kernel
0xF0040000
0x000E0000
内核
2
fakeroot
0xF0120000
0x00140000
根文件系统
3
0xF0260000
Free (unallocated space)
4
RedBoot config
0xF07C0000
0x00001000
5
FIS directory
0xF07E0000
0x00020000
0xF0800000
End
  
  

6 提示

6.1 已经解决的问题
6.1.1 问题描述
  整个开发过程还是比较顺利的,因为有裁减Linux系统的经验(lips),远程N
FS根文件系统的引导过程一次就成功了。稍后使用在FLASH上面使用jffs2文件系统
引导的过程中碰到了一些棘手的问题,幸运的是花了两天的时间就弄清楚了。这里
大概说明一下碰到的问题和解决方法。  当时的情况是,kernel已经写到了FLAS
H中,在主机上用 mkfs.jffs2 命令创建了 fakeroot 的映像文件,但是没有使用
--eraseblock=0x20000 和 -p 参数。然后在用 fis create 命令将映像文件从内存
写入FLASH时,-l 参数指定的长度是 0x200000 (2M),实际上映像文件只有 1.2M左
右,当时想把文件系统留大一些。
  准备好之后,以 root=/dev/mtdblock/2 作为参数启动内核,得到的结果如下

  
  RedBoot> fis list
  Name              FLASH addr  Mem addr    Length      Entry point
  RedBoot           0xF0000000  0xF0000000  0x00040000  0x00000000
  RedBoot config    0xF07C0000  0xF07C0000  0x00001000  0x00000000
  FIS directory     0xF07E0000  0xF07E0000  0x00020000  0x00000000
  kernel            0xF0040000  0x01008000  0x000C0000  0x01008000
  fakeroot          0xF0100000  0xF0100000  0x00200000  0x00100000
  RedBoot> fis free
    0xF0300000 .. 0xF07C0000
  RedBoot> fis load kernel
  RedBoot> exec -c "console=ttyS0,115200 root=/dev/mtdblock/2"
  Using base address 0x01008000 and length 0x000c0000
  Uncompressing Linux.................................................
...... done
  Linux version 2.4.21-rmk1-ds0-dj9 (root@lips) (gcc version 2.95.3 20
010315 (rel
  CPU: XScale-IOP80321 revision 2
  Machine: Intel IQ80321
  
  Using RedBoot partition definition
  Creating 6 MTD partitions on "IOP3xx Flash":
  0x00000000-0x00040000 : "RedBoot"
  0x00040000-0x00100000 : "kernel"
  0x00100000-0x00300000 : "fakeroot"
  0x00300000-0x007c0000 : "unallocated space"
  0x007c0000-0x007c1000 : "RedBoot config"
  mtd: partition "RedBoot config" doesn't end on an erase block -- for
ce read-onl
  0x007e0000-0x00800000 : "FIS directory"
  
  jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0000000
0: 0xf018 i
  jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0000000
4: 0xf018 i
  jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0000000
8: 0xf018 i
  jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0000000
c: 0xf018 id
  …………
  Further such events for this erase block will not be printed
  JFFS2: Erase block at 0x00000000 is not formatted. It will be erased

  jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0002000
0: 0x0008 id
  jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0002000
4: 0xaff0 id
  jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0002000
8: 0x1009 id
  …………
  Further such events for this erase block will not be printed
  JFFS2: Erase block at 0x00020000 is not formatted. It will be erased

  Cowardly refusing to erase blocks on filesystem with no valid JFFS2
nodes
  Kernel panic: VFS: Unable to mount root fs on 1f:00
  
  这里主要存在两个问题,分别说明一下。
6.1.2 创建jffs2文件系统注意事项
  引导过程中出现的数十行”jffs2_scan_eraseblock(): Magic bitmask 0x198
5 not found…”信息说明jffs2文件系统有问题。另外,如果我先用远程NFS根文件
系统引导,然后在目标机系统中直接 mount -t jffs2 /dev/mtdblock/2 /mnt 也会
得到同样的警告信息,不过可以在 /mnt 下面看到正确的文件系统内容。
  为了解决这个问题,我首先仔细看了 mkfs.jffs2 的手册页,发现 --erasebl
ock 参数似乎比较重要,而我没有使用,于是找到该参数值 0x20000,用该参数重
新生成了映像文件。测试表明问题仍然存在。
  查找资料发现,有人强调在 mkfs.jffs2 时使用 -p 选项,其作用是从文件末
尾到最后一个erase block填充0xFF。这时我意识到FLASH的未分配空间必须以0xFF
填充。而我先前的做法不能保证这一点。首先没有指定-p选项;其次,由于-l参数
指定了远远大于实际映像文件大小的长度,而将内存区域中大量垃圾数据写到了FL
ASH中。
  因此,重新带参数-p制作jffs2文件系统映像,并改-l 0x200000为0x140000写
FLASH,这样再次mount该设备就OK了,没有再出现警告信息。但是Kernel panic仍
然存在,这是另外一个问题。
  
6.1.3 /dev/mtdblock/2 还是 /dev/mtdblock2
  (首先说明,’2’只是个例子./dev/mtdblock/n,n=0,1,2,3,…)
  看起来这两个设备节点应该是完全等效的。至少我原来是这么认为。所看到的
资料中,有的用/dev/mtdblock/2,有的用/dev/mtdblock2。能够看到的差别就是,
如果需要多个MTD块设备节点的话,把这些节点放在单独的/dev/mtdblock目录中,
而不是统统放在/dev下面,可以使/dev看起来清爽一些。因此,我在制作根文件系
统的时候,选择了前者,即在/dev/mtdblock目录下面创建了0-7共8个设备节点。

  然而,“Kernel panic: VFS: Unable to mount root fs on 1f:00”错误说明
内核没有从引导参数“root=/dev/mtdblock/2”正确定位到根文件系统(即使已经
解决了上一个问题,保证jffs2文件系统没有问题)。
  在考虑排除了多种可能性之后,无奈之下我决定试一下“root=/dev/mtdblock
2”。奇迹发生了,引导成功!特别注意,这时我并没有修改/dev设备节点,而仅仅
是修改了引导参数的写法。也就是说,不论你创建的MTD设备节点是/dev/mtdblock
/2还是/dev/mtdblock2,内核引导参数都应该是“root=/dev/mtdblock2”!
  为了不致于引起更多迷惑,我还是把设备节点改变为了/dev/mtdblock2的形式
。那么内核引导参数中到底可不可以使用/dev/mtdblock/2的形式呢?后来我猜测内
核如果支持 devfs 的话应该是可以的。devfs 的目的不就是把/dev从一塌糊涂的扁
平结构改成清晰的层次结构嘛?不过我还没有验证。
  另外,在内核引导参数中使用“主设备号、次设备号”的形式来指定根文件系
统的位置也是可以的。如下所示,“root=1f02”同样指定了/dev/mtdblock2。0x1
f=31是MTD块设备的主设备号,0x02=2是次设备号,即mtdblock2.
RedBoot> fis load kernel
RedBoot> exec -c "console=ttyS0,115200 root=1f02"
Using base address 0x00100000 and length 0x000e0000
Uncompressing Linux.....................................................
....
......
VFS: Mounted root (jffs2 filesystem).
Freeing init memory: 232K
Please press Enter to activate this console.
BusyBox v1.00-pre10 (2004.04.27-01:28+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
/ # mount
/dev/mtdblock2 on / type jffs2 (rw)
/proc on /proc type proc (rw)
/ #
原创粉丝点击