printk打印到LCD

本文介绍了Linux内核启动过程中命令行参数的处理,包括如何通过修改`command_line`来改变系统控制台。在`setup_arch`函数中,解析并保存命令行参数,并在`console_init`时初始化控制台。文章详细讲解了`checksetup`函数如何处理命令行参数,`console_setup`函数如何设置控制台。当选择LCD作为显示设备时,`take_over_console`函数将`conswitchp`指向`fb_con`,通过`fbcon_init`实现LCD显示。最后,文章对比了`tty`、`tty0`、`console`、`vc/0`等不同设备的差异。
摘要由CSDN通过智能技术生成

先从ppcboot传过来的启动命令参数说起,ppcboot把它放在内的存固定地址,参数如下
char linux_cmd[] = "initrd=0x30800000,0x440000 root=/dev/ram init=/linuxrc console=ttyS0";
在内核start_kernel函数中调用了setup_arch(&command_line)取到命令参数并保存到
saved_command_line字符数组里,同时command_line字符指针指向一个全局的字符数组
command_line(同名,不过这是全局的),其中存放的同样是命令行参数。
为了方便,我们可以在此就另给command_line赋值,而不需要去改ppcboot了。
command_line="initrd=0x30800000,0x440000 root=/dev/ram init=/linuxrc console=tty0";
这样就可以改变系统的控制台了. 还是在setup_arch函数中找到了以下代码,以后会用到的.
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
 conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
 conswitchp = &dummy_con;
#endif
#endif
CONFIG_VT,在menuconfig的Character devices中选上Virtual terminal
CONFIG_VGA_CONSOLE,在menuconfig的Console drivers中选上VGA text console
CONFIG_DUMMY_CONSOLE,在menuconfig的Console drivers的Frame-buffer support中
选上Support for frame buffer devices,参看driver/video中的Config.in文件
意思是如果选择VGA文本控制台,那么缺省的显示设备接口是vga_con,如果是LCD之类的
Frame-buffer设备,则缺省的显示设备接口是dummy_con.
我这边是用的LCD,所以重点关注dummy_con.
const struct consw *conswitchp;
const struct consw dummy_con = {
    con_startup: dummycon_startup,
    con_init:  dummycon_init,
    con_deinit:  DUMMY,
    con_clear:  DUMMY,
    con_putc:  DUMMY,
    con_putcs:  DUMMY,
    con_cursor:  DUMMY,
    con_scroll:  DUMMY,
    con_bmove:  DUMMY,
    con_switch:  DUMMY,
    con_blank:  DUMMY,
    con_font_op: DUMMY,
    con_set_palette: DUMMY,
    con_scrolldelta: DUMMY,
};
还是回到start_kernel中,接下来调用了parse_options(command_line)来处理命令行
它会以空格对命令行进行分解,比如分解后使得line="console=ttyS0",然后调用
checksetup(line),下面分析一下这个函数
static int __init checksetup(char *line)
{
 struct kernel_param *p;
 p = &__setup_start; //setup段开始地址
 do {
  int n = strlen(p->str);
  if (!strncmp(line,p->str,n)) //比较line和p->str的n个字符
  {
   if (p->setup_func(line+n))//相等则调用函数
    return 1;
  }
  p++;
 } while (p < &__setup_end);
 return 0;
}
需要理解的是这个setup段,这和驱动的初始化init_call段类似,在include/linux/init.h
中可以找到
#define __setup(str, fn)        /
 static char __setup_str_##fn[] __initdata = str;    /
 static struct kernel_param __setup_##fn __attribute__((unused)) __initsetup = { __setup_str_##fn, fn }
#define __initsetup __attribute__ ((unused,__section__ (".setup.init")))
另外我在kernel/printk.c中找到了__setup("console=", console_setup);
通过这个函数,在链接时就会在段.setup.init中建立一个kernel_param结构,其中一个成员
是字符串"console="的指针,另一个则是console_setup这个函数指针,于是这样在checksetup
中就必然会调用到console_setup这个函数了.
该函数的作用是把传入的字符串进行处理并保存在全局结构中.我们以console=ttyS0 console=tty0
为例,这样就会调用console_setup两次,第一次是console_setup("ttyS0"),第二次是console_setup("tty0").
全局结构struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
struct console_cmdline
{
 char name[8];   /* Name of the driver     */
 int index;    /* Minor dev. to use     */
 char *opti

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值