// 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);
        }
示例#2
0
        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");
            }
        }