/// <summary> /// Map the raw memory to alternate settings of the DFUSE device. /// </summary> /// <param name="memory">Raw memory image</param> /// <returns>Memory mapped to alternate settings</returns> private Dictionary <byte, NamedMemory> SortMemoryByAltSetting(RawMemory memory) { Dictionary <byte, NamedMemory> sortedMemory = new Dictionary <byte, NamedMemory>(); byte altSel; int segNo = 0; while (segNo < memory.Segments.Count) { // go through the available memories (each of which is an alternate setting) for (altSel = 0; altSel < NumberOfAlternateSettings; altSel++) { string ml = GetString(iAlternateSetting(altSel)); var layout = ParseLayout(ml); int segCount = 0; var newMem = new NamedMemory(layout.Name); // add segments which fit into this layout for (int i = segNo; (i < memory.Segments.Count) && (memory.Segments[i].StartAddress >= layout.StartAddress) && (memory.Segments[i].EndAddress <= layout.EndAddress); i++) { newMem.TryAddSegment(memory.Segments[i]); segCount++; } // no matching segments, continue searching fitting alternate setting if (segCount == 0) { continue; } sortedMemory.Add(altSel, newMem); // advance with the segments segNo += segCount; break; } // loop terminated without break if (altSel == NumberOfAlternateSettings) { throw new ArgumentOutOfRangeException("memory", memory, "The provided memory has segments that cannot be found on the target device."); } } return(sortedMemory); }
/// <summary> /// Extracts the contents of a DFU file. /// </summary> /// <param name="filepath">Path to the DFU file</param> /// <returns>The device and memory image information</returns> public static FileContent ParseFile(string filepath) { using (BinaryReader reader = new BinaryReader(File.Open(filepath, FileMode.Open))) { var suffix = ReadSuffix(reader); var devInfo = new Device.Identification(suffix); var fc = new FileContent(devInfo); // remove the suffix from the contents byte[] content = new byte[reader.BaseStream.Length - suffix.bLength]; reader.BaseStream.Position = 0; reader.Read(content, 0, content.Length); // if the protocol version is according to USB spec if (fc.DeviceInfo.DfuVersion <= Protocol.LatestVersion) { // no name nor address is stored in the file, use whatever var mem = new NamedMemory("default"); // the rest of the contents is entirely the firmware mem.TryAddSegment(new Segment(~0ul, content)); fc.ImagesByAltSetting.Add(0, mem); } // if the protocol version is according to STMicroelectronics Extension else if (fc.DeviceInfo.DfuVersion == Protocol.SeVersion) { long fileOffset = 0; BufferAllocDelegate getDataChunk = (chunkSize) => { byte[] chunkData = new byte[chunkSize]; Array.Copy(content, fileOffset, chunkData, 0, chunkSize); fileOffset += chunkSize; return(chunkData); }; // DfuSe prefix var prefix = getDataChunk(SePrefix.Size).ToStruct <SePrefix>(); if (prefix.sSignature != SePrefix.Signature) { throw new ArgumentException("The selected dfu file has invalid DfuSe prefix signature."); } // there are a number of targets, each of which is mapped to a different alternate setting for (int tt = 0; tt < prefix.bTargets; tt++) { // image target prefix var target = getDataChunk(SeTargetPrefix.Size).ToStruct <SeTargetPrefix>(); if (target.sSignature != SeTargetPrefix.Signature) { throw new ArgumentException("The selected dfu file has invalid DfuSe target prefix signature."); } // TODO //if (!target.bTargetNamed) var nmem = new NamedMemory(target.sTargetName); // each target contains a number of elements (memory segments) for (uint e = 0; e < target.dwNbElements; e++) { var elem = getDataChunk(SeElementHeader.Size).ToStruct <SeElementHeader>(); nmem.TryAddSegment(new Segment(elem.dwElementAddress, getDataChunk(elem.dwElementSize))); } // the target's alternate setting is the dictionary index fc.ImagesByAltSetting.Add(target.bAlternateSetting, nmem); } // no leftover data is allowed if ((fileOffset + suffix.bLength) != reader.BaseStream.Length) { throw new ArgumentException(String.Format("The selected dfu file has unprocessed data starting at {0}.", fileOffset)); } } else { throw new ArgumentException("The selected dfu file has unsupported DFU specification version."); } return(fc); } }