5. Uboot的编译与修改¶
5.1. 下载安装编译镜像系统¶
推荐使用平台:Ubuntu 18.04.5 LTS 版本和Ubuntu 20.04 LTS 版本
可以使用我们提供的虚拟机镜像 https://doc.embedfire.com/products/link/zh/latest/linux/ebf_i.mx6ull.html#id4
也可以自己下载ubuntu 18.04.5 LTS官方镜像搭建
https://mirrors.aliyun.com/ubuntu-releases/bionic/ubuntu-18.04.5-desktop-amd64.iso
5.2. 安装编译工具和依赖¶
使用apt工具能快速安装好我们需要的工具和依赖
1 | sudo apt install make git gcc-aarch64-linux-gnu gcc bison flex libssl-dev dpkg-dev lzop libncurses5-dev
|
5.3. 获取U-boot¶
5.3.1. 下载源代码¶
uboot的源代码有多种方式可下载,但各自又有不同,野火uboot是根据NXP官方提供的uboot进行板卡的修改与功能的添加,NXP官方的uboot是以uboot官方版本进行芯片的适配。
官方uboot GitHub:
https://github.com/u-boot/u-boot
野火提供的uboot下载链接:
https://gitee.com/Embedfire/ebf_linux_uboot
或者
https://github.com/Embedfire/ebf_linux_uboot
或者
SDK中包含Uboot,可以使用SDK中的Uboot
注意:本教程以野火提供的uboot为分析样本
以下介绍如何单独获取野火uboot。
5.3.2. 查看切换分支¶
通常一个uboot仓库往往维护着不同分支的uboot,进入仓库目录下可通过命令查看及切换uboot分支, 例如在2023-07-23的镜像中使用的uboot分支为 imx_v2020.04_5.4.47_2.2.0 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 git clone https://gitee.com/Embedfire/ebf_linux_uboot.git #查看uboot分支 git branch -a #打印消息如下,默认为master主分支。 * master remotes/origin/HEAD -> origin/master remotes/origin/ebf_v2017_09_rk3328 remotes/origin/ebf_v2018.11_star remotes/origin/ebf_v2020_10_imx remotes/origin/imx_v2019.04_ls1043ardb remotes/origin/imx_v2020.04_5.4.47_2.2.0 remotes/origin/master #切换imx_v2020.04_5.4.47_2.2.0分支 git checkout imx_v2020.04_5.4.47_2.2.0 #打印消息如下 分支 'imx_v2020.04_5.4.47_2.2.0' 设置为跟踪来自 'origin' 的远程分支 'imx_v2020.04_5.4.47_2.2.0'。 切换到一个新分支 'imx_v2020.04_5.4.47_2.2.0' #重新查看当前分支 qinghui@ebf-dev:~/embedfire/ebf_linux_uboot$ git branch * imx_v2020.04_5.4.47_2.2.0 master
也可以在下载时指定分支,如下所示
1 2 3 4 5 #使用-b参数指定imx_v2020.04_5.4.47_2.2.0分支 git clone -b imx_v2020.04_5.4.47_2.2.0 https://gitee.com/Embedfire/ebf_linux_uboot #或者 git clone -b imx_v2020.04_5.4.47_2.2.0 https://github.com/Embedfire/ebf_linux_uboot
5.4. U-boot工程结构分析¶
学习一个软件,尤其是开源软件,首先应该从分析软件的工程结构开始。一个好的软件有良好的工程结构,对于读者学习和理解软件的架构以及工作流程都有很好的帮助。
uboot的源代码布局和我们后面讲的Linux类似,使用了按照模块划分的结构,并且充分考虑了体系结构和跨平台问题,其源代码树结构请参考下图
目录/文件 |
说明 |
目录/文件 |
说明 |
---|---|---|---|
api |
通用的API函数相关目录 |
arch |
与芯片架构相关目录 |
board |
板级相关信息目录 |
cmd |
uboot命令相关目录 |
common |
通用代码目录 |
configs |
boot配置文件目录 |
disk |
磁盘相关内容目录 |
doc |
说明文档 |
drivers |
驱动代码相关目录 |
dtoverlay |
|
dts |
设备树相关目录 |
env |
uboot环境相关 |
examples |
示例代码目录 |
fs |
文件系统相关目录 |
include |
头文件相关目录 |
lib |
lib库文件目录 |
Licenses |
许可证相关目录 |
net |
网络相关代码目录 |
post |
上电自检相关目录 |
scripts |
相关脚本目录 |
test |
测试代码目录 |
tools |
uboot构建工具相关目录 |
Kconfig |
图形配置界面相关文件 |
Makefile |
Makefile文件 |
5.5. U-boot编译¶
在uboot源码顶层目录执行以下命令:
1 2 3 4 5 6 | #清除配置和编译产物
make distclean
#加载板级配置文件,具体的板级配置文件在uboot根目录下的configs目录下
make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- imx8mm_fire_mmc_defconfig
#设置编译架构为arm 编译工具链为aarch64-linux-gnu-,使用8线程 然后开始编译
make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- -j8
|
如果使用SDK,可以在SDK顶层目录执行以下命令:
1 2 | #使用SDK单独编译uboot
make uboot
|
5.6. 编译产物分析¶
编译成功后,将打印以下信息。
u-boot:初步链接后得到的uboot文件
u-boot-nodtb.bin:是在u-boot的基础上,经过objcopy去除符号表信息之后的可执行程序
u-boot.dtb:uboot的设备树,是由arm-none-eabi-gcc和dtc编译出来的
u-boot.bin:是在u-boot-nodtb.bin后追加了u-boot.dtb形成的
u-boot.elf:是u-boot.bin 添加了3KB头部信息和尾部信息组成的镜像
u-boot-spl:是生成的 SPL 可执行文件,用于引导启动。
u-boot-spl-nodtb.bin:是没有设备树的 SPL 二进制文件。
u-boot-spl.bin:是包含设备树的SPL二进制文件。
u-boot.cfg:是U-Boot的配置文件,其中包含了编译U-Boot时所使用的配置选项。
5.7. imx-mkimage说明¶
获取imx-mkimage源码
1 2 3 4 5 | #进入uboot顶层目录
cd ebf_linux_uboot
#获取野火imx-mkimage源码
git clone https://gitee.com/Embedfire/ebf-imx-mkimage.git
|
5.8. imx-mkimage编译¶
将编译好的uboot产物复制到ebf-imx-mkimage对应目录下,然后编译imx-mkimage。
1 2 3 4 5 6 7 8 9 10 11 | #复制uboot产物到ebf-imx-mkimage对应目录下
cp -v u-boot-nodtb.bin ebf-imx-mkimage/iMX8M
cp -v spl/u-boot-spl.bin ebf-imx-mkimage/iMX8M
cp -v arch/arm/dts/imx8mm-fire-mmc.dtb ebf-imx-mkimage/iMX8M/imx8mm-ddr4-evk.dtb
#进入ebf-imx-mkimage
cd ebf-imx-mkimage
#编译
make SOC=iMX8MM clean
make SOC=iMX8MM flash_ddr4_evk_no_hdmi
|
编译输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | .....
Platform: i.MX8M (mScale)
ROM VERSION: v1
Using FIT image
LOADER IMAGE: u-boot-spl-ddr4.bin start addr: 0x007e1000
SECOND LOADER IMAGE: u-boot-ddr4-evk.itb start addr: 0x40200000 offset: 0x00060000
Output: flash.bin
========= IVT HEADER [HDMI FW] =========
header.tag: 0x0
header.length: 0x0
header.version: 0x0
entry: 0x0
reserved1: 0x0
dcd_ptr: 0x0
boot_data_ptr: 0x0
self: 0x0
csf: 0x0
reserved2: 0x0
boot_data.start: 0x0
boot_data.size: 0x0
boot_data.plugin: 0x0
========= IVT HEADER [PLUGIN] =========
header.tag: 0x0
header.length: 0x0
header.version: 0x0
entry: 0x0
reserved1: 0x0
dcd_ptr: 0x0
boot_data_ptr: 0x0
self: 0x0
csf: 0x0
reserved2: 0x0
boot_data.start: 0x0
boot_data.size: 0x0
boot_data.plugin: 0x0
========= IVT HEADER [LOADER IMAGE] =========
header.tag: 0xd1
header.length: 0x2000
header.version: 0x41
entry: 0x7e1000
reserved1: 0x57c00
dcd_ptr: 0x0
boot_data_ptr: 0x7e0fe0
self: 0x7e0fc0
csf: 0x80bdc0
reserved2: 0x0
boot_data.start: 0x7e0bc0
boot_data.size: 0x2d260
boot_data.plugin: 0x0
========= OFFSET dump =========
Loader IMAGE:
header_image_off 0x0
dcd_off 0x0
image_off 0x40
csf_off 0x2ae00
spl hab block: 0x7e0fc0 0x0 0x2ae00
Second Loader IMAGE:
sld_header_off 0x57c00
sld_csf_off 0x58c20
sld hab block: 0x401fcdc0 0x57c00 0x1020
|
编译输出的ebf-imx-mkimage/iMX8M/flash.bin就是我们启动需要的bootloader。
以上信息说明如下:
Platform: i.MX8M (mScale)指定了使用的硬件平台,即i.MX8M处理器
ROM VERSION: v1引导ROM的版本号,指明了启动固件的版本。
Using FIT image表示使用了设备树(Flattened Image Tree,FIT)格式的镜像来引导系统。
LOADER IMAGE: u-boot-spl-ddr4.bin start addr: 0x007e1000,第一阶段引导加载程序(SPL)的二进制文件名为 u-boot-spl-ddr4.bin,其起始地址为 0x007e1000。
SECOND LOADER IMAGE: u-boot-ddr4-evk.itb start addr: 0x40200000 offset: 0x00060000,第二阶段加载的 U-Boot 镜像文件名为 u-boot-ddr4-evk.itb,其起始地址为 0x40200000,偏移量为 0x00060000。
Output: flash.bin,最终生成的输出文件名为 flash.bin。
IVT HEADER [HDMI FW], IVT HEADER [PLUGIN], IVT HEADER [LOADER IMAGE],这部分列出了不同 IVT 头部的信息,每个 IVT 头部包含了关于不同加载程序或固件的元数据信息,如版本号、入口地址、偏移等。
OFFSET dump,里提供了一些偏移值的详细信息,包括加载程序的偏移、设备树(DTB)文件的偏移和签名文件(CSF)的偏移。
5.9. bootloader烧录¶
如果是SD镜像,请编译完整镜像然后烧录到SD卡进行启动。
如果是usb镜像,将flash.bin重命名为u-boot-nodtb.bin,并替换usb烧录包u-boot-nodtb.bin,然后烧录到emmc中进行启动。
5.10. 使用sdk编译bootloader¶
在SDK顶层目录执行以下命令即可一键编译。
编译生成的ebf-image-builder/build/u-boot-nodtb.bin就是我们需要的文件,这个文件是编译imx-mkimage后生成的flash.bin重命名并保存ebf-image-builder/build/u-boot-nodtb.bin的。
5.11. U-boot修改¶
一般来说,要适配一块新的板卡,在U-boot中主要设计三部分的修改和添加,分别是board目录下涉及板卡初始化的部分、 configs目录下对应板卡的配置文件、arch目录下与板级外设相关的文件。
5.11.1. U-boot配置文件¶
在野火iMX8M板卡上使用的具体文件是ebf_linux_uboot/configs/imx8mm_fire_mmc_defconfig 在SDK中ebf-image-builder/configs/boards/ebf_imx_8m_mini.conf文件中UBOOT_MMC_DEFCONFIG变量也定义了使用该配置文件。
5.11.2. U-boot配置修改¶
首先我们要来到U-boot源码顶层目录下,然后执行以下操作:
1 2 3 4 5 | #应用配置文件
make imx8mm_fire_mmc_defconfig
#使用menuconfig来管理修改配置文件
make menuconfig
|
修改完成之后按ESC按键退出,并保存,然后执行以下代码覆盖原来的配置文件。
1 2 3 4 5 | # 保存defconfig文件
make savedefconfig
# 覆盖原来的配置文件
cp defconfig configs/imx8mm_fire_mmc_defconfig
|
5.12. U-boot设备树文件¶
设备树文件是板级设备的描述文件,系统通过设备树文件得知板卡上有哪些外设,从而加载相应的驱动使外设正常工作。
原生的U-Boot只支持使用U-Boot自己的DTB,与内核的设备树不同,主要目的是为了兼容外设板级差异,如:power、clock、display 等,差别如下:
U-Boot DTB:负责初始化存储、打印串口等设备的描述
Kernel DTB:负责初始化存储、打印串口以及驱动其他外设的描述
U-Boot初始化时先用U-Boot DTB完成存储、打印串口初始化, 然后从存储上加载Kernel DTB并转而使用这份DTB继续初始化其余外设。
开发者一般不需要修改 U-Boot DTB(除非更换打印串口),mp157使用的defconfig都已启用kernel DTB机制。 所以通常对于外设的DTS修改,用户应该修改kernel DTB。
此处仅说明使用的u-boot-dtb文件,不做过多说明。
野iMX8MM板卡uboot使用的dtb为:ebf_linux_uboot/arch/arm/dts/imx8mm-fire-mmc.dts
5.13. 参考资料¶
NXP原厂U-boot添加了很多自定义的功能,但其主体还是基于官方U-boot的,所以关于U-boot的操作都是基本相同的,我们可以参考以下wiki。
官方uboot下载链接: http://www.denx.de/wiki/uboot/WebHome
官方uboot GitHub: https://github.com/uboot/uboot
uboot wiki: http://www.denx.de/wiki/uboot/WebHome