修改uboot的log显示

本文介绍如何在U-Boot中自定义启动Logo,包括准备图片、编译配置、环境变量设置等步骤,以及源码分析和背景修改方法。

uboot version:2016.03

hardware:imx6ull

ubuntu 18.04

说明:本文使用uboot的根目录为uboot/

一、修改显示流程

(1)准备一张.jpg的图片(例如图片名为test.jpg),图片像素大小不要超过显示屏的大小,例如我的显示屏像素为1024x600.准备的图片为350x350.

(2)将图片通过工具发送到ubuntu中。使用命令

jpegtopnm test.jpg | ppmquant 31 | ppmtobmp -bpp 8 > test.bmp

生成test.bmp。

(3)将生成test.bmp复制到uboot/tools/logos中。(uboot的log文件都存放这个目录中)

(4)修改uboot/tools的Makefile文件:

# Generic logo
ifeq ($(LOGO_BMP),)
LOGO_BMP= $(srctree)/$(src)/logos/denx.bmp

# Use board logo and fallback to vendor
ifneq ($(wildcard $(srctree)/$(src)/logos/$(BOARD).bmp),)
LOGO_BMP= $(srctree)/$(src)/logos/$(BOARD).bmp
else
ifneq ($(wildcard $(srctree)/$(src)/logos/$(VENDOR).bmp),)
LOGO_BMP= $(srctree)/$(src)/logos/$(VENDOR).bmp
endif
endif

endif # !LOGO_BMP

#alpha board new add
LOGO_BMP= $(srctree)/$(src)/logos/alpha_fczlm.bmp

在LOGO_BMP赋值的最后,给LOGO_BMP重新赋值为test.bmp图片。

(5)返回uboot/执行make命令重新编译uboot.

(6)将编译生成的uboot.imx下载到板子上,开机可以看到图片修改成功。但是现实在左上角如图所示:

(7)解决log显示在左上角的问题。可以设置一个环境变量叫splashpos,这个环境变量是设置log显示的起始位置的。设置命令为:(此处设置显示为中间:则图片显示的起始坐标为:X = 1024/2 - 350/2 = 362;Y = 600/2 - 350/2 = 150)

setenv splashpos '362,150'
saveenv

重启,log即显示在中间。

注意:log显示的起始坐标不是(0,0),就不会显示uboot版本信息。

二、源码分析

(1)uboot中log显示调用函数过程:

void board_init_r()<common\board_r.c>
        int stdio_add_devices(void)<common\stdio.c>
            int drv_video_init(void)<drivers\video\cfb_console.c>
                static int video_init(void)<drivers\video\cfb_console.c>        
                    static void *video_logo(void)<drivers\video\cfb_console.c>

(2)static void *video_logo(void)源码分析

static void *video_logo(void)
{
	char info[128];
	int space, len;
	__maybe_unused int y_off = 0;
	__maybe_unused ulong addr;
	__maybe_unused char *s;

        /*
           获取splashpos环境变量设置的log现实的位置
           (video_logo_xpos和video_logo_ypos是一个静态环境变量,所以默认初始值为0)
         */
	splash_get_pos(&video_logo_xpos, &video_logo_ypos);		
#ifdef CONFIG_SPLASH_SCREEN  //在mx6ull_alpha_emmc.h中定义了该宏
        s = getenv("splashimage");//没有定义该环境变量(该环境变量是制定log路径的)
        if (s != NULL) {
		splash_screen_prepare();
		addr = simple_strtoul(s, NULL, 16);

		if (video_display_bitmap(addr,
					video_logo_xpos,
					video_logo_ypos) == 0) {
			video_logo_height = 0;
			return ((void *) (video_fb_address));
		}
	}
#endif /* CONFIG_SPLASH_SCREEN */

	logo_plot(video_fb_address, video_logo_xpos, video_logo_ypos);	//显示log

#ifdef CONFIG_SPLASH_SCREEN_ALIGN    //在mx6ull_alpha_emmc.h中定义了该宏
	/*
	 * when using splashpos for video_logo, skip any info
	 * output on video console if the logo is not at 0,0
	 */
	if (video_logo_xpos || video_logo_ypos) {   //如果显示坐标不为(0,0)
		/*
		 * video_logo_height is used in text and cursor offset
		 * calculations. Since the console is below the logo,
		 * we need to adjust the logo height
		 */
		if (video_logo_ypos == BMP_ALIGN_CENTER)
			video_logo_height += max(0, (int)(VIDEO_VISIBLE_ROWS -
						     VIDEO_LOGO_HEIGHT) / 2);
		else if (video_logo_ypos > 0)
			video_logo_height += video_logo_ypos;
                
                /*返回video_console_address*/
		return video_fb_address + video_logo_height * VIDEO_LINE_LEN;			
}
#endif
	//从上面代码可以分析出,如果log显示的起始坐标不为(0,0)则不会执行下面的代码
	if (board_cfb_skip())
		return 0;

	sprintf(info, " %s", version_string);	//获取uboot信息
								
	space = (VIDEO_COLS - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
	len = strlen(info);

	if (len > space) {
		int xx = VIDEO_INFO_X, yy = VIDEO_INFO_Y;
		uchar *p = (uchar *) info;
		while (len) {
			if (len > space) {
				video_drawchars(xx, yy, p, space);
				len -= space;

				p = (uchar *) p + space;

				if (!y_off) {
					xx += VIDEO_FONT_WIDTH;
					space--;
				}
				yy += VIDEO_FONT_HEIGHT;

				y_off++;
			} else {
				video_drawchars(xx, yy, p, len);
				len = 0;
			}
		}
	} else
	video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);	//显示uboot信息

#ifdef CONFIG_CONSOLE_EXTRA_INFO
	{
		int i, n =
			((video_logo_height -
			  VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);

		for (i = 1; i < n; i++) {
			video_get_info_str(i, info);
			if (!*info)
				continue;

			len = strlen(info);
			if (len > space) {
				video_drawchars(VIDEO_INFO_X,
						VIDEO_INFO_Y +
						(i + y_off) *
							VIDEO_FONT_HEIGHT,
						(uchar *) info, space);
				y_off++;
				video_drawchars(VIDEO_INFO_X +
						VIDEO_FONT_WIDTH,
						VIDEO_INFO_Y +
							(i + y_off) *
							VIDEO_FONT_HEIGHT,
						(uchar *) info + space,
						len - space);
			} else {
				video_drawstring(VIDEO_INFO_X,
						 VIDEO_INFO_Y +
						 (i + y_off) *
							VIDEO_FONT_HEIGHT,
						 (uchar *) info);
			}
		}
	}
#endif
        //返回video_console_address
	return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);	}
#endif

(3)修改显示背景。修改#define CONSOLE_BG_COL      0x00<include\video_fb.h>即可。0x00为黑色背景,如果要显示白色背景,修改为0xFF即可

 

<think>我们正在查找uboot中配置内核输出等级loglevel的方法。根据用户提供的引用和上下文,我们知道内核的loglevel可以通过多种方式配置,包括内核编译时的默认设置、内核启动参数等。 在uboot中,我们通常通过设置内核启动参数来控制内核的行为。具体到loglevel,它可以通过内核命令行参数`loglevel`或`quiet`来设置。比如: - `loglevel=<n>`: 其中n是一个数字,表示内核打印信息的等级,数值越低表示打印的信息越重要。 - `quiet`: 这个参数会将loglevel设置为0,即只显示最紧急的信息。 在uboot中,我们可以通过设置`bootargs`环境变量来传递这些参数给内核。因为uboot在启动内核时会将`bootargs`环境变量的内容作为命令行参数传递给内核。 因此,在uboot中配置内核输出等级的方法是: 1. 进入uboot命令行界面(通常在系统启动时按下某个键,如空格键或回车键,进入uboot命令行)。 2. 查看当前的环境变量:`printenv` 3. 修改`bootargs`环境变量,在其中添加`loglevel=<n>`或`quiet`参数。如果`bootargs`已经存在,我们可以在其基础上添加;如果不存在,需要创建。 例如,假设我们想将内核的loglevel设置为8(即显示所有信息,包括调试信息): setenv bootargs ${bootargs} loglevel=8 或者,如果我们想使用安静模式: setenv bootargs ${bootargs} quiet 注意:这里${bootargs}表示原有的bootargs内容,这样我们可以在原有基础上追加。如果原有bootargs没有我们需要保留的其他参数,也可以直接覆盖。 4. 保存环境变量:`saveenv`(这样下次启动时也会生效) 5. 启动内核:`boot`(或者根据具体启动命令,可能是`bootm`等) 另外,如果不想永久保存,也可以只对本次启动有效: setenv bootargs ... (不执行saveenv,然后直接启动) 此外,我们也可以在uboot的环境变量中直接设置一个完整的bootargs,而不追加。例如: setenv bootargs console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/path/to/rootfs ip=192.168.1.2:192.168.1.1::255.255.255.0::eth0:off loglevel=8 然后启动。 参考引用[2]中提到了uboot通过环境变量配置启动参数,包括设置bootargs传递给内核。引用[3]和[5]提到内核启动参数可以控制内核的行为,包括日志等级。 因此,总结步骤: 1. 进入uboot命令行。 2. 设置bootargs环境变量,加入loglevel参数(可以追加或覆盖)。 3. 保存(如果需要永久生效)。 4. 启动内核。 注意:具体的bootargs内容需要根据你的系统配置而定(如控制台、根文件系统等其他参数)。 如果用户想查看内核日志等级设置是否生效,可以在内核启动后使用命令`cat /proc/cmdline`查看实际传递的内核参数,以及可以通过`cat /proc/sys/kernel/printk`查看当前内核的日志等级设置。 另外,如果用户还想知道内核默认的日志等级是多少,可以参考引用[1]中提到的内核源码中的默认配置: 在printk.c中定义了console_printk数组,其中第一个元素console_loglevel就是控制台的日志等级。默认值在编译时由CONSOLE_LOGLEVEL_DEFAULT(通常为7)决定。 但是,通过命令行参数传递的loglevel会覆盖内核的默认设置。 生成相关问题: 1. 如何在内核运行时动态修改日志等级? 2. 内核日志等级各数值代表什么含义? 3. 除了loglevel参数,还有哪些内核启动参数会影响输出信息? </think>### Uboot中配置内核输出等级loglevel的方法 在Uboot中配置内核日志输出等级,主要通过修改内核启动参数实现,具体步骤如下: #### 1. **设置内核启动参数** 在Uboot环境变量中,通过修改`bootargs`参数传递`loglevel=<N>`选项给内核: ```bash # 设置日志等级为8(最大值,输出所有信息) setenv bootargs ${bootargs} loglevel=8 # 或设置为0(仅紧急信息) setenv bootargs ${bootargs} loglevel=0 ``` 其中`<N>`取值范围为0-8,数值越高输出越多调试信息[^1][^5]。 #### 2. **永久保存配置** 执行`saveenv`保存配置到存储介质: ```bash saveenv ``` #### 3. **验证参数传递** 启动内核前可通过`printenv`检查参数: ```bash printenv bootargs ``` 输出应包含类似:`loglevel=8 console=ttyS0,115200 root=/dev/mmcblk0p2 ...` #### 4. **内核侧的验证** 内核启动后检查生效状态: ```bash # 查看实际传递的内核参数 cat /proc/cmdline # 查看当前日志等级 cat /proc/sys/kernel/printk ``` 输出示例:`7 4 1 7` (四个值分别对应:当前控制台日志等级/默认消息等级/最低允许等级/启动默认等级)[^1] --- ### 关键原理说明 1. **参数传递机制** Uboot通过`bootargs`环境变量向内核传递命令行参数,内核解析`loglevel=`选项初始化`console_printk[0]`[^1][^5]。 2. **日志等级含义** | 等级 | 含义 | 说明 | |------|---------------|----------------------| | 0 | KERN_EMERG | 系统不可用 | | 1 | KERN_ALERT | 需立即处理 | | 2 | KERN_CRIT | 严重错误 | | 3 | KERN_ERR | 一般错误 | | 4 | KERN_WARNING | 警告 | | 5 | KERN_NOTICE | 普通通知 | | 6 | KERN_INFO | 提示信息 | | 7 | KERN_DEBUG | 调试信息 | | 8 | KERN_DEFAULT | 默认级别(通常同7) | 3. **其他相关参数** - `quiet`:等效于`loglevel=0` - `debug`:等效于`loglevel=8` - `ignore_loglevel`:强制打印所有日志(需内核配置支持) --- ### 操作注意事项 1. 若Uboot与内核版本不匹配,可能导致参数传递失败 2. 某些嵌入式设备可能需要额外指定控制台: `setenv bootargs console=ttyS0,115200 loglevel=8` 3. 修改后若日志无变化,检查内核配置: `CONFIG_CONSOLE_LOGLEVEL_DEFAULT`和`CONFIG_MESSAGE_LOGLEVEL_DEFAULT`[^1] > ⚠️ **安全提示**:生产环境建议设置`loglevel=3`以下,避免敏感信息泄露。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值