// look at.. DIInternalRetrieveConstParamPreparation // public int GetSizeInBits(BinaryReader reader, bool verbose = true) { // if (modeConfig & 0xF00) == 0x300, the value is a const param: DIIsConstParameter // VCFragment does the same thing.. with the same ITT exception // BitPosition /= 8 // look for the string "nImplType <= 6" uint modeE = (uint)ModeConfig & 0xF000; uint modeH = (uint)ModeConfig & 0xFF0; uint modeL = (uint)ModeConfig & 0xF; int resultBitSize = 0; if ((ModeConfig & 0xF00) == 0x300) // this check is made in DIDiagServiceRetrievePreparation { if (modeL > 6) { throw new Exception("nImplType <= 6; trying to map a data type that cannot exist"); } // const params : 0x320, 0x330, 0x340 if (modeH == 0x320) { // this behavior is confirmed resultBitSize = IntegerSizeMapping[modeL]; FieldType = InferredDataType.IntegerType; } else if (modeH == 0x330) { // this behavior is also okay resultBitSize = AlternativeBitWidth; // inPres + 20 FieldType = InferredDataType.BitDumpType; } else if (modeH == 0x340) { // from dasm, but unimplemented // DIInternalRetrieveConstParamPreparation FieldType = InferredDataType.UnhandledITType; throw new NotImplementedException("WARNING: valid but unhandled data size (ITT not parsed)"); // resultBitSize = 0; // inPres + 20 } } else { // if systemparam is -1.. load a default system type if (SystemParam == -1) { // apparently both 0x2000 and 0x8000 source from different pools, but use the same PRESENTATION structure if (modeE == 0x8000) { FieldType = InferredDataType.NativeInfoPoolType; byte[] poolBytes = ParentECU.ReadECUInfoPool(reader); using (BinaryReader poolReader = new BinaryReader(new MemoryStream(poolBytes))) { DiagPresentation pres = ParentECU.GlobalInternalPresentations[InfoPoolIndex]; /* * // depreciate use of ReadCBFWithOffset * poolReader.BaseStream.Seek(ParentECU.Info_EntrySize * InfoPoolIndex, SeekOrigin.Begin); * * int presentationStructOffset = poolReader.ReadInt32(); * int presentationStructSize = poolReader.ReadInt32(); * * reader.BaseStream.Seek(presentationStructOffset + ParentECU.Info_BlockOffset, SeekOrigin.Begin); * byte[] presentationStruct = reader.ReadBytes(presentationStructSize); * * int presentationMode = CaesarStructure.ReadCBFWithOffset(0x1C, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_Type * int presentationLength = CaesarStructure.ReadCBFWithOffset(0x1A, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_TypeLength * if (presentationLength > 0) * { * resultBitSize = presentationLength; * } * else * { * resultBitSize = CaesarStructure.ReadCBFWithOffset(0x21, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // ??? * } */ resultBitSize = pres.TypeLength_1A > 0 ? pres.TypeLength_1A : pres.TypeLengthBytesMaybe_21; // if value was specified in bytes, convert to bits if (pres.Type_1C == 0) { resultBitSize *= 8; } } } else if (modeE == 0x2000) { FieldType = InferredDataType.NativePresentationType; byte[] presPool = ParentECU.ReadECUPresentationsPool(reader); using (BinaryReader poolReader = new BinaryReader(new MemoryStream(presPool))) { DiagPresentation pres = ParentECU.GlobalPresentations[PresPoolIndex]; /* * // depreciate use of ReadCBFWithOffset * poolReader.BaseStream.Seek(ParentECU.Presentations_EntrySize * PresPoolIndex, SeekOrigin.Begin); * int presentationStructOffset = poolReader.ReadInt32(); * int presentationStructSize = poolReader.ReadInt32(); * * reader.BaseStream.Seek(presentationStructOffset + ParentECU.Presentations_BlockOffset, SeekOrigin.Begin); * byte[] presentationStruct = reader.ReadBytes(presentationStructSize); * * int presentationMode = CaesarStructure.ReadCBFWithOffset(0x1C, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_Type * int presentationLength = CaesarStructure.ReadCBFWithOffset(0x1A, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_TypeLength * * if (presentationLength > 0) * { * resultBitSize = presentationLength; * } * else * { * resultBitSize = CaesarStructure.ReadCBFWithOffset(0x21, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // ??? * } */ resultBitSize = pres.TypeLength_1A > 0 ? pres.TypeLength_1A : pres.TypeLengthBytesMaybe_21; // if value was specified in bytes, convert to bits if (pres.Type_1C == 0) { resultBitSize *= 8; } } } else { // should throw an exception? //Console.WriteLine($"WARNING: Unknown or unhandled type for for {qualifier}"); throw new Exception($"Attempted to load an unknown system type for {Qualifier}"); } } else { // not a const param, not a native param, this is a special param, parsed at DIInternalRetrieveSpecialPreparation // DIInternalRetrieveSpecialPreparation officially supports 0x410, 0x420 only if (modeH == 0x410) { int reducedSysParam = SystemParam - 0x10; if (reducedSysParam == 0) { // specifically requests for LOBYTE (& 0xFF) int resultByteSize = (ParentDiagService.RequestBytes.Length & 0xFF) - (BitPosition / 8); resultBitSize = resultByteSize * 8; FieldType = InferredDataType.ExtendedBitDumpType; // Console.WriteLine($"0x{modeH:X} debug for {qualifier} (L: {modeL}) (BitWidth: {AlternativeBitWidth} SP: {SystemParam}), sz: {resultBitSize} b ({resultBitSize/8} B)"); } else if (reducedSysParam == 17) { // open a diagservice based on inputRef name // this is experimental, haven't seen a cbf that uses this yet Console.WriteLine($"Parsing experimental 0x410 prep with sysparam 17 at {Qualifier}"); DiagService referencedDs = ParentECU.GlobalDiagServices.Find(x => x.Qualifier == ParentDiagService.InputRefNameMaybe); if (referencedDs != null) { bool referencedDsHasRequestData = referencedDs.RequestBytes.Length > 0; // supposed to check if requestMessage is valid too int internalType = referencedDs.DataClass_ServiceTypeShifted; if (((referencedDs.DataClass_ServiceTypeShifted & 0xC) > 0) && referencedDsHasRequestData) { if ((referencedDs.DataClass_ServiceTypeShifted & 4) > 0) { internalType = 0x10000000; } else { internalType = 0x20000000; } } if ((internalType & 0x10000) != 0) { // referenced type is a global variable resultBitSize = ParentDiagService.P_Count * 8; FieldType = InferredDataType.UnhandledSP17Type; } else { // use pres dump length FieldType = InferredDataType.UnhandledSP17Type; resultBitSize = ParentDiagService.RequestBytes.Length * 8; } } else { Console.WriteLine($"0x410 : sys param: 17 for qualifier {Qualifier} could not find referenced DiagService with index {ParentDiagService.InputRefNameMaybe}"); // throw new NotImplementedException } } else { throw new Exception($"Invalid system parameter for {Qualifier}"); } } else if (modeH == 0x420) { if (modeL > 6) { throw new Exception("nImplType <= 6; trying to map a data type that cannot exist"); } FieldType = InferredDataType.IntegerType; resultBitSize = IntegerSizeMapping[modeL]; } else if (modeH == 0x430) { // mode 0x430 is nonstandard and doesn't seem to exist in the function that I was disassembling /* * AlternativeBitWidth : 128 * SystemParam : 37 * * See 0x320 vs 0x330, seems to be similar */ resultBitSize = AlternativeBitWidth; // inPres + 20 FieldType = InferredDataType.BitDumpType; } else { FieldType = InferredDataType.UnhandledType; Console.WriteLine($"Unhandled type: {modeH} for {Qualifier}"); PrintDebug(); throw new Exception($"Attempted to load an unknown special param type for {Qualifier}"); //Console.WriteLine($"{qualifier} ({poolThing}/{ParentECU.ecuInfoPool_tableEntryCount})\n{BitUtility.BytesToHex(presentationStruct)}\n\n"); } } } /* * if (modeH == 0x430) * { * // guessed * if (verbose) * { * Console.WriteLine($"Unsupported 0x{modeH:X} behavior for {qualifier} (L: {modeL}) (BitWidth: {AlternativeBitWidth} ByteWidth: {SystemParam})"); * } * //PrintDebug(); * resultBitSize = AlternativeBitWidth; // alternate bit width is 128 which should be a nice 16 bytes * } * else if (modeH > 0x430) * { * // guessed from varcoding behavior * if ((PresPool == 0) && (AvailableBitWidth_PoolThing == 0)) * { * return 0; * } * else * { * //Console.WriteLine($"No idea how to handle Pres 0x750 from {qualifier} : {PresPool}"); * } * Console.WriteLine($"No idea how to handle 0x{modeH:X} from {qualifier} ({PresPool}, {AvailableBitWidth_PoolThing})"); * } */ return(resultBitSize); }
private void FindFragmentSize(BinaryReader reader) { ImplementationUpper = ImplementationType & 0xFF0; ImplementationLower = ImplementationType & 0xF; BitLength = 0; // fixup the bit length if (ImplementationLower > 6) { throw new NotImplementedException("The disassembly throws an exception when fragmentImplementationLower > 6, copying verbatim"); } if (ImplementationUpper > 0x420) { // Console.WriteLine($"fragment value upper: {fragmentImplementationUpper:X}"); ECU ecu = ParentDomain.ParentECU; byte[] infoPool = ecu.ReadECUInfoPool(reader); // int infoEntryWidth = ecu.ecuInfoPool_tableEntrySize; // Console.WriteLine($"Info entry width: {infoEntryWidth}"); // 8 using (BinaryReader poolReader = new BinaryReader(new MemoryStream(infoPool))) { DiagPresentation pres = ParentECU.GlobalInternalPresentations[InfoPoolIndex]; /* * // depreciate use of ReadCBFWithOffset * poolReader.BaseStream.Seek(ecu.Info_EntrySize * InfoPoolIndex, SeekOrigin.Begin); * int presentationStructOffset = poolReader.ReadInt32(); * int presentationStructSize = poolReader.ReadInt32(); * * //Console.WriteLine($"struct offset: 0x{presentationStructOffset:X} , size: {presentationStructSize} , meaningA 0x{fragmentMeaningA_Presentation:X} infoBase 0x{ecu.ecuInfoPool_fileoffset_7:X}\n"); * * reader.BaseStream.Seek(presentationStructOffset + ecu.Info_BlockOffset, SeekOrigin.Begin); * byte[] presentationStruct = reader.ReadBytes(presentationStructSize); * * int presentationMode = CaesarStructure.ReadCBFWithOffset(0x1C, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_Type * int presentationLength = CaesarStructure.ReadCBFWithOffset(0x1A, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_TypeLength * if (presentationLength > 0) * { * BitLength = presentationLength; * } * else * { * BitLength = CaesarStructure.ReadCBFWithOffset(0x21, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // ??? * } */ BitLength = pres.TypeLength_1A > 0 ? pres.TypeLength_1A : pres.TypeLengthBytesMaybe_21; // if value was specified in bytes, convert to bits if (pres.Type_1C == 0) { BitLength *= 8; } } } else { if (ImplementationUpper == 0x420) { BitLength = FragmentLengthTable[ImplementationLower]; } else if (ImplementationUpper == 0x320) { BitLength = FragmentLengthTable[ImplementationLower]; } else if (ImplementationUpper == 0x330) { BitLength = RawBitLength; } else if (ImplementationUpper == 0x340) { //throw new NotImplementedException("Requires implementation of ITT handle"); Console.WriteLine($"[!] Warning: Please avoid {ParentDomain.Qualifier} -> {Qualifier} as it could not be parsed (requires ITT)."); } else { throw new NotImplementedException($"No known fragment length format. Fragment upper: 0x{ImplementationUpper:X}"); } } if (BitLength == 0) { // not sure if there are dummy entries that might trip below exception // throw new NotImplementedException("Fragment length cannot be zero"); } }