Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Embed:
(wiki syntax)
Show/hide line numbers
t8utils.cpp
00001 /******************************************************************************* 00002 00003 t7utils.cpp 00004 (c) 2011, 2012 by Sophie Dexter 00005 portions (c) Tomi Liljemark (firstname.surname@gmail.com) 00006 00007 This C++ module provides functions for communicating simple messages to and from 00008 the T7 ECU 00009 00010 ******************************************************************************** 00011 00012 WARNING: Use at your own risk, sadly this software comes with no guarantees. 00013 This software is provided 'free' and in good faith, but the author does not 00014 accept liability for any damage arising from its use. 00015 00016 *******************************************************************************/ 00017 00018 #include "t8utils.h" 00019 00020 Timer TesterPresent; 00021 00022 00023 // 00024 // t8_initialise 00025 // 00026 // sends an initialisation message to the T7 ECU 00027 // but doesn't displays anything. 00028 // 00029 // inputs: none 00030 // return: bool TRUE if there was a message, FALSE if no message. 00031 // 00032 00033 00034 bool t8_initialise() 00035 { 00036 return TRUE; 00037 } 00038 00039 bool t8_show_VIN() 00040 { 00041 uint32_t i; 00042 char T8TxFlo[] = T8FLOCTL; 00043 char T8TxMsg[] = T8REQVIN; 00044 char T8RxMsg[8]; 00045 printf("Requesting VIN from T8...\r\n"); 00046 // Send "Request VIN" to Trionic8 00047 if (!can_send_timeout (T8TSTRID, T8TxMsg, 8, T8MESSAGETIMEOUT)) 00048 return FALSE; 00049 // wait for the T8 to reply 00050 // Read "Seed" 00051 // if a message is not received id return false 00052 if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) 00053 return FALSE; 00054 //* DEBUG info... 00055 for (i = 0; i < 8; i++ ) printf("0x%02X ", T8RxMsg[i] ); 00056 printf("\r\n"); 00057 for (i = 5; i < 8; i++ ) printf("%c", T8RxMsg[i] ); 00058 printf("\r\n"); 00059 // Send Trionic8 a "Flow Control Message to get the rest of the VIN 00060 if (!can_send_timeout (T8TSTRID, T8TxFlo, 8, T8MESSAGETIMEOUT)) 00061 return FALSE; 00062 if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) 00063 return FALSE; 00064 //* DEBUG info... 00065 for (i = 0; i < 8; i++ ) printf("0x%02X ", T8RxMsg[i] ); 00066 printf("\r\n"); 00067 for (i = 1; i < 8; i++ ) printf("%c", T8RxMsg[i] ); 00068 printf("\r\n"); 00069 if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) 00070 return FALSE; 00071 //* DEBUG info... 00072 for (i = 0; i < 8; i++ ) printf("0x%02X ", T8RxMsg[i] ); 00073 printf("\r\n"); 00074 for (i = 1; i < 8; i++ ) printf("%c", T8RxMsg[i] ); 00075 printf("\r\n"); 00076 //*/ 00077 return TRUE; 00078 } 00079 00080 bool t8_write_VIN() 00081 { 00082 00083 char SetVin10[] = {0x10,0x13,0x3B,0x90,0x59,0x53,0x33,0x46}; 00084 char SetVin21[] = {0x21,0x46,0x34,0x35,0x53,0x38,0x33,0x31}; 00085 // char SetVin22[] = {0x22,0x30,0x30,0x32,0x33,0x34,0x30,0xaa}; // Original 00086 char SetVin22[] = {0x22,0x30,0x30,0x34,0x33,0x32,0x31,0x00}; 00087 char T8RxMsg[8]; 00088 char k = 0; 00089 00090 // GMLANTesterPresent(T8REQID, T8RESPID); 00091 // wait_ms(2000); 00092 // 00093 // printf("Requesting Security Access\r\n"); 00094 // if (!t8_authenticate(0x01)) { 00095 // printf("Unable to get Security Access\r\n"); 00096 // return FALSE; 00097 // } 00098 // printf("Security Access Granted\r\n"); 00099 // 00100 // GMLANTesterPresent(T8REQID, T8RESPID); 00101 // wait_ms(2000); 00102 // 00103 // GMLANTesterPresent(T8REQID, T8RESPID); 00104 // wait_ms(2000); 00105 // 00106 if (!can_send_timeout (T8TSTRID, SetVin10, 8, T8MESSAGETIMEOUT)) { 00107 printf("Unable to write VIN\r\n"); 00108 return FALSE; 00109 } 00110 for (k = 0; k < 8; k++ ) printf("0x%02X ", SetVin10[k] ); 00111 printf("\r\n"); 00112 if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) 00113 return FALSE; 00114 for (k = 0; k < 8; k++ ) printf("0x%02X ", T8RxMsg[k] ); 00115 printf("\r\n"); 00116 // wait_ms(100); 00117 if (!can_send_timeout (T8TSTRID, SetVin21, 8, T8MESSAGETIMEOUT)) { 00118 printf("Unable to write VIN\r\n"); 00119 return FALSE; 00120 } 00121 for (k = 0; k < 8; k++ ) printf("0x%02X ", SetVin21[k] ); 00122 printf("\r\n"); 00123 // wait_ms(100); 00124 if (!can_send_timeout (T8TSTRID, SetVin22, 8, T8MESSAGETIMEOUT)) { 00125 printf("Unable to write VIN\r\n"); 00126 return FALSE; 00127 } 00128 for (k = 0; k < 8; k++ ) printf("0x%02X ", SetVin22[k] ); 00129 printf("\r\n"); 00130 if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) 00131 return FALSE; 00132 for (k = 0; k < 8; k++ ) printf("0x%02X ", T8RxMsg[k] ); 00133 printf("\r\n"); 00134 return TRUE; 00135 // GMLANTesterPresent(T8REQID, T8RESPID); 00136 // wait_ms(2000); 00137 // 00138 } 00139 00140 // 00141 // t8_authenticate 00142 // 00143 // sends an authentication message to the T7 ECU 00144 // but doesn't display anything. 00145 // 00146 // inputs: none 00147 // return: bool TRUE if there was a message, FALSE if no message. 00148 // 00149 00150 bool t8_authenticate(uint32_t ReqID, uint32_t RespID, char level) 00151 { 00152 uint16_t i, seed, key; 00153 // if (!GMLANSecurityAccessRequest(ReqID, RespID, level, seed)) { 00154 // printf("Unable to request SEED value for security access\r\n"); 00155 // return FALSE; 00156 // } 00157 00158 for (i=0; i < 20; i++) { 00159 if (GMLANSecurityAccessRequest(ReqID, RespID, level, seed)) 00160 break; 00161 wait(1); 00162 GMLANTesterPresent(ReqID, RespID); 00163 } 00164 if (i == 20) { 00165 printf("Unable to request SEED value for security access\r\n"); 00166 return FALSE; 00167 } 00168 00169 if ( seed == 0x0000 ) { 00170 printf("T8 ECU is already unlocked\r\n"); 00171 return TRUE; 00172 } 00173 key = (seed >> 5) | (seed << 11); 00174 key += 0xB988; 00175 if (level == 0xFD) { 00176 key /= 3; 00177 key ^= 0x8749; 00178 key += 0x0ACF; 00179 key ^= 0x81BF; 00180 } else if (level == 0xFB) { 00181 key ^= 0x8749; 00182 key += 0x06D3; 00183 key ^= 0xCFDF; 00184 } 00185 /* CIM KEY CALCULATION 00186 uint16_t key = (seed + 0x9130); 00187 key = (key >> 8) | (key << 8); 00188 key -= 0x3FC7; 00189 */ 00190 wait_ms(1); 00191 if (!GMLANSecurityAccessSendKey(ReqID, RespID, level, key)) { 00192 printf("Unable to send KEY value for security access\r\n"); 00193 return FALSE; 00194 } 00195 printf("Key Accepted\r\n"); 00196 wait_ms(500); // was 5 00197 return TRUE; 00198 } 00199 00200 00201 // 00202 // t8_dump 00203 // 00204 // dumps the T8 BIN File 00205 // but doesn't displays anything. 00206 // 00207 // inputs: none 00208 // return: bool TRUE if there was a message, FALSE if no message. 00209 // 00210 00211 bool t8_dump() 00212 { 00213 uint32_t i = 0, k = 0; 00214 char T8TxMsg[8]; 00215 char T8RxMsg[8]; 00216 00217 timer.reset(); 00218 timer.start(); 00219 printf("Creating FLASH dump file...\r\n"); 00220 00221 // 00222 if (!GMLANprogrammingSetupProcess(T8REQID, T8RESPID)) 00223 return FALSE; 00224 // 00225 printf("Requesting Security Access\r\n"); 00226 if (!t8_authenticate(T8REQID, T8RESPID, 0x01)) { 00227 printf("Unable to get Security Access\r\n"); 00228 return FALSE; 00229 } 00230 printf("Security Access Granted\r\n"); 00231 // 00232 if(!GMLANprogrammingUtilityFileProcess(T8REQID, T8RESPID, T8BootloaderRead)) 00233 return FALSE; 00234 // 00235 // 00236 printf("Downloading FLASH BIN file...\r\n"); 00237 printf("Creating FLASH dump file...\r\n"); 00238 FILE *fp = fopen("/local/original.bin", "w"); // Open "original.bin" on the local file system for writing 00239 if (!fp) { 00240 perror ("The following error occured"); 00241 return TERM_ERR; 00242 } 00243 printf(" 0.00 %% complete.\r"); 00244 TesterPresent.start(); 00245 00246 // It is possible to save some time by only reading the program code and CAL data 00247 // This is just a rough calculation, and slight overestimate of the number of blocks of data needed to send the BIN file 00248 T8TxMsg[0] = 0x06; 00249 T8TxMsg[1] = 0x21; 00250 T8TxMsg[2] = 0x80; // Blocksize 00251 T8TxMsg[3] = 0x00; // This address (0x020140) points to the Header at the end of the BIN 00252 T8TxMsg[4] = 0x02; 00253 T8TxMsg[5] = 0x01; 00254 T8TxMsg[6] = 0x40; 00255 T8TxMsg[7] = 0xaa; 00256 if (!can_send_timeout (T8TSTRID, T8TxMsg, 7, T8MESSAGETIMEOUT)) { 00257 printf("Unable to download FLASH\r\n"); 00258 return FALSE; 00259 } 00260 if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) 00261 return FALSE; 00262 uint32_t EndAddress = (T8RxMsg[5] << 16) | (T8RxMsg[6] << 8) | T8RxMsg[7]; 00263 EndAddress += 0x200; // Add some bytes for the Footer itself and to account for division rounded down later 00264 char T8TxFlo[] = T8FLOCTL; 00265 can_send_timeout (T8TSTRID, T8TxFlo, 8, T8MESSAGETIMEOUT); 00266 for (i = 0; i < 0x12; i++) { 00267 if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) 00268 return FALSE; 00269 } 00270 printf("Reading your BIN file adjusted for footer = 0x%06X Bytes\r\n", EndAddress ); 00271 00272 for ( uint32_t StartAddress = 0x0; StartAddress < EndAddress; StartAddress +=0x80 ) { // 0x100000 00273 T8TxMsg[0] = 0x06; 00274 T8TxMsg[1] = 0x21; 00275 T8TxMsg[2] = 0x80; // Blocksize 00276 T8TxMsg[3] = (char) (StartAddress >> 24); 00277 T8TxMsg[4] = (char) (StartAddress >> 16); 00278 T8TxMsg[5] = (char) (StartAddress >> 8); 00279 T8TxMsg[6] = (char) (StartAddress); 00280 T8TxMsg[7] = 0xaa; 00281 #ifdef DEBUG 00282 printf("block %#.3f\r\n",timer.read()); 00283 #endif 00284 if (!can_send_timeout (T8TSTRID, T8TxMsg, 7, T8MESSAGETIMEOUT)) { 00285 printf("Unable to download FLASH\r\n"); 00286 return FALSE; 00287 } 00288 if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) 00289 return FALSE; 00290 #ifdef DEBUG 00291 printf("first %#.3f\r\n",timer.read()); 00292 #endif 00293 uint32_t txpnt = 0; 00294 for (k = 4; k < 8; k++ ) file_buffer[txpnt++] = T8RxMsg[k]; 00295 00296 uint8_t DataFrames = 0x12; 00297 char iFrameNumber = 0x21; 00298 char T8TxFlo[] = T8FLOCTL; 00299 can_send_timeout (T8TSTRID, T8TxFlo, 8, T8MESSAGETIMEOUT); 00300 #ifdef DEBUG 00301 printf("flowCtrl %#.3f\r\n",timer.read()); 00302 #endif 00303 for (i = 0; i < DataFrames; i++) { 00304 if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) 00305 return FALSE; 00306 #ifdef DEBUG 00307 printf("Consec %#.3f\r\n",timer.read()); 00308 #endif 00309 iFrameNumber++; 00310 for (k = 1; k < 8; k++ ) file_buffer[txpnt++] = T8RxMsg[k]; 00311 } 00312 fwrite((file_buffer), 1, 0x80, fp); 00313 if (ferror (fp)) { 00314 fclose (fp); 00315 printf ("Error writing to the FLASH BIN file.\r\n"); 00316 return TERM_ERR; 00317 } 00318 printf("%6.2f\r", (100.0*(float)StartAddress)/(float)(EndAddress) ); 00319 if (TesterPresent.read_ms() > 2000) { 00320 GMLANTesterPresent(T8REQID, T8RESPID); 00321 TesterPresent.reset(); 00322 } 00323 } 00324 00325 for (uint32_t i = 0; i < 0x80; i++) 00326 file_buffer[i] = 0xFF; 00327 while ( ftell(fp) < 0x100000 ) { 00328 // for ( uint32_t StartAddress = EndAddress; StartAddress < 0x100000; StartAddress +=0x80 ) { 00329 fwrite((file_buffer), 1, 0x80, fp); 00330 if (ferror (fp)) { 00331 fclose (fp); 00332 printf ("Error writing to the FLASH BIN file.\r\n"); 00333 return TERM_ERR; 00334 } 00335 } 00336 00337 printf("%6.2f\r\n", (float)100 ); 00338 timer.stop(); 00339 printf("SUCCESS! Getting the FLASH dump took %#.1f seconds.\r\n",timer.read()); 00340 fclose(fp); 00341 return TRUE; 00342 } 00343 00344 00345 bool t8_flash() 00346 { 00347 uint32_t i = 0, j = 0, k = 0; 00348 00349 timer.reset(); 00350 timer.start(); 00351 printf("FLASHing T8 BIN file...\r\n"); 00352 00353 // 00354 if (!GMLANprogrammingSetupProcess(T8REQID, T8RESPID)) 00355 return FALSE; 00356 // 00357 printf("Requesting Security Access\r\n"); 00358 if (!t8_authenticate(T8REQID, T8RESPID, 0x01)) { 00359 printf("Unable to get Security Access\r\n"); 00360 return FALSE; 00361 } 00362 printf("Security Access Granted\r\n"); 00363 // 00364 // All steps needed to transfer and start a bootloader ('Utility File' in GMLAN parlance) 00365 // const uint8_t BootLoader[] = T8BootloaderProg; 00366 // if(!GMLANprogrammingUtilityFileProcess(T8REQID, T8RESPID, BootLoader)) 00367 if(!GMLANprogrammingUtilityFileProcess(T8REQID, T8RESPID, T8BootLoaderWrite)) 00368 return FALSE; 00369 // 00370 uint32_t StartAddress = 0x020000; 00371 uint32_t txpnt = 0; 00372 char iFrameNumber = 0x21; 00373 char GMLANMsg[8]; 00374 char data2Send[0xE0]; 00375 // 00376 // fopen modified.bin here, check it is OK and work out how much data I need to send 00377 // need lots of fcloses though 00378 printf("Checking the FLASH BIN file...\r\n"); 00379 FILE *fp = fopen("/local/modified.bin", "r"); // Open "modified.bin" on the local file system for reading 00380 if (!fp) { 00381 printf("Error: I could not find the BIN file MODIFIED.BIN\r\n");; 00382 return TERM_ERR; 00383 } 00384 // obtain file size - it should match the size of the FLASH chips: 00385 fseek (fp , 0 , SEEK_END); 00386 uint32_t file_size = ftell (fp); 00387 rewind (fp); 00388 00389 // read the initial stack pointer value in the BIN file - it should match the value expected for the type of ECU 00390 uint32_t stack_long = 0; 00391 if (!fread(&stack_long,4,1,fp)) { 00392 fclose(fp); 00393 return TERM_ERR; 00394 } 00395 stack_long = (stack_long >> 24) | ((stack_long << 8) & 0x00FF0000) | ((stack_long >> 8) & 0x0000FF00) | (stack_long << 24); 00396 // 00397 if (file_size != T8FLASHSIZE || stack_long != T8POINTER) { 00398 fclose(fp); 00399 printf("The BIN file does not appear to be for a T8 ECU :-(\r\n"); 00400 printf("BIN file size: %#010x, FLASH chip size: %#010x, Pointer: %#010x.\r\n", file_size, T7FLASHSIZE, stack_long); 00401 return TERM_ERR; 00402 } 00403 // It is possible to save some time by only sending the program code and CAL data 00404 // This is just a rough calculation, and slight overestimate of the number of blocks of data needed to send the BIN file 00405 uint32_t blocks2Send; 00406 fseek(fp,0x020140,SEEK_SET); 00407 if (!fread(&blocks2Send,4,1,fp)) { 00408 fclose(fp); 00409 return TERM_ERR; 00410 } 00411 blocks2Send = (blocks2Send >> 24) | ((blocks2Send << 8) & 0x00FF0000) | ((blocks2Send >> 8) & 0x0000FF00) | (blocks2Send << 24); 00412 printf("Start address of BIN file's Footer area = 0x%06X\r\n", blocks2Send ); 00413 blocks2Send += 0x200; // Add some bytes for the Footer itself and to account for division rounded down later 00414 blocks2Send -= 0x020000; // Remove 0x020000 because we don't send the bootblock and adaptation blocks 00415 printf("Amount of data to send BIN file adjusted for footer = 0x%06X Bytes\r\n", blocks2Send ); 00416 blocks2Send /= 0xE0; 00417 printf("Number of Blocks of 0xE0 Bytes needed to send BIN file = 0x%04X\r\n", blocks2Send ); 00418 // Move BIN file pointer to start of data 00419 fseek (fp , 0x020000 , SEEK_SET); 00420 // Erase the FLASH 00421 printf("Waiting for FLASH to be Erased\r\n"); 00422 if (!GMLANRequestDownload(T8REQID, T8RESPID, GMLANRequestDownloadModeEncrypted)) { 00423 fclose(fp); 00424 printf("Unable to erase the FLASH chip!\r\n"); 00425 return FALSE; 00426 } 00427 // Now send the BIN file 00428 GMLANTesterPresent(T8REQID, T8RESPID); 00429 TesterPresent.start(); 00430 printf("Sending FLASH BIN file\r\n"); 00431 printf(" 0.00 %% complete.\r"); 00432 for (i=0; i<blocks2Send; i++) { 00433 // get a block of 0xE0 bytes in an array called data2Send 00434 if (!fread(data2Send,0xE0,1,fp)) { 00435 fclose(fp); 00436 printf("\r\nError reading the BIN file MODIFIED.BIN\r\n"); 00437 return FALSE; 00438 } 00439 // encrypt data2Send array by XORing with 6 different values in a ring (modulo function) 00440 char key[6] = { 0x39, 0x68, 0x77, 0x6D, 0x47, 0x39 }; 00441 for ( j = 0; j < 0xE0; j++ ) 00442 data2Send[j] ^= key[(((0xE0*i)+j) % 6)]; 00443 // Send the block of data 00444 if (!GMLANDataTransferFirstFrame(T8REQID, T8RESPID, 0xE6, GMLANDOWNLOAD, StartAddress)) { 00445 fclose(fp); 00446 printf("\r\nUnable to start BIN File Upload\r\n"); 00447 return FALSE; 00448 } 00449 // Send 0x20 messages of 0x07 bytes each (0x20 * 0x07 = 0xE0) 00450 txpnt = 0; 00451 iFrameNumber = 0x21; 00452 for (j=0; j < 0x20; j++) { 00453 GMLANMsg[0] = iFrameNumber; 00454 for (k=1; k<8; k++) 00455 GMLANMsg[k] = data2Send[txpnt++]; 00456 if (!can_send_timeout(T8REQID, GMLANMsg, 8, GMLANPTCT)) { 00457 fclose(fp); 00458 printf("\r\nUnable to send BIN File\r\n"); 00459 return FALSE; 00460 } 00461 ++iFrameNumber &= 0x2F; 00462 wait_us(1000); // can be as low as 250 for an ECU on its own, but need 1000 (1ms) to work in a car (use a longer delay to be ultrasafe??? ) 00463 } 00464 if (!GMLANDataTransferBlockAcknowledge(T8RESPID)) { 00465 fclose(fp); 00466 return FALSE; 00467 } 00468 if (TesterPresent.read_ms() > 2000) { 00469 GMLANTesterPresent(T8REQID, T8RESPID); 00470 TesterPresent.reset(); 00471 } 00472 StartAddress += 0xE0; 00473 printf("%6.2f\r", (100.0*(float)i)/(float)(blocks2Send) ); 00474 } 00475 // FLASHing complete 00476 printf("%6.2f\r\n", (float)100 ); 00477 // End programming session and return to normal mode 00478 if (!GMLANReturnToNormalMode(T8REQID, T8RESPID)) { 00479 fclose(fp); 00480 printf("UH-OH! T8 ECU did not Return To Normal Mode!!\r\n"); 00481 return FALSE; 00482 } 00483 timer.stop(); 00484 printf("SUCCESS! FLASHing the BIN file took %#.1f seconds.\r\n",timer.read()); 00485 fclose(fp); 00486 return TRUE; 00487 } 00488 00489 bool t8_recover() 00490 { 00491 uint32_t i = 0, j = 0, k = 0; 00492 00493 timer.reset(); 00494 timer.start(); 00495 printf("Recovering your T8 ECU ...\r\n"); 00496 // 00497 if (!GMLANprogrammingSetupProcess(T8USDTREQID, T8UUDTRESPID)) 00498 return FALSE; 00499 // 00500 printf("Requesting Security Access\r\n"); 00501 if (!t8_authenticate(T8USDTREQID, T8UUDTRESPID, 0x01)) { 00502 printf("Unable to get Security Access\r\n"); 00503 return FALSE; 00504 } 00505 printf("Security Access Granted\r\n"); 00506 // 00507 // const uint8_t BootLoader[] = T8BootloaderProg; 00508 // if(!GMLANprogrammingUtilityFileProcess(T8USDTREQID, T8UUDTRESPID, BootLoader)) 00509 if(!GMLANprogrammingUtilityFileProcess(T8USDTREQID, T8UUDTRESPID, T8BootLoaderWrite)) 00510 return FALSE; 00511 // 00512 00513 00514 // All steps needed to transfer and start a bootloader ('Utility File' in GMLAN parlance) 00515 uint32_t StartAddress = 0x020000; 00516 uint32_t txpnt = 0; 00517 char iFrameNumber = 0x21; 00518 char GMLANMsg[8]; 00519 char data2Send[0xE0]; 00520 // 00521 // fopen modified.bin here, check it is OK and work out how much data I need to send 00522 // need lots of fcloses though 00523 printf("Checking the FLASH BIN file...\r\n"); 00524 FILE *fp = fopen("/local/modified.bin", "r"); // Open "modified.bin" on the local file system for reading 00525 if (!fp) { 00526 printf("Error: I could not find the BIN file MODIFIED.BIN\r\n");; 00527 return TERM_ERR; 00528 } 00529 // obtain file size - it should match the size of the FLASH chips: 00530 fseek (fp , 0 , SEEK_END); 00531 uint32_t file_size = ftell (fp); 00532 rewind (fp); 00533 00534 // read the initial stack pointer value in the BIN file - it should match the value expected for the type of ECU 00535 uint32_t stack_long = 0; 00536 if (!fread(&stack_long,4,1,fp)) { 00537 fclose(fp); 00538 return TERM_ERR; 00539 } 00540 stack_long = (stack_long >> 24) | ((stack_long << 8) & 0x00FF0000) | ((stack_long >> 8) & 0x0000FF00) | (stack_long << 24); 00541 // 00542 if (file_size != T8FLASHSIZE || stack_long != T8POINTER) { 00543 fclose(fp); 00544 printf("The BIN file does not appear to be for a T8 ECU :-(\r\n"); 00545 printf("BIN file size: %#010x, FLASH chip size: %#010x, Pointer: %#010x.\r\n", file_size, T7FLASHSIZE, stack_long); 00546 return TERM_ERR; 00547 } 00548 // It is possible to save some time by only sending the program code and CAL data 00549 // This is just a rough calculation, and slight overestimate of the number of blocks of data needed to send the BIN file 00550 uint32_t blocks2Send; 00551 fseek(fp,0x020140,SEEK_SET); 00552 if (!fread(&blocks2Send,4,1,fp)) { 00553 fclose(fp); 00554 return TERM_ERR; 00555 } 00556 blocks2Send = (blocks2Send >> 24) | ((blocks2Send << 8) & 0x00FF0000) | ((blocks2Send >> 8) & 0x0000FF00) | (blocks2Send << 24); 00557 printf("Start address of BIN file's Footer area = 0x%06X\r\n", blocks2Send ); 00558 blocks2Send += 0x200; // Add some bytes for the Footer itself and to account for division rounded down later 00559 blocks2Send -= 0x020000; // Remove 0x020000 because we don't send the bootblock and adaptation blocks 00560 printf("Amount of data to send BIN file adjusted for footer = 0x%06X Bytes\r\n", blocks2Send ); 00561 blocks2Send /= 0xE0; 00562 printf("Number of Blocks of 0xE0 Bytes needed to send BIN file = 0x%04X\r\n", blocks2Send ); 00563 // Move BIN file pointer to start of data 00564 fseek (fp , 0x020000 , SEEK_SET); 00565 // Erase the FLASH 00566 printf("Waiting for FLASH to be Erased\r\n"); 00567 if (!GMLANRequestDownload(T8REQID, T8RESPID, GMLANRequestDownloadModeEncrypted)) { 00568 fclose(fp); 00569 printf("Unable to erase the FLASH chip!\r\n"); 00570 return FALSE; 00571 } 00572 // Now send the BIN file 00573 GMLANTesterPresent(T8REQID, T8RESPID); 00574 TesterPresent.start(); 00575 printf("Sending FLASH BIN file\r\n"); 00576 printf(" 0.00 %% complete.\r"); 00577 for (i=0; i<blocks2Send; i++) { 00578 // get a block of 0xE0 bytes in an array called data2Send 00579 if (!fread(data2Send,0xE0,1,fp)) { 00580 fclose(fp); 00581 printf("\r\nError reading the BIN file MODIFIED.BIN\r\n"); 00582 return FALSE; 00583 } 00584 // encrypt data2Send array by XORing with 6 different values in a ring (modulo function) 00585 char key[6] = { 0x39, 0x68, 0x77, 0x6D, 0x47, 0x39 }; 00586 for ( j = 0; j < 0xE0; j++ ) 00587 data2Send[j] ^= key[(((0xE0*i)+j) % 6)]; 00588 // Send the block of data 00589 if (!GMLANDataTransferFirstFrame(T8REQID, T8RESPID, 0xE6, GMLANDOWNLOAD, StartAddress)) { 00590 fclose(fp); 00591 printf("\r\nUnable to start BIN File Upload\r\n"); 00592 return FALSE; 00593 } 00594 // Send 0x20 messages of 0x07 bytes each (0x20 * 0x07 = 0xE0) 00595 txpnt = 0; 00596 iFrameNumber = 0x21; 00597 for (j=0; j < 0x20; j++) { 00598 GMLANMsg[0] = iFrameNumber; 00599 for (k=1; k<8; k++) 00600 GMLANMsg[k] = data2Send[txpnt++]; 00601 if (!can_send_timeout(T8REQID, GMLANMsg, 8, GMLANPTCT)) { 00602 fclose(fp); 00603 printf("\r\nUnable to send BIN File\r\n"); 00604 return FALSE; 00605 } 00606 ++iFrameNumber &= 0x2F; 00607 wait_us(1000); // was 250 use 1000 or wait_ms(1) to be ultrasafe 00608 } 00609 if (!GMLANDataTransferBlockAcknowledge(T8RESPID)) { 00610 fclose(fp); 00611 return FALSE; 00612 } 00613 if (TesterPresent.read_ms() > 2000) { 00614 GMLANTesterPresent(T8REQID, T8RESPID); 00615 TesterPresent.reset(); 00616 } 00617 StartAddress += 0xE0; 00618 printf("%6.2f\r", (100.0*(float)i)/(float)(blocks2Send) ); 00619 } 00620 // FLASHing complete 00621 printf("%6.2f\r\n", (float)100 ); 00622 // End programming session and return to normal mode 00623 if (!GMLANReturnToNormalMode(T8REQID, T8RESPID)) { 00624 fclose(fp); 00625 printf("UH-OH! T8 ECU did not Return To Normal Mode!!\r\n"); 00626 return FALSE; 00627 } 00628 timer.stop(); 00629 fclose(fp); 00630 printf("SUCCESS: Your T8 ECU has been recovered.\r\n"); 00631 return TRUE; 00632 }
Generated on Fri Jul 15 2022 00:43:05 by 1.7.2