利用u-boot的NFS命令烧写Linux内核和设备树
参考资料:
基于Exynos4412的嵌入式Linux的几种启动方式分析
ubuntu18.04上配置tftp服务器解决Transfer timed out——利用u-boot的tftp加载kernel
0、Linux内核被读入RAM的几种方式
Linux内核的烧写方式有多种,nfs加载内核是其中一种,具体可参考以下博文:
基于Exynos4412的嵌入式Linux的几种启动方式分析
利用u-boot的nfs
命令加载kernel,使得kernel修改编译后,通过网口就可以烧写进RAM,无需重新烧写Nand Flash,在调试阶段很方便。
但是,nfs烧写速度慢,所以绝大多数情况下是利用tftp服务器烧写内核和设备树,利用nfs挂载根文件系统。利用nfs挂载根文件系统的方法是类似的。利用u-boot的tftp加载kernel可以参考我的另一篇博文:
ubuntu18.04上配置tftp服务器解决Transfer timed out——利用u-boot的tftp加载kernel
1、Ubuntu18.04安装和配置nfs服务器
(1)安装nfs服务器
- 安装nfs:1
sudo apt-get install nfs-kernel-server
- 建立一个nfs服务的专有文件夹2
sudo mkdir -p CBT-SuperIOT/nfsboot
server_args指定nfs的目录,我这里是一个链接,指向源码的boot目录
ln -s /CBT-SuperIOT/nfsboot/ /nfsboot
然后将目录权限增大一点,以防万一
chmod 777 /nfsboot
chmod 777 /CBT-SuperIOT/nfsboot/
- 配置exports
建立好文件夹后,接着执行命令:sudo vim /etc/exports
配置nfs
在文章的最后一行添加:/CBT-SuperIOT *(rw,sync,no_root_squash,no_subtree_check)
rw:挂接此目录的客户端对该共享目录具有读写权限
sync:资料同步写入内存和硬盘
no_root_squash:root用户具有对根目录的完全管理访问权限。
no_subtree_check:不检查父目录的权限。
修改完上述配置文件保存退出。
- 启动 RPC 服务
service rpcbind start
- 启动nfs服务
service nfs-kernel-server restart
- 查看注册的端口列表
rpcinfo -p localhost
- 在服务端看下是否正确加载了设置的 /etc/exports 配置
showmount -e localhost
(2)测试nfs服务器
- 用ip addr命令查看网卡的名称为enp0s3和enp0s8。虚拟网卡enp0s3采用桥接方式,实现宿主机与目标机之间的NFS共享。虚拟网卡enp0s8采用桥接方式,用于虚拟机通过主机连接互联网,安装工具包。
- 使用netplan配置虚拟机Ubuntu18.04的静态IP地址
Ubuntu 18.04使用netplan配置网络,其配置文件在/etc/netplan/目录下,默认的配置文件名为01-network-manager-all.yaml,是yaml格式的。先把源文件做个备份:
sudo cp 01-network-manager-all.yaml 01-network-manager-all.yaml.bak
然后通过vim或者gedit修改它。虚拟网卡的IP地址根据自己系统的实际情况修改。我的IP地址如下:
network:
ethernets:
enp0s3:
addresses: [192.168.1.7/24]
gateway4: 192.168.1.1
#dhcp4: no
nameservers:
addresses:
- 8.8.8.8
enp0s8:
addresses: [192.168.3.111/24]
gateway4: 192.168.3.1
#dhcp4: true
nameservers:
addresses:
- 202.103.24.68
version: 2
#renderer: NetworkManager
- 重启网络服务使配置生效。命令如下:
$ sudo netplan apply
- 用ip addr命令查看是否生效。
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:b3:52:7f brd ff:ff:ff:ff:ff:ff
inet 192.168.1.7/24 brd 192.168.1.255 scope global enp0s3
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:feb3:527f/64 scope link
valid_lft forever preferred_lft forever
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:fd:b5:0f brd ff:ff:ff:ff:ff:ff
inet 192.168.3.111/24 brd 192.168.3.255 scope global enp0s8
valid_lft forever preferred_lft forever
inet6 fe80::bd0c:e183:728a:defd/64 scope link noprefixroute
valid_lft forever preferred_lft forever
- 最后用ping命令查看局域网是否连通。
在u-boot中利用ping
命令查看
[05:31:04:369] CBT4412 #ping 192.168.1.7␍␊
[06:05:46:101] dm9000 i/o: 0x5000000, id: 0x90000a46 ␍␊
[06:05:46:105] DM9000: running in 16 bit mode␍␊
[06:05:46:118] MAC: 00:11:22:33:44:55␍␊
[06:05:48:091] operating at 100M full duplex mode␍␊
[06:05:48:095] Using dm9000 device␍␊
[06:05:51:313] host 192.168.1.7 is alive␍␊
- 在本地Linux系统中测试NFS共享
在/mnt目录下新建目录/mnt/nfs,然后挂载nfs服务器共享目录,最后查看/nfs目录中是否存在共享目录中的文件。
sudo mkdir /mnt/nfs
sudo chmod 776 /mnt/nfs
sudo mount -t nfs -o nolock 192.168.1.7:/CBT-SuperIOT/nfsboot /mnt/nfs/
ls /mnt/nfs
exynos4412-cbt4412.dtb ramdisk-u.img rootfs_qtopia_qt4.img uImage zImage
2、对u-boot的环境变量进行配置
- 首先用printenv看看原始的环境变量
CBT4412 # printenv
baudrate=115200
bootargs=root=/dev/mmcblk0p1 rootfstype=ext4 console=ttySAC0,115200 init=/linuxrc skipcali=y lcd=S70 ctp=2
bootcmd=movi read linux_kernel 0 40008000;movi read linux_ramdisk 0 41000000 100000;bootm 40008000 41000000
bootdelay=3
ethaddr=00:40:5c:26:0a:5b
gatewayip=192.168.0.1
ipaddr=192.168.0.20
netmask=255.255.255.0
serverip=192.168.0.10
Environment size: 374/16380 bytes
- 根据虚拟机Ubuntu18.04的nfs服务器修改环境变量
setenv ipaddr 192.168.1.230
setenv serverip 192.168.1.7
setenv gatewayip 192.168.1.1
其中,ipaddr是本地IP;serverip是nfs服务器IP;gatewayip是网关IP。根据自己的实际情况更改IP地址。
- 利用u-boot自带的nfs命令,就可以烧写内核和设备树了。
nfs 41000000 192.168.1.7:/CBT-SuperIOT/nfsboot/uImage
nfs 42000000 192.168.1.7:/CBT-SuperIOT/nfsboot/exynos4412-cbt4412.dtb
bootm 41000000 - 42000000
41000000表示烧写RAM的地址,默认是十六进制。
bootm 命令用于启动内核映像运行,其语法为:
bootm [address of kernel] [address of ramdisk] [address of dtb]
。
kernel image的地址是必须的,但是如果内核配置不需要ramdisk和dtb的地址可以省略。 如果有 dtb 但没有 ramdisk。ramdisk 地址可以用破折号 (-) 代替。 例如:
bootm 41000000 - 42000000
运行结果如下:
[05:03:19:666] CBT4412 #nfs 42000000 192.168.1.7:/CBT-SuperIOT/nfsroot/exynos4412-cbt4412.dtb␍␊
[05:05:32:024] dm9000 i/o: 0x5000000, id: 0x90000a46 ␍␊
[05:05:32:032] DM9000: running in 16 bit mode␍␊
[05:05:32:032] MAC: 00:11:22:33:44:55␍␊
[05:05:34:199] operating at 100M full duplex mode␍␊
[05:05:34:203] Using dm9000 device␍␊
[05:05:34:203] File transfer via NFS from server 192.168.1.7; our IP address is 192.168.1.230␍␊
[05:05:34:268] Filename '/CBT-SuperIOT/nfsroot/exynos4412-cbt4412.dtb'.␍␊
[05:05:34:268] Load address: 0x42000000␍␊
[05:05:34:268] Loading: *<0x08>##########T T T T T T T T T T T T T ␍␊
[05:07:51:256] done␍␊
[05:07:51:256] Bytes transferred = 46112 (b420 hex)␍␊
但是,启动Linux内核还需要可行的内核、设备树以及正确的bootargs、bootcmd。这里仅仅展示nfs烧写。
nfs烧写速度慢,所以绝大多数情况下是利用tftp服务器烧写内核和设备树。
利用u-boot的tftp加载kernel可以参考我的另一篇博文:
ubuntu18.04上配置tftp服务器解决Transfer timed out——利用u-boot的tftp加载kernel