Regelmatig vervang ik de standaard firmware van fabrikanten door iets dat veel beter werkt. Dat is niet altijd gemakkelijk. Maar de bewust geplaatste boobytrap van Western Digital om het apparaat onbruikbaar te maken, ben ik niet eerder tegengekomen. Gelukkig is er een geheime bootprompt...
Henk van de Kamer
In oktober 1984 kocht ik een Commodore 64. De spelletjes waren leuk, maar al snel wilde ik deze zelf kunnen maken. Dat betekende sprites en geluid uitzoeken. Dat leidde weer tot het leren van machinetaal. Tijdens het uitpluizen van de Kernal - geen tikfout van mij! - ontdekte ik hoe de C64 dankzij een in de processor hard gecodeerde JMP ($FFFC) opstart en uiteindelijk de READY-prompt op het scherm toont.
Ontstaan Unix
De C64 verving ik begin 1990 door een 80286. Deze start globaal op dezelfde manier. Helaas kunnen we dat over de huidige Core iN – jij mag zelf die N invullen – niet meer zeggen. Intel start als eerste een verstopte processor en besturingssysteem vóórdat de processor waar wij op werken aan zijn taak begint. Ik ben nog steeds bezig met het onderzoek voor dit verhaal, maar ik vermoed dat slechts een handjevol mensen op deze wereld exact weet wat voor stiekeme dingen er allemaal worden uitgespookt.
Vorig jaar oktober kocht ik het boek Unix: A History and a Memoir van Brian Kernighan. Na het lezen ontstond bij mij het plan om het wiel opnieuw uit te vinden. Of wellicht beter omschreven: vanaf niets een ‘dode’ processor tot leven wekken. Gemakkelijk? Tegenwoordig is het heel gebruikelijk om een compleet besturingssysteem te compileren op een bestaande computer en daarmee de nieuwere generatie te starten. Ook dat proces is ondertussen zo complex geworden dat bijna niemand meer weet hoe dat voor de eerste generatie werkte. Daar hadden we immers geen vorige versie om ons te helpen!
De aanleiding: het boek Unix: A History and a Memoir |
Een extra eis aan mijn experiment is daarom het niet-direct gebruiken van andere computers. Ik moet dit enigszins nuanceren: ik mag een computer gebruiken om dingen op internet op te zoeken. Ook mag ik deze hulpcomputer gebruiken om de informatie te testen. Ik heb namelijk weinig zin om weken te verspillen aan experimenten die gebaseerd zijn op onjuiste of onvolledige informatie. Zodra echter duidelijk is hoe de gekozen processor tot leven kan worden gewekt, moet alles uitgevoerd worden zonder hulp van een andere processor. Omdat bijvoorbeeld een sd-kaart, usb flashdrive of SATA-harddisk allemaal een verstopte processor hebben, zorgt deze extra eis voor een heuse uitdaging!
Mijn experiment bevindt zich op dit moment in de planningsfase. Ofwel: vooral heel veel lezen en nadenken. Voor zover ik uit literatuuronderzoek kan nagaan, moet mijn idee met een Cortex M0-processor uitgevoerd kunnen worden. Dit is waarschijnlijk de meest simpele 32-bits ARM-processor. Als het daarmee lukt, is dat meteen een interessant startpunt voor de volgende stappen. Het kan bijvoorbeeld dienen in een terminal of voor het programmeren van een zwaardere ARM-processor, om zo uiteindelijk een volwaardige desktop te krijgen.
Met een Cortex M0-processor moet mijn project uitgevoerd kunnen worden |
Bricked
Mogelijk is bovenstaande uitleg erg vaag. Ook dit verhaal is nog in onderzoek. Waarom ik het dan nu al deels vertel? Tja, ik heb in het verleden al eens geschreven over de My Cloud NAS van Western Digital. De standaardsoftware van dat bedrijf is voor mij onbruikbaar en ik heb deze ondertussen via Debian Jessie en Stretch weten te upgraden naar Debian Buster. In deze laatste stap begonnen de U-Boot (de bootlader die op veel embedded systemen wordt gebruikt)-beperkingen die Western Digital bewust heeft ingebouwd, mij te irriteren. En om nieuwsgierige aagjes zoals ikzelf te straffen, is het geheel ook nog eens voorzien van een volwaardige boobytrap. Uiteraard heb ik deze bom doen afgaan, met als gevolg dat het systeem nu bricked is. De precieze details gaan voor deze aflevering te ver en kun je in mijn labjournaal (https://www.hetlab.tk/embedded/wd-my-cloud-bricked) nalezen.
Brom
De Engelse term bricked betekent zoiets als ‘veranderen in een steen’. Met andere woorden: het apparaat is voor de meeste mensen alleen nog maar bruikbaar om mee te gooien. Voor mij is het echter een ‘dode’ processor die nu in wanhoop het volgende aangeeft:
BootROM - 1.51
Booting from SPI flash
BootROM: Bad header at offset D4000000
...
BootROM: Bad header at offset D4E00000
Trying Uart
Snap je nu mijn uitstapje naar het vage plan dat ik hierboven beschreef? Op embedded systemen zit een zogenaamde SoC - System on a Chip. Deze bevat de processor, chipset en zaken als netwerk, usb, SATA en meer. De C64 waarmee we begonnen, had een in de processor ingebakken eerste instructie. Dat geldt ook voor de processor in deze SoC. In de C64 was op geheugenlocatie $FFFC een 8 kilobyte ROM (Read Only Memory)-chip aanwezig met daarin de code om het systeem op te starten. Bovenstaande SoC heeft iets soortgelijks en de uitvoer wordt via een eveneens aanwezige UART - Universal Asynchronous Receiver/Transmitter (oftewel seriële verbinding) - de buitenwereld ingestuurd. De BootROM, vaak afgekort tot BROM, op de Marvell Armada 375 SoC is 32 kilobyte groot, ofwel de helft van de hoeveelheid geheugen die de Commodore 64 (de verklaring van de naam) had.
Activeren UART-boot
Ondanks het 32 kilobyte grote programma zijn de mogelijkheden van de BROM veel beperkter dan de kleinere hoeveelheid in de C64. beperkt. Voor de Armada 370 is de nodige documentatie door Marvell vrijgegeven en deze lijkt grotendeels ook van toepassing op deze nieuwere variant. Er zou van verschillende media gestart kunnen worden, maar ik zie alleen SPI-flash voorbijkomen. En die is nou net door de boobytrap vernietigd.
Tijdens het opstarten wordt op de UART tevens geluisterd of er een acht-bytes code wordt verstuurd. Daarmee kunnen we het booten vanaf de verschillende media onderbreken. De Trying Uart doet hetzelfde zodra geen van de andere mogelijkheden is gelukt. Volgens de documentatie is de string 0xBB 0x11 0x22 0x33 0x44 0x55 0x66 0x77. Het leuke van Linux is dat alles - dus ook de seriële verbinding - gewoon als bestand wordt gezien. Daardoor kunnen we met de gebruikelijke opdrachten dit soort codes naar het seriële poort-‘bestand’ schrijven. Al snel had ik het volgende Bash-script:
#!/bin/bash
echo "Powercycle the WD My Cloud board..."
while true; do
echo -ne "\xbb\x11\x22\x33\x44\x55\x66\x77" > /dev/ttyUSB0
done
Zodra dit script wordt gestart, gaat het continue de acht bytes versturen. In een tweede terminal geven we de commando’s - in rood - uit figuur 1. De ‘raw’ in de eerste opdracht zorgt ervoor dat niet-afdrukbare (leg ik zo dadelijk uit) ASCII-codes in de uitvoer als punt worden getoond. Het hexdump-commando in de tweede opdracht toont de ontvangen tekens. Oftewel: in de eerste terminal versturen we opdrachten naar de Marvell-processor en de tweede toont diens antwoorden.
De geheime (Boot)prompt in de Marvell Armada 375-processor |
Zodra alles is gestart, voorzien we de printplaat uit de WD My Cloud van stroom. Tijdens de initialisatie stuurt deze alle ontvangen tekens terug zoals je in het eerste deel van figuur 1 ziet. Vervolgens zien we de eerste normale reactie zoals eerder ook al getoond. Nu wordt echter het standaard opstarten onderbroken, omdat de Marvell de speciale reeks ontvangt. De tweede regel is dus een (Boot)prompt, waarna het systeem nu grofweg elke seconde een NAK verstuurd. Diens hexadecimale waarde is 15h ofwel decimaal 21. Waarschijnlijk weet je dat de eerste 32 ASCII-codes geen normale tekens zijn, maar bedoeld voor opdrachten. Deze tekens hebben geen inhoud in de karaktertabel, vandaar dat ze niet-afdrukbaar worden genoemd. Zonder de ‘raw’ zouden we dit deel nooit te zien krijgen!
Xmodem
De NAK geeft aan dat de Marvell-processor nu een programma verwacht dat via het Xmodem-protocol wordt geüpload. Wie in een ver verleden op BBS’en programma’s downloadde, gaat nu glimlachen. Inderdaad zijn dit soort oude protocollen nog steeds nuttig!
De standaardinitialisatie onderbreken en een programma versturen met Xmodem kan met het kwboot-programma. Helaas struikelt dit over de (Boot)prompt die nieuwere Marvell-processoren versturen. Er is een patch te vinden, maar deze is nooit geaccepteerd. Als ik deze doorvoer en compileer, zie ik de Xmodem-upload beginnen, maar verder dan een tiental pakketjes (van elk 128 bytes) ben ik nooit gekomen. Ik heb de indruk dat de kwboot gewoon zijn ouderdom vertoont. Op dit punt ga ik voor nu dus even stoppen, wordt vervolgd.