嵌入式 Linux 开发 5:u-boot 引导加载程序

简介 u-boot

启动 Linux 是一部三幕剧:bootloader-->kernel-->init@rootfs 如下图所示

而 u-boot 是使用最广泛的 bootloader 软件,它负责初始化硬件为 kernel 构建合适的运行环境。
花时间掌握 u-boot 的编译,烧录,使用是很值得的,不但提高开发效率,还能实现一些高级功能。

u-boot 镜像格式

为了识别 Linux kernel 镜像的属性 u-boot 在镜像文件的前面添加一个较小的头部。
如下图所示 u-boot 提供了一个名为 mkimage 的工具,用于生成这个镜像头部。

uImage
+--------+
| u-boot |
| header |
+--------+ u-boot +--------+
| zImage |<-----------| zImage |
+--------+ mkimage +--------+

导入 Linux 内核

假设按嵌入式 Linux 开发 3:搭建开发环境搭建了 TFTP 服务器。

在 u-boot 命令行设置如下环境变量
setenv ipaddr 192.168.1.103 # 配置目标板 IP
setenv serverip 192.168.1.101 # 配置服务器 IP
setenv tftp tftpboot 7fc0 980uimage # 通过 TFTP 从服务器下载 kernel 文件 980uimage 到 0x7fc0@SDRAM
setenv boot bootm 7fc0 # 从 0x7fc0@SDRAM 启动 kernel
运行 saveenv 保存环境变量

现在可以体验快速测试 kernel 的流程

  • 在开发主机 配置/编译 kernel 并将镜像文件复制到 TFTP 共享目录
  • 重启目标板,进入 u-boot 执行 $tftp$boot 导入并运行 kernel

传递 rootfs 参数

bootargs=noinitrd root=/dev/nfs rw nfsroot=192.168.1.101:/nfsroot/nuc980_rootfs/rootfs,v3 ip=192.168.1.103:192.168.1.101:192.168.1.1:255.255.255.0 console=ttyS0,115200n8 rdinit=/sbin/init mem=64M

设备树 DTB

为了将底层硬件信息从 u-boot 传递给 Linux kernel 引入了设备树机制。
设备树 DTB(Device Tree Blob)是一个数据库,它代表了一个给定嵌入式 Linux 的硬件元件。

DTB 由设备节点组成,通常描述一个设备或总线,每个节点包含一组描述它的属性。

设备树编译器(dtc)将开发人员可读的设备树源码转换成机器可读的二进制文件,而 u-boot 和 kernel 都能理解这个二进制文件。
一般在 kernel 源码根目录下执行如下命令即可编译 DTB
make ARCH=arm board.dtb

Linux 启动过程

理解下图 Linux 启动全过程很重要,无论是构建相应的组件(u-boot-->kernel-->rootfs),还是解决 bug 或提升性能。

编译与部署 fw_printenv

背景

U-Boot 提供 fw_printenv(fw_setenv)程序,这允许 Linux 在用户空间查看和修改 U-Boot 环境变量。
升级 Linux 镜像经常要用到这个实用程序,下面描述编译和测试的流程。

查找环境变量数值

find $PRJROOT/bootldr -name *.h -print | xargs grep "CONFIG_ENV_" | grep -i <target_name>
#define CONFIG_ENV_OFFSET 0x80000 --> 环境变量在 MTD 偏移量
#define CONFIG_ENV_SIZE 0x20000 --> 环境变量大小
#define CONFIG_ENV_SECT_SIZE 0x20000 --> 环境变量块大小

修改 fw_env.config

cd $(find $PRJROOT/bootldr -name *.h -print | xargs grep "fw_printenv" -l | xargs dirname) # 进入 env 目录
tar zcvf ./fw_env.config.tar.gz ./fw_env.config # 备份配置文件
vi ./fw_env.config # 按环境变量数值修改配置文件
# MTD SPI-dataflash example
# MTD device name Device offset Env. size Flash sector size Number of sectors
/dev/mtd0 0x80000 0x20000

编译

make CROSS_COMPILE=${CROSS}- env -C ../..
编译 env 得在 U-Boot 根目录下执行,编译成功后会生成 fw_printenv 可执行文件。

复制文件到 rootfs

sudo cp -vf ./fw_env.config <target_rootfs_dir>/etc/
sudo cp -vf ./fw_printenv <target_rootfs_dir>/usr/bin/
cd <target_rootfs_dir>/usr/bin/
sudo ln -s ./fw_printenv ./fw_setenv # 二者是同一个执行文件

建立 lock 目录(仅运行 1 个实体)

cd <target_rootfs_dir>/var/
sudo ln -s ../tmp ./lock # 建立软链接目录 /var/lock->/tmp

升级板子 rootfs 并测试

fw_printenv --> 显示 U-Boot 环境变量
fw_setenv ethaddr 00:11:22:33:44:55 --> 配置 MAC 地址
fw_printenv --> 查看 MAC 地址

posted @ 2022-09-22 13:30  KevinAshton  阅读(265)  评论(0编辑  收藏  举报