1、linux显示启动logo整个流程分析

(1)logo图片在内核源码中是以ppm格式的文件保存,在编译内核时会把ppm格式的文件自动转换成.c文件,在c文件中会构造一个struct linux_logo结构体变量,
变量名字就是文件的名字,struct linux_logo结构体在内核中用来表示一副logo图像信息;
(2)内核在初始化显示器后,会按照配置去匹配合适的struct linux_logo结构体,也就是查找logo图片;
(3)将logo图像显示到默认屏幕上;

2、linux显示启动logo源码分析

2.1、全局变量fb_logo

(1)显示启动logo的代码在fbmem.c中实现,使用struct logo_data结构体来描述启动logo相关的信息;
(2)成员logo表示启动logo图像的具体信息,其他的变量和图像的格式和图像深度有关系;

2.2、struct linux_logo结构体

#define LINUX_LOGO_MONO      1   /* monochrome black/white */
#define LINUX_LOGO_VGA16    2   /* 16 colors VGA text palette */
#define LINUX_LOGO_CLUT224  3   /* 224 colors */
#define LINUX_LOGO_GRAY256  4   /* 256 levels grayscale */

(1)struct linux_logo结构体就是内核中用来描述logo图片的,这个结构体不用我们去构造,是有ppm文件转换成c文件时自动生成;
(2)logo图像有4中格式,其中LINUX_LOGO_CLUT224应用最为广泛,所占空间也最小。LINUX_LOGO_CLUT224类型的图像颜色种类不会超过224中,颜色的具体信息保存在clut成员表示的颜色对照表中,成员data
指向由颜色对照表索引构成的图像数据。
(3)LINUX_LOGO_CLUT224类型的图像空间计算,比如:对于长宽分别是150和100的 Logo,如果bpp为24 使用颜色对照表方式存储这幅Logo最多需要( 150×100+224 × 3)=15672字节,而如果直接
存储 Logo的所有像素信息,就需要(150×100×3)=45000字节。
(4)通常情况下,内核对于bpp大于等于8的情况,会使用颜色对照表的方式存放Logo ,而bpp小于8时,使用颜色对照表反而可能占用更多空间,因此直接将像素信息存放在成员data中;

2.3、函数调用关系

s3cfb_probe()    //这是显示器驱动的prob函数fb_prepare_logo()   //查找合适的logofb_get_color_depth() //获取显示器的颜色深度fb_find_logo()  //真正找到合适的logo图像,也就是struct linux_logo结构体fb_prepare_extra_logos()  //设置附加的logo数据,不是必须的fb_set_cmap() //设置显示屏的颜色表fb_show_logo()   //显示logo图像fb_show_logo_line()   //构建struct fb_image结构体fb_do_show_logo() //执行logo显示info->fbops->fb_imageblit() //调用显示驱动的fb_imageblit()方法,这里是实际操作硬件的fb_show_extra_logos()    //显示附加的logo数据,非必须

2.4、fb_prepare_logo()函数

int fb_prepare_logo(struct fb_info *info, int rotate)
{//计算颜色深度int depth = fb_get_color_depth(&info->var, &info->fix);unsigned int yres;memset(&fb_logo, 0, sizeof(struct logo_data));if (info->flags & FBINFO_MISC_TILEBLITTING ||info->flags & FBINFO_MODULE)return 0;if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {depth = info->var.blue.length;if (info->var.red.length < depth)depth = info->var.red.length;if (info->var.green.length < depth)depth = info->var.green.length;}if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {/* assume console colormap */depth = 4;}/* 根据颜色深度返回找到的struct linux_logo结构体 */fb_logo.logo = fb_find_logo(depth);if (!fb_logo.logo) {return 0;}//判断是否旋转if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)yres = info->var.yres;elseyres = info->var.xres;//判断logo图像的高是否超过可视屏幕的高if (fb_logo.logo->height > yres) {fb_logo.logo = NULL;return 0;}/* 根据logo图像类型设置图像深度 */if (fb_logo.logo->type == LINUX_LOGO_CLUT224)fb_logo.depth = 8;else if (fb_logo.logo->type == LINUX_LOGO_VGA16)fb_logo.depth = 4;elsefb_logo.depth = 1;if (fb_logo.depth > 4 && depth > 4) {switch (info->fix.visual) {case FB_VISUAL_TRUECOLOR:fb_logo.needs_truepalette = 1;break;case FB_VISUAL_DIRECTCOLOR:fb_logo.needs_directpalette = 1;fb_logo.needs_cmapreset = 1;break;case FB_VISUAL_PSEUDOCOLOR:fb_logo.needs_cmapreset = 1;break;}}return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
}

(1)调用fb_get_color_depth()函数,根据info->var和info->fix计算图像深度,并返回给局部变量depth;
(2)调用fb_find_logo()函数,根据图像深度何也找到合适的Logo图像数据并返回给fb_logo.logo;
(3)如果找到了合适的图像数据,则根据 Logo 图像数据的类型给fb_logo.depth赋值
(4)如果由fb_logo.depth和depth 都大于 4,则根据 info->fix且sual 的值设置 fb_logo 剩下的成员:若 info->fix且sual 为 FB_VISUAL_TRUECOLOR,则由1__logo 的 needs二刷刷e出成员被设置,若为 FB_VISUAL_TR四COLOR,则 needs_directpalette 和 needs_cmapreset 均被设置,若为 FB_VISUAL_PSEUDOCOLOR,则 needs_cmapreset 被设置;
(5)调用fb_prepare_extra_logos()函数设置附加Logo数据;

2.5、fb_find_logo()函数

const struct linux_logo * __init_refok fb_find_logo(int depth)
{const struct linux_logo *logo = NULL;if (nologo)return NULL;if (depth >= 1) {#ifdef CONFIG_LOGO_LINUX_MONO/* Generic Linux logo */logo = &logo_linux_mono;
#endif}if (depth >= 4) {#ifdef CONFIG_LOGO_LINUX_VGA16/* Generic Linux logo */logo = &logo_linux_vga16;
#endif}if (depth >= 8) {#ifdef CONFIG_LOGO_LINUX_CLUT224/* Generic Linux logo */logo = &logo_linux_clut224;
#endif//X210开发板的logo图像数据
#ifdef CONFIG_LOGO_X210_CLUT224
/* x210 android logo */
logo = &logo_x210_clut224;
#endif}return logo;
}

(1)根据depth去查找合适的logo数据,这里的struct linux_logo结构体是由ppm文件转换成C语言文件得到的;
(2)注意这里的查找有后覆盖性,当查找到合适的struct linux_logo结构体函数不会返回,会把所有的结构体都查找一遍,最后一个
匹配的会被返回;

2.6、fb_show_logo_line()函数

static int fb_show_logo_line(struct fb_info *info, int rotate,const struct linux_logo *logo, int y,unsigned int n)
{u32 *palette = NULL, *saved_pseudo_palette = NULL;unsigned char *logo_new = NULL, *logo_rotate = NULL;struct fb_image image;/* Return if the frame buffer is not mapped or suspended */if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||info->flags & FBINFO_MODULE)return 0;image.depth = 8;image.data = logo->data;   //图像数据//若needs_cmapreset被设置,则根据logo配置颜色表,设置颜色表//最终会调用info->fbops中的fb_setcmap()或fb_setcolreg()方法if (fb_logo.needs_cmapreset)fb_set_logocmap(info, logo);//若needs_truepalette或 needs_directpalette被设置,则根据logo分配并设置调色板if (fb_logo.needs_truepalette ||fb_logo.needs_directpalette) {palette = kmalloc(256 * 4, GFP_KERNEL);if (palette == NULL)return 0;if (fb_logo.needs_truepalette)fb_set_logo_truepalette(info, logo, palette);elsefb_set_logo_directpalette(info, logo, palette);//备份info中原调色板内容,并设置为新的调色板saved_pseudo_palette = info->pseudo_palette;info->pseudo_palette = palette;}//对于depth <=4 的情况,既不使用颜色表,也不使用调色板,//image.data中直接存入像素信息,而不是颜色表或者调色板的索引if (fb_logo.depth <= 4) {logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);if (logo_new == NULL) {kfree(palette);if (saved_pseudo_palette)info->pseudo_palette = saved_pseudo_palette;return 0;}image.data = logo_new;fb_set_logo(info, logo, logo_new, fb_logo.depth);}//logo显示的起始坐标image.dx = 0;image.dy = y;//logo图像的宽高image.width = logo->width;image.height = logo->height;//根据旋转方式调整图像if (rotate) {logo_rotate = kmalloc(logo->width *logo->height, GFP_KERNEL);if (logo_rotate)fb_rotate_logo(info, logo_rotate, &image, rotate);}//执行logo显示fb_do_show_logo(info, &image, rotate, n);kfree(palette);//恢复原调色板内容if (saved_pseudo_palette != NULL)info->pseudo_palette = saved_pseudo_palette;kfree(logo_new);kfree(logo_rotate);return logo->height;
}
传参 注释
info 帧缓冲设备描述结构
rotate 屏幕旋转方式
logo 待显示的 Logo 图像 logo(实际上是 fb_logo.logo)
y logo显示起始坐标的y值
n 系统 CPU 数量

3、制作ppm文件

//安装工具包
sudo apt-get install netpbm//将名字为logo.png的图像,转换成logo_linux_clut224.ppm文件
pngtopnm logo.png | ppmquant -fs 224 | pnmtoplainpnm > logo_linux_clut224.ppm

(1)上面是利用命令pngtopnm & ppmquant & pnmtoplainpnm来将png格式图像转换成ppm格式图像,如果linux中没有相关命令则要先安装命令包;
(2)在上面的命令中,注意图片文件的名字和你实际的对应上,放到内核源码中放ppm格式文件的目录下;

4、ppm文件自动转换成C源文件

obj-$(CONFIG_LOGO)           += logo.o
obj-$(CONFIG_LOGO_LINUX_MONO)       += logo_linux_mono.oobj-$(CONFIG_SPU_BASE)            += logo_spe_clut224.o//添加宏进行控制
obj-$(CONFIG_LOGO_X210_CLUT224)         += logo_x210_clut224.o # Use logo-cfiles to retrieve list of .c files to be built
logo-cfiles = $(notdir $(patsubst %.$(2), %.c, \$(wildcard $(srctree)/$(src)/*$(1).$(2))))# Mono logos
extra-y += $(call logo-cfiles,_mono,pbm)# VGA16 logos
extra-y += $(call logo-cfiles,_vga16,ppm)# 224 Logos
extra-y += $(call logo-cfiles,_clut224,ppm)# Gray 256
extra-y += $(call logo-cfiles,_gray256,pgm)pnmtologo := scripts/pnmtologo# Create commands like "pnmtologo -t mono -n logo_mac_mono -o ..."
quiet_cmd_logo = LOGO    $@cmd_logo = $(pnmtologo) \-t $(patsubst $*_%,%,$(notdir $(basename $<))) \-n $(notdir $(basename $<)) -o $@ $<$(obj)/%_mono.c: $(src)/%_mono.pbm $(pnmtologo) FORCE$(call if_changed,logo)$(obj)/%_vga16.c: $(src)/%_vga16.ppm $(pnmtologo) FORCE$(call if_changed,logo)#将ppm格式转换成c语言文件
$(obj)/%_clut224.c: $(src)/%_clut224.ppm $(pnmtologo) FORCE$(call if_changed,logo)$(obj)/%_gray256.c: $(src)/%_gray256.pgm $(pnmtologo) FORCE$(call if_changed,logo)# Files generated that shall be removed upon make clean
clean-files := *.o *_mono.c *_vga16.c *_clut224.c *_gray256.c

(1)上面是内核中放ppm格式文件目录的Makefile,在匹配规则中,有将各种pbm、ppm等格式的图像转换成C语言文件的规则;
(2)规则的匹配是根据文件的后缀名来匹配,所以我们要注意对ppm文件的名字命名要以"_clut224"结尾;
(3)通过宏控制要编译哪些ppm格式的文件;

5、转换得到的logo_linux_clut224.c文件


static unsigned char logo_x210_clut224_data[] __initdata = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,······
}static unsigned char logo_x210_clut224_clut[] __initdata = {0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x19, 0x09, 0x18, 0x36, 0x14,······
}const struct linux_logo logo_x210_clut224 __initconst = {.type        = LINUX_LOGO_CLUT224,      //图像类型.width        = 800,                     //宽.height      = 480,                     //高.clutsize    = 102,                     //颜色对照表大小.clut      = logo_x210_clut224_clut,  //颜色对照表.data        = logo_x210_clut224_data   //Logo 图像数据
};

(1)主要就是构建一个struct linux_logo结构体,这是内核用来描述logo图像信息的结构体;
(2)注意这个结构体的名字是和文件名一致的;

6、ppm文件如何与内核源码关联

(1)ppm格式转换成c语言文件,是根据文件的后缀名去Makefile中进行规则的匹配,自动完成编译;
(2)C语言文件中主体就是struct linux_logo结构体,名字和c文件的名字一致;
(3)在内核源码中就是匹配转换得到的struct linux_logo结构体;

7、替换内核启动logo图像

(1)制作ppm格式的文件,注意文件名字的后缀要符合Makefile的匹配规则,并且图像大小不能超过显示屏的分辨率;
(2)修改ppm文件同级的Makefile文件,按照其他的ppm文件的添加方式,通过宏进行控制;
(3)在内核源码的fb_find_logo()函数中,添加新生成的struct linux_logo结构体变量;

8、修改启动logo图像显示位置

修改fb_show_logo_line()函数中logo显示的起始坐标;

linux显示启动logo源码分析以及修改显示logo相关推荐

  1. 【Android 插件化】VirtualApp 源码分析 ( 启动应用源码分析 | HomePresenterImpl 启动应用方法 | VirtualCore 启动插件应用最终方法 )

    文章目录 一.启动应用源码分析 1.HomeActivity 启动应用点击方法 2.HomePresenterImpl 启动应用方法 3.VirtualCore 启动插件应用最终方法 一.启动应用源码 ...

  2. Spring Boot 2.x 启动全过程源码分析(全)

    上篇<Spring Boot 2.x 启动全过程源码分析(一)入口类剖析>我们分析了 Spring Boot 入口类 SpringApplication 的源码,并知道了其构造原理,这篇我 ...

  3. Spring Boot 2.x 启动全过程源码分析(上)入口类剖析

    转载自   Spring Boot 2.x 启动全过程源码分析(上)入口类剖析 Spring Boot 的应用教程我们已经分享过很多了,今天来通过源码来分析下它的启动过程,探究下 Spring Boo ...

  4. storm启动supervisor源码分析-supervisor.clj

    storm启动supervisor源码分析-supervisor.clj supervisor是storm集群重要组成部分,supervisor主要负责管理各个"工作节点".sup ...

  5. storm启动nimbus源码分析-nimbus.clj

    storm启动nimbus源码分析-nimbus.clj nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus ...

  6. 3supervisor启动worker源码分析-worker.clj

    supervisor启动worker源码分析-worker.clj supervisor通过调用sync-processes函数来启动worker,关于sync-processes函数的详细分析请参见 ...

  7. supervisor启动worker源码分析-worker.clj

    supervisor通过调用sync-processes函数来启动worker,关于sync-processes函数的详细分析请参见"storm启动supervisor源码分析-superv ...

  8. Linux brk(),mmap()系统调用源码分析3:brk()的内存申请流程

    Linux brk(),mmap()系统调用源码分析 brk()的内存申请流程 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.com/Rt ...

  9. Linux系统编程 / triggerhappy 源码分析(3.select 的应用)

    哈喽,我是老吴,继续记录我的学习心得. 一.进步的滞后性 我们期望进步是线性: 每一个人付出一些努力后,都希望它有立竿见影的效果. 现实是: 做出努力后,结果的显现往往滞后. 只有在几个月或几年后,我 ...

最新文章

  1. JDK12的五大重要新特性
  2. 最大似然估计与损失函数
  3. java算法:冒泡排序
  4. cmd执行python 环境变量应该怎么写_python怎么运行py文件?.py文件cmd命令方法及环境变量配置教程...
  5. 【JavaWeb】数据库基础复习
  6. 《C++面向对象高效编程(第2版)》——3.16 从函数中返回引用
  7. 大话RAC介质恢复---联机日志损坏
  8. lg linux电视安装软件,LG电视如何安装第三方应用软件的方法教程
  9. 明解c语言练习答案,《明解C语言》练习题4-2的实现
  10. 苹果系统安装Java开发环境JDK
  11. 高通平台音频软件架构
  12. 某音漂亮小姐姐视频合集一键下载,想看就看!
  13. 最近把beecloud,芝麻信用,智能门锁接入了系统。闲下来把遇到的一些坑排下,也能给后人一些指导
  14. php拼多多api接口,api.php
  15. ACM-ICPC 2018 沈阳赛区网络预赛 G. Spare Tire
  16. 【Unity】碰撞后缩小比例并与碰撞目标紧贴(吸附效果)
  17. 湾区潮涌·香港向前 | 香港科大副校长汪扬:用好一国两制制度优势,香港要成数字经济接轨世界桥梁...
  18. 【工具推荐】图形化Git客户端Sourcetree推荐
  19. 视屏剪辑学习笔记(3)
  20. 环境规划与管理名词解释

热门文章

  1. 还在付费使用 XShell?我选择这款超牛逼的 SSH 客户端,完全免费
  2. java 读取shp
  3. 基于 python 的接口自动化测试,让你轻松掌握接口自动化
  4. SRIO IP Core license for VC709 ethenet 40/50G subsystem IP core license for VCU118
  5. 计算机书籍(必看推荐)
  6. H1102NL 普思Pulse 网络变压器
  7. 霍尔元件在VCM音圈马达中的应用
  8. C++ 硬件信息 获取主板序列号
  9. 随机生成植物生长及舞动算法
  10. ensp关于MPLS的实验