linux kernel logo

CPU:imx8mp
系统:Android 11

一、内核配置

##需要开启的宏
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_VT=y
CONFIG_LOGO=y

##相关文件所在位置
drivers/video/logo/

二、logo制作

ubuntu系统安装下面命令:

sudo apt-get install netpbm

PNG图片参考下面命令:

pngtopnm linux_usr_logo.png >linux_usr_logo.pnm    #将png转换成pnm文件
pnmquant 224 linux_usr_logo.pnm >linux_usr_logo_clut224.pnm  #将pnm图片颜色数限制在224色
pnmtoplainpnm linux_usr_logo_clut224.pnm >linux_usr_logo_clut224.ppm #将pnm图片转换成ppm。

BMP图片参考下面命令:

bmptoppm linux_usr_logo.png >linux_usr_logo.ppm    #将BMP转换成ppm文件
ppmquant 224 linux_usr_logo.ppm >linux_usr_logo_clut224_tmp.ppm  #将ppm图片颜色数限制在224色
pnmnoraw linux_usr_logo_clut224_tmp.ppm >linux_usr_logo_clut224.ppm  #转换成ascii格式。

将生成的ppm文件替换掉内核"drivers/video/logo/"中的logo文件,如果需要新增logo文件,可仿照logo_linux_clut224修改。

三、logo居中且只显示一张图片

通常linux显示的内核logo会根据CPU的核心数,在屏幕左上角显示出多张logo图片。下面通过设置CMDLINE让logo仅显示一张图片并居中。
android系统找到"BOARD_KERNEL_CMDLINE"(一般在"BoardConfig.mk"中),其它系统需要找对应"bootargs",添加如下内容:

fbcon=logo-pos:center,logo-count:1

这段设置来自于"drivers/video/fbdev/core/fbcon.c"的“fb_console_setup”函数,如果函数中存在下面内容,设置才有效。

static int __init fb_console_setup(char *this_opt)
{
        char *options;
        int i, j;

        if (!this_opt || !*this_opt)
                return 1;

        while ((options = strsep(&this_opt, ",")) != NULL) {
                if (!strncmp(options, "font:", 5)) {
                        strlcpy(fontname, options + 5, sizeof(fontname));
                        continue;
                }
                ...部分代码省略...                
                if (!strncmp(options, "logo-pos:", 9)) {     //设置logo居中
                        options += 9;
                        if (!strcmp(options, "center"))
                                fb_center_logo = true;
                        continue;
                }

                if (!strncmp(options, "logo-count:", 11)) {  //设置logo图片数量
                        options += 11;
                        if (*options)
                                fb_logo_count = simple_strtol(options, &options, 0);
                        continue;
                }
        }
        return 1;
}
__setup("fbcon=", fb_console_setup);     //这里能看到是cmdline中的那个参数。

四、调试

正常下启用上面宏后,在显示正常的情况下内核启动过程中就会显示企鹅图标。但是在我的系统中kernel阶段的logo并没有显示出来,只显示了一个光标,然后就就进入android logo了。查看"drivers/video/logo/logo.c"的"fb_find_logo"函数中可以看到当nologo或logos_freed被设置成true时函数直接返回,并且在这里添加log也能看到logos_freed确实被设置成了true。尝试注释掉判断内核logo依然无法显示,而且内核会报错,报错的提示logo文件不存在。

const struct linux_logo * __ref fb_find_logo(int depth)
{
    const struct linux_logo *logo = NULL;

    if (nologo || logos_freed)
        return NULL;
...部分代码省略...
      return logo;
}
EXPORT_SYMBOL_GPL(fb_find_logo);

无法显示的原因:
在logo.c中可以看到下面一段初始化的代码。这个初始化函数被放在late_initcall_sync代码段中,这个代码段中的函数会在内核初始化的最后阶段被调用。函数的注解也说明logo被放在了initdata数据段中,而且在kernel_init中会被释放,使用late_init来标记logo是否被释放,防止进一步使用。所以函数中设置了’logos_freed = true",就是为了防止logo数据已经被清除的情况下,还在使用。

static bool logos_freed;
 /*
 * Logos are located in the initdata, and will be freed in kernel_init.
 * Use late_init to mark the logos as freed to prevent any further use.
 */
static int __init fb_logo_late_init(void)
{
    logos_freed = true;
    return 0;
}

late_initcall_sync(fb_logo_late_init);

另外:在编译输出"drivers/video/logo/“下可以看到对应ppm文件生成的”.c"文件。通过这个文件中的内容也可以看出生成的logo数据被放在initdata数据段中。其实造成这一现象的主要原因是我的系统在开机要显示logo的时候,系统内核初始化过程已经完成,都已经执行android的init进程了,initdata数据段也已经被清除了,所以无法显示logo。
修改方法:

  • 注释掉"fb_find_logo"中对"logos_freed"的判断或在fb_logo_late_init函数中设置“logos_freed = false”。
  • 将logo数据不要放在initdata数据段中。“ppm"生成“.c”的过程是“drivers/video/logo/pnmtologo.c”完成的,删除这个文件中关于指定”__initdata"和"__initconst"数据段的地方。
    修改的patch:
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index 141f15a9a..0e1208a3b 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -31,7 +31,7 @@ static bool logos_freed;

 static int __init fb_logo_late_init(void)
 {
-       logos_freed = true;
+       logos_freed = false;
        return 0;
 }

diff --git a/drivers/video/logo/pnmtologo.c b/drivers/video/logo/pnmtologo.c
index 4718d7895..9220d5899 100644
--- a/drivers/video/logo/pnmtologo.c
+++ b/drivers/video/logo/pnmtologo.c
@@ -244,14 +244,14 @@ static void write_header(void)
     fprintf(out, " *  Linux logo %s\n", logoname);
     fputs(" */\n\n", out);
     fputs("#include <linux/linux_logo.h>\n\n", out);
-    fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
+    fprintf(out, "static unsigned char %s_data[] = {\n",
            logoname);
 }

 static void write_footer(void)
 {
     fputs("\n};\n\n", out);
-    fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
+    fprintf(out, "const struct linux_logo %s = {\n", logoname);
     fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
     fprintf(out, "\t.width\t\t= %d,\n", logo_width);
     fprintf(out, "\t.height\t\t= %d,\n", logo_height);
@@ -381,7 +381,7 @@ static void write_logo_clut224(void)
     fputs("\n};\n\n", out);

     /* write logo clut */
-    fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
+    fprintf(out, "static unsigned char %s_clut[] = {\n",
            logoname);
     write_hex_cnt = 0;
     for (i = 0; i < logo_clutsize; i++) {

这样内核的logo就能正常显示了。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飘忽不定的bug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值