现在的位置: 首页 > 综合 > 正文

利用uboot启动远程Kernel(TFTp)

2018年04月17日 ⁄ 综合 ⁄ 共 7976字 ⁄ 字号 评论关闭

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. 准备工作

    编译ubootlinux内核都需要使用到交叉编译器,所以需要确保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
也是使用的这个配置项:

复制代码

  1.         make ARCH=arm CROSS_COMPILE=arm-linux- tiny210_config


    然后才是真正的编译uboot

复制代码

  1.         make ARCH=arm CROSS_COMPILE=arm-linux- all spl


    编译完成以后,就可以看到uboot的二进制文件 spl/tiny210-spl.bin
uboot.bin

    另外还有一个用于制作 uImage
的工具 tool/mkimage。为了方便,把这个文件拷贝到 /usr/bin

复制代码

  1.         sudo cp tool/mkimage  /usr/bin/

2. uboot写入SD

    注意,这部需要特别留心,别因为误写入,把你的硬盘给弄坏了。
    
注意,SD卡的内容最好备份好。

    SD卡放到读卡器里面,并将SD卡读卡器接入开发环境,在我的环境中, SD卡会被识别为
/dev/sdc

    通过下面的命令将uboot写入SD卡,保证这个SD卡可以启动。

复制代码

  1.     sudo dd iflag=dsync oflag=dsync if=spl/tiny210-spl.bin of=/dev/sdc seek=1
  2.     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图形配置界面。
    
下面几个个内核配置项,必须选中。

复制代码

  1.     * Networking support -> Networking options ->IP:kernel level autoconfiguration


        注意,这个选项下面的 IP:DHCP support / IP:BOOTP support /IP:RARP aupport
不能选。
        
因为我的开发环境中没有安装 DHCP server。开发板的 IP
是在内核启动参数中指定的。

复制代码

  1.     * File systems -> Network File System -> NFS client support
  2.     * File systems -> Network File System -> NFS client support for NFS version 3 或者 4
  3.     * File systems -> Network File System -> Root file system on NFS


    
    将退出配置,并保存。
    
执行下面的命令生成 uImage
内核镜像文件,这个过程其实是先生成了 zImage
,然后调用了刚才uboot的那个 mkimage
生成 uImage

复制代码

  1.         make uImage

    下面的LOG表明 uImage
生成了,位于 arch/arm/boot/uImage

复制代码

  1.       CHK     include/linux/version.h
  2.       CHK     include/generated/utsrelease.h
  3.     make[1]: `include/generated/mach-types.h' is up to date.
  4.       CALL    scripts/checksyscalls.sh
  5.       CHK     include/generated/compile.h
  6.       Kernel: arch/arm/boot/Image is ready
  7.       SHIPPED arch/arm/boot/compressed/lib1funcs.S
  8.       AS      arch/arm/boot/compressed/lib1funcs.o
  9.       LD      arch/arm/boot/compressed/vmlinux
  10.       OBJCOPY arch/arm/boot/zImage
  11.       Kernel: arch/arm/boot/zImage is ready
  12.       UIMAGE  arch/arm/boot/uImage
  13.     Image Name:   Linux-3.0.8-TINY210V2+
  14.     Created:      Wed Jan 23 21:10:56 2013
  15.     Image Type:   ARM Linux Kernel Image (uncompressed)
  16.     Data Size:    3555872 Bytes = 3472.53 kB = 3.39 MB
  17.     Load Address: 20008000
  18.     Entry Point:  20008000
  19.       Image arch/arm/boot/uImage is ready


    编译内核的时候,如果你使用的是 4.6以后的 gcc,需要在Makefile中添加
-mno-unaligned-access
KBUILD_CFLAGS
防止内核解压完以后启动不了。

复制代码

  1.          367 KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
  2.          368            -fno-strict-aliasing -fno-common \
  3.          369            -Werror-implicit-function-declaration \
  4.          370            -Wno-format-security \
  5.          371            -fno-delete-null-pointer-checks \
  6.          372            -mno-unaligned-access

    如果你生成的内核有问题,可以试一试我的内核配置文件 my_config

4. 开发环境安装TFTP服务器

    接下来,就是要在开发环境上安装 TFTP
服务器,使开发板可以通过TFTP协议下载 uImage
这个文件。
    
ubuntu
下,可以通过下面的命令安装 TFTP
服务器,这个服务是通过 inet
监听的。

复制代码

  1.         sudo apt-get install atftpd openbsd-inetd

    安装完以后,需要配置一下 TFTP
的默认查找目录,我将其设定为 /srv/tftp
    
确认 /etc/inetd.conf
文件中有如下一行:

复制代码

  1.         #:BOOT: TFTP service is provided primarily for booting.  Most sites
  2.         #       run this only on machines acting as "boot servers."
  3.         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

复制代码

  1.         ln -s /opt/S5PV210/rootfs/usr/src/linux-3.0.8/arch/arm/boot/uImage  /srv/tftp/uImage

    可以通过下面的命令重启 inetd
,保证这个 supper服务器能够监听 TFTP
端口:

复制代码

  1.         sudo service  openbsd-inetd restart

    可以通过查看端口确认 inetd
是否真的在监听 TFTP
端口:

复制代码

  1.         zoulz@Seagate:/tmp$ netstat  -a | grep tftp
  2.         udp        0      0 *:tftp                  *:*  

    可以通过下面的命令测试一下 TFTP
服务是否正常工作:

复制代码

  1.         zoulz@Seagate:/tmp$ tftp localhost
  2.         tftp> get uImage
  3.         Received 3578106 bytes in 0.3 seconds

5. 开发环境安装NFS服务器

    
接下来是配置 NFS
服务器,用于开发板上内核启动以后挂载开发环境的ROOTFS

    通过下面的命令安装 nfs
服务器:

复制代码

  1.         sudo apt-get  install nfs-kernel-server

    安装完成以后,还需要修改 /etc/exports
文件,设置 NFS
共享的文件目录。我们需要将 /opt/S5PV210/rootfs
设置为NFS共享目录。

复制代码

  1.         # Example for NFSv2 and NFSv3:
  2.         # /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
  3.         #
  4.         # Example for NFSv4:
  5.         # /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
  6.         # /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
  7.         #
  8.         /opt/S5PV210/rootfs *(rw,sync,no_subtree_check,no_root_squash)

    每一次修改 /etc/exports
这个文件,都需要重新启动 NFS
服务器:

复制代码

  1.          sudo service nfs-kernel-server restart

    可以通过下面的命令测试 NFS
服务器是否设置正确:

复制代码

  1.         zoulz@Seagate:/tmp$ rm a b
  2.         zoulz@Seagate:/tmp$ mkdir /tmp/a
  3.         zoulz@Seagate:/tmp$ sudo mount -t nfs -o nolock localhost:/opt/S5PV210/rootfs /tmp/a
  4.         zoulz@Seagate:/tmp$ ls /tmp/a
  5.         bin  dev  etc  home  lib  linuxrc  proc  root  run  sbin  sys  tmp  usr  var
  6.         zoulz@Seagate:/tmp$ ls /opt/S5PV210/rootfs
  7.         bin  dev  etc  home  lib  linuxrc  proc  root  run  sbin  sys  tmp  usr  var

    也可以通过 df
命令查看挂载情况:

复制代码

  1.         zoulz@Seagate:/tmp$ df
  2.         Filesystem                    1K-blocks     Used Available Use% Mounted on
  3.         localhost:/opt/S5PV210/rootfs 125439744 36394112  89045632  30% /tmp/a

6. 目标环境设置uboot参数

    注意: ubuntu
network manager如果开发板和开发环境的PC直连的话,每次开发板哪掉电,开发环境PC会检测为网络未链接,
        nm
就会将已经设置好的网卡 down
掉。这在开发板reset的时候特别讨厌,你得每次都重新去设置PCIP地址。

    因此我将桌面右上角的network manager Enable Networking
设置为不选中,禁止 network manager
去管理网络。
    
然后在终端里通过下面的命令,将网卡设置为 192.168.1.5,这样每次开发板reset就不用再设置开发环境PCIP了。

复制代码

  1.         sudo ifconfig eth0 192.168.1.5

    当然,如果你的开发板和开发环境PC都是链接到路由器或者HUB,就没有这个烦恼。

    现在所有的东西都准备好了。将SD卡插入开发板,并调整switch,设置从SD卡启动系统。

    正常情况下,就应该能够看到 uboot
的界面了( FriendlyLEG-TINY210
)了:
    
uboot
shell中,通过 setenv
命令设置相关参数。

复制代码

  1.         setenv baudrate 115200
  2.         setenv stderr serial
  3.         setenv stdin  serial
  4.         setenv stdout serial
  5.         setenv bootdelay 3
  6.         setenv ethact dm9000
  7.         setenv ethaddr 00:40:5c:26:0a:5b
  8.         setenv gatewayip 192.168.1.1
  9.         setenv ipaddr 192.168.1.80
  10.         setenv netmask 255.255.255.0
  11.         setenv serverip 192.168.1.5
  12.         setenv bootargs root=/dev/nfs rw nfsroot=$serverip:/opt/S5PV210/rootfs,nolock,tcp ip=$ipaddr console=ttySAC0,115200 ctp=1 kgdboc=ttySAC0,115200
  13.         setenv bootcmd "tftp 21000000 uImage;bootm 21000000"

    bootcmd参数中的 tftp 21000000
用于:通过 TFTP
命令,将 192.168.1.5
/srv/tftp/uImage
下载到 0x21000000 这个位置。
    bootcmd
参数中的 bootm 21000000
用于: ubootCPU执行权地交给 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。

抱歉!评论已关闭.