HomeHome ArchiveArchive

A graphical boot from BIOS to your Application

Intro

This article describes how to configure your Linux system to display an nice graphical image from the BIOS until your application or the login manager appear. No text should appear on the screen during that time.

The web is full with descriptions and tools that cover tiny parts of this process, however there seems to be no document that covers the whole path end to end. This document wants to do this and cover the whole stretch.

Please write to me if you have informations that complement or complete this article. You find my email at the bottom.

Overview

Linux’ boot process consists of multiple parts, that each start the next part

  1. the BIOS boots
  2. the boot loader gets loaded
  3. the kernel starts
  4. init start
  5. the rest of the userspace processes get started
  6. X starts

We now look at each of the points separately.

the BIOS boots

Normally you can not do much about the BIOS displaying its chatter. Some BIOSes support displaying a custom image, however that’s something you’ll need to find out through reading the technical documentation of your mainboard or BIOS.

the boot loader gets loaded

I’ll only cover here GRUB, since it seems to be the dominant boot loader today.

On an average system GRUB takes ony a second or so to load itself and the kernel. Since this is so short a time I am ignoring it and accepting a “black” screen during that second.

This effect can be achieved by setting timeout = 0 in /boot/grub/menu.lst. This will make GRUB skip displaying the boot menu and directly load the default boot entry. If you need to select a different entry then you’ll have to press cursor down in the split second between the BIOS and before GRUB is loaded.

GRUB will still display a line saying that it is loading the kernel (and if your system is configured accordingly also the init filesystem), as described above that line is visible only for a very short time and thus I am ignoring that here:

Uncompressing Linux... Ok, booting the kernel.

However if you want to remove even that, there is a patch from Ubuntu that seems to do that (I have not tested it): quiet.diff

the kernel starts

GRUB loads the kernel and possibly an init filesystem (named initrd or initramfs in Linux speak). It starts the kernel and if configured accordingly on your system, passes the init filesystem on to the kernel.

You can tell the kernel to display an image as soon as it is started. This is usually referred to as “the frambuffer boot logo”. A howto can be found here.

After displaying the boot logo, the linux kernel will usually proceed with verbosely initializing all the hardware. You can suppress all the output by specifying quietin the kernel boot parameters. Just add the word quiet to the kernel boot parameters in /boot/grub/menu.lst. Mine looks like this:

title           Linux 2.6.24.2
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.24.2 root=/dev/hda1 ro vga=791 quiet splash
savedefault

init start

After the kernel has started it will either mount and continue with the boot procedure inside the init filesystem (initrd or initramfs) or it will start the init process.

Both the init filesystem and the init process will immediately start babbling aloud about what they are doing.

What we need to achieve at this stage is:

  1. if that applies to make sure that whatever is started in the init filesystem is shut up
  2. to shut up init
  3. to shut up all that follows the first started processes

I will not go into siliencing the init filesystem, since I am not using any but instead made a custom built kernel, that has all the minimally required drivers compiled into it and thus am not qualified to comprehensively cover the init filesystem part.

The init process itself will dump one line where it will identify itself:

INIT: version 2.68 booting

I don’t know how to prevent init from writing that. Patching it out from the source should be easy, however there should be a better way.

the rest of the userspace processes get started

After init and/or the init filesystem are started, they will usually proceed with mounting all the required filesystems and dispatching udev which will try to identify all hardware, load the required drivers/kernel modules and allocate the according device node in /dev.

This will produce another 3 or so lines. It should be easy to disable displaying those by patching the respective init scripts, however there should be some universal and standard way to do that, which I do not know of.

After that, but as soon as possible you can start a userspace splash manager. I’m using splashy, there are numerous others though.

X start

At some final point your application or the login manager will start as an X client. I am doing that like this:

/etc/init.d/splashy stop
xinit /usr/bin/my_app

however there are numerous other ways to achieve this. The point is that you need to stop the splash screen manger before your target application or the login manager is started.

One final ugly unsolved problem is the unaesthetic start procedure of the X server, which will typically first display the infamous classic “X” as the background. One can use xsetroot to set the background once X is loaded however between the start of X and the execution of xsetroot you’ll still be looking at “X”’s default background. Again, there should be a way to initialize the background before X switches into graphics mode with a nice background, which I have not found yet.

Contributions to this HOWTO are gladly accepted, thanks, Tomas Pospisek, tpo_deb at sourcepole.ch.

Note that http://sourcepole.com is doing develpment of embedded Linux systems and will gladly provide consulting and implementation to solve any of the above mentioned or further problems.

Nginx kills large SVN commits

Lately, when committing large files with Subversion I had problems like this:

\$ svn commit linux-2.6.24.2.tar.gz
Adding (bin) linux-2.6.24.2.tar.gz
Transmitting file data .svn: Commit failed (details follow):
svn: PUT of '/svn/!svn/wrk/38f59907-4ccf-4e05-acf4-444499e715cc/embipc/branches/ipc/linux-image/linux-2.6.24.2.tar.gz': Could not send request body: connection was closed by server. (<https://www.example.org>)
svn: Your commit message was left in a temporary file:
svn: '/some/path/embipc/branches/ipc/linux-image/svn-commit.tmp'

Apache’s Log was very quiet about the problem. All I could see that SVN would be deleting the uploaded file after abort (that’s what I think it was doing):

192.168.0.2 - joe [07/Mar/2008:13:53:59 +0100] "DELETE /svn/!svn/act/38f59907-4ccf-4e05-acf4-444
3b969 HTTP/1.0" 204 - "-" "SVN/1.4.4 (r25188) neon/0.26.4"

The root of the problem is however that we’re having multiple virtual servers on our hardware and are proxying and distributing request to them through nginx. And nginx had a default setting for maximal file upload sizes, which made it automatically abort all commits that exeeded that size:

2008/03/07 13:56:16 [error] 15916\#0: \*1463829 client intented to send too large body: 59042053 bytes
, client: 10.0.0.15, server: www.example.org, URL: "/svn/!svn/wrk/38f59907-4ccf-4e05-acf4-444

We had to change the respective setting in nginx.conf, and everything was fine after:

 \# ---- dev ---
 location /svn {

      # Set the max size for file uploads
      client_max_body_size 100M;

The real problem here is though, that the stack of technologies is not able to pass forward errors. It’s the svn client that should have told me “client intented to send too large body: 59042053 bytes” and not the nginx log.

Taxme 2006 auf Debian lenny (testing)

  • Damit Taxme 2006 funktioniert, musste ich Blackdown’s j2re1.4 installieren, man bekommt es hier. Einfach

    deb http://sunsite.cnlab-switch.ch/ftp/mirror/java-linux/debian testing non-free
    

    in /etc/apt/sources.list eintragen. Offenbar ist Taxme nicht kompatibel mit 1.5er oder 1.6er JRE’s.

  • Damit die Hilfe im Taxme 2006 erscheint, musste ich:
    • das Paket libxul0d installieren (welches /usr/lib/xulrunner/libgtkembedmoz.so enthält, welches Taxme benötigt)
    • das folgende Startscript schreiben:

      #!/bin/sh
      # offenbar braucht SWT libgtkembedmoz, welches
      # TaxMe2006: z.B. in libxul0d in /usr/lib/xulrunner/ liegt
      #            siehe http://www.aptana.com/docs/index.php/Installing_Aptana_Milestone_7_on_Linux#Other_Linux_Distributions
      #                  http://dev.eclipse.org/newslists/news.eclipse.platform.swt/msg22648.html
      #
      export MOZILLA_FIVE_HOME=
      export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/lib/xulrunner/
      cd TaxMeBe2006
      ./TaxMeBe2006
      
    • Das Problem ist nur, dass zwar die Hilfe erscheint, der Index sichtbar ist, aber, wie weiter unten bei der Kurzhilfe der Hilfetext selbst leer bleibt. Tips?
  • Die Kurzhilfe scheint nicht zu funktionieren. Tips?

A RingBuffer in Ruby

I needed a ring buffer in Ruby, and since a web search didn’t yield anything I did it myself. Here you go, use as you wish:


Simple RingBuffer implementation
================================

see class RingBufferTest below for usage examples
=================================================

class RingBuffer \< Array

alias\_method :array\_push, :push
 alias\_method :array\_element, :[]

def initialize( size )
 @ring\_size = size
 super( size )
 end

def push( element )
 if length == @ring\_size
 shift \# loose element
 end
 array\_push element
 end

\# Access elements in the RingBuffer
 \#
 \# offset will be typically negative!
 \#
 def [](offset%20=%200)
 return self.array\_element( - 1 + offset )
 end
end

Usage example and unit test for the Ring Buffer
===============================================

require 'test/unit'
class RingBufferTest \< Test::Unit::TestCase

\# Usage example (and test)
 def test\_ring\_buffer

    rb = RingBuffer.new 2               # create RingBuffer with 2 elements

    rb.push 'Apple'                     # put 'Apple' into RingBuffer
    rb.push 'Pear'
    assert( rb[] == 'Pear' )            # the most recent element in the RingBuffer
                                        # is the 'Pear'

    assert( rb[0] == 'Pear' )           # same as before

    assert( rb[-1] == 'Apple' )         # get the second most recent element - it
                                        # shold be 'Apple'

    rb.push 'Mango'
    assert( rb == ['Pear', 'Mango'] )   # the 'Mango' has pushed the 'Apple' out of
                                        # the RingBuffer

end
end