2003-11-22 16:15:47 +01:00
%
% This document is released under the GPL
% Initially written by Stefan Reinauer, <stepan@openbios.org>
%
\documentclass [titlepage,12pt] { article}
\usepackage { a4}
\usepackage { graphicx}
\usepackage { url}
\usepackage [pdftex] { hyperref}
% \usepackage{makeidx}
% \makeindex
\hypersetup {
urlbordercolor={ 1 1 1} ,
menubordercolor={ 1 1 1} ,
linkbordercolor={ 1 1 1} ,
colorlinks=false,
% pdfpagemode=None, % PDF-Viewer starts without TOC
% pdfstartview=FitH,
pdftitle={ LinuxBIOS on AMD64} ,
pdfauthor={ Stefan Reinauer} ,
pdfsubject={ LinuxBIOS configuration and build process} ,
pdfkeywords={ LinuxBIOS, Opteron, AMD64, Athlon64, Build}
}
% \newcommand{\sh}[1]{\begin{verbatim}\texttt{#1}\end{verbatim}}
% \newcommand{\prog}[1]{\textit{#1}}
\setlength { \parindent } { 0pt}
\title { LinuxBIOS on AMD64}
\author { Stefan Reinauer $ < $ stepan@openbios.org$ > $ }
2004-06-02 13:25:31 +02:00
\date { June 2nd, 2004}
2003-11-22 16:15:47 +01:00
\begin { document}
\maketitle
\thispagestyle { empty}
\tableofcontents
\newpage
%
% 1 Abstract
%
\section { Abstract}
2004-06-02 13:25:31 +02:00
This document targets porting LinuxBIOS to new mainboards and creating
2003-11-22 16:15:47 +01:00
custom firmware images using LinuxBIOS. It describes how to build
LinuxBIOS images for the AMD64 platform, including hypertransport
configuration and pertinent utilities. If you are missing information or
find errors in the following descriptions, contact
\href { mailto:stepan@openbios.org} { \textit { Stefan Reinauer $ < $ stepan@openbios.org$ > $ } }
%
2004-02-10 18:30:04 +01:00
% 2 Changes
%
\section { Changes}
\begin { itemize}
2004-06-02 13:25:31 +02:00
\item 2004/06/02 url and language fixes from Ken Fuchs $ < $ kfuchs@winternet.com$ > $
2004-02-10 18:30:04 +01:00
\item 2004/02/10 acpi and option rom updates
2004-06-02 13:25:31 +02:00
\item 2003/11/18 initial release
2004-02-10 18:30:04 +01:00
\end { itemize}
%
% 3 What is LinuxBIOS
2003-11-22 16:15:47 +01:00
%
\section { What is LinuxBIOS?}
LinuxBIOS aims to replace the normal BIOS found on PCs, Alphas, and
other machines with a Linux kernel that can boot Linux from a cold
start. The startup code of an average LinuxBIOS port is about 500 lines
of assembly and 5000 lines of C. It executes 16 instructions to get into
32bit mode and then performs DRAM and other hardware initializations
required before Linux can take over.
The projects primary motivation initially was maintenance of large
clusters. Not surprisingly interest and contributions have come from
people with varying backgrounds. Nowadays a large and growing number of
Systems can be booted with LinuxBIOS, including embedded systems,
Desktop PCs and Servers.
%
2004-02-10 18:30:04 +01:00
% 4 Build Requirements
2003-11-22 16:15:47 +01:00
%
\section { Build Requirements}
To build LinuxBIOS for AMD64 from the sources you need a recent Linux
system for x86 or AMD64. SUSE Linux 8.2 or 9.0 are known to work fine.
The following toolchain is recommended:
\begin { itemize}
\item GCC 3.3.1
\item binutils 2.14.90.0.5
\item Python 2.3
\item CVS 1.11.6
\end { itemize}
\textbf { NOTE:} Later versions should also work. Prior versions might lead to problems.
\newpage
%
2004-02-10 18:30:04 +01:00
% 5 Getting the Sources
2003-11-22 16:15:47 +01:00
%
\section { Getting the Sources}
The latest LinuxBIOS sources are available via CVS. The CVS repository
2004-06-02 13:25:31 +02:00
is maintained at SourceForge.net (the project name is \emph { FreeBIOS} ).
First you should create a directory for your LinuxBIOS trees:
{ \small
\begin { verbatim}
$ mkdir linuxbios
$ cd linuxbios
\end { verbatim}
}
You can get the entire source tree via CVS:
2003-11-22 16:15:47 +01:00
{ \small
\begin { verbatim}
2004-06-02 13:25:31 +02:00
$ cvs - d:pserver:anonymous@cvs.sourceforge.net: / cvsroot / freebios login
2003-11-22 16:15:47 +01:00
\end { verbatim}
}
Hit return when you are asked for a password. Then checkout (or update)
the freebios source tree as follows:
{ \small
\begin { verbatim}
2004-06-02 13:25:31 +02:00
$ cvs - z 3 - d:pserver:anonymous@cvs.sourceforge.net: / cvsroot / freebios co freebios 2
2003-11-22 16:15:47 +01:00
\end { verbatim}
}
Once the source tree is checked out, it can be updated with:
{ \small
\begin { verbatim}
2006-08-23 12:52:12 +02:00
% cvs update -Pd
2003-11-22 16:15:47 +01:00
\end { verbatim}
}
Due to recent problems with SourceForge's CVS infrastructure we set up a
snapshot site that keeps hourly source trees of the last four days. It
is available at \url { http://snapshots.linuxbios.org/} .
Due to major structural enhancements to \hbox { LinuxBIOS} , AMD64 support
is only available in the \texttt { freebios2} tree. This tree reflects (as
of November 2003) LinuxBIOS version 1.1.5 and will lead to LinuxBIOS 2.0
when finished. Most x86 hardware is currently only supported by the
LinuxBIOS 1.0 tree.
%
2004-02-10 18:30:04 +01:00
% 6 LinuxBIOS configuration overview
2003-11-22 16:15:47 +01:00
%
\section { LinuxBIOS configuration overview}
To support a large variety of existing hardware LinuxBIOS allows for a
lot of configuration options that can be tweaked in several ways:
\begin { itemize}
\item
Firmware image specific configuration options can be set in the image
configuration file which is usually found in
2004-06-02 13:25:31 +02:00
\texttt { freebios2/targets/$ < $ vendor$ > $ /$ < $ mainboard$ > $ /} . Such
2003-11-22 16:15:47 +01:00
options are the default amount of output verbosity during bootup, image
size, use of fallback mechanisms, firmware image size and payloads
(Linux Kernel, Bootloader...) The default configuration file name is
\texttt { Config.lb} , but LinuxBIOS allows multiple configurations to
reside in that directory.
2004-06-02 13:25:31 +02:00
\item Mainboard specific configuration options can be set in the
mainboard configuration file placed in
\texttt { freebios2/src/mainboard/$ < $ vendor$ > $ /$ < $ mainboard$ > $ } . The
mainboard configuration file is always called \texttt { Config.lb} . It
contains information on the onboard components of the mainboard like
2003-11-22 16:15:47 +01:00
CPU type, northbridge, southbridge, hypertransport configuration and
SuperIO configuration. This configuration file also allows to include
addon code to hook into the LinuxBIOS initialization mechanism at
basically any point.
\end { itemize}
This document describes different approaches of changing and configuring the
LinuxBIOS source tree when building for AMD64.
2004-02-10 18:30:04 +01:00
%
% 7 Building LinuxBIOS
%
2003-11-22 16:15:47 +01:00
\section { Building LinuxBIOS}
One of the design goals for building LinuxBIOS was to keep object files
2004-06-02 13:25:31 +02:00
out of the source tree in a separate place. This is mandatory for
building parallel LinuxBIOS images for several distinct mainboards
2003-11-22 16:15:47 +01:00
and/or platforms. Therefore building LinuxBIOS consists of two steps:
\begin { itemize}
\item
creating a build tree which holds all files automatically created by the
configuration utility and the object files
\item
compiling the LinuxBIOS code and creating a flashable firmware image.
\end { itemize}
The first of these two steps is accomplished by the \texttt { buildtarget}
script found in \texttt { freebios2/targets/} . To build LinuxBIOS for
2004-06-02 13:25:31 +02:00
instance for the AMD Solo Athlon64 mainboard enter:
2003-11-22 16:15:47 +01:00
\begin { verbatim}
% cd freebios2/targets
% ./buildtarget amd/solo
\end { verbatim}
This will create a directory containing a Makefile and other software
components needed for this build. The directory name is defined in the
firmware image specific configuration file. In the case of AMD's Solo
2004-06-02 13:25:31 +02:00
mainboard the default directory resides in
2003-11-22 16:15:47 +01:00
\texttt { freebios2/targets/amd/solo/solo} . To build the LinuxBIOS image, do
\begin { verbatim}
% cd amd/solo/solo
% make
\end { verbatim}
The LinuxBIOS image filename is specified in the firmware image specific
2004-06-02 13:25:31 +02:00
configuration file. The default filename for AMD's Solo mainboard is
2003-11-22 16:15:47 +01:00
\texttt { solo.rom} .
2004-02-10 18:30:04 +01:00
%
% 8 Programming LinuxBIOS to flash memory
%
2003-11-22 16:15:47 +01:00
\section { Programming LinuxBIOS to flash memory}
The image resulting from a LinuxBIOS build can be directly programmed to
a flash device, either using a hardware flash programmer or by using the
Linux flash driver devbios or mtd. This document assumes that you use a
hardware flash programmer. If you are interested in doing in-system
software flash programming, find detailed information:
\begin { itemize}
\item \url { http://www.openbios.org/development/devbios.html} (/dev/bios)
2004-06-02 13:25:31 +02:00
\item \url { http://www.linux-mtd.infradead.org/} (Memory Technology Device Subsystem MTD)
2003-11-22 16:15:47 +01:00
\end { itemize}
\newpage
2004-02-10 18:30:04 +01:00
%
% 9 LinuxBIOS configuration
%
2003-11-22 16:15:47 +01:00
\section { LinuxBIOS configuration}
The following chapters will cope with configuring LinuxBIOS. All
configuration files share some basic rules
\begin { itemize}
\item
The default configuration file name in LinuxBIOS is \texttt { Config.lb} .
\item
All variables used in a configuration file have to be declared in this
file with \texttt { uses VARNAME} before usage.
\item
Comments can be added on a new line by using the comment identifier
\texttt { \# } at the beginning of the line.
\item
LinuxBIOS distinguishes between statements and options. Statements cause
the LinuxBIOS configuration mechanism to act, whereas options set
variables that are used by the build scripts or source code.
\item
2004-06-02 13:25:31 +02:00
Default configuration values can be set in the mainboard configuration
2003-11-22 16:15:47 +01:00
files (keyword default)
\item
Option overrides to the default configuration can only be specified in
the build target configuration file
\texttt { freebios2/targets/$ < $ vendor$ > $ /$ < $ mainboard$ > $ /Config.lb}
(keyword option)
\end { itemize}
\subsection { Common Configuration Statements}
\begin { itemize}
\item \begin { verbatim} uses\end { verbatim}
All local configuration variables have to be declared before they can be
used. Example:
\begin { verbatim}
uses ROM_ IMAGE_ SIZE
\end { verbatim}
\textbf { NOTE:} Only configuration variables known to the configuration
system can be used in configuration files. LinuxBIOS checks
\texttt { freebios2/src/config/Options.lb} to see whether a configuration
variable is known.
\item \begin { verbatim} default\end { verbatim}
The \texttt { default} statement is used to set a configuration variable
2004-06-02 13:25:31 +02:00
with an overridable default value. It is commonly used in mainboard
2003-11-22 16:15:47 +01:00
configuration files.
Example:
\begin { verbatim}
default ROM_ IMAGE_ SIZE=0x10000
\end { verbatim}
It is also possible to assign the value of one configuration variable to
another one, i.e.:
\begin { verbatim}
default FALLBACK_ SIZE=ROM_ SIZE
\end { verbatim}
Also, simple expressions are allowed:
\begin { verbatim}
default FALLBACK_ SIZE=(ROM_ SIZE - NORMAL_ SIZE)
\end { verbatim}
If an option contains a string, this string has to be protected with
quotation marks:
\begin { verbatim}
2006-08-23 12:52:12 +02:00
default CC="gcc -m32"
2003-11-22 16:15:47 +01:00
\end { verbatim}
\item \begin { verbatim} option\end { verbatim}
The \texttt { option} statement basically behaves identically to the
\texttt { default} statement. But unlike default it can only be used in
build target configuration files
(\texttt { freebios2/targets/$ < $ vendor$ > $ /$ < $ mainboard$ > $ } ). The option
statement allows either to set new options or to override default values
2004-06-02 13:25:31 +02:00
set with the default statement in a mainboard configuration file.
2003-11-22 16:15:47 +01:00
Syntax and application are the same as with default.
\end { itemize}
\subsection { Firmware image specific configuration}
LinuxBIOS allows to create different firmware images for the same
hardware. Such images can differ in the amount of output they produce,
the payload, the number of subimages they consist of etc.
2004-06-02 13:25:31 +02:00
The firmware image specific configuration file can be found in \\
\texttt { freebios2/targets/$ < $ vendor$ > $ /<mainboard$ > $ } .
2003-11-22 16:15:47 +01:00
\subsubsection { Firmware image specific keywords}
In addition to the above described keywords the following statements are
available in firmware image specific configuration files:
\begin { itemize}
\item \begin { verbatim} romimage\end { verbatim}
The \texttt { romimage} definition describes a single rom build within the
final LinuxBIOS image. Normally there are two romimage definitions per
LinuxBIOS build: \texttt { normal} and \texttt { fallback} .
Each \texttt { romimage} section needs to specify a mainboard directory and a
payload. The mainboard directory contains the mainboard specific
configuration file and source code. It is specified relatively to
\texttt { freebios2/src/mainboard} . The payload definition is an absolute
path to a static elf binary (i.e Linux kernel or etherboot)
\begin { verbatim}
romimage "normal"
option USE_ FALLBACK_ IMAGE=0
option ROM_ IMAGE_ SIZE=0x10000
2008-01-18 16:08:58 +01:00
option COREBOOT_ EXTRA_ VERSION=".0Normal"
2003-11-22 16:15:47 +01:00
mainboard amd/solo
payload /suse/stepan/tg3ide_
disk.zelf
end
\end { verbatim}
\item \begin { verbatim} buildrom\end { verbatim}
The \texttt { buildrom} statement is used to determine which of the
LinuxBIOS image builds (created using \texttt { romimage} ) are packed
together to the final LinuxBIOS image. It also specifies the order of
the images and the final image size:
\begin { verbatim}
buildrom ./solo.rom ROM_ SIZE "normal" "fallback"
\end { verbatim}
\end { itemize}
\subsubsection { Firmware image configuration options}
In addition to the definitions described above there are a number of
commonly used options. Configuration options set in the firmware image
specific configuration file can override default selections from the
2004-06-02 13:25:31 +02:00
Mainboard specific configuration. See above examples about
2003-11-22 16:15:47 +01:00
option on how to set them.
\begin { itemize}
\item \begin { verbatim} CC\end { verbatim}
Target C Compiler. Default is \texttt { \$ (CROSS\_ COMPILE)gcc} . Set to
2006-08-23 12:52:12 +02:00
\texttt { gcc -m32} for compiling AMD64 LinuxBIOS images on an AMD64
2003-11-22 16:15:47 +01:00
machine.
\item \begin { verbatim} CONFIG_ CHIP_ CONFIGURE \end { verbatim}
Use new \textit { chip\_ configure} method for configuring (nonpci)
2004-06-02 13:25:31 +02:00
devices. Set to \texttt { 1} for all AMD64 mainboards.
2003-11-22 16:15:47 +01:00
\item \begin { verbatim} MAXIMUM_ CONSOLE_ LOGLEVEL\end { verbatim}
Errors or log messages up to this level can be printed. Default is
\texttt { 8} , minimum is \texttt { 0} , maximum is \texttt { 10} .
\item \begin { verbatim} DEFAULT_ CONSOLE_ LOGLEVEL\end { verbatim}
Console will log at this level unless changed. Default is \texttt { 7} ,
minimum is \texttt { 0} , maximum is \texttt { 10} .
\item \begin { verbatim} CONFIG_ CONSOLE_ SERIAL8250\end { verbatim}
Log messages to 8250 uart based serial console. Default is \texttt { 0}
(don't log to serial console). This value should be set to \texttt { 1}
for all AMD64 builds.
\item \begin { verbatim} ROM_ SIZE\end { verbatim}
Size of final ROM image. This option has no default value.
\item \begin { verbatim} FALLBACK_ SIZE\end { verbatim}
Fallback image size. Defaults to \texttt { 65536} bytes. \textbf { NOTE:}
This does not include the fallback payload.
\item \begin { verbatim} HAVE_ OPTION_ TABLE\end { verbatim}
Export CMOS option table. Default is \texttt { 0} . Set to \texttt { 1} if
2004-06-02 13:25:31 +02:00
your mainboard has CMOS memory and you want to use it to store
2003-11-22 16:15:47 +01:00
LinuxBIOS parameters (Loglevel, serial line speed, ...)
2006-12-15 13:56:28 +01:00
\item \begin { verbatim} CONFIG_ ROM_ PAYLOAD\end { verbatim}
2003-11-22 16:15:47 +01:00
2006-12-15 13:56:28 +01:00
Boot image is located in ROM (as opposed to \texttt { CONFIG\_ IDE\_ PAYLOAD} , which
2003-11-22 16:15:47 +01:00
will boot from an IDE disk)
\item \begin { verbatim} HAVE_ FALLBACK_ BOOT\end { verbatim}
Set to \texttt { 1} if fallback booting is required. Defaults to
\texttt { 0} .
\end { itemize}
The following options should be used within a romimage section:
\begin { itemize}
\item \begin { verbatim} USE_ FALLBACK_ IMAGE\end { verbatim}
Set to \texttt { 1} to build a fallback image. Defaults to \texttt { 0}
\item \begin { verbatim} ROM_ IMAGE_ SIZE\end { verbatim}
Default image size. Defaults to \texttt { 65535} bytes.
2008-01-18 16:08:58 +01:00
\item \begin { verbatim} COREBOOT_ EXTRA_ VERSION\end { verbatim}
2003-11-22 16:15:47 +01:00
LinuxBIOS extra version. This option has an empty string as default. Set
to any string to add an extra version string to your LinuxBIOS build.
\end { itemize}
\newpage
2004-06-02 13:25:31 +02:00
\subsection { Mainboard specific configuration}
2003-11-22 16:15:47 +01:00
2004-06-02 13:25:31 +02:00
Mainboard specific configuration files describe the onboard
mainboard components, i.e. bridges, number and type of CPUs. They also
2003-11-22 16:15:47 +01:00
contain rules for building the low level start code which is translated
using romcc and/or the GNU assembler. This code enables caches and
registers, early mtrr settings, fallback mechanisms, dram init and
possibly more.
2004-06-02 13:25:31 +02:00
\textbf { NOTE:} The \texttt { option} keyword can not be used in mainboard
specific configuration files. Options shall instead be set using the
\texttt { default} keyword so that they can be overridden by the image
specific configuration files if needed.
2003-11-22 16:15:47 +01:00
2004-06-02 13:25:31 +02:00
\subsubsection { Mainboard specific keywords}
2003-11-22 16:15:47 +01:00
2004-06-02 13:25:31 +02:00
The following statements are used in mainboard specific configuration
2003-11-22 16:15:47 +01:00
files:
\begin { itemize}
\item \begin { verbatim} arch\end { verbatim}
2004-06-02 13:25:31 +02:00
Sets the CPU architecture. This should be \texttt { i386} for AMD64 boards.\\
2003-11-22 16:15:47 +01:00
Example:
\begin { verbatim}
arch i386 end
\end { verbatim}
\item \begin { verbatim} cpu\end { verbatim}
The cpu statement is needed once per possibly available CPU. In a
one-node system, write:
\begin { verbatim}
cpu k8 "cpu0" end
\end { verbatim}
\item \begin { verbatim} driver\end { verbatim}
The \texttt { driver} keyword adds an object file to the driver section of a
LinuxBIOS image. This means it can be used by the PCI device
initialization code. Example:
\begin { verbatim}
driver mainboard.o
\end { verbatim}
\item \begin { verbatim} object\end { verbatim}
The \texttt { object} keyword adds an object file to the LinuxBIOS image.
Per default the object file will be compiled from a \texttt { .c} file
with the same name. Symbols defined in such an object file can be used
in other object files and drivers. Example:
\begin { verbatim}
object reset.o
\end { verbatim}
\item \begin { verbatim} makerule\end { verbatim}
This keyword can be used to extend the existing file creation rules
during the build process. This is useful if external utilities have to
be used for the build. LinuxBIOS on AMD64 uses romcc for it's early
startup code placed in auto.c.
To tell the configuration mechanism how to build \texttt { romcc} files,
do:
\begin { verbatim}
makerule ./auto.E
2004-11-04 12:04:33 +01:00
depends "$ ( MAINBOARD ) / auto.c option _ table.h . / romcc"
2006-08-23 12:52:12 +02:00
action "./romcc -E -mcpu=k8 -O2 -I$ ( TOP ) / src - I. $ (CPPFLAGS) \
2004-11-04 12:04:33 +01:00
$ ( MAINBOARD ) / auto.c - o $ @"
2003-11-22 16:15:47 +01:00
end
makerule ./auto.inc
2004-11-04 12:04:33 +01:00
depends "$ ( MAINBOARD ) / auto.c option _ table.h . / romcc"
2006-08-23 12:52:12 +02:00
action "./romcc -mcpu=k8 -O2 -I$ ( TOP ) / src - I. $ (CPPFLAGS) \
2004-11-04 12:04:33 +01:00
$ ( MAINBOARD ) / auto.c - o $ @"
2003-11-22 16:15:47 +01:00
end
\end { verbatim}
2004-06-02 13:25:31 +02:00
Each \texttt { makerule} section contains file dependencies (using the
texttt{ depends} keyword) and an action that is taken when the dependencies
are satisfied (using the \texttt { action} keyword).
2003-11-22 16:15:47 +01:00
\item \begin { verbatim} mainboardinit\end { verbatim}
With the mainboardinit keyword it's possible to include assembler code
directly into the LinuxBIOS image. This is used for early infrastructure
initialization, i.e. to switch to protected mode. Example:
\begin { verbatim}
mainboardinit cpu/i386/entry16.inc
\end { verbatim}
\item \begin { verbatim} ldscript\end { verbatim}
The GNU linker ld is used to link object files together to a LinuxBIOS
ROM image.
Since it is a lot more comfortable and flexible to use the GNU linker
with linker scripts (ldscripts) than to create complex command line
calls, LinuxBIOS features including linker scripts to control image
creation. Example:
\begin { verbatim}
ldscript /cpu/i386/entry16.lds
\end { verbatim}
\item \begin { verbatim} dir\end { verbatim}
LinuxBIOS reuses as much code between the different ports as possible.
2004-06-02 13:25:31 +02:00
To achieve this, commonly used code can be stored in a separate
directory. For a new mainboard, it is enough to know that the code in
2003-11-22 16:15:47 +01:00
that directory can be used as is.
LinuxBIOS will also read a \texttt { Config.lb} file stored in that
directory. This happens with:
\begin { verbatim}
dir /pc80
\end { verbatim}
\item \begin { verbatim} config\end { verbatim}
This keyword is needed by the new chip configuration scheme. Should be
used as:
\begin { verbatim}
config chip.h
\end { verbatim}
\item \begin { verbatim} register\end { verbatim}
The \texttt { register} keyword can occur in any section, passing
2004-06-02 13:25:31 +02:00
additional \\
parameters to the code handling the associated device.
2003-11-22 16:15:47 +01:00
Example:
\begin { verbatim}
register "com1" = "{ 1, 0, 0x3f8, 4} "
\end { verbatim}
\item \begin { verbatim} northbridge\end { verbatim}
The \texttt { northbridge} keyword describes a system northbridge. Some
systems, like AMD64, can have more than one northbridge, i.e. one per
CPU node. Each northbridge is described by the path to the northbridge
code in LinuxBIOS (relative to \texttt { freebios2/src/northbridge} ), i.e.
2004-06-02 13:25:31 +02:00
\texttt { amd/amdk8} and a unique name (i.e \texttt { mc0} ) \\
Example:
2003-11-22 16:15:47 +01:00
\begin { verbatim}
northbridge amd/amdk8 "mc0"
[..]
end
\end { verbatim}
\item \begin { verbatim} southbridge\end { verbatim}
To simplify the handling of bus bridges in a LinuxBIOS system, all
bridges available in a system that are not northbridges (i.e AGP, IO,
PCIX) are seen as southbridges.
Since from the CPUs point of view any southbridge is connected via the
northbridge, a southbridge section is declared within the northbridge
section of the north bridge it is attached to.
Like the northbridge, any other bridge is described by the path to it's
driver code, and a unique name. If the described bridge is a
hypertransport device, the northbridge's hypertransport link it connects
to can be specified using the \texttt { link} keyword. Example:
\begin { verbatim}
northbridge amd/amdk8 "mc0"
[..]
southbridge amd/amd8111 "amd8111" link 0
[..]
end
[..]
end
\end { verbatim}
\item \begin { verbatim} pci\end { verbatim}
The \texttt { pci} keyword can only occur within a \texttt { northbridge} or
\texttt { southbridge} section. It is used to describe the PCI devices
that are provided by the bridge. Generally all bridge sections have a
couple of \texttt { pci} keywords.
The first occurrence of the \texttt { pci} keyword tells LinuxBIOS where
the bridge devices start, relative to the PCI configuration space used
by the bridge. The following occurences of the \texttt { pci} keyword
describe the provided devices.
Adding the option \texttt { on} or \texttt { off} to a PCI device will
enable or disable this device. This feature can be used if some bridge
devices are not wired to hardware outputs and thus are not used.
Example:
\begin { verbatim}
northbridge amd/amdk8 "mc1"
pci 0:19.0
pci 0:19.0
pci 0:19.0
pci 0:19.1
pci 0:19.2
pci 0:19.3
end
\end { verbatim}
or
\begin { verbatim}
southbridge amd/amd8111 "amd8111" link 0
pci 0:0.0
pci 0:1.0 on
pci 0:1.1 on
pci 0:1.2 on
pci 0:1.3 on
pci 0:1.5 off
pci 0:1.6 off
pci 1:0.0 on
pci 1:0.1 on
pci 1:0.2 on
pci 1:1.0 off
[..]
end
\end { verbatim}
\item \begin { verbatim} superio\end { verbatim}
SuperIO devices are basically handled like brigdes. They are taking
their driver code from \texttt { freebios2/src/superio/} . They don't
provide a PCI compatible configuration interface, but instead are ISA
PnP devices. Normally they are connected to a southbridge. If this is
the case, the \texttt { superio} section will be a subsection of the
\texttt { southbridge} section of the southbridge it is connected to.
Example:
\begin { verbatim}
2006-10-25 01:00:42 +02:00
superio nsc/pc87360 link 1
2003-11-22 16:15:47 +01:00
pnp 2e.0
pnp 2e.1
pnp 2e.2
pnp 2e.3
pnp 2e.4
pnp 2e.5
pnp 2e.6
pnp 2e.7
pnp 2e.8
pnp 2e.9
pnp 2e.a
register "com1" = "{ 1, 0, 0x3f8, 4} "
register "lpt" = "{ 1} "
end
\end { verbatim}
\end { itemize}
\newpage
2004-06-02 13:25:31 +02:00
\subsubsection { Mainboard specific configuration options}
2003-11-22 16:15:47 +01:00
2004-06-02 13:25:31 +02:00
The following options are commonly used in mainboard specific
2003-11-22 16:15:47 +01:00
configuration files.
They should be set using the \texttt { default} keyword:
\begin { itemize}
\item \begin { verbatim} HAVE_ HARD_ RESET\end { verbatim}
If set to \texttt { 1} , this option defines that there is a hard reset
function for this mainboard. This option is not defined per default.
\item \begin { verbatim} HAVE_ PIRQ_ TABLE\end { verbatim}
If set to \texttt { 1} , this option defines that there is an IRQ Table for
this mainboard. This option is not defined per default.
\item \begin { verbatim} IRQ_ SLOT_ COUNT\end { verbatim}
Number of IRQ slots. This option is not defined per default.
\item \begin { verbatim} HAVE_ MP_ TABLE\end { verbatim}
Define this option to build an MP table (v1.4). The default is not to
build an MP table.
\item \begin { verbatim} HAVE_ OPTION_ TABLE\end { verbatim}
Define this option to export a CMOS option table. The default is not to
export a CMOS option table.
\item \begin { verbatim} CONFIG_ SMP\end { verbatim}
Set this option to \texttt { 1} if the mainboard supports symmetric
multiprocessing (SMP). This option defaults to \texttt { 0} (no SMP).
\item \begin { verbatim} CONFIG_ MAX_ CPUS\end { verbatim}
If \begin { verbatim} CONFIG_ SMP\end { verbatim} is set, this option defines
the maximum number of CPUs (i.e. the number of CPU sockets) in the
system. Defaults to \texttt { 1} .
\item \begin { verbatim} CONFIG_ IOAPIC\end { verbatim}
Set this option to \texttt { 1} to enable IOAPIC support. This is
mandatory if you want to boot a 64bit Linux kernel on an AMD64 system.
\item \begin { verbatim} STACK_ SIZE\end { verbatim}
LinuxBIOS stack size. The size of the function call stack defaults to
\texttt { 0x2000} (8k).
\item \begin { verbatim} HEAP_ SIZE\end { verbatim}
LinuxBIOS heap size. The heap is used when LinuxBIOS allocates memory
with malloc(). The default heap size is \texttt { 0x2000} , but AMD64 boards
generally set it to \texttt { 0x4000} (16k)
\item \begin { verbatim} XIP_ ROM_ BASE\end { verbatim}
Start address of area to cache during LinuxBIOS execution directly from
ROM.
\item \begin { verbatim} XIP_ ROM_ SIZE\end { verbatim}
Size of area to cache during LinuxBIOS execution directly from ROM
\item \begin { verbatim} CONFIG_ COMPRESS\end { verbatim}
Set this option to \texttt { 1} for a compressed image. If set to
\texttt { 0} , the image is bigger but will start slightly faster (since no
decompression is needed).
\end { itemize}
\newpage
2004-02-10 18:30:04 +01:00
2003-11-22 16:15:47 +01:00
%
2004-02-10 18:30:04 +01:00
% 10. Tweaking the source code
2003-11-22 16:15:47 +01:00
%
2004-02-10 18:30:04 +01:00
2003-11-22 16:15:47 +01:00
\section { Tweaking the source code}
Besides configuring the existing code it is sometimes necessary or
2004-06-02 13:25:31 +02:00
desirable to tweak certain parts of LinuxBIOS by direct changes to the
2003-11-22 16:15:47 +01:00
code. This chapter covers some possible enhancements and changes that
2004-06-02 13:25:31 +02:00
are needed when porting LinuxBIOS to a new mainboard or just come
2003-11-22 16:15:47 +01:00
handy now and then.
\subsection { Hypertransport configuration}
Before LinuxBIOS is able to activate all CPUs and detect bridges
attached to these CPUs (and thus, see all devices attached to the
system) it has to initialize the coherent hypertransport devices.
The current algorithms to do coherent hypertransport initialization are
2004-06-02 13:25:31 +02:00
not fully, automatically evaluating the hypertransport chain graph.
2003-11-22 16:15:47 +01:00
Therefore the code needs to be adapted when porting LinuxBIOS to a new
2004-06-02 13:25:31 +02:00
AMD64 mainboard. An example arrangement of hypertransport devices
2003-11-22 16:15:47 +01:00
looks like this:
\begin { figure} [htb]
\centering
\includegraphics [scale=1.0] { hypertransport.pdf}
\caption { Example: Hypertransport Link Connections}
\label { fix:hypertransport}
\end { figure}
Each hypertransport device has one to three hypertransport links that
are used for device interconnection. These links are called LDT$ [ $ 012$ ] $ , or
accordingly UP, ACROSS, DOWN. Communication between the hypertransport
devices can be freely routed, honoring the physical wiring. Teaching the
coherent hypertransport initialization algorithm this wiring happens in
two steps.
\newpage
\begin { enumerate}
\item Setting outgoing connections
The algorithm needs to know which outgoing port of a CPU node is
connected to the directly succeeding node. This is done in
\texttt { freebios2/src/mainboard/$ < $ vendor$ > $ /$ < $ mainboard$ > $ /auto.c}
with a number of preprocessor defines (one define for two-node systems,
three defines for four-node systems).
The ports in question are flagged with a circle in the graph for
illustration. For the example graph above (all outgoing connections are
realized using LDT1/ACROSS) the defines are:
\begin { verbatim}
#define CONNECTION_ 0_ 1 ACROSS
#define CONNECTION_ 0_ 2 ACROSS
#define CONNECTION_ 1_ 3 ACROSS
\end { verbatim}
\item Describing routing information between CPUs.
There are basically three different message types for hypertransport
communication:
\begin { enumerate}
\item request packages
\item response packages
\item broadcast packages
\end { enumerate}
These three message types are routed using different hypertransport
ports. The routing information is written to the AMD K8 routing table.
In an Nnode system this routing table consists of 3*N*N entries , one
for each message type and for each possible CPU --> CPU communication. For
simplicity LinuxBIOS keeps the 3 routing entries for each CPU --> CPU
communication in one machine word. The routing table of each node looks
like this:
\begin { verbatim}
/* Routing Table for Node i
*
* F0: 0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c
* i: 0, 1, 2, 3, 4, 5, 6, 7
*
* [ 0: 3] Request Route
* [0] Route to this node
* [1] Route to Link 0
* [2] Route to Link 1
* [3] Route to Link 2
* [11: 8] Response Route
* [0] Route to this node
* [1] Route to Link 0
* [2] Route to Link 1
* [3] Route to Link 2
* [19:16] Broadcast route
* [0] Route to this node
* [1] Route to Link 0
* [2] Route to Link 1
* [3] Route to Link 2
*/
\end { verbatim}
The routing table is passed to the coherent hypertransport
initialization algorithm by defining a function called
\texttt { generate\_ row()} in \texttt { auto.c} :
\begin { verbatim}
static unsigned int generate_ row
(uint8_ t node, uint8_ t row, uint8_ t maxnodes)
\end { verbatim}
This function is trivial if there is only one CPU in the system, since
no routing has to be done:
\begin { verbatim}
static unsigned int generate_ row
(uint8_ t node, uint8_ t row, uint8_ t maxnodes)
{
return 0x00010101; /* default row entry */
}
\end { verbatim}
On a two-node system things look slightly more complicated. Since the
coherent hypertransport initialization algorithm works by consecutively
enabling CPUs, it contains routing information for driving the system
with one node and two nodes:
\begin { verbatim}
static unsigned int generate_ row
(uint8_ t node, uint8_ t row, uint8_ t maxnodes)
{
uint32_ t ret=0x00010101; /* default row entry */
static const unsigned int rows_ 2p[2][2] = {
{ 0x00050101, 0x00010404 } ,
{ 0x00010404, 0x00050101 }
} ;
if(maxnodes>2) maxnodes=2;
if (!(node>=maxnodes || row>=maxnodes)) {
ret=rows_ 2p[node][row];
}
return ret;
}
\end { verbatim}
Systems with four nodes have to contain routing information for one, two
and four-node setups:
\begin { verbatim}
static unsigned int generate_ row
(uint8_ t node, uint8_ t row, uint8_ t maxnodes)
{
uint32_ t ret=0x00010101; /* default row entry */
static const unsigned int rows_ 2p[2][2] = {
{ 0x00030101, 0x00010202 } ,
{ 0x00010202, 0x00030101 }
} ;
static const unsigned int rows_ 4p[4][4] = {
{ 0x00070101, 0x00010202, 0x00030404, 0x00010204 } ,
{ 0x00010202, 0x000b0101, 0x00010208, 0x00030808 } ,
{ 0x00030808, 0x00010208, 0x000b0101, 0x00010202 } ,
{ 0x00010204, 0x00030404, 0x00010202, 0x00070101 }
} ;
if (!(node>=maxnodes || row>=maxnodes)) {
if (maxnodes==2)
ret=rows_ 2p[node][row];
if (maxnodes==4)
ret=rows_ 4p[node][row];
}
return ret;
}
\end { verbatim}
\end { enumerate}
\subsection { DRAM configuration}
Setting up the RAM controller(s) is probably the most complex part of
LinuxBIOS. Basically LinuxBIOS serially initializes all RAM controllers
in the system, using SPDROM (serial presence detect) data to set
timings, size and other properties. The SPD data is usually read
utilizing the I2C SMBUS interface of the southbridge.
There is one central data structure that describes the RAM controllers
2004-06-02 13:25:31 +02:00
available on an AMD64 system and the associated devices:
2003-11-22 16:15:47 +01:00
\begin { verbatim}
struct mem_ controller {
unsigned node_ id;
device_ t f0, f1, f2, f3;
uint8_ t channel0[4];
uint8_ t channel1[4];
} ;
\end { verbatim}
2004-06-02 13:25:31 +02:00
Available mainboard implementations and CPUs create the need to add
2003-11-22 16:15:47 +01:00
special setup code to RAM initialization in a number of places.
LinuxBIOS provides hooks to easily add code in these places without
having to change the generic code. Whether these hooks have to be used
2004-06-02 13:25:31 +02:00
depends on the mainboard design. In many cases the functions executed
2003-11-22 16:15:47 +01:00
by the hooks just carry out trivial default settings or they are even
empty.
2004-06-02 13:25:31 +02:00
Some mainboard/CPU combinations need to trigger an additional memory
2003-11-22 16:15:47 +01:00
controller reset before the memory can be initialized properly. This is,
for example, used to get memory working on preC stepping AMD64
processors. LinuxBIOS provides two hooks for triggering onboard memory
reset logic:
\begin { itemize}
\item \begin { verbatim} static void memreset_ setup(void)\end { verbatim}
\item \begin { verbatim} static void memreset(int controllers, const struct
mem_ controller *ctrl)\end { verbatim}
\end { itemize}
2004-06-02 13:25:31 +02:00
Some mainboards utilize an SMBUS hub or possibly other mechanisms to
2003-11-22 16:15:47 +01:00
allow using a large number of SPDROMs and thus ram sockets. The result
is that only the SPDROM information of one cpu node is visible at a
time. The following function, defined in \texttt { auto.c} , is called every time
before a memory controller is initialized and gets the memory controller
information of the next controller as a parameter:
\begin { verbatim}
static inline void activate_ spd_ rom (const struct mem_ controller *ctrl)
\end { verbatim}
The way SMBUS hub information is coded into the \texttt { mem\_ controller}
2004-06-02 13:25:31 +02:00
structure is mainboard implementation specific and not
2003-11-22 16:15:47 +01:00
described here. See \texttt { freebios2/src/mainboard/amd/quartet/auto.c}
for an example.
LinuxBIOS folks have agreed on SPD data being the central information
2004-06-02 13:25:31 +02:00
source for RAM specific information. But not all mainboards/RAM
modules feature a physical SPD ROM. To still allow an easy to use SPD
2003-11-22 16:15:47 +01:00
driven setup, there is a hook that abstracts reading the SPD ROM
ingredients that are used by the memory initialization mechanism:
\begin { verbatim}
static inline int spd_ read_ byte(unsigned device, unsigned address)
\end { verbatim}
This function, defined in \texttt { auto.c} , directly maps it's calls to
\texttt { smbus\_ read\_ byte()} calls if SPD ROM information is read via
the I2C SMBUS:
\begin { verbatim}
static inline int spd_ read_ byte(unsigned device, unsigned address)
{
return smbus_ read_ byte(device & 0xff, address);
}
\end { verbatim}
If there is no SPD ROM available in the system design, this function
keeps an array of SPD ROM information hard coded per logical RAM module.
2009-04-17 18:18:02 +02:00
It returns the faked' SPD ROM information using device and address
2003-11-22 16:15:47 +01:00
as indices to this array.
\subsection { IRQ Tables}
2004-06-02 13:25:31 +02:00
Mainboards that provide an IRQ table should have the following two
2003-11-22 16:15:47 +01:00
variables set in their \texttt { Config.lb} file:
\begin { verbatim}
default HAVE_ PIRQ_ TABLE=1
default IRQ_ SLOT_ COUNT=7
\end { verbatim}
2004-06-02 13:25:31 +02:00
This will make LinuxBIOS look for the file \\
\texttt { freebios2/src/mainboard/<vendor>/<mainboard>/irq\_ tables.c} which
2003-11-22 16:15:47 +01:00
contains the source code definition of the IRQ table. LinuxBIOS corrects
small inconsistencies in the IRQ table during startup (checksum and
number of entries), but it is not yet writing IRQ tables in a completely
dynamic way.
\textbf { NOTE:} To get Linux to understand and actually use the IRQ
table, it is not always a good idea to specify the vendor and device id
of the actually present interrupt router device. Linux 2.4 for example
does not know about the interrupt router of the AMD8111 southbridge. In
such cases it is advised to choose the vendor/device id of a compatible
device that is supported by the Linux kernel. In case of the AMD8111
interrupt router it is advised to specify the AMD768/Opus interrupt
controller instead (vendor id=\texttt { 0x1022} , device id=\texttt { 0x7443} )
\subsection { MP Tables}
LinuxBIOS contains code to create MP tables conforming the
Multiprocessor Specification V1.4. To include an MP Table in a LinuxBIOS
image, the following configuration variables have to be set (in the
mainboard specific configuration file
\texttt { freebios2/src/mainboard/<vendor><mainboard>/Config.lb} ):
\begin { verbatim}
default CONFIG_ SMP=1
default CONFIG_ MAX_ CPUS=1 # 2,4,..
default HAVE_ MP_ TABLE=1
\end { verbatim}
LinuxBIOS will then look for a function for setting up the MP table in
the file \texttt { freebios2/src/mainboard<vendor>/<mainboard>/mptable.c} :
\begin { verbatim}
void *smp_ write_ config_ table(void *v, unsigned long * processor_ map)
\end { verbatim}
MP Table generation is still somewhat static, i.e. changing the bus
numbering will force
you to adopt the code in mptable.c. This is subject to change in future
revisions.
2004-02-10 17:53:55 +01:00
\subsection { ACPI Tables}
There is initial ACPI support in LinuxBIOS now. Currently the only gain with
this is the ability to use HPET timers in Linux. To achieve this, there is a
framework that can generate the following tables:
\begin { itemize}
\item RSDP
\item RSDT
\item MADT
\item HPET
\end { itemize}
To enable ACPI in your LinuxBIOS build, add the following lines to your
configuration files:
\begin { verbatim}
uses HAVE_ ACPI_ TABLES
[..]
option HAVE_ ACPI_ TABLES=1
\end { verbatim}
To keep Linux doing it's pci ressource allocation based on IRQ tables and MP
tables, you have to specify the kernel parameter \texttt { pci=noacpi} otherwise
your PCI devices won't get interrupts.
It's likely that more ACPI support will follow, when there is need for certain
features.
2003-11-22 16:15:47 +01:00
\subsection { POST}
LinuxBIOS has three different methods of handling POST codes. They can
be triggered using configuration file options.
\begin { itemize}
\item
\emph { Ignore POST completely} . No early code debugging is possible with
this setting. Set the configuration variable \texttt { NO\_ POST} to
\texttt { 1} to switch off all POST handling in LinuxBIOS.
\item
\emph { Normal IO port 80 POST} . This is the default behavior of
LinuxBIOS. No configuration variables have to be set. To be able to see
port 80 POST output, you need a POST expansion card for ISA or PCI. Port
80 POST allows simple debugging without any other output method
available (serial interface or VGA display)
\item
\emph { Serial POST} .
This option allows to push POST messages to the serial interface instead
of using IO ports. \textbf { NOTE:} The serial interface has to be
initialized before serial POST can work. To use serial POST, set the
configuration variable \texttt { CONFIG\_ SERIAL\_ POST} to the value 1.
\end { itemize}
\subsection { HDT Debugging}
If you are debugging your LinuxBIOS code with a Hardware Debug Tool
(HDT), you can find the source code line for a given physical EIP
address as follows: Look the address up in the file linuxbios.map. Then
search the label Lxx in the file auto.inc created by romcc. The original
source code file and line number is mentioned in auto.inc.
\subsection { Device Drivers}
With only a few data structures LinuxBIOS features a simple but flexible
device driver interface. This interface is not intended for autonomously
driving the devices but to initialize all system components so that they
can be used by the booted operating system.
Since nowadays most systems are PCI centric, the data structures used
are tuned towards (onboard and expansion bus) PCI devices. Each driver
consists of at least two structures.
The \texttt { pci\_ driver} structure maps PCI vendor/device id pairs to a
second structure that describes a set of functions that together
initialize and operate the device:
\begin { verbatim}
static void adaptec_ scsi_ init(struct device *dev)
{
[..]
}
static struct device_ operations lsi_ scsi_ ops = {
.read_ resources = pci_ dev_ read_ resources,
.set_ resources = pci_ dev_ set_ resources,
.enable_ resources = pci_ dev_ enable_ resources,
.init = lsi_ scsi_ init,
.scan_ bus = 0,
} ;
static struct pci_ driver lsi_ scsi_ driver _ _ pci_ driver = {
.ops = & lsi_ scsi_ ops,
.vendor = 0xXXXX,
.device = 0xXXXX,
} ;
\end { verbatim}
By separating the two structures above, M:N relations between compatible
devices and drivers can be described. The driver source code containing
above data structures and code have to be added to a LinuxBIOS image
2004-06-02 13:25:31 +02:00
using the driver keyword in the mainboard specific configuration file \\
2003-11-22 16:15:47 +01:00
\texttt { freebios2/src/mainboard/<vendor>/<mainboard>/Config.lb} :
\begin { verbatim}
driver lsi_ scsi.o
\end { verbatim}
\subsection { Bus Bridges}
Currently all bridges supported in the LinuxBIOS2 tree are transparent
bridges. This means, once the bridge is initialized, it's remote devices
are visible on one of the PCI buses without special probing. LinuxBIOS
supports also bridges that are nontransparent. The driver support code
can provide a \texttt { scan\_ bus} function to scan devices behind the bridge.
\subsection { CPU Reset}
When changing speed and width of hypertransport chain connections
LinuxBIOS has to either assert an LDTSTOP or a reset to make the changes
become active. Additionally Linux can do a firmware reset, if LinuxBIOS
provides the needed infrastructure. To use this capability, define the
option \texttt { HAVE\_ HARD\_ RESET} and add an object file specifying the
reset code in your mainboard specific configuration file
\texttt { freebios2/src/mainboard/$ < $ vendor$ > $ /$ < $ mainboard$ > $ /Config.lb} :
\begin { verbatim}
default HAVE_ HARD_ RESET=1
object reset.o
\end { verbatim}
The C source file \texttt { reset.c} (resulting in \texttt { reset.o}
during compilation) shall define the following function to take care
of the system reset:
\begin { verbatim}
void hard_ reset(void);
\end { verbatim}
See \texttt { freebios2/src/mainboard/arima/hdama/reset.c} for an example
implementation.
\newpage
%
2004-02-10 18:30:04 +01:00
% 11. LinuxBIOS Internals
2003-11-22 16:15:47 +01:00
%
\section { LinuxBIOS Internals}
This chapter covers some of the internal structures and algorithms of
LinuxBIOS that have not been mentioned so far.
\subsection { Code Flow}
\begin { figure} [htb]
\centering
\includegraphics [scale=0.7] { codeflow.pdf}
\caption { LinuxBIOS rough Code Flow}
\label { fix:codeflow}
\end { figure}
\newpage
\subsection { Fallback mechanism}
LinuxBIOS provides a mechanism to pack two different LinuxBIOS builds
within one LinuxBIOS ROM image. Using the system CMOS memory LinuxBIOS
determines whether the last boot with a default image succeeded and
boots a failsafe image on failure. This allows insystem testing without
the risk to render the system unusable. See
\texttt { freebios2/src/mainboard/arima/hdama/failover.c} for example
code. The fallback mechanism can be used with the \texttt { cmos\_ util} .
\subsection { (Un) Supported Standards}
LinuxBIOS supports the following standards
\begin { itemize}
\item Multiprocessing Specification (MPSPEC) 1.4
2004-02-10 17:53:55 +01:00
\item IRQ Tables (PIRQ)
\item ACPI (initial support on AMD64)
2003-11-22 16:15:47 +01:00
\item Elf Booting
\end { itemize}
However, the following standards are not supported until now, and will
probably not be supported in future revisions:
\begin { itemize}
\item APM
\end { itemize}
\subsection { LinuxBIOS table}
LinuxBIOS stores information about the system in a data structure called
the LinuxBIOS table. This table can be read under Linux using the tool
lxbios from the Lawrence Livermore National Laboratory.
Get more information about lxbios and the utility itself at
\url { http://www.llnl.gov/linux/lxbios/lxbios.html}
\subsection { ROMCC limitations}
ROMCC, part of the LinuxBIOS project, is a C compiler that translates to
completely rommable code. This means the resulting code does not need
any memory to work. This is one of the major improvements in LinuxBIOS
V2, since it allows almost all code to be written in C. DRAM
initialization can be factored and reused more easily among mainboards
and platforms.
Since no memory is available during this early initialization point,
2004-06-02 13:25:31 +02:00
romcc has to map all used variables in registers for the time being.
2003-11-22 16:15:47 +01:00
Same applies for their stack usage. Generally the less registers are
used up by the algorithms, the better code can be factored, resulting in
a smaller object size. Since getting the best register usage is an NP
hard problem, some heuristics are used to get reasonable translation
time. If you run out of registers during compilation, try to refactor
your code.
\subsection { CMOS handling}
2004-06-02 13:25:31 +02:00
LinuxBIOS can use the mainboard's CMOS memory to store information
2003-11-22 16:15:47 +01:00
defined in a data structure called the CMOS table . This information
contains serial line speed, fallback boot control, output verbosity,
default boot device, ECC control, and more. It can be easily enhanced by
enhancing the CMOS table. This table, if present, is found at
\texttt { freebios2/src/mainboard/$ < $ vendor$ > $ /$ < $ mainboard$ > $ /cmos.layout} .
It describes the available options, their possible values and their
position within the CMOS memory. The layout file looks as follows:
\begin { verbatim}
# startbit length config configID name
[..]
392 3 e 5 baud_ rate
[..]
# configid value human readable description
5 0 115200
5 1 57600
5 2 38400
5 3 19200
5 4 9600
5 5 4800
5 6 2400
5 7 1200
\end { verbatim}
To change CMOS values from a running Linux system, use the
\texttt { cmos\_ util} , provided by Linux Networks as part of the LinuxBIOS
utilities suite. Get it at
\textit { ftp://ftp.lnxi.com/pub/linuxbios/utilities/}
\subsection { Booting Payloads}
LinuxBIOS can load a payload binary from a Flash device or IDE. This
payload can be a boot loader, like FILO or Etherboot, a kernel image, or
any other static ELF binary.
To create a Linux kernel image, that is bootable in LinuxBIOS, you have
to use mkelfImage. The command line I used, looks like follows:
\begin { verbatim}
2009-04-17 18:18:02 +02:00
objdir/sbin/mkelfImage t bzImagei386 kernel /boot/vmlinuz \
commandline="console=ttyS0,115200 root=/dev/hda3" \
initrd=/boot/initrd output vmlinuz.elf
2003-11-22 16:15:47 +01:00
\end { verbatim}
This will create the file \texttt { vmlinuz.elf} from a distribution
kernel, console redirected to the serial port and using an initial
ramdisk.
\subsection { Kernel on dhcp/tftp}
One possible scenario during testing is that you keep your kernel (or
any additional payload) on a different machine on the network. This can
quickly be done using a DHCP and TFTP server.
Use for example following \texttt { /etc/dhcpd.conf} (adapt to your
network):
\begin { verbatim}
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.0 192.168.1.31;
option broadcastaddress 192.168.1.255;
}
ddnsupdatestyle adhoc;
host hammer12 {
hardware ethernet 00:04:76:EA:64:31;
fixedaddress 192.168.1.24;
filename "vmlinuz.elf";
}
\end { verbatim}
Additionally you have to run a \texttt { tftp} server. You can start one
using \texttt { inetd} . To do this, you have to remove the comment from
the following line in \texttt { /etc/inetd.conf} :
\begin { verbatim}
tftp dgram udp wait root /usr/sbin/in.tftpd in.tftpd -s /tftpboot
\end { verbatim}
2004-06-02 13:25:31 +02:00
Then put your kernel image \texttt { vmlinuz.elf} in \texttt { /tftpboot} on
2003-11-22 16:15:47 +01:00
the \texttt { tftp} server.
\newpage
%
2004-02-10 18:30:04 +01:00
% 12. Advanced Device Initialization Mechanisms
%
\section { Advanced Device Initialization Mechanisms}
Like software, today's hardware is getting more and more complex. To
stay flexible many hardware vendors start breaking hardware
2004-06-02 13:25:31 +02:00
compatibility to old standards like VGA. Thus, VGA is still supported by
2004-02-10 18:30:04 +01:00
most cards, but emulation has to be enabled by the firmware for the
device to operate properly. Also, many expansion cards are small
discrete systems that have to initialize attached ram, download
controller firmware and similar. Without this initialization, an
operating system can not take advantage of the hardware, so there needs
to be a way to address this issue. There are several alternatives:
\subsection { Native LinuxBIOS Support}
For some devices (ie Trident Cyberblade 3d) there is native LinuxBIOS
support This means there is a small driver bound to the PCI id of the
device that is called after PCI device ressources are allotted.
PROs:
\begin { itemize}
\item open source
\item minimal driver
\item early control
\end { itemize}
CONs:
\begin { itemize}
\item need an additional driver
\item viable for onboard devices only
\item not flexible for pci cards
\end { itemize}
\subsection { Using Native Linux Support}
A simple way of getting a whole lot of drivers available for LinuxBIOS
is to reuse Linux drivers by putting a Linux kernel to flash. This
works, because no drivers are needed to get the Linux kernel (as opposed
to store the kernel on a harddisk connected to isa/scsi/raid storage)
PROs:
\begin { itemize}
\item large number of open source drivers
\end { itemize}
CONs:
\begin { itemize}
\item need Linux in Flash (BLOAT!)
\item drivers expect devices to be initialized (LSI1020/1030)
\item Linux only
\item large flash needed (4MBit minimum, normal operations 8+ MBit)
\end { itemize}
\subsection { Running X86 Option ROMs}
Especially SCSI/RAID controllers and graphics adapters come with a
special option rom. This option rom usually contains x86 binary code
that uses a legacy PCBIOS interface for device interaction. If this code
gets executed, the device becomes operable in Linux and other operating
systems.
PROs:
\begin { itemize}
\item really flexible
\item no need for additional drivers on firmware layer
\item large number of supported devices
\end { itemize}
CONs:
\begin { itemize}
\item non-x86 platforms need complex emulation
\item x86 platforms need legacy API
\item outdated concept
\end { itemize}
\subsection { Running Open Firmware Option ROMs}
Some PCI devices come with open firmware option roms. These devices are
normally found in computers from SUN, Apple or IBM. Open Firmware is a
instruction set architecture independent firmware standard that allows
device specific initialization using simple, small, but flexible
bytecode that runs with minimal footprint on all architectures that have
an Open Firmware implementation.
There is a free Open Firmware implementation available, called OpenBIOS,
that runs on top of LinuxBIOS. See www.openbios.org
PROs:
\begin { itemize}
\item architecture independence
\item small footprint
\item clean concept, less bugs
\end { itemize}
CONs:
\begin { itemize}
\item only small number of devices come with OpenFirmware capable option roms
\end { itemize}
2009-04-17 18:18:02 +02:00
%
% 13 image types
%
\section { Image types}
There used to be one image type for LinuxBIOS, as described above. Since this paper was written (2004) there have been many changes. First, the name
was changed to coreboot, for many reasons. Second, Ying-Hai Liu, then of AMD, now of Sun, added Cache As Ram support (CAR) for many AMD CPUs, which both simplified and complicated things. Simplification came with the removal of romcc; complication came with the addition of new ways to build.
There are two big additions to the build process and, furthermore, more than two new CONFIG variables to control them.
\begin { itemize}
\item \begin { verbatim} USE_ DCACHE_ RAM\end { verbatim}
Set to \texttt { 1} to use Cache As Ram (CAR). Defaults to \texttt { 0}
\item \begin { verbatim} CONFIG_ USE_ INIT\end { verbatim}
Set to \texttt { 1} to figure this out. Defaults to \texttt { 0}
\item \begin { verbatim} CONFIG_ USE_ PRINTK_ IN_ CAR\end { verbatim}
Set to \texttt { 1} to use printk, instead of the primitive print functions, in CAR. Defaults to \texttt { 0}
\end { itemize}
Before going over the new image types, derived from v3, we will quickly review the standard v2 image types. We are hoping this review will
aid comprehension.
A coreboot rom file consists of one or more \textit { images} . All images consist of a part that runs in ROM, and a part that runs in RAM. The RAM can be in compressed form and is decompressed when needed by the ROM code. The main function of the ROM code is to get memory working. Both ROM and RAM consist of a very small amount of assembly code and mostly C code.
\subsection { romcc images}
ROMCC images are so-called because C code for the ROM part is compiled with romcc. romcc is an optimizing C compiler which compiles one, and only
one file; to get more than one file, one must include the C code via include statements. The main ROM code .c file is usually called auto.c.
\subsubsection { how it is built}
Romcc compiles auto.c to produce auto.inc. auto.inc is included in the main crt0.S, which is then preprocessed to produce crt0.s. The inclusion of files into crt0.S is controlled by the CRT0\_ INCLUDES variable. crt0.s is then assembled.
File for the ram part are compiled in a conventional manner.
The final step is linking. The use of named sections is used very heavily in coreboot to control where different bits of code go. The reset vector must go in the top 16 bytes. The start portion of the ROM code must go in the top 64K bytes, since most chipsets only enable this much ROM at startup time. Here is a quick look at a typical image:
\begin { verbatim}
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .ram PROGBITS ffff0000 001000 005893 00 WA 0 0 1
[ 2] .rom PROGBITS ffff5893 006893 00029d 00 AX 0 0 16
[ 3] .reset PROGBITS fffffff0 006ff0 000010 00 A 0 0 1
[ 4] .id PROGBITS ffffffd1 006fd1 00001f 00 A 0 0 1
[ 5] .shstrtab STRTAB 00000000 007000 000030 00 0 0 1
[ 6] .symtab SYMTAB 00000000 007170 000c30 10 7 37 4
[ 7] .strtab STRTAB 00000000 007da0 000bfd 00 0 0 1
\end { verbatim}
The only sections that get loaded into a ROM are the Allocated ones. We can see the .ram, .rom, .reset and .id sections.
\subsubsection { layout}
As we mentioned, the ROM file consists of multiple images. In the basic file, there are two full coreboot rom images. The build sequence for each is the same, and in fact the ldscript.ld files are almost identical. The only difference is in a few makefile variables, generated by the config tool.
\begin { itemize}
\item PAYLOAD\_ SIZE. Each image may have a different payload size.
\item \_ ROMBASE Each image must have a different base in rom.
\item \_ RESET Unclear what this is used for.
\item \_ EXCEPTION\_ VECTORS where an optional IDT might go.
\item USE\_ OPTION\_ TABLE if set, an option table section will be linked in.
\item CONFIG\_ ROM\_ PAYLOAD\_ START This is the soon-to-be-deprecated way of locating a payload. cbfs eliminates this.
\item USE\_ FALLBACK\_ IMAGE Whether this is a fallback or normal image
\item ROM\_ SECTION\_ SIZE Essentially, the payload size. Soon to be deprecated.
\item ROM\_ IMAGE\_ SIZE Size of this image (i.e. fallback or normal image)
\item ROM\_ SIZE Total size of the ROM
\item XIP\_ RAM\_ BASE The start of eXecute In Place code. XIP allows for not copying code to ram, but just running it from ROM.
\end { itemize}
Each image (normal or fallback) is built completely independently and does not get linked to the other. They are assembled into one ROM image by the (soon to be deprecated) buildrom tool, or by the cbfs tool.
\subsubsection { boot sequence}
We boot and start at fffffff0. We then jump to the entry point at \_ start. Protected\_ start does some machine init and an lgdt and jumps to \_ \_ protected\_ start, at which point we are in protected mode. The code does a bit more machine setup and then starts executing the romcc code.
If fallback has been built in, some setup needs to be done. On some machines, it is extensive. Full rom decoding must be enabled. This may in turn require additional PCI setup to enable decoding to be enabled (!). To decided which image to use, hardware registers (cold boot on the Opteron) or CMOS are checked. Finally, once the image to use has been decided, a jmp is performed, viz:
\begin { verbatim}
/* This is the primary cpu how should I boot? */
else if (do_ normal_ boot()) {
goto normal_ image;
}
else {
goto fallback_ image;
}
normal_ image:
_ _ asm_ _ volatile ("jmp _ _ normal_ image"
: /* outputs */
: "a" (bist), "b" (cpu_ init_ detectedx) /* inputs */
);
fallback_ image:
#if HAVE_ FAILOVER_ BOOT==1
_ _ asm_ _ volatile ("jmp _ _ fallback_ image"
: /* outputs */
: "a" (bist), "b" (cpu_ init_ detectedx) /* inputs */
)
#endif
;
\end { verbatim}
How does the fallback image get the symbol for normal entry? Via magic in the ldscript.ld -- remember, the images are not linked to each other.
\subsection { car images}
\subsubsection { how it is built}
\subsubsection { layout}
\subsubsection { boot sequence}
We boot and start at fffffff0. We then jump to the entry point at protected\_ start (a clear misnomer, since we're not in protected mode at that
point). Protected\_ start does an lgdt and jumps to \_ \_ protected\_ start, at which point we are in protected mode.
\subsection { car + config\_ use\_ init images}
\subsubsection { how it is built}
\subsubsection { layout}
\subsubsection { boot sequence}
\subsection { failover}
2004-02-10 18:30:04 +01:00
%
2009-04-17 18:18:02 +02:00
% 14 Glossary
2003-11-22 16:15:47 +01:00
%
\section { Glossary}
\begin { itemize}
\item payload
2009-04-17 18:18:02 +02:00
LinuxBIOS only cares about low level machine initialization, but also has
2003-11-22 16:15:47 +01:00
very simple mechanisms to boot a file either from FLASHROM or IDE. That
file, possibly a Linux Kernel, a boot loader or Etherboot, are called
payload, since it is the first software executed that does not cope with
pure initialization.
\item flash device
Flash devices are commonly used in all different computers since unlike
ROMs they can be electronically erased and reprogrammed.
\end { itemize}
\newpage
%
2004-02-10 18:30:04 +01:00
% 14 Bibliography
2003-11-22 16:15:47 +01:00
%
\section { Bibliography}
\subsection { Additional Papers on LinuxBIOS}
\begin { itemize}
\item { \small
\textit { \url { http://www.linuxnetworx.com/products/linuxbios_ white_ paper.pdf} }
}
\item
\textit { \url { http://www.linuxbios.org/papers/} }
\item
\textit { \url { http://www.lysator.liu.se/upplysning/fa/linuxbios.pdf} }
\item
\textit { \url { http://portal.acm.org/citation.cfm?id=512627} }
\end { itemize}
\subsection { Links}
\begin { itemize}
\item Etherboot: \textit { \url { http://www.etherboot.org/} }
\item Filo: \textit { \url { http://te.to/~ts1/filo/} }
\item OpenBIOS: \textit { \url { http://www.openbios.org/} }
\end { itemize}
\end { document}