##Ergänzung Heimarbeitstutorial

Dies ist eine Ergänzung zum Heimarbeitstutorial des Betriebssystempraktikums.
Ich habe hier dem Gedächtnis nach aufgeschrieben, was ich noch beachten musste.
Das Betriebssystem, das ich zum Compilieren und für den TFTP-Server verwendet habe, ist Arch Linux.
Bei einem anderen Betriebssystem müssen die Befehle gegebenenfalls angepasst werden.

Ich erhebe keinen Anspruch auf Vollständigkeit und übernehme keine Haftung für Schäden. Jeder ist für sein Handeln selbst verantwortlich. Dies ist nur als Hilfestellung für die Einrichtung der Toolchain zu Hause gedacht.

##1. Linux

War bei mir schon installiert. Gegebenenfalls nachinstallieren oder in einer VM.

##2. ARM Toolchain

1. Ordner toolchain unter /home/<Benutzername>/toolchain machen.

2. Makefile in /home/<Benutzername>/toolchain speichern und ausführen.

Bei mir hat das Makefile einmal mit einer Fehlermeldung gestoppt. Es konnte in irgendeiner Header-Datei (den Namen habe ich vergessen) Z. 6 <capstone.h> nicht finden. <capstone.h> durch <capstone/capstone.h> ersetzen hat die Sache gefixt.

3. Evtl. erneut Makefile ausführen.

$ make

##3. RaspberryPi mit USB UART ausstatten

Ich habe statt screen minicom benutzt:

1. Minicom installieren

$ sudo pacman -S minicom

2. Minicom konfigurieren

$ sudo minicom -s

- Auf 'Einstellungen zum seriellen Anschluss' gehen, Enter
- Taste F drücken, Es sollte nun unter anderem zu sehen sein: F - Hardware Flow Control    : Nein
	(Wenn Hardware Flow Control auf Ja gesetzt ist, wurden bei mir die Zeichen, die ich eingetippt habe, nicht übermittelt, ich bin also sonst nicht auf die U-Boot-Konsole gekommen.)
- Enter zum Bestätigen
- Auf 'Speichern als >>dfl<<' gehen
- Auf 'Minicom beenden' gehen

3. Minicom starten

$ sudo minicom -D /dev/ttyUSB0

##4. Bootloader U-Boot

Die MicroSD Karte hatte eine Partitionstabelle vom Type dos. (Also nicht gpt, kann mit 'sudo fdisk -l' nachgeguckt werden. Ich habe es nicht ausprobiert, ob gpt auch funktioniert, eventuell spielt es also keine Rolle.)

Als Partitionstyp habe ich 'c  W95 FAT32 (LBA)' in fdisk ausgewählt.

Folgende Dateien habe ich aus der zip-Datei von Isis auf die MicroSD-Karte übertragen:

bootcode.bin
kernel7.img
start.elf

Mit TTL-UART-Kabel Raspberry Pi und Rechner verbinden.
Falls beim Hochfahren des Raspberry Pi kein Text auf der minicom-Konsole erscheint, nachgucken, ob die TXD- und RXD- Kabel vertauscht wurden. Das RXD-Kabel des Konverters muss auf den TXD-Pin des Raspberry und umgekehrt.

Beim Start des Raspberry zu gegebener Zeit eine Taste drücken, um autoboot zu verhindern.  Der U-Boot-Prompt sollte erscheinen.

Ich habe als Server-IP 10.0.0.2 gewählt. (Welche IP man wählt, ist im Prizip egal, es wird aber später nochmal wichtig, dies muss dann gegebenenfalls angepasst werden.) Den Parameter ipaddr nur setzen, wenn die IP-Adresse später statisch sein soll (also ohne einen DHCP-Server zugeordnet werden soll).

U-Boot> setenv autoload yes
U-Boot> setenv autostart yes
U-Boot> setenv bootfile kernel.img
U-Boot> setenv ipaddr 10.0.0.1
U-Boot> setenv serverip 10.0.0.2
U-Boot> setenv loadaddr 0x8000
U-Boot> saveenv

Als nächstes wird U-Boot so umgestellt dass er automatisch durch tftp bootet.
Laut [1] führt U-Boot zuerst bootcmd aus. Ich habe mir das Skript und die daraus resultierenden Startvorgänge angesehen:

U-Boot> printenv bootcmd
bootcmd=run distro_bootcmd
U-Boot> printenv distro_bootcmd
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done
U-Boot> printenv boot_targets
boot_targets=mmc0 usb0 pxe dhcp
U-Boot> printenv bootcmd_mmc0
bootcmd_mmc0=setenv devnum 0; run mmc_boot
U-Boot> printenv bootcmd_usb0
bootcmd_usb0=setenv devnum 0; run usb_boot
U-Boot> printenv bootcmd_pxe
bootcmd_pxe=run boot_net_usb_start; dhcp; if pxe get; then pxe boot; fi
U-Boot> printenv bootcmd_dhcp
bootcmd_dhcp=run boot_net_usb_start; if dhcp ${scriptaddr} ${boot_script_dhcp}; then source ${scriptaddr}; fi;setenv efi_fdtfile ${fd;

Offensichtlich werden alle Möglichkeiten aus boot_targets probiert. Diese starten jeweils ein Skript, welches dann den bootspezifischen Bootvorgang ausführt. TFTP ist offensichtlich nicht dabei. Ich habe durch ausprobieren herausgefunden, dass man jedoch, falls man den TFTP-Server schon am laufen hat, durch 'tftpboot' in U-Boot direkt dadurch booten kann. Dies wollte ich jedoch nicht jedes Mal per Hand machen. Daher habe ich tftp zu den boot_targets hinzugefügt:

U-Boot> setenv boot_targets 'tftp '${boot_targets}
U-Boot> setenv bootcmd_tftp 'tftpboot'
U-Boot> printenv boot_targets
boot_targets=tftp mmc0 usb0 pxe dhcp
U-Boot> saveenv
Saving Environment to FAT...
writing uboot.env
FAT: Misaligned buffer address (07b3dd68)
done

Das Skript bootcmd_tftp wird dann automatisch aufgerufen und führt 'tftpboot' aus.

##5. TFTP Server

In Arch:

sudo pacman -S atftp
sudo chmod -R 777 /srv/atftp/

Im Makefile Z. 57 TFTP_PATH = /srv/atftp/ setzen.
$ cat /etc/config/atftpd:

# Parameters to be passed to ATFTPD
ATFTPD_ARGS="--no-multicast --maxthread 20 --verbose=6 /srv/atftp"
USE_INETD=false

TFTP-Server starten:

$ sudo systemctl start atftpd.service

##6. IP-Adressen

Damit der Raspberry sich das Image vom Rechner holen kann, braucht er eine IP-Adresse.
Diese könnte er dynamisch vom Rechner bekommen, wenn man auf diesem neben dem TFTP-Server noch einen DHCP-Server laufen lässt.
Ich wollte dies nicht da ich nicht das Risiko eingehen wollte, in meinem Heimnetzwerk zwei DHCP-Server laufen zu haben. Es gibt Möglichkeiten, so etwas zu umgehen. Ich habe mich jedoch noch nicht damit beschäftigt.
Ich habe daher die Variante der statischen IP-Adressen gewählt.

Daher habe ich auch weiter oben im U-Boot promt den Parameter ipaddr gesetzt. In meinem Fall hat der Raspberry die IP-Adresse 10.0.0.1 und der Rechner die IP-Adresse 10.0.0.2.

Ich habe den Raspberry Pi über ein Ethernet-Kabel mit dem Rechner verbunden und somit ein extra Netzwerk geschaffen.

Ermitteln des Namens der Netzwerkkarte:

$ ip addr show

(Nach etwas suchen das so ähnlich wie eno1. dies entsprechend einsetzen)

IP-Adresse statisch hinzufügen (ist nur bis zum nächsten Bootvorgang gesetzt)
$ sudo ip addr add 10.0.0.2/24 dev eno1

Ich habe außerdem eine Internetverbindung beim Networkmanager mit nm-connection-editor erstellt. Dies kann auch nicht graphisch mittels "nmcli connection add ..." erfolgen:

Name Ethernet-Lokal
Gerät (Mac Adresse einstellen)
IPv4-Einstellungen: Manuell, Adresse 10.0.0.2, Netzmaske 24, Gateway leer lassen

Verbindung aktivieren:
$ nmcli con up Ethernet-Lokal

##7. Automatisierung

Manche dieser Befehle müssen jedes Mal nach reboot ausgeführt werden, daher habe ich folgendes Skript erstellt:

$ setup_Raspberry

#!/bin/bash

#add 10.0.0.2 as IP address for eno1
sudo ip addr add 10.0.0.2/24 dev eno1 || echo $0": adding ip address 10.0.0.2 to eno1 failed."

#start tftp server
sudo systemctl start atftpd.service || echo $0": starting tftpd.service failed."

# set connection to Ethernet on
nmcli connection up Ethernet-Lokal || echo $0": starting connection 'Ethernet-Lokal' failed."

#start minicom
sudo minicom -D /dev/ttyUSB0 || echo $0": minicom failed."

Dieses kann in einen Ordner eingefügt werden, der in der PATH-Variable steht. Mit chmod +x ausführbar machen.

##8. Bootvorgang vorgehensweise

Folgendes muss regelmäßig (nach einem Bootvorgang des Rechners) getan werden:

1. Im Ordner vorgaben:

$ make home

2. Rechner und Raspberry mit USB-TTL-UART-Kabel verbinden (falls noch nicht getan).

3. Rechner und Raspberry mit Ethernet-Kabel verbinden(falls noch nicht getan).

4. $ setup_Raspberry

5. Raspberry starten/resetten

Folgendes muss getan werden, wenn ein neuer kernel erzeugt wurde:

1. $ make home
2. Raspberry starten/resetten

Quellen:

https://www.linuxjournal.com/content/handy-u-boot-trick [1]
https://wiki.archlinux.org/index.php/TFTP
https://askubuntu.com/questions/22835/how-to-network-two-ubuntu-computers-using-ethernet-without-a-router
https://askubuntu.com/questions/638378/minicom-doesnt-work
https://ask.roboflow.ai/question/16726559
https://kasiviswanathanblog.wordpress.com/2017/11/24/booting-linux-kernel-from-tftp-and-nfs-file-system-for-pandaboard/
http://she-devel.com/Laptop-to-target-network.html
https://www.beyondlogic.org/compiling-u-boot-with-device-tree-support-for-the-raspberry-pi/
https://wiki.dave.eu/index.php/BELK-TN-004:_Managing_both_Ethernet_ports_with_U-Boot_(BoraEVB/BoraXEVB)