TRW450 Reverse Engineering Writeup
![[Pasted image 20250625105754.png]]
**Project Background**
Traditionally, enabling additional features in TRW450 modules required physically accessing the EEPROM; This compromised waterproofing and was especially difficult on left-hand drive vehicles. I was Inspired by Willem Melching’s work on EPS modifications [[icanhack.nl](https://icanhack.nl/blog/vw-part1)] , so I started this project to create a software-only solution.
**Hardware Analysis**
Overview of the TMS470 Microcontroller
The TRW450 ABS module utilizes the Texas Instruments TMS470R1VF67ACZJQ microcontroller, based on the ARM7TDMI architecture. This automotive-grade MCU serves as both the main processor and coprocessor in the system.
After examining datasheets, we obtained RAM size, control register maps, and memory mappings to assist in Ghidra. The binary was imported as ARMv4T BE.
The TMS470's programmable memory selectors allow remapping RAM and program memory. After some trial and error, RAM was confirmed to be at 0x200000.
Loaded symbol maps for known addresses, including:
![[Pasted image 20250625105907.png]]
GIO0 0xFFF7EC00 l
SPI1 0xFFF7F800 l
SPI2 0xFFF7D400 l
SPI3 0xFFF7D500 l
SPI4 0xFFF7D600 l
SPI5 0xFFF7D700 l
SCC 0xFFF7E800 l
SCC2 0xFFF7EA00 l
SCC3 0xFFF7D000 l
CAN_MBOX 0xFFF7E400 l
CAN_MBOX2 0xFFF7E600 l
CAN_MBOX3 0xFFF7D200 l
We are also missing the first 0x4000, that is where the bootloader lives, we may need access to this location later on, but for now we just put a placeholder.
**Hardware Version Analysis**
Using Ghidra's scalar search for hardware version identifiers, a hunt for the ASCII value 0x45 (“E”) led to functions referencing hardware versions (4, 5, D, E). One function validated these versions, indicating a compatibility check. References to V2 and V3 confirmed further version control mechanisms.
![[Pasted image 20250625105927.png]]
Another key function managed software part numbers stored to the EEPROM, but neglected to write them for V4 and V5 variants, a known bug in firmware version 42.
![[Pasted image 20250625105945.png]]
**Feature Mask Discovery**
A major breakthrough came from analysing the below function. Converting the hexadecimal values to binary revealed a pattern:
![[Pasted image 20250625110004.png]]
VE: 0xB8 (1011 1000) : Full feature set
VD: 0x98 (1001 1000) : Missing one bit (TPMS)
V5: 0xB0 (1011 0000) : Missing one bit (ACC)
V4: 0x90 (1001 0000) : Features disabled
This binary mask revealed how features are controlled through bit flags, with each bit corresponding to a specific function.
Such an approach allows manufacturers to toggle features across different markets or model types without needing entirely new hardware. For instance, if indirect TPMS became mandatory in certain regions during the module’s production, they could simply enable the relevant bit on any HW version.
**Developing the Patch**
Based on these findings, there are six memory addresses that, when modified, enable the full feature set across 4-D hardware versions. However, if you only want to enable a single feature for example, ACC on V5, then you only need to flip the one corresponding bit in the feature mask rather than modifying all six addresses.
![[Pasted image 20250625110022.png]]
Hardware Version ('E'):
0x345E3 → 0x45
0x345E9 → 0x45
0x345EF → 0x45
Feature Mask (0xB8):
0x345E5 → 0xB8
0x345EB → 0xB8
0x345F1 → 0xB8
**Checksum**
One of the biggest challenges was working out the firmware's checksum system. Modifications triggered the bootloader mode (Reporting "BLV 7.4") indicating a checksum was failing somewhere in the process. Early attempts using standard CRC algorithms led nowhere, even after reviewing other TRW products (including GM implementations) and exploring the TMS chip’s PSA features lead me even to look at GM BCM code also running on a TMS chip [pcmhacking.net](https://pcmhacking.net/forums/viewtopic.php?t=7100&start=90)
When I compared different firmware versions that had only minor differences. It revealed patterns suggesting the checksum might be a simpler byte-sum method plus shifts in header values, tied to prefixes like "3AA" and "7N0" hinted that "magic numbers" were used, based on internal naming or project conventions.
Ultimately, the checksum algorithm proved surprisingly simple and close to the SGO format's approach:
Sum all bytes after the header, starting at offset 0x06
Subtract 1
XOR with 0xFF
Add a magic number derived from the firmware header
I’ll be posting a separate, in-depth write-up on the checksum soon. It will include details on how I reverse-engineered each step, tested the patch, and verified it on the actual hardware. This deeper dive will be particularly helpful if you’re trying to replicate or adapt the checksum process for other modules.
I will also include details on the VIN checking logic and brake parameter tables.
![[Pasted image 20250625110102.png]]