之前在分析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函数分析:

 const struct linux_logo * __init_refok fb_find_logo(int depth)
{
const struct linux_logo *logo = NULL; /* 定义一个linux_logo结构体指针变量 */ if (nologo)
return NULL; if (depth >= ) { /* 如果depth >= 1 选择下面的logo文件 */
#ifdef CONFIG_LOGO_LINUX_MONO
/* Generic Linux logo */
logo = &logo_linux_mono;
#endif
#ifdef CONFIG_LOGO_SUPERH_MONO
/* SuperH Linux logo */
logo = &logo_superh_mono;
#endif
} if (depth >= ) { /* 如果depth >= 4 选择下面的logo文件 */
#ifdef CONFIG_LOGO_LINUX_VGA16
/* Generic Linux logo */
logo = &logo_linux_vga16;
#endif
#ifdef CONFIG_LOGO_BLACKFIN_VGA16
/* Blackfin processor logo */
logo = &logo_blackfin_vga16;
#endif
#ifdef CONFIG_LOGO_SUPERH_VGA16
/* SuperH Linux logo */
logo = &logo_superh_vga16;
#endif
} if (depth >= ) { /* 如果depth >= 8 选择下面的logo文件 */
#ifdef CONFIG_LOGO_LINUX_CLUT224
/* Generic Linux logo */
logo = &logo_linux_clut224;
#endif
#ifdef CONFIG_LOGO_LINUX_FULL_CLUT224
/* Full screen Linux logo */
logo = &logo_linux_full_clut224;
#endif
// lqm added
#ifdef CONFIG_LOGO_X210_CLUT224
/* x210 android logo */
logo = &logo_x210_clut224;
#endif
// end added.
#ifdef CONFIG_LOGO_BLACKFIN_CLUT224
/* Blackfin Linux logo */
logo = &logo_blackfin_clut224;
#endif
#ifdef CONFIG_LOGO_DEC_CLUT224
/* DEC Linux logo on MIPS/MIPS64 or ALPHA */
logo = &logo_dec_clut224;
#endif
#ifdef CONFIG_LOGO_MAC_CLUT224
/* Macintosh Linux logo on m68k */
if (MACH_IS_MAC)
logo = &logo_mac_clut224;
#endif
#ifdef CONFIG_LOGO_PARISC_CLUT224
/* PA-RISC Linux logo */
logo = &logo_parisc_clut224;
#endif
#ifdef CONFIG_LOGO_SGI_CLUT224
/* SGI Linux logo on MIPS/MIPS64 and VISWS */
logo = &logo_sgi_clut224;
#endif
#ifdef CONFIG_LOGO_SUN_CLUT224
/* Sun Linux logo */
logo = &logo_sun_clut224;
#endif
#ifdef CONFIG_LOGO_SUPERH_CLUT224
/* SuperH Linux logo */
logo = &logo_superh_clut224;
#endif
#ifdef CONFIG_LOGO_M32R_CLUT224
/* M32R Linux logo */
logo = &logo_m32r_clut224;
#endif
}
return logo;
}
//   include\linux\linux_logo.h  

 1 extern const struct linux_logo logo_linux_mono;
extern const struct linux_logo logo_linux_vga16;
extern const struct linux_logo logo_linux_clut224;
extern const struct linux_logo logo_linux_full_clut224;
extern const struct linux_logo logo_blackfin_vga16;
extern const struct linux_logo logo_blackfin_clut224;
extern const struct linux_logo logo_dec_clut224;
extern const struct linux_logo logo_mac_clut224;
extern const struct linux_logo logo_parisc_clut224;
extern const struct linux_logo logo_sgi_clut224;
extern const struct linux_logo logo_sun_clut224;
extern const struct linux_logo logo_superh_mono;
extern const struct linux_logo logo_superh_vga16;
extern const struct linux_logo logo_superh_clut224;
extern const struct linux_logo logo_m32r_clut224;
extern const struct linux_logo logo_spe_clut224;
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函数分析:

 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; /* 定义一个fb_image类型的结构体变量,这个结构体就是用来描述在LCD上显示的logo的信息 */ /* Return if the frame buffer is not mapped or suspended */
if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
info->flags & FBINFO_MODULE)
return ; image.depth = ;
image.data = logo->data; if (fb_logo.needs_cmapreset)
fb_set_logocmap(info, logo); if (fb_logo.needs_truepalette ||
fb_logo.needs_directpalette) {
palette = kmalloc( * , GFP_KERNEL);
if (palette == NULL)
return ; if (fb_logo.needs_truepalette)
fb_set_logo_truepalette(info, logo, palette);
else
fb_set_logo_directpalette(info, logo, palette); saved_pseudo_palette = info->pseudo_palette;
info->pseudo_palette = palette;
} if (fb_logo.depth <= ) {
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 ;
}
image.data = logo_new;
fb_set_logo(info, logo, logo_new, fb_logo.depth);
} image.dx = ; /* 在LCD上显示的logo图标的起始水平位置(以像素为单位) */
image.dy = y; /* 在LCD上显示的logo图标的起始垂直位置(以像素为单位) */
image.width = logo->width; /* 在LCD上显示的logo图标的宽度(以像素为单位) */
image.height = logo->height; /* 在LCD上显示的logo图标的高度(以像素为单位) */ if (rotate) {
logo_rotate = kmalloc(logo->width *
logo->height, GFP_KERNEL);
if (logo_rotate)
fb_rotate_logo(info, logo_rotate, &image, rotate);
} 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;
}

函数中有这么一段:

就是用来控制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文件的信息) 结构体变量传进来,

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

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

Linux内核启动logo的更多相关文章

  1. 修改linux内核启动logo及显示位置

    转载于:http://blog.chinaunix.net/uid-28458801-id-3484269.html 在此基础上我又添加了我的一些不同的地方,仅供参考 内核版本: 2.6.35.3 l ...

  2. 【转载】linux内核启动android文件系统过程分析

    主要介绍linux 内核启动过程以及挂载android 根文件系统的过程,以及介绍android 源代码中文件系统部分的浅析. 主要源代码目录介绍Makefile (全局的Makefile)bioni ...

  3. Linux内核启动过程概述

    版权声明:本文原创,转载需声明作者ID和原文链接地址. Hi!大家好,我是CrazyCatJack.今天给大家带来的是Linux内核启动过程概述.希望能够帮助大家更好的理解Linux内核的启动,并且创 ...

  4. linux内核启动以及文件系统的加载过程

    Linux 内核启动及文件系统加载过程 当u-boot 开始执行 bootcmd 命令,就进入 Linux 内核启动阶段.普通 Linux 内核的启动过程也可以分为两个阶段.本文以项目中使用的 lin ...

  5. Linux内核启动

    Linux内核启动过程概述 Linux的启动代码真的挺大,从汇编到C,从Makefile到LDS文件,需要理解的东西很多.毕竟Linux内核是由很多人,花费了巨大的时间和精力写出来的.而且直到现在,这 ...

  6. 通过从代码层面分析Linux内核启动来探知操作系统的启动过程

    通过从代码层面分析Linux内核启动来探知操作系统的启动过程 前言说明 本篇为网易云课堂Linux内核分析课程的第三周作业,我将围绕Linux 3.18的内核中的start_kernel到init进程 ...

  7. linux内核启动参数

    Linux内核启动参数   Console Options                         参数 说明 选项 内核配置/文件   console=Options 用于说明输出设备 tt ...

  8. Linux内核启动代码分析二之开发板相关驱动程序加载分析

    Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c  start_ke ...

  9. Linux内核启动及根文件系统载入过程

    上接博文<u-boot之u-boot-2009.11启动过程分析> Linux内核启动及文件系统载入过程 当u-boot開始运行bootcmd命令,就进入Linux内核启动阶段.与u-bo ...

随机推荐

  1. ubuntu 调整桌面图标大小

    打开文件浏览器,例如从“位置” 里打开 “主文件夹”,点 “编辑” –>“首选项”,把 “图标视图默认值” 下的“默认缩放级别” 改为 75%.现在图标大小跟WinXP 下的差不多. 或者 在 ...

  2. Java配置环境变量

    首先,你应该已经安装了Java 的 JDK 了,笔者安装的是:jdk-7u7-windows-x64 接下来主要讲怎么配置 Java 的环境变量 1.进入“计算机”的“属性”选项后如图 2.选择“高级 ...

  3. Opencv创建有滚动条的视频

    #include "stdafx.h"#include "cv.h"#include "cxcore.h"#include "hi ...

  4. 【学习笔记】Oracle-1.安装及配置

    Win7旗舰版安装Oracle_11gR1_database:  http://my.oschina.net/laiwanshan/blog/89951 Oracle用户登陆 sqlplus sys/ ...

  5. sql语句与数据库2

    增加数据 insert into wyx(xh,nl,xb,sfzh,zcrq)values(0422,28,男,210623198711111111,2016-8-19); 删除数据 delete ...

  6. wordpress(二)wordpress环境迁移

    迁移wordpress到服务器 本地环境如下 win8.1 appser 服务器环境如下 centos7 lnmp 1.使用phpmyadmin备份本地wordpress站点的数据库 2.备份本地wo ...

  7. RobotFramwork + Appium+ Andriod 环境搭建

    RF+Appium+Android环境搭建教程 - 1.RF安装 一.适用操作系统 Win7 旗舰版Sp1 32位操作系统 RF环境搭建,请参考文档<RobotFramwork安装指南> ...

  8. 2016HUAS_ACM暑假集训2D - 敌兵布阵

    刚开始接触线段树,不得不说,每次接触到一个新的数据结构,都会是一场头脑风暴的“盛宴”.希望我能继续痛苦并快乐着学下去.我相信,有各路大神的博客相助,我还是能坚持下去的. 这个题目是HDU的1166,只 ...

  9. centos-系统语言检查设置安装

    查看当前系统语言 登陆linux系统打开操作终端之后,输入 echo $LANG可以查看当前使用的系统语言. 查看安装的语言包 查看是否有中文语言包可以在终端输入 locale命令,如有zh cn 表 ...

  10. Jquery数组操作

    jQuery的数组处理,便捷,功能齐全. 最近的项目中用到的比较多,深感实用,一步到位的封装了很多原生js数组不能企及的功能. 最近时间紧迫,今天抽了些时间回过头来看 jQuery中文文档 中对数组的 ...