NXP iMX8MP 處理器基于 Linux 關(guān)閉 Debug Console 輸出
1). 簡介
嵌入式平臺設備基于 Yocto Linux 在開發(fā)后期量產(chǎn)前期,為了安全以及提高啟動速度等考慮,希望將 ARM 處理器平臺的 Debug Console 輸出關(guān)閉,本文就基于 NXP i.MX8MP ARM 處理器平臺來演示相關(guān)流程。
本文所示例的平臺來自于 Toradex Verdin i.MX8MP 嵌入式平臺。
2. 準備
a). Verdin i.MX8MP ARM核心版配合Dahlia 載板并連接 Debug Console 和 HDMI 顯示器進行測試。
3). 測試流程
a). 參考這里說明下載 Toradex Yocto Linux BSP7 對應 U-Boot 源碼,根據(jù)如下 patch 文件修改編譯配置后重新編譯 U-Boot Image。
-------------------------------
--- a/.config 2024-12-27 14:52:26.151705541 +0800
+++ .b/.config 2025-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 的時候參考如下命令來關(guān)閉 log 輸出。
-------------------------------
$ make PLAT=imx8mp IMX_BOOT_UART_BASE=0x30880000 LOG_LEVEL=0 DEBUG=0 bl31
-------------------------------
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 中的環(huán)境變量定義文件。
-------------------------------
--- a/u-boot-initial-env-sd 2024-10-01 21:50:32.000000000 +0800
+++ b/u-boot-initial-env-sd 2024-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 環(huán)境變量的修改也可以通過修改 U-boot 源代碼中 include/configs/verdin-imx8mp.h 文件來修改,本文不做贅述。
// 如果只需要不顯示部分 Kernel log 信息,則可以只設置增加如下環(huán)境變量即可,無需重新修改編譯 U-Boot
-------------------------------
# setenv tdxargs '${tdxargs} quiet'
# saveenv
-------------------------------
f). 參考這里說明將修改的 BSP Image 重新更新到 Verdin i.MX8MP 模塊,啟動后 Debug Console 輸出如下,僅剩下 SPL 配合 ARM 處理器 BootRoM 啟動的簡單 log 信息輸出,其他 U-Boot以及 Linux Kernel/Rootfs 等輸出均已經(jīng)不顯示。同時此時測試在不進行任何其他優(yōu)化的前提下,從按下載板 “Power ON” 按鍵開機,到連接的 HDMI 屏幕出現(xiàn) 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 啟動相關(guān) log 打印即可滿足需求,如果一定要完全去掉,就需要逐項查看對應的源代碼,當前打印信息對應(BSP版本變更可能導致變化)以及修改 patch 請見如下,在對應源碼中注釋掉相關(guān)的 “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 環(huán)境變量配置來忽略這個功能。設置后可以將啟動時間縮短為 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). 總結(jié)
本文基于 NXP i.MX8MP ARM 處理器平臺測試了關(guān)閉 Debug Console 來增強安全和提高啟動時間的流程。
參考文檔
https://developer.toradex.com/software/development-resources/configuring-serial-port-debug-console-linuxu-boot/
![](http://src.gongkong.com/website/gongkong/images/news/icon.png)
提交
ARM 處理器平臺 Ethernet Compliance 測試流程示例
基于 NXP iMX8QM 運行 QNX
通過恢復模式更新 Toradex ARM 計算機模塊 BSP 鏡像
Yocto Linux BSP7 新版本介紹
基于 NXP iMX8MP 平臺簡單測試 PySide6 應用