Exemple #1
0
        public CFFHeader(BinaryReader reader)
        {
            reader.BaseStream.Seek(StubHeader.StubHeaderSize, SeekOrigin.Begin);
            CffHeaderSize = reader.ReadInt32();

            BaseAddress = reader.BaseStream.Position;

            ulong bitFlags = reader.ReadUInt16();

            CaesarVersion  = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            GpdVersion     = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            EcuCount       = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            EcuOffset      = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            CtfOffset      = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            StringPoolSize = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            DscOffset      = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            DscCount       = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            DscEntrySize   = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);

            CbfVersionString = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);
            GpdVersionString = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);
            XmlString        = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);


            long dataBufferOffsetAfterStrings = StringPoolSize + CffHeaderSize + 0x414;

            if (DscCount > 0)
            {
                DscBlockOffset = DscOffset + dataBufferOffsetAfterStrings;
                DscBlockSize   = DscEntrySize * DscCount;
                reader.BaseStream.Seek(DscBlockOffset, SeekOrigin.Begin);
                DSCPool = reader.ReadBytes(DscBlockSize);
            }
        }
Exemple #2
0
        public CTFHeader(BinaryReader reader, long baseAddress, int headerSize)
        {
            BaseAddress = baseAddress;
            reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin);
            ulong ctfBitflags = reader.ReadUInt16();

            CtfUnk1                = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader);
            Qualifier              = CaesarReader.ReadBitflagStringWithReader(ref ctfBitflags, reader, BaseAddress);
            CtfUnk3                = CaesarReader.ReadBitflagInt16(ref ctfBitflags, reader);
            CtfUnk4                = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader);
            CtfLanguageCount       = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader);
            CtfLanguageTableOffset = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader);
            CtfUnkString           = CaesarReader.ReadBitflagStringWithReader(ref ctfBitflags, reader, BaseAddress);

            long ctfLanguageTableOffsetRelativeToDefintions = CtfLanguageTableOffset + BaseAddress;

            // parse every language record
            CtfLanguages = new List <CTFLanguage>();
            for (int languageEntry = 0; languageEntry < CtfLanguageCount; languageEntry++)
            {
                long languageTableEntryOffset = ctfLanguageTableOffsetRelativeToDefintions + (languageEntry * 4);

                reader.BaseStream.Seek(languageTableEntryOffset, SeekOrigin.Begin);
                long        realLanguageEntryAddress = reader.ReadInt32() + ctfLanguageTableOffsetRelativeToDefintions;
                CTFLanguage language = new CTFLanguage(reader, realLanguageEntryAddress, headerSize);
                CtfLanguages.Add(language);
            }
        }
Exemple #3
0
        public ECUInterface(BinaryReader reader, long baseAddress)
        {
            BaseAddress = baseAddress;
            reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin);

            // we can now properly operate on the interface block
            ulong interfaceBitflags = reader.ReadUInt32();

            Qualifier          = CaesarReader.ReadBitflagStringWithReader(ref interfaceBitflags, reader, BaseAddress);
            Name_CTF           = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader, -1);
            Description_CTF    = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader, -1);
            VersionString      = CaesarReader.ReadBitflagStringWithReader(ref interfaceBitflags, reader, BaseAddress);
            Version            = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader);
            ComParamCount      = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader);
            ComParamListOffset = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader);
            Unk6 = CaesarReader.ReadBitflagInt16(ref interfaceBitflags, reader);


            long comparamFileOffset = ComParamListOffset + BaseAddress;

            // Console.WriteLine($"interface string table offset from definition block : {interfaceStringTableOffset_fromDefinitionBlock:X}");

            for (int interfaceStringIndex = 0; interfaceStringIndex < ComParamCount; interfaceStringIndex++)
            {
                // seek to string pointer
                reader.BaseStream.Seek(comparamFileOffset + (interfaceStringIndex * 4), SeekOrigin.Begin);
                // from pointer, seek to string
                long interfaceStringReadoutPtr = reader.ReadInt32() + comparamFileOffset;
                reader.BaseStream.Seek(interfaceStringReadoutPtr, SeekOrigin.Begin);
                string comParameter = CaesarReader.ReadStringFromBinaryReader(reader);
                comParameters.Add(comParameter);
            }
        }
        // void __cdecl DiagServiceReadPresentation(int *inBase, DECODED_PRESENTATION *outPresentation)
        // Looks like its actually a presentation
        // See DIDiagservice* functions
        public DiagPreparation(BinaryReader reader, CTFLanguage language, long baseAddress, int bitPosition, ushort modeConfig, ECU parentEcu, DiagService parentDiagService)
        {
            BitPosition       = bitPosition;
            ModeConfig        = modeConfig;
            Language          = language;
            BaseAddress       = baseAddress;
            ParentECU         = parentEcu;
            ParentDiagService = parentDiagService;

            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);
            ulong bitflags = reader.ReadUInt32();


            Qualifier           = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);
            Name_CTF            = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            Unk1                = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);
            Unk2                = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);
            AlternativeBitWidth = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            IITOffset           = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            InfoPoolIndex       = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            PresPoolIndex       = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Field1E             = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            SystemParam         = CaesarReader.ReadBitflagInt16(ref bitflags, reader, -1);
            DumpMode            = CaesarReader.ReadBitflagInt16(ref bitflags, reader);
            DumpSize            = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            if (DumpMode == 5)
            {
                // dump is actually a string, use
                // CaesarReader.ReadBitflagDumpWithReaderAsString
            }
            Dump = CaesarReader.ReadBitflagDumpWithReader(ref bitflags, reader, DumpSize, baseAddress);

            SizeInBits = GetSizeInBits(reader);
            // PrintDebug();
        }
Exemple #5
0
        public VCSubfragment(BinaryReader reader, VCFragment parentFragment, CTFLanguage language, long baseAddress)
        {
            // see DIOpenCBF_FragValHandle
            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);
            ulong bitflags = reader.ReadUInt16();

            Name_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            if (parentFragment.CCFHandle == 5)
            {
                // fragment should be parsed as PBSGetDumpAsStringFn, though internally we perceive this as the same
            }
            Dump                     = CaesarReader.ReadBitflagDumpWithReader(ref bitflags, reader, parentFragment.VarcodeDumpSize, baseAddress);
            Description_CTF          = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            QualifierUsuallyDisabled = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);
            Unk3                     = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            Unk4                     = CaesarReader.ReadBitflagInt16(ref bitflags, reader, -1);
            SupplementKey            = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);
            NameCTFResolved          = language.GetString(Description_CTF);

            //int subfragmentIdk2 = reader.ReadInt32();
            //int subfragmentName = reader.ReadInt32();
            //int subfragmentIdkIncremented = reader.ReadInt32();
            //Console.WriteLine($"Subfragment: {subfragmentIdk1:X} {subfragmentIdk2:X} {language.GetString(subfragmentName)} {subfragmentIdkIncremented:X}");
            //PrintDebug();
        }
Exemple #6
0
        // DIIAddCBFFile

        /*
         *  21 bits active
         *  f [6, 4,4,4,4, 4,4,4,4, 4,4,4,4, 4,4,4,4, 4,4,4,4, 1],
         */
        public FlashHeader(BinaryReader reader)
        {
            reader.BaseStream.Seek(StubHeader.StubHeaderSize, SeekOrigin.Begin);
            CffHeaderSize = reader.ReadInt32();

            BaseAddress = reader.BaseStream.Position;

            ulong bitFlags = reader.ReadUInt32();

            reader.ReadUInt16(); // unused

            FlashName             = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);
            FlashGenerationParams = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);
            Unk3                        = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            Unk4                        = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            FileAuthor                  = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);
            FileCreationTime            = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);
            AuthoringToolVersion        = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);
            FTRAFOVersionString         = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);
            FTRAFOVersionNumber         = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            CFFVersionString            = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);
            NumberOfFlashAreas          = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            FlashDescriptionTable       = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            DataBlockTableCountProbably = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            DataBlockRefTable           = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            CTFHeaderTable              = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            LanguageBlockLength         = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            NumberOfECURefs             = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            ECURefTable                 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            UnkTableCount               = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            UnkTableProbably            = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            Unk15                       = CaesarReader.ReadBitflagUInt8(ref bitFlags, reader);

            DescriptionHeaders = new List <FlashDescriptionHeader>();
            for (int flashDescIndex = 0; flashDescIndex < NumberOfFlashAreas; flashDescIndex++)
            {
                long flashTableEntryAddress = FlashDescriptionTable + BaseAddress + (flashDescIndex * 4);
                reader.BaseStream.Seek(flashTableEntryAddress, SeekOrigin.Begin);

                long flashEntryBaseAddress = FlashDescriptionTable + BaseAddress + reader.ReadInt32();
                FlashDescriptionHeader fdh = new FlashDescriptionHeader(reader, flashEntryBaseAddress);
                DescriptionHeaders.Add(fdh);
            }

            DataBlocks = new List <FlashDataBlock>();
            for (int dataBlockIndex = 0; dataBlockIndex < DataBlockTableCountProbably; dataBlockIndex++)
            {
                long datablockEntryAddress = DataBlockRefTable + BaseAddress + (dataBlockIndex * 4);
                reader.BaseStream.Seek(datablockEntryAddress, SeekOrigin.Begin);

                long           datablockBaseAddress = DataBlockRefTable + BaseAddress + reader.ReadInt32();
                FlashDataBlock fdb = new FlashDataBlock(reader, datablockBaseAddress);
                DataBlocks.Add(fdb);
            }
        }
Exemple #7
0
        public FlashDataBlock(BinaryReader reader, long baseAddress)
        {
            BaseAddress = baseAddress;
            reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin);

            ulong bitflags = reader.ReadUInt32();

            reader.ReadUInt16();

            Qualifier   = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress);
            LongName    = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Description = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            FlashData   = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            BlockLength     = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            DataFormat      = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            FileName        = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            NumberOfFilters = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            FiltersOffset    = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            NumberOfSegments = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            SegmentOffset    = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            EncryptionMode   = CaesarReader.ReadBitflagInt16(ref bitflags, reader);

            KeyLength         = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            KeyBuffer         = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            NumberOfOwnIdents = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            IdentsOffset      = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            NumberOfSecurities = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            SecuritiesOffset   = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            DataBlockType      = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress);
            UniqueObjectId     = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            FlashDataInfo_Idk  = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress);
            FlashDataInfoLang1 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            FlashDataInfoLang2 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            FlashDataInfo_Idk2 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);


            // CtfUnk1 = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader);
            FlashSegments = new List <FlashSegment>();
            for (int segmentIndex = 0; segmentIndex < NumberOfSegments; segmentIndex++)
            {
                long segmentEntryAddress = SegmentOffset + BaseAddress + (segmentIndex * 4);
                reader.BaseStream.Seek(segmentEntryAddress, SeekOrigin.Begin);

                long segmentBaseAddress = SegmentOffset + BaseAddress + reader.ReadInt32();

                FlashSegment segment = new FlashSegment(reader, segmentBaseAddress);
                FlashSegments.Add(segment);
            }
        }
        public CTFLanguage(BinaryReader reader, long baseAddress, int headerSize)
        {
            BaseAddress = baseAddress;
            reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin);
            ulong languageEntryBitflags = reader.ReadUInt16();

            Qualifier      = CaesarReader.ReadBitflagStringWithReader(ref languageEntryBitflags, reader, BaseAddress);
            LanguageIndex  = CaesarReader.ReadBitflagInt16(ref languageEntryBitflags, reader);
            StringPoolSize = CaesarReader.ReadBitflagInt32(ref languageEntryBitflags, reader);
            MaybeOffsetFromStringPoolBase = CaesarReader.ReadBitflagInt32(ref languageEntryBitflags, reader);
            StringCount = CaesarReader.ReadBitflagInt32(ref languageEntryBitflags, reader);

            LoadStrings(reader, headerSize, CaesarReader.DefaultEncoding);
        }
        public FlashSegment(BinaryReader reader, long baseAddress)
        {
            BaseAddress = baseAddress;
            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);

            ulong bitFlags = reader.ReadUInt16();

            // start reading

            FromAddress   = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            SegmentLength = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            Unk3          = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            SegmentName   = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress);

            Unk5 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            Unk6 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
            Unk7 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader);
        }
Exemple #10
0
        public CTFLanguage(BinaryReader reader, long baseAddress, int headerSize)
        {
            BaseAddress = baseAddress;
            reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin);

            ulong languageEntryBitflags = reader.ReadUInt16();

            Qualifier      = CaesarReader.ReadBitflagStringWithReader(ref languageEntryBitflags, reader, BaseAddress);
            LanguageIndex  = CaesarReader.ReadBitflagInt16(ref languageEntryBitflags, reader);
            StringPoolSize = CaesarReader.ReadBitflagInt32(ref languageEntryBitflags, reader);
            MaybeOffsetFromStringPoolBase = CaesarReader.ReadBitflagInt32(ref languageEntryBitflags, reader);
            StringCount = CaesarReader.ReadBitflagInt32(ref languageEntryBitflags, reader);

            // I have no idea if encoding data is included, using ascii as a default for now. Some german character data will be lost
            LoadStrings(reader, headerSize, CaesarReader.DefaultEncoding);

            //PrintDebug();
        }
        public ECUVariantPattern(BinaryReader reader, long baseAddress)
        {
            BaseAddress = baseAddress;
            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);
            ulong bitflags = reader.ReadUInt32();

            UnkBufferSize = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            UnkBuffer  = CaesarReader.ReadBitflagDumpWithReader(ref bitflags, reader, UnkBufferSize, baseAddress);
            Unk3       = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Unk4       = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Unk5       = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            VendorName = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);

            KwpVendorID = CaesarReader.ReadBitflagUInt16(ref bitflags, reader);
            Unk8        = CaesarReader.ReadBitflagInt16(ref bitflags, reader);
            Unk9        = CaesarReader.ReadBitflagInt16(ref bitflags, reader);
            Unk10       = CaesarReader.ReadBitflagInt16(ref bitflags, reader);

            Unk11 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);
            Unk12 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);
            Unk13 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);
            Unk14 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);
            Unk15 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);

            Unk16 = CaesarReader.ReadBitflagDumpWithReader(ref bitflags, reader, 5, baseAddress); // read with a constant size

            Unk17 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);
            Unk18 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);
            Unk19 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);
            Unk20 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader);

            Unk21 = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);

            Unk22       = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Unk23       = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            UdsVendorID = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            PatternType = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            VariantID = UdsVendorID == 0 ? KwpVendorID : UdsVendorID;
            // type 3 contains a vendor name
        }
        public FlashDescriptionHeader(BinaryReader reader, long baseAddress)
        {
            BaseAddress = baseAddress;

            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);
            ulong flashBitFlags = reader.ReadUInt32();

            Qualifier                 = CaesarReader.ReadBitflagStringWithReader(ref flashBitFlags, reader, baseAddress);
            Description               = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            FlashAreaName             = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            FlashTableStructureCount  = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            FlashTableStructureOffset = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            NumberOfUploads           = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            UploadTableRefTable       = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            NumberOfIdentServices     = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            IdentServicesOffset       = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            UniqueObjectID            = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            unkb = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
            unkc = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader);
        }
Exemple #13
0
        public long GetFlashDataOffset(BinaryReader reader)
        {
            reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin);

            ulong bitflags = reader.ReadUInt32();

            reader.ReadUInt16();

            CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress); // Qualifier
            CaesarReader.ReadBitflagInt32(ref bitflags, reader);                         // LongName
            CaesarReader.ReadBitflagInt32(ref bitflags, reader);                         // Description

            if (CaesarReader.CheckAndAdvanceBitflag(ref bitflags))
            {
                return(reader.BaseStream.Position);
            }
            else
            {
                return(-1);
            }
        }
Exemple #14
0
        public long GetCALInt16Offset(BinaryReader reader)
        {
            reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin);

            ulong bitflags        = reader.ReadUInt32();
            ulong bitflagExtended = reader.ReadUInt32();

            CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress); // Qualifier
            CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);                     // Name
            CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);                     // Description
            CaesarReader.ReadBitflagUInt16(ref bitflags, reader);                        // Type
            CaesarReader.ReadBitflagUInt16(ref bitflags, reader);                        // IsExecutable
            if (CaesarReader.CheckAndAdvanceBitflag(ref bitflags))
            {
                return(reader.BaseStream.Position);
            }
            else
            {
                return(-1);
            }
        }
Exemple #15
0
        public DTC(BinaryReader reader, CTFLanguage language, long baseAddress, int poolIndex, ECU parentEcu)
        {
            ParentECU   = parentEcu;
            PoolIndex   = poolIndex;
            BaseAddress = baseAddress;
            Language    = language;
            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);

            ulong bitflags = reader.ReadUInt16();

            Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);

            Description_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            Reference_CTF   = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
#if DEBUG
            if (bitflags > 0)
            {
                Console.WriteLine($"DTC {Qualifier} has additional unparsed fields : 0x{bitflags:X}");
            }
#endif
        }
Exemple #16
0
        public ECUInterfaceSubtype(BinaryReader reader, long baseAddress, int index)
        {
            Index       = index;
            BaseAddress = baseAddress;
            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);
            // we can now properly operate on the interface block
            ulong ctBitflags = reader.ReadUInt32();

            Qualifier       = CaesarReader.ReadBitflagStringWithReader(ref ctBitflags, reader, BaseAddress);
            Name_CTF        = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader, -1);
            Description_CTF = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader, -1);

            Unk3 = CaesarReader.ReadBitflagInt16(ref ctBitflags, reader);
            Unk4 = CaesarReader.ReadBitflagInt16(ref ctBitflags, reader);

            Unk5 = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader);
            Unk6 = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader);
            Unk7 = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader);

            Unk8  = CaesarReader.ReadBitflagUInt8(ref ctBitflags, reader);
            Unk9  = CaesarReader.ReadBitflagUInt8(ref ctBitflags, reader);
            Unk10 = CaesarReader.ReadBitflagInt8(ref ctBitflags, reader); // might be signed
        }
        // 0x05 [6,   4,4,4,4,  4,4,4,4,  4,4,4,4,  2,2,2,4,      4,4,4,4,   4,4,4,4,   4,4,1,1,  1,1,1,4,     4,4,2,4,   4,4],

        public DiagPresentation(BinaryReader reader, long baseAddress, int presentationsIndex, CTFLanguage language)
        {
            BaseAddress       = baseAddress;
            PresentationIndex = presentationsIndex;
            Language          = language;

            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);
            ulong bitflags = reader.ReadUInt32();

            ulong extendedBitflags = reader.ReadUInt16(); // skip 2 bytes

            Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress);

            Description_CTF  = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            ScaleTableOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            ScaleCountMaybe  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            Unk5 = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            Unk6 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Unk7 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Unk8 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            Unk9 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            UnkA = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            UnkB = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            UnkC = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            UnkD = CaesarReader.ReadBitflagInt16(ref bitflags, reader);
            UnkE = CaesarReader.ReadBitflagInt16(ref bitflags, reader);
            UnkF = CaesarReader.ReadBitflagInt16(ref bitflags, reader);
            DisplayedUnit_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);

            Unk11        = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Unk12        = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            EnumMaxValue = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Unk14        = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);

            Unk15            = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Description2_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            Unk17            = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            Unk18            = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            Unk19         = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            TypeLength_1A = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            Unk1b         = CaesarReader.ReadBitflagInt8(ref bitflags, reader, -1);
            Type_1C       = CaesarReader.ReadBitflagInt8(ref bitflags, reader, -1);

            Unk1d       = CaesarReader.ReadBitflagInt8(ref bitflags, reader);
            EnumType_1E = CaesarReader.ReadBitflagInt8(ref bitflags, reader);
            Unk1F       = CaesarReader.ReadBitflagInt8(ref bitflags, reader);
            Unk20       = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            bitflags = extendedBitflags;

            TypeLengthBytesMaybe_21 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Unk22 = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            Unk23 = CaesarReader.ReadBitflagInt16(ref bitflags, reader);
            Unk24 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            Unk25 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Unk26 = CaesarReader.ReadBitflagInt32(ref bitflags, reader);


            long scaleTableBase = BaseAddress + ScaleTableOffset;

            Scales = new List <Scale>();
            for (int i = 0; i < ScaleCountMaybe; i++)
            {
                reader.BaseStream.Seek(scaleTableBase + (i * 4), SeekOrigin.Begin);
                int entryRelativeOffset = reader.ReadInt32();

                Scale scale = new Scale(reader, scaleTableBase + entryRelativeOffset, language);
                Scales.Add(scale);
            }
        }
Exemple #18
0
        public ECUVariant(BinaryReader reader, ECU parentEcu, CTFLanguage language, long baseAddress, int blockSize)
        {
            // int __usercall DIIFindVariantByECUID@<eax>(ECU_VARIANT *a1@<ebx>, _DWORD *a2, int a3, __int16 a4, int a5)

            BaseAddress = baseAddress;
            ParentECU   = parentEcu;
            Language    = language;
            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);
            byte[] variantBytes = reader.ReadBytes(blockSize);

            using (BinaryReader variantReader = new BinaryReader(new MemoryStream(variantBytes)))
            {
                ulong bitFlags = variantReader.ReadUInt32();
                int   skip     = variantReader.ReadInt32();

                Qualifier       = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader);
                Name_CTF        = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader, -1);
                Description_CTF = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader, -1);
                UnkStr1         = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader);
                UnkStr2         = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader);

                Unk1 = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);                   // 1
                MatchingPatternCount   = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 2
                MatchingPatternOffset  = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 3
                SubsectionB_Count      = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 4
                SubsectionB_Offset     = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 5
                ComParamsCount         = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 6
                ComParamsOffset        = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 7
                DiagServiceCode_Count  = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 8
                DiagServiceCode_Offset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 9
                DiagServicesCount      = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 10
                DiagServicesOffset     = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 11
                DTC_Count             = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);  // 12
                DTC_Offset            = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);  // 13
                EnvironmentCtx_Count  = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);  // 14
                EnvironmentCtx_Offset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);  // 15
                Xref_Count            = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);  // 16
                Xref_Offset           = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);  // 17

                VCDomainsCount  = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);        // 18
                VCDomainsOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);        // 19

                NegativeResponseName = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader);
                UnkByte = CaesarReader.ReadBitflagInt8(ref bitFlags, variantReader);  // 20 byte

                // vcdomain
                VCDomainPoolOffsets = new List <int>();
                variantReader.BaseStream.Seek(VCDomainsOffset, SeekOrigin.Begin);
                for (int variantCodingIndex = 0; variantCodingIndex < VCDomainsCount; variantCodingIndex++)
                {
                    VCDomainPoolOffsets.Add(variantReader.ReadInt32());
                }
                // diagnostic services
                DiagServicesPoolOffsets = new List <int>();
                variantReader.BaseStream.Seek(DiagServicesOffset, SeekOrigin.Begin);
                for (int diagIndex = 0; diagIndex < DiagServicesCount; diagIndex++)
                {
                    DiagServicesPoolOffsets.Add(variantReader.ReadInt32());
                }
                // DTCs
                //DTCsPoolOffsets = new List<int>();
                DTCsPoolOffsetsWithBounds = new List <Tuple <int, int, int> >();
                variantReader.BaseStream.Seek(DTC_Offset, SeekOrigin.Begin);
                for (int dtcIndex = 0; dtcIndex < DTC_Count; dtcIndex++)
                {
                    int actualIndex = variantReader.ReadInt32();
                    int xrefStart   = variantReader.ReadInt32();
                    int xrefCount   = variantReader.ReadInt32(); // stitch with table H : int __cdecl DIECUGetNumberOfEnvForAllErrors(DI_ECUINFO *ecuh, int a2, int a3)
                    //DTCsPoolOffsets.Add(actualIndex); // todo: depreciate this
                    DTCsPoolOffsetsWithBounds.Add(new Tuple <int, int, int>(actualIndex, xrefStart, xrefCount));
                }
                // EnvCtxs
                EnvironmentContextsPoolOffsets = new List <int>();
                variantReader.BaseStream.Seek(EnvironmentCtx_Offset, SeekOrigin.Begin);
                for (int envIndex = 0; envIndex < EnvironmentCtx_Count; envIndex++)
                {
                    EnvironmentContextsPoolOffsets.Add(variantReader.ReadInt32());
                }
            }

            CreateVCDomains(parentEcu, language);
            CreateDiagServices(parentEcu, language);
            CreateVariantPatterns(reader);
            CreateComParameters(reader, parentEcu);
            CreateDTCs(parentEcu, language);
            CreateEnvironmentContexts(parentEcu, language);
            CreateXrefs(reader, parentEcu, language);
            //PrintDebug();
        }
Exemple #19
0
        public ECU(BinaryReader reader, CTFLanguage language, CFFHeader header, long baseAddress, CaesarContainer parentContainer)
        {
            ParentContainer = parentContainer;
            BaseAddress     = baseAddress;
            // Read 32+16 bits
            ulong ecuBitFlags = reader.ReadUInt32();
            // after exhausting the 32 bits, load these additional 16 bits
            ulong ecuBitFlagsExtended = reader.ReadUInt16();

            // Console.WriteLine($"ECU bitflags: {ecuBitFlags:X}");

            // advancing forward to ecuBase + 10
            int ecuHdrIdk1 = reader.ReadInt32(); // no idea

            // Console.WriteLine($"Skipping: {ecuHdrIdk1:X8}");

            Qualifier            = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress);
            EcuName_CTF          = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader, -1);
            EcuDescription_CTF   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader, -1);
            EcuXmlVersion        = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress);
            InterfaceBlockCount  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            InterfaceTableOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            SubinterfacesCount   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            SubinterfacesOffset  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            EcuClassName         = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress);
            UnkStr7 = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress);
            UnkStr8 = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress);

            int dataBufferOffsetRelativeToFile = header.StringPoolSize + StubHeader.StubHeaderSize + header.CffHeaderSize + 4;

            // Console.WriteLine($"{nameof(dataBufferOffsetRelativeToFile)} : 0x{dataBufferOffsetRelativeToFile:X}");

            IgnitionRequired   = CaesarReader.ReadBitflagInt16(ref ecuBitFlags, reader);
            Unk2               = CaesarReader.ReadBitflagInt16(ref ecuBitFlags, reader);
            UnkBlockCount      = CaesarReader.ReadBitflagInt16(ref ecuBitFlags, reader);
            UnkBlockOffset     = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            EcuSgmlSource      = CaesarReader.ReadBitflagInt16(ref ecuBitFlags, reader);
            Unk6RelativeOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            EcuVariant_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile;
            EcuVariant_EntryCount  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            EcuVariant_EntrySize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            EcuVariant_BlockSize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            DiagJob_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile;
            DiagJob_EntryCount  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            DiagJob_EntrySize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            DiagJob_BlockSize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            Dtc_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile;
            Dtc_EntryCount  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            Dtc_EntrySize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            Dtc_BlockSize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            Env_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile;
            Env_EntryCount  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            Env_EntrySize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            // bitflags will be exhausted at this point, load the extended bitflags
            ecuBitFlags = ecuBitFlagsExtended;

            Env_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            VcDomain_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile;
            VcDomain_EntryCount  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            VcDomain_EntrySize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            VcDomain_BlockSize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            Presentations_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile;
            Presentations_EntryCount  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            Presentations_EntrySize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            Presentations_BlockSize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            Info_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile;
            Info_EntryCount  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            Info_EntrySize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            Info_BlockSize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            Unk_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile;
            Unk_EntryCount  = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            Unk_EntrySize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);
            Unk_BlockSize   = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            Unk39 = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader);

            // read ecu's supported interfaces and subtypes

            // try to read interface block from the interface buffer table
            // this address is relative to the definitions block
            long interfaceTableAddress = BaseAddress + InterfaceTableOffset;

            // Console.WriteLine($"Interface table address: {interfaceTableAddress:X}, given offset: {interfaceTableOffset:X}");

            ECUInterfaces = new List <ECUInterface>();
            for (int interfaceBufferIndex = 0; interfaceBufferIndex < InterfaceBlockCount; interfaceBufferIndex++)
            {
                // Console.WriteLine($"Parsing interface {interfaceBufferIndex + 1}/{interfaceBlockCount}");

                // find our interface block offset
                reader.BaseStream.Seek(interfaceTableAddress + (interfaceBufferIndex * 4), SeekOrigin.Begin);
                // seek to the actual block (ambiguity: is this relative to the interface table or the current array?)
                int interfaceBlockOffset = reader.ReadInt32();

                long ecuInterfaceBaseAddress = interfaceTableAddress + interfaceBlockOffset;

                ECUInterface ecuInterface = new ECUInterface(reader, ecuInterfaceBaseAddress);
                ECUInterfaces.Add(ecuInterface);
            }

            // try to read interface subtype block from the interface buffer table
            // this address is relative to the definitions block
            ECUInterfaceSubtypes = new List <ECUInterfaceSubtype>();
            long ctTableAddress = BaseAddress + SubinterfacesOffset;

            // Console.WriteLine($"Interface subtype table address: {ctTableAddress:X}, given offset: {ecuChildTypesOffset:X}");
            for (int ctBufferIndex = 0; ctBufferIndex < SubinterfacesCount; ctBufferIndex++)
            {
                // Console.WriteLine($"Parsing interface subtype {ctBufferIndex + 1}/{ecuNumberOfEcuChildTypes}");
                // find our ct block offset
                reader.BaseStream.Seek(ctTableAddress + (ctBufferIndex * 4), SeekOrigin.Begin);
                // seek to the actual block (ambiguity: is this relative to the ct table or the current array?)
                int  actualBlockOffset = reader.ReadInt32();
                long ctBaseAddress     = ctTableAddress + actualBlockOffset;

                ECUInterfaceSubtype ecuInterfaceSubtype = new ECUInterfaceSubtype(reader, ctBaseAddress, ctBufferIndex);
                ECUInterfaceSubtypes.Add(ecuInterfaceSubtype);
            }

            CreateDiagServices(reader, language);
            CreateEcuVariants(reader, language);
            CreatePresentations(reader, language);
            ECUDescriptionTranslated = language.GetString(EcuDescription_CTF);
        }
Exemple #20
0
        public VCDomain(BinaryReader reader, ECU parentEcu, CTFLanguage language, int variantCodingDomainEntry)
        {
            ParentECU = parentEcu;

            byte[] variantCodingPool = parentEcu.ReadVarcodingPool(reader);
            using (BinaryReader poolReader = new BinaryReader(new MemoryStream(variantCodingPool)))
            {
                poolReader.BaseStream.Seek(variantCodingDomainEntry * parentEcu.VcDomain_EntrySize, SeekOrigin.Begin);
                int  entryOffset     = poolReader.ReadInt32();
                int  entrySize       = poolReader.ReadInt32();
                uint entryCrc        = poolReader.ReadUInt32();
                long vcdBlockAddress = entryOffset + parentEcu.VcDomain_BlockOffset;

                // Console.WriteLine($"VCD Entry @ 0x{entryOffset:X} with size 0x{entrySize:X} and CRC {entryCrc:X8}, abs addr {vcdBlockAddress:X8}");

                long baseAddress = vcdBlockAddress;
                reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);
                ulong bitflags = reader.ReadUInt16();

                Qualifier           = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);
                Name_CTF            = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
                Description_CTF     = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
                ReadServiceName     = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);
                WriteServiceName    = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);
                FragmentCount       = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
                FragmentTableOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader) + (int)baseAddress; // demoting long (warning)
                DumpSize            = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
                DefaultStringCount  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
                StringTableOffset   = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
                Unk1 = CaesarReader.ReadBitflagInt16(ref bitflags, reader);

                // PrintDebug();

                VCFragments = new List <VCFragment>();
                for (int fragmentIndex = 0; fragmentIndex < FragmentCount; fragmentIndex++)
                {
                    VCFragment fragment = new VCFragment(reader, this, FragmentTableOffset, fragmentIndex, language);
                    VCFragments.Add(fragment);
                }
                // ValidateFragmentCoverage();

                if (DefaultStringCount > 0)
                {
                    DefaultData = new List <Tuple <string, byte[]> >();
                    long stringTableBaseAddress = StringTableOffset + baseAddress;
                    // this could almost be a class of its own but there isn't a distinct name to it
                    for (int stringTableIndex = 0; stringTableIndex < DefaultStringCount; stringTableIndex++)
                    {
                        reader.BaseStream.Seek(stringTableBaseAddress + (4 * stringTableIndex), SeekOrigin.Begin);
                        int  offset            = reader.ReadInt32();
                        long stringBaseAddress = stringTableBaseAddress + offset;
                        reader.BaseStream.Seek(stringBaseAddress, SeekOrigin.Begin);
                        ulong  strBitflags         = reader.ReadUInt16();
                        int    nameUsuallyAbsent_T = CaesarReader.ReadBitflagInt32(ref strBitflags, reader, -1);
                        int    offsetToBlob        = CaesarReader.ReadBitflagInt32(ref strBitflags, reader);
                        int    blobSize            = CaesarReader.ReadBitflagInt32(ref strBitflags, reader);
                        int    valueType_T         = CaesarReader.ReadBitflagInt32(ref strBitflags, reader, -1);
                        string noIdeaStr1          = CaesarReader.ReadBitflagStringWithReader(ref strBitflags, reader, stringBaseAddress);
                        int    noIdea2_T           = CaesarReader.ReadBitflagInt32(ref strBitflags, reader, -1);
                        int    noIdea3             = CaesarReader.ReadBitflagInt16(ref strBitflags, reader);
                        string noIdeaStr2          = CaesarReader.ReadBitflagStringWithReader(ref strBitflags, reader, stringBaseAddress);
                        byte[] blob = new byte[] { };
                        if (blobSize > 0)
                        {
                            long blobFileAddress = stringBaseAddress + offsetToBlob;
                            reader.BaseStream.Seek(blobFileAddress, SeekOrigin.Begin);
                            blob = reader.ReadBytes(blobSize);
                            // memcpy
                        }

                        string valueType = language.GetString(valueType_T);
                        DefaultData.Add(new Tuple <string, byte[]>(valueType, blob));
                        //Console.WriteLine($"Blob: {BitUtility.BytesToHex(blob)} @ {valueType}");
                        //Console.WriteLine($"String base address: 0x{stringBaseAddress:X}");
                    }
                }
            }
        }
Exemple #21
0
        public ECUVariant(BinaryReader reader, ECU parentEcu, CTFLanguage language, long baseAddress, int blockSize)
        {
            // int __usercall DIIFindVariantByECUID@<eax>(ECU_VARIANT *a1@<ebx>, _DWORD *a2, int a3, __int16 a4, int a5)

            BaseAddress = baseAddress;
            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);
            byte[] variantBytes = reader.ReadBytes(blockSize);

            using (BinaryReader variantReader = new BinaryReader(new MemoryStream(variantBytes)))
            {
                ulong bitFlags = variantReader.ReadUInt32();
                int   skip     = variantReader.ReadInt32();

                Qualifier       = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader);
                Name_CTF        = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader, -1);
                Description_CTF = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader, -1);
                UnkStr1         = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader);
                UnkStr2         = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader);

                Unk1 = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);                  // 1
                MatchingPatternCount  = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 2
                MatchingPatternOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 3
                SubsectionB_Count     = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 4
                SubsectionB_Offset    = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 5
                ComParamsCount        = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 6
                ComParamsOffset       = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 7
                SubsectionD_Count     = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 8
                SubsectionD_Offset    = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 9
                DiagServicesCount     = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 10
                DiagServicesOffset    = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 11
                SubsectionF_Count     = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 12
                SubsectionF_Offset    = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 13
                SubsectionG_Count     = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 14
                SubsectionG_Offset    = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 15
                SubsectionH_Count     = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 16
                SubsectionH_Offset    = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 17

                VCDomainsCount  = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);       // 18
                VCDomainsOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader);       // 19

                NegativeResponseName = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader);
                UnkByte = CaesarReader.ReadBitflagInt8(ref bitFlags, variantReader);  // 20 byte

                VCDomainPoolOffsets = new List <int>();
                variantReader.BaseStream.Seek(VCDomainsOffset, SeekOrigin.Begin);
                for (int variantCodingIndex = 0; variantCodingIndex < VCDomainsCount; variantCodingIndex++)
                {
                    VCDomainPoolOffsets.Add(variantReader.ReadInt32());
                }

                DiagServicesPoolOffsets = new List <int>();
                variantReader.BaseStream.Seek(DiagServicesOffset, SeekOrigin.Begin);
                for (int diagIndex = 0; diagIndex < DiagServicesCount; diagIndex++)
                {
                    DiagServicesPoolOffsets.Add(variantReader.ReadInt32());
                }
            }

            CreateVCDomains(reader, parentEcu, language);
            CreateDiagServices(reader, parentEcu, language);
            CreateVariantPatterns(reader);
            CreateComParameters(reader, parentEcu);
        }
Exemple #22
0
        public DiagService(BinaryReader reader, CTFLanguage language, long baseAddress, int poolIndex, ECU parentEcu)
        {
            ParentECU   = parentEcu;
            PoolIndex   = poolIndex;
            BaseAddress = baseAddress;
            reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin);

            ulong bitflags        = reader.ReadUInt32();
            ulong bitflagExtended = reader.ReadUInt32();

            Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);

            Name_CTF        = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);
            Description_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1);

            DataClass_ServiceType        = CaesarReader.ReadBitflagUInt16(ref bitflags, reader);
            DataClass_ServiceTypeShifted = 1 << (DataClass_ServiceType - 1);

            IsExecutable        = CaesarReader.ReadBitflagUInt16(ref bitflags, reader);;
            ClientAccessLevel   = CaesarReader.ReadBitflagUInt16(ref bitflags, reader);;
            SecurityAccessLevel = CaesarReader.ReadBitflagUInt16(ref bitflags, reader);;

            T_ComParam_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            T_ComParam_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            Q_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Q_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            R_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            R_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            InputRefNameMaybe = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);

            U_prep_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            U_prep_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            // array of DWORDs, probably reference to elsewhere
            V_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            V_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            RequestBytes_Count  = CaesarReader.ReadBitflagInt16(ref bitflags, reader);
            RequestBytes_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            W_OutPres_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            W_OutPres_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            field50 = CaesarReader.ReadBitflagUInt16(ref bitflags, reader);

            NegativeResponseName = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); // negative response name
            UnkStr3 = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);
            UnkStr4 = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress);

            P_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            P_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            DiagServiceCodeCount  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            DiagServiceCodeOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            S_Count  = CaesarReader.ReadBitflagInt16(ref bitflags, reader);
            S_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            bitflags = bitflagExtended;

            X_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            X_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            Y_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Y_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            Z_Count  = CaesarReader.ReadBitflagInt32(ref bitflags, reader);
            Z_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader);

            if (RequestBytes_Count > 0)
            {
                reader.BaseStream.Seek(baseAddress + RequestBytes_Offset, SeekOrigin.Begin);
                RequestBytes = reader.ReadBytes(RequestBytes_Count);
            }
            else
            {
                RequestBytes = new byte[] { };
            }

            // u_table to u_entries
            InputPreparations = new List <DiagPreparation>();
            for (int prepIndex = 0; prepIndex < U_prep_Count; prepIndex++)
            {
                long presentationTableOffset = baseAddress + U_prep_Offset;
                reader.BaseStream.Seek(presentationTableOffset + (prepIndex * 10), SeekOrigin.Begin);

                // DIOpenDiagService (reads 4, 4, 2 then calls DiagServiceReadPresentation) to build a presentation
                int    prepEntryOffset = reader.ReadInt32();  // file: 0 (DW)
                int    prepEntryBitPos = reader.ReadInt32();  // file: 4 (DW)
                ushort prepEntryMode   = reader.ReadUInt16(); // file: 8 (W)

                DiagPreparation preparation = new DiagPreparation(reader, language, presentationTableOffset + prepEntryOffset, prepEntryBitPos, prepEntryMode, parentEcu, this);
                //preparation.PrintDebug();
                InputPreparations.Add(preparation);
            }


            OutputPreparations = new List <List <DiagPreparation> >();
            long outPresBaseAddress = BaseAddress + W_OutPres_Offset;

            for (int presIndex = 0; presIndex < W_OutPres_Count; presIndex++)
            {
                reader.BaseStream.Seek(outPresBaseAddress + (presIndex * 8), SeekOrigin.Begin);
                int resultPresentationCount  = reader.ReadInt32();
                int resultPresentationOffset = reader.ReadInt32();

                List <DiagPreparation> ResultPresentationSet = new List <DiagPreparation>();
                for (int presInnerIndex = 0; presInnerIndex < resultPresentationCount; presInnerIndex++)
                {
                    long presentationTableOffset = outPresBaseAddress + resultPresentationOffset;
                    reader.BaseStream.Seek(presentationTableOffset + (presIndex * 10), SeekOrigin.Begin);

                    int    prepEntryOffset = reader.ReadInt32();  // file: 0 (DW)
                    int    prepEntryBitPos = reader.ReadInt32();  // file: 4 (DW)
                    ushort prepEntryMode   = reader.ReadUInt16(); // file: 8 (W)

                    DiagPreparation preparation = new DiagPreparation(reader, language, presentationTableOffset + prepEntryOffset, prepEntryBitPos, prepEntryMode, parentEcu, this);
                    ResultPresentationSet.Add(preparation);
                }
                OutputPreparations.Add(ResultPresentationSet);
            }

            DiagComParameters = new List <ComParameter>();
            long comParamTableBaseAddress = BaseAddress + T_ComParam_Offset;

            for (int cpIndex = 0; cpIndex < T_ComParam_Count; cpIndex++)
            {
                reader.BaseStream.Seek(comParamTableBaseAddress + (cpIndex * 4), SeekOrigin.Begin);
                int          resultCpOffset     = reader.ReadInt32();
                long         cpEntryBaseAddress = comParamTableBaseAddress + resultCpOffset;
                ComParameter cp = new ComParameter(reader, cpEntryBaseAddress, parentEcu.ECUInterfaces);
                DiagComParameters.Add(cp);
            }

            // DJ_Zugriffsberechtigung_Abgleich
            // DJ_Zugriffsberechtigung
            // DT_Abgasklappe_kontinuierlich
            // FN_HardReset
            // WVC_Implizite_Variantenkodierung_Write

            // NR_Disable_Resp_required noexec
            // DT_Laufzeiten_Resetzaehler_nicht_implementiert exec

            /*
             * if (false && qualifierName.Contains("RVC_SCN_Variantencodierung_VGS_73_Lesen"))
             * {
             *
             *  Console.WriteLine($"{nameof(field50)} : {field50}");
             *  Console.WriteLine($"{nameof(IsExecutable)} : {IsExecutable} {IsExecutable != 0}");
             *  Console.WriteLine($"{nameof(AccessLevel)} : {AccessLevel}");
             *  Console.WriteLine($"{nameof(SecurityAccessLevel)} : {SecurityAccessLevel}");
             *  Console.WriteLine($"{nameof(DataClass)} : {DataClass}");
             *
             *
             *
             *  Console.WriteLine($"{qualifierName} - ReqBytes: {RequestBytes_Count}, P: {P_Count}, Q: {Q_Count}, R: {R_Count}, S: {S_Count}, T: {T_Count}, Preparation: {U_prep_Count}, V: {V_Count}, W: {W_Count}, X: {X_Count}, Y: {Y_Count}, Z: {Z_Count}, DSC {DiagServiceCodeCount}");
             *  Console.WriteLine($"at 0x{baseAddress:X}, W @ 0x{W_Offset:X}, DSC @ 0x{DiagServiceCodeOffset:X}");
             *  Console.WriteLine($"ReqBytes: {BitUtility.BytesToHex(RequestBytes)}");
             * }
             */
            //Console.WriteLine($"{qualifierName} - O: {RequestBytes_Count}, P: {P_Count}, Q: {Q_Count}, R: {R_Count}, S: {S_Count}, T: {T_Count}, U: {U_Count}, V: {V_Count}, W: {W_Count}, X: {X_Count}, Y: {Y_Count}, Z: {Z_Count}, DSC {DiagServiceCodeCount}");


            byte[] dscPool             = parentEcu.ParentContainer.CaesarCFFHeader.DSCPool;
            long   dscTableBaseAddress = BaseAddress + DiagServiceCodeOffset;

            using (BinaryReader dscPoolReader = new BinaryReader(new MemoryStream(dscPool)))
            {
                for (int dscIndex = 0; dscIndex < DiagServiceCodeCount; dscIndex++)
                {
                    reader.BaseStream.Seek(dscTableBaseAddress + (4 * dscIndex), SeekOrigin.Begin);
                    long dscEntryBaseAddress = reader.ReadInt32() + dscTableBaseAddress;
                    reader.BaseStream.Seek(dscEntryBaseAddress, SeekOrigin.Begin);

                    ulong  dscEntryBitflags = reader.ReadUInt16();
                    uint   idk1             = CaesarReader.ReadBitflagUInt8(ref dscEntryBitflags, reader);
                    uint   idk2             = CaesarReader.ReadBitflagUInt8(ref dscEntryBitflags, reader);
                    int    dscPoolOffset    = CaesarReader.ReadBitflagInt32(ref dscEntryBitflags, reader);
                    string dscQualifier     = CaesarReader.ReadBitflagStringWithReader(ref dscEntryBitflags, reader, dscEntryBaseAddress);

                    dscPoolReader.BaseStream.Seek(dscPoolOffset * 8, SeekOrigin.Begin);
                    long dscRecordOffset = dscPoolReader.ReadInt32() + parentEcu.ParentContainer.CaesarCFFHeader.DscBlockOffset;
                    int  dscRecordSize   = dscPoolReader.ReadInt32();

                    reader.BaseStream.Seek(dscRecordOffset, SeekOrigin.Begin);

                    // Console.WriteLine($"DSC {qualifierName} @ 0x{dscTableBaseAddress:X8} {idk1}/{idk2} pool @ 0x{dscPoolOffset:X}, name: {dscQualifier}");
                    byte[] dscBytes = reader.ReadBytes(dscRecordSize);
#if DEBUG
                    //string dscName = $"{parentEcu.Qualifier}_{Qualifier}_{dscIndex}.pal";
                    //Console.WriteLine($"Exporting DSC: {dscName}");
                    //File.WriteAllBytes(dscName, dscBytes);
#endif
                    // at this point, the DSC binary is available in dscBytes, intended for use in DSCContext (but is currently unimplemented)
                    // Console.WriteLine($"DSC actual at 0x{dscRecordOffset:X}, size=0x{dscRecordSize:X}\n");
                }
            }
        }
Exemple #23
0
        public VCFragment(BinaryReader reader, VCDomain parentDomain, long fragmentTable, int fragmentIndex, CTFLanguage language, ECU parentEcu)
        {
            // see DIOpenVarCodeFrag
            ParentDomain = parentDomain;
            ParentECU    = parentEcu;

            long fragmentTableEntry = fragmentTable + (10 * fragmentIndex);

            reader.BaseStream.Seek(fragmentTableEntry, SeekOrigin.Begin);
            // no bitflag required for 10-byte table entry since it is mandatory
            int fragmentNewBaseOffset = reader.ReadInt32();

            ByteBitPos         = reader.ReadInt32();
            ImplementationType = reader.ReadUInt16();

            // Console.WriteLine($"Fragment new base @ 0x{fragmentNewBaseOffset:X}, byteBitPos 0x{fragmentByteBitPos:X}, implementationType: 0x{implementationType:X}");
            long fragmentBaseAddress = fragmentTable + fragmentNewBaseOffset;

            reader.BaseStream.Seek(fragmentBaseAddress, SeekOrigin.Begin);
            ulong fragmentBitflags = reader.ReadUInt32();

            // Console.WriteLine($"Fragment new bitflag @ 0x{fragmentBitflags:X}");

            Name_CTF              = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1);
            Description_CTF       = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1);
            ReadAccessLevel       = CaesarReader.ReadBitflagUInt8(ref fragmentBitflags, reader);
            WriteAccessLevel      = CaesarReader.ReadBitflagUInt8(ref fragmentBitflags, reader);
            ByteOrder             = CaesarReader.ReadBitflagUInt16(ref fragmentBitflags, reader);
            RawBitLength          = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader);
            IttOffset             = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader);
            InfoPoolIndex         = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1);
            MeaningB              = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1);
            MeaningC              = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1);
            CCFHandle             = CaesarReader.ReadBitflagInt16(ref fragmentBitflags, reader, -1);
            VarcodeDumpSize       = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader);
            VarcodeDump           = CaesarReader.ReadBitflagDumpWithReader(ref fragmentBitflags, reader, VarcodeDumpSize, fragmentBaseAddress);
            SubfragmentCount      = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader);
            SubfragmentFileOffset = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader);
            Qualifier             = CaesarReader.ReadBitflagStringWithReader(ref fragmentBitflags, reader, fragmentBaseAddress);

            // Console.WriteLine($"{nameof(fragmentName)} : {fragmentName}, child {fragmentNoOfSubFragments} @ 0x{fragmentSubfragmentFileOffset:X} base {fragmentBaseAddress:X}");


            if ((ByteOrder != 0) && (BitLength > 0))
            {
                //throw new Exception("Currently assumes everything is little-endian");
                Console.WriteLine($"WARNING: {Qualifier} (Size: {BitLength}) has an unsupported byte order. Please proceed with caution");
                //PrintDebug(true);
            }


            long subfragmentTableAddress = SubfragmentFileOffset + fragmentBaseAddress;

            Subfragments.Clear();
            for (int subfragmentIndex = 0; subfragmentIndex < SubfragmentCount; subfragmentIndex++)
            {
                reader.BaseStream.Seek(subfragmentTableAddress + (subfragmentIndex * 4), SeekOrigin.Begin);
                long          subfragmentAddress = reader.ReadInt32() + subfragmentTableAddress;
                VCSubfragment subfragment        = new VCSubfragment(reader, this, language, subfragmentAddress);
                Subfragments.Add(subfragment);
            }
            // PrintDebug();
            // Console.WriteLine($"implementation-default : {implementationType:X4} upper: {(implementationType & 0xFF0):X4} lower: {(implementationType & 0xF):X4}");
            FindFragmentSize(reader);
        }