一. loglevel参数的传递过程
1. nand flash上env分区
a. 在lichee/tools/pack/out/env.cfg中保存了传给内核的参数,
其中就包含了loglevel:
b. pack脚本(lichee/tools/pack/pack)中将env.cf转为了env.fex
-
function do_pack_android()
-
{
-
u_boot_env_gen env.cfg env.fex
-
}
然后在烧录时写在了nandb分区.
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
-
}
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;
-
}
-
}
3. kernel解析u-boot传来的参数loglevel
在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);
在include/linux/printk.h中
-
#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中
-
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();
-
}
在drivers/tty/tty_io.c中
-
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包着的函数都是在 con_initcall.init段中
下面找一下有几个函数被console_initcall包着
阅读(878) | 评论(0) | 转发(0) |