Bootstrap

香橙派全志H3烧录Uboot,远程加载zImage,dtb,rootfs

前言

本篇文章将从0开始,编译出uboot,kernel image, rootfs。虚拟机都是重装的。
文章将采用“ 遇到问题,解决问题 ”的叙述结构
希望可以对你有所帮助

准备工作

准备一块orangepi pc,以及相应的供电线,网线,usb转串口,读卡器,不小于1GB的SD卡。
ddddddcsrdd
下载uboot_2020.04源码https://github.com/orangepi-xunlong/u-boot-orangepi/tree/v2021.10-sunxi
下载kernel_5.4.6源码:https://github.com/orangepi-xunlong/linux-orangepi
访问慢的话,拉取到gitee里下载会快很多
下载busybox1.29.0 :https://busybox.net/downloads/busybox-1.29.0.tar.bz2
下载gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf编译器
https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-a/9.2-2019.12/binrel/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf.tar.xz
全套打包放CSDN了https://download.csdn.net/download/qq_42039294/85535963?spm=1001.2014.3001.5501
下载完成后,我们会有如下文件

linux-orangepi-orange-pi-5.4.zip			232MB
u-boot-orangepi-v2020.04.zip				26.6MB
gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf.tar.xz  251 MB
busybox-1.29.0.tar.bz2                        2.19 MB

一共0.5G,如果使用香橙派社区的工具包,下载一份几百兆的文件夹,运行其中的build.sh脚本,他会帮你下载源文件,配置编译器,但是体积会达到10个G。

准备一份装好了ubuntu的虚拟机,香橙派社区文档里推荐使用18.04版本,

安装gcc编译器,大家参考如下链接
https://blog.csdn.net/lengyuefeng212/article/details/119255594
最后测试使用指令

arm-none-linux-gnueabihf-gcc -v

uboot

编译uboot

解压,打开uboot源码顶层makefile,指定架构和交叉编译器

CROSS_COMPILE ?= arm-none-linux-gnueabihf-
ARCH ?= arm

在这里插入图片描述
指定编译目标, 编译

make orangepi_pc_defconfig
make

如果你是像我一样,从头安装的ubuntu 18.04, 在这里你会遇到一连串问题。你可以直接安装以下软件

sudo apt-get install bison -y
sudo apt-get install flex -y
sudo apt-get install python3-distutils -y
sudo apt install swig -y
sudo apt install python3-dev -y	//版本输入python -V 查看

这些软件没有安装的话,对应的问题如下,按顺序对应

1:scripts/Makefile.lib:226: recipe for target 'scripts/kconfig/zconf.tab.c' failed
2:scripts/Makefile.lib:218: recipe for target 'scripts/kconfig/zconf.lex.c' failed
3:ModuleNotFoundError: No module named 'distutils.core'
4:unable to execute 'swig': No such file or directory
5:scripts/dtc/pylibfdt/libfdt_wrap.c:149:11: fatal error: Python.h: 没有那个文件或目录  # include <Python.h>

解决所有问题之后,编译出现以下文件就说明成功了
在这里插入图片描述

制作启动sd卡

首先,使用SD card formatter软件格式化SD卡
之后接入到虚拟机,umount卸载掉这张SD卡,

winston@winston-vm:~$ ls /media/winston/
DBC7-27AF
winston@winston-vm:~$ umount /media/winston/DBC7-27AF
winston@winston-vm:~$ ls /dev/sd*
/dev/sda  /dev/sda1  /dev/sdb  /dev/sdb1

使用fdisk将这张SD卡分为前200M、剩余空间两个分区

winston@winston-vm:~$ sudo fdisk /dev/sdb
[sudo] winston 的密码: 

欢迎使用 fdisk (util-linux 2.31.1)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。


命令(输入 m 获取帮助): d			//删除SD card formatter创建的一个分区
已选择分区 1
分区 1 已删除。

命令(输入 m 获取帮助): n			//创建新分区
分区类型
   p   主分区 (0个主分区,0个扩展分区,4空闲)
   e   扩展分区 (逻辑分区容器)
选择 (默认 p): 

将使用默认回应 p。
分区号 (1-4, 默认  1): 
第一个扇区 (2048-15728639, 默认 2048): 
上个扇区,+sectors 或 +size{K,M,G,T,P} (2048-15728639, 默认 15728639): +200M

创建了一个新分区 1,类型为“Linux”,大小为 200 MiB。

命令(输入 m 获取帮助): n
分区类型
   p   主分区 (1个主分区,0个扩展分区,3空闲)
   e   扩展分区 (逻辑分区容器)
选择 (默认 p): 

将使用默认回应 p。
分区号 (2-4, 默认  2): 
第一个扇区 (411648-15728639, 默认 411648): 
上个扇区,+sectors 或 +size{K,M,G,T,P} (411648-15728639, 默认 15728639): //直接回车

创建了一个新分区 2,类型为“Linux”,大小为 7.3 GiB。

命令(输入 m 获取帮助): w
分区表已调整。
将调用 ioctl() 来重新读分区表。
正在同步磁盘。

winston@winston-vm:~$ 

前者格式化为vfat格式,后者格式化为ext4。

sudo mkfs.vfat /dev/sdb1
sudo mkfs.ext4 /dev/sdb2

使用lsblk -f查看一下
插拔一次SD卡,

烧录,启动

进入uboot顶层目录,使用如下命令烧录,建议将这个命令做成脚本使用

sudo dd if=u-boot-sunxi-with-spl.bin  of=/dev/sdb bs=1024 seek=8

在这里插入图片描述
注意,这里的烧录速度不应该太快,如果出现几百兆/s,一定是SD卡没连接到虚拟机。或者出现了僵尸文件/dev/sdb,手动删除/dev/sdb再插入SD卡就行
将烧录好的SD卡插入香橙派,上电,连接USB-TTL,
启动的时候按一下空格,不然它就要加载linux镜像了。串口助手打印的完整启动日志如下

U-Boot 2020.04 (Jun 03 2022 - 16:32:12 +0800) Allwinner Technology

CPU:   Allwinner H3 (SUN8I 1680)
Model: Xunlong Orange Pi PC
DRAM:  1 GiB
MMC:   mmc@1c0f000: 0
Loading Environment from FAT... *** Warning - bad CRC, using default environment

In:    serial@1c28000
Out:   serial@1c28000
Err:   serial@1c28000
Net:   phy interface0
eth0: ethernet@1c30000
starting USB...
Bus usb@1c1a000: USB EHCI 1.00
Bus usb@1c1a400: USB OHCI 1.0
Bus usb@1c1b000: USB EHCI 1.00
Bus usb@1c1b400: USB OHCI 1.0
Bus usb@1c1c000: USB EHCI 1.00
Bus usb@1c1c400: USB OHCI 1.0
Bus usb@1c1d000: USB EHCI 1.00
Bus usb@1c1d400: USB OHCI 1.0
scanning bus usb@1c1a000 for devices... 1 USB Device(s) found
scanning bus usb@1c1a400 for devices... 1 USB Device(s) found
scanning bus usb@1c1b000 for devices... 1 USB Device(s) found
scanning bus usb@1c1b400 for devices... 1 USB Device(s) found
scanning bus usb@1c1c000 for devices... 1 USB Device(s) found
scanning bus usb@1c1c400 for devices... 1 USB Device(s) found
scanning bus usb@1c1d000 for devices... 1 USB Device(s) found
scanning bus usb@1c1d400 for devices... 1 USB Device(s) found
       scanning usb for storage devices... 0 Storage Device(s) found
Autoboot in 2 seconds, press <Space> to stop
=>

让我们测试一下网络是不是好使的,在uboot里配置以下环境变量, 网段按照实际情况自己改

setenv ipaddr 192.168.137.88
setenv gatewayip 192.168.137.1
setenv netmask 255.255.255.0
setenv serverip 192.168.137.221
saveenv

设置完成,重启,ping一下虚拟机。重启不用拔线,输入reset就行
ping通,显示如下
在这里插入图片描述

uboot 其他设置

我们启动uboot的时候,会发现大部分时间都花在了扫描usb口的启动介质上了,我们从网络启动不需要这个功能。我们能从打印日志里看到扫描USB之前有一个starting USB…字符串,直接在uboot源码里搜索这个字符串,找到如下
在这里插入图片描述
这个do_usb函数应该就是负责这项功能的,直接在函数开头return 0 即可。
源码改完之后记得编译再烧录。删除这项功能之后,uboot启动就快得多

U-Boot 2020.04 (Jun 03 2022 - 17:33:16 +0800) Allwinner Technology

CPU:   Allwinner H3 (SUN8I 1680)
Model: Xunlong Orange Pi PC
DRAM:  1 GiB
MMC:   mmc@1c0f000: 0
Loading Environment from FAT... OK
In:    serial@1c28000
Out:   serial@1c28000
Err:   serial@1c28000
Net:   phy interface0
eth0: ethernet@1c30000
Autoboot in 2 seconds, press <Space> to stop
=>

kernel

编译内核

打开linux源码顶层makefile,指定编译器和架构

CROSS_COMPILE ?= arm-none-linux-gnueabihf-
ARCH ?= arm

在这里插入图片描述
指定编译目标,开始编译

make sunxi_defconfig
make

报错
/bin/sh: 1: mkimage: not found
安装
sudo apt-get install u-boot-tools

我的电脑CPU是5800H, 分配6核心12线程,初次编译耗时不到两分钟,这个比香橙派的工具快很多。编译完成,虚拟机出现以下日志
在这里插入图片描述
我们需要的镜像zImage,设备树文件sun8i-h3-orangepi-pc.dtb都出现了
在这里插入图片描述

虚拟机安装tftp nfs服务

tftp服务用来加载zImage和设备树文件,nfs服务用来挂在网络文件系统,在这里就一起做了
TFTP

sudo apt-get install tftp-hpa tftpd-hpa xinetd

新建一个文件夹,tftp会将这个文件夹共享出去

mkdir ~/Desktop/netpi/tftpboot -p
sudo chmod 777 ~/Desktop/netpi/tftpboot

新建文件/etc/xinetd.d/tftp,输入以下内容,

server tftp
{
	socket_type = dgram
	protocol = udp
	wait = yes
	user = root
	server = /usr/sbin/in.tftpd
	server_args = -s /home/winston/Desktop/netpi/tftpboot
	disable = no
	per_source = 11
	cps = 100 2
	flags = IPv4
}

修改/etc/default/tftpd-hpa文件内容为如下

# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/winston/Desktop/netpi/tftpboot"
TFTP_ADDRESS=":69" 
TFTP_OPTIONS="-l -c -s" 

注意,以上两个配置文件中的文件夹路径,不可以使用~代替/home/user
启动服务

sudo service tftpd-hpa start
service --status-all | grep tftpd-hpa		//查看服务tftpd-hpa是否开启

+号代表已启动,-号代表未启动
在这里插入图片描述

uboot加载测试
将zImage和设备树文件复制到~/Desktop/netpi/tftpboot里,去uboot里面输入

tftp 42000000 zImage										//zImage复制到内存的42000000处 
tftp 43000000 sun8i-h3-orangepi-pc.dtb			//设备树复制到内存的43000000 处

正常的话,出现如下内容

tftp测试完毕,直接保存到bootcmd里

setenv bootcmd 'tftp 42000000 zImage; tftp 43000000 sun8i-h3-orangepi-pc.dtb; bootz 0x42000000 - 0x43000000'
saveenv

此时直接输入boot启动的话,你会在日志里看到如下错误

......
[    1.830518] VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
[    1.838032] Please append a correct "root=" boot option; here are the available partitions:
......
[    2.289431] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---

这是由于我们没有挂载根文件系统而导致的,挂载根文件系统需要nfs服务
NFS
nfs服务用于加载网络操作系统,network file system
在虚拟机里安装软件

sudo apt-get install nfs-kernel-server rpcbind

新建共享文件夹nfs,并在共享文件夹nfs里创建一个空文件text用于测试

mkdir ~/Desktop/netpi/nfs
chmod 777 ~/Desktop/netpi/nfs

修改配置文件/etc/exports, 末尾追加

/home/winston/Desktop/netpi/nfs *(rw,sync,no_root_squash)

因为uboot支持的是nfs2,ubuntu18默认不支持,所以我们要修改虚拟机的配置文件,使其支持nfs2。修改/etc/default/nfs-kernel-server为如下(删除了一些注释)

RPCNFSDCOUNT="-V 2 8"
RPCNFSDPRIORITY=0
RPCMOUNTDOPTS="-V 2 --manage-gids"
NEED_SVCGSSD=""
RPCSVCGSSDOPTS="--nfs-version 2,3,4 --debug --syslog"

测试一下

nfs 48000000 192.168.137.221:/home/winston/Desktop/netpi/nfs/text

在这里插入图片描述

rootfs

编译rootfs

nfs目录下创建rootfs文件夹,chmod 777 权限
修改busybox源码顶层Makefile,指定编译器和架构
在这里插入图片描述

指定为默认配置,进入menuconfig

make defconfig
make menuconfig

修改如下项目,注意,如要支持中文还需要改一下其他地方还有源码,但是我基本上用不到,所以就不改了。
正点原子将rootfs编译为动态库,并且复制了编译器的一些库文件进去。本文使用的编译器和正点原子使用的不同,我不知道照做会不会出问题,编译为静态库应该会省事。orangpi-pc是1GB的内存,足够放入静态库了。

 Location: 
	-> Settings 
		-> Build static binary (no shared libs)	//编译为静态库
		-> vi-style line editing commands		//选中
	-> Linux Module Utilities
		-> Simplified modutils		//取消选中

编译,指定输出目录

make
make install CONFIG_PREFIX=/home/winston/Desktop/netpi/nfs/rootfs

这样就算成功了
在这里插入图片描述
在uboot里指定bootargs,启动看看

setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.137.221:/home/winston/Desktop/netpi/nfs/rootfs,proto=tcp rw ip=192.168.137.88:192.168.137.221:192.168.137.1:255.255.255.0::eth0:off'
saveenv

成功的话,日志中会有如下

[    6.165249] VFS: Mounted root (nfs filesystem) on device 0:14.
[    6.171461] devtmpfs: error mounting -2
[    6.176708] Freeing unused kernel memory: 1024K
[    6.223892] Run /sbin/init as init process
[    6.240688] random: fast init done
can't run '/etc/init.d/rcS': No such file or directory

can't open /dev/tty2: No such file or directory
can't open /dev/tty4: No such file or directory
......
完善rootfs

可以看到,rootfs已经挂载成功了,但是devtmpfs和初始化好像有点问题,前者是因为我们根文件目录少创建了很多文件夹,后者参考正点原子解决。
在nfs/rootfs里创建其他文件夹

mkdir dev proc mnt sys tmp root etc

在/etc文件夹下新建如下文件
在这里插入图片描述
fstab内容如下

#<file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0

/init.d/rcS内容如下,注意给权限

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH 
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

inittab内容如下

#etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

重启香橙派

[    6.243956] Run /sbin/init as init process
[    6.260700] random: fast init done
/etc/init.d/rcS: line 11: can't create /proc/sys/kernel/hotplug: nonexistent directory

Please press Enter to activate this console. [   36.323836] vcc3v0: disabling
[   36.326819] vcc5v0: disabling
[   36.329783] cam500b-avdd: disabling
[   36.333266] cam500b-dovdd: disabling
[   36.336858] cam500b-dvdd: disabling
[   36.340343] usb0-vbus: disabling
/ #

shell 可以用了,但是hotplug有问题,应该是内核没有开启相关功能
打开Device Drivers > Generic Driver Options > Support for uevent helper

[    6.171445] ALSA device list:
[    6.174437]   No soundcards found.
[    6.186098] VFS: Mounted root (nfs filesystem) on device 0:14.
[    6.192365] devtmpfs: mounted
[    6.196671] Freeing unused kernel memory: 1024K
[    6.234093] Run /sbin/init as init process
[    6.249850] random: fast init done

Please press Enter to activate this console.
/ #
/ #
/ #
/ #

好用了。

后记

担心的问题:

静态库好用不好用?我也不知道到此为止能不能证明静态库好用了,大佬们知道的可以在底下说一声。

我的疑问:

rootfs是在内核阶段挂载的,为什么uboot里要测试好不好使?如果在uboot里关闭nfs服务,系统还能正常运行吗?

文章资源在这里https://download.csdn.net/download/qq_42039294/85535963?spm=1001.2014.3001.5501

参考:
【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5
香橙派全志H3烧入U-boot和Linux内核以及配置
OrangePi_PC_H3_用户手册_v3.2.pdf

——END

;