15 minute read

Tracing the code supporting the OBD2 Diagnostic Trouble Codes (DTCs) can help provide more insights on which DTCs are supported, and also on the identity of various internal variables. From the earlier post on Canbus and OBD2 ( OBD2 and UDS services ), we have an idea as to which DTC related services are supported, namely:

  • 0x03 - Show DTCs
  • 0x04 - Clear DTCs
  • 0x07 - Show pending DTCs
  • 0x14 - Clear all DTCs

A good place to start is service 3 to show DTCs, and per the above previous post, this is implemented on IC601 using FUN 121c2 when requested via Canbus.

dtc code snapshot1

At the start of the function, there is some housekeeping related to the canbus request:

  • check that no UDS service 31 is active, which would cause conflicts (variable b12e4 bit 2 not set)
  • check the canbus request command is of the correct length (variable b16cf is equal to 0)
  • start to prepare the response message (0x43 is response to service request 0x03 - i.e. add 0x40 to service request)

Then there is a setup for a function call

  • temporary variable b0064 is loaded with the value 0xcc
  • X pointer is loaded with the address 0x1b8b4, so it likely points to a lookup table of some kind
  • Jump to subroutine 0x116f4

After the jump to subroutine, there is some more setup (preparing the response message) and then the following:

dtc code snapshot2

An address offset is computed based on the variable b16e8 multiplied by 0x0a (= decimal 10) 6 is added to this offset, and then this overall offset, combined with the table base address in X, is used to load a value into register D

i.e. LDD E,X: Load register D with value stored at address X + E = 0x1b8b4 + (10 * var b16e8) + 6

The other notable point is the arrow on the left, coming from below, and pointing to LAB_00011708 (address 0x11708). This indicates that there is a jump from later on in the subroutine, which loops back to address 0x11708, which suggests an iterative loop.

Moving down in the function to where it loops back, we see the following:

dtc code snapshot3

We have the test: (value of temporary variable b0064 - 1) <= (value of variable b16e8). Since b0064 was initialized to the value 0xcc at the start, then we are checking if variable b16e8 >= 0xcb (0xcb = 203 decimal). Assuming variable b16e8 is set to 0 on entry (which it is), then the test will fail. Ignoring for a moment the test of b16ea bit 5 (related to P1000/P1111 monitor drive cycle readiness checking), the value of variable b16e8 is incremented, and we loop back to address 11708

So we have a loop that will execute 204 times, incrementing variable b16e8 from 0 to 203. Since, as above, b16e8 is used to calculate a table address offset, we can conclude that there is a table starting at address 0x1b8b4, with 203 entries each of 10 bytes.

We also know that a word is stored at offset 6 for each entry, based on the LDD E,X instruction discussed above. Scanning through the function, and looking for other accesses to the table, we can get more insight in the structure of each 10 byte entry

dtc code snapshot4

The entry at offset 2 (base address in variable b0066, plus 2) is used as a pointer to a memory byte, and this byte is used for various bit tests. So we know that offset 2 contains a word value which is a pointer to a memory byte, containing bit flags

dtc code snapshot5

The entry at offset 4 is a word value, which is tested if equal to other constant values like 0x0300, 0x0301, 0x0302, ..0x1313, 0x1316, etc. These look like DTC codes, and it turns out that this is the case, and offset 4 stores the DTC code value.

Analysis can continue along these lines with the other DTC related services, but cutting to the chase, the upshot is:

  • IC601 contains a table starting at 0x1b8b4
  • Each entry contains 10 bytes
    • offset 4 contains the DTC code (word value, in hex)
    • offset 0 contains a pointer to a memory byte, which stores bit flags relating to this DTC state. Sometimes this pointer is null (with value 0xffff)
    • offset 2 contains a pointer to a memory byte, which also stores bit flags relating to this DTC state
    • offset 6 contains a word constant, which stores bit flags. These provide context on how the DTC should be processed.
    • offset 8 contains a pointer to a function, which can be called whilst resetting the DTC. Or the pointer can be null (with value 0xf00f)
  • There are 3 sub-tables
    • First table at address 0x1b8b4 with 158 entries. These entries relate to standardized DTCs which also relevant for component checks
    • second table at address 0x1bee0 with 46 entries. These entries relate to standardized DTCs, not included in component checks.
    • Third table at address 0x1c0ac with 23 entries. These entries relate to proprietary Jaguar DTCs
  • Since processing is split across IC601 and IC501, it should come as not surprise that there are similar tables located on IC501, which are used when the DTC processing code is executed on IC501

In order to assist code analysis, the DTC table data can be formatted and labeled using a script (which I’ll try and address in a subsequent post)

dtc code snapshot6

For the example above, the table located at address 0xb18b4 is designated as “Table 37”. A structure is applied to each 10 byte entry, and here we are looking at entry index [44]. Offset 0 is formatted as a pointer to a byte, commented as “pointer to DTC byte0”. This memory byte is renamed to include the DTC code it is related to, in this case P0122_byte0. Any time this byte is used in other code, it is then will be immediately obvious that the code is related to processing, or status, for P0122. Offset 2 is formatted as a pointer to a byte, commented as “pointer to DTC byte1”. Formatting is similar to offset0. Offset 4 is formatted as a word value, and commented as “DTC code”. In this case we have DTC code P0122. Offset 6 is formatted as a word value, and commented as “DTC type and which CPU”, since the bit flags within this word indicate which CPU supports the DTC, and how it should be processed. Special processing is used for lean/rich codes (P0171-0175), as well as misfire codes (P0300-308, 1313, 1314, 1316). Offset 8 is formatted as a pointer to a function, which if not null (0xf00f) will provide a cross reference to that function.

In this specific case, the P0122 code has the following definition from Jaguar

dtc p0122 definition

So we know that we are dealing with the Throttle Position Sensor (TPS) circuit 1, and detecting if it is out of acceptable range with an excessively low value. Tracing “byte1” by double clicking on it, Ghidra takes us to its location, and we can see which functions reference it

dtc code snapshot7

The above tells us that FUN 575a is likely responsible for detecting the out of range condition.

dtc code snapshot8

Examining FUN 575a we first see a test on variable b0002, to see if it is lower in value that the constant value 0x0048 stored at b85a8. So if we did not determine it earlier (and so had not already labeled b0002 as “TPS1_1”), we would now know that variable b0002 is probably TPS circuit 1 voltage. This illustrates how knowledge of the DTC codes can assist in determining the identities of various variables.

Looking in more detail at the code, we have two possible outcomes:

  • the TPS voltage is < threshold (0x0048) - which is likely the error condition
    • in this case a counter (b0834) is incremented
    • then at 5790, if this counter exceeds the value 0x06 (meaning the error condition has continued for 6 iterations), the following actions are taken
      • the counter is reset to 0
      • bits 0 and 4 of DTC byte0 are set
      • bits 0 and 1 of DTC byte 1 are set
  • if the TPS voltage is >= threshold (0x0048) - which is likely the no fault condition
    • at 5764 the counter is reset to 0
    • bits 0 is cleared and bit 5 is set for DTC byte 0
    • bit 1 is cleared for DTC byte 1
  • the above analysis has skipped over a couple of other tests, which relate to conditions like the supply voltage being out of range, etc.
  • the remaining part of the function relates to similar tests for P0222, which is TPS2 voltage out of range low evaluation

So we have insights into some of the bit flag states relating to the DTC detection process

  • error condition triggered
    • set byte0 bit 0, bit 4
    • set byte1 bit 0, bit 1
  • error condition cleared
    • clr byte0 bit 0
    • set byte0 bit 5
    • clr byte1 bit 1

Subsequent to this error detection process, the state of DTC byte0 and byte1 are further processed by a ‘state machine’ function. The location from which this state machine function is called is not immediately obvious, because of the use of indirect references, but a little searching reveals the following:

dtc code snapshot9

The addresses for byte0 (0xb0827) and byte1 (0xb110e) are loaded into the X and Y registers, and then a call is made to FUN 193f0. It can also been seen that similar calls are made for other pairs of variables, relating to other DTCs. FUN 193f0 is a bit complex to analyze, but basically processes the state of various bits, depending on how the bits are set/cleared by the DTC detection routines (and some other processes).

An (incomplete) summary of what the various bits represent, is as follows:

  • byte0
    • bit 0, set when error condition triggered, clr when error condition cleared
    • bit 5, set when DTC readiness conditions met, clr if readiness conditions not met
  • byte 1
    • bit 0, set if error condition triggered, clr at start of next drive cycle
    • bit 1, set if error condition triggered, clr when error condition cleared
    • bit 2, set on if error condition for 2 drive cycles - used in freeze frame triggering
    • bit 3, set on if error condition for 2 drive cycles - used to determine CEL status
    • bit 4, set on if error condition for 2 drive cycles
    • bit 6, set and triggers freeze frame recording if bit 2 is set
    • bit 7, set if byte0 bit 5 is set, used for P1000/P1111 determination (monitor drive cycle readiness checks complete)

By extracting data from the DTC tables discussed above, a summary of which DTC codes are supported, and the identity of the byte0 and byte1 can be created. To conclude this post, a summary of that information is shown below.

Table Entry Byte0 Byte1 DTC DTC Type FUN
subtable 1          
0 BFFFF B1328 171 3320 1F00F
1 BFFFF B1326 172 3320 1F00F
2 BFFFF B132C 174 3320 1F00F
3 BFFFF B132A 175 3320 1F00F
4 B163F B11D7 300 FA20 1B802
5 B163F B11D7 301 FA20 1B802
6 B163F B11D7 302 FA20 1B802
7 B163F B11D7 303 FA20 1B802
8 B163F B11D7 304 FA20 1B802
9 B163F B11D7 305 FA20 1B802
10 B163F B11D7 306 FA20 1B802
11 B163F B11D7 307 FA20 1B802
12 B163F B11D7 308 FA20 1B802
13 B163F B11D7 1313 FA3F 1B858
14 B163F B11D7 1314 FA60 1B858
15 B1644 B11DC 1316 FA20 1B886
16 B06C6 B10F4 10 F020 1F00F
17 B06CA B10F8 20 F020 1F00F
18 BFFFF B138A 31 3220 1F00F
19 BFFFF B138C 32 3220 1F00F
20 B07D4 B10EA 37 F220 1F00F
21 B07DC B10EE 38 F220 1F00F
22 BFFFF B138E 51 3220 1F00F
23 BFFFF B1390 52 3220 1F00F
24 B07D6 B10EC 57 F220 1F00F
25 B07E2 B10F0 58 F220 1F00F
26 BFFFF B13BE 65 2020 1F00F
27 BFFFF B13BC 66 3020 1F00F
28 BFFFF B13BA 101 3022 1F00F
29 BFFFF B13B4 102 3020 1F00F
30 BFFFF B13B6 103 3020 1F00F
31 B10B1 B1120 105 F020 1F00F
32 BFFFF B1386 106 3020 1F00F
33 BFFFF B1382 107 3020 1F00F
34 BFFFF B1384 108 3020 1F00F
35 BFFFF B13D4 111 3020 1F00F
36 BFFFF B13D6 111 3020 1F00F
37 BFFFF B13A2 112 3020 1F00F
38 BFFFF B13A4 113 3020 1F00F
39 BFFFF B13D0 116 3021 1F00F
40 BFFFF B13D2 116 3021 1F00F
41 BFFFF B139E 117 3020 1F00F
42 BFFFF B13A0 118 3020 1F00F
43 B082B B1118 121 F03A 1F00F
44 B0827 B110E 122 F020 1F00F
45 B0828 B1114 123 F020 1F00F
46 BFFFF B13D0 125 3020 1F00F
47 B07FA B123E 128 F000 1F00F
48 BFFFF B1392 131 3220 1F00F
49 BFFFF B1394 132 3220 1F00F
50 BFFFF B13B0 133 2220 1F00F
51 BFFFF B13A8 137 3220 1F00F
52 BFFFF B13AC 138 3220 1F00F
53 BFFFF B1356 140 2220 1F00F
54 BFFFF B1396 151 3220 1F00F
55 BFFFF B1398 152 3220 1F00F
56 BFFFF B13B2 153 2220 1F00F
57 BFFFF B13AA 157 3220 1F00F
58 BFFFF B13AE 158 3220 1F00F
59 BFFFF B13A6 160 2220 1F00F
60 BFFFF B1372 196 3020 1F00F
61 BFFFF B136E 197 3020 1F00F
62 BFFFF B1370 198 3020 1F00F
63 BFFFF B132E 201 3020 1F00F
64 BFFFF B1334 202 3020 1F00F
65 BFFFF B1338 203 3020 1F00F
66 BFFFF B1332 204 3020 1F00F
67 BFFFF B1330 205 3020 1F00F
68 BFFFF B1336 206 3020 1F00F
69 BFFFF B133A 207 3020 1F00F
70 BFFFF B133C 208 3020 1F00F
71 B0829 B1110 222 F020 1F00F
72 B082A B1116 223 F020 1F00F
73 BFFFF B135C 327 3023 1F00F
74 BFFFF B135E 328 3024 1F00F
75 BFFFF B1360 332 3025 1F00F
76 BFFFF B1362 333 3026 1F00F
77 BFFFF B137C 335 3020 1F00F
78 BFFFF B137E 336 3020 1F00F
79 BFFFF B1374 340 3020 1F00F
80 BFFFF B1378 341 3020 1F00F
81 BFFFF B1340 351 3020 1F00F
82 BFFFF B134A 352 3020 1F00F
83 BFFFF B134C 353 3020 1F00F
84 BFFFF B1342 354 3020 1F00F
85 BFFFF B1348 355 3020 1F00F
86 BFFFF B1344 356 3020 1F00F
87 BFFFF B133E 357 3020 1F00F
88 BFFFF B1346 358 3020 1F00F
89 B0699 B1230 400 E220 1F00F
90 B069A B1232 400 E220 1F00F
91 B069C B123A 405 F220 1F00F
92 B069E B123C 406 F220 1F00F
93 BFFFF B1352 420 2220 1F00F
94 BFFFF B1354 430 2220 1F00F
95 B0888 B10DA 441 C220 1F00F
96 B0881 B10D6 442 E200 1F00F
97 B0883 B10DC 443 F000 1F00F
98 BFFFF B139A 444 3020 1F00F
99 BFFFF B139C 445 3020 1F00F
100 B0884 B10DE 446 F000 1F00F
101 B0886 B10FC 447 F000 1F00F
102 B0887 B10FE 448 F000 1F00F
103 B0885 B10E0 450 F000 1F00F
104 BFFFF B13C8 452 3000 1F00F
105 BFFFF B13CA 453 3000 1F00F
106 B0880 B10D4 455 E200 1F00F
107 B0882 B10D8 456 E000 1F00F
108 BFFFF B1380 460 3020 1F00F
109 B082C B111C 506 F000 1F00F
110 B082D B111E 507 F000 1F00F
111 B07CE B10F2 560 F020 1F00F
112 BFFFF B1388 603 2020 1F00F
113 BFFFF B13B8 1104 3020 1F00F
114 B10B3 B1122 1107 F020 1F00F
115 B10B2 B1124 1108 F020 1F00F
116 BFFFF B13DE 1112 3020 1F00F
117 BFFFF B13E0 1113 3020 1F00F
118 B0826 B1100 1121 F039 1F00F
119 B0822 B1102 1122 F035 1F00F
120 B0824 B1106 1123 F036 1F00F
121 B0823 B1104 1222 F037 1F00F
122 B0825 B1108 1223 F038 1F00F
123 B0820 B1112 1224 F033 1F00F
124 B0821 B111A 1229 F034 1F00F
125 BFFFF B13CE 1230 3020 1F00F
126 BFFFF B13CC 1230 3020 1F00F
127 B07C4 B10E6 1240 F031 1F00F
128 B07C0 B10E2 1241 F020 1F00F
129 B07C2 B10E4 1242 F020 1F00F
130 B07CC B10E8 1243 F020 1F00F
131 BFFFF B13C4 1245 3000 1F00F
132 BFFFF B13C6 1246 3000 1F00F
133 B086B B110A 1251 F03B 1F00F
134 BFFFF B1376 1340 3020 1F00F
135 BFFFF B137A 1341 3020 1F00F
136 BFFFF B134E 1367 3020 1F00F
137 BFFFF B1350 1368 3020 1F00F
138 B06C7 B10F6 1384 F020 1F00F
139 B06CB B10FA 1396 F020 1F00F
140 B07F6 B1234 1474 F020 1F00F
141 BFFFF B13C2 1516 3000 1F00F
142 B07CA B1126 1606 E020 1F00F
143 B07D2 B1900 1609 7032 1F00F
144 BFFFF B13D8 1611 3028 1F00F
145 B086C B110C 1631 F03C 1F00F
146 BFFFF B13DA 1633 3029 1F00F
147 B070B B112E 1634 F020 1F00F
148 BFFFF B1368 1637 3020 1F00F
149 BFFFF B136C 1638 2020 1F00F
150 BFFFF B136A 1642 2020 1F00F
151 BFFFF B1366 1643 3020 1F00F
152 BFFFF B1358 1646 3220 1F00F
153 BFFFF B135A 1647 3220 1F00F
154 BFFFF B1364 1648 3027 1F00F
155 B0816 B1240 1649 F020 1F00F
156 B06D2 B112A 1656 F020 1F00F
157 BFFFF B13DC 1671 3020 1F00F
subtable 2          
158 BFFFF B13F0 702 30AC 1F00F
159 BFFFF B140A 705 30AE 1F00F
160 BFFFF B13F1 706 30AD 1F00F
161 BFFFF B13FD 711 30A0 1F00F
162 BFFFF B13FE 712 30A0 1F00F
163 BFFFF B13FF 713 30A0 1F00F
164 BFFFF B13F4 715 30A0 1F00F
165 BFFFF B140B 730 30AF 1F00F
166 BFFFF B1404 731 30A0 1F00F
167 BFFFF B1405 732 30A0 1F00F
168 BFFFF B1406 733 30A0 1F00F
169 BFFFF B1407 734 30A0 1F00F
170 BFFFF B1408 735 30A0 1F00F
171 BFFFF B1410 740 30A0 1F00F
172 BFFFF B13F6 741 30A0 1F00F
173 BFFFF B13F7 742 30A0 1F00F
174 BFFFF B13F8 743 30A0 1F00F
175 BFFFF B1409 748 30A0 1F00F
176 BFFFF B1400 753 30A0 1F00F
177 BFFFF B1401 758 30A0 1F00F
178 BFFFF B1402 763 30A0 1F00F
179 BFFFF B140C 780 30A0 1F00F
180 BFFFF B140D 1601 30B0 1F00F
181 BFFFF B13ED 1603 30A0 1F00F
182 BFFFF B13EC 1605 30AB 1F00F
183 BFFFF B13EE 1608 30A0 1F00F
184 BFFFF B140E 1700 30A0 1F00F
185 BFFFF B13F2 1720 30A0 1F00F
186 BFFFF B13F5 1722 30A0 1F00F
187 BFFFF B13F3 1726 30A0 1F00F
188 BFFFF B13EF 1732 30A0 1F00F
189 BFFFF B1403 1733 30A0 1F00F
190 BFFFF B1411 1744 30A0 1F00F
191 BFFFF B13F9 1745 30A0 1F00F
192 BFFFF B13FA 1746 30A0 1F00F
193 BFFFF B13FB 1747 30A0 1F00F
194 BFFFF B13FC 1748 30A0 1F00F
195 BFFFF B140F 1758 30A0 1F00F
196 BFFFF B13EB 1789 30A0 1F00F
197 BFFFF B13EA 1793 30A0 1F00F
198 BFFFF B13E7 1795 30A0 1F00F
199 BFFFF B13E8 1796 30A0 1F00F
200 BFFFF B13E9 1797 30AA 1F00F
201 BFFFF B1414 5137 30A0 1F00F
202 BFFFF B1412 5165 30A0 1F00F
203 BFFFF B1413 5175 30A0 1F00F
subtable 3          
204 BFFFF B13E4 480 400 1F00F
205 BFFFF B13E5 480 400 1F00F
206 BFFFF B13E2 482 400 1F00F
207 BFFFF B13E3 482 400 1F00F
208 B06DA B1136 566 C400 1F00F
209 B06D9 B1135 567 C400 1F00F
210 B06D5 B1131 568 C400 1F00F
211 B06D6 B1132 568 C400 1F00F
212 B06D8 B1134 569 C400 1F00F
213 B06D7 B1133 570 C400 1F00F
214 B070F B1242 1136 C400 1F00F
215 B06D1 B1129 1250 C41E 1F00F
216 B06D0 B1128 1254 C41D 1F00F
217 BFFFF B1415 1260 400 1F00F
218 BFFFF B1416 1260 400 1F00F
219 BFFFF B13C0 1517 400 1F00F
220 B06D4 B1130 1571 C400 1F00F
221 BFFFF B13E6 1582 400 1F00F
222 B070E B112D 1657 C400 1F00F
223 B070A B112C 1658 C400 1F00F
224 B06DC B1157 1697 C400 1F00F
225 B06DB B1137 1697 C400 1F00F
226 B06DD B1177 1696 C400 1F00F