Pages: [1]
Author Topic: Forcing Readiness & evsup with 8 byte code patch  (Read 1233 times)
360trev
Full Member
***

Karma: +45/-1
Offline Offline

Posts: 195


« on: May 25, 2021, 01:50:11 PM »

I know this isn't the preferred solution but the way I solved this was with an 8 byte code patch, and yes I know this is old, but hey we ARE in the Reverse Engineering section Smiley

Lets look at what's actually contained in the 'evsup1' byte;

           Bit 0 : Catalyst monitoring                     0xFE  1111 1110   0000 0001      1     0x01
           Bit 1 : Heated catalyst monitoring              0xFD  1111 1101   0000 0010      2     0x02
           Bit 2 : Evaporative system monitoring           0xFB  1111 1011   0000 0100      4     0x04
           Bit 3 : Secondary air system monitoring         0xF7  1111 0111   0000 1000      8     0x08
           Bit 4 : A/C system refrigerant monitoring       0xEF  1110 1111   0001 0000     16     0x10
           Bit 5 : Oxygen sensor monitoring                0xDF  1101 1111   0010 0000     32     0x20
           Bit 6 : Oxygen sensor heater monitoring         0xBF  1011 1111   0100 0000     64     0x40
           Bit 7 : EGR system monitoring                   0x7F  0111 1111   1000 0000    128     0x80

For example on this car I was looking at.
EVSUP1:  0x6D  0 1 1 0 1 1 0 1

                   7 6 5 4 3 2 1 0  bits
                   ---------------
EVSUP1:      0x6D  0 1 1 0 1 1 0 1
                   | | | | | | | |
                   | | | | | | | +--- b_katfz     Bit 0 :  Condition bit for Catalyst monitoring Support
                   | | | | | | +----- b_kath      Bit 1 :  Condition bit for Heated catalyst monitoring Support
                   | | | | | +------- b_cdtes     Bit 2 :  Condition bit for Evaporative system monitoring Support
                   | | | | +--------- b_cdsls     Bit 3 :  Condition bit for Secondary air system monitoring Support
                   | | | +----------- b_???       Bit 4 :  Condition bit for A/C system refrigerant monitoring Support
                   | | +------------- b_cdlsv     Bit 5 :  Condition bit for Oxygen sensor monitoring Support
                   | +--------------- b_cdhsv     Bit 6 :  Condition bit for Oxygen sensor heater monitoring Support
                   +----------------- b_cdagr     Bit 7 :  Condition bit for EGR system monitoring Support



In my case it looks like this... Obviously depends on the version of ME7.x your looking at.

Easy way to find it is look up the correct function from the function table. Search for the KWP2000_Setup_ini() function where it sets the services_table_OTHER.

e.g.
Code:
Init_KWP2000_Setup_ini:
                mov     r4, #kwp2000_checksumCalc_func
                mov     r5, #0
                mov     asc0_KWP2000_ChecksumCalculate_Function, r4
                mov     asc0_KWP2000_ChecksumCalculate_Function_segment, r5

                mov     r4, #kwp_timings_table0
                mov     r5, #0
                mov     kwp2000_Timings, r4
                mov     kwp2000_Timings_segment, r5

                mov     r4, #kwp_timings_table4
                mov     r5, #206h
                mov     kwp2000_Timings_Limit, r4
                mov     kwp2000_Timings_Limit_segment, r5

                mov     r4, #services_table_OTHER                ; <--------------- ******** this one
                mov     r5, #206h
                mov     kwp2000_Services, r4
                mov     kwp2000_Services_segment, r5

                mov     r4, #serviceIndex_table1
                mov     r5, #206h
                mov     kwp2000_ServicesIndex, r4
                mov     kwp2000_ServicesIndex_segment, r5

                mov     r4, #KWPDIAG_Strings
                mov     r5, #206h
                mov     kwp2000_ECUD_datas, r4
                mov     kwp2000_ECUID_Table_segment, r5

...

e.g. In my firmware...

Code:
services_table_OTHER:
                dw kwp2000_service_notSupported
                dw 0
                dw kwp2000_srv_startCommunication_81h
                dw 82h
                dw kwp2000_service_stopCommunication_82h
                dw 0
                dw kwp2000_service_accessTimingParameter_83h
                dw 0
                dw kwp2000_service_startDiagnosticSession_10h_VER_2
                dw 82h
                dw kwp2000_service_stopDiagnosticSession_20h
                dw 0
                dw kwp2000_service_startCommunicationMcMess_A0h
                dw 82h
                dw kwp2000_service_readEcuIdentification_1Ah
                dw 82h
                dw kwp2000_service_securityAccess_27h
                dw 0
                dw kwp2000_service_testerPresent_3Eh
                dw 0
                dw kwp2000_service_startRoutinebyLocalIdentifier_31h
                dw 0
                dw kwp2000_service_stopRoutineByLocalIdentifier_32h
                dw 0
                dw kwp2000_service_requestRoutineResultsByLocalIdentifier_33h
                dw 82h
                dw kwp2000_service_requestDownload_34h
                dw 0
                dw kwp2000_service_transferData_36h
                dw 0
                dw kwp2000_service_requestTransferExit_37h
                dw 0
                dw kwp2000_srv_ECUReset_suspected_11h_ret51h
                dw 82h
                dw kwp2000_srv_readDataByLocalIdentifier_21h
                dw 83h
                dw kwp2000_srv_readDataByCommonIdentifier_22h
                dw 83h
                dw kwp2000_srv_dynamicallyDefineLocalIdentifier_2Ch
                dw 83h
                dw kwp2000_srv_writeDataByLocalIdentifier_3Bh
                dw 83h
                dw kwp2000_srv_readMemoryByAddress_23h
                dw 83h
                dw kwp2000_srv_writeMemoryByAddress_3Dh
                dw 83h
                dw kwp2000_srv_readFreezeFrameData_func1_12h
                dw 83h
                dw kwp2000_srv_clearDiagnosticsInformation_14h
                dw 83h
                dw kwp2000_srv_readStatusOfDiagnosticTroubleCodes_17h
                dw 83h
                dw kwp2000_srv_readDiagnosticTroubleCodesByStatus_18h
                dw 83h
                dw kwp2000_srv_cmd_Negative_Response_7Fh
                dw 83h
****         dw J1939_TC2MOD_DTCs_A_Pending_41h_CARB_Mode_1    <------------------- ****
                dw 83h
                dw J1939_TC8MOD_DTCs_A_ConfirmedActive_cmd_42h
                dw 83h
                dw J1939_TC8MOD_DTCs_A_PreviouslyActive_cmd_43h
                dw 83h
                dw J1939_TC8MOD_DTCs_B1_Pending_cmd_44h
                dw 83h
                dw J1939_TC8MOD_DTCs_B1_ConfirmedActive_cmd_45h
                dw 83h
                dw J1939_TC8MOD_DTCs_B1_PreviouslyActive_cmd_46h
                dw 83h
                dw J1939_TC8MOD_DTCs_B2_Pending_cmd_47h
                dw 83h
                dw J1939_TC8MOD_DTCs_B2_PreviouslyActive_cmd_48h
                dw 83h
                dw kwp2000_srv_inputOutputControlByLocalIdentifier_30h
                dw 82h

So inside of J1939_TC2MOD_DTCs_A_Pending_41h_CARB_Mode_1(), that function makes a call to  DIMC_J1939_TC1MOD_CARB_Mode_1().
That function uses a jump table to choose the appropriate PID call to use. Find PID 0x01 and you are there.

e.g.

Code:
DIMC_CARB_StatusInformationIncReadiness_PID_01h:
                mov     r12, #1
                calls   83h, GetDTCPidsNumOf
                movb    [r6], rl4
                movbz   r4, milstat     ; milstat :  [DMIL CAN]
                and     r4, #40h
                jmpr    cc_Z, _skip_milstat_set
                movb    rl4, [r6]
                addb    rl4, #80h ; 'Ç' ; milstat set
                movb    [r6], rl4
_skip_milstat_set:
                movb    rl4, #4
                movb    [r7], rl4
                mov     r4, cd_bits1_w  ; cd_bits1_w
                and     r4, #cdbits1w_0_CDMD
                jmpr    cc_Z, _not_CDMD_set
                movb    rl4, [r7]
                orb     rl4, #1         ; CDMD set
                movb    [r7], rl4
_not_CDMD_set:
                mov     r4, cd_bits1_w  ; cd_bits1_w
                and     r4, #cdbits1w_11_CDKVS
                jmpr    cc_Z, _not_CDKVS_set
                movb    rl4, [r7]
                orb     rl4, #2         ; CDKVS set
                movb    [r7], rl4
_not_CDKVS_set:
;---------------------------------------------------------------------------------
                movb    [r8], evsup1 ; gets evsup1
                movb    rl4, ready     ; gets readiness byte
                movb    [r9+5], rl4   ; returns in the payload of the protocol
;---------------------------------------------------------------------------------
                movb    rl4, #6
                jmpa    cc_UC, _exit_func


In my case it was trivial to force it with a few bytes patch...

 ** BEFORE **

0x00038D24:seg083: (+0   )  A4 08 B1 8A                  movb     [r8], evsup1
0x00038D28:seg083: (+4   )  F3 F8 0F B3                  movb     r14, ready
0x00038D2C:seg083: (+8   )  E4 89 05 00                  movb     [r9+5], r14
***
 ** AFTER ** : Applied Forced Readiness and evsup1

0x00038D24:seg083: (+0   )  E7 F8 6D 00                  movb     r14, #006Dh    ; <---- force use of any evsup1 value you want
0x00038D28:seg083: (+4   )  B9 88                        movb     [r8], r14
0x00038D2A:seg083: (+6   )  E1 08                        movb     r14, #0
0x00038D2C:seg083: (+8   )  E4 89 05 00                  movb     [r9+5], r14
***

Just change the value, in this case the 6D to whatever bitmask of supported features you want and your done. No waiting for drive cycles or other such stuff.
Logged
prj
Hero Member
*****

Karma: +403/-108
Offline Offline

Posts: 4120


« Reply #1 on: May 27, 2021, 09:48:23 AM »

I did exactly this 8 years ago Cheesy
Logged
john9357
Jr. Member
**

Karma: +10/-1
Offline Offline

Posts: 49


« Reply #2 on: May 27, 2021, 02:39:57 PM »

I did exactly this 8 years ago Cheesy

And you want a medal?
Logged
360trev
Full Member
***

Karma: +45/-1
Offline Offline

Posts: 195


« Reply #3 on: May 27, 2021, 05:16:28 PM »

I did exactly this 8 years ago Cheesy

haha Smiley

Yes I know a few experts like prj on here did it, ... but not much of that information for some reason became "general knowledge" and has stuck.  Hence why people are still struggling with this today. I was just offering an "alternative solution" as clearly its still an issue people face even in 2021.

You can actually automate the entire process of finding and patching as only a few variants across the ME7.x exist. Ask me how I know Smiley

Logged
prj
Hero Member
*****

Karma: +403/-108
Offline Offline

Posts: 4120


« Reply #4 on: May 28, 2021, 01:04:30 AM »

The problem with this solution is that some places clear it, and then make sure that readiness does not immediately instantly show all passed.
So if you do it this way, you will not pass everywhere.

A good idea is to also build in a timer, which re-sets it after a number of ignition cycles or something. So need to hook a few more things.
Logged
360trev
Full Member
***

Karma: +45/-1
Offline Offline

Posts: 195


« Reply #5 on: May 28, 2021, 01:42:48 AM »

The problem with this solution is that some places clear it, and then make sure that readiness does not immediately instantly show all passed.
So if you do it this way, you will not pass everywhere.

A good idea is to also build in a timer, which re-sets it after a number of ignition cycles or something. So need to hook a few more things.

Never had a problem myself with this but yes I can understand why some would see it as odd, most don't care btw.

If its an issue ofcourse its trivially easy to add a couple more instructions ( to check Engine Running Time, or 'timmot_w', the engine running counter and just delay for any arbitrary amount of time before setting the evsup1 to be whatever you want. Something like

   F2 Fx yy yy                           mov     rX, timmot_w    ; timmot_w
   46 Fx yy yy                           cmp     r4, #DESIRED_RUNNING_TIME_VALUE
   9D xx                                   jmpr    cc_NC, force_evsup_override_patch

So add another 10 bytes, now up to an 18 bytes patch Smiley
Logged
prj
Hero Member
*****

Karma: +403/-108
Offline Offline

Posts: 4120


« Reply #6 on: May 28, 2021, 02:35:03 AM »

This isn't really the correct solution.

They turn on the ignition.
Then they check the monitors, make sure all is passed.
Then they reset the monitors <--- this is the problem
Then they check the monitors again.

So after the reset they can't show passed right away again.
The reset needs to be hooked.
Logged
360trev
Full Member
***

Karma: +45/-1
Offline Offline

Posts: 195


« Reply #7 on: May 28, 2021, 03:01:33 AM »

Yes agreed and actually its even more work if you want to make it work with the implemented spec...

For anyone who wants to do this much more robustly I suggest you get yourself a copy of the J1939 spec's and look at the DIMC_J1939_TC1MOD_CARB_Mode_1() function which processes all the pids.

For instance PID 0x13 shows which Sensors are installed, and ofcourse these come from your PROKON bits which are defined by your Control Words so if you want it to show they are installed even if you've configured them deleted then you need to patch these routines too.

DIMC_CARB_InstalledLambdaSensors_PID_13h:
DIMC_J1939_TC1MOD_CARB_Mode_1+282  E1 08                                   movb    rl4, #0
DIMC_J1939_TC1MOD_CARB_Mode_1+284  B9 86                                   movb    [r6], rl4
DIMC_J1939_TC1MOD_CARB_Mode_1+286  4A 01 F4 40                             bmov    r4.0, PROKON_Bits.b_lsv  ; Condition 1. Lambda sensor installed upstream   of cat (Bank1)
DIMC_J1939_TC1MOD_CARB_Mode_1+28A  49 81                                   cmpb    rl4, #1
DIMC_J1939_TC1MOD_CARB_Mode_1+28C  3D 03                                   jmpr    cc_NZ, check_lsh       <----------- HERE
DIMC_J1939_TC1MOD_CARB_Mode_1+28E  A9 86                                   movb    rl4, [r6]
DIMC_J1939_TC1MOD_CARB_Mode_1+290  09 81                                   addb    rl4, #1
DIMC_J1939_TC1MOD_CARB_Mode_1+292  B9 86                                   movb    [r6], rl4
DIMC_J1939_TC1MOD_CARB_Mode_1+294                          check_lsh:
DIMC_J1939_TC1MOD_CARB_Mode_1+294  E1 08                                   movb    rl4, #0
DIMC_J1939_TC1MOD_CARB_Mode_1+296  4A 01 F4 20                             bmov    r4.0, PROKON_Bits.2.b_lsh ; Condition 2. Lambda sensor installed downstream of cat (Bank1)
DIMC_J1939_TC1MOD_CARB_Mode_1+29A  49 81                                   cmpb    rl4, #1
DIMC_J1939_TC1MOD_CARB_Mode_1+29C  3D 03                                   jmpr    cc_NZ, check_lsv2    <----------- HERE
DIMC_J1939_TC1MOD_CARB_Mode_1+29E  A9 86                                   movb    rl4, [r6]
DIMC_J1939_TC1MOD_CARB_Mode_1+2A0  09 82                                   addb    rl4, #2
DIMC_J1939_TC1MOD_CARB_Mode_1+2A2  B9 86                                   movb    [r6], rl4
DIMC_J1939_TC1MOD_CARB_Mode_1+2A4                          check_lsv2:
DIMC_J1939_TC1MOD_CARB_Mode_1+2A4  E1 08                                   movb    rl4, #0
DIMC_J1939_TC1MOD_CARB_Mode_1+2A6  4A 01 F4 50                             bmov    r4.0, PROKON_Bits.b_lsv2 ;  Condition 1. Lambda sensor installed upstream   of cat (Bank2)
DIMC_J1939_TC1MOD_CARB_Mode_1+2AA  49 81                                   cmpb    rl4, #1
DIMC_J1939_TC1MOD_CARB_Mode_1+2AC  3D 04                                   jmpr    cc_NZ, check_lsh2        <----------- HERE
DIMC_J1939_TC1MOD_CARB_Mode_1+2AE  A9 86                                   movb    rl4, [r6]
DIMC_J1939_TC1MOD_CARB_Mode_1+2B0  07 F8 10 00                             addb    rl4, #10h
DIMC_J1939_TC1MOD_CARB_Mode_1+2B4  B9 86                                   movb    [r6], rl4
DIMC_J1939_TC1MOD_CARB_Mode_1+2B6                          check_lsh2:
DIMC_J1939_TC1MOD_CARB_Mode_1+2B6  E1 08                                   movb    rl4, #0
DIMC_J1939_TC1MOD_CARB_Mode_1+2B8  4A 01 F4 30                             bmov    r4.0, PROKON_Bits.b_lsh2 ;  : Condition 2. Lambda sensor installed downstream of cat (Bank2)
DIMC_J1939_TC1MOD_CARB_Mode_1+2BC  49 81                                   cmpb    rl4, #1
DIMC_J1939_TC1MOD_CARB_Mode_1+2BE  3D 04                                   jmpr    cc_NZ, checks_done    <----------- HERE
DIMC_J1939_TC1MOD_CARB_Mode_1+2C0  A9 86                                   movb    rl4, [r6]
DIMC_J1939_TC1MOD_CARB_Mode_1+2C2  07 F8 20 00                             addb    rl4, #20h
DIMC_J1939_TC1MOD_CARB_Mode_1+2C6  B9 86                                   movb    [r6], rl4
DIMC_J1939_TC1MOD_CARB_Mode_1+2C8                          checks_done:
DIMC_J1939_TC1MOD_CARB_Mode_1+2C8  E1 38                                   movb    rl4, #3
DIMC_J1939_TC1MOD_CARB_Mode_1+2CA  0D 1D                                   jmpr    cc_UC, _exit_func


Could be modified to fake they are installed with


DIMC_CARB_InstalledLambdaSensors_PID_13h:
DIMC_J1939_TC1MOD_CARB_Mode_1+282  E1 08                                   movb    rl4, #33h
DIMC_J1939_TC1MOD_CARB_Mode_1+292  B9 86                                   movb    [r6], rl4
DIMC_J1939_TC1MOD_CARB_Mode_1+2CA  0D 1D                                   jmpr    cc_UC, _exit_func



And ofcourse it also reports the voltage of the O2 sensors too so you may need to take the voltage of the Primary and reduce it by how much a catalyst would normally do with a bit of hysteria (random values to simulate real world)

DIMC_J1939_TC1MOD_CARB_Mode_1+2CC                          DIMC_CARB_OxygenSensorOutputVoltageOfSensorDownstreamCat_PID_15h:
DIMC_J1939_TC1MOD_CARB_Mode_1+2CC  A4 06 73 8B                             movb    [r6], ushkj     ; ushkj : Voltage lambda probe behind Kat, without offset
DIMC_J1939_TC1MOD_CARB_Mode_1+2D0  E7 F8 FF 00                             movb    rl4, #0FFh
DIMC_J1939_TC1MOD_CARB_Mode_1+2D4  B9 87                                   movb    [r7], rl4
DIMC_J1939_TC1MOD_CARB_Mode_1+2D6  E1 48                                   movb    rl4, #4
DIMC_J1939_TC1MOD_CARB_Mode_1+2D8  0D 16                                   jmpr    cc_UC, _exit_func

« Last Edit: May 28, 2021, 03:10:06 AM by 360trev » Logged
prj
Hero Member
*****

Karma: +403/-108
Offline Offline

Posts: 4120


« Reply #8 on: May 28, 2021, 04:50:29 AM »

I think this is only some states in the US though. Most of the time the method you described will be perfectly fine.
Logged
bamofo
Sr. Member
****

Karma: +29/-1
Offline Offline

Posts: 352


« Reply #9 on: May 28, 2021, 07:16:25 AM »

I think this is only some states in the US though. Most of the time the method you described will be perfectly fine.

Not only are some of the US states doing your above reset to see if it instantly pass, it also is now comparing last years pass/unsupported/failed because they allow X amount of systems to be incomplete in a test to still pass. So if you turned off misfire over the last year for instance, you may fail your next test in at least 6 states. So if you want to do it right you should set readiness for systems in question based off a system that always passes like O2 Heating, or you should setup the ECU so it still passes without the systems feedback on the pieces that fail. Either way its a cool writeup.
Logged
Blazius
Hero Member
*****

Karma: +52/-30
Online Online

Posts: 950



« Reply #10 on: May 28, 2021, 11:36:27 AM »

Not only are some of the US states doing your above reset to see if it instantly pass, it also is now comparing last years pass/unsupported/failed because they allow X amount of systems to be incomplete in a test to still pass. So if you turned off misfire over the last year for instance, you may fail your next test in at least 6 states. So if you want to do it right you should set readiness for systems in question based off a system that always passes like O2 Heating, or you should setup the ECU so it still passes without the systems feedback on the pieces that fail. Either way its a cool writeup.

What a load of bullshit.. but hey cars are bad and they should all be banned, meanwhile electrics are great!!!!!

But I suppose everything can be "fixed" with the right connections Tongue?

Nice writeup trev.
Logged
360trev
Full Member
***

Karma: +45/-1
Offline Offline

Posts: 195


« Reply #11 on: May 30, 2021, 01:55:25 PM »

Not only are some of the US states doing your above reset to see if it instantly pass, it also is now comparing last years pass/unsupported/failed because they allow X amount of systems to be incomplete in a test to still pass. So if you turned off misfire over the last year for instance, you may fail your next test in at least 6 states. So if you want to do it right you should set readiness for systems in question based off a system that always passes like O2 Heating, or you should setup the ECU so it still passes without the systems feedback on the pieces that fail. Either way its a cool writeup.

Thanks,

Yes, that's a great idea. Link all test passes to just one of them. That way its still going through the usual testing cycles, etc. but should pass pretty quickly then. This is actually probably the easiest way to accomplish it with the minimum of code patches required. I would still think we'd need to patch all the standard PID requests for number of o2's so it reports as it should and then it should just work..


Logged
bamofo
Sr. Member
****

Karma: +29/-1
Offline Offline

Posts: 352


« Reply #12 on: June 01, 2021, 09:47:18 AM »

Thanks,

Yes, that's a great idea. Link all test passes to just one of them. That way its still going through the usual testing cycles, etc. but should pass pretty quickly then. This is actually probably the easiest way to accomplish it with the minimum of code patches required. I would still think we'd need to patch all the standard PID requests for number of o2's so it reports as it should and then it should just work..




I have not had any emissions related failures due to changing the number of O2 sensors. What i have had issues with was (Misfire detection / SAI / Catalyst of course / (any single system failing 2 years in a row).

But the others can be manipulated to make it work.
Logged
prj
Hero Member
*****

Karma: +403/-108
Offline Offline

Posts: 4120


« Reply #13 on: June 01, 2021, 01:03:23 PM »

I agree also with linking it to something that always passes.
All you need to do is have a configurable byte where you can select the main supported mask, that you can get by ID-ing an unmolested binary, and then tie passed/not passed to something like front o2 heating, as said instead of checking individually.
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Page created in 0.05 seconds with 17 queries. (Pretty URLs adds 0s, 0q)