<!DOCTYPE ARTICLE PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
]>

<!-- %% -*-tex-*-
%%
%% Hello. This file is called "boot.lj", at least on my disk.
%%
%% Since the Author's Guide doesn't tell about comments, I'll use a
%% percent sign at column zero. Moreover, I'm used to use "[/]" instead
%% of "[ecw]". You can fix both things with the following line:
%%
%% grep -v '^%' boot.lj | sed 's/\[\/\]/[ecw]/' > boot.doc
%%
%% Note that comments are for you, and you are expected to read
%% the article first, and strip comments later before sending to production
%%
%% I also use to lay-out the bare text to ease my reading. If you
%% don't like initial tabs and spaces you can do:
%%	sed 's/^[\t ]*//'
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->

<article id="index">
  <artheader>
    <authorgroup>
      <author>
	<firstname>Alessandro</firstname>
	<surname>Rubini</surname>
	<affiliation>
	  <address>
	    <email>rubini@linux.it</email>
	  </address>
	</affiliation>
	<authorblurb>
	  <para>
	    Alessandro is a Linux enthusiast who writes documentation because
	    he's not smart enough to write software.  His 486 is specialized in
	    grepping through source code, and humbly leaves real jobs to the
	    Alpha and the Sparc.
	  </para>
	</authorblurb>
      </author>
    </authorgroup>
    <copyright>
      <year>1999</year>
      <holder> </holder>
    </copyright>
    <title>Booting the Kernel</title>

    <abstract> 
      <para>
 	 This article describes the steps that are performed to boot
       	 the Linux kernel. While this kind of information is not
       	 relevant to the system's functionality, it's interesting to
       	 see how the different architectures bring the system up.
      </para> 
    </abstract> 
  </artheader>
 
<sect1 id="copyright">
<title>Copyright and Licensing</title>
<para>
This article is copyright (c) 1997 Alessandro Rubini.
</para>
<para>
Verbatim copying is allowed in any media, as well as porting to a
different layout as long as the text is unmodified; parts may be quoted
according to normal academic practice.  Other forms of derived works and
translations must be approved by the author.  Needless to say, the
author has no exclusive rights over the facts being described and their
use is not under the scope of copyright law.
</para>
<para>
Reprinted with permission of Linux Journal.
</para>
</sect1>
 
  <sect1 id="intro">
    <title>Introduction</title>
    <para>
      A computer system is a complex machinery, and the operating system is an
      elaborate tool that unrolls hardware complexities to end up showing a
      simple and standardized environment to the end user. When the power is
      turned on, however, the system software must work in a limited
      environment, and it must load the kernel using this scarse operating
      environment.  
    </para>
    <para>
      I'm going to describe here the booting process of three
      platforms: the old-fashioned PC and the more featured Alpha and Sparc
      platforms. The PC will take most of the space in this article because it
      is still more widespread than other platforms, and also because it's the
      most tricky platform to bring up. I am not going to show any code in this
      issue of the Kernel Korner because assembly is unintelligible to most
      readers, and each platform has its own assembly language.
    </para>
  </sect1>

  <sect1 id="power-on">
    <title>The Computer at Power-On</title>

    <para>
      In order to be able to do something with the computer when power is
      applied, things are arranged so that the processor begins execution from
      the system's firmware. The firmware is "unmovable software" found in ROM
      memory; some companies call it BIOS (Basic Input-Output System) to
      underline its software role, some call it PROM or "flash" to stress on its
      hardware implementation, while someone else calls it "console" to focus on
      user interaction.
    </para>
    <para>
      The firmware usually checks that the hardware is correctly working, and
      retrieves part (or all) of the kernel from a storage medium and executes
      it. This first part of the kernel must load the rest of itself and
      initialize the whole system. I won't deal with firmware issues here, but
      only with kernel code, whose source is distributed along with Linux.
    </para>
  </sect1>

  <sect1 id="PC">
    <title>The PC</title>

    <para>
      When the x86 processor is turned on in a personal computer, it is a 16-bit
      processor that only sees one meg of RAM. This environment is known as
      "real mode", and is dictated by compatibility with older processors of
      the same family. Everything that makes up a complete system must live
      within the available meg of address space: the firmware, video buffers,
      space for expansion boards and a little RAM (the infamous 640kB) must all
      be there.
    </para>
    <para>
      To make things difficult, the PC firmware only loads half a kilobyte of
      code, and establishes its own memory layout before loading this first
      sector.  Whichever the boot media, the first sector of the boot partition
      is loaded in memory to address 0x7c00, where execution begins. What
      happens at 0x7c00 depends on the boot-loader being used; I'm going to
      examine three situations here: <emphasis>no boot-loader</emphasis>,
      <application>lilo</application>, <application>loadlin</application>.
    </para>
  </sect1>


  <sect1 id="zImage">
    <title>Booting <filename>zImage</filename> and <filename>bzImage</filename></title>

    <para>
      Even though it's pretty rare to boot the system without a boot loader, it
      is still possible to do so by copying the raw kernel to a floppy disk.  A
      command like <command>cat zImage > /dev/fd0[/]</command> will work
      perfectly on Linux, although some other Unix systems can do the task
      reliably only by using the <command>dd</command> command. The raw floppy
      image thus created can then be configured by using the
      <application>rdev</application> program, but I won't discuss it here.
    </para>
    <para>
      The file called <filename>zImage</filename> is the compressed kernel image
      that lives in <filename>arch/i386/boot</filename> after you issued
      <command>make</command> <filename>zImage</filename> or
      <command>make</command> <filename>boot</filename> -- the latter invocation
      is the one I prefer, as it works unchanged on other platforms. If you
      built a <emphasis>big</emphasis> <filename>zImage</filename>, instead, the
      file is called <filename>bzImage</filename>, and lives in the same
      directory.
    </para>
    <para>
      Booting an x86 kernel is a tricky task because of the limited amount of
      available memory. The Linux kernel tries to maximize usage of the low 640
      kilobytes by moving itself around several times. But let's see in detail
      the steps performed by a <filename>zImage</filename> kernel; all the
      following pathnames are relative to <filename>arch/i386/boot</filename>.
    </para>
    <itemizedlist mark="bullet">
      <listitem>
	<para>
	  The first sector (executing at 0x7c00) moves itself to 0x90000 and
	  loads subsequent sectors after itself, getting them from the boot
	  device using the firmware's funtions to access the disk.  The rest of
	  the kernel is then loaded to address 0x10000, allowing for a maximum
	  size of half a meg of data -- but this is the compressed image.  The
	  boot-sector code lives in <filename>bootsect.S</filename>, a real-mode
	  assembly file.
	</para>
      </listitem>
      <listitem>
	<para>
	 Then, code at 0x90200 (defined in <filename>setup.S</filename>) takes
	 care of some hardware initialization and allows to change the default
	 text mode (<filename>video.S</filename>). Text mode selection has become a
	 compile-time option from 2.1.9 onwards.
	</para>
      </listitem>
      <listitem>
	<para>
	  Later, all the kernel is moved from 0x10000 (64K) to 0x1000 (4K).
	  This move overwrites BIOS data stored in RAM, and no BIOS call can be
	  performed after then. The first physical page is not touched because
	  it is the so-called "zero-page", used in handling virtual memory.
	</para>
      </listitem>
      <listitem>
	<para>
	  At this point <filename>setup.S</filename> enters protected mode and
	  jumps to 0x1000, where the kernel lives. All the available memory can
	  be accessed now, and the system can begin to run.
	</para>
      </listitem>
    </itemizedlist>
    <para>
      The steps just shown used to be the whole story of booting when the kernel
      was small enough to fit half a meg -- the address range between 0x10000
      and 0x90000. When the kernel was small it lived at 0x1000, but as features
      were added to the system it didn't fit half a meg any more: code at 0x1000
      isn't the Linux kernel nowadays, but rather the "gunzip" part of the
      <application>gzip</application> program. The following additional steps
      are needed to uncompress the real kernel and execute it:
    </para>
    <itemizedlist mark="bullet">
      <listitem>
	<para>
	  Code at 0x1000 is <filename>compressed/head.S</filename>, and is in
	  charge of "gunzipping" the kernel: it calls the function
	  <function>decompress_kernel</function>, defined in
	  <filename>compressed/misc.c</filename>, which in turns calls
	  <function>inflate</function> which writes its output starting at
	  address 0x100000 (one meg). High memory can now be accessed, because
	  the processor is definitely out of its limited boot environment -- the
	  "real" mode.
	</para>
      </listitem>
      <listitem>
	<para>
	  After decompression, <filename>head.S</filename> jumps to the real
	  beginning of the kernel. The relevant code is in
	  <filename>../kernel/head.S</filename>, outside of the
	  <filename>boot</filename> directory.
	</para>
      </listitem>
    </itemizedlist>
    <para>
      Boot is over now, and <filename>head.S</filename> (i.e., the code found at
      0x100000 that used to be at 0x1000 before introducing compressed boots)
      can complete processor initialization and call
      <function>start_kernel()</function>.  Everything is written in C from now
      on.
    </para>
    <para>
      The various data movements that are performed at system boot are depicted
      in <xref linkend="fig-boot">.
    </para>
    <figure id="fig-boot">
      <title>Data Movements Performed at System Boot</title>
      <graphic fileref="boot-lj" format="gif"></graphic>
    </figure>
	    
<!-- @lay:The figure is boot-lj.eps. It's a color figure, but I have been
careful not to depend from color. If it goes to a colored page that's
good, otherwise it's readable as well (unlike the VFS figure I sent in
last time). -->
      
    <para>
      The boot steps shown up to now rely on the assumption that the compressed
      kernel can fit in half a meg of space. While the assumption holds most of
      the times, a system stuffed of device drivers might not fit any more. This
      oversizing may happen for example to kernels used in installation disks:
      these kernels can easily get bigger than the available space, and some new
      machinery is needed to fix the problem.  This something is called
      <filename>bzImage</filename>, and has been introduced in kernel version
      1.3.73.
    </para>
    <para>
      A <filename>bzImage</filename> is generated by issuing <command>make
      </command> <filename>bzImage</filename> from the toplevel Linux source
      directory. This kind of kernel image boots similarly to the
      <filename>zImage</filename>, with a few changes:
    </para>
    <itemizedlist mark="bullet">
      <listitem>
	<para>
	  When the system is loaded to address 0x10000, a little helper routine
	  is called after loading each 64k data block.  The helper routing moves
	  the data block to high memory by using a special BIOS call. Only
	  not-so-old BIOS'es implement the functionality, and that's why
	  <command>make boot</command> still builds the conventional
	  <filename>zImage</filename> as I write this article -- but this might
	  change in the near future.
	</para>
      </listitem>
      <listitem>
	<para>
	  <filename>setup.S</filename> doesn't move the system back to 0x1000
	  (4k), but jumps instead directly to address 0x100000 (one meg) after
	  entering protected mode. "One meg" is where data has been moved by the
	  BIOS in the previous step.
	</para>
      </listitem>
      <listitem>
	<para>
	  The decompressor found at one-meg writes the uncompressed kernel image
	  in low memory until it gets exhausted, and then in high memory after
	  the compressed image. The two pieces are then reassembled to address
	  0x100000 (one meg). Several memory moves are needed to perform the
	  task correctly, but I won't detail the issue any deeper.
	</para>
      </listitem>
    </itemizedlist>
    <para>
      The rule for building the big compressed image can be read from
      <filename>Makefile</filename>: it affects several files in
      <filename>arch/i386/boot</filename>.  One good point of
      <filename>bzImage</filename> is that when
      <filename>kernel/head.S</filename> gets called it won't notice the extra
      work, and everything will go on as usual.
    </para>
  </sect1>

  <sect1 id="use-lilo">
    <title>Using Lilo</title>

    <para>
      Most Linux-x86 users don't boot the raw kernel image from a floppy, but
      rather boot Lilo from the hard disk. Lilo replaces part of the process
      outlined above so that it can load a Linux kernel that is scattered
      throughout a disk. This allows the user to boot a kernel file off a
      filesystem partition, without using the floppy.
    </para>
    <para>
      In practice, Lilo uses the BIOS services to load single sectors from the
      disk, and then jumps to <filename>setup.S</filename>. In other words, it
      arranges the memory layout like <filename>bootsect.S</filename> does, so
      the usual booting mechanism can complete painlessly. Lilo is also able to
      handle a kernel command line, and this is a good reason by itself to avoid
      booting the raw kernel image.
    </para>
    <para>
      If you want to boot a <filename>bzImage</filename> with Lilo, you need
      version 18 or newer of the tool. Earlier versions of Lilo are not able to
      load segments to high memory, which is needed when loading big images in
      order for <filename>setup.S</filename> to find the expected memory layout.
    </para>
    <para>
      The main disadvantage of Lilo is that is uses the BIOS to load the
      system. This forces to put the kernel and other relevant files in disks
      that can be accessed by the BIOS, and in the first 1024 cylinders of
      them. Actually, when you use the PC firmware you really discover how
      old-fashioned the architecture is.
    </para>
    <para>
      Even if you don't run Lilo, you can enjoy the documentation files that are
      distributed with Lilo's source code. They document the boot process on the
      PC, and explain how to handle (almost) every conceivable situation.
    </para>
  </sect1>
  
  <sect1 id="use-loadlin">
    <title>Using Loadlin</title>

    <para>
      If you want to boot your Operating System (uppercase) off another
      operating system (lowercase), Loadlin is the tool for you. The program is
      similar to Lilo because it loads the kernel from a disk partition and then
      jumps to <filename>setup.S</filename>. It is different from Lilo in that
      is must not only face the BIOS restrictions, but also get rid of an
      established memory layout without compromising the system' stability.  On
      the other hand, it is not restricted to be half-a-kilobyte long, because
      it is not a boot sector but a complete program file.
    </para>
    <note>
      <title>NOTE</title>
      <para>
	Version 1.6 and newer of the program are able to load big images.
      </para>
    </note>
    <para>
      Loadlin is able to pass a command line to the kernel and is therefore as
      flexible as Lilo; most of the times you'll end up writing a
      <filename>linux.bat</filename> file to pass a full-featured command line
      to Loadlin when calling the <filename>linux</filename> command.
    </para>
    <para>
      You can use Loadlin to turn any networked PC into a Linux box: you only
      need a kernel image equipped for mounting the root partition via NFS,
      Loadlin and a <filename>linux.bat</filename> with the correct IP numbers
      in. Sure you need a properly configured NFS server as well, but any Linux
      machine can do the job. For example, the following command line turns my
      gilfriend's PC (<systemitem
      class="systemname">alfred.unipv.it</systemitem>) into a workstation:
    </para>
    <para> 
      Well, it must be properly formatted for your system....
    </para>
    <programlisting>
@cx:loadlin c:\zimage rw nfsroot=/usr/root/alfred nfsaddrs=193.204.35.117:193.204.35.110:193.204.35.254:255.255.255.0:alfred.unipv.it
    </programlisting>
  </sect1>

  <sect1 id="more">
    <title>More of it</title>

    <para>
      As you might imagine, the code is not as easy as I described it: it must
      deal with a lot of details, like bringing around the kernel's command
      line, keep an eye over the boot technique being used and so on.  The
      curious reader can look in the source file to learn something more and to
      read the authors' comments that live herein. There's a lot of information
      in the comments, and they are often funny to read.
    </para>
    <para>
      I personally don't feel you'll ever need to touch the boot code, because
      things get much more interesting when the system is up and running: you
      can exploit all the features of your processor and all the available RAM
      without getting mad with processor-level issues.
    </para>
  </sect1>
  
  <sect1 id="alpha">
    <title>Booting an Alpha box</title>

    <para>
      The Alpha platform is much more mature than the PC and its firmware
      reflects this maturity. My experience with Alpha is limited to the ARC
      firmware, which is anyway the most used.
    </para>
    <para>
      After performing the usual detection of devices, the firmware displays a
      boot menu which lets you choose what file to boot. The firmware is able to
      read a disk partition (though only a FAT partition), so you actually boot
      a "file", without the need to hack boot sectors and build maps of disk
      blocks.
    </para>
    <para>
      The file that gets booted will usually be
      <filename>linload.exe</filename>, which in turn loads Milo (the "Mini
      Loader", whose name is a pun about Milo's size). In order to boot Linux
      through the ARC firmware you need to have a small FAT partition on your
      hard drive to store <filename>linload.exe</filename> and
      <filename>milo</filename>. The Linux kernel doesn't need to access the
      partition unless you upgrade Milo, so FAT support can be left out of your
      Alpha kernel without incurring in side effects.
    </para>
    <para>
      Actually, the user can exploit different options: the ARC boot menu can be
      configured to boot Linux by default, and Milo can even be burnt in flash
      memory in order to get rid of the FAT partition. But whatever you do, you
      end up with Milo running.
    </para>
    <para>
      The Milo program is a stripped-down version of the Linux kernel: it has
      all the Linux device drivers and some filesystem decoder; unlike the
      kernel it doesn't have process control and includes Alpha initialization
      code. The tool is able to setup virtual memory and enable it, and can load
      a file from either an <acronym>ext2</acronym> partition or an
      <hardware>iso9660</hardware> device. The "file" in question is loaded to
      virtual address 0xfffffc0000300000 and then executed.  The virtual address
      used is the one where the Linux kernel runs: it's unlikely you'll ever
      load anything but Linux, with the exception of the
      <application>fmu</application> (flash management utility) program used to
      burn Milo in flash ROM &mdash; <application>fmu</application> is compiled to
      execute from the same virtual address whence the kernel runs and is
      distributed with Milo.
    </para>
    <para>
      It's interesting to note that Milo also includes a small 386 emulator and
      some of the PC BIOS functionality. This is needed in order to execute
      self-initialization code found on many <hardware>ISA/PCI</hardware>
      peripheral boards (<hardware>PCI</hardware> boards, though claiming to be
      processor-independent, use intel machine code in their ROM images).
    </para>
    <para>
      But, if Milo does all of this, what is left to the Linux kernel?
    </para>
    <para>
      A very little, actually. The first kernel code to execute in Linux-Alpha
      is <filename>arch/alpha/kernel/head.S</filename>, and it just needs to
      setup a few pointers and jump to
      <function>start_kernel()</function>. Actually,
      <filename>kernel/head.S</filename> for Alpha is much shorter than the
      equivalent x86 source file.
    </para>
    <para>
      If you don't want to run Milo there is an alternative, though not a
      practical one. In <filename>arch/alpha/boot</filename> you'll find the
      sources of a "raw" loader which gets compiled by issuing <command>make
      rawboot</command> from the toplevel Linux source directory.  The utility
      is able to load a file from a sequential region of a device (the floppy or
      the hard disk) using the firmware's callbacks.
    </para>
    <para>
      In practice, the raw loader accomplishes a task similar to what
      <filename>bootsect.S</filename> does for the PC platform, and this forces
      to copy the kernel to either a raw floppy or a raw hard-disk partition.
      As you see, there's no real reason to try out this technique, which is
      quite hairy and lacks the flexibility Milo offers. I personally don't even
      know if it still works: the "PALcode" used by Linux is exported by Milo,
      and is different from the one exported by the ARC firmware.  The PALcode
      is a library of low-level functions used by Alpha processors to implement
      low-level hardware management like paging; if the current PALcode
      implements different operations than the software expects, the system
      won't work.
    </para>
  </sect1>

  <sect1 id="sparc">
    <title>Booting a Sparc station</title>

    <para>
      Bringing up a Sparc computer is similar to booting the Alpha
      on the user side, and similar to booting the PC on the software side.
    </para>
    <para>
      What the user sees it that the firmware loads a program and executes it,
      the program in turn is able to retrieve and uncompress a file found on a
      disk partition. The "program" in question is called <application>Silo</application>, and it can read
      files from either an <acronym>ext2</acronym> partition or an
      <acronym>ufs</acronym> one. Unlikely Milo (likely Lilo), <application>Silo</application> is able to
      boot another operating system. There is no such need for the Alpha,
      because the firmware can boot multiple systems: once you run Milo, you
      have already made your choice -- the Right Choice.
    </para>
    <para>
      When a Sparc computer boots, the firmware loads a boot sector after
      performing all the hardware checks and device initialization. It's
      interesting to note that Sbus devices <emphasis>are</emphasis> platform
      independent, and their initialization code is portable Forth code rather
      than machine language bound to a particular processor.
    </para>
    <para>
      The boot sector that gets loaded is what you find in
      <filename>/boot/first.b</filename> in your Linux-Sparc system, and is a
      bare 512 bytes.  It is loaded to address 0x4000 and its role is retrieving
      from disk <filename>/boot/second.b</filename> and putting it to address
      0x280000 (2.5 megs); the address has been chosen because the Sparc
      specifications state that at least three megabytes of RAM are mapped at
      boot time.
    </para>
    <para>
      Everything else is then performed by the second-stage boot loader: it is
      linked with <filename>libext2.a</filename> to access system partitions,
      and can thus load a kernel image from your Linux filesystem. It can also
      uncompress the image because it includes <filename>inflate.c</filename>,
      from <application>gzip</application>.
    </para>
    <para>
      <filename>second.b</filename> accesses a configuration file called
      <filename>/etc/<application>Silo</application>.conf</filename>, similar in shape to
      [cw]lilo.conf[/]. Since the file is read at boot time there's no need to
      re-install the kernel maps when a new kernel is added to the boot
      choices. When <application>Silo</application> shows its prompt you can choose from any kernel image
      (or other operating system) specified in <filename><application>Silo</application>.conf</filename>,
      or you can specify a complete device/pathname pair to load a different
      kernel image without editing the configuration file.
    </para>
    <para>
      
      <application>Silo</application> loads the disk file to address 0x4000. This means that the kernel
      must be shorter than 2.5 megs: if it is longer <application>Silo</application> will refure to
      overwrite its own image. No conceivable Linux-Sparc kernel is currently
      bigger than thant, unless you compiled it with <parameter
      class="command">-g</parameter> to have debugging information available. In
      this case the kernel image must be stripped before being handled to <application>Silo</application>.
    </para>
    <para>
      Finally, <application>Silo</application> performs kernel decompression and/or remapping to place the
      image at virtual address 0xf0004000. The code that takes over <application>Silo</application> is
      &mdash; as you may imagine &mdash;
      <filename>arch/sparc/kernel/head.S</filename>. The source includes all the
      trap tables for the processor and the actual code to set the machine up
      and call <function>start_kernel()</function>. The Sparc version of
      <filename>head.S</filename> is actually quite big.
    </para>
  </sect1>

  <sect1 id="start-kernel">
    <title>start_kernel and on</title>

    <para>
      After architecture-specific initialization is over,
      <filename>init/main.c</filename> takes control of the processor &mdash;
      whichever the processor is.
    </para>
    <para>
      The <function>start_kernel()</function> function calls
      <function>setup_arch()</function> first, which is the last
      architecture-specific function. Unlike other code, however,
      <function>setup_arch()</function> can exploit all the processor's
      features, and is a much easier source file than the ones described
      earlier. The function is defined in <filename>kernel/setup.c</filename>
      under each architecture source tree.
    </para>
    <para>
      The function then initializes all the kernel's subsystems &mdash; IPC,
      networking, buffer cache and so on. After all initialization is over,
      these two lines complete <function>start_kernel()</function>:
    </para>
    <programlisting>
	@cx:
	kernel_thread(init, NULL, 0);
	cpu_idle(NULL);
    </programlisting>
    <para>
      The <function>init</function> thread is process number 1: it mounts the
      root partition, executes <filename>/linuxrc</filename> if <parameter
      class="command">CONFIG_INITRD</parameter> has been selected at compile
      time, and then executes the <application>init</application> program. If
      <application>init</application> can't be found,
      <application>/etc/rc</application> is executed; using
      <application>rc</application> is discouraged nowadays, as
      <application>init</application> is much more flexible than a shell script
      in handling system configuration.
    </para>
    <para>
      If neither <application>init</application> nor
      <application>/etc/rc</application> can be run, or if they exit,
      <application>/bin/sh</application> is executed repeatedly. This feature
      only exists as a safeguard in case the system administrator removes or
      corrupts <application>init</application> by mistake: if you remove
      <filename>a.out</filename> support from the kernel forgetting that your
      old <application>init</application> has not been recompiled, you'll enjoy
      having at least a shell running after reboot.
    </para>
    <para>
      The kernel has nothing more to do after spawning process number 1, and
      everything else is handled in user space -- by
      <application>init</application>, <application>/etc/rc</application> or
      <application>/bin/sh</application>.
    </para>
    <para>
      And process 0? we've seen hoe the so called idle task executed
      <function>cpu_idle()</function>: this is a function that calls the
      <function>idle()</function> function in an endless
      loop. <function>idle()</function>, in turn is an architecture-dependent
      function, which is usually in charge of turning off the processor to save
      power and increase the processor's lifetime.
    </para>
  </sect1>

<!-- @lay:Photo is available as ftp://iride.unipv.it/pub/info/guack.gif use
``guack-face.gif'' if you plan to cut only the face anyway.  But if you put the
photo last time you'd better leave it offline this time. --> 

</article>
