| % |
| % 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$>$} |
| \date{June 2nd, 2004} |
| |
| \begin{document} |
| |
| \maketitle |
| |
| \thispagestyle{empty} |
| |
| \tableofcontents |
| |
| \newpage |
| |
| % |
| % 1 Abstract |
| % |
| |
| \section{Abstract} |
| |
| This document targets porting LinuxBIOS to new mainboards and creating |
| 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$>$}} |
| |
| |
| % |
| % 2 Changes |
| % |
| |
| \section{Changes} |
| \begin{itemize} |
| \item 2004/06/02 url and language fixes from Ken Fuchs $<$kfuchs@winternet.com$>$ |
| \item 2004/02/10 acpi and option rom updates |
| \item 2003/11/18 initial release |
| \end{itemize} |
| |
| |
| |
| % |
| % 3 What is LinuxBIOS |
| % |
| |
| \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. |
| |
| % |
| % 4 Build Requirements |
| % |
| |
| \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 |
| |
| % |
| % 5 Getting the Sources |
| % |
| |
| \section{Getting the Sources} |
| |
| The latest LinuxBIOS sources are available via CVS. The CVS repository |
| 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: |
| |
| { \small |
| \begin{verbatim} |
| $ cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/freebios login |
| \end{verbatim} |
| } |
| |
| Hit return when you are asked for a password. Then checkout (or update) |
| the freebios source tree as follows: |
| |
| { \small |
| \begin{verbatim} |
| $ cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/freebios co freebios2 |
| \end{verbatim} |
| } |
| |
| Once the source tree is checked out, it can be updated with: |
| |
| { \small |
| \begin{verbatim} |
| % cvs update Pd |
| \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. |
| |
| % |
| % 6 LinuxBIOS configuration overview |
| % |
| |
| \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 |
| \texttt{freebios2/targets/$<$vendor$>$/$<$mainboard$>$/}. Such |
| 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. |
| |
| \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 |
| 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. |
| |
| % |
| % 7 Building LinuxBIOS |
| % |
| |
| \section{Building LinuxBIOS} |
| One of the design goals for building LinuxBIOS was to keep object files |
| out of the source tree in a separate place. This is mandatory for |
| building parallel LinuxBIOS images for several distinct mainboards |
| 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 |
| instance for the AMD Solo Athlon64 mainboard enter: |
| |
| \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 |
| mainboard the default directory resides in |
| \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 |
| configuration file. The default filename for AMD's Solo mainboard is |
| \texttt{solo.rom}. |
| |
| % |
| % 8 Programming LinuxBIOS to flash memory |
| % |
| |
| \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) |
| \item \url{http://www.linux-mtd.infradead.org/} (Memory Technology Device Subsystem MTD) |
| \end{itemize} |
| |
| \newpage |
| |
| % |
| % 9 LinuxBIOS configuration |
| % |
| |
| \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 |
| Default configuration values can be set in the mainboard configuration |
| 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 |
| with an overridable default value. It is commonly used in mainboard |
| 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} |
| default CC="gcc m32" |
| \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 |
| set with the default statement in a mainboard configuration file. |
| 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. |
| |
| The firmware image specific configuration file can be found in \\ |
| \texttt{freebios2/targets/$<$vendor$>$/<mainboard$>$}. |
| |
| \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 |
| option LINUXBIOS_EXTRA_VERSION=".0Normal" |
| 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 |
| Mainboard specific configuration. See above examples about |
| 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 |
| \texttt{gcc m32} for compiling AMD64 LinuxBIOS images on an AMD64 |
| machine. |
| |
| \item \begin{verbatim}CONFIG_CHIP_CONFIGURE \end{verbatim} |
| |
| Use new \textit{chip\_configure} method for configuring (nonpci) |
| devices. Set to \texttt{1} for all AMD64 mainboards. |
| |
| \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 |
| your mainboard has CMOS memory and you want to use it to store |
| LinuxBIOS parameters (Loglevel, serial line speed, ...) |
| |
| \item \begin{verbatim}CONFIG_ROM_STREAM\end{verbatim} |
| |
| Boot image is located in ROM (as opposed to \texttt{CONFIG\_IDE\_STREAM}, which |
| 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. |
| |
| \item \begin{verbatim}LINUXBIOS_EXTRA_VERSION\end{verbatim} |
| |
| 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 |
| |
| \subsection{Mainboard specific configuration} |
| |
| Mainboard specific configuration files describe the onboard |
| mainboard components, i.e. bridges, number and type of CPUs. They also |
| 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. |
| |
| \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. |
| |
| \subsubsection{Mainboard specific keywords} |
| |
| The following statements are used in mainboard specific configuration |
| files: |
| |
| \begin{itemize} |
| \item \begin{verbatim}arch\end{verbatim} |
| |
| Sets the CPU architecture. This should be \texttt{i386} for AMD64 boards.\\ |
| 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 |
| depends "$(MAINBOARD)/auto.c" |
| action "$(CPP) I$(TOP)/src $(ROMCCPPFLAGS) $(CPPFLAGS) \ |
| $(MAINBOARD)/auto.c > ./auto.E" |
| end |
| makerule ./auto.inc |
| depends "./auto.E ./romcc" |
| action "./romcc mcpu=k8 O ./auto.E > auto.inc" |
| end |
| \end{verbatim} |
| |
| 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). |
| |
| \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. |
| 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 |
| 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 |
| additional \\ |
| parameters to the code handling the associated device. |
| 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. |
| \texttt{amd/amdk8} and a unique name (i.e \texttt{mc0}) \\ |
| Example: |
| |
| \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} |
| superio NSC/pc87360 link 1 |
| 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 |
| |
| \subsubsection{Mainboard specific configuration options} |
| |
| The following options are commonly used in mainboard specific |
| 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 |
| |
| % |
| % 10. Tweaking the source code |
| % |
| |
| \section{Tweaking the source code} |
| Besides configuring the existing code it is sometimes necessary or |
| desirable to tweak certain parts of LinuxBIOS by direct changes to the |
| code. This chapter covers some possible enhancements and changes that |
| are needed when porting LinuxBIOS to a new mainboard or just come |
| 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 |
| not fully, automatically evaluating the hypertransport chain graph. |
| Therefore the code needs to be adapted when porting LinuxBIOS to a new |
| AMD64 mainboard. An example arrangement of hypertransport devices |
| 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 |
| available on an AMD64 system and the associated devices: |
| |
| \begin{verbatim} |
| struct mem_controller { |
| unsigned node_id; |
| device_t f0, f1, f2, f3; |
| uint8_t channel0[4]; |
| uint8_t channel1[4]; |
| }; |
| \end{verbatim} |
| |
| Available mainboard implementations and CPUs create the need to add |
| 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 |
| depends on the mainboard design. In many cases the functions executed |
| by the hooks just carry out trivial default settings or they are even |
| empty. |
| |
| Some mainboard/CPU combinations need to trigger an additional memory |
| 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} |
| |
| Some mainboards utilize an SMBUS hub or possibly other mechanisms to |
| 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} |
| structure is mainboard implementation specific and not |
| 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 |
| source for RAM specific information. But not all mainboards/RAM |
| modules feature a physical SPD ROM. To still allow an easy to use SPD |
| 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. |
| It returns the ´faked' SPD ROM information using device and address |
| as indices to this array. |
| |
| |
| \subsection {IRQ Tables} |
| |
| Mainboards that provide an IRQ table should have the following two |
| variables set in their \texttt{Config.lb} file: |
| |
| \begin{verbatim} |
| default HAVE_PIRQ_TABLE=1 |
| default IRQ_SLOT_COUNT=7 |
| \end{verbatim} |
| |
| This will make LinuxBIOS look for the file \\ |
| \texttt{freebios2/src/mainboard/<vendor>/<mainboard>/irq\_tables.c} which |
| 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. |
| |
| \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. |
| |
| \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 |
| using the driver keyword in the mainboard specific configuration file \\ |
| \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 |
| |
| % |
| % 11. LinuxBIOS Internals |
| % |
| |
| \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 |
| \item IRQ Tables (PIRQ) |
| \item ACPI (initial support on AMD64) |
| \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, |
| romcc has to map all used variables in registers for the time being. |
| 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} |
| LinuxBIOS can use the mainboard's CMOS memory to store information |
| 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} |
| objdir/sbin/mkelfImage t bzImagei386 kernel /boot/vmlinuz \ |
| commandline="console=ttyS0,115200 root=/dev/hda3" \ |
| initrd=/boot/initrd output vmlinuz.elf |
| \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} |
| |
| Then put your kernel image \texttt{vmlinuz.elf} in \texttt{/tftpboot} on |
| the \texttt{tftp} server. |
| |
| |
| \newpage |
| |
| % |
| % 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 |
| compatibility to old standards like VGA. Thus, VGA is still supported by |
| 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} |
| |
| |
| % |
| % 13 Glossary |
| % |
| |
| \section{Glossary} |
| \begin{itemize} |
| \item payload |
| |
| LinuxBIOS only cares about lowlevel machine initialization, but also has |
| 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 |
| |
| % |
| % 14 Bibliography |
| % |
| |
| \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} |