利用uboot启动远程Kernel(TFTp)
来源:互联网 发布:尤克里里推荐知乎 编辑:程序博客网 时间:2024/06/05 05:27
0. 准备工作
1. 编译uboot
2. 将uboot写入SD卡
3. 编译kernel,设置其可以通过NFS挂载根文件系统
4. 开发环境安装TFTP服务器
5. 开发环境安装NFS服务器
6. 目标环境设置uboot参数
7. 制作根文件系统(optional)。
8. 完整的启动LOG。
有几位网友发信问我uboot挂载文件系统的方法,其实这个部分也不是我原创的,大部分都是参考其他网友的方法,现在将我的手顺记录下来,希望对大家有所帮助。
整体思路大概是这样:
* 将uboot烧写到SD卡。
* 从SD卡启动系统,SD卡中的uboot通过TFTP协议将远程的的Kernel下载到内存中。
* uboot将内核参数设定为ROOT分区为远程的NFS-SERVER共享的一个目录,并JUMP到内核的START ADDRESS。
* kernel自解压,并JUMP到解压后的新的内核START ADDRESS,内核正常启动。
* 最后通过内核通过uboot设置的ROOTFS参数得知根文件系统在远程,并通过NFS挂载ROOTFS。
* 根文件系统挂载完了以后,就会去执行init程序, init程序被uboot指定为 /linuxrc。
我的开发环境是 ubunto 12.04LTS。
目标系统的内核是 3.0.8,源代码位于 /opt/S5PV210/rootfs/usr/src/linux-3.0.8。
uboot的源代码位于 /opt/S5PV210/rootfs/usr/src/opencsbc-u-boot。
目标环境的根文件系统位于/opt/S5PV210/rootfs。
交叉编译器位于/opt/linaro-gcc473-eglibc216-armv7a-neon。
0. 准备工作
编译uboot和linux内核都需要使用到交叉编译器,所以需要确保shell的PATH 环境中包含了你的交叉编译器的路径。
比如我的PATH为:(通过export查看)
declare -xPATH="/usr/lib/lightdm/lightdm:/opt/linaro-gcc473-eglibc216-armv7a-neon/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
这样,就可以直接查找到 arm-linux-gcc这条命令了,不许要输入 arm-linux-gcc的绝对路径。
1. 编译uboot
uboot来自于kasim修改的uboot,原帖在http://www.arm9home.net/read.php?tid-16001.html。
可以通过https://gitorious.org/opencsbc/u-boot/trees/mini210_linaro-2012.11- stable右边的 download mini210_linaro-2012.11-stable astar.gz这个按钮获取到打包的源代码。
将源代码下载下来以后,解压到某一个目录,我机器上是位于/opt/S5PV210/rootfs/usr/src/opencsbc-u-boot这个目录。进入到这个目录。
首先配置uboot是针对 tiny210环境的。 tiny210v2 也是使用的这个配置项:
复制代码
- make ARCH=arm CROSS_COMPILE=arm-linux- tiny210_config
然后才是真正的编译uboot:
复制代码
- make ARCH=arm CROSS_COMPILE=arm-linux- all spl
编译完成以后,就可以看到uboot的二进制文件 spl/tiny210-spl.bin和 uboot.bin。
另外还有一个用于制作 uImage的工具 tool/mkimage。为了方便,把这个文件拷贝到 /usr/bin:
复制代码
- sudo cp tool/mkimage /usr/bin/
2. 将uboot写入SD卡
注意,这部需要特别留心,别因为误写入,把你的硬盘给弄坏了。
注意,SD卡的内容最好备份好。
将SD卡放到读卡器里面,并将SD卡读卡器接入开发环境,在我的环境中, SD卡会被识别为 /dev/sdc。
通过下面的命令将uboot写入SD卡,保证这个SD卡可以启动。
复制代码
- sudo dd iflag=dsync oflag=dsync if=spl/tiny210-spl.bin of=/dev/sdc seek=1
- sudo dd iflag=dsync oflag=dsync if=u-boot.bin of=/dev/sdc seek=49
如果怕写入不同步,可以再执行一下 sync这个命令,保证cache都写入到磁盘中。
到此为止,就可以通过SD卡启动uboot了。
3. 编译kernel,设置其可以通过NFS挂载根文件系统
光盘中带的内核,默认不支持从NFS挂载ROOTFS。需要重新配置并编译内核。
在/opt/S5PV210/rootfs/usr/src/linux-3.0.8目录下,通过 make menuconfig启动ncurses图形配置界面。
下面几个个内核配置项,必须选中。
复制代码
- * Networking support -> Networking options ->IP:kernel level autoconfiguration
注意,这个选项下面的 IP:DHCP support / IP:BOOTP support /IP:RARP aupport不能选。
因为我的开发环境中没有安装 DHCP server。开发板的 IP是在内核启动参数中指定的。
复制代码
- * File systems -> Network File System -> NFS client support
- * File systems -> Network File System -> NFS client support for NFS version 3 或者 4
- * File systems -> Network File System -> Root file system on NFS
将退出配置,并保存。
执行下面的命令生成 uImage内核镜像文件,这个过程其实是先生成了 zImage,然后调用了刚才uboot的那个 mkimage生成 uImage。
复制代码
- make uImage
下面的LOG表明 uImage生成了,位于 arch/arm/boot/uImage。
复制代码
- CHK include/linux/version.h
- CHK include/generated/utsrelease.h
- make[1]: `include/generated/mach-types.h' is up to date.
- CALL scripts/checksyscalls.sh
- CHK include/generated/compile.h
- Kernel: arch/arm/boot/Image is ready
- SHIPPED arch/arm/boot/compressed/lib1funcs.S
- AS arch/arm/boot/compressed/lib1funcs.o
- LD arch/arm/boot/compressed/vmlinux
- OBJCOPY arch/arm/boot/zImage
- Kernel: arch/arm/boot/zImage is ready
- UIMAGE arch/arm/boot/uImage
- Image Name: Linux-3.0.8-TINY210V2+
- Created: Wed Jan 23 21:10:56 2013
- Image Type: ARM Linux Kernel Image (uncompressed)
- Data Size: 3555872 Bytes = 3472.53 kB = 3.39 MB
- Load Address: 20008000
- Entry Point: 20008000
- Image arch/arm/boot/uImage is ready
编译内核的时候,如果你使用的是 4.6以后的 gcc,需要在Makefile中添加 -mno-unaligned-access 给 KBUILD_CFLAGS防止内核解压完以后启动不了。
复制代码
- 367 KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
- 368 -fno-strict-aliasing -fno-common \
- 369 -Werror-implicit-function-declaration \
- 370 -Wno-format-security \
- 371 -fno-delete-null-pointer-checks \
- 372 -mno-unaligned-access
如果你生成的内核有问题,可以试一试我的内核配置文件 my_config。
4. 开发环境安装TFTP服务器
接下来,就是要在开发环境上安装 TFTP服务器,使开发板可以通过TFTP协议下载 uImage这个文件。
在 ubuntu 下,可以通过下面的命令安装 TFTP 服务器,这个服务是通过 inet 监听的。
复制代码
- sudo apt-get install atftpd openbsd-inetd
安装完以后,需要配置一下 TFTP的默认查找目录,我将其设定为 /srv/tftp:
确认 /etc/inetd.conf文件中有如下一行:
复制代码
- #:BOOT: TFTP service is provided primarily for booting. Most sites
- # run this only on machines acting as "boot servers."
- tftp dgram udp wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd /srv/tftp
因为 TFTP服务主要是给 uboot提供内核镜像文件,为了避免每次内核编译完以后都拷贝到 /srv/tftp目录中,
我在 /srv/tftp 目录中,建立了一个符号文件,指向 /opt/S5PV210/rootfs/usr/src/linux-3.0.8/arch/arm/boot/uImage。
复制代码
- ln -s /opt/S5PV210/rootfs/usr/src/linux-3.0.8/arch/arm/boot/uImage /srv/tftp/uImage
可以通过下面的命令重启 inetd,保证这个 supper服务器能够监听 TFTP端口:
复制代码
- sudo service openbsd-inetd restart
可以通过查看端口确认 inetd是否真的在监听 TFTP 端口:
复制代码
- zoulz@Seagate:/tmp$ netstat -a | grep tftp
- udp 0 0 *:tftp *:*
可以通过下面的命令测试一下 TFTP服务是否正常工作:
复制代码
- zoulz@Seagate:/tmp$ tftp localhost
- tftp> get uImage
- Received 3578106 bytes in 0.3 seconds
5. 开发环境安装NFS服务器
接下来是配置 NFS 服务器,用于开发板上内核启动以后挂载开发环境的ROOTFS。
通过下面的命令安装 nfs服务器:
复制代码
- sudo apt-get install nfs-kernel-server
安装完成以后,还需要修改 /etc/exports文件,设置 NFS 共享的文件目录。我们需要将 /opt/S5PV210/rootfs设置为NFS共享目录。
复制代码
- # Example for NFSv2 and NFSv3:
- # /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
- #
- # Example for NFSv4:
- # /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
- # /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
- #
- /opt/S5PV210/rootfs *(rw,sync,no_subtree_check,no_root_squash)
每一次修改 /etc/exports这个文件,都需要重新启动 NFS 服务器:
复制代码
- sudo service nfs-kernel-server restart
可以通过下面的命令测试 NFS服务器是否设置正确:
复制代码
- zoulz@Seagate:/tmp$ rm a b
- zoulz@Seagate:/tmp$ mkdir /tmp/a
- zoulz@Seagate:/tmp$ sudo mount -t nfs -o nolock localhost:/opt/S5PV210/rootfs /tmp/a
- zoulz@Seagate:/tmp$ ls /tmp/a
- bin dev etc home lib linuxrc proc root run sbin sys tmp usr var
- zoulz@Seagate:/tmp$ ls /opt/S5PV210/rootfs
- bin dev etc home lib linuxrc proc root run sbin sys tmp usr var
也可以通过 df命令查看挂载情况:
复制代码
- zoulz@Seagate:/tmp$ df
- Filesystem 1K-blocks Used Available Use% Mounted on
- localhost:/opt/S5PV210/rootfs 125439744 36394112 89045632 30% /tmp/a
6. 目标环境设置uboot参数
注意: ubuntu的 network manager,如果开发板和开发环境的PC直连的话,每次开发板哪掉电,开发环境PC会检测为网络未链接,
nm 就会将已经设置好的网卡 down掉。这在开发板reset的时候特别讨厌,你得每次都重新去设置PC的IP地址。
因此我将桌面右上角的network manager的 Enable Networking设置为不选中,禁止 network manager去管理网络。
然后在终端里通过下面的命令,将网卡设置为 192.168.1.5,这样每次开发板reset就不用再设置开发环境PC的IP了。
复制代码
- sudo ifconfig eth0 192.168.1.5
当然,如果你的开发板和开发环境PC都是链接到路由器或者HUB,就没有这个烦恼。
现在所有的东西都准备好了。将SD卡插入开发板,并调整switch,设置从SD卡启动系统。
正常情况下,就应该能够看到 uboot的界面了( FriendlyLEG-TINY210)了:
在 uboot 的shell中,通过 setenv命令设置相关参数。
复制代码
- setenv baudrate 115200
- setenv stderr serial
- setenv stdin serial
- setenv stdout serial
- setenv bootdelay 3
- setenv ethact dm9000
- setenv ethaddr 00:40:5c:26:0a:5b
- setenv gatewayip 192.168.1.1
- setenv ipaddr 192.168.1.80
- setenv netmask 255.255.255.0
- setenv serverip 192.168.1.5
- setenv bootargs root=/dev/nfs rw nfsroot=$serverip:/opt/S5PV210/rootfs,nolock,tcp ip=$ipaddr console=ttySAC0,115200 ctp=1 kgdboc=ttySAC0,115200
- setenv bootcmd "tftp 21000000 uImage;bootm 21000000"
bootcmd参数中的 tftp 21000000用于:通过 TFTP命令,将 192.168.1.5 的 /srv/tftp/uImage 下载到 0x21000000 这个位置。
bootcmd参数中的 bootm 21000000用于: uboot将CPU执行权地交给 0x21000000这个位置的内核镜像,也就是启动内核。
bootargs参数用于设置内核的启动参数,其中 root=/dev/fs rwnfsroot=$serverip:/opt/S5PV210/rootfs,nolock,tcp告诉内核通过NFS启动,
根文件系统位于192.168.1.5:/opt/S5PV210/rootfs
NFS 的参数为 nolock,tcp,用于防止 udp 不稳定导致 NFS 读取NG的情况。
ip=$ipaddr 设置开发板自身的ip地址为 192.168.1.80。
通过 saveenv 将上面的参数写入到 SD卡中,这样就不用每次reset都输入一遍uboot的参数了。
通过 boot 命令,将CPU 执行权专递给 Kernel。
7. 制作根文件系统(optional)。
待续,busybox + toolchain。
- 利用uboot启动远程Kernel(TFTp)
- 利用uboot启动远程Kernel(TFTP)以及挂载远程ROOTFS(NFS)
- 利用uboot启动远程Kernel(TFTP)以及挂载远程ROOTFS(NFS)
- 移植5- uboot之tftp启动kernel
- linux uboot,kernel启动流程
- uboot通过tftp来启动内核
- mini2440_NFS 利用uboot启动
- mini2440_NFS 利用uboot启动
- mini2440_NFS 利用uboot启动
- qemu利用uboot启动
- Uboot启动流程和Kernel启动流程
- Uboot tftp
- uboot之u盘启动kernel
- uboot之u盘启动kernel
- kernel如何得到uboot启动信息
- kernel如何得到uboot启动信息
- tq210-自带uboot启动kernel
- [uboot] uboot启动kernel篇(三)——uboot解析uImage的kernel信息
- 我把 最深沉的秘密放在那里
- Android overridePendingTransition 失效问题解决
- JavaScript利用URL向后台传入中文参数乱码问题解决之道!
- 第四章知识导图
- 注册表修改PSD关联photoshop
- 利用uboot启动远程Kernel(TFTp)
- Chrome 程序启动
- Using Android's TextureView to Display Video Mirrored
- android 中的4种activity启动模式(launchMode)
- iOS开发学习之#提醒处理#(1)响应提醒视图
- 备忘录模式
- 友盟自定义事件的使用方法
- 嵌入式高手谈嵌入式
- iOS UItableView+UINavigationController实现单元格的删除