从ramdisk根文件和initramfs系统启动Linux

从ramdisk根文件系统启动Linux

Author:窦少彬    Emailmail.dsb@163.com

开发环境:Fedora 12

工具链:arm-linux-gcc 4.3.2 with EABI

内核版本:2.6.29.4-FriendlyARM。

开发板:mini2440-128M Nand Flash

Bootloader:u-boot-2009.11


具体步骤如下:
1.解压内核源码树
解压linux-2.6.29-mini2440-20090708.tgz

2.修改内核配置选项
进入内核源码目录linux-2.6.29目录

#cp config_mini2440_t35 .config

#make menuconfig ARCH=arm

打开配置菜单,修改两个配置项,分别是:

General setup-->Initial RAM filesystem and RAM disk......(选择)

General setup--> Optimize for size (选中) 此项优化内核大小,根据需要进行配置。

Device Drivers-->Block devices-->RAM block device support(选择)
Device Drivers-->Block devices-->
(8192)Default RAM disk size (Kbytes)(根据镜像大小修改数值)

如果这个大小和你做的ramdisk不匹配,则启动时仍然会出现kernel panic内核恐慌,提示ramdisk格式不正确,挂载不上ramdisk。

File systems-><*> Second extended fs support(选中)

ramdisk是一种内存虚拟磁盘技术,实质上并不是一种文件系统,它使用的文件系统时ext2文件系统。

然后保存配置退出。这样就为内核添加好了ramdisk启动功能和ramdisk的驱动支持了。


3.修改内核启动参数

方法有二:

a)修改.config的中CONFIG_CMDLINE=""CONFIG_CMDLINE="initrd=0x31000000,0x200000 root=/dev/ram rw init=/linuxrc console=ttySAC0 mem=64M"

意思为从ramdisk启动,ramdisk压缩文件起始地址在内存地址0x31000000处,文件大小为0x200000

此参数也可以在make menuconfig ARCH=arm时进入Boot options菜单,然后在Default kernel command string里修改。

b)用u-bootbootargs环境变量来传递启动参数。

[u-boot]# setenv bootargs ‘initrd=0x31000000,0x200000 root=/dev/ram rw init=/linuxrc console=ttySAC0 mem=64M

[u-boot]# saveenv  保存u-boot环境变量

 

4.编译内核

#make zImage ARCH=arm CROSS_COMPILE=arm-linux-

编译完成后在arch/arm/boot 出现zImage内核映像。

 

(若出现cc1: error: invalid option `abi=aapcs-linux' …旧编译器可能是用OABI的,而配置内核时又选择了使用EABI的,修改内核配置: Kernel Features ---->Use the ARM EABIto compile the kernel不选该项)

 

注:好像友善之臂把内核源码目录里的uImage目标给注释了,以前在论坛里看到过有人说,直接make uImage好像提示没有uImage的目标。所以我就先制作zImage,然后再用u-bootmkimage工具转化为uImage。其实 uImage就是在zImage的开头部分增加了一个64字节的内核映像说明。说明一下:zImageARM Linux常用的一种压缩映像文件,uImageU-boot专用的映像文件,它是在zImage之前加上一个长度为0x40,说明这个映像文件的类型、加载位置、生成时间、大小等信息。换句话说,如果直接从uImage0x40位置开始执行,zImageuImage没有任何区别。另外,Linux2.4内核不支持uImageLinux2.6内核加入了很多对嵌入式系统的支持,但是uImage的生成也需要设置。

 

5.制作uImage内核映像
由于我使用的Bootloader是u-boot,所以要将zImage转化为uImage,方法如下:

 #mkimage -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -n "Linux kernel Image" -d zImage uImage-ramdisk

说明:mkimage工具是u-boot格式uImage内核映像制作工具。如果成功编译u-boot之后,它会在u-boot源码树下的tools目录之下。建议将其拷贝到宿主机的/sbin/目录下,以方便使用。

6.制作ramdisk根文件系统
6.1创建根文件系统目录:
#cd转入到你的工作目录。
#mkdir rootfs
#cd rootfs
#mkdir bin dev etc lib proc sbin sys usr mnt tmp var
#mkdir usr/bin usr/lib usr/sbin lib/modules

6.2 创建最基本的设备文件:
#cd dev

#mknod -m 666 console c 5 1

#mknod -m 666 null c 1 3

#cd ..

 

6.3 安装/etc配置文件

etc/fstab文件:

# device     mount-point    type   options        dump  fsck order

proc           /proc        proc   defaults        0     0

tmpfs          /tmp         tmpfs  defaults        0     0

 

etc/inittab文件:

#etc/inittab

::sysinit:/etc/init.d/rcS

ttySAC0::askfirst:-/bin/sh

::ctrlaltdel:/sbin/reboot

::shutdown:/bin/umount -a -r

etc/init.d/rcS文件:

#!/bin/sh

ifconfig eth0 192.168.1.17

mount -a

 

6.4 编译内核模块:

#cd linux-2.6.29

#make modules ARCH=arm CROSS_COMPILE=arm-linux-

 

6.5 安装内核模块:

#make modules_install ARCH=arm INSTALL_MOD_PATH=/xxx/rootfs   //嵌入式中的内核模块都要在文件系统中。

 

6.6 配置busybox

#cd busybox-xxx

#make menuconfig,配置如下:

Busybox Settings -> build Options ->选中"Build busybox as a static binary“,即静态链接,免去拷贝大量的库文件。

Installation Options -> 选中"Don't use /usr",以免busybox不慎被安装到宿主机系统的相应目录下,破坏宿主机系统。
Busybox Installation Prefix (/xxx/rootfs,修改该选项表明编译后的busybox将安装到该位置。

6.7编译、安装busybox
#make ARCH=arm CROSS_COMPILE=arm-linux-

#make install

安装到Busybox Installation Prefix (/xxx/rootfs)设定的目录里。

完成根文件系统的创建


6.8 制作ramdisk根文件系统镜像

方法一:

1dd if=/dev/zero of=ramdisk.img bs=1k count=4096 ,这样制作的镜像有4MB,可以根据自己的需要修改
2mkfs.ext2 -m0 ramdisk.img,将ramdisk.img格式化为ext2格式
3mount -o loop ramdisk.img /mnt/ramdisk/,将ramdisk.img挂载到/mnt/ramdisk目录
4cp -a /rootfs /mnt/ramdisk,将自己的文件系统全部拷贝到/mnt/ramdisk目录去
5umount /mnt/ramdisk,卸载ramdisk挂载。此时生成可用的ramdisk.img镜像
6gzip -v9 ramdisk.img,压缩镜像。

 

方法二:

http://genext2fs.sourceforge.net/下载制作ramdisk文件系统的工具genext2fs,当前最新版本为genext2fs-1.4.1.tar.gz 。编译生成该工具genext2fs,并将其放入宿主机的/sbin/目录下以方便使用。
跳转到要制作的rootfs的上一级目录

#genext2fs -b 4096 -d rootfs ramdisk

-b是指制作的ramdisk大小为4096K字节,-d是指要制作成ramdisk的根文件系统目录,ramdiskname是制作出来的ramdisk的文件名。
#gzip -9 -f ramdisk
,将该ramdisk以最优方式压缩为ramdisk.gz

 

7.下载内核映像和ramdisk映像
启动u-boot ,设置u-boot环境变量:

ipaddr=202.127.201.2 (开发板ip

serverip=202.127.201.209 tftp服务器ip,必须同开发板ip在同一个网段)

bootargs=initrd=0x32000000,0x400000 root=/dev/ram rw init=/linuxrc console=ttySAC0 mem=64M

下载内核和ramdisk映像:

[u-boot@MINI2440]# tftp 0x31000000 uImage-ramdisk

[u-boot@MINI2440]# tftp 0x32000000 ramdisk.gz

8)使用ramdisk根文件系统启动内核

[u-boot@MINI2440]# bootm 0x32000000

 

说明:配置文件自动启动网卡脚本/etc/init.d/rcS

在最下边添加如下两行命令即可自动启动网卡:

/sbin/ifconfig lo 127.0.0.1

/sbin/ifconfig eth0 192.168.31.230 netmask 255.255.255.0 up

 


使用initramfs启动Linux


参照《从ramdisk根文件系统启动Linux成功,总结一下》
http://www.arm9home.net/read.php?tid-5610.html

开发环境:Fedora 9
交叉编译工具链:arm-linux-gcc 4.3.2 with EABI
嵌入式Linux内核版本:2.6.29.4-FriendlyARM。本文就是友善之臂的2.6.29.4-FriendlyARM的那个版本config_mini2440_t35的内核的基础上改的。其它版本的应该也类似,仅供参考。
开发板:mini2440-128M Nand Flash
Bootloader:u-boot-2009.11

主要的不同点:
步骤2.修改内核配置选项
进入内核源码目录linux-2.6.29目录
#cp config_mini2440_t35 .config
#make menuconfig ARCH=arm
打开配置菜单,配置使用ramdisk启动系统时需要设置两个选项,这里只需要配置下面一个配置项:
General setup-->选择 Initial RAM filesystem and RAM disk...... 项


因为,我们使用的是initramfs,而不是ramdisk,所以不用配置ramdisk的驱动支持项:

Device Drivers-->Block devices-->RAM block device support 不选项。相应的之后的(4096)Default RAM disk size kbytes等相关默认配置选项就不会再出现了。

另外 initramfs技术和ramdisk技术的另一个重要的区别就是initramfs并不是在内存中模拟出一个磁盘,所以也就不在需要ramdisk中所需的ext2驱动支持。所以,

File systems -->  < > Second extended fs support选项就可以取消了。

在这一步还有一个重要的区别就是需要在

General setup-->Initial RAM filesystem and RAM disk...... 项的相关项( ) Initramfs source file(s)中填写你要制作成initramfs格式的根文件系统目录,在这里我要做的根文件系统的目录是/work/rootfs。

步骤6.制作initramfs根文件系统
h)制作initramfs根文件系统镜像

制作最小系统根文件系统的步骤和以前制作ramdisk根文件系统的步骤基本一致,这里只说明最后一步有何不同。
因为initramfs根文件系统启动时执行的第一个程序是init,而不是linuxrc,所以在此,我们制作的根文件系统需要添加一个init文件,相应的linuxrc文件就不再需要了。
按照如下方式修改根文件系统
#cd /work/rootfs
#ln -s bin/busybox init
这样就为busybox创建了一个软链接init,这个文件就是我们要创建的init文件。

另外就是我们制作ramdisk根文件系统镜像的时候使用的是genext2fs工具,在此我们制作initramfs根文件系统镜像时,并不需要额外的步骤,而是在你编译Linux内核的时候就自动生成了。自动生成的initramfs根文件系统镜像在Linux源码树的usr目录下。名字叫initramfs_data.cpio.gz它是gz格式的压缩文件。

这样就有一个问题,在编译可以使用initramfs启动的内核的时候,它的配置选项有一个相关项,就是要在(/work/rootfs) Initramfs source file(s)中填写你要制作成initramfs格式的根文件系统目录。这样就要求我们在编译内核的时候,首先先把根文件系统做好。值得注意的是我们按照这个方法制作出来的内核镜像实际上比原来的大了许多,这是因为我们在做这一步的时候,实际上是将initramfs根文件系统直接合并到内核镜像里边了。这样,合二为一的镜像就不再需要单独烧写根文件系统镜像了,相应的,启动内核时的参数就不需要添加initrd=……来指定initramfs的位置了。当然如果你不想将initramfs合并到内核中,直接用配置ramdisk的内核来启动系统即可,不过这时你就必须使用initrd=……来指定 initramfs的位置了,并且第二个参数initramfs根文件系统映像的大小必须指定为实际大小,否则提示映像校验错误,无法启动系统。

其它的就没有区别了。

-------------------------------------------------------------------
一切工作做好了,uImage和initramfs_data.cpio.gz都已经编译出来了。
用u-boot下载内核镜像和initramfs根文件系统镜像,此时启动系统,最终内核恐慌kernel panic启动失败。
在超级终端的最后一行显示错误如下:
Unpacking initramfs...<0>Kernel panic - not syncing: bad gzip magic numbers

上网查阅了相关的错误,解决方案如下:
  “这个问题已经解决;
       是因为,我在u-boot传递给内核的initrd=bufptr,size;
  size这个参数中,大小比实际的initramfs的大小还大;
  导致unpack_to_rootfs在调用gunzip进行initramfs压缩包进行解压时,gunzip无法判断到initramfs压缩包的结束地址;进行重复的解  压导致的;(gunzip这个东东真不智能啊,呵呵)

  将size设置和initramfs压缩包的大小一致就OK了;”

如法炮制,系统启动成功。

 

烧写镜像

 

烧写一体化内核uImage-initramfs:

 

把uImage-initramfs用tftp下载到内存中,然后再固化到Nand Flash中

[Uboot]# tftp 0x31000000 uImage-initramfs  //将uImage.img下载到内存0x31000000处

[Uboot]# nand erase 0x80000 0x580000 //擦除nand的0x60000 0x560000的内容,一定大于镜像文件大小.0x40000-0x60000 是uboot环境变量的保存地址,在include/mini2440.h中定义#define CONFIG_ENV_OFFSET 0X60000  #define CONFIG_ENV_SIZE 0x20000

 

[Uboot]# nand write 0x31000000 0x80000 0x4CC000 //将内存0x31000000处的内容写入到nand的0x60000--0x4CC000处。文件大小的确定((uImage-initramfs大小/2048 +1)*2048)

 

从nand启动:

[Uboot]# nboot 0x31000000 0 0x80000

[Uboot]# bootm 0x31000000

 

设为上电自动启动:

[Uboot]# set bootcmd 'nboot 0x31000000 0 0x80000; bootm 0x31000000'

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值