2017. augusztus 16., szerda

ECU #9

Az elmúlt időben elég sok feltétlenül szükséges teendő adódott az autóval, így egy darabig mellőztem az ECU-val kapcsolatos további vizsgálódást. Továbbá eléggé jól is viselkedett az autó, így nem sürgetett semmi.
Az egyik hosszabban elhúzódó elfoglaltság a már említett kinyomócsapágyas történet volt, amit tulajdonképpen körülölelt egy klímával kapcsolatos hiba is. Nevezetesen az, hogy a télen elszökött belőle a gáz egy része. Működött, de inkább csak langyosat fújt hideg helyett, így még tavasszal lefejtésre került a maradék. A szivárgás helyének megkeresésére és a feltöltésre csak júniusban került sor, azonban a javítás után annak ellenére sem akart bekapcsolni, hogy látszólag minden rendben volt. A mechanikus részek jól működtek, mivel a kompresszor direktben kötve működött és hűtött rendesen. Miután egy autóvillamosságis is feladta a keresést 1-2 nap után, magamnak kellett megtalálnom és kijavítanom a hibát. Egy tárolt hibakód (P0530 - A/C Refrigerant Pressure Sensor Circuit Malfunction) alapján elég jól be tudtam szűkíteni a forrást, de a szenzor többszöri, köztük egy újra való cseréje sem hozott javulást. Természetesen megvolt a kapcsoló, a biztosítékok és a relék ellenőrzése is. Mind jó volt. A vezetékek ellenőrzéséhez viszont be kellett szereznem egy megfelelő kapcsolási rajzot beszereznem. Ezen az látszott, hogy a szenzor 3 vezetéke egyenesen az ECU-ba megy. Kimértem és szerencsére nem volt szakadás sem. Nem maradt más mint maga az motorvezérlő. Vagyis a program.
Még akkor tavasszal éppen úgy jött ki, hogy a gáz lefejtése után pár nappal írtam fel az 12594688AH (12594690) programot, ami minden más tekintetben hibátlanul működött hónapokon át. Viszont a klíma nem működik vele. Visszaírtam hát a korábbi 09391263BA programot, amiben nulláztam az EGR térképet, és a klíma megjavult.
Azt gyanítom továbbá, hogy a 12594688AH-val vesztettem némi dinamikát is, és elképzelhető, hogy (részben) ennek is köszönhető a Referencia #4 gyengébb eredménye. Az előtte-utána közvetlen összehasonlítás kicsit nehézkes, mivel a programok felírása után a korrekciós értékek beállásáig mindig kicsit élettelenebb az autó, de a 09391263BA-val mintha picit jobban húzna.

Ezután újra elkezdtek motoszkálni a fejemben az ECU-val kapcsolatos kérdések, így ismét szántam egy kis időt a régi módszernek, de semmi újat nem sikerült felfedeznem. A figyelmem egyre erősebben a disassemble felé terelődött.

Checksum
Rövidre fogom. Sikerült megfejtem a checksum számítási algoritmust és programot írnom rá. Ezt számos (10+) nálam lévő különböző programon teszteltem, és mindegyiken a megfelelő eredményt produkálta. Továbbá kipróbáltam élesben is. Felírtam egy olyan módosítást MPPS-el, ahol előzőleg manuálisan korrigáltam a checksum értékét.

Újabb pipa. Nem vagyok többé a KESS-hez kötve.

A korábbiakkal ellentétben azonban most nem adom ki a kezemből sem a metódust, sem a megtaláláshoz vezető út leírását. Legalábbis egyelőre.
Ha a jövőben mégis megteszem, akkor ezt a posztot fogom frissíteni.

Ha valakinek addig szüksége van checksum korrekcióra, vagy EGR kiírásra (térkép nullázással) az nyugodtan keressen meg.

------------------------
    Update
------------------------

Eltelt közel egy hónap. Hezitálásom oka azzal kapcsolatosan, hogy megosszam-e a checksum számítás módját abból adódott, hogy sejtésem szerint a világon összesen sincsenek túl sokan, akik ezt ismerik. Amit pedig csak kevesen ismernek, annak jelentős az értéke, ennél fogva jobban is vigyázunk rá. Az, hogy kevesen ismerik részben annak is köszönhető, hogy viszonylag keveseknek fűződik hozzá érdeke, hogy időt és energiát fordítsanak a tudás megszerzésére. És az is lehet, hogy tévedek, de valószínűsítem, hogy akik chiptuning-al foglaloznak csak hardveres vagy szoftveres eszközt vásárolnak és sohasem jutnak a know-how birtokába. Z22SE-től függetlenül, rendkívül kevés konkrét számítási metódus leírásával akadtam össze, pedig elég sokat kutattam a témában. Mindamelett az információ szabad áramlásának jelentős előnyei vannak. Ha valaki ezt előttem nyilvánosságra hozta volna, akkor az ezzel eltöltött időmet más hasznosabb tevékenységre is tudtam volna fordítani. Remélem, hogy segíthetek vele valakinek, aki majd más hasznos dolgot tud végezni ehelyett. A számítás visszafejtésében nem mellesleg én sem jutottam volna el idáig, ha nem lett volna segítségemre számos különböző publikusan elérhető információ. Egyszóval nincs több titkok. Lássuk a medvét!

Azt már említettem, hogy az idők folyamán egyértelművé vált, hogy az ECU valamilyen Motorola mikroprocesszorra épül. Később kristályosodott ki, hogy ez az m68000-es szériának, amelyet m68k-nak is neveznek valamelyik tagja lehet. Azt a mai napig nem tudom, hogy pontosan melyik, de szerencsére eddig úgy tűnik ennek nincs is különösebb jelentősége. A processzor típusának meghatározása elengedhetetlen annak érdekében, hogy megtaláljuk a megfelelő disassembler-t, amely a binárisból előállítja a gépi kódot. A gépi kód már jól struktúrált és messze jobban olvasható, mint a hexa kód, de az értelmezése még így sem könnyű feladat. Ráadásul a konkrét esetben borzalmasan nagy méretű a program. Csak a lényegi részt számítva körülbelül 75000(!) sor.

Számos ingyenes disassembler létezik (68kd , vda68k , dasm68), amelyekkel egy többé-kevésbé megfelelő kódot elő lehet állítani, de a legjobbnak az online disassembler (ODA) -t találtam. Használata rendkívül egyszerű, rengeteg platformot támogat (csak az m68k különböző változataiból több, mint 40-et), és ez adta a legjobb kimenetet, mind olvashatóság mind pontosság tekintetében. Szinte csoda, hogy létezik. (meg is ijedtem, amikor a múlt hónapban pár napon keresztül egyáltalán nem volt elérhető)

A visszafejtett gép kód első ránézésre nem volt sokkal barátságosabb, mint annak idején a hexa kód. Néhány parancs önmagában ugyan elég jól értelmezhető, de egy-egy programrészlet megértéséhez rengeteget kell gondolkodni és kombinálni. Ha valaki szeretne elmélyedni a témában, de kevés vagy egyáltalán nincs tapasztalata, akkor MarkeyJester tutorial-ját ajánlom. Elképesztően informatív, olvasmányos és szemléletes. Nagy kár, hogy bizonyos utasítások hiányoznak belőle. És sajnos nem is tűnik úgy, hogy valaha felkerülnek majd az oldalra. Itt lehet még találni némi kiegészítést, de ami egyik helyen sincs az benne lesz (minden részletre kiterjedően, de szárazan) a Programming Refrence Manual -ban.

Én emellett beleolvastam néhány a témával foglalkozó könyvbe is. Pl:
Assembly Language Programming for the M68000 Family / Thomas P. Skinner
Microprocessors and Microcomputer-Based System Design 2nd Edition / Mohamed Rafiquzzaman

Ahhoz, hogy a 75000 sorból közelíteni lehessen a checksum számítás helyére kellett valami kapaszkó. A checksum pontos helye éppen ilyen volt. Mérget vettem volna rá, hogy a 8000-nek szerepelnie kell a metódusban. Így is lett, de utólag már látom, hogy a 8000-es szám említése nélkül is vígan meg lehetett volna írni ezt a részt. Kell néha egy kis szerencse is.
A "0x00008000" mindössze 5 helyen szerepel a programban és ebből 3-szor ebben a viszonylag kis részletben. A 8000 mellett megjelennek olyan kitüntetett helyek is mint a 4000, az immo-s blokk kezdete, vagy a 20000 a programkód eleje, de szerepel a program szinte legvége 7fffc és 7fffe, valamit egy új szereplő a 17fff, ami az adatblokk vége körüli cím. Az első pillanattól fogva tudtam, hogy jó helyen járok, de olyan szinten zavaros az egész, hogy csak nagy nehezen sikerült kibogarásznom a lényeget, és minden részletet továbbra sem értek.

Checksum subroutine

.data:00022e7e 24 78 94 66                      moveal 0xffffffffffff9466,%a2
.data:00022e82 28 78 94 6a                      moveal 0xffffffffffff946a,%a4
.data:00022e86 47 f9 00 00 80 00                lea 0x00008000,%a3                   
.data:00022e8c 4b f8 40 00                      lea 0x00004000,%a5
.data:00022e90 43 f9 00 02 00 00                lea 0x00020000,%a1
.data:00022e96 42 83                            clrl %d3
.data:00022e98 16 38 94 64                      moveb 0xffffffffffff9464,%d3
.data:00022e9c 4a 8a                            tstl %a2
.data:00022e9e 67 04                            beqs 0x00022ea4                # if a2=0 then go to 0x00022ea4 else ignored
.data:00022ea0 b5 cc                            cmpal %a4,%a2
.data:00022ea2 65 18                            bcss 0x00022ebc                # if a2>=a4 then go to 0x00022ebc else ignored
.data:00022ea4 42 78 94 56                      clrw 0xffffffffffff9456
.data:00022ea8 45 f8 05 46                      lea 0x00000546,%a2            # 0x00000546 to a2 /// data at 0x00000546 = 00 00 00 00
.data:00022eac 28 72 36 04                      moveal %a2@(0000000000000004,%d3:w:8),%a4
.data:00022eb0 24 72 36 00                      moveal %a2@(0000000000000000,%d3:w:8),%a2
.data:00022eb4 21 cc 94 6a                      movel %a4,0xffffffffffff946a
.data:00022eb8 52 78 81 54                      addqw #1,0xffffffffffff8154
.data:00022ebc 02 7c f8 00                      andiw #-2048,%sr
.data:00022ec0 38 38 94 56                      movew 0xffffffffffff9456,%d4
.data:00022ec4 00 7c 07 00                      oriw #1792,%sr
.data:00022ec8 b5 cb                            cmpal %a3,%a2
.data:00022eca 64 06                            bccs 0x00022ed2                # if a2>=8000 then go to 0x00022ed2 else ignored
.data:00022ecc b5 cd                            cmpal %a5,%a2
.data:00022ece 65 02                            bcss 0x00022ed2                # if a2<4000 then go to 0x00022ed2 else ignored
.data:00022ed0 24 49                            moveal %a1,%a2                # a2=20000
.data:00022ed2 d8 5a                            addw %a2@+,%d4                # add a2@ to d4 then increment a2
.data:00022ed4 d8 5a                            addw %a2@+,%d4                # ...
.data:00022ed6 d8 5a                            addw %a2@+,%d4                # ...
.data:00022ed8 d8 5a                            addw %a2@+,%d4                # ...
.data:00022eda d8 5a                            addw %a2@+,%d4                # ...
.data:00022edc d8 5a                            addw %a2@+,%d4                # ...
.data:00022ede d8 5a                            addw %a2@+,%d4                # ...
.data:00022ee0 d8 5a                            addw %a2@+,%d4                # ...
.data:00022ee2 4e 71                            nop                            # no operand
.data:00022ee4 4e 71                            nop                            # ...
.data:00022ee6 4e 71                            nop                            # ...
.data:00022ee8 4e 71                            nop                            # ...
.data:00022eea 4e 71                            nop                            # ...
.data:00022eec 4e 71                            nop                            # ...
.data:00022eee 4e 71                            nop                            # ...
.data:00022ef0 31 c4 94 56                      movew %d4,0xffffffffffff9456
.data:00022ef4 52 78 81 54                      addqw #1,0xffffffffffff8154
.data:00022ef8 21 ca 94 66                      movel %a2,0xffffffffffff9466
.data:00022efc b5 cc                            cmpal %a4,%a2
.data:00022efe 65 bc                            bcss 0x00022ebc                # if a2<a4 then go to 0x00022ebc else ignored
.data:00022f00 08 39 00 06 00 00 80 1d          btst #6,0x0000801d
.data:00022f08 66 30                            bnes 0x00022f3a
.data:00022f0a b5 c9                            cmpal %a1,%a2
.data:00022f0c 65 12                            bcss 0x00022f20                # if a2<a1 then go to 0x00022f20 else ignored
.data:00022f0e 49 f9 00 01 7f ff                lea 0x00017fff,%a4            # 0x00017fff to a4
.data:00022f14 45 f9 00 00 80 00                lea 0x00008000,%a2            # 0x00008000 to a2
.data:00022f1a 21 cc 94 6a                      movel %a4,0xffffffffffff946a
.data:00022f1e 60 98                            bras 0x00022eb8                # branch always to 0x00022eb8
.data:00022f20 98 79 00 00 80 00                subw 0x00008000,%d4            # d4-0x00008000
.data:00022f26 98 79 00 07 ff fc                subw 0x0007fffc,%d4            # d4-0x0007fffc
.data:00022f2c 98 79 00 07 ff fe                subw 0x0007fffe,%d4            # d4-0x0007fffe
.data:00022f32 44 44                            negw %d4                    # negate d4
.data:00022f34 31 c4 94 58                      movew %d4,0xffffffffffff9458
.data:00022f38 60 34                            bras 0x00022f6e
.data:00022f3a 49 f8 05 2a                      lea 0x0000052a,%a4
.data:00022f3e 4a 03                            tstb %d3
.data:00022f40 67 0a                            beqs 0x00022f4c
.data:00022f42 49 f8 05 46                      lea 0x00000546,%a4
.data:00022f46 28 74 36 00                      moveal %a4@(0000000000000000,%d3:w:8),%a4
.data:00022f4a 60 0c                            bras 0x00022f58
.data:00022f4c 98 79 00 07 ff fc                subw 0x0007fffc,%d4
.data:00022f52 98 79 00 07 ff fe                subw 0x0007fffe,%d4
.data:00022f58 98 54                            subw %a4@,%d4
.data:00022f5a 44 44                            negw %d4
.data:00022f5c 45 f8 94 58                      lea 0xffffffffffff9458,%a2
.data:00022f60 35 84 32 00                      movew %d4,%a2@(0000000000000000,%d3:w:2)
.data:00022f64 52 03                            addqb #1,%d3
.data:00022f66 0c 03 00 05                      cmpib #5,%d3
.data:00022f6a 65 08                            bcss 0x00022f74
.data:00022f6c 42 03                            clrb %d3
.data:00022f6e 08 f8 00 00 8c 3a                bset #0,0xffffffffffff8c3a
.data:00022f74 11 c3 94 64                      moveb %d3,0xffffffffffff9464
.data:00022f78 52 78 81 54                      addqw #1,0xffffffffffff8154
.data:00022f7c 42 b8 94 66                      clrl 0xffffffffffff9466
.data:00022f80 60 00 fe fc                      braw 0x00022e7e                # branch always to 0x00022e7e


A fontosabb részeket kommenteltem, de kicsit sajnos szétcsúszik a megjelenítés. A legnehezebben a különöző regiszterek kezdeti értékének meghatározása ment. Sokáig megzavart például a 0x00000546 a2-be betöltése. Azt hittem, hogy onnan kezdődik az összeadás, és csak később vettem észre, hogy az azon a helyen lévő adat számít mégis. A bccs és a bcss váltakozásába is könnyű belezavarodni, és nekem kicsit nehéz volt memorizálni, hogy mikor melyiknek kell kisebbnek, nagyobbnak vagy egyenlőnek lenni. A blokk kezdetét könnyű volt azonosítani, mert a megelőző sorban egy rts szerepel, de a mai napig rejtély, hogy ha a végén állandóan visszaugrik a 22e7e-re, akkor vajon hogyan lép ki ebből a ciklusból. (talán a státusz regiszter működésében van a magyarázat)

Végül ezt hoztam ki belőle:
# First stage
    addw 0000 - 4000
# Second stage
    addw 20000 - 7FFFF
# Third stage
    addw 8000 - 17FFF
# Fourth stage
    subw 8000
    subw 7fffc
    subw 7fffe
    negw
Így már nem is tűnik bonyolultnak. Írtam rá egy python szkriptet, ami első körben csak a meglévő binárisok egy részénél adta a jó eredményt, a többinél viszont furcsán eltért.

Calculated/Original: a7b4 / dfb4 // d4: 0x82fe /// diff: -0x3800 //// 09391263 BA.ori
Calculated/Original: dfb4 / dfb4 // d4: 0x4afe /// diff: 0x0 //// 09391263BA_original.ori
Calculated/Original: a2da / d5da // d4: 0x7dfe /// diff: -0x3300 //// 09391283BC_original.ori
Calculated/Original: 4a13 / 4a13 // d4: 0x4afe /// diff: 0x0 //// 12210453 EB.ori
Calculated/Original: 63a4 / 96a4 // d4: 0x7dfe /// diff: -0x3300 //// 12594688AH.Bin


Némi tesztelés után viszonylag hamar rájöttem, hogy ha a 0x4000-en lévő "word" érték nem "FFFF", akkor azzal korrigálni kell! Javítás után hibátlan:

Calculated/Original: dfb4 / dfb4 // d4: 0x82fe /// diff: 0x0 //// 09391263 BA.ori
Calculated/Original: dfb4 / dfb4 // d4: 0x4afe /// diff: 0x0 //// 09391263BA_original.ori
Calculated/Original: d5da / d5da // d4: 0x7dfe /// diff: 0x0 //// 09391283BC_original.ori
Calculated/Original: 4a13 / 4a13 // d4: 0x4afe /// diff: 0x0 //// 12210453 EB.ori
Calculated/Original: 96a4 / 96a4 // d4: 0x7dfe /// diff: 0x0 //// 12594688AH.Bin
Calculated/Original: e87f / fc8f // d4: 0x5f0e /// diff: -0x1410 //// 09391263BA_egrmapoff_idle850_170815.ori
Calculated/Original: e87f / e87f // d4: 0x4afe /// diff: 0x0 //// 09391263BA_egrmapoff_idle850_170815_chkd.ori


Az utolsó előtti sor egy tartalmában módosított bináris, ahol megfelelő módon jelzi, hogy nem helyes az ellenőrző összeg. Az utolsóban az összeget a megfelelőre átírva már helyes eredményt ad. Ez volt az, amit később fel is töltöttem, és megbizonyosodtam a megfelelő működéséről.

És ez még csak 80 sor volt a 75000-ből, a teljes programnak csak a 0.1%-a.