Пример #1
0
        /// <summary>
        /// Creates a <see cref="DeviceFirmware"/> object extracted from the specified ASCII
        /// stream in Intel HEX format, the specified metadata string and page size.
        /// </summary>
        /// <param name="metadata">The firmware metadata encoded in a text string representation.</param>
        /// <param name="stream">The ASCII stream in Intel HEX format from which to extract the device firmware.</param>
        /// <param name="pageSize">The size of the memory blocks used to upload the device firmware.</param>
        /// <returns>
        /// A new <see cref="DeviceFirmware"/> object representing the extracted binary firware blob,
        /// together with the metadata extracted from the firmware file name.
        /// </returns>
        public static DeviceFirmware FromStream(string metadata, Stream stream, int pageSize)
        {
            const char StartCode        = ':';
            var        firmwareMetadata = FirmwareMetadata.Parse(metadata);

            using (var reader = new StreamReader(stream))
            {
                var lineNumber  = 0;
                var baseAddress = 0;
                var hexDigit    = new char[4];
                var data        = new short[0];
                Expand(ref data, pageSize);
                while (!reader.EndOfStream)
                {
                    if (ReadChar(reader, hexDigit) != StartCode)
                    {
                        throw new ArgumentException($"{lineNumber}: Invalid record start code found in hex stream.");
                    }

                    var sum        = 0;
                    var count      = ReadHexByte(reader, hexDigit);
                    var address    = ReadHexUInt16(reader, hexDigit);
                    var recordType = (RecordType)ReadHexByte(reader, hexDigit);
                    switch (recordType)
                    {
                    case RecordType.Data:
                        sum = ReadHexData(reader, hexDigit, ref data, baseAddress + address, count, pageSize);
                        break;

                    case RecordType.EndOfFile: break;

                    case RecordType.ExtendedSegmentAddress:
                        if (count != 2)
                        {
                            throw new ArgumentException($"{lineNumber}: Invalid extended segment address payload found in hex stream.");
                        }
                        var segmentAddress = ReadHexUInt16(reader, hexDigit);
                        baseAddress = segmentAddress * 16;
                        sum         = Checksum(segmentAddress);
                        break;

                    case RecordType.ExtendedLinearAddress:
                        if (count != 2)
                        {
                            throw new ArgumentException($"{lineNumber}: Invalid extended linear address payload found in hex stream.");
                        }
                        var extendedAddress = ReadHexUInt16(reader, hexDigit);
                        baseAddress = extendedAddress << 16;
                        sum         = Checksum(extendedAddress);
                        break;

                    case RecordType.StartLinearAddress:
                    case RecordType.StartSegmentAddress: throw new NotSupportedException($"{lineNumber}: Unsupported record type found in hex stream.");

                    default: throw new ArgumentException($"{lineNumber}: Invalid record type found in hex stream.");
                    }

                    sum = (byte)(sum + count + Checksum(address) + (byte)recordType);
                    var checksum = sum + ReadHexByte(reader, hexDigit);
                    if ((byte)checksum != 0)
                    {
                        throw new ArgumentException($"{lineNumber}: Invalid data checksum found in hex stream.");
                    }

                    reader.ReadLine();
                    lineNumber++;
                }

                var byteCode = Array.ConvertAll(data, value => (byte)value);
                return(new DeviceFirmware(firmwareMetadata, byteCode));
            }
        }
Пример #2
0
 private DeviceFirmware(FirmwareMetadata metadata, byte[] data)
 {
     Metadata = metadata;
     Data     = data;
 }