Vialle LPE computer ontleding

Gestart door Maarten-t5, 20-05-2018 23:45:18

Vorige topic - Volgende topic

0 leden en 1 gast bekijken dit topic.

Maarten-t5

Een tijdje geleden heb ik de LPI installatie overgenomen die Arjen onlangs aanbood.  De set had wat aandacht nodig, maar was verder in goede staat. Na hem zelf ingebouwd te hebben is hij vorige week maandag goedgekeurd. Reden tot vreugde uiteraard :D Dat rijden voor 61 cent de liter bevalt erg goed.
Wat echter minder goed bevalt is het gebrek aan informatie en tools voor het 'zwarte' doosje dat heel het gebeuren aanstuurt. In mijn geval is dat een lpe6.6 computer van Vialle. Reden om er eens in te duiken. Aangezien een lpi ecu veel minder complex is dan een volwaardige ecu lijkt het me wel aardig om het proces bij te houden op het forum. Misschien dat het vermakelijk is.
Ik ben van plan om wat dieper op de materie in te gaan dus het zullen zeker in het begin geen korte posts worden met wellicht een wat hoog nerd gehalte.
Bij wijze van experiment zal ik wat stukken arceren die in principe geskipped kunnen worden zonder de draad kwijt te raken.

Zoals gezegd gebruikt mijn systeem een lpe6.6 computer. Omdat ik geen extra lpe6.6 computer heb en ik niet direct van plan ben om aan mijn goed werkende computer te rommelen zonder backup, had ik al eerder een beetje rondgevraagd voor een al dan niet defecte computer. Kim had er nog 1 liggen (defect volgens mij?) welke ik uit elkaar mocht trekken, alleen is dit een lpe5.6 computer. Hiervan is de printplaat en de gebruikte flash anders, maar omdat de microcontrollers identiek zijn is het een goede plek om te beginnen. In ieder geval tot ik ergens een lpe6.6 computer vandaan kan halen. Met een beetje geluk zijn lijkt de lpe6.6 ecu genoeg op zijn voorganger om de overgang niet al te moeilijk te maken.
Waar begin dan je met zoiets? Welnu voor mij is de eerste cruciale stap om uit te vinden wat voor type microcontroller er gebruikt word om het zaakje aan te sturen.


In het geval van LPE5.6 (en ook LPE6.6) staat het gewoon op de chip (dit is bij ecu's niet vanzelfsprekend) en gaat het om de Motorola (nu NXP) MC68HC11F1CFN4. Voor deze lijn microcontrollers is goede documentatie te vinden (kun je zo downloaden van de site van NXP). Dit geld ook voor bijna alle andere componenten op de printplaat, wat enorm helpt en ook niet vanzelfsprekend is. Bij Bosch ecu's zijn bijvoorbeeld bijna alle chips voorzien van modelnummers van Bosch zelf, waar geen documentatie bij te vinden is.
In de documentatie van de microcontroller staat beschreven hoe de architectuur in elkaar zit, hoe alle onderdelen van de micro aangestuurd worden, hoe de instructieset werkt, wat de pinout is etc.  Hieruit word later ook duidelijk waarom de LPE(5/6).6 twee identieke microcontrollers gebruikt  met elk hun eigen flash chip. In eerste instantie bestudeer ik bepaalde delen van de manual aandachtig (bijvoorbeeld het deel over memory) en later gebruik ik de manual constant om functies en de werking van bepaalde onderdelen van de micro in op te zoeken.


De volgende stap is het desolderen van de flash chips om ze uit te lezen. Wederom helpt het dat het type netjes op de chip geprint is, voor de chipreader moet je namelijk het juiste voetje bij de chip zoeken. De package van de chip is hetzelfde als die van de flash chip van een m44 ecu, maar de pinout is anders en de manier van lezen en schrijven ook. Gelukkig hadden we het juiste voetje liggen, dus ik kon hem direct uitlezen.


Als alles goed gaat heb je dan een bin file op je pc staan gevuld met binaire machinetaal, uitgedrukt in hex codes, die niet direct human readable is.  Om de code te analyseren ontkom je er niet aan om de file te disassembelen. Hiervoor zijn verschillende tools beschikbaar. Ik gebruik Ida,  een uitgebreid programma wat ook in de antivirus industrie gebruikt word. Om de bin in te laden open je hem met ida en geef je op om wat voor micro het gaat. In eerste instantie verander ik niets aan de parameters die je daarbij in kunt stellen kijk ik eerst eens waar ida mee op de proppen komt en waar eea te vinden is in de bin.


Een wat teleurstellend resultaat, maar dat is niet onverwacht. Ida heeft geen code gedisassembled en laat alleen de hex code zien (aangegeven met het lichtbruine kleurtje in de balk boven.  Echter kun je nu wel makkelijker door de bin heen scrollen om te kijken waar de groepen data zich bevinden.
De reden dat er niets is gedisassembled is dat de code niet op de juiste plaats ingeladen is. De m68hc11f1 micro is 8-bits, met een 16 bit adressenbus. Dit betekend dat hij 65535 verschillende locaties (16 binaire enen op een rij is 65535 in ons decimale systeem) kan aanspreken. Dit vertaald zich naar 64 kilobyte aan adresruimte voor alle verschillende vormen van geheugen (alle soorten geheugen in dit type micro delen dezelfde adressenruimte). De flash is echter 256 kilobit, ofwel 32 kb groot, dus er is een hoop lege adresruimte over. Dit betekend dat de data op de flash chip niet per sé aan het begin van de adresruimte hoeft te staan, maar een offset kan hebben. Deze offset kun je invoeren in ida, maar dan moet je wel weten wat deze moet zijn anders kloppen de verwijzingen naar subroutines in de code niet en kan ida niet automatisch disassembelen.  Je kunt dan wel handmatig stukken code disassembelen, waarna ik in de code referenties naar subroutines zag die vrij hoog in de adresruimte zou moeten staan.

Mijn intuïtie vertelde mij om de data in de flash op te schuiven zodat de eerste byte halverwege de adresruimte zit en de data de bovenste helft van de adresruimte vult. Dit komt neer op een offset van 0x8000 in hex. Dit leverde al direct een beter resultaat op.


Achteraf gezien kon ik ook op meerdere manieren bevestigen dat dit goed moest zijn. Allereerst zit de flash op de hoogste 15 bits van de adresbus van de micro aangesloten wat een directe bevestiging is. Verder zitten de interrupt vectors van de m68hc11 helemaal aan het eind van de adresruimte.
Als er een interrupt afgaat in de micro word dus code opgeroepen die op die plek in de adresruimte staat. Deze bestaat bijna altijd uit een directe branch naar een subroutine. Aan het einde van de code in de flash staan deze pointers ook. Ik wist dus vrij zeker dat dit goed moest zijn.



Ga je vervolgens in de code rondkijken zie je dat er goedgevormde routines zijn welke ida in "graph" weergave kan tonen (aangegeven met blauw in de balk bovenin). Als een  routine verminkt is (aangegeven met rood in de balk bovenin)  dan kan ida alleen een lijst met opcodes weergeven. Dit gebeurd bijvoorbeeld als je ida tabeldata laat disassembelen krijg je implausibele "routines" die naast dat ze er niet uit zien als logische code ook  deze verminkingen hebben (jumps naar lege plekken enzo).


Kijken we echter achterin de code, dan zien we dat  de laatste routine wel plausibele code heeft, maar toch verminkingen heeft. Dit komt doordat hij door lijkt te lopen in een deel van de adresruimte waar standaard zich standaard de interne EEPROM zich bevind. Hij snijd daar de routine gewoon af als het ware.
De verklaring hiervoor is dat de plaats van de EEPROM in de adresruimte instelbaar is bij deze microcontrollers. Dit word al vroeg in het programma gedaan, maar ida houd hier standaard geen rekening mee en gaat uit van de standaard plaats.
Om dit op te lossen vertellen we ida voorlopig om de interne eeprom even te vergeten, waardoor de adresruimte vrij komt en de laatste routine ook normaal gedisassembled kan worden. Nu begint het al ergens op te lijken. De ISR (interrupt service routines) vectoren wijzen allemaal naar een jump naar routines en er zijn geen halve routines meer.
Tijd om eens een beetje rond te kijken in de bin. Het eerste wat de meeste microcontrollers doen als hij opgestart word is een soort reset routine draaien.

In dit geval word bij een reset de NOCOP interrupt getriggerd. COP staat voor Computer Operating Properly. Dit slaat op het feit dat er een watchdog op de achtergrond meedraait die in de gaten houd of de micro goed functioneerd. Dit is eigenlijk gewoon een timer die periodiek gereset word door de micro. Als dit niet gebeurd en de timer een instelbare grens overschrijd word de micro gereset waarna de NOCOP interrupt afgaat.

Hierbij word de volgende subroutine opgeroepen:

In deze routine word er naar verschillende geheugenplaatsen geschreven en worden allerlei registers ingevuld. Hier is veel te halen, maar all in due time.

Links onderin zie je dat de routine branched als er aan bepaalde voorwaarden voldaan word.
De jump leid naar locatie 0x8000 in de adresruimte. Dit is precies de plek waard de bin hebben laten beginnen wat suggereert dat dit waarschijnlijk correct is. De routine waar heen gejumped word ziet er zo uit:


Een tiny maar toch een redelijk belangrijke routine. Zoals in mijn comments te lezen valt is dit de main loop. De meeste programma's die geschreven worden voor microcontrollers laten een oneindige loop draaien waaruit sequentieel allerlei subroutines worden opgeroepen. Zo'n loop bestaat ook bij bijvoorbeeld m4.X, maar deze is veeeel uitgebreider en complexer, omdat een motormanagement ecu veel meer te doen heeft.

De LPI computer volgt echter als slave de benzine ecu welke al het complexe werk voor hem doet. Dit zorgt ervoor dat de main loop klein en erg eenvoudig is en dus heel goed als voorbeeld kan dienen van assembly analyse. Het eerste wat er gebeurd is een jsr instructie met een verwijzing naar een adres erachter. In de manual kun je beschrijvingen van alle instructies vinden. JSR staat voor Jump to SubRoutine. Hetgene wat erna volgt heet een "operand" en is de data waar de instructie mee uitgevoerd word. In dit geval is dit dus een verwijzing naar de locatie van de betreffende subroutine sub_8186 (op adres 8186 dus). Op deze plek staat een subroutine waar allerlei ram variabelen en ook wat registers ingevuld worden met een vaste waarde (dus onafhankelijk van parameters en dergelijke). Het is evident dat dit gebeurd om de micro na een reset altijd in dezelfde bekende staat te brengen. Interessant voor latere bestudering, maar nu laat ik hem nog even voor wat ie is. Aan het eind van de sub_8186 routine staat een RTS (ReTurn from Subroutine) instructie, waardoor de micro weer terug springt naar de reset routine waar we vandaan kwamen.
Hierna volgt een CLI instructie, welke de interrupt mask bit in het CCR register cleared. Hiermee schakelt de microcontroller de interrupts in.
Vlak daarna volgt een interessant stukje code.
-clr byte_0 leegt simpelweg byte 0 in het ram.
-ldab byte_0 laad de inhoud van ram byte 0 in het Accumulator B register. Een accumulator register kun je zien als een ram geheugenplaats waar speciale bewerkingen op uitgevoerd kunnen worden.
-cmpb unk_8185 is zo'n speciale bewerking waarbij de inhoud van Accumulator register B met de waarde van de byte op positie 0x8185 in de flash vergeleken word. Dit vergelijken gebeurd door de waarde van flash byte 0x8185 (in dit geval 0x05, ofwel gewoon 5) af te trekken van de waarde van register B. Als de waarde van register B groter of gelijk aan 5 is word condition bit "Carry" op 0 gezet en anders op 1.
-bcc loc_8004 staat voor Branch Carry Clear loc_8004. Dit betekend dat de micro naar locatie 0x8004 springt als de waarde van register B groter of gelijk is aan 5. Dit zorgt er immers voor dat de carry bit in de vorige instructie gecleared werd. Op locatie 8004 kom je weer bij de eerder genoemde clr byte_0 instructie uit waarna het spelletje weer opnieuw begint.
Dit moet duidelijk een loop zijn die 5 keer draait voordat byte_0 gereset word, met in byte_0 een teller.
Om de loop te laten functioneren moet byte_0 wel ergens verhoogd worden. Als de carry op 1 staat en byte_0 dus de 5 nog niet bereikt heeft, doet de bcc instructie niets en gaat de micro gewoon verder met de daaropvolgende code:
clra (Clear Accumulator A): zet Accumulator A op 0;
lsld (Logical shift left D): Verschuif alle bits van Accumulator D 1 plek naar links (gezien als MSB naar LSB).
addd #$8178 (add D): tel de waarde 0x8178 op bij de waarde aanwezig in Accumulator D.
XGDY (eXchanGe D en Y): verwisseld de inhoud van Accumulator D met die van register Y.
ldy 0,y (Load Y met 0,y): Neemt de waarde van het register Y en ziet dit als adres van een bytelocatie in de flash (een pointer dus). Vervolgens laad hij de bytewaarde van de flash op dit adres in de MSB van Y en de bytewaarde van de daaropvolgende bytewaarde in de flash in de LSB van Y.
jsr 0,y (Jump to SubRoutine 0xy): Hier word de waarde van y gebruikt als adres waar de microcontroller heen springt.
bra loc_8007 (Branch Always): Als laatste keert de microcontroller terug naar het begin van de loop.


Wat hier gebeurd is het volgende:
-De hele loop word 5 keer doorlopen waarbij ram_0 van 0 tot 4 optelt.
-ACCD is de combinatie ACCA en ACCB, waardoor je ACCA en ACCB als één (16 bit) register kunt gebruiken. Elke keer dat de loop doorlopen word worden de hoogste 8 bits van ACCD gereset (door ACCA te resetten) en worden de laagste 8 bits van ACCD geladen met de inhoud van ram_0 (onze teller van 0-4).
- Daarna word het hele ACCD register met 1 plek naar links opgeschoven, wat in binair een vermenigvuldiging met 2 betekend en word de waarde 0x8178 opgeteld bij het resultaat.
Dus eigenlijk telt ACCD steeds ram_0 * 2 op bij 0x8178:
0x8178 + 0 = 0x8178
0x8178 + (1*2) = 0x817A
0x8178 + (2*2) = 0x817C
...
0x8178 + (4*2) = 0x8180
En weer overnieuw.

Het resultaat van deze optelling word gebruikt als adres in de flash waar steeds 2 opeenvolgende bytes worden opgehaald. De waarde van de opgehaalde bytes worden weer gebruikt als adres om naartoe te springen (positie van een subroutine dus).

Kortom: Op 0x8178 bevind zich een tabel van adressen van 5 subroutines die 1 voor 1 door deze routine worden aangeroepen. Ida kan deze natuurlijk niet automatisch disassembelen, aangezien dit een programma specifieke manier is om routines aan te roepen. Als we naar de routines die in de tabel staan gaan en ze handmatig disassembelen komen er inderdaad keurige routines tevoorschijn op plekken waarvan ik al vermoedde dat er programma code stond. De codebalk kleurt al aardig blauw en alle stukken code waarvan ik dacht dat het routines moesten zijn zijn gedisassembled.


De disassembly is weer een stuk completer en er zijn aardig wat interessante plekken om te bestuderen tevoorschijn gekomen. Inmiddels heb ik al aardig wat meer interessante ontdekkingen gedaan, maar voor nu is deze monsterpost meer dan lang genoeg. Later volgt wat printplaat tracing en meer (bondigere) disassembly analyse (globaal ipv per individuele opcode).

Piet

Het is een cursus motor/lpe-management hacken geworden  :D

haasje

Volgens mij heb ik nog een goede LPE 6.6 liggen

Maarten-t5


haasje

Ik zal van de week even zoeken waar die gebleven is

BBS

Ik nomineer hem als post van het jaar 2018 :D
Jullie werkelijk ook niks meer over aan computer systemen in onze wagens wat niet te hacken valt :D
Is het nog de bedoeling dat er in de instellingen iets gemodificeerd kan worden, of is het leuk om te weten?
Neemt niet weg dat je terug goed bent Maarten! :eusa_clap:
Volvoloos....

freefall

ik voel hier een tuners deugd 2.0 aankomen...

Mooi dat het gelukt is met je inbouw, da's een...en twee....damn...too much info zonder koffie ;D

Briljant dat onze oude systemen zo ontleed worden.
1997 417 nautic blue S70 2.5T AT Zoonlief
2000 426 mystic silver V70D AT
1997 421 dark olive pearl V70 2.5T 2.3T AT AWD
1998 419 sand silver S70 T5 AT zoonlief
1995 421 dark olive pearl 850 T5R AT
i beun, therefore i am

de Boeing

#7
Gelukkig had ik (idd) net een nieuwe kop koffie naast mijn toetsenbord staan deze morgen...

Maar interessant! En de volgende vraag dringt zich op: je hebt een (professionele) achtergrond in elektronica/informatica of is dit allemaal ontstaan uit pure interesse? Anyway, Respect!

arjenT5R

#8
Eindelijk Maarten aan t gas ;D we zitten allemaal met smart te wachten op nieuwe lpi mods ;D

Geweldige post! Zal m nog eens een keer of 5 moeten lezen wellicht ;D

Keep up the good works!

Wat een  :D Monster Post  :D
Liquid propane, knock free, ice cold " go fast fuel "!!

Ries van de Zilverschuit

'k Ben zeer benieuwd waar dit gaat eindigen...
Volvo V70 2.5T lpi, 1997, mt, mystic silver
Toyota Previa 2.4 Linea Sol, 2002, mt, grayish blue

Piet

Citaat van: BBS op 21-05-2018 07:27:31
Is het nog de bedoeling dat er in de instellingen iets gemodificeerd kan worden, of is het leuk om te weten?
Neemt niet weg dat je terug goed bent Maarten! :eusa_clap:

Het ene volgt als vanzelf uit het andere  ;D

KIM

Jaaaa mooi!
Ik moet het denk ik ook nog een keer of tien lezen en misschien dat ik er dan 20% van begrijp. Desalniettemin snakken wij LPi rijders hier al jaaaaren naar!
Keep up the good work!

razorx

Mooi stukje reverse engineering Maarten!  :eusa_clap: :eusa_clap: :eusa_clap:
Ik zal dit met bovengemiddelde interesse volgen.

classicT5

Nou blijf maar lekker nerdy posten Maarten, erg indrukwekkend  :eusa_clap:

alfredgeel

hetgeen ik verontrustend vind is dat iemand, met kennis van zaken , deze info uit de ECU kan halen.

het kan zijn dat ik me vergis want ik ben een leek op dit gebied, maar dient die SW niet beveiligd te zijn?

Langs de andere kant vind ik dit fanatstisch om te lezen .

knap werk