Original-URL des Artikels: https://www.golem.de/news/reverse-engineering-wie-ich-linux-auf-dem-oszilloskop-installierte-1611-123612.html    Veröffentlicht: 21.11.2016 12:03    Kurz-URL: https://glm.io/123612

Reverse Engineering

Wie ich Linux auf dem Oszilloskop installierte

Die Open-Source-Community liebt es, Linux selbst auf vermeintlich geschlossenen Systemen zu installieren. Ich habe Linux auf einem Digital-Oszilloskop zum Laufen gebracht.

Ob Fernseher, Router oder Kinder-Handheld, die Liste der Geräte, auf denen Linux von Nutzern installiert wurde, ohne dass es der Hersteller vorgesehen hat, wird immer länger. Doch wieviel Aufwand steckt eigentlich dahinter? Welches Wissen ist notwendig, welche Software-Werkzeuge?

Christer Weinigel, freiberuflicher Ingenieur, hat in seinem Blog eine Artikelserie publiziert, in der er beschreibt, wie er ein Oszilloskop per Reverse Engineering analysiert hat und noch analysiert. Mit den dabei bereits erworbenen Kenntnissen über die Hardware und die Firmware gelang es ihm, eine lauffähige Linux-Installation aufzusetzen und auch die besonderen Fähigkeiten des Oszilloskops zur Signalanalyse unter Linux nutzbar zu machen.

Der Autor hat uns erlaubt, seine Artikel ins Deutsche zu übersetzen und dabei einige Kürzungen und Ergänzungen vorzunehmen, damit der Inhalt auch Einsteigern verständlich ist.

Ein Oszilloskop zum Hacken

Vor ein paar Jahren habe ich mir ein OWON-SDS7-102-Oszilloskop gekauft. Die Spezifikationen sahen gut aus: angemessene Bandbreite und Sampling-Raten, ein großes, helles Display, Akkubetrieb und Anschlüsse für USB und Ethernet. In der Praxis zeigten sich aber einige Macken, manches funktionierte nicht richtig.

Trotzdem war es mir als Zweitgerät nützlich. Zumeist musste ich die Übertragung einer I2C- oder SPI-Verbindung prüfen und dabei störten die Einschränkungen des Gerätes nicht. Sein großes Display und die intuitiv angeordneten Bedienungselemente machen es hier zu einem guten Werkzeug. Außerdem passt es in eine alte Laptoptasche, und weil es preiswert war, mache ich mir auch keine Gedanken, dass es beim Transport kaputtgehen könnte. Für unterwegs ist auch der Akkubetrieb von Vorteil.

Ich habe es aber auch noch aus einem anderen Grund gekauft. Andere Nutzer haben es bereits auseinandergenommen und deshalb wusste ich, dass darin ein System-on-a-Chip (SoC) von Samsung steckt sowie ein Spartan-6-FPGA. Mit beiden bin ich vertraut. Im Hinterkopf hatte ich die Idee, einmal ein wenig Reverse Engineering zu betreiben und damit Verschiedenes auszuprobieren. Zwei Jahre nach dem Kauf setzte ich die Idee in die Tat um.

Was ist Reverse Engineering?

Die Idee hinter Reverse Engineering ist es, ein fertiges System von jemandem anzuschauen und dessen Funktion und Entwicklung zu verstehen.

Es gibt bereits eine große Diskussion zum Oszilloskop im Forum des EEVBlogs und große Teile des Gerätes wurden bereits analysiert. Allerdings konzentrieren sie sich stark auf die analogen Parts, meine Neugier galt hingegen der digitalen Verarbeitung und der Firmware.

Das Oszilloskop wird zerlegt

Am Anfang wird das Gerät zerlegt, um herauszufinden, aus welchen größeren Bestandteilen es besteht. Ich öffnete das Oszilloskop und entfernte Bauteile, bis ich auf das Mainboard stieß, das die eigentliche Arbeit verrichtet.

Als Nächstes galt es, die wichtigsten Bauelemente auf dem Mainboard zu finden und eine Vorstellung davon zu entwickeln, wie sie zusammenarbeiten.

Die Bauteile auf der Frontseite

Hier ist die Seite der Mainboard-Platine zu sehen, die der Vorderseite des Oszilloskops zugewandt ist. Der Anschluss zur LCD-Platine ist in der oberen linken Ecke, eine Steckverbindung zum Frontpanel des Oszilloskops mit all seinen Tastern und Knöpfen ist in der rechten oberen Ecke. Der quadratische Chip im oberen Teil ist mit "Chrontel 7026B-TF" beschriftet. Eine kurze Internetsuche bestätigt, dass es sich um einen 7026B TV/VGA Encoder der Firma Chrontel handelt. Ansonsten gibt es nicht hier nicht viel zu sehen. Die Schaltkreise, an die die Tastköpfe des Oszilloskops angesteckt werden (Analog-Frontend - AFE), sind durch eine Abschirmung verdeckt. Ich will die Abdeckung lieber nicht entfernen, wenn ich nicht muss. Jemand namens tinhead hat das im EEVblog bereits getan.

Die Bauteile auf der Rückseite

Für mich deutlich interessanter ist die Rückseite mit ihren elektronischen Chips. Das quadratische Bauteil im oberen Teil ist ein Samsung-S3C2416-SoC. Links von der CPU befindet sich ein Metallobjekt mit dem Aufdruck 12.0000M. Bei solchen Metallteilen handelt es sich immer um einen Quarz, hier um einen 12MHz-Quarz für den SoC. Auf dem Bauteil rechts vom SoC ist Samsung K9F1G08U0C aufgedruckt. Eine schnelle Suche sagt mir, dass es sich um einen 128M-x-8Bit-NAND-Flash-Speicher handelt. Den sichtbaren Leiterbahnen auf der Platine nach ist er mit dem SoC verbunden, darauf ist wahrscheinlich die Firmware gespeichert. Das Bauteil unter dem SoC ist ein Hynix H5PS5162GFR - entweder ein 32- oder 64-MByte-DDR2-Speicherbaustein. Dessen Leiterbahnen führen ebenfalls zum SoC.

Der Chip rechts unterhalb des SoC ist ein Xilinx-Spartan-6-XC6SLX9-FPGA. Darüber befindet sich ein weiterer Hynix-DDR2-RAM-Baustein, dessen Leiterbahnen zum FPGA führen. Der Speicher nimmt vermutlich die analogen Messdaten auf. Eine große Anzahl von Leiterbahnen führen zu einem großen Bauteil mit einem National-Semiconductor-Logo darauf und den Bezeichnungen VE206ABE2 und S7002952. Eine direkte Internetsuche zu diesen Bezeichnungen ergibt zuerst keine Ergebnisse, aber nach einer intensiveren Recherche scheint es ein ADC08D500 zu sein, ein 8-Bit-Analog/Digital-Konverter (ADC). Er kann zwei Kanäle mit je 500 Msamples pro Sekunde oder einen Kanal mit 1 Gsample pro Sekunde analysieren. Das entspricht den Spezifikationen des Oszilloskops. Zwei verschiedene Paare von Leiterbahnen verschwinden unter der Abdeckung und scheinen die ADC-Daten vom Analog-Frontend zu liefern.

Links vom ADC befindet sich ein Bauteil, das mit ADF und 4360-7 beschriftet ist, es ist ein "350 to 1800MHz Integrated synthesizer and VCO" von Analog Devices. Die Bauteile darüber und links davon sind mit "0.100000" und "DCP1311 1315" markiert. Darüber konnte ich keine Informationen finden, aber ich vermute, es handelt sich um Quarzoszillatoren, die als Referenzquellen für den ADF4350-Synthesizer dienen.

Nahe des Ethernet-Anschlusses befindet sich ein Micrel-KSZ8851-Single-Port-Ethernet-MAC/PHY. Daneben befindet sich wieder ein Metallobjekt mit der Aufschrift L25.000M, von dem zwei Leiterbahnen zu den Taktpins des KSZ8851 führen. 25 MHz ist eine typische Frequenz für Ethernet-Chips - und das ist offensichtlich der zugehörige Taktquarz.

Schließlich gibt es noch ein Bauteil mit der Aufschrift AT88SC 0401CA, für das ich kein direktes Datenblatt finden konnte. Wahrscheinlich ist es ein Krypto-Chip von Atmel, der die Seriennummer des Gerätes enthält und verifizieren kann.



Auf der Suche nach neuen Kontakten

Oft sind die Bauteile einer Schaltung interessant, die sich nicht auf der Leiterplatte befinden. Einige Bauteile sind nur während der Software-Entwicklung notwendig, aber nicht für die Massenproduktion. Dazu zählen Anschlüsse für eine serielle Schnittstelle zur Ausgabe von Debug-Meldungen und ein JTAG-Programmierer, um Software zu laden und zu debuggen.

Oberhalb des SoC gibt es vier Kontakte für Pins, die ein serieller Anschluss sein könnten, in der linken oberen Ecke sind zehn weitere Kontakte, die womöglich für einen JTAG-Programmierer bestimmt sind. Drei weitere Kontakte zwischen dem VGA- und USB-B-Anschluss könnten ein weiterer serieller Anschluss sein.

Zuerst probiere ich die vier Pins über dem SoC aus, doch dort erhalte ich keinerlei Signale. Mehr Erfolg habe ich mit den Kontakten neben dem VGA-Anschluss. Der mittlere Pin erweist sich als der Massekontakt, die beiden anderen als Transmitter- und Receiver-Leitung eines seriellen Anschlusses.

Nachdem ich einen USB-zu-Seriell-Adapter an die Pins angeschlossen habe, stelle ich mein Terminalprogramm auf 115200 BPS ein und schalte das Oszilloskop an. Ich bekomme tatsächlich eine Ausgabe:



Lilliput ist das Unternehmen hinter der OWON-Marke.

Die Ausgabe ist vielversprechend. Doch nichts passiert, als ich Y oder Enter drücke. Der Bootloader setzt stattdessen seine Arbeit fort und lädt die Firmware des Oszilloskops. Ich gebe an dieser Stelle erst einmal auf und will mein Glück mit dem JTAG-Anschluss versuchen.

JTAG verstehen

JTAG steht für Joint Test Action Group, ursprünglich ein Standard, um zusammengebaute Leiterplatinen zu prüfen. Über den sogenannten Boundary Scan ist es damit möglich, alle IO-Pins eines ICs damit zu steuern, und er wird verwendet, um zu prüfen, ob diese korrekt verbunden sind. Für ICs mit einem Prozessor, wie die ARM-CPU im Samsung-Chip, fungiert er als Debug-Schnittstelle.

Ein JTAG-Anschluss muss mindestens vier Pins haben: Test Clock (TCK), Test Mode Select (TMS), Test Data In (TDI) und Test Data Out (TDO). Optionale Pins sind Test Reset (TRST), um den Anschluss zurückzusetzen und System Reset (SRST), womit das ganze System neustartet. Üblicherweise steht auch ein VREF-Pin als Spannungsreferenz für die übrigen Pins zur Verfügung wie auch ein Masseanschluss (GND).

Das sind ein halbes Dutzend Kontakte, die beliebig angeordnet werden können. Manchmal haben Leiterplatinen gar keinen JTAG-Anschluss, sondern die JTAG-Kontakte sind als Testkontakte über die Platine verteilt. Manchmal ist der Anschluss auch hinter einem Aufkleber versteckt oder befindet sich auf einem Platinenteil, der nach der Herstellung abgebrochen wird.

Auf dem Mainboard des Oszilloskops gibt es Platz für einen 2-x-5-Anschluss, der sehr erfolgversprechend aussieht. Beim Test mit dem Multimeter ergibt sich, dass die fünf Pins der einen Seite mit der Stromversorgung und der Masse verbunden sind, die anderen Pins sind mit Widerständen verbunden. Wenn es sich um einen JTAG-Anschluss handelt, dann müssten vier Pins die Pflichtpins sein, der fünfte ein Reset-Pin oder überhaupt nicht angeschlossen. Es gibt eine Liste von Pinbelegungen, aber dort ist nur ein Bruchteil der Möglichkeiten verzeichnet. Und keine der Belegungen stimmt mit der vorliegenden überein.

Es gibt ein Projekt namens JTAGulator, das anhand eines selbstgebauten Testers alle möglichen Kombinationen durchprobiert. Auf der Webseite sind auch einige interessante Vorträge und Videos, die zeigen, wie die JTAG-Schnittstelle in einem Gerät bestimmt werden kann. Zum Glück muss ich mich nicht tiefer damit befassen. Tinhead hat auch die Belegung bereits ermittelt und im EEVblog-Forum gepostet, wie ich herausfand.

Die Belegung sieht wie folgt aus:



Ich lötete einige Kabel an den JTAG- und den seriellen Anschluss. Dann baue ich das Oszilloskop wieder zusammen und führe die Kabel nach außen.

Die losen Kabel liegen am seriellen Anschluss. Die Buchsenleiste führt zum JTAG-Anschluss und die Belegung funktioniert mit einem Bus Blaster MIPS, das ich besitze.



OpenOCD zum Debuggen

OpenOCD ist ein Werkzeug, um über JTAG-Adapter mit der Debug-Schnittstelle auf einem Chip zu kommunizieren. Es unterstützt neben anderen auch meinen Bus Blaster als JTAG-Debug-Adapter. Das Programm bietet zwar keine direkte Unterstützung für den verbauten Samsung-SoC, allerdings tun das einige andere Modelle aus Samsungs S3C-Familie - und sie scheinen sich stark zu ähneln.

Die Dokumentation von OpenOCD ist nicht sonderlich gut. Aber nach einigem Trial and Error habe ich eine funktionierende openocd.cfg:



OpenOCD zeigt nach dem Start an, dass es etwas gefunden hat:



Jetzt kann ich mich mit OpenOCD verbinden und Dinge ausprobieren.



Damit wird die CPU angehalten und führt CPU-Anweisungen im Einzelschrittmodus aus. Entsprechend des Speicher-Mappings laut dem Datenblatt des S3C2416 wird der DDR-RAM ab der Adresse 0x30000000 eingeblendet, die angezeigte Adresse 0x33c04664 liegt also in diesem RAM.

Jetzt kann ich herumspielen und Daten aus den Registern des SoC lesen und auch beschreiben. Für einen schnellen Test suche ich das Transmit-Register der seriellen Schnittstelle im Datenblatt. Es heißt UTXH0 und befindet sich an Adresse 0x50000020. Ich versuche, den Wert 0x55 (ASCII-Code für "U") in das Register zu schreiben: mww 0x50000020 0x55

Und tatsächlich: "U" wird über die serielle Schnittstelle ausgegeben. Jetzt weiß ich, wie ich Text ausgeben kann.



Flash-Speicher auslesen

Nachdem ich weiter im Datenblatt des SoC geblättert und es mit anderen Datenblättern der S3C-Familie verglichen habe, sieht es danach aus, als ob sie den gleichen Controller verwenden, um den NAND-Flash-Speicher anzusprechen wie den S3C2412, der von OpenOCD unterstützt wird. Ich ergänze die openocd.cfg entsprechend: nand device 0 s3c2412 s3c2416.cpu

Ich starte OpenOCD neu und teste den Zugriff auf den Flash-Speicher:



Wunderbar! Wenn der S3C2416-SoC vom Flash-Speicher bootet, lädt der die ersten 8 KByte in den internen SRAM an der Adresse 0x40000000. Ich probiere, den Inhalt des Speichers in einer Datei zu speichern:



Der Inhalt der Datei sieht nach ARM-Maschinencode aus. Jetzt will ich den kompletten Inhalt des Flash-Speichers. Allerdings würde das Herunterladen von 128 MByte über die Schnittstelle mit 1 MHz sehr langsam sein. Ich probiere, die Übertragungsgeschwindigkeit anzuheben. 30 MHz funktionieren nicht, aber 20 MHz klappen. Also ändere ich openocd.cfg erneut:



Mit einer ARM-CPU gibt es allerdings noch weitere Möglichkeiten, den Vorgang zu beschleunigen. Indem OpenOCD ein wenig RAM auf dem Oszilloskop benutzen darf, kann es etwas ARM-Code hochladen und auf der CPU ausführen, anstatt Code Zeile für Zeile auszuführen. Ich ändere die Konfigurationsdatei erneut. Der Code wird dabei am Ende des DDR-RAMs platziert (0x30000000 + 64MByte - 1MByte = 0x33f00000):



Danach weise ich OpenOCD an, loszulegen:



Doch selbst mit dieser Beschleunigung würde der Download grob überschlagen mindestens zehn Stunden dauern. Also gehe ich erstmal nach Hause.

Allerdings übersehe ich dabei, dass ich aus Sicherheitsgründen die Stromversorgung abgesteckt habe und das Gerät im Batteriebetrieb läuft. Als ich am nächsten Tag ins Büro zurückkehre, ist das Oszilloskop aus und der Dump unvollständig. Allerdings kann ich die Übertragung erneut starten.

So habe ich nach zwei Tagen einen vollständigen Dump des Flash-Inhaltes. Sollte ich bei zukünftigen Experimenten Mist bauen, kann ich den Flash wieder auf den Werkszustand zurücksetzen.



Register auslesen

Als Nächstes schreibe ich ein kleines Skript für OpenOCD, um den Inhalt der SoC-Register über JTAG auszulesen. Die folgenden OpenOCD-Kommandos zeigen zum Beispiel die Konfiguration des GPIO-Port C an:



Allein mit dem Blick auf die Register gibt es schon Einiges zu entdecken. Die Registerdaten zusammen mit dem Datenblatt für den SoC helfen mir, herauszufinden, wie die Hardware konfiguriert ist.

An der Adresse 0x56000020 steht das GPIO-C-Control-Register (GPCCON). Es legt fest, wie die GPIO-Pins konfiguriert sind. Jedem Pin im Register sind zwei Bits zugewiesen. Der Wert 00 heißt, der Pin ist ein Input-Pin, 01 ein Output-Pin und 10 weist dem Pin eine spezielle Funktion zu. Die Pins 5, 6 und 7 sind als Output definiert, die übrigen mit speziellen Funktionen. Bei Port C heißt das, sie werden für die Videoausgabe benutzt. Das Register an Adresse 0x56000024 (GPCDAT) zeigt den aktuellen Zustand der Pins dieses Ports und 0x56000028 (GPCUDP) steuert aktiviert Pull-up- beziehungsweise Pull-down-Widerstände an den Pins.

Die Belegung für die Videoausgabe-Pins habe ich mir notiert:



Ein Großteil der Pins an den Ports C und D steuert das LCD an. Indem ich die Register des Display-Controllers im SoC auslese, erhalte ich die LCD-Konfiguration: Länge des Sync-Signals, Videotaktrate und so weiter.

Mit Port A funktioniert es genauso:



Jeder Pin benutzt aber nur ein Bit in 0x56000000 (GPACON). Die 0 steht für einen Output-Pin, 1 entspricht einer Spezialfunktion.

Die Pins GPA17 bis 22 dienen zur Ansteuerung des NAND-Flash-Speichers, wie er auch auf dem Mainboard verbaut ist. Allerdings scheinen andere, wie GPA 25 und 26, weniger sinnvoll. Sie sind für eine Spezialfunktion konfiguriert. Die Pins (DQM2 und 3) sollten mit 32 Bit breiten SDRAM verwendet werden, aber der verbaute Hynix SRAM ist nur 16 Bit breit. Entweder handelt es sich dabei um die Standardkonfiguration des Chips oder der Firmware-Code enthält Überbleibsel aus früheren Versionen.

Wenn Pins als Output konfiguriert sind, ist es auch lehrreich, einfach ihren Zustand zu ändern. Schalte ich GPA1 oder GPA2, höre ich ein Klickgeräusch im Inneren des Oszilloskops. Wahrscheinlich schalten sie Relais im Analog-Frontend. Das ist praktisch, wenn mit der Zustandsänderung ein Geräusch verbunden ist, die anderen Pins muss ich dagegen durchmessen, um zu sehen, was sie tatsächlich tun.

Der erste Versuch mit Linux

Praktisch habe ich jetzt alles, was notwendig ist, um Linux für das Oszilloskop zu portieren. Mit den Registerdaten dauert es nur drei Abende, Linux auf dem Oszilloskop mit einer seriellen Konsole und einer Busybox-Shell zu starten.

Linux unterstützt den SoC und die meisten seiner Funktionen bereits. Ich werde nicht zu tief in die Details gehen, aber im Prinzip geht es allein darum, die Werte aus den Registern in die existierenden Treiber einzubauen.



Trotzdem ist es nicht ganz einfach



Zuerst probiere ich, einen Device Tree zu bauen, um den Kernel für die Hardware zu konfigurieren. Allerdings funktioniert das nicht. Das Device-Tree-Konzept war noch im Entstehen begriffen, als die Unterstützung für den SoC im Kernel hinzugefügt wurde. Nachdem ich einen Tag damit verschwendet habe, finde ich heraus, dass die Device-Tree-Unterstützung für den SoC nie fertiggestellt wurde, die Infrastruktur für Taktraten und Interrupts ist im Mainline-Kernel sogar komplett kaputt.

Ich beschließe, die Unterstützung im Linux-Kernel für den SoC wie in früheren Zeiten zu implementieren: per Maschinendatei. Also packe ich die Hardware-Konfiguration in die mach-smdk2416-Datei. Sie wird zur Konfiguration der Samsung-Referenz-Plattform des S3C2416-SoC verwendet, und damit geht es.

Allerdings habe ich auch noch einige Probleme mit OpenOCD. Wenn der Linux-Kernel bootet, müssen die MMU und die Caches des SoC deaktiviert werden. Das soll mit dem "mcr"-Kommando in OpenOCD möglich sein, bei mir funktioniert es aber nicht. Wenn ich OpenOCD gestartet habe, die Verbindung hergestellt ist und ich "halt" eingeben habe, hat der Bootloader im Oszilloskop längst die MMC und die Caches aktiviert.

Wenn es mir aber gelingt, den Bootloader schnell genug zu stoppen, nachdem ich das Oszilloskop angeschaltet habe, dann hat der erste Teil des Bootloaders den SDRAM-Speicherkontroller bereits konfiguriert, aber noch nicht die MMU. Ich probiere, das Oszilloskop mit der einen Hand anzuschalten und mit der anderen Hand einen Kommandozeilenaufruf auszulösen:



Stimmt mein Timing, dann füllt der Bootloader den SDRAM nur mit Null auf und ich kann danach meinen eigenen Code ausführen.

Linux-Start

Mit Buildroot erzeuge ich ein gepacktes Linux-Image mit einer RAM-Disk, die Busybox enthält. So hätte ich eine Shell und eine Kernel-Kommandozeile auf dem Oszilloskop zur Verfügung. Das eigenständige Paket in einer Datei im zImage-Format kann ich per JTAG übertragen und benötige lediglich eine CPU und SDRAM zur Ausführung. Ich weise Linux an, auf dem ersten seriellen Anschluss, UART0, Debug-Meldungen auszugeben. Außerdem ergänze ich den Startup-Code im Kernel um einige Anweisungen, damit einige Register korrekt gesetzt werden.

Um den Kernel zu booten, verbinde ich mich wieder mit OpenOCD. Um sicherzugehen, überschreibe ich die Interrupt-Register, um jegliche Interrupts zu deaktivieren. Dann lade ich das zImage in den RAM und führe es aus:



Mich überkommt ein Glücksgefühl, als der Linux-Kernel tatsächlich bootet:



Allerdings komme ich nicht weit. Der Ausschnitt stammt noch von meinen ersten Versuchen mit dem Device Tree, und da die Timer-Interrupts nicht funktionierten, kam der Start nie über "Calibrating delay loop..." hinaus. Doch am nächsten Tag, mit dem Kernel ohne Device Tree, bootet das System bis zur Shell auf der seriellen Konsole.

Gerätetreiber

Danach aktiviere ich einen Gerätetreiber nach dem anderen. Da ich die notwendigen Konfigurationsdaten für das LCD schon habe, fange ich damit an. Ich muss wirklich nur die Werte in die mach-smdk241-Datei eintragen.

Der USB-Host-Anschluss benötigt keine weitere Konfiguration, er funktioniert einfach. Ich kann eine USB-Maus anstecken. Beim Ein- oder Ausstecken einer USB-Festplatte dagegen hängt der Kernel. Allerdings denke ich, dass dort ein elektrisches Problem vorliegt. Ich merke, dass ich nicht mal die Festplatte einstecken muss, schon die Berührung der Abschirmung des USB-Steckers mit der Buchse stoppt den Kernel. Mich interessiert wirklich, was da fehlschlägt, doch ich mache erst einmal weiter.

Der USB-Client-Anschluss ist etwas komplizierter. Linux nimmt an, dass der Takt von einem der Taktgeber der CPU auch den USB-Takt vorgibt und mit 48 MHz läuft. Das ist im Treiber hardcodiert. Der SoC verhält sich aber anders und die Konfiguration ist laut Datenblatt eigentlich inkorrekt. Aber schließlich gelingt es mir, den Treiber umzuschreiben - und dann funktioniert es.

Auch der Flash-Speicher funktioniert. Aufwendig ist nur, die richtige Syntax für das mtdpart-Argument für den Linux-Kernel-Kommandozeilenaufruf herauszufinden. Dann kann ich das Werkzeug nanddump benutzen, um den Inhalt des Flash-Speichers auszulesen. Dessen Ausgabe entspricht der Ausgabe über OpenOCD.



Wie es weitergeht

Das war alles soweit recht einfach - alle Funktionen befinden sich im SoC und die Konfiguration kann ich aus den Registern auslesen.

Der Ethernet-Controller ist hingegen ein externer Chip und ich brauche länger dafür. Ich muss die Firmware des Oszilloskops dafür disamblieren. Danach wird mir allerdings klar, dass die Anbindung des Ethernets identisch zum Referenz-SMDK2416-SoC ist. Es werden die gleichen Pins des SPI-Busses verwendet und der gleiche Chip-Select-Pon. Der einzige Unterschied ist die Anbindung der Interrupt-Leitung. Ich hätte Einiges an Aufwand gespart, wenn ich mir vorher die Referenz-Implementierung angeschaut hätte. Doch dazu in einem späteren Artikel mehr.

Zurzeit ist die Ethernet-Verbindung recht langsam. Es gelingt mir nicht, den Highspeed-SPI-Controller zum Laufen zu bekommen. Stattdessen konfiguriere ich die SPI-Pins als GPIOs und benutze den SPI-Treiber im Treiber, der per Bitbanging arbeitet. Die Transferrate beträgt rund 1 Mbit über die Ethernet-Verbindung. Aber der Chip unterstützt 100-Mbit-Ethernet und die SPI-Verbindung kann mit einem 40-MHz-Takt betrieben werden, eine entsprechende Transferrate sollte also möglich sein.

An diesem Punkt ist das Oszilloskop ein funktionierendes Linux-System mit einem Display, USB-Host- und Client-Anschluss, Flash-Speicher und Ethernet. Das ist nach ein paar Abenden kein schlechtes Ergebnis.

Es sollte mir nun möglich sein, einen angepassten Bootloader für den SoC zu schreiben und Linux vom Flash-Speicher zu laden.

Im nächsten Artikel analysiert Christer Weinigel den Bootprozess und das Dateisystem des Oszilloskops - mit einer überraschenden Erkenntnis.

Christer Weinigel ist freiberuflicher Ingenieur in seinem eigenen Unternehmen (Weinigel Ingenjörsbyrå AB). Er entwickelt hardwarenahe Software, arbeitet mit Embedded Betriebssystemen und spielt deshalb auch öfters direkt mit Hardware.  (crw)


Verwandte Artikel:
Reverse Engineering: Das Xiaomi-Ökosystem vom Hersteller befreien   
(23.02.2018, https://glm.io/132878 )
Librem 5: Purism-Smartphone bekommt Smartcard für Verschlüsselung   
(09.03.2018, https://glm.io/133248 )
Kernel: Microsoft patcht Code-Execution-Lücke im Kernel   
(14.02.2018, https://glm.io/132759 )
CPU-Architektur: Western Digital will 2 Milliarden RISC-V-Kerne im Jahr   
(30.11.2017, https://glm.io/131428 )
Bilderkennung: Roboter löst Rubik's Cube in 380 Millisekunden   
(08.03.2018, https://glm.io/133228 )

© 1997–2019 Golem.de, https://www.golem.de/