1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > linux显示启动logo源码分析以及修改显示logo

linux显示启动logo源码分析以及修改显示logo

时间:2023-01-14 07:04:20

相关推荐

linux显示启动logo源码分析以及修改显示logo

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_MONO1/* monochrome black/white */#define LINUX_LOGO_VGA162/* 16 colors VGA text palette */#define LINUX_LOGO_CLUT2243/* 224 colors */#define LINUX_LOGO_GRAY2564/* 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;}

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.oobj-$(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 builtlogo-cfiles = $(notdir $(patsubst %.$(2), %.c, \$(wildcard $(srctree)/$(src)/*$(1).$(2))))# Mono logosextra-y += $(call logo-cfiles,_mono,pbm)# VGA16 logosextra-y += $(call logo-cfiles,_vga16,ppm)# 224 Logosextra-y += $(call logo-cfiles,_clut224,ppm)# Gray 256extra-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 cleanclean-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显示的起始坐标;

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。