/// <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)); } }
private DeviceFirmware(FirmwareMetadata metadata, byte[] data) { Metadata = metadata; Data = data; }