用bootsplash制作Linux全图形启动界面

Linux的各种发行版在启动时基本上都有两种模式:silent mode和verbose mode。verbose模式下会打印极为详尽的启动信息,比如挂载文件系统,加载光驱,激活网络服务等等,而silent模式则屏蔽掉这些信息。bootsplash工具可以将一张图片放在silent模式下的虚拟控制台上,从而使Linux用户看到一个全画面的启动过程。另外一个工具是gensplash,比bootsplash要稍微复杂一些,不过功能更为强大,设计也更为合理——它将一些非必要的元素从kernel space挪出来,放在user space来做。

  网络上关于bootsplash(启动动画)的使用基本上是基于Linux的SuSe发行版进行讨论的——开发这组工具的作者说他们的工作平台是SuSe。gensplash则是基于Linux的Gentoo发行版进行讨论的。当然这些两组工具都可以通过适当的改动应用于Linux的其它发行版。

  由于我的工作平台是red hat linux,此篇文章就讨论怎样在RH linux下使用bootsplash。下面先给出相关的一些网站:

  http://www.bootsplash.org (官方网站,基本使用及相关原理)
  http://www.bootsplash.com  (详尽的使用方法,基于SuSe发行版)
  http://www.bootsplash.de  (bootsplash的爱好者组织的网站,资料齐全)
  http://www.kernel.org (Linux内核下载)

  本文严重参考http://www.linuxhall.org/modules.php?name=News&file=article&sid=201,哈哈,特此说明。

  现在我们进入正题。

  http://www.bootsplash.org网站上说,bootsplash的内核补丁针对2.4.18--2.4.22和2.6.0-test9,这个消息很旧了,可以到http://www.bootsplash.de站点查看bootsplash所提供的各个版本的内核补丁,然后确定你所用的Linux内核版本,选择一个补丁下载。

  我的内核是2.4.20-8,下载补丁bootsplash-3.0.7-2.4.20.vanilla.diff。补丁中的3.0.7是bootsplash工具的版本号,我们下载bootsplash-3.0.7.tar.bz2,再下载所要用的主题Theme-NewLinux.tar.bz2,关于材料的准备就完成了。这些都可以在上面的提及的网站上找到。如果你的内核没有相应补丁,那么可以选择一个版本的内核源代码,打上补丁后,编译一个新的内核。

  如果没有编译过内核,可以到网上查找相关资料,对照着练习一下。当然,我们需要root的权限。

  第一步 修改/usr/include目录下的三个符号链接:asm,scsi,linux(mv asm asm.bak,mv scsi scsi.bak,mv linux linux.bak),如果没有,则要新建。在编译内核时,用到这些链接所指向的一些头文件。我在/usr/src目录下建了一个名为linux的链接指向同一层的内核源代码目录linux-2.4.20-8(这样以后再编译不同版本内核时,只需修改/usr/src目录下的linux符号链接就可以了)。(命令ln -s linux-2.4.20-8 linux),然后进入/usr/include目录,分别执行ln -s /usr/src/linux/include/asm-i386 asm;ln -s /usr/src/linux/include/linux linux;ln -s /usr/src/linux/include/scsi scsi。

  第二步 打补丁,假设补丁在/usr/src/linux目录下(不在的话加上路径即可)。patch -p1<bootsplash-3.0.7-2.4.20.vanilla.diff

  第三步 设定核心:make menuconfig。确定下列选项被编译进内核而不是被编译成模块。

       对于2.4.x内核:

Code maturity level options  ---> 
    [*] Prompt for development and/or incomplete code/drivers 
 Processor type and features  ---> 
    [*] MTRR (Memory Type Range Register) support 
 Block Devices -> 
    [*] Loopback device support 
    [*] RAM disk support 
    (4096)  Default RAM disk size 
    [*] Initial RAM disk (initrd) support 
 Console Drivers -> 
    [*] VGA text console 
    [*] Video mode selection support 
 Console Drivers -> Frame-buffer support -> 
    [*] Support for frame buffer devices 
    [*] VESA VGA graphics console 
    [*] Use splash screen instead of boot logo

    对于2.6.x内核: 
 Code maturity level options  ---> 
    [*] Prompt for development and/or incomplete code/drivers 
 Processor type and features  ---> 
    [*] MTRR (Memory Type Range Register) support 
 Device Drivers  ---> 
    Block devices  ---> 
      <*> Loopback device support 
      <*> RAM disk support 
      (4096) Default RAM disk size 
      [*]  Initial RAM disk (initrd) support 
 Graphics support  ---> 
    [*] Support for frame buffer devices 
    [*]  VESA VGA graphics support 
    Console display driver support  ---> 
      [*]  Video mode selection support 
      <*> Framebuffer Console support 
    Bootsplash configuration  ---> 
      [*] Bootup splash screen 

  第四步  

a>  make mkproper 清除旧的设定
b>  make dep    产生依赖
c>  make bzImage  编译内核
d>  make modules modules_install 编译模块
e>  cp /usr/src/linux/arch/i386/boot/bzImage /boot/bzImage-2.4.20

  第五步 安装bootsplash的工具软件和主题图片

# tar jxvf /patch/bootsplash-3.0.7.tar.bz2
  # tar jxvf /patch/Theme-NewLinux.tar.bz2
  # cd bootsplash-3.0.7/Utilities
  # make all
  # cp fbmngplay fbresolution fbtruetype splash /sbin
  # cd ../../

  下面这几步必须要做,不然在用splash命令时就会出现类似下面的错误:splash:/etc/bootsplash/themes/Linux/images/silent-800x600.jpg不存在。这个其实是由于主题的配置文件中做了绝对路径设定。

# mkdir /etc/bootsplash
  # mkdir /etc/bootsplash/themes
  # cp -a NewLinux /etc/bootsplash/themes/

  我们来看一个完整的主题配置文件,以800x600分辨率为例,文件名为bootsplash-800x600.cfg,可以用vi进行编辑,####开头的为笔者加的注释。

[/code:1:7b9eb010fc]
[code:1:7b9eb010fc]
# This is the configuration file for the 800x600 bootsplash picture.
#
# This file is necessary to specify the coordinates of the text box on
# the splash screen.
#
# Comments are welcome by oliver@dediziert.org

# config file version
version=3

# should the picture be displayed?
state=1

# fgcolor is the text forground color.
# bgcolor is the text background (i.e. transparent) color.
fgcolor=7 
bgcolor=0

# (tx, ty) are the (x, y) coordinates of the text window in pixels.
# tw/th is the width/height of the text window in pixels.
tx=0
ty=0
tw=800
th=600

####predefine area for the text info
text_x=260
text_y=545
text_size=20
text_color=0xeef4ff
####

# name of the picture file (full path recommended)
jpeg=/etc/bootsplash/themes/NewLinux/images/bootsplash-800x600.jpg
silentjpeg=/etc/bootsplash/themes/NewLinux/images/silent-800x600.jpg

progress_enable=1

# background
box silent noover 160 520 642 538 #00000050
box silent inter 160 520 160 537 #b77200 #b77200 #f2b700 #f2b700
box silent  160 520 642 538 #b77200 #b77200 #f2b700 #f2b700

# black border
box silent  160 520 642 520 #b5b5b5
box silent  160 538 642 538 #b5b5b5
box silent  160 520 160 538 #b5b5b5
box silent  642 520 642 538 #b5b5b5

overpaintok=1
[/code:1:7b9eb010fc]

  我们可以修改这个文件中的一些选项来得到自己想要的效果。具体选项的含义可以查看:

http://www.bootsplash.org/config.html
# name of the picture file (full path recommended)
jpeg=/etc/bootsplash/themes/NewLinux/images/bootsplash-800x600.jpg
silentjpeg=/etc/bootsplash/themes/NewLinux/images/silent-800x600.jpg

  这两行指定了作为启动动画的图片和控制台背景的图片的名字和绝对路径,我们只需把自己制作的图片命名为这里指定的图片,并且放在这个路径下,就可以应用自己的主题了。(想想看,制作themes是相当简单的。不明白为什么网上没有redhat linux的主题图片。)

  我修改了/etc/bootsplash/themes/NewLinux/config/bootsplash-800x600.cfg文件,定义显示文本信息区域。###部分是我添加的内容。

[code:1:7b9eb010fc]

第六步  将图片与 init Ram Disk 绑定 splash -s -f /etc/bootsplash/themes/Linux/config/bootsplash-800x600.cfg > /boot/initrd-splash.img 对于ide硬盘,我们可以直接用splash工具生成initrd*.img文件,这个文件对ide硬盘来说没什么用,我们在这里只是通过它来使用启动画面。

  如果你只想看到一副静态的画面,跳过第七步,看第八步,不用修改脚本文件。

  第七步>  将脚本splash.sh拷入/etc/rc.d/下,并修改splash.sh和rc,建议在修改rc脚本文件前进行备份(cp rc rc.bak)
# cp bootsplash-3.0.7/Scripts/splash.sh/etc/rc.d

  下面来看完整的splash.sh脚本文件,要想这个脚本起作用,必须修改rc脚本,通过rc脚本调用splash.sh脚本,需要赋予splash.sh脚本可执行权限。需要一些shell script的知识。网上很多,google吧。

   我现在的/etc/rc.d/splash.sh脚本,删除了原来放在这个脚本中的绘制进度条部分(调试不成功)和播放动画部分(还没有实验),以及不适用于red hat linux的一些命令。这个脚本现在只打印类似“booting the system"和"shutting down the system"的信息和实现关机时的silent mode。

#!/bin/bash
#
# splash.sh - This shell script triggers bootsplash actions during
# system boot/shutdown. It can be run by the init scripts repeatedly
# specifying the currently executed system script.
#
#rewrite this script at the base of offered by http://www.bootsplash.org
#line with ### added by me

_procsplash="`cat /proc/splash 2>/dev/null`"

###give the variable "THEME" the name of the directory which the current
###silent mode picture stored
THEME="NewLinux"

test ! -d "/etc/bootsplash/themes/$THEME" && exit 0

# assertions
test -r /proc/splash || exit 0
test -z "`echo $_procsplash|grep on`" && exit 0

####"Yast" is a utilies for SuSE Linux,no for RedHat Linux
####maybe we can erase it 
test "$1" == "bootnetwork stop" -o "$1" == "YaST" && exit 0 # no progress

# We chose verbose in grub
test "`cat /proc/cmdline |grep \"splash=silent\"`" == "" && exit 0 

if [ "$PREVLEVEL" == "3" -o "$PREVLEVEL" == "5" ]; then
###no below ,no silent mode when shutting down
 if [ "$RUNLEVEL"  = "3" -o "$RUNLEVEL" == "5" ]; then
  exit 0
 fi
### but why ? 
fi

# acquire data

_shutdown="no"
_silent="no"
test "`cat /proc/splash |grep silent`" && _silent="yes"
test "$RUNLEVEL" == "6" -o "$RUNLEVEL" == "0" && _shutdown="yes"

test -f "/etc/bootsplash/themes/$THEME/config/bootsplash-`fbresolution`.cfg" && \
 . /etc/bootsplash/themes/$THEME/config/bootsplash-`fbresolution`.cfg

#
# Print text string. (Booting/Shutting down the system. Press
# F2 for verbose mode)
#
###switch to slient mode when shutdown or reboot the system
 test "$_shutdown" == "yes" && ( echo "silent" >/proc/splash; chvt 1)

###print infomation at the area predifined by config file "bootsplash-800x600.cfg"
 _boot="Booting"; test "$_shutdown" == "yes" && _boot="Shutting down"

###is the area for infomation defined? yes ,print info, no,run on 
 if [ "$text_x" != "" -a "$text_y" != "" \
    -a "$text_color" != "" -a "$text_size" != "" -a "$_silent" == "yes" ]; 
 then
  fbtruetype -x $text_x -y $text_y -t $text_color -s $text_size \
   "$_boot the system ..."
 fi

[/code:1:7b9eb010fc]

  下面来看rc脚本(此为系统脚本,决定runlevel和kill or start services,修改前要备份一下,到时要改回来只要覆盖一下就好了cp rc.bak rc)。下面是我现在的/etc/rc.d/rc脚本,定义一个函数,for循环中调用它,以绘制启动进度。重新写了几行代码,绘制进度条。以运行级下的服务总个数和已经启动的服务个数之比作为progress bar的进度,这样进度条显得均匀了一些。

  现在这个可以实现以下功能,开机silent模式,有开始画面,有进度条,进度条下有booting system 提示。关机时切换到silent模式,有画面。提示shutting down the system.

不过在开机的时候,有一半时间进度条是空的(系统在加载内核,检测硬件),在关机的时候,进度条一下子就满了,然后又变空,直到关机。呵呵,回头再改,告一段落了先。

[code:1:7b9eb010fc]
#! /bin/bash
#
# rc        This file is responsible for starting/stopping
#          services when the runlevel changes.
#
# Original Author:     
#          Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
#

# check a file to be a correct runlevel script

###########################Bootsplash start##############
####function progressbar
function progressbar ()
{
_progress=$1
_num=$num
echo show "$(( 65534*($_progress + 1)/$_num ))">/proc/splash 2>/dev/null
}
####end fuction
##########################Bootsplash End###############
check_runlevel ()
{
# Check if the file exists at all.
[ -x "$1" ] || return 1

# Reject backup files and files generated by rpm.
case "$1" in
 *.rpmsave|*.rpmorig|*.rpmnew|*~|*.orig)
  return 1
 ;;
esac
return 0
}

# Now find out what the current and what the previous runlevel are.
argv1="$1"
set `/sbin/runlevel`
runlevel=$2
previous=$1
export runlevel previous

. /etc/init.d/functions

# See if we want to be in user confirmation mode
if [ "$previous" = "N" ]; then
if [ -f /var/run/confirm ] \
  || grep -i confirm /proc/cmdline >/dev/null; then
 rm -f /var/run/confirm
 CONFIRM=yes
 export CONFIRM
 echo $"Entering interactive startup"
else
 echo $"Entering non-interactive startup"
fi
fi

# Get first argument. Set new runlevel to this argument.
[ -n "$argv1" ] && runlevel="$argv1"

####################Bootsplash start###############
progress=0
num=0
###count the services for progressbar
for countservices in /etc/rc$runlevel.d/*;do
num=$(( $num + 1 ))
done
###################Bootsplash End##################

# Is there an rc directory for this new runlevel?
[ -d /etc/rc$runlevel.d ] || exit 0

# First, run the KILL scripts.
for i in /etc/rc$runlevel.d/K*; do
###################Bootsplash start#################
progress=$(( $progress + 1 ))
/etc/rc.d/splash.sh 2>/dev/null
progressbar $progress
##################Bootsplash End####################
check_runlevel "$i" || continue

# Check if the subsystem is already up.
subsys=${i#/etc/rc$runlevel.d/K??}
[ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] \
 || continue

# Bring the subsystem down.
if egrep -q "(killproc |action )" $i; then
 $i stop
else
 action $"Stopping $subsys: " $i stop
fi
done

# Now run the START scripts.
for i in /etc/rc$runlevel.d/S*; do
###################Bootsplash start#################
progress=$(( $progress + 1 ))
/etc/rc.d/splash.sh 2>/dev/null
progressbar $progress
##################Bootsplash End####################
check_runlevel "$i" || continue

# Check if the subsystem is already up.
subsys=${i#/etc/rc$runlevel.d/S??}
[ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] \
 && continue
    
# If we’re in confirmation mode, get user confirmation
if [ -n "$CONFIRM" ]; then
 confirm $subsys
 case $? in
  0) :;;
  2) CONFIRM=;;
  *) continue;;
 esac 
fi

# Bring the subsystem up.
if [ "$subsys" = "halt" -o "$subsys" = "reboot" ]; then
 export LC_ALL=C
 exec $i start
fi
if egrep -q "(daemon |action |success |failure )" $i 2>/dev/null \
  || [ "$subsys" = "single" -o "$subsys" = "local" ]; then
 $i start
else
 action $"Starting $subsys: " $i start
fi
done
[/code:1:7b9eb010fc]
[code:1:7b9eb010fc]

  第八步 修改(bootloader)  grub(或者lilo)。我用的是grub,硬盘是ide的。只列出需要修改的部分。我的硬盘分区swap,boot,/。

title Red Hat Linux (2.4.20+bootsplash)
 root (hd0,0)
 kernel /bzImage-2.4.20 ro root=/dev/hda3 vga=788 splash=silent  
 initrd /initrd-splash.img
title Red Hat Linux (2.4.23)
 root (hd0,0)
 kernel /vmlinuz-2.4.20-8 ro root=LABEL=/  
 initrd /initrd-2.4.20-8.img

  788为800x600模式,791为1024x768模式。这里的模式选择要与图片的大小一致。

  到这里就可以重新启动了。呵呵,大功告成。赶紧实验一下,享受自己的全画面Linux启动吧。