分类: 嵌入式
2011-01-03 15:30:44
.7 引导过程:FLASH根文件系统 # 使用 mkfs.jffs2 工具,制作根文件系统映像 # -d fakeroot # -e 0x20000 # -p # -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 RedBoot RedBoot config FIS directory kernel RedBoot> fis free # 通过网络从主机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 映像文件的大小,然后取一个稍大并且对齐erase block size 0x20000的值。) RedBoot> fis write -b 0x100000 -f 0xf0120000 -l 0x140000 * CAUTION * about to program FLASH 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 RedBoot RedBoot config FIS directory kernel fakeroot RedBoot> fis free # 从FLASH加载内核 RedBoot> fis load kernel # exec命令执行内核,-c指定引导参数 # console=ttyS0,115200 # root=/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 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 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 RedBoot RedBoot config FIS directory kernel fakeroot fakeroot2 RedBoot> fis free RedBoot> dump -b 0xf025ff00 F025FF00: FF FF FF FF FF FF FF FF .....| F025FF10: 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: 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 RedBoot RedBoot config FIS directory kernel fakeroot RedBoot> fis free 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) / # |