Blame Documentation/dtc-paper.tex

Packit Service 87beb7
\documentclass[a4paper,twocolumn]{article}
Packit Service 87beb7
Packit Service 87beb7
\usepackage{abstract}
Packit Service 87beb7
\usepackage{xspace}
Packit Service 87beb7
\usepackage{amssymb}
Packit Service 87beb7
\usepackage{latexsym}
Packit Service 87beb7
\usepackage{tabularx}
Packit Service 87beb7
\usepackage[T1]{fontenc}
Packit Service 87beb7
\usepackage{calc}
Packit Service 87beb7
\usepackage{listings}
Packit Service 87beb7
\usepackage{color}
Packit Service 87beb7
\usepackage{url}
Packit Service 87beb7
Packit Service 87beb7
\title{Device trees everywhere}
Packit Service 87beb7
Packit Service 87beb7
\author{David Gibson \texttt{<{dwg}{@}{au1.ibm.com}>}\\
Packit Service 87beb7
  Benjamin Herrenschmidt \texttt{<{benh}{@}{kernel.crashing.org}>}\\
Packit Service 87beb7
  \emph{OzLabs, IBM Linux Technology Center}}
Packit Service 87beb7
Packit Service 87beb7
\newcommand{\R}{\textsuperscript{\textregistered}\xspace}
Packit Service 87beb7
\newcommand{\tm}{\textsuperscript{\texttrademark}\xspace}
Packit Service 87beb7
\newcommand{\tge}{$\geqslant$}
Packit Service 87beb7
%\newcommand{\ditto}{\textquotedbl\xspace}
Packit Service 87beb7
Packit Service 87beb7
\newcommand{\fixme}[1]{$\bigstar$\emph{\textbf{\large #1}}$\bigstar$\xspace}
Packit Service 87beb7
Packit Service 87beb7
\newcommand{\ppc}{\mbox{PowerPC}\xspace}
Packit Service 87beb7
\newcommand{\of}{Open Firmware\xspace}
Packit Service 87beb7
\newcommand{\benh}{Ben Herrenschmidt\xspace}
Packit Service 87beb7
\newcommand{\kexec}{\texttt{kexec()}\xspace}
Packit Service 87beb7
\newcommand{\dtbeginnode}{\texttt{OF\_DT\_BEGIN\_NODE\xspace}}
Packit Service 87beb7
\newcommand{\dtendnode}{\texttt{OF\_DT\_END\_NODE\xspace}}
Packit Service 87beb7
\newcommand{\dtprop}{\texttt{OF\_DT\_PROP\xspace}}
Packit Service 87beb7
\newcommand{\dtend}{\texttt{OF\_DT\_END\xspace}}
Packit Service 87beb7
\newcommand{\dtc}{\texttt{dtc}\xspace}
Packit Service 87beb7
\newcommand{\phandle}{\texttt{linux,phandle}\xspace}
Packit Service 87beb7
\begin{document}
Packit Service 87beb7
Packit Service 87beb7
\maketitle
Packit Service 87beb7
Packit Service 87beb7
\begin{abstract}
Packit Service 87beb7
  We present a method for booting a \ppc{}\R Linux\R kernel on an
Packit Service 87beb7
  embedded machine.  To do this, we supply the kernel with a compact
Packit Service 87beb7
  flattened-tree representation of the system's hardware based on the
Packit Service 87beb7
  device tree supplied by Open Firmware on IBM\R servers and Apple\R
Packit Service 87beb7
  Power Macintosh\R machines.
Packit Service 87beb7
Packit Service 87beb7
  The ``blob'' representing the device tree can be created using \dtc
Packit Service 87beb7
  --- the Device Tree Compiler --- that turns a simple text
Packit Service 87beb7
  representation of the tree into the compact representation used by
Packit Service 87beb7
  the kernel.  The compiler can produce either a binary ``blob'' or an
Packit Service 87beb7
  assembler file ready to be built into a firmware or bootwrapper
Packit Service 87beb7
  image.
Packit Service 87beb7
Packit Service 87beb7
  This flattened-tree approach is now the only supported method of
Packit Service 87beb7
  booting a \texttt{ppc64} kernel without Open Firmware, and we plan
Packit Service 87beb7
  to make it the only supported method for all \texttt{powerpc}
Packit Service 87beb7
  kernels in the future.
Packit Service 87beb7
\end{abstract}
Packit Service 87beb7
Packit Service 87beb7
\section{Introduction}
Packit Service 87beb7
Packit Service 87beb7
\subsection{OF and the device tree}
Packit Service 87beb7
Packit Service 87beb7
Historically, ``everyday'' \ppc machines have booted with the help of
Packit Service 87beb7
\of (OF), a firmware environment defined by IEEE1275 \cite{IEEE1275}.
Packit Service 87beb7
Among other boot-time services, OF maintains a device tree that
Packit Service 87beb7
describes all of the system's hardware devices and how they're
Packit Service 87beb7
connected.  During boot, before taking control of memory management,
Packit Service 87beb7
the Linux kernel uses OF calls to scan the device tree and transfer it
Packit Service 87beb7
to an internal representation that is used at run time to look up
Packit Service 87beb7
various device information.
Packit Service 87beb7
Packit Service 87beb7
The device tree consists of nodes representing devices or
Packit Service 87beb7
buses\footnote{Well, mostly.  There are a few special exceptions.}.
Packit Service 87beb7
Each node contains \emph{properties}, name--value pairs that give
Packit Service 87beb7
information about the device.  The values are arbitrary byte strings,
Packit Service 87beb7
and for some properties, they contain tables or other structured
Packit Service 87beb7
information.
Packit Service 87beb7
Packit Service 87beb7
\subsection{The bad old days}
Packit Service 87beb7
Packit Service 87beb7
Embedded systems, by contrast, usually have a minimal firmware that
Packit Service 87beb7
might supply a few vital system parameters (size of RAM and the like),
Packit Service 87beb7
but nothing as detailed or complete as the OF device tree.  This has
Packit Service 87beb7
meant that the various 32-bit \ppc embedded ports have required a
Packit Service 87beb7
variety of hacks spread across the kernel to deal with the lack of
Packit Service 87beb7
device tree.  These vary from specialised boot wrappers to parse
Packit Service 87beb7
parameters (which are at least reasonably localised) to
Packit Service 87beb7
CONFIG-dependent hacks in drivers to override normal probe logic with
Packit Service 87beb7
hardcoded addresses for a particular board.  As well as being ugly of
Packit Service 87beb7
itself, such CONFIG-dependent hacks make it hard to build a single
Packit Service 87beb7
kernel image that supports multiple embedded machines.
Packit Service 87beb7
Packit Service 87beb7
Until relatively recently, the only 64-bit \ppc machines without OF
Packit Service 87beb7
were legacy (pre-POWER5\R) iSeries\R machines.  iSeries machines often
Packit Service 87beb7
only have virtual IO devices, which makes it quite simple to work
Packit Service 87beb7
around the lack of a device tree.  Even so, the lack means the iSeries
Packit Service 87beb7
boot sequence must be quite different from the pSeries or Macintosh,
Packit Service 87beb7
which is not ideal.
Packit Service 87beb7
Packit Service 87beb7
The device tree also presents a problem for implementing \kexec.  When
Packit Service 87beb7
the kernel boots, it takes over full control of the system from OF,
Packit Service 87beb7
even re-using OF's memory.  So, when \kexec comes to boot another
Packit Service 87beb7
kernel, OF is no longer around for the second kernel to query.
Packit Service 87beb7
Packit Service 87beb7
\section{The Flattened Tree}
Packit Service 87beb7
Packit Service 87beb7
In May 2005 \benh implemented a new approach to handling the device
Packit Service 87beb7
tree that addresses all these problems.  When booting on OF systems,
Packit Service 87beb7
the first thing the kernel runs is a small piece of code in
Packit Service 87beb7
\texttt{prom\_init.c}, which executes in the context of OF.  This code
Packit Service 87beb7
walks the device tree using OF calls, and transcribes it into a
Packit Service 87beb7
compact, flattened format.  The resulting device tree ``blob'' is then
Packit Service 87beb7
passed to the kernel proper, which eventually unflattens the tree into
Packit Service 87beb7
its runtime form.  This blob is the only data communicated between the
Packit Service 87beb7
\texttt{prom\_init.c} bootstrap and the rest of the kernel.
Packit Service 87beb7
Packit Service 87beb7
When OF isn't available, either because the machine doesn't have it at
Packit Service 87beb7
all or because \kexec has been used, the kernel instead starts
Packit Service 87beb7
directly from the entry point taking a flattened device tree.  The
Packit Service 87beb7
device tree blob must be passed in from outside, rather than generated
Packit Service 87beb7
by part of the kernel from OF.  For \kexec, the userland
Packit Service 87beb7
\texttt{kexec} tools build the blob from the runtime device tree
Packit Service 87beb7
before invoking the new kernel.  For embedded systems the blob can
Packit Service 87beb7
come either from the embedded bootloader, or from a specialised
Packit Service 87beb7
version of the \texttt{zImage} wrapper for the system in question.
Packit Service 87beb7
Packit Service 87beb7
\subsection{Properties of the flattened tree}
Packit Service 87beb7
Packit Service 87beb7
The flattened tree format should be easy to handle, both for the
Packit Service 87beb7
kernel that parses it and the bootloader that generates it.  In
Packit Service 87beb7
particular, the following properties are desirable:
Packit Service 87beb7
Packit Service 87beb7
\begin{itemize}
Packit Service 87beb7
\item \emph{relocatable}: the bootloader or kernel should be able to
Packit Service 87beb7
  move the blob around as a whole, without needing to parse or adjust
Packit Service 87beb7
  its internals.  In practice that means we must not use pointers
Packit Service 87beb7
  within the blob.
Packit Service 87beb7
\item \emph{insert and delete}: sometimes the bootloader might want to
Packit Service 87beb7
  make tweaks to the flattened tree, such as deleting or inserting a
Packit Service 87beb7
  node (or whole subtree).  It should be possible to do this without
Packit Service 87beb7
  having to effectively regenerate the whole flattened tree.  In
Packit Service 87beb7
  practice this means limiting the use of internal offsets in the blob
Packit Service 87beb7
  that need recalculation if a section is inserted or removed with
Packit Service 87beb7
  \texttt{memmove()}.
Packit Service 87beb7
\item \emph{compact}: embedded systems are frequently short of
Packit Service 87beb7
  resources, particularly RAM and flash memory space.  Thus, the tree
Packit Service 87beb7
  representation should be kept as small as conveniently possible.
Packit Service 87beb7
\end{itemize}
Packit Service 87beb7
Packit Service 87beb7
\subsection{Format of the device tree blob}
Packit Service 87beb7
\label{sec:format}
Packit Service 87beb7
Packit Service 87beb7
\begin{figure}[htb!]
Packit Service 87beb7
  \centering
Packit Service 87beb7
  \footnotesize
Packit Service 87beb7
  \begin{tabular}{r|c|l}
Packit Service 87beb7
    \multicolumn{1}{r}{\textbf{Offset}}& \multicolumn{1}{c}{\textbf{Contents}} \\\cline{2-2}
Packit Service 87beb7
    \texttt{0x00} & \texttt{0xd00dfeed} & magic number \\\cline{2-2}
Packit Service 87beb7
    \texttt{0x04} & \emph{totalsize} \\\cline{2-2}
Packit Service 87beb7
    \texttt{0x08} & \emph{off\_struct} & \\\cline{2-2}
Packit Service 87beb7
    \texttt{0x0C} & \emph{off\_strs} & \\\cline{2-2}
Packit Service 87beb7
    \texttt{0x10} & \emph{off\_rsvmap} & \\\cline{2-2}
Packit Service 87beb7
    \texttt{0x14} & \emph{version} \\\cline{2-2}
Packit Service 87beb7
    \texttt{0x18} & \emph{last\_comp\_ver} & \\\cline{2-2}
Packit Service 87beb7
    \texttt{0x1C} & \emph{boot\_cpu\_id} & \tge v2 only\\\cline{2-2}
Packit Service 87beb7
    \texttt{0x20} & \emph{size\_strs} & \tge v3 only\\\cline{2-2}
Packit Service 87beb7
    \multicolumn{1}{r}{\vdots} & \multicolumn{1}{c}{\vdots} & \\\cline{2-2}
Packit Service 87beb7
    \emph{off\_rsvmap} & \emph{address0} & memory reserve \\
Packit Service 87beb7
    + \texttt{0x04} & ...& table \\\cline{2-2}
Packit Service 87beb7
    + \texttt{0x08} & \emph{len0} & \\
Packit Service 87beb7
    + \texttt{0x0C} & ...& \\\cline{2-2}
Packit Service 87beb7
    \vdots & \multicolumn{1}{c|}{\vdots} & \\\cline{2-2}
Packit Service 87beb7
    & \texttt{0x00000000}- & end marker\\
Packit Service 87beb7
    & \texttt{00000000} & \\\cline{2-2}
Packit Service 87beb7
    & \texttt{0x00000000}- & \\
Packit Service 87beb7
    & \texttt{00000000} & \\\cline{2-2}
Packit Service 87beb7
    \multicolumn{1}{r}{\vdots} & \multicolumn{1}{c}{\vdots} & \\\cline{2-2}
Packit Service 87beb7
    \emph{off\_strs} & \texttt{'n' 'a' 'm' 'e'} & strings block \\
Packit Service 87beb7
    + \texttt{0x04} & \texttt{~0~ 'm' 'o' 'd'} & \\
Packit Service 87beb7
    + \texttt{0x08} & \texttt{'e' 'l' ~0~ \makebox[\widthof{~~~}]{\textrm{...}}} & \\
Packit Service 87beb7
    \vdots & \multicolumn{1}{c|}{\vdots} & \\\cline{2-2}
Packit Service 87beb7
    \multicolumn{1}{r}{+ \emph{size\_strs}} \\
Packit Service 87beb7
    \multicolumn{1}{r}{\vdots} & \multicolumn{1}{c}{\vdots} & \\\cline{2-2}
Packit Service 87beb7
    \emph{off\_struct} & \dtbeginnode & structure block \\\cline{2-2}
Packit Service 87beb7
    + \texttt{0x04} & \texttt{'/' ~0~ ~0~ ~0~}  & root node\\\cline{2-2}
Packit Service 87beb7
    + \texttt{0x08} & \dtprop & \\\cline{2-2}
Packit Service 87beb7
    + \texttt{0x0C} & \texttt{0x00000005} & ``\texttt{model}''\\\cline{2-2}
Packit Service 87beb7
    + \texttt{0x10} & \texttt{0x00000008} & \\\cline{2-2}
Packit Service 87beb7
    + \texttt{0x14} & \texttt{'M' 'y' 'B' 'o'} & \\
Packit Service 87beb7
    + \texttt{0x18} & \texttt{'a' 'r' 'd' ~0~} & \\\cline{2-2}
Packit Service 87beb7
    \vdots & \multicolumn{1}{c|}{\vdots} & \\\cline{2-2}
Packit Service 87beb7
    & \texttt{\dtendnode} \\\cline{2-2}
Packit Service 87beb7
    & \texttt{\dtend} \\\cline{2-2}
Packit Service 87beb7
    \multicolumn{1}{r}{\vdots} & \multicolumn{1}{c}{\vdots} & \\\cline{2-2}
Packit Service 87beb7
    \multicolumn{1}{r}{\emph{totalsize}} \\
Packit Service 87beb7
  \end{tabular}
Packit Service 87beb7
  \caption{Device tree blob layout}
Packit Service 87beb7
  \label{fig:blob-layout}
Packit Service 87beb7
\end{figure}
Packit Service 87beb7
Packit Service 87beb7
The format for the blob we devised, was first described on the
Packit Service 87beb7
\texttt{linuxppc64-dev} mailing list in \cite{noof1}.  The format has
Packit Service 87beb7
since evolved through various revisions, and the current version is
Packit Service 87beb7
included as part of the \dtc (see \S\ref{sec:dtc}) git tree,
Packit Service 87beb7
\cite{dtcgit}.
Packit Service 87beb7
Packit Service 87beb7
Figure \ref{fig:blob-layout} shows the layout of the blob of data
Packit Service 87beb7
containing the device tree.  It has three sections of variable size:
Packit Service 87beb7
the \emph{memory reserve table}, the \emph{structure block} and the
Packit Service 87beb7
\emph{strings block}.  A small header gives the blob's size and
Packit Service 87beb7
version and the locations of the three sections, plus a handful of
Packit Service 87beb7
vital parameters used during early boot.
Packit Service 87beb7
Packit Service 87beb7
The memory reserve map section gives a list of regions of memory that
Packit Service 87beb7
the kernel must not use\footnote{Usually such ranges contain some data
Packit Service 87beb7
structure initialised by the firmware that must be preserved by the
Packit Service 87beb7
kernel.}.  The list is represented as a simple array of (address,
Packit Service 87beb7
size) pairs of 64 bit values, terminated by a zero size entry.  The
Packit Service 87beb7
strings block is similarly simple, consisting of a number of
Packit Service 87beb7
null-terminated strings appended together, which are referenced from
Packit Service 87beb7
the structure block as described below.
Packit Service 87beb7
Packit Service 87beb7
The structure block contains the device tree proper.  Each node is
Packit Service 87beb7
introduced with a 32-bit \dtbeginnode tag, followed by the node's name
Packit Service 87beb7
as a null-terminated string, padded to a 32-bit boundary.  Then
Packit Service 87beb7
follows all of the properties of the node, each introduced with a
Packit Service 87beb7
\dtprop tag, then all of the node's subnodes, each introduced with
Packit Service 87beb7
their own \dtbeginnode tag.  The node ends with an \dtendnode tag, and
Packit Service 87beb7
after the \dtendnode for the root node is an \dtend tag, indicating
Packit Service 87beb7
the end of the whole tree\footnote{This is redundant, but included for
Packit Service 87beb7
ease of parsing.}.  The structure block starts with the \dtbeginnode
Packit Service 87beb7
introducing the description of the root node (named \texttt{/}).
Packit Service 87beb7
Packit Service 87beb7
Each property, after the \dtprop, has a 32-bit value giving an offset
Packit Service 87beb7
from the beginning of the strings block at which the property name is
Packit Service 87beb7
stored.  Because it's common for many nodes to have properties with
Packit Service 87beb7
the same name, this approach can substantially reduce the total size
Packit Service 87beb7
of the blob.  The name offset is followed by the length of the
Packit Service 87beb7
property value (as a 32-bit value) and then the data itself padded to
Packit Service 87beb7
a 32-bit boundary.
Packit Service 87beb7
Packit Service 87beb7
\subsection{Contents of the tree}
Packit Service 87beb7
\label{sec:treecontents}
Packit Service 87beb7
Packit Service 87beb7
Having seen how to represent the device tree structure as a flattened
Packit Service 87beb7
blob, what actually goes into the tree?  The short answer is ``the
Packit Service 87beb7
same as an OF tree''.  On OF systems, the flattened tree is
Packit Service 87beb7
transcribed directly from the OF device tree, so for simplicity we
Packit Service 87beb7
also use OF conventions for the tree on other systems.
Packit Service 87beb7
Packit Service 87beb7
In many cases a flat tree can be simpler than a typical OF provided
Packit Service 87beb7
device tree.  The flattened tree need only provide those nodes and
Packit Service 87beb7
properties that the kernel actually requires; the flattened tree
Packit Service 87beb7
generally need not include devices that the kernel can probe itself.
Packit Service 87beb7
For example, an OF device tree would normally include nodes for each
Packit Service 87beb7
PCI device on the system.  A flattened tree need only include nodes
Packit Service 87beb7
for the PCI host bridges; the kernel will scan the buses thus
Packit Service 87beb7
described to find the subsidiary devices.  The device tree can include
Packit Service 87beb7
nodes for devices where the kernel needs extra information, though:
Packit Service 87beb7
for example, for ISA devices on a subsidiary PCI/ISA bridge, or for
Packit Service 87beb7
devices with unusual interrupt routing.
Packit Service 87beb7
Packit Service 87beb7
Where they exist, we follow the IEEE1275 bindings that specify how to
Packit Service 87beb7
describe various buses in the device tree (for example,
Packit Service 87beb7
\cite{IEEE1275-pci} describe how to represent PCI devices).  The
Packit Service 87beb7
standard has not been updated for a long time, however, and lacks
Packit Service 87beb7
bindings for many modern buses and devices.  In particular, embedded
Packit Service 87beb7
specific devices such as the various System-on-Chip buses are not
Packit Service 87beb7
covered.  We intend to create new bindings for such buses, in keeping
Packit Service 87beb7
with the general conventions of IEEE1275 (a simple such binding for a
Packit Service 87beb7
System-on-Chip bus was included in \cite{noof5} a revision of
Packit Service 87beb7
\cite{noof1}).
Packit Service 87beb7
Packit Service 87beb7
One complication arises for representing ``phandles'' in the flattened
Packit Service 87beb7
tree.  In OF, each node in the tree has an associated phandle, a
Packit Service 87beb7
32-bit integer that uniquely identifies the node\footnote{In practice
Packit Service 87beb7
usually implemented as a pointer or offset within OF memory.}.  This
Packit Service 87beb7
handle is used by the various OF calls to query and traverse the tree.
Packit Service 87beb7
Sometimes phandles are also used within the tree to refer to other
Packit Service 87beb7
nodes in the tree.  For example, devices that produce interrupts
Packit Service 87beb7
generally have an \texttt{interrupt-parent} property giving the
Packit Service 87beb7
phandle of the interrupt controller that handles interrupts from this
Packit Service 87beb7
device.  Parsing these and other interrupt related properties allows
Packit Service 87beb7
the kernel to build a complete representation of the system's
Packit Service 87beb7
interrupt tree, which can be quite different from the tree of bus
Packit Service 87beb7
connections.
Packit Service 87beb7
Packit Service 87beb7
In the flattened tree, a node's phandle is represented by a special
Packit Service 87beb7
\phandle property.  When the kernel generates a flattened tree from
Packit Service 87beb7
OF, it adds a \phandle property to each node, containing the phandle
Packit Service 87beb7
retrieved from OF.  When the tree is generated without OF, however,
Packit Service 87beb7
only nodes that are actually referred to by phandle need to have this
Packit Service 87beb7
property.
Packit Service 87beb7
Packit Service 87beb7
Another complication arises because nodes in an OF tree have two
Packit Service 87beb7
names.  First they have the ``unit name'', which is how the node is
Packit Service 87beb7
referred to in an OF path.  The unit name generally consists of a
Packit Service 87beb7
device type followed by an \texttt{@} followed by a \emph{unit
Packit Service 87beb7
address}.  For example \texttt{/memory@0} is the full path of a memory
Packit Service 87beb7
node at address 0, \texttt{/ht@0,f2000000/pci@1} is the path of a PCI
Packit Service 87beb7
bus node, which is under a HyperTransport\tm bus node.  The form of
Packit Service 87beb7
the unit address is bus dependent, but is generally derived from the
Packit Service 87beb7
node's \texttt{reg} property.  In addition, nodes have a property,
Packit Service 87beb7
\texttt{name}, whose value is usually equal to the first path of the
Packit Service 87beb7
unit name. For example, the nodes in the previous example would have
Packit Service 87beb7
\texttt{name} properties equal to \texttt{memory} and \texttt{pci},
Packit Service 87beb7
respectively.  To save space in the blob, the current version of the
Packit Service 87beb7
flattened tree format only requires the unit names to be present.
Packit Service 87beb7
When the kernel unflattens the tree, it automatically generates a
Packit Service 87beb7
\texttt{name} property from the node's path name.
Packit Service 87beb7
Packit Service 87beb7
\section{The Device Tree Compiler}
Packit Service 87beb7
\label{sec:dtc}
Packit Service 87beb7
Packit Service 87beb7
\begin{figure}[htb!]
Packit Service 87beb7
  \centering
Packit Service 87beb7
  \begin{lstlisting}[frame=single,basicstyle=\footnotesize\ttfamily,
Packit Service 87beb7
    tabsize=3,numbers=left,xleftmargin=2em]
Packit Service 87beb7
/memreserve/ 0x20000000-0x21FFFFFF;
Packit Service 87beb7
Packit Service 87beb7
/ {
Packit Service 87beb7
	model = "MyBoard";
Packit Service 87beb7
	compatible = "MyBoardFamily";
Packit Service 87beb7
	#address-cells = <2>;
Packit Service 87beb7
	#size-cells = <2>;
Packit Service 87beb7
Packit Service 87beb7
	cpus {
Packit Service 87beb7
		#address-cells = <1>;
Packit Service 87beb7
		#size-cells = <0>;
Packit Service 87beb7
		PowerPC,970@0 {
Packit Service 87beb7
			device_type = "cpu";
Packit Service 87beb7
			reg = <0>;
Packit Service 87beb7
			clock-frequency = <5f5e1000>;
Packit Service 87beb7
			timebase-frequency = <1FCA055>;
Packit Service 87beb7
			linux,boot-cpu;
Packit Service 87beb7
			i-cache-size = <10000>;
Packit Service 87beb7
			d-cache-size = <8000>;
Packit Service 87beb7
		};
Packit Service 87beb7
	};
Packit Service 87beb7
Packit Service 87beb7
	memory@0 {
Packit Service 87beb7
		device_type = "memory";
Packit Service 87beb7
		memreg: reg = <00000000 00000000
Packit Service 87beb7
		               00000000 20000000>;
Packit Service 87beb7
	};
Packit Service 87beb7
Packit Service 87beb7
	mpic@0x3fffdd08400 {
Packit Service 87beb7
		/* Interrupt controller */
Packit Service 87beb7
		/* ... */
Packit Service 87beb7
	};
Packit Service 87beb7
Packit Service 87beb7
	pci@40000000000000 {
Packit Service 87beb7
		/* PCI host bridge */
Packit Service 87beb7
		/* ... */
Packit Service 87beb7
	};
Packit Service 87beb7
Packit Service 87beb7
	chosen {
Packit Service 87beb7
		bootargs = "root=/dev/sda2";
Packit Service 87beb7
		linux,platform = <00000600>;
Packit Service 87beb7
		interrupt-controller =
Packit Service 87beb7
			< &/mpic@0x3fffdd08400 >;
Packit Service 87beb7
	};
Packit Service 87beb7
};
Packit Service 87beb7
\end{lstlisting}
Packit Service 87beb7
  \caption{Example \dtc source}
Packit Service 87beb7
  \label{fig:dts}
Packit Service 87beb7
\end{figure}
Packit Service 87beb7
Packit Service 87beb7
As we've seen, the flattened device tree format provides a convenient
Packit Service 87beb7
way of communicating device tree information to the kernel.  It's
Packit Service 87beb7
simple for the kernel to parse, and simple for bootloaders to
Packit Service 87beb7
manipulate.  On OF systems, it's easy to generate the flattened tree
Packit Service 87beb7
by walking the OF maintained tree.  However, for embedded systems, the
Packit Service 87beb7
flattened tree must be generated from scratch.
Packit Service 87beb7
Packit Service 87beb7
Embedded bootloaders are generally built for a particular board.  So,
Packit Service 87beb7
it's usually possible to build the device tree blob at compile time
Packit Service 87beb7
and include it in the bootloader image.  For minor revisions of the
Packit Service 87beb7
board, the bootloader can contain code to make the necessary tweaks to
Packit Service 87beb7
the tree before passing it to the booted kernel.
Packit Service 87beb7
Packit Service 87beb7
The device trees for embedded boards are usually quite simple, and
Packit Service 87beb7
it's possible to hand construct the necessary blob by hand, but doing
Packit Service 87beb7
so is tedious.  The ``device tree compiler'', \dtc{}\footnote{\dtc can
Packit Service 87beb7
be obtained from \cite{dtcgit}.}, is designed to make creating device
Packit Service 87beb7
tree blobs easier by converting a text representation of the tree
Packit Service 87beb7
into the necessary blob.
Packit Service 87beb7
Packit Service 87beb7
\subsection{Input and output formats}
Packit Service 87beb7
Packit Service 87beb7
As well as the normal mode of compiling a device tree blob from text
Packit Service 87beb7
source, \dtc can convert a device tree between a number of
Packit Service 87beb7
representations.  It can take its input in one of three different
Packit Service 87beb7
formats:
Packit Service 87beb7
\begin{itemize}
Packit Service 87beb7
\item source, the normal case.  The device tree is described in a text
Packit Service 87beb7
  form, described in \S\ref{sec:dts}.
Packit Service 87beb7
\item blob (\texttt{dtb}), the flattened tree format described in
Packit Service 87beb7
  \S\ref{sec:format}.  This mode is useful for checking a pre-existing
Packit Service 87beb7
  device tree blob.
Packit Service 87beb7
\item filesystem (\texttt{fs}), input is a directory tree in the
Packit Service 87beb7
  layout of \texttt{/proc/device-tree} (roughly, a directory for each
Packit Service 87beb7
  node in the device tree, a file for each property).  This is useful
Packit Service 87beb7
  for building a blob for the device tree in use by the currently
Packit Service 87beb7
  running kernel.
Packit Service 87beb7
\end{itemize}
Packit Service 87beb7
Packit Service 87beb7
In addition, \dtc can output the tree in one of three different
Packit Service 87beb7
formats:
Packit Service 87beb7
\begin{itemize}
Packit Service 87beb7
\item blob (\texttt{dtb}), as in \S\ref{sec:format}.  The most
Packit Service 87beb7
  straightforward use of \dtc is to compile from ``source'' to
Packit Service 87beb7
  ``blob'' format.
Packit Service 87beb7
\item source (\texttt{dts}), as in \S\ref{sec:dts}.  If used with blob
Packit Service 87beb7
  input, this allows \dtc to act as a ``decompiler''.
Packit Service 87beb7
\item assembler source (\texttt{asm}).  \dtc can produce an assembler
Packit Service 87beb7
  file, which will assemble into a \texttt{.o} file containing the
Packit Service 87beb7
  device tree blob, with symbols giving the beginning of the blob and
Packit Service 87beb7
  its various subsections.  This can then be linked directly into a
Packit Service 87beb7
  bootloader or firmware image.
Packit Service 87beb7
\end{itemize}
Packit Service 87beb7
Packit Service 87beb7
For maximum applicability, \dtc can both read and write any of the
Packit Service 87beb7
existing revisions of the blob format.  When reading, \dtc takes the
Packit Service 87beb7
version from the blob header, and when writing it takes a command line
Packit Service 87beb7
option specifying the desired version.  It automatically makes any
Packit Service 87beb7
necessary adjustments to the tree that are necessary for the specified
Packit Service 87beb7
version.  For example, formats before 0x10 require each node to have
Packit Service 87beb7
an explicit \texttt{name} property.  When \dtc creates such a blob, it
Packit Service 87beb7
will automatically generate \texttt{name} properties from the unit
Packit Service 87beb7
names.
Packit Service 87beb7
Packit Service 87beb7
\subsection{Source format}
Packit Service 87beb7
\label{sec:dts}
Packit Service 87beb7
Packit Service 87beb7
The ``source'' format for \dtc is a text description of the device
Packit Service 87beb7
tree in a vaguely C-like form.  Figure \ref{fig:dts} shows an
Packit Service 87beb7
example.  The file starts with \texttt{/memreserve/} directives, which
Packit Service 87beb7
gives address ranges to add to the output blob's memory reserve table,
Packit Service 87beb7
then the device tree proper is described.
Packit Service 87beb7
Packit Service 87beb7
Nodes of the tree are introduced with the node name, followed by a
Packit Service 87beb7
\texttt{\{} ... \texttt{\};} block containing the node's properties
Packit Service 87beb7
and subnodes.  Properties are given as just {\emph{name} \texttt{=}
Packit Service 87beb7
  \emph{value}\texttt{;}}.  The property values can be given in any
Packit Service 87beb7
of three forms:
Packit Service 87beb7
\begin{itemize}
Packit Service 87beb7
\item \emph{string} (for example, \texttt{"MyBoard"}).  The property
Packit Service 87beb7
  value is the given string, including terminating NULL.  C-style
Packit Service 87beb7
  escapes (\verb+\t+, \verb+\n+, \verb+\0+ and so forth) are allowed.
Packit Service 87beb7
\item \emph{cells} (for example, \texttt{<0 8000 f0000000>}).  The
Packit Service 87beb7
  property value is made up of a list of 32-bit ``cells'', each given
Packit Service 87beb7
  as a hex value.
Packit Service 87beb7
\item \emph{bytestring} (for example, \texttt{[1234abcdef]}).  The
Packit Service 87beb7
  property value is given as a hex bytestring.
Packit Service 87beb7
\end{itemize}
Packit Service 87beb7
Packit Service 87beb7
Cell properties can also contain \emph{references}.  Instead of a hex
Packit Service 87beb7
number, the source can give an ampersand (\texttt{\&}) followed by the
Packit Service 87beb7
full path to some node in the tree.  For example, in Figure
Packit Service 87beb7
\ref{fig:dts}, the \texttt{/chosen} node has an
Packit Service 87beb7
\texttt{interrupt-controller} property referring to the interrupt
Packit Service 87beb7
controller described by the node \texttt{/mpic@0x3fffdd08400}.  In the
Packit Service 87beb7
output tree, the value of the referenced node's phandle is included in
Packit Service 87beb7
the property.  If that node doesn't have an explicit phandle property,
Packit Service 87beb7
\dtc will automatically create a unique phandle for it.  This approach
Packit Service 87beb7
makes it easy to create interrupt trees without having to explicitly
Packit Service 87beb7
assign and remember phandles for the various interrupt controller
Packit Service 87beb7
nodes.
Packit Service 87beb7
Packit Service 87beb7
The \dtc source can also include ``labels'', which are placed on a
Packit Service 87beb7
particular node or property.  For example, Figure \ref{fig:dts} has a
Packit Service 87beb7
label ``\texttt{memreg}'' on the \texttt{reg} property of the node
Packit Service 87beb7
\texttt{/memory@0}.  When using assembler output, corresponding labels
Packit Service 87beb7
in the output are generated, which will assemble into symbols
Packit Service 87beb7
addressing the part of the blob with the node or property in question.
Packit Service 87beb7
This is useful for the common case where an embedded board has an
Packit Service 87beb7
essentially fixed device tree with a few variable properties, such as
Packit Service 87beb7
the size of memory.  The bootloader for such a board can have a device
Packit Service 87beb7
tree linked in, including a symbol referring to the right place in the
Packit Service 87beb7
blob to update the parameter with the correct value determined at
Packit Service 87beb7
runtime.
Packit Service 87beb7
Packit Service 87beb7
\subsection{Tree checking}
Packit Service 87beb7
Packit Service 87beb7
Between reading in the device tree and writing it out in the new
Packit Service 87beb7
format, \dtc performs a number of checks on the tree:
Packit Service 87beb7
\begin{itemize}
Packit Service 87beb7
\item \emph{syntactic structure}:  \dtc checks that node and property
Packit Service 87beb7
  names contain only allowed characters and meet length restrictions.
Packit Service 87beb7
  It checks that a node does not have multiple properties or subnodes
Packit Service 87beb7
  with the same name.
Packit Service 87beb7
\item \emph{semantic structure}: In some cases, \dtc checks that
Packit Service 87beb7
  properties whose contents are defined by convention have appropriate
Packit Service 87beb7
  values.  For example, it checks that \texttt{reg} properties have a
Packit Service 87beb7
  length that makes sense given the address forms specified by the
Packit Service 87beb7
  \texttt{\#address-cells} and \texttt{\#size-cells} properties.  It
Packit Service 87beb7
  checks that properties such as \texttt{interrupt-parent} contain a
Packit Service 87beb7
  valid phandle.
Packit Service 87beb7
\item \emph{Linux requirements}:  \dtc checks that the device tree
Packit Service 87beb7
  contains those nodes and properties that are required by the Linux
Packit Service 87beb7
  kernel to boot correctly.
Packit Service 87beb7
\end{itemize}
Packit Service 87beb7
Packit Service 87beb7
These checks are useful to catch simple problems with the device tree,
Packit Service 87beb7
rather than having to debug the results on an embedded kernel.  With
Packit Service 87beb7
the blob input mode, it can also be used for diagnosing problems with
Packit Service 87beb7
an existing blob.
Packit Service 87beb7
Packit Service 87beb7
\section{Future Work}
Packit Service 87beb7
Packit Service 87beb7
\subsection{Board ports}
Packit Service 87beb7
Packit Service 87beb7
The flattened device tree has always been the only supported way to
Packit Service 87beb7
boot a \texttt{ppc64} kernel on an embedded system.  With the merge of
Packit Service 87beb7
\texttt{ppc32} and \texttt{ppc64} code it has also become the only
Packit Service 87beb7
supported way to boot any merged \texttt{powerpc} kernel, 32-bit or
Packit Service 87beb7
64-bit.  In fact, the old \texttt{ppc} architecture exists mainly just
Packit Service 87beb7
to support the old ppc32 embedded ports that have not been migrated
Packit Service 87beb7
to the flattened device tree approach.  We plan to remove the
Packit Service 87beb7
\texttt{ppc} architecture eventually, which will mean porting all the
Packit Service 87beb7
various embedded boards to use the flattened device tree.
Packit Service 87beb7
Packit Service 87beb7
\subsection{\dtc features}
Packit Service 87beb7
Packit Service 87beb7
While it is already quite usable, there are a number of extra features
Packit Service 87beb7
that \dtc could include to make creating device trees more convenient:
Packit Service 87beb7
\begin{itemize}
Packit Service 87beb7
\item \emph{better tree checking}: Although \dtc already performs a
Packit Service 87beb7
  number of checks on the device tree, they are rather haphazard.  In
Packit Service 87beb7
  many cases \dtc will give up after detecting a minor error early and
Packit Service 87beb7
  won't pick up more interesting errors later on.  There is a
Packit Service 87beb7
  \texttt{-f} parameter that forces \dtc to generate an output tree
Packit Service 87beb7
  even if there are errors.  At present, this needs to be used more
Packit Service 87beb7
  often than one might hope, because \dtc is bad at deciding which
Packit Service 87beb7
  errors should really be fatal, and which rate mere warnings.
Packit Service 87beb7
\item \emph{binary include}: Occasionally, it is useful for the device
Packit Service 87beb7
  tree to incorporate as a property a block of binary data for some
Packit Service 87beb7
  board-specific purpose.  For example, many of Apple's device trees
Packit Service 87beb7
  incorporate bytecode drivers for certain platform devices.  \dtc's
Packit Service 87beb7
  source format ought to allow this by letting a property's value be
Packit Service 87beb7
  read directly from a binary file.
Packit Service 87beb7
\item \emph{macros}: it might be useful for \dtc to implement some
Packit Service 87beb7
  sort of macros so that a tree containing a number of similar devices
Packit Service 87beb7
  (for example, multiple identical ethernet controllers or PCI buses)
Packit Service 87beb7
  can be written more quickly.  At present, this can be accomplished
Packit Service 87beb7
  in part by running the source file through CPP before compiling with
Packit Service 87beb7
  \dtc.  It's not clear whether ``native'' support for macros would be
Packit Service 87beb7
  more useful.
Packit Service 87beb7
\end{itemize}
Packit Service 87beb7
Packit Service 87beb7
\bibliographystyle{amsplain}
Packit Service 87beb7
\bibliography{dtc-paper}
Packit Service 87beb7
Packit Service 87beb7
\section*{About the authors}
Packit Service 87beb7
Packit Service 87beb7
David Gibson has been a member of the IBM Linux Technology Center,
Packit Service 87beb7
working from Canberra, Australia, since 2001.  Recently he has worked
Packit Service 87beb7
on Linux hugepage support and performance counter support for ppc64,
Packit Service 87beb7
as well as the device tree compiler.  In the past, he has worked on
Packit Service 87beb7
bringup for various ppc and ppc64 embedded systems, the orinoco
Packit Service 87beb7
wireless driver, ramfs, and a userspace checkpointing system
Packit Service 87beb7
(\texttt{esky}).
Packit Service 87beb7
Packit Service 87beb7
Benjamin Herrenschmidt was a MacOS developer for about 10 years, but
Packit Service 87beb7
ultimately saw the light and installed Linux on his Apple PowerPC
Packit Service 87beb7
machine.  After writing a bootloader, BootX, for it in 1998, he
Packit Service 87beb7
started contributing to the PowerPC Linux port in various areas,
Packit Service 87beb7
mostly around the support for Apple machines. He became official
Packit Service 87beb7
PowerMac maintainer in 2001. In 2003, he joined the IBM Linux
Packit Service 87beb7
Technology Center in Canberra, Australia, where he ported the 64 bit
Packit Service 87beb7
PowerPC kernel to Apple G5 machines and the Maple embedded board,
Packit Service 87beb7
among others things.  He's a member of the ppc64 development ``team''
Packit Service 87beb7
and one of his current goals is to make the integration of embedded
Packit Service 87beb7
platforms smoother and more maintainable than in the 32-bit PowerPC
Packit Service 87beb7
kernel.
Packit Service 87beb7
Packit Service 87beb7
\section*{Legal Statement}
Packit Service 87beb7
Packit Service 87beb7
This work represents the view of the author and does not necessarily
Packit Service 87beb7
represent the view of IBM.
Packit Service 87beb7
Packit Service 87beb7
IBM, \ppc, \ppc Architecture, POWER5, pSeries and iSeries are
Packit Service 87beb7
trademarks or registered trademarks of International Business Machines
Packit Service 87beb7
Corporation in the United States and/or other countries.
Packit Service 87beb7
Packit Service 87beb7
Apple and Power Macintosh are a registered trademarks of Apple
Packit Service 87beb7
Computer Inc. in the United States, other countries, or both.
Packit Service 87beb7
Packit Service 87beb7
Linux is a registered trademark of Linus Torvalds.
Packit Service 87beb7
Packit Service 87beb7
Other company, product, and service names may be trademarks or service
Packit Service 87beb7
marks of others.
Packit Service 87beb7
Packit Service 87beb7
\end{document}