一. loglevel参数的传递过程
1. nand flash上env分区
a. 在lichee/tools/pack/out/env.cfg中保存了传给内核的参数,
其中就包含了loglevel:
b. pack脚本(lichee/tools/pack/pack)中将env.cf转为了env.fex
然后在烧录时写在了nandb分区.
2. uboot将env分区中的数据引入到环境变量中
board_init_r
--> env_relocate
--> env_relocate_spec
--> flash_env_relocate_spec
在common/env_sunxi_flash.c中
2.1 引入环境变量
在common/env_common.c中
buf是nandb分区读到内存的buf,check是否进行crc校验
3. kernel解析u-boot传来的参数loglevel
在init/main.c中
在include/linux/printk.h中
/ # 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. 解压之前的打印 uncompress
2. 解压之后进入start_kernel之前的打印
3. start_kernel之后的打印
在init/main.c中
在drivers/tty/tty_io.c中
arch/arm/kernel/vmlinux.lds:
__con_initcall_start = .; *(.con_initcall.init) __con_initcall_end = .;
include/linux/init.h
只要是被
console_initcall
包着的函数都是在 con_initcall.init段中
下面找一下有几个函数被console_initcall包着
1. nand flash上env分区
a. 在lichee/tools/pack/out/env.cfg中保存了传给内核的参数,
其中就包含了loglevel:
- 9 loglevel=4
- function do_pack_android()
- {
- u_boot_env_gen env.cfg env.fex
- }
2. uboot将env分区中的数据引入到环境变量中
board_init_r
--> env_relocate
--> env_relocate_spec
--> flash_env_relocate_spec
在common/env_sunxi_flash.c中
- static void flash_env_relocate_spec(void)
- {
- //通过CONFIG_SUNXI_ENV_PARTITION="env",找到nand上的env分区的首地址
- start = sunxi_partition_get_offset_byname(CONFIG_SUNXI_ENV_PARTITION);
- //这个start就是nand上的env分区的首地址:start=0x10000
- env_offset=start;
- //将nand上的env分区读到buf中,当然并不是全部读而是读CONFIG_ENV_SIZE/512这些页
- sunxi_flash_read(start, CONFIG_ENV_SIZE/512, buf);
- //最后通过env_import将buf中的数据引入到u-boot的环间变量中去
- env_import(buf, 1); //2.1
- }
在common/env_common.c中
buf是nandb分区读到内存的buf,check是否进行crc校验
- int env_import(const char *buf, int check)
- {
- env_t *ep = (env_t *)buf;
-
- if (check) { //进行crc校验
- memcpy(&crc, &ep->crc, sizeof(crc));
- crc32(0, ep->data, ENV_SIZE);
- }
- //通过下面这个himport_r函数将buf中的env引入到环境变量中
- if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
- gd->flags |= GD_FLG_ENV_READY;
- return 1;
- }
- }
在init/main.c中
- static int __init loglevel(char *str)
- {
- //根据字符串"loglevel",在u-boot传的参数中查找匹配的一项.
- //并解析出loglevel的值并保存到全局变量console_loglevel中
- if (get_option(&str, &newlevel)) {
- console_loglevel = newlevel;
- return 0;
- }
- }
-
- early_param("loglevel", loglevel);
- #define console_loglevel (console_printk[0])
4 7 1 7
这四个值分别代表:
当前日志级别, 缺省的 消息 级别, 最低的日志级别, 缺省的日志级别
这说明,当前日志级别为4,只有小于4的日志才可以打印出来,即printk为KERN_ERR时才可打印.
4. 修改默认日志级别
只需将env.cfg中的loglevel的值由4改为7,并重新烧写即可打印全部日志.
附录: console_loglevel是如何影响输出的呢?
内核的打印级别:
在include/linux/printk.h中
- 0 --> KERN_EMERG
- 1 --> KERN_ALERT
- 2 --> KERN_CRIT
- 3 --> KERN_ERR
- 4 --> KERN_WARNING
- 5 --> KERN_NOTICE
- 6 --> KERN_INFO
- 7 --> KERN_DEBUG
1. 解压之前的打印 uncompress
2. 解压之后进入start_kernel之前的打印
3. start_kernel之后的打印
在init/main.c中
- asmlinkage void __init start_kernel(void)
- {
- printk(KERN_NOTICE "%s", linux_banner);
- console_init();
- }
- void __init console_init(void)
- {
- initcall_t *call;
-
- /* Setup the default TTY line discipline. */
- tty_ldisc_begin();
-
- /*
- * set up the console device so that later boot sequences can
- * inform about problems etc..
- */
- //调用在__con_initcall_start与__con_initcall_end之间的函数
- call = __con_initcall_start;
- while (call < __con_initcall_end) {
- (*call)();
- call++;
- }
- }
arch/arm/kernel/vmlinux.lds:
__con_initcall_start = .; *(.con_initcall.init) __con_initcall_end = .;
include/linux/init.h
- #define console_initcall(fn) \
- static initcall_t __initcall_##fn \
- __used __section(.con_initcall.init) = fn
下面找一下有几个函数被console_initcall包着