\documentclass{beamer}
\usetheme{linutronix}
\usepackage{german}
\usepackage[utf8]{inputenc}
\usepackage{pgf}
\usepackage{graphicx}
\usepackage{lxextras}


\title{\lq Workshop: Cross Development\rq}
\institute{Linutronix GmbH}

\lstset{keywordstyle=\color{blue},commentstyle=\color{orange}}

\begin{document}

\maketitle

\begin{frame}
\frametitle{Übersicht}
\tableofcontents
\end{frame}

\section{Cross Übersetzen}
\begin{frame}[containsverbatim]
\frametitle{Cross ''Hello world''}
\begin{lstlisting}[language=c]
/* cross_hello.c */
#include <stdio.h>

int main(void)
{
    printf("Hello cross compiling world\n");
    return 0;
}
\end{lstlisting}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Übersetzen für das Zielsystem}
\begin{lstlisting}[language=bash]
# Uebersetzen
$ arm-none-linux-gnueabi-gcc -static \
-o cross_hello cross_hello.c
\end{lstlisting}
\begin{lstlisting}[language=bash]
# Executable ueberpruefen
$ file cross_hello
cross_hello: ELF 32-bit LSB executable, ARM,
version 1 (SYSV), dynamically
linked (uses shared libs),
for GNU/Linux 2.6.14, not stripped
\end{lstlisting}
\end{frame}

\section{Testing auf dem Host}

\begin{frame}
\frametitle{Qemu als Werkzeug zur Cross Entwicklung}
\begin{alertblock}{Was ist Qemu?}
Qemu ist eine sehr performante Emulations- und Virtualisierungsumgebung für alle
gängigen CPU Architekturen.
\end{alertblock}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Testen eines Executables mit der Qemu user emulation}
\begin{lstlisting}[language=bash]
$ ./cross_hello
 : ./cross_hello: cannot execute binary file
$ qemu-arm ./cross_hello
Hello cross compiling world
\end{lstlisting}
\end{frame}

\section{Rootfilesystem}
\subsection{Filesystem from scratch}
\begin{frame}
\frametitle{Komponenten des Zielsystems}
\begin{overprint}
\onslide <1>
\begin{figure}[h]
\centering
\includegraphics[width=6cm]{images/target.png}
\end{figure}
\onslide <2>
\begin{figure}[h]
\centering
\includegraphics[width=6cm]{images/target_highlight_rfs.png}
\end{figure}
\end{overprint}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Erstellen eines Rootfilesystems für die Zielarchitektur}
1) Busybox
\begin{lstlisting}[language=bash]
sudo mkdir -p /tftpboot/nfsroot
cd busybox-1.17.3
make menuconfig
make CROSS_COMPILE=arm-none-linux-gnueabi- \
                 install
sudo rsync -Hav _install/ /tftpboot/nfsroot
cd /tftpboot/nfsroot
\end{lstlisting}
\end{frame}

\begin{frame}
\frametitle{Device nodes}
\begin{figure}[h]
\centering
\includegraphics[width=8cm]{images/mknod.png}
\end{figure}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Erstellen eines Rootfilesystems für die Zielarchitektur}
\begin{lstlisting}[language=bash]
# Verzeichnisstruktur
mkdir lib etc tmp dev mnt sys proc root
# Devices nodes (als root!)
sudo mknod dev/console c 5 1
sudo mknod dev/null    c 1 3
sudo mknod dev/ttyS0   c 4 64
sudo mknod dev/ttyS1   c 4 65
sudo mknod dev/ttyS2   c 4 66
sudo mknod dev/tty     c 5 0
sudo mknod dev/tty0    c 4 0
sudo mknod dev/tty1    c 4 1
sudo mknod dev/tty2    c 4 2
sudo mknod dev/tty3    c 4 3
sudo mknod dev/tty4    c 4 4
\end{lstlisting}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Erstellen eines Rootfilesystems für die Zielarchitektur}
3) Startscript(e) erstellen
\begin{lstlisting}[language=bash]
sudo cd /tftpboot/nfsroot
sudo mkdir etc/init.d
sudo vim etc/init.d/rcS
\end{lstlisting}
/etc/init.d/rcS:
\begin{verbatim}
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys

mount -o remount,rw /
\end{verbatim}
\begin{lstlisting}[language=bash]
sudo chmod u+x etc/init.d/rcS
\end{lstlisting}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Erstellen eines Rootfilesystems für die Zielarchitektur}
\begin{lstlisting}[language=bash]
# Loader
$ sudo cp \
/home/devel/CodeSourcery/Sourcery_G++_Lite/\
arm-none-linux-gnueabi/libc/lib/ld-* lib/
# Getting the dependencies and copy them
$ arm-none-linux-gnueabi-objdump -x \
/tftpboot/nfsroot/bin/busybox | grep NEEDED
  NEEDED               libm.so.6
  NEEDED               libc.so.6
$ sudo cp /path_to_my_libc/lib/libm.so.6 \
/tftpboot/nfsroot/lib
$ sudo cp /path_to_my_libc/lib/libc.so.6 \
/tftpboot/nfsroot/lib
\end{lstlisting}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Erstellen eines Rootfilesystems für die Zielarchitektur}
\begin{lstlisting}[language=bash]
sudo chown -R root:root /tftpboot/nfsroot
\end{lstlisting}
That's it!! :)
\end{frame}

\subsection{Exportieren per NFS}
\subsubsection{Konfiguration}
\begin{frame}[containsverbatim]
\frametitle{Exportieren per NFS}
\begin{lstlisting}
# Auf Debian basierten Systemen (als root)
sudo apt-get install nfs-kernel-server
\end{lstlisting}
\end{frame}
\begin{frame}[containsverbatim]
\frametitle{Exportieren per NFS}
2) Directory exportieren
\begin{lstlisting}[language=bash]
sudo vim /etc/exports
\end{lstlisting}
\begin{verbatim}
/tftpboot/nfsroot \
192.168.2.0/255.255.255.0\
(rw,no_root_squash,no_subtree_check,insecure)
\end{verbatim}
\begin{lstlisting}[language=bash]
/etc/init.d/nfs-kernel-server restart
\end{lstlisting}
\end{frame}
\subsubsection{Filesystem testen}

\begin{frame}[fragile]
\frametitle{U-Boot setup}
\small
\begin{verbatim}
setenv serverip 192.168.2.1

setenv nfsargs 'setenv bootargs console=${console}
vram=${vram} omapfb.mode=dvi:${dvimode} omapfb.debug=y
omapdss.def_disp=${defaultdisplay} root=/dev/nfs
nfsroot=${serverip}:/tftpboot/nfsroot rootwait
ip=dhcp devtmpfs.mount=0'

setenv bootcmd 'mmc init; run nfsargs;
fatload mmc 0 80200000 uImage.bin; bootm 80200000'
\end{verbatim}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{RFS booten}
\begin{verbatim}
[...]
IP-Config: Got DHCP answer from 10.0.2.2, my address
IP-Config: Complete:
      device=eth0, addr=10.0.2.15, mask=255.255.255.0
     host=10.0.2.15, domain=, nis-domain=(none),
     bootserver=10.0.2.2, rootserver=10.0.2.2, rootpath=
Looking up port of RPC 100003/2 on 10.0.2.2
Looking up port of RPC 100005/1 on 10.0.2.2
VFS: Mounted root (nfs filesystem) readonly.
Freeing unused kernel memory: 208k init

Please press Enter to activate this console.
\end{verbatim}
\end{frame}

\begin{frame}
\frametitle{Congrats!!!}
Ihr erstes eigenes Linux System!! :)
\end{frame}

\begin{frame}[fragile]
\frametitle{Startskript erweitern}
\begin{lstlisting}[language=bash]
cd /tftpboot/nfsroot
sudo mkdir dev/pts
sudo vim /tftpboot/nfsroot/etc/init.d/rcS
\end{lstlisting}
\begin{lstlisting}[language=bash]
[...]
mount devpts /dev/pts -t devpts

tcpsvd -vE 0.0.0.0 21 ftpd -w / &
\end{lstlisting}
\end{frame}

\subsection{RFS um FTPD erweitern}
\begin{frame}[fragile]
\frametitle{FTP testen}
Auf dem Host:
\begin{verbatim}
$ dd if=/dev/zero of=bla bs=512 count=1
[...]
$ ftp 192.168.2.2
Connected to 192.168.2.2
220 Operation successful
Name (192.168.2.2:devel): root
230 Operation successful
[...]
ftp> put bla
local: bla remote: bla
200 Operation successful
150 Ok to send data
[...]
\end{verbatim}
\end{frame}

\subsection{RFS um SSH erweitern}
\begin{frame}
\frametitle{dropbear}
Dropbear ist eine schlanke SSH Server und Client Implementierung
und wird daher recht häufig in Embedded Systemen verwendet.
\begin{alertblock}{Vorteile}
\begin{itemize}
\item Einfach zu übersetzen
\item Schlank / Wenig Footprint
\item Einfach Konfiguration
\end{itemize}
\end{alertblock}
\begin{alertblock}{Nachteile}
\begin{itemize}
\item Keine eigene SFTP Implementierung
\end{itemize}
\end{alertblock}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Dropbear übersetzen}
\begin{lstlisting}[language=bash]
$ ./configure --host=arm-none-linux-gnueabi \
   --disable-zlib --prefix=/usr
make
# Als root
make DESTDIR=/tftpboot/nfsroot install
\end{lstlisting}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Dropbear: Benötigte Bibliotheken}
\begin{lstlisting}[language=bash]
# Schritt 1: libnss
cp /path_to_my_libc/lib/libnss_* lib/
# Schritt 2: It's your turn!
\end{lstlisting}
Aufgabe: Ermitteln der benötigten Bibliotheken von Dropbear
und kopieren an die richtige Stelle im RFS.
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Dropbear: Benötigte Bibliotheken / Lösung}
\begin{lstlisting}[language=bash]
$ arm-none-linux-gnueabi-objdump -x \
/tftpboot/nfsroot/usr/sbin/dropbear | \
grep NEEDED
  NEEDED               libutil.so.1
  NEEDED               libcrypt.so.1
[...]
$ sudo cp /path_to_my_libc/libcrypt.so.1 \
     /tftpboot/nfsroot/lib
$ sudo cp /path_to_my_libc/libutil.so.1 \
     /tftpboot/nfsroot/lib
$ sudo cp /path_to_my_libc/libgcc_s.so.1 \
     /tftpboot/nfsroot/lib
\end{lstlisting}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{RFS um SSH erweitern}
Vorbereitungen:
\begin{lstlisting}[language=bash]
sudo su
cd /tftpboot/nfsroot
mknod dev/urandom c 1 9
mknod dev/ptmx c 5 2

mkdir root
mkdir etc/dropbear

echo "root:x:0:0::/root:/bin/sh" >> etc/passwd
echo "root:x:0:" >> etc/group
exit
\end{lstlisting}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Password für root setzen}
\begin{lstlisting}[language=bash]
# Im gebooteten System:
passwd
\end{lstlisting}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{Dropbear: Startskript erweitern}
\begin{lstlisting}[language=bash]
sudo vim /tftpboot/nfsroot/etc/init.d/rcS
\end{lstlisting}
\begin{lstlisting}[language=bash,basicstyle=\ttfamily\fontsize{7}{7}\selectfont]
[...]
if [ ! -f /etc/dropbear/dropbear_rsa_host_key ]
then
  dropbearkey -type rsa -f /etc/dropbear/dropbear_rsa_host_key
fi

if [ ! -f /etc/dropbear/dropbear_dss_host_key ]
then
  dropbearkey -type dss -f /etc/dropbear/dropbear_dss_host_key
fi

/usr/sbin/dropbear
\end{lstlisting}
\end{frame}

\begin{frame}[containsverbatim]
\frametitle{SSH testen}
Vom Host-System:
\begin{lstlisting}[language=bash]
ssh root@192.168.2.2
\end{lstlisting}
\begin{verbatim}
root@localhost's password: 
#
\end{verbatim}
\end{frame}

\subsection{Filesystem für Remote Debugging vorbereiten}
\begin{frame}[fragile]
\frametitle{gdbserver und libthread\_db}
\begin{lstlisting}[language=bash]
$ cp /home/devel/CodeSourcery/Sourcery_G++_Lite/\
arm-none-linux-gnueabi/\
libc/lib/libthread_db.so.1 lib/

$ sudo cp /home/devel/CodeSourcery/Sourcery_G++_Lite/\
arm-none-linux-gnueabi/\
libc/lib/libdl.so.2 lib/

$ sudo cp /home/devel/CodeSourcery/Sourcery_G++_Lite/\
arm-none-linux-gnueabi/\
libc/usr/bin/gdbserver bin/
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Remotedebugging}
\begin{lstlisting}[language=bash]
$ arm-none-linux-gnueabi-gcc -Wall \
-Wextra -g -O0 \
-o cross_hello cross_hello.c
sudo cp cross_hello /tftpboot /nfsroot
\end{lstlisting}
\begin{lstlisting}[language=bash]
$ gdbserver :2345 /cross_hello 
Process /cross_hello created; pid = 65
Listening on port 2345
\end{lstlisting}
\begin{lstlisting}[language=bash]
$ arm-none-linux-gnueabi-gdb cross_hello
(gdb) set solib-absolute-prefix \
/home/devel/CodeSourcery/Sourcery_G++_Lite/\
arm-none-linux-gnueabi/libc
(gdb) target remote 10.10.0.Y:2345
Remote debugging using 10.10.0.Y:2345
[...]
\end{lstlisting}
\end{frame}
\end{document}
