ILD

aarch64 boot console init
作者:YUAN JIANPENG 邮箱:yuanjp@hust.edu.cn
发布时间:2018-7-16 站点:Inside Linux Development

在启动过程中,start_kernel() (init/main.c) 在比较靠后的位置调用console_init()。


console_init()定义在kernel/printk/printk.c,它调用存储在.con_initcall.init section中的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
 * Initialize the console device. This is called *early*, so
 * we can't necessarily depend on lots of kernel help here.
 * Just do some early initializations, and do the complex setup
 * later.
 */
void __init console_init(void)
{
    initcall_t *call;
 
    /* Setup the default TTY line discipline. */
    n_tty_init();
 
    /*
     * set up the console device so that later boot sequences can
     * inform about problems etc..
     */
    call = __con_initcall_start;                                                                                                                                                                                    
    while (call < __con_initcall_end) {
        (*call)();
        call++;
    }    
}

在树莓派3 Model B 64位内核,drivers/tty/serial/8250/8250_core.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static struct console univ8250_console = {
    .name       = "ttyS",
    .write      = univ8250_console_write,
    .device     = uart_console_device,
    .setup      = univ8250_console_setup,
    .match      = univ8250_console_match,
    .flags      = CON_PRINTBUFFER | CON_ANYTIME,
    .index      = -1,
    .data       = &serial8250_reg,
};
 
static int __init univ8250_console_init(void)                                                                                                                                                                       
{
    if (nr_uarts == 0)
        return -ENODEV;
 
    serial8250_isa_init_ports();
    register_console(&univ8250_console);
    return 0;
}
console_initcall(univ8250_console_init);


register_console注册一个console。console_initcall定义个函数指针变量,存储在.con_initcall.init section中。

1
2
3
#define console_initcall(fn)                    \                                                                                                                                                                   
    static initcall_t __initcall_##fn           \
    __used __section(.con_initcall.init) = fn


注意,树莓派 64位内核,8250注册的不是CON_BOOT类型的console。在console_init()之前的printk将被缓存起来,不会打印,直到注册了console。这里的逻辑比较复杂,不追究了。


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.