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命令来检测一下: