Skip to the content.

1. 添加命令

代码位置:u-boot/cmd (以u-boot-2023.10为例)。

1.1 现有命令修改

修改 u-boot/cmd/time.c

--- a/u-boot/cmd/time.c
+++ b/u-boot/cmd/time.c
@@ -22,6 +22,19 @@ static void report_time(ulong cycles)
        if (minutes)
                printf(" %lu minutes,", minutes);
        printf(" %lu.%03lu seconds\n", seconds, milliseconds);
+
+       printf("test 1.\n");
+       log_emer("test 2.\n");
+       log_alert("test 3.\n");
+       log_crit("test 4.\n");
+       log_err("test 5.\n");
+       log_warning("test 6.\n");
+       log_notice("test 7.\n");
+       log_info("test 8.\n");
+       log_debug("test 9.\n");
+       log_content("test 10.\n");
+       log_io("test 11.\n");
+       log_cont("test 12.\n");
+       debug("test 13.\n");
 }

 static int do_time(struct cmd_tbl *cmdtp, int flag, int argc,

修改完成后,u-boot根目录执行编译:

$ make -j4

测试如下:

$ ./u-boot
U-Boot 2023.10 (Jan 04 2024 - 11:10:55 +0800)

DRAM:  256 MiB
Core:  27 devices, 14 uclasses, devicetree: board
MMC:   
Loading Environment from nowhere... OK
Warning: device tree node '/config/environment' not found
In:    serial,cros-ec-keyb,usbkbd
Out:   serial,vidconsole
Err:   serial,vidconsole
Net:   No ethernet found.
Hit any key to stop autoboot:  0 
=> 
=> 
=> 
=> 
=> time true

time: 0.000 seconds
test 1.
test 2.
test 3.
test 4.
test 5.
test 6.
test 7.
test 8.
=>

从上面的测试结果看出,log_debug及以下等级,不会打印出来,原因是loglevel等级的限制:

CONFIG_LOG_DEFAULT_LEVEL=6

查看loglevel定义的话是在:

log_level_t @ u-boot-2023.10/include/log.h

另外,debug()中的内容,也没有打印,原因是没有开启debug,开启debug的方法是:

#ifdef DEBUG @ u-boot-2023.10/include/log.h

这个宏定义之前定义:

#define DEBUG

1.2 添加新命令

首先是在 u-boot/cmd 目录下新建文件:

$ cd u-boot/cmd/
$ touch hello-test.c

在 u-boot/cmd/Makefile 中添加如下内容:

obj-$(CONFIG_CMD_HELLO1) += hello-test.o

或者:

obj-y += hello-test.o

使用后者其它步骤就可以忽略,直接跳转到代码编写环节,这里使用前者,所以还需要做一些额外的工作:

在 u-boot/cmd/Kconfig 中添加如下内容:

config CMD_HELLO1
	bool "hello1"
	help
	  Run commands and display hello world to stdout.

这里采用 sandbox 仿真 u-boot,所以在 u-boot/configs/sandbox_defconfig 添加如下内容:

CONFIG_CMD_HELLO1=y

然后,进入编码环节:

在 include/command.h 中,包含了命令声明宏:

#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)		\
	U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)

#define U_BOOT_CMD_WITH_SUBCMDS(_name, _usage, _help, ...)		\
	U_BOOT_SUBCMDS(_name, __VA_ARGS__)				\
	U_BOOT_CMDREP_COMPLETE(_name, CONFIG_SYS_MAXARGS, do_##_name,	\
			       _usage, _help, complete_##_name)

U_BOOT_CMD 和 U_BOOT_CMD_WITH_SUBCMDS 的区别就是,一次声明命令的数量,前者一次申请一个命令,后者一次同时申请多个命令(比如acpi有acpi list、acpi items等多个命令)。

这里使用 U_BOOT_CMD,它的参数含义如下:

_name:     添加的命令的名字
_maxargs:  添加的命令最多有几个参数(注意,假如你设置的参数个数是3,而实际的参数个数是4,那么执行命令会输出帮助信息的)
_rep:      是否重复(1重复,0不重复)(即按下Enter键的时候,自动执行上次的命令)
_cmd:      执行函数,即运行了命令具体做啥会在这个函数中体现出来
_usage:    帮助信息(short)
_help:     帮助信息(long)

编辑 hello-test.c:

/**
 * hello-test.c
 * 	command test example.
 *
 * License - MIT.
 */

#include <common.h>
#include <command.h>

static int do_hello(struct cmd_tbl *cmdtp, int flag, int argc,
                   char *const argv[])
{
    printf("hello world.\n");

    return 0;
}

U_BOOT_CMD(hello1, CONFIG_SYS_MAXARGS, 0, do_hello,
           "run commands and display hello world to stdout",
           "command\n");

编译:

$ make sandbox_defconfig all -j4

运行:

$ ./u-boot
U-Boot 2023.10 (Jan 04 2024 - 12:13:55 +0800)

DRAM:  256 MiB
Core:  27 devices, 14 uclasses, devicetree: board
MMC:   
Loading Environment from nowhere... OK
Warning: device tree node '/config/environment' not found
In:    serial,cros-ec-keyb,usbkbd
Out:   serial,vidconsole
Err:   serial,vidconsole
Net:   No ethernet found.
Hit any key to stop autoboot:  0 
=> 
=> 
=> 
=> 
=> hello1
hello world.
=>

2. U-boot原生命令

2048      - 2048游戏
?         - 'help'的别名
ab_select - 选择用于启动的插槽并注册启动尝试。
abootimg  - 操纵 Android 启动映像
acpi      - ACPI表
addrmap   - 列出 32 位 CPU 的非标识虚拟物理内存映射
aes       - AES 128/192/256 CBC 加密
armffa    - Arm FF-A 测试命令
askenv    - 从 stdin 获取环境变量
avb       - 提供用于测试 Android Verified Boot 2.0 功能的命令
axi       - AXI 子系统
base      - 打印或设置地址偏移量
bdinfo    - 打印板信息结构
bind      - 将设备绑定到驱动程序
blkcache  - 块缓存诊断和控制
blkmap    - 可组合的虚拟块设备
bloblist  - 块列表
bmp       - 操作 BMP 图像数据
boot      - 启动默认值,即运行“bootcmd”
bootcount - bootcount
bootd     - 启动默认值,即运行“bootcmd”
bootdev   - 启动设备
bootefi   - 从内存启动 EFI 负载
bootflow  - 启动流程
bootm     - 从内存启动应用程序映像
bootmenu  - ANSI 终端启动菜单
bootmeth  - 启动方式
bootp     - 使用 BOOTP/TFTP 协议通过网络启动映像
bootstage - 启动阶段命令
bootz     - 从内存启动 Linux zImage 映像
btrsubvol - 列出 BTRFS 文件系统的子卷
button    - 管理按钮
cat       - 将文件打印到标准输出
cbfsinfo  - 打印有关文件系统的信息
cbfsinit  - 初始化cbfs驱动
cbfsload  - 从 cbfs 文件系统加载二进制文件
cbfsls    - 列出文件
cdp       - 执行 CDP 网络配置
cedit     - 配置编辑器
chpart    - 更改 MTD 设备的活动分区
clone     - 简单存储克隆
cls       - 清除屏幕
cmp       - 内存比较
config    - 打印 .config
coninfo   - 打印控制台设备和信息
cp        - 内存复制
cpu       - 显示有关 CPU 的信息
cramfsload- 从文件系统映像加载二进制文件
cramfsls  - 列出目录中的文件 (default /)
crc32     - 校验和计算
crosec    - CROS-EC实用程序命令
cyclic    - 循环
date      - 获取/设置/重置日期和时间
demo      - 驱动模型(dm)演示操作
dhcp      - 使用 DHCP/TFTP 协议通过网络启动映像
dhcp6     - 使用 DHCPv6/TFTP 协议通过网络启动映像。 使用带有 [] 括号的 IPv6 hostIPaddr
dhry      - [迭代] - 运行 dhrystone 基准测试
diskboot  - 从 IDE 设备启动
dm        - 驱动程序模型低级访问
dns       - 查找主机名的IP
echo      - 将参数回显到控制台
editenv   - 编辑环境变量
eficonfig - 提供菜单驱动的UEFI变量维护界面
efidebug  - 配置UEFI环境
env       - 环境处理命令
erase     - 擦除闪存
eraseenv  - 从持久存储中删除环境变量
erofsload - 从 EROFS 文件系统加载二进制文件
erofsls   - 列出目录中的文件。 默认值:根 (/)。
ethsw     - 以太网二层交换机命令
event     - 事件
exception - 强制发生异常
exit      - 退出脚本
ext2load  - 从 Ext2 文件系统加载二进制文件
ext2ls    - 列出目录中的文件(默认 /)
ext4load  - 从 Ext4 文件系统加载二进制文件
ext4ls    - 列出目录中的文件(默认 /)
ext4size  - 确定文件的大小
ext4write - 在根目录下创建一个文件
extension - 扩展板管理子系统
false     - 什么也不做,不成功
fastboot  - 作为 fastboot USB 或 udp 设备运行
fatinfo   - 打印有关文件系统的信息
fatload   - 从 dos 文件系统加载二进制文件
fatls     - 列出目录中的文件(默认 /)
fatmkdir  - 创建一个目录
fatrm     - 删除一个文件
fatsize   - 确定文件的大小
fatwrite  - 将文件写入dos文件系统
fdt       - 扁平化设备树实用程序命令
flinfo    - 打印FLASH存储器信息
font      - 字体
fstype    - 查找文件系统类型
fstypes   - 列出支持的文件系统类型
gettime   - 获取计时器 val 已过时间
go        - 在地址“addr”处启动应用程序
gpio      - 查询和控制GPIO引脚
gpt       - GUID分区表
grepenv   - 搜索环境变量
gzwrite   - 解压缩并将内存写入块设备
hash      - 计算哈希消息摘要
help      - 打印命令说明/用法
host      - 各种主机命令
i2c       - I2C 子系统
ide       - IDE 子系统
iminfo    - 打印应用程序图像的标题信息
imxtract  - 提取多图像的一部分
iod       - IO空间显示
iotrace   - iotrace 实用程序命令
iow       - IO空间修改
itest     - 整数比较时返回 true/false
lcdputs   - 在视频帧缓冲区上打印字符串
led       - 管理 LED
license   - 打印 GPL 许可证文本
linklocal - 使用链路本地协议获取网络IP地址
ln        - 创建符号链接
load      - 从文件系统加载二进制文件
loadb     - 通过串行线加载二进制文件(kermit 模式)
loadm     - 将二进制 blob 从源地址加载到目标地址
loads     - 通过串行线加载 S-Record 文件
loadx     - 通过串行线路加载二进制文件(xmodem 模式)
loady     - 通过串行线路加载二进制文件(ymodem 模式)
loop      - 地址范围上的无限循环
loopw     - 地址范围上的无限写循环
ls        - 列出目录中的文件(默认 /)
lsblk     - 列出块驱动程序和设备
lzmadec   - lzma 解压缩内存区域
mbr       - MBR (Master Boot Record,主引导记录)
md        - 内存显示
md5sum    - 计算MD5消息摘要
mdc       - 内存循环显示
mdio      - MDIO 实用程序命令
meminfo   - 显示内存信息
mii       - MII 实用程序命令
mm        - 内存修改(自动递增地址)
mmc       - MMC 子系统
mmcinfo   - 显示MMC信息
ms        - 记忆搜索
mtdparts  - 定义flash/nand分区
mtest     - 简单的RAM读/写测试
mux       - 列出、选择和取消选择多路复用器
mw        - 内存写入(填充)
mwc       - 内存写循环
net       - NET 子系统
nm        - 内存修改(常量地址)
nvme      - NVM Express 子系统
osd       - OSD 子系统
panic     - 带有可选消息的panic
part      - 磁盘分区相关命令
pause     - 延迟直到用户输入
pcap      - pcap
pci       - 列出并访问 PCI 配置空间
pci_mps   - 配置 PCI Express MPS
ping      - 发送 ICMP ECHO_REQUEST 到网络主机
ping6     - 发送 ICMPv6 ECHO_REQUEST 到网络主机
pinmux    - 显示引脚控制器复用
pmc       - 电源管理控制器信息
pmic      - PMIC子系统
poweroff  - 执行设备断电
printenv  - 打印环境变量
protect   - 启用或禁用 FLASH 写保护
pstore    - 管理 Linux 持久存储
pwm       - 控制 PWM 通道
pxe       - 从 pxe 文件获取和引导的命令要使用 IPv6 添加 -ipv6 参数
qfw       - QEMU 固件接口
random    - 用随机模式填充内存
rarpboot  - 使用 RARP/TFTP 协议通过网络启动映像
read      - 从分区加载二进制数据
regulator - uclass操作
reset     - 执行 CPU 的 RESET
rng       - 从硬件随机数生成器打印字节
rproc     - 控制 SoC 中远程处理器的操作
rtc       - RTC 子系统
run       - 在环境变量中运行命令
save      - 将文件保存到文件系统
saveenv   - 将环境变量保存到持久存储
sb        - 沙箱状态命令
scp03     - 安全通道协议03控制
scsi      - SCSI子系统
scsiboot  - 从 SCSI 设备启动
setcurs   - 设置屏幕内的光标位置
setenv    - 设置环境变量
setexpr   - 将环境变量设置为 eval 表达式的结果
sf        - SPI闪存子系统
showvar   - 打印本地 hushshell 变量
size      - 确定文件的大小
sleep     - 延迟执行一段时间
sntp      - 通过网络同步RTC
sound     - 声音子系统
source    - 从内存中运行脚本
sqfsload  - 从 SquashFS 文件系统加载二进制文件
sqfsls    - 列出目录中的文件。 默认值:根 (/)
sspi      - SPI 实用命令
stackprot_test- 测试堆栈保护器失败
sysboot   - 从 syslinux 文件获取并启动的命令
temperature- 热传感器温度
test      - 最小测试,如 /bin/sh
test_fdtdec- test_fdtdec
tftpboot  - 使用 TFTP 协议通过网络启动映像 要使用 IPv6,请添加 -ipv6 参数或使用用 [] 括号括起来的 IPv6 hostIPaddr
tftpput   - TFTP put命令,用于将文件上传到服务器
tftpsrv   - 充当 TFTP 服务器并启动第一个接收到的文件
time      - 运行命令并总结执行时间
timer     - 访问系统定时器
tpm       - 发出 TPMv1.x 命令
tpm2      - 发出 TPMv2.x 命令
tpmtest   - TPM 测试
true      - 什么都不做,成功
unbind    - 解除设备与驱动程序的绑定
unzip     - 解压缩内存区域
usb       - USB子系统
usbboot   - 从 USB 设备启动
ut        - 单元测试
ut_cmd    - 命令解析器的非常基本的测试
vbe       - 嵌入式验证启动
version   - 打印监视器、编译器和链接器版本
virtio    - virtio 块设备子系统
w1        - onewire 接口实用程序命令
wdt       - Watchdog 子系统
write     - 将二进制数据存储到分区
xxd       - 将文件作为十六进制转储打印到标准输出