LV09-03-linux-01-内核加载
本文主要是linux——内核加载的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows | windows11 |
Ubuntu | Ubuntu16.04的64位版本 |
VMware® Workstation 16 Pro | 16.2.3 build-19376536 |
SecureCRT | Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日 |
Linux开发板 | 华清远见 底板: FS4412_DEV_V5 核心板: FS4412 V2 |
u-boot | 2013.01 |
点击查看本文参考资料
参考方向 | 参考原文 |
--- | --- |
点击查看相关文件下载
文件 | 下载链接 |
exynos4412-fs4412.rar | 设备树文件 |
ramdisk.rar | linux镜像 |
roofs.rar | 根文件系统(通过nfs共享给开发板的时候用) |
ramdisk.rar | 根文件系统镜像 |
一、所需文件下载
开篇我放了自己在蓝奏云存储的几个文件,我们可以下载下来并解压,然后我们会的到下边几个文件:
这些文件都存放在windows
与ubuntu
共享目录下,在ubuntu
中共享文件路径为:
1 | /mnt/hgfs/Sharedfiles/test/linux |
二、加载方式与准备工作
1. 加载方式简介
我们可以有以下几种方式来加载linux
内核和根文件系统:
方式一 | tftp加载linux内核,tftp加载rootfs根文件系统 |
方式二 | eMMC加载linux内核,eMMC加载rootfs根文件系统 |
方式三 | tftp加载linux内核,nfs加载rootfs根文件系统 |
后边将详细介绍这三种方式。
2. 加载前的准备
2.1 网络设置
我们首先要设置开发板中的服务器IP
和ubuntu
服务器IP
,在SecureCRT
终端中执行以下命令:
1 | fs4412 # setenv ipaddr 192.168.10.102 |
2.2 tftp
首先我们要保证自己已经安装了tftp
,并且可以正常使用,我的ubuntu
服务器ip
与tftp
目录如下:
1 | 192.168.10.101:/home/hk/3tftp |
由于我已经在开发板中设置了serverip
为192.168.10.101
,且所有fs4412
在linux
内核加载和根文件系统加载中所需的文件都放在下面的路径中:
1 | /home/hk/3tftp/fs4412 |
故后边在开发板的交互界面可以直接通过下边类似命令下载文件:
1 | fs4412 # tftp 40008000 /fs4412/clear.bin |
2.3 nfs
后边会用到nfs
来挂载根文件系统,所以我们需要确保我们的ubuntu
服务器已经设置好了nfs
共享文件夹,我设置的文件夹为:
1 | /home/hk/4nfs |
2.4 文件准备
之前我们已经将相关文件下载并解压到了ubuntu
与windows
下的共享目录中,接下来就是将相关文件拷贝到3tftp/fs4412
或者nfd
路径下了,相关拷贝命令如下:
~/3tftp/fs4412/
路径下需要有的文件
1 | hk@vm:~$ cp /mnt/hgfs/Sharedfiles/test/linux/exynos4412-fs4412.dtb ~/3tftp/fs4412/ |
~/nfs
路径下需要有的文件(方式三会使用)
1 | hk@vm:~$ cp /mnt/hgfs/Sharedfiles/test/linux/roofs/rootfs.tar.bz2 ~/nfs/ |
这个文件复制完毕之后我们还需要进行解压,我们可以在终端执行以下命令:
1 | hk@vm:~$ cd ~/nfs/ |
三、加载方式一
方式一就是我们通过tftp
来加载linux
系统内核和rootfs
根文件系统。
1. 修改bootcmd
我们修改一下uboot
的启动参数,让其在启动后读秒结束直接从ubuntu
下载相关文件并启动linux
内核。我们在secureCRT
终端执行以下命令:
1 | fs4412 # setenv bootcmd tftp 0x41000000 /fs4412/uImage\;tftp 0x42000000 /fs4412/exynos4412-fs4412.dtb\;tftp 0x43000000 /fs4412/ramdisk.img\;bootm 0x41000000 0x43000000 0x42000000 |
然后我们打印一下这个环境变量的值,检查一下:
1 | fs4412 # printenv bootcmd |
【注意】
(1)多条命令之间用\;
分隔开。
(2)bootm
参数顺序为内核的下载地址、根文件系统的下载地址、设备树的下载地址。
2. 修改bootargs
我们还需要修改一下传给linux
的参数信息,也就是修改一下bootargs
环境变量的值。我们在secureCRT
终端执行以下命令:
1 | fs4412 # setenv bootargs root=/dev/nfs nfsroot=192.168.10.101:/home/hk/4nfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.10.102 |
然后我们打印一下这个环境变量的值,检查一下:
1 | fs4412 # printenv bootargs |
【注意】
(1)nfsroot=192.168.10.101
后边那个IP
为ubuntu
服务器的IP
,ip=192.168.10.102
后边的这个IP
为开发板自己的IP
,需要确保这两个IP
处于同一网段。
(2)该种加载方式的根文件系统并非来自于nfs
共享目录,而是来自于根文件系统镜像。
3. 重启开发板
3.1 uImage
文件加载
1 | dm9000 i/o: 0x5000000, id: 0x90000a46 |
3.2 exynos4412-fs4412.dtb
文件加载
1 | dm9000 i/o: 0x5000000, id: 0x90000a46 |
3.3 ramdisk.img
文件加载
1 | dm9000 i/o: 0x5000000, id: 0x90000a46 |
3.4 三个文件检测信息
1 | # Booting kernel from Legacy Image at 41000000 ... |
3.5 启动内核
1 | Starting kernel ... |
当我们看到这个信息的时候,说明后边的操作将会启动linux
内核。
3.6 挂载根文件系统
在内核安装完毕之后,会进行根文件系统挂载,挂载完成将会有以下信息提示:
1 | [ 2.145000] VFS: Mounted root (ext2 filesystem) on device 1:0. |
4. 启动成功
当我们的开发板加载linux
内核并启动成功的时候,我们可以运行一个ls
命令来检测一下:
四、加载方式二
通过方式一我们虽然可以加载Linux
内核和根文件系统并正常运行,但方式一我们是把内核镜像、设备树、根文件系统镜像都放到了tftp
服务器上,然后开发板上电之后再通过tftp
去下载这些文件到开发板的内存中运行;但在实际我们不可能每次开机都通过网络去服务器上下载这些镜像,所以以下步骤我们就将这些镜像安装到开发板上的eMMC
中,然后从EMMC
启动内核。
下边我们就来使用加载方式二,通过eMMC
来加载linux
内核和rootfs
根文件系统。
1. 相关文件下载
1.1 linux
镜像
- 下载内核镜像到内存中
1 | fs4412 # tftp 0x41000000 /fs4412/uImage |
下载完成会有以下提示信息:
1 | dm9000 i/o: 0x5000000, id: 0x90000a46 |
- 将内核镜像写入到
eMMC
中指定的扇区
uImage
大小为2.9M
,也就是2.9 * 1024 * 1024 = 3040870.4
字节,写入到eMMC
的时候,每个块,或者说扇区的大小为512
字节,所以uImage
一共会占3040870.4 / 512 = 5939.2
个扇区,大概就是5940
个扇区,换算为十六进制为0x1734
,所以使用的扇区数量我们可以设置为0x2000
。
1 | fs4412 # mmc write 0 0x41000000 0x800 0x2000 |
写入成功会有以下提示信息:
1 | MMC write: dev # 0, block # 2048, count 8192. 8192 blocks write finish |
1.2 设备树
- 下载设备树到内存中
1 | fs4412 # tftp 0x41000000 /fs4412/exynos4412-fs4412.dtb |
下载完成会有以下提示信息:
1 | dm9000 i/o: 0x5000000, id: 0x90000a46 |
- 将设备树写入到
eMMC
中指定的扇区
exynos4412-fs4412.dtb
大小为34K
,也就是34 * 1024 = 34816
字节,写入到eMMC
的时候,每个块,或者说扇区的大小为512
字节,所以exynos4412-fs4412.dtb
一共会占34816 / 512 = 68
个扇区,换算为十六进制为0x44
,所以使用的扇区数量我们可以设置为0x800
。
1 | fs4412 # mmc write 0 0x41000000 0x2800 0x800 |
写入成功会有以下提示信息:
1 | MMC write: dev # 0, block # 10240, count 2048. 2048 blocks write finish |
1.3 根文件系统镜像
- 下载根文件系统镜像到内存中
1 | fs4412 # tftp 0x41000000 /fs4412/ramdisk.img |
下载完成会有以下提示信息:
1 | dm9000 i/o: 0x5000000, id: 0x90000a46 |
- 将根文件系统镜像写入到
eMMC
中指定的扇区
ramdisk.img
大小为2.5M
,也就是2.5 * 1024 * 1024 = 2621440
字节,写入到eMMC
的时候,每个块,或者说扇区的大小为512
字节,所以ramdisk.img
一共会占2621440 / 512 = 5120
个扇区,换算为十六进制为0x1400
,所以使用的扇区数量我们可以设置为0x2000
。
1 | fs4412 # mmc write 0 0x41000000 0x3000 0x2000 |
写入成功会有以下提示信息:
1 | MMC write: dev # 0, block # 12288, count 8192. 8192 blocks write finish |
2. 修改bootcmd
我们在secureCRT
终端执行以下命令:
1 | fs4412 # setenv bootcmd mmc read 0 0x41000000 0x800 0x2000\;mmc read 0 0x42000000 0x2800 0x800\;mmc read 0 0x43000000 0x3000 0x2000\;bootm 0x41000000 0x43000000 0x42000000 |
点击查看可能出现的问题及解决方式
我们按下enter
按键确认的时候可能会有以下提示信息:
1 | setenv - set environment variables |
这个时候我们可以这样解决,将命令用' '
包裹:
1 | fs4412 # setenv bootcmd 'mmc read 0 0x41000000 0x800 0x2000\;mmc read 0 0x42000000 0x2800 0x800\;mmc read 0 0x43000000 0x3000 0x2000\;bootm 0x41000000 0x43000000 0x42000000' |
然后我们打印一下这个环境变量的值,检查一下:
1 | fs4412 # printenv bootcmd |
【注意】
(1)多条命令之间用\;
分隔开。
(2)bootm
参数顺序为内核的下载地址、根文件系统的下载地址、设备树的下载地址。
3. 修改bootargs
我们还需要修改一下传给linux
的参数信息,也就是修改一下bootargs
环境变量的值。我们在secureCRT
终端执行以下命令:
1 | fs4412 # setenv bootargs root=/dev/nfs nfsroot=192.168.10.101:/home/hk/4nfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.10.102 |
然后我们打印一下这个环境变量的值,检查一下:
1 | fs4412 # printenv bootargs |
【注意】
(1)nfsroot=192.168.10.101
后边那个IP
为ubuntu
服务器的IP
,ip=192.168.10.102
后边的这个IP
为开发板自己的IP
,需要确保这两个IP
处于同一网段。
(2)该种加载方式的根文件系统并非来自于nfs
共享目录,而是来自于根文件系统镜像。
4. 重启开发板
4.1 uImage
文件加载
1 | MMC read: dev # 0, block # 2048, count 8192 ...8192 blocks read: OK |
4.2 exynos4412-fs4412.dtb
文件加载
1 | MMC read: dev # 0, block # 10240, count 2048 ...2048 blocks read: OK |
4.3 ramdisk.img
文件加载
1 | MMC read: dev # 0, block # 12288, count 8192 ...8192 blocks read: OK |
4.4 三个文件检测信息
1 | # Booting kernel from Legacy Image at 41000000 ... |
4.5 启动内核
1 | Starting kernel ... |
当我们看到这个信息的时候,说明后边的操作将会启动linux
内核。
4.6 挂载根文件系统
在内核安装完毕之后,会进行根文件系统挂载,挂载完成将会有以下信息提示:
1 | [ 2.205000] VFS: Mounted root (ext2 filesystem) on device 1:0. |
5. 启动成功
当我们的开发板加载linux
内核并启动成功的时候,我们可以运行一个ls
命令来检测一下:
五、加载方式三
在进行开发的过程中会经常修改内核和设备树的源码,也会经常向根文件系统中添加一些驱动或应用程序,这样每次修改之后我们都要重新将内核或根文件系统安装到eMMC
中,步骤会比较繁琐,开发效率也比较低,所以在开发阶段我们经常使用的方式是通过tftp
加
载内核和设备树再通过nfs
挂载根文件系统,这样步骤简单,效率也比较高,待开发完成之后在安装到eMMC
中。
下边我们就来使用加载方式三,通过tftp
来加载linux
内核,通过nfs
加载rootfs
根文件系统。该方式会用到nfs
,开发板中在linux
内核安装完成后,是已经安装了nfs
的,所以我们只需要保证ubuntu
安装了nfs
,并设置了可访问的共享目录即可。
1. 修改bootcmd
我们在secureCRT
终端执行以下命令:
1 | fs4412 # setenv bootcmd tftp 0x41000000 /fs4412/uImage\;tftp 0x42000000 /fs4412/exynos4412-fs4412.dtb\;bootm 0x41000000 - 0x42000000 |
然后我们打印一下这个环境变量的值,检查一下:
1 | fs4412 # printenv bootcmd |
【注意】
(1)多条命令之间用\;
分隔开。
(2)bootm
参数顺序为内核的下载地址、根文件系统的下载地址、设备树的下载地址。
2. 修改bootargs
我们还需要修改一下传给linux
的参数信息,也就是修改一下bootargs
环境变量的值。我们在secureCRT
终端执行以下命令:
1 | fs4412 # setenv bootargs root=/dev/nfs nfsroot=192.168.10.101:/home/hk/4nfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.10.102 |
然后我们打印一下这个环境变量的值,检查一下:
1 | fs4412 # printenv bootargs |
【注意】
(1)nfsroot=192.168.10.101
后边那个IP
为ubuntu
服务器的IP
,ip=192.168.10.102
后边的这个IP
为开发板自己的IP
,需要确保这两个IP
处于同一网段。
(2)该种加载方式的根文件系统来自于nfs
共享目录,所以我们可以在ubuntu
服务器上对根文件系统进行操作。
3. 重启开发板
3.1 uImage
文件加载
1 | dm9000 i/o: 0x5000000, id: 0x90000a46 |
3.2 exynos4412-fs4412.dtb
文件加载
1 | dm9000 i/o: 0x5000000, id: 0x90000a46 |
3.3 两个文件检测信息
1 | # Booting kernel from Legacy Image at 41000000 ... |
3.4 启动内核
1 | Starting kernel ... |
当我们看到这个信息的时候,说明后边的操作将会启动linux
内核。
3.5 挂载根文件系统
在内核安装完毕之后,会进行根文件系统挂载,挂载完成将会有以下信息提示:
1 | [ 2.855000] VFS: Mounted root (nfs filesystem) on device 0:10. |
注意这里很容易卡死,nfs
共享目录的设置一定要保证其他机器可以正常访问,另外需要注意这里使用的uboo2013
版本只支持nfs2
,而高版本的ubuntu
已经不支持这个版本了,有的资料说在一个文件中配置一下就行,但是我好像没有成功,所以只能换了ubuntu
的版本,更换了16.04
版本后就没有问题了,后边知道高版本的怎么处理了再在这里补充吧。
4. 启动成功
当我们的开发板加载linux
内核并启动成功的时候,我们可以运行一个ls
命令来检测一下: