earlycon 的使用【轉】

轉自:https://blog.csdn.net/wjxcn/article/details/79542406

關於 earlycon 的實現機制,已經有很多文章提及,這裏就不贅述了。

主要就是記錄在某高通平臺打開 earlycon 的一個過程記錄。

使用 earlycon 最好的方式,其參數是從 dtb 取得,也就是我們要在 dts 裏配置 chosen 節點

    chosen {
        bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1 app_setting.use_32bit_app_setting=1";
        stdout-path = &uart0;
    };
關於 stdout-path ,在這個平臺上並沒有 uart0 這個節點,其 /proc/cmdline 裏控制檯參數是

console=ttyHSL0,115200,n8
查看下它的設備號

# ls -l /dev/ttyHSL0
crw------- 1 root root 240,   0 1970-01-01 06:27 /dev/ttyHSL0
查看下其他相關信息

# cd /sys/dev/char/240:0
/sys/dev/char/240:0 # cat iomem_base                                   
0x75B0000
/sys/dev/char/240:0 # cat uevent                                       
MAJOR=240
MINOR=0
DEVNAME=ttyHSL0
/sys/dev/char/240:0 # cd device/                                       
/sys/dev/char/240:0/device # cat uevent                                e
DRIVER=msm_serial_hsl
OF_NAME=serial
OF_FULLNAME=/soc/serial@075b0000
OF_COMPATIBLE_0=qcom,msm-lsuart-v14
OF_COMPATIBLE_N=1
MODALIAS=of:NserialT<NULL>Cqcom,msm-lsuart-v14

根據 compatible 和 iomem_base 從相關的dtsi 裏確認,其 stdout-path 應該爲

    chosen {
        bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1 app_setting.use_32bit_app_setting=1";
        stdout-path = &uartblsp2dm1;
    };
找到平臺對應的mk 文件(這裏是BoardConfig.mk)添加

ifneq ($(TARGET_BUILD_VARIANT),user)
    BOARD_KERNEL_CMDLINE += earlycon
endif
結果發現並沒有生效,而是出現這樣的 Kernel log

[    0.000000] Malformed early option 'earlycon'
由網上的文章,我們可以知道,在一個特定系統裏對於 earlycon 支持,關鍵的幾個配置開關

CONFIG_DEBUG_KERNEL=y
CONFIG_SERIAL_EARLYCON=y
CONFIG_OF_EARLY_FLATTREE=Y

幾個定義

EARLYCON_DECLARE
OF_EARLYCON_DECLARE
在代碼裏查找,發現使用的是

EARLYCON_DECLARE(msm_hsl_uart, msm_hsl_earlycon_setup);
OF_EARLYCON_DECLARE(msm_hsl_uart, "qcom,msm_hsl_uart", msm_hsl_earlycon_setup);
由 fdt.c 裏的相關源碼

#ifdef CONFIG_SERIAL_EARLYCON
extern struct of_device_id __earlycon_of_table[];
 
static int __init early_init_dt_scan_chosen_serial(void)
{
    int offset;
    const char *p;
    int l;
    const struct of_device_id *match = __earlycon_of_table;
    const void *fdt = initial_boot_params;
    offset = fdt_path_offset(fdt, "/chosen");
    if (offset < 0)
        offset = fdt_path_offset(fdt, "/chosen@0");
    if (offset < 0)
        return -ENOENT;
 
    p = fdt_getprop(fdt, offset, "stdout-path", &l);
    if (!p)
        p = fdt_getprop(fdt, offset, "linux,stdout-path", &l);
    if (!p || !l)
        return -ENOENT;
 
    /* Get the node specified by stdout-path */
    offset = fdt_path_offset(fdt, p);
    if (offset < 0)
        return -ENODEV;
 
    while (match->compatible[0]) {
        unsigned long addr;
        if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
            match++;
            continue;
        }
 
        addr = fdt_translate_address(fdt, offset);
        if (!addr){
            return -ENXIO;
        }
 
        of_setup_earlycon(addr, match->data);
        return 0;
    }
    return -ENODEV;
}
 
static int __init setup_of_earlycon(char *buf)
{
    if (buf)
        return 0;
 
    return early_init_dt_scan_chosen_serial();
}
early_param("earlycon", setup_of_earlycon);
#endif
在進行 of 掃描時,會檢查 compatible,因此換裏這裏的

OF_EARLYCON_DECLARE(msm_hsl_uart, "qcom,msm_hsl_uart", msm_hsl_earlycon_setup); 
應當改爲

OF_EARLYCON_DECLARE(msm_hsl_uart, "qcom,msm-lsuart-v14", msm_hsl_earlycon_setup);
重新編譯下載 boot.img,果然 OK 。

後續閱讀 Documentation/kernel-parameters.txt,關於 earlycon 還有與msm_hsl_uart 相關的一段說明

earlycon=    [KNL] Output early console device and options.
.
.
.
        msm_hsl_uart,<addr>
             Start an early, polled-mode console on an msm serial
             port at the specified address. The serial port
             must already be setup and configured. Options are not
             yet supported.
.
.
.
我們如果只修改 kernel 的命令行

BOARD_KERNEL_CMDLINE += earlycon=msm_hsl_uart,0x075b0000
也是可以的,但是這樣,參數就不是從 dtb 讀取。
————————————————
版權聲明:本文爲CSDN博主「wjxcn」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/wjxcn/article/details/79542406

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章