Example #1
0
        /// <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);
        }
Example #2
0
        /// <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);
            }
        }