Пример #1
0
        public static async Task <Codeplug> ReadFromRadio(string comPort, IProgress <string> progress = null)
        {
            Codeplug codeplug = null;
            await Task.Run(() =>
            {
                try
                {
                    using var com     = new Com(comPort);
                    com.StatusUpdate += (s, e) => progress?.Report(e.Status);
                    com.EnterProgrammingMode();
                    var firmwareVersion = com.GetFirmwareVersion();
                    var extStartBytes   = com.Read(0x0002, 0x02);
                    var extStart        = extStartBytes[0] * 0x100 + extStartBytes[1];
                    var lengthBytes     = com.Read(extStart + 0x26, 0x02);

                    //Calculate total bytes to read from 0x0000 to end of External Codeplug
                    var length        = extStart + (lengthBytes[0] * 0x100 + lengthBytes[1]);
                    var codeplugBytes = new byte[length];

                    for (int i = 0; i < length; i += 0x20)
                    {
                        var bytesToRead = Math.Min(0x20, length - i);
                        com.Read(i, bytesToRead, codeplugBytes);
                    }
                    codeplug             = new Codeplug(codeplugBytes);
                    codeplug.Model       = Common.GetModel(codeplug.InternalCodeplug.Model);
                    codeplug.Firmware    = Common.GetFirmware(firmwareVersion);
                    codeplug.FactoryCode = com.Read(0x81F0, 0x10);
                    com.ExitSbepMode();

                    AuthCode.Calculate(codeplug);
                    File.WriteAllBytes(codeplug.GetProposedFileName(), codeplugBytes);
                }
                catch (Exception e)
                {
                    if (progress != null)
                    {
                        progress.Report($"\r\n\r\nOperation Failed!\r\n\r\n{e.Message}");
                    }
                    else
                    {
                        throw;
                    }
                }
            }).ConfigureAwait(false);

            return(codeplug);
        }
Пример #2
0
        public static void Calculate(Codeplug codeplug)
        {
            var signatureBytes = codeplug.Firmware.SignatureBytes;

            if (signatureBytes == null || signatureBytes.Length == 0)
            {
                codeplug.AuthCodeStatus = $"Unknown Firmware Version {codeplug.Firmware.Version:0.00}. Firmware must be read in Flash Mode to get the bytes required for the calculation.";
                return;
            }

            byte[] buffer = new byte[0x50];

            Encoding.ASCII.GetBytes(codeplug.InternalCodeplug.Model).CopyTo(buffer, MODEL);

            //Calculate Factory Code Bytes 7 and 8
            //These bytes are calculated by the official process and already stored in flash.
            //Codeplug has the same series of bytes, except for bytes 7 and 8 are 0x00;
            //Seems to just really be a checksum
            var fc    = codeplug.FactoryCode;
            var check = (fc[0x0] * 0x100 + fc[0x1]) +
                        (fc[0x2] * 0x100 + fc[0x3]) +
                        (fc[0x4] * 0x100 + fc[0x5]) +
                        (fc[0x8] * 0x100 + fc[0x9]) +
                        (fc[0xA] * 0x100 + fc[0xB]) +
                        (fc[0xC] * 0x100 + fc[0xD]) +
                        (fc[0xE] * 0x100 + fc[0xF]);

            check   = ~((check & 0xFFFF) - 0xFFF8) + 1;
            fc[0x6] = (byte)(check / 0x100);
            fc[0x7] = (byte)(check % 0x100);

            fc.CopyTo(buffer, FACTORY_CODE);

            signatureBytes.CopyTo(buffer, FLASH_SIGNATURE);

            codeplug.InternalCodeplug.Block10.FeatureBlock.CopyTo(buffer, FDB_PART_A);
            codeplug.InternalCodeplug.Block10.Flashcode.CopyTo(buffer, FDB_PART_B);

            byte[] authCode = new byte[10];

            var  i = 0;
            var  j = 0;
            byte z = 0;

            foreach (byte o in ORDER)
            {
                byte a = buffer[o];

                a ^= z;                       //eora byte_70
                z  = a;                       //staa byte_70

                a  = (byte)((sbyte)(a) >> 1); //asra    ;Arithmetic Shift Right
                a  = (byte)(a >> 1);          //lsra    ;Logical Shift Right
                a ^= z;                       //eora byte_70

                byte b = a;                   //tab

                a = (byte)(a << 1);           //asla (or lsla)  ;Logical Shift Left

                a &= 0xF0;                    //anda #$F0

                b = (byte)((sbyte)(b) >> 1);  //asrb    ;Arithmetic Shift Right

                if ((b & 0x80) == 0x80)       //bmi  ;Is MSB (aka Negative Bit) Set?
                {
                    b = (byte)(~b);           //comb
                }

                b &= 0x0f;         //andb #$F

                a = (byte)(a + b); //aba

                b  = z;            //ldab byte_70
                b &= 0x7;          //andb #7

                a ^= KEY[b];       //ldx #$D8B9  -- abx  -- eora 0,x

                z = a;             //staa byte_70

                if (++i % 8 == 0)
                {
                    authCode[j++] = z;
                    z             = 0;
                }
            }

            byte[] serial = Encoding.ASCII.GetBytes(codeplug.InternalCodeplug.Serial);
            for (int x = 0; x < 10; x++)
            {
                authCode[x] = (byte)(authCode[x] ^ serial[x]);
            }

            codeplug.CalculatedAuthCode = authCode;
            if (authCode.SequenceEqual(codeplug.InternalCodeplug.AuthCode))
            {
                codeplug.AuthCodeStatus = "Successfully calculated matching auth code.";
            }
            else
            {
                codeplug.AuthCodeStatus = "Not able to calculate existing auth code. If radio is showing 01/93 error, the calculated code should be written to the radio to fix this error.";
            }
        }