private void FixCALs(CaesarContainer container) { int newLevel = 1; byte[] newFile = new byte[container.FileBytes.Length]; Buffer.BlockCopy(container.FileBytes, 0, newFile, 0, container.FileBytes.Length); Console.WriteLine($"Creating a new CBF with access level requirements set at {newLevel}"); List <DiagService> dsPendingFix = new List <DiagService>(); using (BinaryReader reader = new BinaryReader(new MemoryStream(container.FileBytes))) { foreach (ECU ecu in container.CaesarECUs) { foreach (DiagService ds in ecu.GlobalDiagServices) { if (ds.ClientAccessLevel > newLevel) { dsPendingFix.Add(ds); Console.WriteLine($"-> {ds.Qualifier} (Level {ds.ClientAccessLevel})"); long fileOffset = ds.GetCALInt16Offset(reader); if (fileOffset != -1) { newFile[fileOffset] = (byte)newLevel; newFile[fileOffset + 1] = (byte)(newLevel >> 8); } } } } uint checksum = CaesarReader.ComputeFileChecksum(newFile); byte[] checksumBytes = BitConverter.GetBytes(checksum); Array.ConstrainedCopy(checksumBytes, 0, newFile, newFile.Length - 4, checksumBytes.Length); } SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new CBF file"; sfd.Filter = "CBF files (*.cbf)|*.cbf|All files (*.*)|*.*"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(sfd.FileName, newFile); } }
private void exportSplicedFileToolStripMenuItem_Click(object sender, EventArgs e) { if (FlashContainer is null) { return; } if (!LoadMappedAddresses()) { return; } /* * we need to.. * - get the fileoffsets of the segment sizes * - get the fileoffsets of the segment addresses * - get the fileoffset of the flash start address * * - patch all the fileoffsets (size+address) with the new value */ int flashDataFileOffset = FlashContainer.CaesarFlashHeader.CffHeaderSize + FlashContainer.CaesarFlashHeader.LanguageBlockLength + 0x414; byte[] nonFlashData = FlashBytes.Take(flashDataFileOffset).ToArray(); using (BinaryReader reader = new BinaryReader(new MemoryStream(FlashBytes))) using (BinaryWriter nonFlashWriter = new BinaryWriter(new MemoryStream(nonFlashData))) using (BinaryWriter flashPayloadWriter = new BinaryWriter(new MemoryStream())) { int segmentCursor = 0; for (int i = 0; i < FlashContainer.CaesarFlashHeader.DataBlocks.Count; i++) { FlashDataBlock db = FlashContainer.CaesarFlashHeader.DataBlocks[i]; // read block offset fileoffset long blockOffsetFileOffset = db.GetFlashDataOffset(reader); // patch segment length on filebytes nonFlashWriter.BaseStream.Seek(blockOffsetFileOffset, SeekOrigin.Begin); nonFlashWriter.Write(segmentCursor); int localBlockLength = 0; for (int j = 0; j < db.FlashSegments.Count; j++) { FlashSegment seg = db.FlashSegments[j]; // check: which fields are mutable when splicing long offset = db.FlashData + // somewhat mutable : probably if there's more than 1 datablock, this value will be nonzero FlashContainer.CaesarFlashHeader.CffHeaderSize + // constant FlashContainer.CaesarFlashHeader.LanguageBlockLength + // constant segmentCursor + // mutable, see below 0x414; // constant byte[] segmentPayload = FlashData[i][j]; if (SplicePath[i][j].Length > 0) { segmentPayload = File.ReadAllBytes(SplicePath[i][j]); } int segmentMappedAddress = MappedAddresses[i][j]; // read segment length's offset long segmentLengthFileOffset = seg.GetSegmentLengthFileOffset(reader); // read segment's mapped address long segmentMappedAddressFileOffset = seg.GetMappedAddressFileOffset(reader); // patch segment length on filebytes nonFlashWriter.BaseStream.Seek(segmentLengthFileOffset, SeekOrigin.Begin); nonFlashWriter.Write(segmentPayload.Length); // patch segment's mapped address nonFlashWriter.BaseStream.Seek(segmentMappedAddressFileOffset, SeekOrigin.Begin); nonFlashWriter.Write(segmentMappedAddress); // increment segment offset for db.flashdata segmentCursor += segmentPayload.Length; localBlockLength += segmentPayload.Length; // append flash payload to temp buffer flashPayloadWriter.Write(segmentPayload); } // refresh the block size // read block size fileoffset long blockSizeFileOffset = db.GetBlockLengthOffset(reader); // patch block length nonFlashWriter.BaseStream.Seek(blockSizeFileOffset, SeekOrigin.Begin); nonFlashWriter.Write(localBlockLength); } // take the non-flash part of the bytes that we patched... // .. then merge it with the flash section that we rebuilt byte[] flashPayload = ((MemoryStream)flashPayloadWriter.BaseStream).ToArray(); byte[] nonFlashPrefix = ((MemoryStream)nonFlashWriter.BaseStream).ToArray(); byte[] result = new byte[flashPayload.Length + nonFlashPrefix.Length + 4]; Array.ConstrainedCopy(nonFlashPrefix, 0, result, 0, nonFlashPrefix.Length); Array.ConstrainedCopy(flashPayload, 0, result, nonFlashPrefix.Length, flashPayload.Length); // restore the checksum uint checksum = CaesarReader.ComputeFileChecksumLazy(result); result[result.Length - 4] = (byte)((checksum >> 0) & 0xFF); result[result.Length - 3] = (byte)((checksum >> 8) & 0xFF); result[result.Length - 2] = (byte)((checksum >> 16) & 0xFF); result[result.Length - 1] = (byte)((checksum >> 24) & 0xFF); // save the result SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new CFF file"; sfd.Filter = "CFF files (*.cff)|*.cff|All files (*.*)|*.*"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(sfd.FileName, result); } } }