Cubietruck---10.Linux3.3_开机log的打印分析

一. loglevel参数的传递过程
1. nand flash上env分区
  a. 在lichee/tools/pack/out/env.cfg中保存了传给内核的参数,
其中就包含了loglevel:
  1. 9 loglevel=4
  b. pack脚本(lichee/tools/pack/pack)中将env.cf转为了env.fex
  1. function do_pack_android()
  2. {
  3.    u_boot_env_gen env.cfg env.fex
  4. }
然后在烧录时写在了nandb分区.
2. uboot将env分区中的数据引入到环境变量中
board_init_r
--> env_relocate
    --> env_relocate_spec
    --> flash_env_relocate_spec
在common/env_sunxi_flash.c中
  1. static void flash_env_relocate_spec(void)
  2. {
  3.     //通过CONFIG_SUNXI_ENV_PARTITION="env",找到nand上的env分区的首地址
  4.     start = sunxi_partition_get_offset_byname(CONFIG_SUNXI_ENV_PARTITION);
  5.     //这个start就是nand上的env分区的首地址:start=0x10000
  6.     env_offset=start;
  7.     //将nand上的env分区读到buf中,当然并不是全部读而是读CONFIG_ENV_SIZE/512这些页
  8.     sunxi_flash_read(start, CONFIG_ENV_SIZE/512, buf);
  9.     //最后通过env_import将buf中的数据引入到u-boot的环间变量中去
  10.     env_import(buf, 1);  //2.1
  11. }
2.1 引入环境变量
在common/env_common.c中
buf是nandb分区读到内存的buf,check是否进行crc校验
  1. int env_import(const char *buf, int check)
  2. {
  3.     env_t *ep = (env_t *)buf;
  4.     
  5.     if (check) {                                //进行crc校验
  6.         memcpy(&crc, &ep->crc, sizeof(crc));
  7.         crc32(0, ep->data, ENV_SIZE);
  8.     }
  9.     //通过下面这个himport_r函数将buf中的env引入到环境变量中
  10.     if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
  11.         gd->flags |= GD_FLG_ENV_READY;
  12.         return 1;
  13.     }
  14. }
3. kernel解析u-boot传来的参数loglevel
在init/main.c中
  1. static int __init loglevel(char *str)
  2. {
  3.     //根据字符串"loglevel",在u-boot传的参数中查找匹配的一项.
  4.     //并解析出loglevel的值并保存到全局变量console_loglevel中    
  5.     if (get_option(&str, &newlevel)) {
  6.         console_loglevel = newlevel;
  7.         return 0;
  8.     }
  9. }

  10. early_param("loglevel", loglevel);
在include/linux/printk.h中
  1. #define console_loglevel (console_printk[0])
/ # cat /proc/sys/kernel/printk
4       7       1       7
这四个值分别代表: 
当前日志级别, 缺省的 消息 级别, 最低的日志级别, 缺省的日志级别
这说明,当前日志级别为4,只有小于4的日志才可以打印出来,即printk为KERN_ERR时才可打印.
4. 修改默认日志级别
只需将env.cfg中的loglevel的值由4改为7,并重新烧写即可打印全部日志.



附录: console_loglevel是如何影响输出的呢?





内核的打印级别:
在include/linux/printk.h中
  1. --> KERN_EMERG
  2. --> KERN_ALERT
  3. --> KERN_CRIT
  4. --> KERN_ERR
  5. --> KERN_WARNING
  6. --> KERN_NOTICE
  7. --> KERN_INFO
  8. --> KERN_DEBUG







1. 解压之前的打印 uncompress  
2.  解压之后进入start_kernel之前的打印
3. start_kernel之后的打印
在init/main.c中
  1. asmlinkage void __init start_kernel(void)
  2. {
  3.     printk(KERN_NOTICE "%s", linux_banner);
  4.     console_init();
  5. }
在drivers/tty/tty_io.c中
  1. void __init console_init(void)
  2. {
  3.     initcall_t *call;

  4.     /* Setup the default TTY line discipline. */
  5.     tty_ldisc_begin();

  6.     /*
  7.      * set up the console device so that later boot sequences can
  8.      * inform about problems etc..
  9.      */
  10.     //调用__con_initcall_start__con_initcall_end之间的函数
  11.     call = __con_initcall_start;
  12.     while (call < __con_initcall_end) {
  13.         (*call)();
  14.         call++;
  15.     }
  16. }


arch/arm/kernel/vmlinux.lds:
      __con_initcall_start = .; *(.con_initcall.init) __con_initcall_end = .;
include/linux/init.h
  1. #define console_initcall(fn) \
  2.     static initcall_t __initcall_##fn \
  3.     __used __section(.con_initcall.init) = fn
只要是被 console_initcall 包着的函数都是在 con_initcall.init段中

下面找一下有几个函数被console_initcall包着
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值