Linux内核启动logo - 涛少&

deng-tao 2021-08-15 原文


Linux内核启动logo

之前在分析samsung的fb驱动代码的时候,其中有一段代码是处理内核logo显示相关的,今天就内核logo这个话题来聊一聊!

 

一、处理内核logo显示相关的代码在哪?

回到samsung的fb驱动代码中,因为fb的驱动代码是基于platform平台总线编写的,所以我们需要找到platform_driver结构体中的probe函数,如下所示:

 

1、函数执行流程

/***********************************************************************/

s3cfb_probe    //    “drivers\video\samsung\s3cfb.c”      

     fb_prepare_logo    // 准备logo文件,也就是去找到需要显示的logo文件   “drivers\video\fbmem.c”

          fb_find_logo   // 找到logo文件   “drivers\video\logo\logo.c”

     fb_show_logo      // 显示logo   “drivers\video\fbmem.c”

          fb_show_logo_line    // 真正的显示logo的函数   “drivers\video\fbmem.c”

               fb_do_show_logo   //   “drivers\video\fbmem.c”

                    info->fbops->fb_imageblit(info, image)   // 最终操作fb硬件进行显示工作的函数

/***********************************************************************/

从上面可以知道:fb_prepare_logo  和 fb_show_logo 都是定义在 “drivers\video\fbmem.c” 文件中的,而这个文件之前说过,他是属于fb驱动框架源代码的文件,所以可以知道

上面的处理内核启动logo显示的函数是fb驱动框架提供的,也就是说是由fb驱动框架支持的。

 

(1)fb_find_logo函数分析:

 1 const struct linux_logo * __init_refok fb_find_logo(int depth)
 2 {
 3     const struct linux_logo *logo = NULL;  /* 定义一个linux_logo结构体指针变量 */
 4 
 5     if (nologo)
 6         return NULL;
 7 
 8     if (depth >= 1) {    /* 如果depth >= 1 选择下面的logo文件 */ 
 9 #ifdef CONFIG_LOGO_LINUX_MONO
10         /* Generic Linux logo */
11         logo = &logo_linux_mono;
12 #endif
13 #ifdef CONFIG_LOGO_SUPERH_MONO
14         /* SuperH Linux logo */
15         logo = &logo_superh_mono;
16 #endif
17     }
18      
19     if (depth >= 4) {   /* 如果depth >= 4 选择下面的logo文件 */ 
20 #ifdef CONFIG_LOGO_LINUX_VGA16
21         /* Generic Linux logo */
22         logo = &logo_linux_vga16;
23 #endif
24 #ifdef CONFIG_LOGO_BLACKFIN_VGA16
25         /* Blackfin processor logo */
26         logo = &logo_blackfin_vga16;
27 #endif
28 #ifdef CONFIG_LOGO_SUPERH_VGA16
29         /* SuperH Linux logo */
30         logo = &logo_superh_vga16;
31 #endif
32     }
33     
34     if (depth >= 8) {   /* 如果depth >= 8 选择下面的logo文件 */ 
35 #ifdef CONFIG_LOGO_LINUX_CLUT224
36         /* Generic Linux logo */
37         logo = &logo_linux_clut224;
38 #endif
39 #ifdef CONFIG_LOGO_LINUX_FULL_CLUT224
40         /* Full screen Linux logo */
41         logo = &logo_linux_full_clut224;
42 #endif
43 // lqm added
44 #ifdef CONFIG_LOGO_X210_CLUT224
45 /* x210 android logo */
46 logo = &logo_x210_clut224;              
47 #endif
48 // end added.
49 #ifdef CONFIG_LOGO_BLACKFIN_CLUT224
50         /* Blackfin Linux logo */
51         logo = &logo_blackfin_clut224;
52 #endif
53 #ifdef CONFIG_LOGO_DEC_CLUT224
54         /* DEC Linux logo on MIPS/MIPS64 or ALPHA */
55         logo = &logo_dec_clut224;
56 #endif
57 #ifdef CONFIG_LOGO_MAC_CLUT224
58         /* Macintosh Linux logo on m68k */
59         if (MACH_IS_MAC)
60             logo = &logo_mac_clut224;
61 #endif
62 #ifdef CONFIG_LOGO_PARISC_CLUT224
63         /* PA-RISC Linux logo */
64         logo = &logo_parisc_clut224;
65 #endif
66 #ifdef CONFIG_LOGO_SGI_CLUT224
67         /* SGI Linux logo on MIPS/MIPS64 and VISWS */
68         logo = &logo_sgi_clut224;
69 #endif
70 #ifdef CONFIG_LOGO_SUN_CLUT224
71         /* Sun Linux logo */
72         logo = &logo_sun_clut224;
73 #endif
74 #ifdef CONFIG_LOGO_SUPERH_CLUT224
75         /* SuperH Linux logo */
76         logo = &logo_superh_clut224;
77 #endif
78 #ifdef CONFIG_LOGO_M32R_CLUT224
79         /* M32R Linux logo */
80         logo = &logo_m32r_clut224;
81 #endif
82     }
83     return logo;
84 }

 

//   include\linux\linux_logo.h  

1
extern const struct linux_logo logo_linux_mono; 2 extern const struct linux_logo logo_linux_vga16; 3 extern const struct linux_logo logo_linux_clut224; 4 extern const struct linux_logo logo_linux_full_clut224; 5 extern const struct linux_logo logo_blackfin_vga16; 6 extern const struct linux_logo logo_blackfin_clut224; 7 extern const struct linux_logo logo_dec_clut224; 8 extern const struct linux_logo logo_mac_clut224; 9 extern const struct linux_logo logo_parisc_clut224; 10 extern const struct linux_logo logo_sgi_clut224; 11 extern const struct linux_logo logo_sun_clut224; 12 extern const struct linux_logo logo_superh_mono; 13 extern const struct linux_logo logo_superh_vga16; 14 extern const struct linux_logo logo_superh_clut224; 15 extern const struct linux_logo logo_m32r_clut224; 16 extern const struct linux_logo logo_spe_clut224; 17 extern const struct linux_logo logo_x210_clut224;

从函数可以看出,根据色深depth的大小和相应的宏定义来选择我们所需要的logo文件,函数中的linux_logo类型变量是会被重复赋值,只有最后一个赋值的logo才是真正的显示的logo文件。

函数中用到的所有linux_logo类型的变量都是在 “include\linux\linux_logo.h” 文件中进行了申明,每一个变量其实就是对应一个logo文件(注意内核中的提供的logo文件都是ppm格式的

文件,内核中的代码能够识别这种格式并进行显示)。

 

(2)所以我们如果想要自定义一个内核启动显示logo,应该怎么做?

   1):首先我们应该先提供一个ppm格式的logo文件(例如:logo_xxx_clut224.ppm)

   2):将logo文件放在内核源码树 drivers\video\logo 目录下

   3):在 include\linux\linux_logo.h 文件中申明logo文件变量 (extern const struct linux_logo logo_xxx_clut224)

   4):在 drivers\video\logo\logo.c 文件中的 fb_find_logo 添加如下

         #ifdef CONFIG_LOGO_XXX_CLUT224

         logo = &logo_xxx_clut224;

         #endif

     5):修改 drivers\video\logo 目录下的Makefile 和 Kconfig,能够实现通过make menuconfig进行动态配置

 

(3)struct  linux_logo结构体

 

(4)fb_show_logo_line函数分析:

 1 static int fb_show_logo_line(struct fb_info *info, int rotate,
 2                  const struct linux_logo *logo, int y,
 3                  unsigned int n)
 4 {
 5     u32 *palette = NULL, *saved_pseudo_palette = NULL;
 6     unsigned char *logo_new = NULL, *logo_rotate = NULL;
 7     struct fb_image image;                    /* 定义一个fb_image类型的结构体变量,这个结构体就是用来描述在LCD上显示的logo的信息 */
 8 
 9     /* Return if the frame buffer is not mapped or suspended */
10     if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
11         info->flags & FBINFO_MODULE)
12         return 0;
13 
14     image.depth = 8;
15     image.data = logo->data;
16 
17     if (fb_logo.needs_cmapreset)
18         fb_set_logocmap(info, logo);
19 
20     if (fb_logo.needs_truepalette ||
21         fb_logo.needs_directpalette) {
22         palette = kmalloc(256 * 4, GFP_KERNEL);
23         if (palette == NULL)
24             return 0;
25 
26         if (fb_logo.needs_truepalette)
27             fb_set_logo_truepalette(info, logo, palette);
28         else
29             fb_set_logo_directpalette(info, logo, palette);
30 
31         saved_pseudo_palette = info->pseudo_palette;
32         info->pseudo_palette = palette;
33     }
34 
35     if (fb_logo.depth <= 4) {
36         logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
37         if (logo_new == NULL) {
38             kfree(palette);
39             if (saved_pseudo_palette)
40                 info->pseudo_palette = saved_pseudo_palette;
41             return 0;
42         }
43         image.data = logo_new;
44         fb_set_logo(info, logo, logo_new, fb_logo.depth);
45     }
46 
47     image.dx = 0;                /* 在LCD上显示的logo图标的起始水平位置(以像素为单位) */ 
48     image.dy = y;                /* 在LCD上显示的logo图标的起始垂直位置(以像素为单位) */
49     image.width = logo->width;   /* 在LCD上显示的logo图标的宽度(以像素为单位) */
50     image.height = logo->height; /* 在LCD上显示的logo图标的高度(以像素为单位) */
51 
52     if (rotate) {
53         logo_rotate = kmalloc(logo->width *
54                       logo->height, GFP_KERNEL);
55         if (logo_rotate)
56             fb_rotate_logo(info, logo_rotate, &image, rotate);
57     }
58 
59     fb_do_show_logo(info, &image, rotate, n);   
60 
61     kfree(palette);
62     if (saved_pseudo_palette != NULL)
63         info->pseudo_palette = saved_pseudo_palette;
64     kfree(logo_new);
65     kfree(logo_rotate);
66     return logo->height;
67 }

 函数中有这么一段:

就是用来控制LCD上显示的logo图标在LCD屏幕上的位置,通过分析上层函数可知,image.dy = 0,所以由此可知,内核启动之后logo默认显示在LCD的左上角

所以如果我们需要修改logo图标的位置和大小,则可以通过修改这4个参数来达到我们的要求。

 

二、修改内核启动logo(自定义logo文件、修改logo图标在LCD上的显示位置)

1、制作ppm格式的logo文件

ppm也是一种图片的格式,但是一般的图片都不是这种格式,所以我们需要将一个logo图片文件转换成ppm格式的文件,所以这里我们需要在Linux中安装这个格式转换工具,

也就是netpbm工具。

sudo apt-get install netpbm    // 可以直接在线安装,首先是你的虚拟机能够上网

工具安装成功之后,我们就可以使用工具制作一个ppm格式的logo文件:

pngtopnm logo.png | ppmquant -fs 224 | pnmtoplainpnm > logo_xxx_clut224.ppm    // logo.png就是我们提供的png格式的logo源文件,logo_xxx_clut224.ppm

                                                                                                                       // 就是最后生成的ppm格式的logo文件

需要注意的是:我们制作好的ppm格式的logo文件的文件名最好是以  _clut224.ppm、_vga16.ppm结尾,因为在这个drivers/video/logo/Makefile 文件中会处理以这些名字

结尾的logo文件,这样可以避免很多的问题。

2、将制作好的ppm格式的logo文件放入内核源码目录 drivers/video/logo 目录下

3、在 include\linux\linux_logo.h 文件中申明:

    extern const struct linux_logo logo_xxx_clut224;    // 我们只需要仿照里面写的代码

4、在 drivers\video\logo\logo.c 文件中的 fb_find_logo 函数中添加一个宏控制编译条件

    #ifdef CONFIG_LOGO_XXX

    logo = &logo_xxx_clut224;
    #endif

5、修改 drivers\video\logo 目录下的Makefile文件和Kconfig文件,使其能够支持在内核进行make menuconfig配置时能够对显示的logo进行配置

    例如在Kconfig中添加:

          config LOGO_XXX_CLUT224

          bool “linux logo !!!”
          default y

    例如在Makefile中添加:

          obj-$(CONFIG_LOGO_XXX_CLUT224)      += logo_xxx_clut224.o 

 

6、如果我们需要修改logo图标的显示位置,则需要修改之前说的那4个参数,默认是显示在LCD的左上角,如果我们需要将logo显示在LCD的中间,可以将参数修改为下面的方式:

image.dx = (info->var.xres – logo->width) / 2;

image.dy = (info->var.yres – logo->height) / 2;

因为调用 fb_show_logo_line 函数的时候会将设备的 fb_info(携带了LCD的硬件信息) 结构体变量 和 Linux_logo(携带了logo文件的信息) 结构体变量传进来,

所以我们是可以在函数中获取的,而不需要将代码写成静态的形式,这样影响移植。

 

至此,本篇文章就已经写完了,,欢迎大家指出错误!!!

 

 

 

 

 

 

                                                                                              

 

 

 

 

 

 

 

发表于
2016-11-19 20:52 
涛少& 
阅读(974
评论(0
编辑 
收藏 
举报

 

版权声明:本文为deng-tao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/deng-tao/p/6081517.html

Linux内核启动logo - 涛少&的更多相关文章

  1. 图解六大UML类图关系 – 屌丝迷途

    图解六大UML类图关系 在学习UML类图的过程中,UML类图关系是必须要掌握的问题,UML定义的关系主要有六种 […]...

  2. Iphone的发送短信-邮件-打电话代码示例 – martin.zhang

    Iphone的发送短信-邮件-打电话代码示例 Map    http://maps.google.com/ma […]...

  3. 个人网站架构设计(三) – 从设计到前端到后台 – Barret李靖

    个人网站架构设计(三) – 从设计到前端到后台 2014-07-04 18:06  Barret李 […]...

  4. Spring Boot 2 快速教程:WebFlux 集成 Mongodb(四)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关 […]...

  5. c++ _beginthread – luckygxf

    c++ _beginthread c++多线程编程 1 #include <windows.h> […]...

  6. [报错:访问终端localhos不允许远程访问]ERROR 1044 (42000): Access denied for user \’root\’@\’localhost\’ – Tanwheey

    [报错:访问终端localhos不允许远程访问]ERROR 1044 (42000): Access deni […]...

  7. 【ColdFusion】中文系统,运行页面竟然出现乱码 – Peter Jin

    【ColdFusion】中文系统,运行页面竟然出现乱码 2010-05-11 11:30  Peter Jin […]...

  8. 互联网时代:程序员如何做一名自由职业者 – WalkersChao

    互联网时代:程序员如何做一名自由职业者 有时站在拥挤的地铁、堵在早高峰的环路上,就会有这样的梦想:要成为一名自 […]...

随机推荐

  1. 我们公司用了6年的通用的权限管理系统设计方案

    一、CAS身份认证 二、基于角色的权限管理模型 三、数据表设计 四、角色及权限点设计 五、身份认证加权限管理实 […]...

  2. JSP调用外部js文件

    在jsp中调用外部js文件分两种情况: 1. 一般来说jsp调用外部js的时候是使用jsp文件的相对路径。   […]...

  3. 熵,条件熵,相对熵,互信息的相关定义及公式推导

    熵,条件熵,相对熵,互信息的相关定义及公式推导 熵是随机变量不确定性的度量,不确定性越大,熵值越大,若随机变量 […]...

  4. 【RecyclerView与Glide】实现一个Android电子书阅读APP

    http://www.cnblogs.com/xfangs/ 欢迎在本文下方评论,小方很需要鼓励支持!!! 本 […]...

  5. form中采用图片作为提交按钮 – 菜鸟Z

    form中采用图片作为提交按钮 <span style="font-size:14px;">< […]...

  6. 用shell处理以下内容 1、按单词出现频率降序排序! 2、按字母出现频率降序排序! the squid project provides a number of resources toassist users design,implement and support squid installations. Please browsethe documentation and support

    此题目有多种解法,sed、awk、tr等等,都可以解决此题,命令运用灵活多变。 编写shell脚本no_20. […]...

  7. Effective Java 第三版——51. 仔细设计方法签名

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java- […]...

  8. 二叉树建树(层序+中序)

    题目描述 给一棵二叉树的层序遍历序列和中序遍历序列,求这棵二叉树的先序遍历序列和后序遍历序列。   输入 每个 […]...

展开目录

目录导航