飞腾基于 VPX、COMe、Mini-ITX 等主流标准板卡接口协议设计了多款 E2000 行业开发板,用于提升研发效率。E2000实际使用中会有采用uboot来引导系统启动的情况。
本文以飞腾E2000D电力开发板为例,简单介绍下E2000使用uboot引导启动系统的整个过程。这个启动过程不严谨的分解,由uboot、环境变量、设备树、内核、文件系统组成。下面我们逐项说明。
一、uboot
首先,uboot是广义上的称呼,飞腾的uboot固件由多个部分组成的。
固件生成过程大体分成三个步骤,
1.编译系统固件。根据选用的系统固件(SFW)编译UEFI或U-Boot的源码,生成PHYTIUM.fd或u-boot.bin,将其重命名为bl33_new.bin,做为备用。
2.低速引脚复用配置。通过 E2000 LSD复用工具进行低速引脚复用配置,生成文件pad_set.bin,做为备用。
3.打包。通过 PBF 打包工具,配置板级参数和高速引脚复用,最后生成文件 fip-all.bin,该文件可直接烧录到FLASH中,用于启动。
Uboot固件的制作,基本可以参考原桌面CPU的操作过程和环境。
与桌面CPU操作的区别是E2000有低速引脚,需要使用专用的配置工具生成pad_set.bin文件,并且最后一并打包到固件中。
二、环境变量
uboot的环境变量设置完全可以参考网上的资料,这里飞腾没有任何特殊的地方。主要需要确定的就是设备树、内核和文件系统在板卡存储设备(sata、nvme、sd等)中的位置和加载地址。既然要设置这些文件的位置,那么我们就不得不介绍存储设备里文件的制作。所以环境变量我们先放一放,我们先看后面,设备树、内核和文件系统。
三、设备树、内核和文件系统
设备树、内核和文件系统最终是要存到存储设备中的,那么我们首先就要准备好文件,其次处理好存储设备,最后就是把准备好的文件存放到存储设备中。
3.1 文件准备
我们以汉为的E2000D电力开发板为例来讲解。
我们要准备三个文件,设备树、内核、文件系统。分别为:e2000d-power-board.dtb、Image、rootfs.tar.xz。
设备树、内核都是二进制文件,这个不用动。文件系统是使用buildroot方式做的压缩包。如何使用buildroot做文件系统,看飞腾的gitee。
链接:https://gitee.com/phytium_embedded/phytium-linux-buildroot
3.2 nvme盘分区、格式化
3.2.1 硬件接法
这个汉为E2000D电力开发板是使用nvme作为存储介质的。我们要对这个nvme盘进行处理。
有两种方式,一就是找一个nvme转pcie的转接板,将nvme盘接入一个能开机的飞腾板子上。二就是使用nvme转USB的转接板,接入windows电脑里的虚拟机,在linux虚拟机里操作。总而言之,这个nvme盘要在linux系统下进行操作。
3.2.2 分区
当我们nvme盘接入了linux系统后,我们使用fdisk命令先确定好nvme盘系统下的盘符。我这里nvme盘接入linux系统后名字叫nvme0n1。
我们先进行分区(下文是将nvme盘按两个分区进行的操作,但是对于本文的引导系统启动操作来说,分成一个区就可以。分两个区也是为了更多的展示细节)。
先分区nvme,命令
#fdisk /dev/nvme0n1
n是新建分区,p主分区,1代表分区1,First sector就是新分区的第一个扇区,默认就是顺序第一个空扇区;Last sector是新分区的最后一个扇区,默认是整个磁盘最后一个扇区,+2g代表在first sector上+2g,也就是分区大小2GB。如果在操作过程中直接回车,则执行的是default的值。
最后输入w写入分区信息。
再执行fdisk命令进行查看,就可以看到nvme的两个分区了nvme0n1p1和nvme0n1p2。
3.2.3 格式化
对nvme0n1p1和nvme0n1p2两个分区进行格式化。
格式化成ext4格式,命令为:
#mkfs.ext4 /dev/nvme0n1p1
#mkfs.ext4 /dev/nvme0n1p2
3.3 系统盘文件制作
我们在linux系统中新建mnt目录里新建mnvme的目录,用于实体nvme盘的挂载。
命令:
#mkdir /mnt/mnvme
#mount /dev/nvme0n1p2 /mnt/mnvme
###将nvme的第2个分区挂载到mnt目录中的mnvme中
之后我们把3.1中准备的设备树、内核、文件系统。复制到mnt目录中的mnvme中。(我把这三个文件放到了linux系统的桌面上,所以下面命令都是从“/home/ft/桌面/”进行复制的)
#cp /home/ft/桌面/e2000d-power-board.dtb /mnt/mnvme
#cp /home/ft/桌面/Image /mnt/mnvme
#cp /home/ft/桌面/rootfs.tar.xz /mnt/mnvme
因为设备树和内核都是二进制文件,因此不需要进行额外的处理。根文件系统是tar.xz的压缩包,我们需要对其进行解压。
#cd /mnt/mnvme
#tar xvf rootfs.tar.xz
最后,要记得进行一次同步操作,保证我们nvme盘内的文件与挂载的/mnt/mnvme目录内的文件一致。
#sync
最后我们卸载mnvme目录就好了。
#umount /mnt/mnvme
四、环境变量
将uboot固件烧写到flash,做好的nvme盘安装到板卡上后。给E2000D电力开发板加电启动,我们进入uboot的命令行。
我们可以print看一下当前的环境变量(首先提示,这个默认的环境变量是启动不起来的)。
E2000#print
arch=arm
baudrate=115200
board=e2000
board_name=e2000
boot_os=bootm kernel_addr -:- ft_fdt_addr
bootargs=earlycon=pl011,0x2800d000 root=/dev/sda2 rw
bootcmd=run distro_bootcmd
bootdelay=2
cpu=armv8
distro_bootcmd=run load_kernel; run load_initrd; run load_fdt; run boot_os
eth0addr=00:11:22:33:44:55
eth1addr=10:22:33:44:55:66
eth2addr=10:11:22:33:44:55
eth3addr=00:22:33:44:55:66
ethaddr=00:11:22:33:44:55
fdt_addr=0x381BC000
fdtcontroladdr=fa43c860
ft_fdt_addr=0x90000000
ft_fdt_name=boot/dtb/e2000.dtb
gatewayip=202.197.67.1
initrd_addr=0x95000000
ipaddr=202.197.67.2
kernel_addr=0x90100000
load_fdt=ext4load scsi 0:2 ft_fdt_addr ft_fdt_name
load_initrd=ext4load scsi 0:2 $initrd_addr initrd.img-4.19.0.e2000
load_kernel=ext4load scsi 0:2 $kernel_addr boot/uImage-2004
loadaddr=0x90000000
netdev=eth0
netmask=255.255.255.0
serverip=202.197.67.3
stderr=uart@2800d000
stdin=uart@2800d000
stdout=uart@2800d000
vendor=phytium
Environment size: 930/4092 bytes
bootcmd=run distrobootcmd,也就是执行bootcmd就是run distrobootcmd,run就是执行distrobootcmd,那么我们再看distrobootcmd是要执行什么。distrobootcmd=run loadkernel; run loadinitrd; run loadfdt; run bootos,那就是首先执行loadkernel,再执行 loadinitrd,再执行loadfdt,再执行boot_os……就这样逐步的拆解,最后落实到最终的指令上。
通过上面的解析,我们也大概了解了整个的启动参数,并且也看出其中有一些参数的问题,比如现在是nvme盘,但是环境变量是sata盘,同时ext4load的文件和我们在“三、设备树、内核和文件系统”中做到nvme盘中的文件不一致。那么我就要对这些与自己板卡不符合的内容进行修改。
还是针对汉为E2000D电力开发板,我们需要执行如下命令:
'console=ttyAMA1,115200 audit=0 earlycon=pl011,0x2800d000 root=/dev/nvme0n1p2 rw' setenv bootargs
确定调试串口信息,确定根文件在/dev/nvme0n1p2中
#setenv load_kernel 'ext4load nvme 0:2 0x90100000 Image'
使用ext4load命令加载nvme盘0第2个分区中的Image内核到内存地址0x90100000中
#setenv load_fdt 'ext4load nvme 0:2 0x90000000 e2000d-power-board.dtb'
使用ext4load命令加载nvme盘0第2个分区中的dtb设备树到内存地址0x90000000中
#setenv boot_os 'booti 0x90100000 -:- 0x90000000'
使用booti命令,从内存地址进行系统加载启动
#saveenv
保存环境变量
最后可以用于启动的完整环境变量为:
E2000#print
arch=arm
baudrate=115200
board=e2000
board_name=e2000
boot_os=booti 0x90100000 -:- 0x90000000
bootargs=console=ttyAMA1,115200 audit=0 earlycon=pl011,0x2800d000 root=/dev/nvme0n1p2 rw
bootcmd=run distro_bootcmd
bootdelay=2
cpu=armv8
distro_bootcmd=run load_kernel; run load_initrd; run load_fdt; run boot_os
eth0addr=00:11:22:33:44:55
eth1addr=10:22:33:44:55:66
eth2addr=10:11:22:33:44:55
eth3addr=00:22:33:44:55:66
ethaddr=00:11:22:33:44:55
fdt_addr=0x381BC000
fdtcontroladdr=fa43d860
ft_fdt_addr=0x90000000
ft_fdt_name=boot/dtb/e2000.dtb
gatewayip=202.197.67.1
initrd_addr=0x95000000
ipaddr=202.197.67.2
kernel_addr=0x90100000
load_fdt=ext4load nvme 0:2 0x90000000 e2000d-power-board.dtb
load_initrd=ext4load scsi 0:2 $initrd_addr initrd.img-4.19.0.e2000
load_kernel=ext4load nvme 0:2 0x90100000 Image
loadaddr=0x90000000
netdev=eth0
netmask=255.255.255.0
serverip=202.197.67.3
stderr=uart@2800d000
stdin=uart@2800d000
stdout=uart@2800d000
vendor=phytium
Environment size: 957/4092 bytes
仔细分析上面的环境变量。其加载的设备树、内核、文件系统,都是我们前面做好的,再nvme盘中的,并且将文件加载到了指定的内存地址位置。那么到最后booti命令,我们从内存执行就可以了。
五、总结
前面我们也说了,不严谨的分解,整个启动过程由uboot、环境变量、设备树、内核、文件系统组成。上面的步骤中,我们做完了所有的文件。Uboot已经做好了并且已经启动了,环境变量指定了启动加载的设备树、内核、文件系统的位置和文件。整个流程中,uboot和系统文件通过环境变量有机的结合到了一起,最终实现了uboot引导系统启动的整个流程。
往期文章
欢迎飞腾爱好者加入微信交流群。 群内大家可以在群内交流遇到的问题,分享自己的调试心得。 希望大家共建飞腾友谊!