Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2149194
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: Android平台

2014-05-06 17:59:43

一. 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. 0 --> KERN_EMERG
  2. 1 --> KERN_ALERT
  3. 2 --> KERN_CRIT
  4. 3 --> KERN_ERR
  5. 4 --> KERN_WARNING
  6. 5 --> KERN_NOTICE
  7. 6 --> KERN_INFO
  8. 7 --> 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包着






阅读(878) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~