\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 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}