// debug stub, not intended for direct execution private void SetSessionStub(ECUConnection Connection) { return; Console.WriteLine("Entering bootmode"); Connection.SendMessage(BitUtility.BytesFromHex("1002")); Console.WriteLine("Requesting for seed"); byte[] seed = Connection.SendMessage(BitUtility.BytesFromHex("2705")); SecurityAccess.SecurityAutoLogin.QueryUnlockEcu(seed.Skip(2).ToArray(), "X_4", 5, out byte[] key); Console.Write("Authenticating for bootmode.. "); List <byte> keyResponse = new List <byte>(new byte[] { 0x27, 0x06 }); keyResponse.AddRange(key); byte[] authResponse = Connection.SendMessage(keyResponse); Console.WriteLine(BitUtility.BytesToHex(authResponse)); // remind myself to write fingerprint Console.WriteLine($"2EF15A 00 0004 150213 00000000\r\n2EF15A 01 0004 150213 00000000\r\n3101FF00"); /* * int blockId = 1; // block0: CODE, block1: DATA * Console.WriteLine($"Writing fingerprint"); * // 2e f1 5a 00 00 04 15 02 16 00 00 00 00 * Connection.SendMessage(BitUtility.BytesFromHex($"2EF15A {blockId:X2} 0004 150213 00000000")); * * // 2EF15A 00 0004 150213 00000000 * // 2EF15A 01 0004 150213 00000000 * * Console.WriteLine($"Erasing block {blockId}"); * Connection.SendMessage(BitUtility.BytesFromHex("3101FF00")); * Console.WriteLine("Ready to accept flash data"); */ }
public static bool TryReadKW2C3PEChassisNumber(ECUConnection connection, out string chassisNumber) { chassisNumber = ""; byte[] response = connection.SendMessage(new byte[] { 0x1A, 0x90 }); // VIN current if (response.Length != 19) // 5A 90 + 17byte vin { return(false); } if (response[0] != 0x5A) { return(false); } chassisNumber = Encoding.ASCII.GetString(response.Skip(2).ToArray()); return(true); }
public static bool TryReadUDSChassisNumber(ECUConnection connection, out string chassisNumber) { chassisNumber = ""; byte[] response = connection.SendMessage(new byte[] { 0x22, 0xF1, 0xA0 }); if (response.Length != 20) // 62 F1 A0 + 17byte vin { return(false); } if (response[0] != 0x62) { return(false); } chassisNumber = Encoding.ASCII.GetString(response.Skip(3).ToArray()); return(true); }
private void txtJ2534Input_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { e.Handled = true; string inText = txtJ2534Input.Text; txtJ2534Input.Text = ""; if (BitUtility.CheckHexValid(inText)) { byte[] requestData = BitUtility.BytesFromHex(inText.Replace(" ", "").ToUpper()); byte[] response = Connection.SendMessage(requestData); Console.WriteLine($"ECU: {BitUtility.BytesToHex(response, true)}"); } else { Console.WriteLine($"Could not understand provided hex input: '{inText}'"); } } }
private void btnRead_Click(object sender, EventArgs e) { if (!FetchAndValidateInput(out uint sourceAddress, out uint destinationAddress, out uint bufferSize)) { return; } int strideWidth = decimal.ToInt32(nudIOWidth.Value); int addressWidth = decimal.ToInt32(nudAddressWidth.Value); int ioDigitCount = GetMemoryDigitCount(strideWidth); byte readCmd = decimal.ToByte(nudReadCmd.Value); byte positiveResponse = (byte)(readCmd + 0x40); byte alfid = GetAddressAndLengthFormatIdentifier( addressWidth, ioDigitCount ); byte[] memoryBuffer = new byte[bufferSize]; uint readCursor = sourceAddress; int bufferCursor = 0; bool hasBadReads = false; while (readCursor < destinationAddress) { uint remainder = destinationAddress - readCursor; int readSize = strideWidth; if (readSize > remainder) { readSize = (int)remainder; } List <byte> readCommand = CreateReadCommand(readCmd, alfid, readCursor, addressWidth, readSize); //byte[] response = //MessageBox.Show($"cmd: {BitUtility.BytesToHex(readCommand.ToArray(), true)}, width: {readSize}, remainder: {remainder}"); byte[] response = Connection.SendMessage(readCommand); if (response[0] == positiveResponse) { Array.ConstrainedCopy(response, 1, memoryBuffer, bufferCursor, readSize); } else { hasBadReads = true; } readCursor += (uint)readSize; bufferCursor += readSize; } OriginalBuffer = memoryBuffer; /* * HexboxBuffer = new byte[memoryBuffer.Length]; * Array.ConstrainedCopy(memoryBuffer, 0, HexboxBuffer, 0, memoryBuffer.Length); */ Hexbox.LineInfoOffset = sourceAddress; Hexbox.ByteProvider = new DynamicByteProvider(OriginalBuffer); if (hasBadReads) { MessageBox.Show("One or more read requests were rejected by the ECU, and the empty blocks were substituted with zeros. \r\n\r\n" + "Please check if the memory address is valid to the ECU, and if the ECU has been unlocked if required.\r\n\r\n" + "If the memory region has protected bytes, consider loading a smaller, more specific range with a I/O width of 1 to skip past the protected bytes.", "Warning: Invalid reads"); } }
private void StartDownload() { int sumBytesTransferred = 0; int sumBytes = 0; foreach (FlashBlock block in FlashBlocks) { sumBytes += block.Payload.Length; } GenericLoader loader = new GenericLoader(); loader.Text = "Reading from ECU"; loader.TopMost = true; loader.Show(); Application.DoEvents(); foreach (FlashBlock block in FlashBlocks) { byte[] startDownloadCmd = CreateDownloadRequest(block.Address, (uint)block.Payload.Length); byte[] response = connection.SendMessage(startDownloadCmd); // comment this, uncomment below if dryrun //byte[] response = BitUtility.BytesFromHex("74 20 00 03"); if (response.Length < 2) { MessageBox.Show($"Error: ECU sent an incorrectly sized response when initiating download for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } if (response[0] != startDownloadCmd[0] + 0x40) { MessageBox.Show($"Error: ECU sent a non-positive response ({BitUtility.BytesToHex(response)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // read alfid to know memory size description's width byte rxAlfid = response[1]; // we are only expecting a size value if ((rxAlfid & 0xF) > 0) { MessageBox.Show($"Error: Could not understand ECU ALFID response ({BitUtility.BytesToHex(response)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // find out how wide the memory size description is int memSize = rxAlfid >> 4; List <byte> memBytes = response.Skip(2).Take(memSize).ToList(); if (memBytes.Count != memSize) { MessageBox.Show($"Error: Could not understand ECU ALFID response (size mismatch) ({BitUtility.BytesToHex(response)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // parse the memory size desc as a BE integer uint messageSize = 0; for (int i = 0; i < memBytes.Count; i++) { messageSize <<= 8; messageSize |= memBytes[i]; } // debug: uncomment to cap msg size at 0x100, normally 0xF02, blocksize = 0xF00 // messageSize = 0x102; int blockSize = (int)messageSize - 2; int totalBlockCount = (int)(block.Payload.Length / blockSize); int remainderBytes = block.Payload.Length % blockSize; if (remainderBytes != 0) { totalBlockCount++; } // reconfigure connection for block transfer connection.TesterPresentTimer.Enabled = false; RaiseSTMin(); byte[] dataBlock = new byte[messageSize]; loader.SetProgressMax(totalBlockCount); for (int blockCounter = 0; blockCounter < totalBlockCount; blockCounter++) { dataBlock[0] = 0x36; dataBlock[1] = (byte)((blockCounter + 1) & 0xFF); // if this is the last block, and there is a remainder block, write only the remainder if (((blockCounter + 1) == totalBlockCount) && (remainderBytes != 0)) { Array.ConstrainedCopy(block.Payload, blockCounter * blockSize, dataBlock, 2, remainderBytes); dataBlock = dataBlock.Take(2 + remainderBytes).ToArray(); } else { Array.ConstrainedCopy(block.Payload, blockCounter * blockSize, dataBlock, 2, blockSize); } byte[] transferResponse = connection.SendMessage(dataBlock); // comment this, uncomment below if dryrun //byte[] transferResponse = new byte[] { 0x76, 0x00 }; if ((transferResponse.Length > 0) && (transferResponse[0] == 0x76)) { // no need to check block index, if the ecu accepts it, continue } else { MessageBox.Show($"Error: Data transfer rejected by ECU ({BitUtility.BytesToHex(transferResponse)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // update progress sumBytesTransferred += dataBlock.Length - 2; // loader.Text = $"Writing to ECU : 0x{sumBytesTransferred:X8} of 0x{sumBytes:X8}"; loader.Text = $"Writing to ECU : block {blockCounter} of 0x{totalBlockCount}"; loader.SetProgressValue(blockCounter); Application.DoEvents(); // fixme: show two progressbars, one for the block# and another for the individual block's % } byte[] exitTransferResponse = connection.SendMessage(new byte[] { 0x37 });// ------------------ patch if debugging if (!((exitTransferResponse.Length > 0) && (exitTransferResponse[0] == 0x77))) { MessageBox.Show($"Error: Exit transfer rejected by ECU ({BitUtility.BytesToHex(exitTransferResponse)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } } // restore prior connection status connection.TesterPresentTimer.Enabled = true; ResetSTMin(); loader.Close(); MessageBox.Show("Download completed"); }
private void btnRead_Click(object sender, EventArgs e) { if (!FetchAndValidateInput(out uint sourceAddress, out uint destinationAddress, out uint bufferSize)) { return; } int strideWidth = decimal.ToInt32(nudIOWidth.Value); int addressWidth = decimal.ToInt32(nudAddressWidth.Value); int ioDigitCount = GetMemoryDigitCount(strideWidth); byte readCmd = decimal.ToByte(nudReadCmd.Value); byte positiveResponse = (byte)(readCmd + 0x40); byte alfid = GetAddressAndLengthFormatIdentifier( addressWidth, ioDigitCount ); GenericLoader loader = new GenericLoader(); loader.Text = "Reading from ECU"; loader.SetProgressMax((int)(destinationAddress - sourceAddress)); loader.SetProgressValue(0); loader.TopMost = true; loader.Show(); Application.DoEvents(); byte[] memoryBuffer = new byte[bufferSize]; uint readCursor = sourceAddress; int bufferCursor = 0; bool hasBadReads = false; while (readCursor < destinationAddress) { loader.Text = $"Reading from ECU : 0x{readCursor:X8}"; loader.SetProgressValue((int)(readCursor - sourceAddress)); Application.DoEvents(); uint remainder = destinationAddress - readCursor; int readSize = strideWidth; if (readSize > remainder) { readSize = (int)remainder; } List <byte> readCommand = CreateReadCommand(readCmd, alfid, readCursor, addressWidth, readSize); byte[] response = Connection.SendMessage(readCommand); if (response[0] == positiveResponse) { Array.ConstrainedCopy(response, 1, memoryBuffer, bufferCursor, readSize); } else { hasBadReads = true; } readCursor += (uint)readSize; bufferCursor += readSize; } loader.Close(); Application.DoEvents(); OriginalBuffer = memoryBuffer; Hexbox.LineInfoOffset = sourceAddress; Hexbox.ByteProvider = new DynamicByteProvider(OriginalBuffer); if (hasBadReads) { MessageBox.Show("One or more read requests were rejected by the ECU, and the empty blocks were substituted with zeros. \r\n\r\n" + "Please check if the memory address is valid to the ECU, and if the ECU has been unlocked if required.\r\n\r\n" + "If the memory region has protected bytes, consider loading a smaller, more specific range with a I/O width of 1 to skip past the protected bytes.", "Warning: Invalid reads"); } }