Since this is not part of the CEM swapping subject, I decided to open a new one.
I have a 2001 XC70 that I only have one key and one fob for. I found a donor car (2003) and pulled the UEM and CEM and have 2 flip keys with it. I can either swap the actual locks or cut blades for my own car, but is it possible to read the donor UEM and/or CEM to copy the key information and add these to my own car?
I am assuming I will need to read/write the two modules from both cars, find key/fob info edit binaries for the target vehicle, correct checksums and write the CEM/UEM for the target vehicle.
Has anyone done this? What hardware and software do I need? Is there a good procedure for this? Obviously, the goal is to do research and get this well documented, find the cheapest reliable option just like the CEM swapping project is doing.
Using keys from one car on another: CEM/UEM reading/copy
-
vtl
- Posts: 4724
- Joined: 16 August 2012
- Year and Model: 2005 XC70
- Location: Boston
- Has thanked: 114 times
- Been thanked: 605 times
In the donor chassis to which I transplanted the whole drivetrain and interior from my crashed XC70, I detached the immobilizer antenna from the steering column, glued the only donor's key I've had to it and had it hidden under the dash. Next thing is I drilled the ignition lock security bolts out and replaced it with the my lock, which had a full set of 3 keys. Then I swapped UEM for remotes.
The valet key I put in engine compartment, inside a fuse box. Just in case the doors become locked (though I never do it) I attached a pair of steel cables to both hood locks, so the hood could be opened by pulling the cables. Even if that is not possible for some reason, the door glass can be broken, the ignition switch can be unscrewed and the car started with a screwdriver, or knife, or anything.
I think I'm all set
Though I'd love to disable immobilizer permanently, it's a single choking point that may leave me or my kid stranded. Old Volvo itself is a sufficient car theft deterrent.
The valet key I put in engine compartment, inside a fuse box. Just in case the doors become locked (though I never do it) I attached a pair of steel cables to both hood locks, so the hood could be opened by pulling the cables. Even if that is not possible for some reason, the door glass can be broken, the ignition switch can be unscrewed and the car started with a screwdriver, or knife, or anything.
I think I'm all set
-
WhizzMan
- Posts: 33
- Joined: 21 February 2021
- Year and Model: 2001 XC70
- Location: Göteborg
- Has thanked: 8 times
- Been thanked: 2 times
While I see the practicality of your solution, I am hoping to get to a point where "ordinary folks" no longer have to resort to this sort of a solution.
My 850T5 got stolen (because it didn't have an immobilizer) by a bunch of white trash that first "drove it like they stole it" until it was almost out of oil and then stole my R wheels, left driver door (!!???), my luggage cover, portable toolcase and my stereo. Police incompetence and legal limits made them get away with the crime, even though I knew exactly who stole the car (don't lose your debit card and letters from your social worker in a vehicle you have stolen. Police did a "forensic examination" of the car but other than dust the steering wheel and handles for prints they apparently didn't do a search).
Since then, I really appreciate having a working immobilizer and the odd tracking device(s) somewhere hidden in my vehicles.
Any information helping getting the dumps of the CEM, UEM and the ECM and decoding the immo/fob bits so they can be edited and reprogrammed would be helpful. I can re-read the CEM swapping topic and copy/paste everything relevant I find here. There are commercial solutions to do this, several enterprising individuals have made their own private tools already to do at least part of this. This ain't rocket surgery! I am hoping that others will add to this so we can as a community get somewhere with this. the CEM swapping topic is a succesful example of what a community can do, I am hoping to see a repeat here.
My 850T5 got stolen (because it didn't have an immobilizer) by a bunch of white trash that first "drove it like they stole it" until it was almost out of oil and then stole my R wheels, left driver door (!!???), my luggage cover, portable toolcase and my stereo. Police incompetence and legal limits made them get away with the crime, even though I knew exactly who stole the car (don't lose your debit card and letters from your social worker in a vehicle you have stolen. Police did a "forensic examination" of the car but other than dust the steering wheel and handles for prints they apparently didn't do a search).
Since then, I really appreciate having a working immobilizer and the odd tracking device(s) somewhere hidden in my vehicles.
Any information helping getting the dumps of the CEM, UEM and the ECM and decoding the immo/fob bits so they can be edited and reprogrammed would be helpful. I can re-read the CEM swapping topic and copy/paste everything relevant I find here. There are commercial solutions to do this, several enterprising individuals have made their own private tools already to do at least part of this. This ain't rocket surgery! I am hoping that others will add to this so we can as a community get somewhere with this. the CEM swapping topic is a succesful example of what a community can do, I am hoping to see a repeat here.
-
vtl
- Posts: 4724
- Joined: 16 August 2012
- Year and Model: 2005 XC70
- Location: Boston
- Has thanked: 114 times
- Been thanked: 605 times
I don't do anything related to Volvo software reprogramming, so I can't add anything to that thread, but I think you have to start in that long CEM cracker thread. It simply gets the attention of all the right folks over there, who do it for life. Then, as you said, you could distill the essential bits in this thread. Or not. You may be taking bread and butter away from these folks 
- matthew1
- Site Admin
- Posts: 14463
- Joined: 14 September 2002
- Year and Model: 850 T5, 1997
- Location: Denver, Colorado, US
- Has thanked: 2652 times
- Been thanked: 1240 times
- Contact:
I'm sorry to hear this. You have my sympathy. My 850 got stolen also, about 10 years ago. I wrote about it in the 850 forum.WhizzMan wrote: ↑14 Nov 2023, 10:44 My 850T5 got stolen (because it didn't have an immobilizer) by a bunch of white trash that first "drove it like they stole it" until it was almost out of oil and then stole my R wheels, left driver door (!!???), my luggage cover, portable toolcase and my stereo. Police incompetence and legal limits made them get away with the crime, even though I knew exactly who stole the car (don't lose your debit card and letters from your social worker in a vehicle you have stolen. Police did a "forensic examination" of the car but other than dust the steering wheel and handles for prints they apparently didn't do a search).
Sorry I can't help with the P2 key question.
Help keep MVS on the web -> click sponsors' links here on MVS when you buy from them.
Also -> Amazon link. Click that when you go to buy something on Amazon and MVS gets a cut!
1998 V70, no dash lights on
1997 850 T5 [gone] w/ MSD ignition coil, Hallman manual boost controller, injectors, R bumper, OMP strut brace
2004 V70 R [gone]
How to Thank someone for their post

Also -> Amazon link. Click that when you go to buy something on Amazon and MVS gets a cut!
1998 V70, no dash lights on
1997 850 T5 [gone] w/ MSD ignition coil, Hallman manual boost controller, injectors, R bumper, OMP strut brace
2004 V70 R [gone]
How to Thank someone for their post

-
WhizzMan
- Posts: 33
- Joined: 21 February 2021
- Year and Model: 2001 XC70
- Location: Göteborg
- Has thanked: 8 times
- Been thanked: 2 times
Thanks to LukeT5, arduino code to dump the CEM firmware. Will post the schematic to go with this later.
T5Luke wrote: ↑21 Aug 2022, 03:29 Here have fun with it:
Code: Select all
#define BKPT 4 #define RESET 5 #define FREEZE 6 #define DSI 7 #define DSO 8 static word CMD_READ = 0x1940; static word CMD_GO = 0x0C00; static word CMD_WRITEM = 0x1840; char command; int n_line; void setup() { // put your setup code here, to run once: pinMode(BKPT, OUTPUT); digitalWrite(BKPT, HIGH); pinMode(RESET, OUTPUT); digitalWrite(RESET, LOW); pinMode(FREEZE, INPUT); pinMode(DSI, OUTPUT); digitalWrite(DSI, LOW); pinMode(DSO, INPUT); Serial.begin(57600); while(!Serial){ } Serial.println(F("Arduino CEM Reader, press:")); Serial.println(); Serial.println(F("e: enter BDM Mode")); Serial.println(F("l: leave BDM (experimental)")); Serial.println(F("r: read complete memory")); Serial.println(F("b: read Boot 0-3FFF")); Serial.println(F("s: read security block 4000-7FFF")); Serial.println(F("d: read car data 8000-1FFFF")); Serial.println(F("f: read firmware 20000-7FFFF")); Serial.println(F("c: BD32 Command Mode")); } void loop() { // put your main code here, to run repeatedly: if (Serial.available()) { command = Serial.read(); switch (command) { case 'e': Serial.println("Enter BDM"); digitalWrite(BKPT, LOW); delay(10); digitalWrite(RESET, HIGH); delay(100); Serial.println(digitalRead(FREEZE)); break; case 'l': Serial.println("leave BDM"); shift_BKPT_up(); digitalWrite(RESET, LOW); delay(10); digitalWrite(RESET, HIGH); wait_openchannel(); bdm_command(CMD_GO); digitalWrite(DSO, LOW); shift_BKPT_up(); Serial.println(digitalRead(FREEZE)); break; case 'r': Serial.println("Read FLASH"); for (unsigned long offset = 0x0000; offset<=0x7FFFF; offset = offset + 0x02) { shiftRWord(offset); } break; case 'b': Serial.println(F("Read bootblock")); for (unsigned long offset = 0x0000; offset<=0x3FFF; offset = offset + 0x02) { shiftRWord(offset); } break; case 's': Serial.println(F("Read securityblock")); for (unsigned long offset = 0x4000; offset<=0x7FFF; offset = offset + 0x02) { shiftRWord(offset); } break; case 'd': Serial.println(F("Read cardata")); for (unsigned long offset = 0x8000; offset<=0x1FFFF; offset = offset + 0x02) { shiftRWord(offset); } break; case 'f': Serial.println(F("Read firmware")); for (unsigned long offset = 0x10000; offset<=0x7FFFF; offset = offset + 0x02) { shiftRWord(offset); } break; case 'c': Serial.println(F("BD32 Command Mode")); serialFlush(); while(!Serial.available()); { } break; default: break; case 'i': Serial.println("wipe"); for (int i=0; i<=250; i++) { digitalWrite(BKPT, LOW); delay(1); digitalWrite(BKPT, HIGH); delay(1); } break; } } } void shiftRWord(unsigned long val) { word i; word lowbyte = val; word hibyte = val >> 16; //Wait for DSO to get 0 => gets ready wait_openchannel(); bdm_command(CMD_READ); shift_BKPT_up(); shift_BKPT_up(); for (i = 0; i < 16; i++) { //HighByte digitalWrite(DSI, !!(hibyte & (1 << (15 - i)))); shift_BKPT_up(); } digitalWrite(DSI, LOW); delayMicroseconds(1); shift_BKPT_up(); for (i = 0; i < 16; i++) { //LowByte digitalWrite(DSI, !!(lowbyte & (1 << (15 - i)))); shift_BKPT_up(); } digitalWrite(DSI, LOW); delayMicroseconds(1); word W_Read; for (i= 0; i < 1; i++) //Read Status Byte { //digitalWrite(BKPT, HIGH); //delayMicroseconds(1); digitalWrite(BKPT, LOW); delayMicroseconds(1); //Serial.print(digitalRead(DSO)); } for (i= 0; i < 16; i++) //Read back { digitalWrite(BKPT, HIGH); delayMicroseconds(1); digitalWrite(BKPT, LOW); delayMicroseconds(1); //Serial.print(digitalRead(DSO)); bitWrite(W_Read,(15-i),digitalRead(DSO)); } check_lzero(W_Read); if (n_line <=6) { Serial.print(W_Read,HEX); Serial. print(" "); n_line++; }else{ Serial.println(W_Read,HEX); n_line = 0; } //return W_Read; } void write_Register(word cmd, unsigned long addr) { word lowbyte = addr; word hibyte = addr >> 16; wait_openchannel(); //Wait for DSO to get 0 => gets ready bdm_command2(cmd); shift_BKPT_up(); for (int i = 0; i < 16; i++) { //HighByte OFFSET digitalWrite(DSI, !!(hibyte & (1 << (15 - i)))); shift_BKPT_up(); } digitalWrite(DSI, LOW); delayMicroseconds(1); shift_BKPT_up(); for (int i = 0; i < 16; i++) { //LowByte OFFSET digitalWrite(DSI, !!(lowbyte & (1 << (15 - i)))); shift_BKPT_up(); } digitalWrite(DSI, LOW); delayMicroseconds(1); } void check_lzero(word W_Read){ if (W_Read < 0x10) { Serial.print("000"); return; } if (W_Read < 0x100) { Serial.print("00"); return; } if (W_Read < 0x1000) { Serial.print("0"); return; } } void shift_BKPT_up() { digitalWrite(BKPT, LOW); delayMicroseconds(1); digitalWrite(BKPT, HIGH); delayMicroseconds(1); } void wait_openchannel() { while(digitalRead(DSO)!=0) { shift_BKPT_up(); } while(digitalRead(DSO)!=1) { shift_BKPT_up(); } } void bdm_command(word command) { for (int i = 0; i < 15; i++) { digitalWrite(DSI, !!(command & (1 << (15 - i)))); shift_BKPT_up(); } digitalWrite(DSI, LOW); } void bdm_command2(word command) { for (int i = 0; i < 16; i++) { digitalWrite(DSI, !!(command & (1 << (15 - i)))); shift_BKPT_up(); } digitalWrite(DSI, LOW); } void serialFlush(){ while(Serial.available() > 0) { char t = Serial.read(); } }
-
WhizzMan
- Posts: 33
- Joined: 21 February 2021
- Year and Model: 2001 XC70
- Location: Göteborg
- Has thanked: 8 times
- Been thanked: 2 times
Once again, thanks to LukeT5:
T5Luke wrote: ↑22 Aug 2022, 10:40 Here...
2 options, connect the 5V line at the capacitor, or connect the 12V at the CEMs main connector. Both connections 5V and +12V are not needed together...
Masse means GND
If you use 12V power supply connect GND from it also to arduios GND, so they should have common GND.
-
- Similar Topics
- Replies
- Views
- Last post






