By Toradex?秦海
1). 簡介
嵌入式平臺(tái)設(shè)備基于Yocto Linux 在開發(fā)后期量產(chǎn)前期,為了安全以及提高啟動(dòng)速度等考慮,希望將 ARM 處理器平臺(tái)的 Debug Console 輸出關(guān)閉升薯,本文就基于 NXP i.MX8MP ARM 處理器平臺(tái)來演示相關(guān)流程忿墅。
本文所示例的平臺(tái)來自于?Toradex Verdin?i.MX8MP 嵌入式平臺(tái)闷旧。
2. 準(zhǔn)備
a). Verdin i.MX8MP ARM核心版配合Dahlia載板并連接Debug Console 和 HDMI 顯示器進(jìn)行測試窃这。
3). 測試流程
a). 參考這里說明下載Toradex Yocto Linux BSP7 對(duì)應(yīng) 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 的時(shí)候參考如下命令來關(guān)閉 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 <downloading dir>/Verdin-iMX8MP_Reference-Multimedia-Image-Tezi_7.0.0+build.1.tar
$ $ cd <downloading dir>/Verdin-iMX8MP_Reference-Multimedia-Image-Tezi_7.0.0+build.1/
$ cp <workdir>/imx-mkimage/iMX8M/flash.bin <downloading dir>/Verdin-iMX8MP_Reference-Multimedia-Image-Tezi_7.0.0+build.1/imx-boot
-------------------------------
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:*,
-------------------------------
//當(dāng)然,U-Boot 環(huán)境變量的修改也可以通過修改 U-boot 源代碼中include/configs/verdin-imx8mp.h文件來修改,本文不做贅述煌茴。
// 如果只需要不顯示部分 Kernel log 信息,則可以只設(shè)置增加如下環(huán)境變量即可虾标,無需重新修改編譯 U-Boot
-------------------------------
# setenv tdxargs '${tdxargs} quiet'
# saveenv
-------------------------------
f). 參考這里說明將修改的BSP Image 重新更新到 Verdin i.MX8MP 模塊,啟動(dòng)后 Debug Console 輸出如下灌砖,僅剩下 SPL 配合 ARM 處理器 BootRoM 啟動(dòng)的簡單 log 信息輸出璧函,其他 U-Boot以及 Linux Kernel/Rootfs 等輸出均已經(jīng)不顯示贞让。同時(shí)此時(shí)測試在不進(jìn)行任何其他優(yōu)化的前提下,從按下載板 “Power ON”按鍵開機(jī)柳譬,到連接的HDMI 屏幕出現(xiàn) Qt Cinama Demo 應(yīng)用顯示,一共是14s 時(shí)間续镇。而正常不做任何修改的 Yocto Linux Multimedia BSP 同樣情況啟動(dòng)時(shí)間在 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 啟動(dòng)相關(guān) log 打印即可滿足需求,如果一定要完全去掉摸航,就需要逐項(xiàng)查看對(duì)應(yīng)的源代碼制跟,當(dāng)前打印信息對(duì)應(yīng)(BSP版本變更可能導(dǎo)致變化)以及修改 patch 請見如下,在對(duì)應(yīng)源碼中注釋掉相關(guān)的 “printf()/puts()”打印log 輸出代碼重新編譯即可酱虎,測試下來這樣可以將啟動(dòng)時(shí)間縮短到 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
-------------------------------
-------------------------------
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 默認(rèn)的 countdown 功能雖然沒有打印 log 了读串,但是還是依然存在聊记,可以通過如下修改 u-boot-initial-env-sd 環(huán)境變量配置來忽略這個(gè)功能。設(shè)置后可以將啟動(dòng)時(shí)間縮短為 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 處理器平臺(tái)測試了關(guān)閉 Debug Console 來增強(qiáng)安全和提高啟動(dòng)時(shí)間的流程排监。
參考文檔
https://developer.toradex.com/software/development-resources/configuring-serial-port-debug-console-linuxu-boot/