By Toradex 秦海
1). 简介
嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。
本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。
2. 准备
a). Verdin i.MX8MP ARM核心版配合Dahlia载板并连接Debug Console 和 HDMI 显示器进行测试。
3). 测试流程
a). 参考这里说明下载Toradex Yocto Linux BSP7 对应 U-Boot 源码,根据如下 patch 文件修改编译配置后重新编译 U-Boot Image。
-------------------------------
--- a/.config2024-12-27 14:52:26.151705541 +0800
+++ .b/.config2025-01-03 17:41:42.779299312 +0800
@@ -535,9 +535,13 @@
# CONFIG_DISABLE_CONSOLE is not set
CONFIG_LOGLEVEL=4
CONFIG_SPL_LOGLEVEL=4
-# CONFIG_SILENT_CONSOLE is not set
-# CONFIG_SPL_SILENT_CONSOLE is not set
+CONFIG_SILENT_CONSOLE=y
+CONFIG_SPL_SILENT_CONSOLE=y
# CONFIG_TPL_SILENT_CONSOLE is not set
+# CONFIG_SILENT_U_BOOT_ONLY is not set
+CONFIG_SILENT_CONSOLE_UPDATE_ON_SET=y
+CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC=y
+# CONFIG_SILENT_CONSOLE_UNTIL_ENV is not set
# CONFIG_PRE_CONSOLE_BUFFER is not set
CONFIG_CONSOLE_FLUSH_SUPPORT=y
# CONFIG_CONSOLE_FLUSH_ON_NEWLINE is not set
@@ -644,7 +648,7 @@
CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x42200000
CONFIG_SPL_SYS_MALLOC_SIZE=0x80000
-CONFIG_SPL_BANNER_PRINT=y
+# CONFIG_SPL_BANNER_PRINT is not set
# CONFIG_SPL_DISPLAY_PRINT is not set
CONFIG_SPL_SYS_MMCSD_RAW_MODE=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
-------------------------------
b). 参考这里说明重新组装Verdin i.MX8MP Boot Container,在编译 ATF Image 的时候参考如下命令来关闭 log 输出。
-------------------------------
$ make PLAT=imx8mp IMX_BOOT_UART_BASE=0x30880000 LOG_LEVEL=0 DEBUG=0bl31
-------------------------------
c). 从下面地址下载 Yocto linux BSP7 Minimal/Multimedia Image 并解压。
https://developer.toradex.cn/software/toradex-embedded-software/toradex-download-links-torizon-linux-bsp-wince-and-partner-demos/#bsp-quarterly-releases
d). 用上述步骤 b 生成的 flash.bin binary 文件重命名为 “imx-boot”并替换BSP Image 里面的 “imx-boot”文件。
-------------------------------
$ tar xvf
$ $ cd
$ cp
-------------------------------
e). 参考如下 patch 修改编译 BSP Image 中的环境变量定义文件。
-------------------------------
--- a/u-boot-initial-env-sd2024-10-01 21:50:32.000000000 +0800
+++ b/u-boot-initial-env-sd2024-12-27 16:28:20.000000000 +0800
@@ -19,7 +19,7 @@
bootcmd_mmc1=devnum=1; run mmc_boot
bootcmd_mmc2=devnum=2; run mmc_boot
bootdelay=1
-console=ttymxc2
+console=null
cpu=armv8
distro_bootcmd=setenv nvme_need_init; for target in ${boot_targets}; do run bootcmd_${target}; done
efi_dtb_prefixes=/ /dtb/ /dtb/current/
@@ -45,6 +45,7 @@
scan_dev_for_scripts=for script in ${boot_scripts}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then echo Found U-Boot script ${prefix}${script}; run boot_a_script; echo SCRIPT FAILED: continuing...; fi; done
scriptaddr=0x50280000
soc=imx8m
+silent=1
update_uboot=askenv confirm Did you load flash.bin (y/N)?; if test "$confirm" = "y"; then setexpr blkcnt ${filesize} + 0x1ff && setexpr blkcnt ${blkcnt} / 0x200; mmc dev 2 1; mmc write ${loadaddr} 0x0 ${blkcnt}; fi
usb_boot=usb start; if usb dev ${devnum}; then devtype=usb; run scan_dev_for_boot_part; fi
usb_ignorelist=0x1050:*,
-------------------------------
//当然,U-Boot 环境变量的修改也可以通过修改 U-boot 源代码中include/configs/verdin-imx8mp.h文件来修改,本文不做赘述。
// 如果只需要不显示部分 Kernel log 信息,则可以只设置增加如下环境变量即可,无需重新修改编译 U-Boot
-------------------------------
# setenv tdxargs '${tdxargs} quiet'
# saveenv
-------------------------------
f). 参考这里说明将修改的BSP Image 重新更新到 Verdin i.MX8MP 模块,启动后 Debug Console 输出如下,仅剩下 SPL 配合 ARM 处理器 BootRoM 启动的简单 log 信息输出,其他 U-Boot以及 Linux Kernel/Rootfs 等输出均已经不显示。同时此时测试在不进行任何其他优化的前提下,从按下载板 “Power ON”按键开机,到连接的HDMI 屏幕出现 Qt Cinama Demo 应用显示,一共是14s 时间。而正常不做任何修改的 Yocto Linux Multimedia BSP 同样情况启动时间在 17s - 18s。
-------------------------------
DDRINFO: start DRAM init
DDRINFO: DRAM rate 4000MTS
Training FAILED
DDRINFO: start DRAM init
DDRINFO: DRAM rate 4000MTS
DDRINFO:ddrphy calibration done
DDRINFO: ddrmix config done
DDR configured as single rank
SEC0: RNG instantiated
Normal Boot
WDT: Started watchdog@30280000 with servicing every 1000ms (60s timeout)
Boot Stage: Primary boot
Find img info 0x4802d200, size 888
Need continue download 1024
Failed to find node!, err: -1!
Failed to find node!, err: -1!
-------------------------------
g). 通常情况上面保留 SPL BootROM 启动相关 log 打印即可满足需求,如果一定要完全去掉,就需要逐项查看对应的源代码,当前打印信息对应(BSP版本变更可能导致变化)以及修改 patch 请见如下,在对应源码中注释掉相关的 “printf()/puts()”打印log 输出代码重新编译即可,测试下来这样可以将启动时间缩短到 13.8s 左右。
./ ddr_init.c - https://git1.toradex.com/cgit/u-boot-toradex.git/tree/drivers/ddr/imx/imx8m/ddr_init.c?h=toradex_imx_lf_v2024.04
-------------------------------
DDRINFO: start DRAM init
DDRINFO: DRAM rate 4000MTS
DDRINFO: start DRAM init
DDRINFO: DRAM rate 4000MTS
DDRINFO:ddrphy calibration done
DDRINFO: ddrmix config done
-------------------------------
./ ddrphy_utils.c - https://git1.toradex.com/cgit/u-boot-toradex.git/tree/drivers/ddr/imx/phy/ddrphy_utils.c?h=toradex_imx_lf_v2024.04#n101
-------------------------------
Training FAILED
-------------------------------
./ spl.c - https://git1.toradex.com/cgit/u-boot-toradex.git/tree/board/toradex/verdin-imx8mp/spl.c?h=toradex_imx_lf_v2024.04
-------------------------------
DDR configured as single rank
Normal Boot
-------------------------------
./ jr.c - https://git1.toradex.com/cgit/u-boot-toradex.git/tree/drivers/crypto/fsl/jr.c?h=toradex_imx_lf_v2024.04#n937
-------------------------------
SEC0: RNG instantiated
-------------------------------
./ wdt-uclass.c - https://git1.toradex.com/cgit/u-boot-toradex.git/tree/drivers/watchdog/wdt-uclass.c?h=toradex_imx_lf_v2024.04#n143
-------------------------------
WDT: Started watchdog@30280000 with servicing every 1000ms (60s timeout)
-------------------------------
./ spl_imx_romapi.c - https://git1.toradex.com/cgit/u-boot-toradex.git/tree/arch/arm/mach-imx/spl_imx_romapi.c?h=toradex_imx_lf_v2024.04
-------------------------------
Boot Stage: Primary boot
Find img info 0x4802d200, size 888
Need continue download 1024
-------------------------------
./ spl.c - https://git1.toradex.com/cgit/u-boot-toradex.git/tree/arch/arm/mach-imx/spl.c?h=toradex_imx_lf_v2024.04#n459
-------------------------------
Failed to find node!, err: -1!
Failed to find node!, err: -1!
-------------------------------
// 完整修改 patch 请见如下
-------------------------------
diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c
index d6664bf9103..a8ef680593b 100644
--- a/arch/arm/mach-imx/spl.c
+++ b/arch/arm/mach-imx/spl.c
@@ -456,7 +456,7 @@ int board_handle_rdc_config(void *fdt_addr, const char *config_name, void *dst_a
node = fdt_node_offset_by_compatible(fdt_addr, -1, "imx8m,mcu_rdc");
if (node < 0) {
-printf("Failed to find node!, err: %d!\n", node);
+//printf("Failed to find node!, err: %d!\n", node);
ret = -1;
goto exit;
}
diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c
index 8b8d16d911f..fea293cb9ca 100644
--- a/arch/arm/mach-imx/spl_imx_romapi.c
+++ b/arch/arm/mach-imx/spl_imx_romapi.c
@@ -387,7 +387,7 @@ static int spl_romapi_load_image_stream(struct spl_image_info *spl_image,
}
imagesize = img_info_size(phdr);
-printf("Find img info 0x%p, size %d\n", phdr, imagesize);
+//printf("Find img info 0x%p, size %d\n", phdr, imagesize);
if (p - phdr < imagesize) {
imagesize -= p - phdr;
@@ -463,11 +463,11 @@ int board_return_to_bootrom(struct spl_image_info *spl_image,
if (ret != ROM_API_OKAY)
goto err;
-printf("Boot Stage: ");
+//printf("Boot Stage: ");
switch (bstage) {
case BT_STAGE_PRIMARY:
-printf("Primary boot\n");
+//printf("Primary boot\n");
break;
case BT_STAGE_SECONDARY:
printf("Secondary boot\n");
diff --git a/board/toradex/verdin-imx8mp/spl.c b/board/toradex/verdin-imx8mp/spl.c
index 73729a42b45..f6bf9260527 100644
--- a/board/toradex/verdin-imx8mp/spl.c
+++ b/board/toradex/verdin-imx8mp/spl.c
@@ -42,7 +42,7 @@ void spl_dram_init(void)
lpddr4_single_rank_training_patch();
if (!ddr_init(&dram_timing)) {
-puts("DDR configured as single rank\n");
+//puts("DDR configured as single rank\n");
return;
}
puts("DDR configuration failed\n");
@@ -69,7 +69,7 @@ void spl_board_init(void)
clock_set_target_val(GIC_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(5));
clock_enable(CCGR_GIC, 1);
-puts("Normal Boot\n");
+//puts("Normal Boot\n");
}
#define I2C_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PE)
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index 97b0cf83ae7..efb2544de02 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -934,7 +934,7 @@ init:
return -1;
}
-printf("SEC%u: RNG instantiated\n", sec_idx);
+//printf("SEC%u: RNG instantiated\n", sec_idx);
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
if (CONFIG_IS_ENABLED(DM_RNG)) {
diff --git a/drivers/ddr/imx/imx8m/ddr_init.c b/drivers/ddr/imx/imx8m/ddr_init.c
index 91d963419d6..06ff6feaa09 100644
--- a/drivers/ddr/imx/imx8m/ddr_init.c
+++ b/drivers/ddr/imx/imx8m/ddr_init.c
@@ -316,7 +316,7 @@ int ddr_init(struct dram_timing_info *dram_timing)
unsigned int tmp, initial_drate, target_freq;
int ret;
-printf("DDRINFO: start DRAM init\n");
+//printf("DDRINFO: start DRAM init\n");
/* Step1: Follow the power up procedure */
if (is_imx8mq()) {
@@ -339,7 +339,7 @@ int ddr_init(struct dram_timing_info *dram_timing)
initial_drate = dram_timing->fsp_msg[0].drate;
/* default to the frequency point 0 clock */
-printf("DDRINFO: DRAM rate %dMTS\n", initial_drate);
+//printf("DDRINFO: DRAM rate %dMTS\n", initial_drate);
ddrphy_init_set_dfi_clk(initial_drate);
/* D-aasert the presetn */
@@ -409,7 +409,7 @@ int ddr_init(struct dram_timing_info *dram_timing)
tmp = reg32_read(DDRPHY_CalBusy(0));
} while ((tmp & 0x1));
-printf("DDRINFO:ddrphy calibration done\n");
+//printf("DDRINFO:ddrphy calibration done\n");
/* Step15: Set SWCTL.sw_done to 0 */
reg32_write(DDRC_SWCTL(0), 0x00000000);
@@ -462,7 +462,7 @@ int ddr_init(struct dram_timing_info *dram_timing)
/* enable port 0 */
reg32_write(DDRC_PCTRL_0(0), 0x00000001);
-printf("DDRINFO: ddrmix config done\n");
+//printf("DDRINFO: ddrmix config done\n");
board_dram_ecc_scrub();
diff --git a/drivers/ddr/imx/phy/ddrphy_utils.c b/drivers/ddr/imx/phy/ddrphy_utils.c
index 59a15764526..cddf270e594 100644
--- a/drivers/ddr/imx/phy/ddrphy_utils.c
+++ b/drivers/ddr/imx/phy/ddrphy_utils.c
@@ -98,7 +98,7 @@ int wait_ddrphy_training_complete(void)
debug("Training PASS\n");
return 0;
} else if (mail == 0xff) {
-printf("Training FAILED\n");
+//printf("Training FAILED\n");
return -1;
}
}
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
index 417e8d7eef9..7e4213858b8 100644
--- a/drivers/watchdog/wdt-uclass.c
+++ b/drivers/watchdog/wdt-uclass.c
@@ -140,9 +140,9 @@ int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
}
}
-printf("WDT: Started %s with%s servicing %s (%ds timeout)\n",
+/*printf("WDT: Started %s with%s servicing %s (%ds timeout)\n",
dev->name, IS_ENABLED(CONFIG_WATCHDOG) ? "" : "out",
- str, (u32)lldiv(timeout_ms, 1000));
+ str, (u32)lldiv(timeout_ms, 1000));*/
}
return ret;
-------------------------------
h). 另外,U-Boot 默认的 countdown 功能虽然没有打印 log 了,但是还是依然存在,可以通过如下修改 u-boot-initial-env-sd 环境变量配置来忽略这个功能。设置后可以将启动时间缩短为 12s - 13s。
-------------------------------
bootdelay=-2
// bootdelay variable description from U-Boot documentation
bootdelay: After reset, U-Boot will wait this number of seconds before it executes the contents of the bootcmd variable. During this time a countdown is printed, which can be interrupted by pressing any key.
Set this variable to 0 boot without delay. Be careful: depending on the contents of your bootcmd variable, this can prevent you from entering interactive commands again forever!
Set this variable to -1 to disable autoboot.
Set this variable to -2 to boot without delay and not check for abort.
-------------------------------
4). 总结
本文基于NXP i.MX8MP ARM 处理器平台测试了关闭 Debug Console 来增强安全和提高启动时间的流程。
参考文档
https://developer.toradex.com/software/development-resources/configuring-serial-port-debug-console-linuxu-boot/
作者: hai.qin_651820742, 来源:面包板社区
链接: https://mbb.eet-china.com/blog/uid-me-1864768.html
版权声明:本文为博主原创,未经本人允许,禁止转载!
文章评论(0条评论)
登录后参与讨论