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类似,使用了按照模块划分的结构,并且充分考虑了体系结构和跨平台问题,其源代码树结构请参考下图

uboot目录

目录/文件

说明

目录/文件

说明

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
../../_images/uboot_menuconfig0.jpg

修改完成之后按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