Skip to content

Commit

Permalink
Add command line interface
Browse files Browse the repository at this point in the history
Merge branch 'feature-cli' into master
  • Loading branch information
riuson committed Oct 2, 2020
2 parents 02e3669 + 5c75fc7 commit 608b89c
Show file tree
Hide file tree
Showing 69 changed files with 4,225 additions and 42 deletions.
31 changes: 24 additions & 7 deletions DfuConverter.sln
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sources", "Sources", "{8C399723-4385-44B9-AB6E-BD783E8A382A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DfuConvLib", "Sources\DfuConvLib\DfuConvLib.csproj", "{C44B365D-64F4-4911-9738-648FDD69A3FF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DfuConvLib", "Sources\DfuConvLib\DfuConvLib.csproj", "{C44B365D-64F4-4911-9738-648FDD69A3FF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DfuConvLib.Tests", "Sources\DfuConvLib.Tests\DfuConvLib.Tests.csproj", "{56934EB8-2AEC-4D04-8963-FEA9A04FC4B7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DfuConvLib.Tests", "Sources\DfuConvLib.Tests\DfuConvLib.Tests.csproj", "{56934EB8-2AEC-4D04-8963-FEA9A04FC4B7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DfuToolCli", "Sources\DfuToolCli\DfuToolCli.csproj", "{C721031A-5DE3-4538-91F7-0CB8EE1B10D6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DfuToolCli.Tests", "Sources\DfuToolCli.Tests\DfuToolCli.Tests.csproj", "{DECF69A6-3708-4BB2-BE6C-775A4405868F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C44B365D-64F4-4911-9738-648FDD69A3FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C44B365D-64F4-4911-9738-648FDD69A3FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
Expand All @@ -26,9 +27,25 @@ Global
{56934EB8-2AEC-4D04-8963-FEA9A04FC4B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{56934EB8-2AEC-4D04-8963-FEA9A04FC4B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{56934EB8-2AEC-4D04-8963-FEA9A04FC4B7}.Release|Any CPU.Build.0 = Release|Any CPU
{C721031A-5DE3-4538-91F7-0CB8EE1B10D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C721031A-5DE3-4538-91F7-0CB8EE1B10D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C721031A-5DE3-4538-91F7-0CB8EE1B10D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C721031A-5DE3-4538-91F7-0CB8EE1B10D6}.Release|Any CPU.Build.0 = Release|Any CPU
{DECF69A6-3708-4BB2-BE6C-775A4405868F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DECF69A6-3708-4BB2-BE6C-775A4405868F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DECF69A6-3708-4BB2-BE6C-775A4405868F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DECF69A6-3708-4BB2-BE6C-775A4405868F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C44B365D-64F4-4911-9738-648FDD69A3FF} = {8C399723-4385-44B9-AB6E-BD783E8A382A}
{56934EB8-2AEC-4D04-8963-FEA9A04FC4B7} = {8C399723-4385-44B9-AB6E-BD783E8A382A}
{C721031A-5DE3-4538-91F7-0CB8EE1B10D6} = {8C399723-4385-44B9-AB6E-BD783E8A382A}
{DECF69A6-3708-4BB2-BE6C-775A4405868F} = {8C399723-4385-44B9-AB6E-BD783E8A382A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {11C50B46-8B02-4A5A-8F91-8D1B786124EA}
EndGlobalSection
EndGlobal
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# DfuTools

This is a tools to manipulate STM32 DFU files.

## Using DfuToolCli

1. Create empty DFU

~~~ cmd
dfutoolcli dfu-create --set-device 0x1234 --set-product 0x5678 --set-vendor 0x0483 sample.dfu
~~~

2. Change IDs in DFU file

~~~ cmd
dfutoolcli dfu-change --set-device 0xf132 --set-product 0xf567 --set-vendor 0xf483 sample.dfu
~~~

3. Remove all targets from DFU file

~~~ cmd
dfutoolcli dfu-clear sample.dfu
~~~

4. Show DFU contents

~~~ cmd
dfutoolcli dfu-show --data-length 16 sample.dfu
~~~

5. Add new image element to specified target

~~~ cmd
dfutoolcli element-create --id 0 --set-address 0x08000000 --set-content element.bin sample.dfu
~~~

6. Extract image element from specified target to file

~~~ cmd
dfutoolcli element-extract --id 0 --index 0 --output-file element.bin sample.dfu
~~~

7. Remove image element from specified target

~~~ cmd
dfutoolcli element-remove --id 0 --index 0 sample.dfu
~~~

8. Change target's ID and Name

~~~ cmd
dfutoolcli target-change --id 0 --set-id 2 --set-name "Hello, World!" sample.dfu
~~~

9. Remove all image elements from target

~~~ cmd
dfutoolcli target-clear --id 0
~~~

10. Create new target

~~~ cmd
dfutoolcli target-create --set-name "Bootloader" --set-id 0 sample.dfu
~~~

11. Remove existing target

~~~ cmd
dfutoolcli target-remove --id 0 sample.dfu
~~~
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ public void CanReadReal() {

var dfuImage = dfu.Images.Images.First();
var targetPrefix = dfuImage.Prefix;
Assert.That(targetPrefix.AlternateSetting, Is.EqualTo(2));
Assert.That(targetPrefix.TargetId, Is.EqualTo(2));
Assert.That(targetPrefix.Signature, Is.EqualTo("Target"));
Assert.That(targetPrefix.TargetNamed, Is.True);
Assert.That(targetPrefix.IsTargetNamed, Is.True);
Assert.That(targetPrefix.TargetName, Is.EqualTo(new string('Q', 255)));

Assert.That(dfuImage.ImageElements.Count, Is.EqualTo(1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ public void CanReadFullMocks() {
dfuSuffixMock.SetupProperty(x => x.DfuSignature);

var targetPrefixMock = new Mock<ITargetPrefix>();
targetPrefixMock.SetupProperty(x => x.AlternateSetting);
targetPrefixMock.SetupProperty(x => x.TargetId);
targetPrefixMock.SetupProperty(x => x.Signature);
targetPrefixMock.SetupProperty(x => x.TargetNamed);
targetPrefixMock.SetupProperty(x => x.IsTargetNamed);
targetPrefixMock.SetupProperty(x => x.TargetName);
targetPrefixMock.SetupProperty(x => x.TargetSize);
targetPrefixMock.SetupProperty(x => x.NbElements);
Expand Down Expand Up @@ -186,9 +186,9 @@ public void CanReadFullMocks() {

var dfuImage = dfu.Images.Images.First();
var targetPrefix = dfuImage.Prefix;
Assert.That(targetPrefix.AlternateSetting, Is.EqualTo(2));
Assert.That(targetPrefix.TargetId, Is.EqualTo(2));
Assert.That(targetPrefix.Signature, Is.EqualTo("Target"));
Assert.That(targetPrefix.TargetNamed, Is.True);
Assert.That(targetPrefix.IsTargetNamed, Is.True);
Assert.That(targetPrefix.TargetName, Is.EqualTo(new string('Q', 255)));

Assert.That(dfuImage.ImageElements.Count, Is.EqualTo(1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,20 @@ public void CanRead() {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Target size.
0, 0, 0, 0,
0x12, 0, 0, 0,
// NbElements.
0, 0, 0, 0
0x34, 0, 0, 0
};

var tempStream = new MemoryStream(sample, false);

var targetPrefixMock = new Mock<ITargetPrefix>();
targetPrefixMock.SetupProperty(x => x.Signature);
targetPrefixMock.SetupProperty(x => x.AlternateSetting);
targetPrefixMock.SetupProperty(x => x.TargetNamed);
targetPrefixMock.SetupProperty(x => x.TargetId);
targetPrefixMock.SetupProperty(x => x.IsTargetNamed);
targetPrefixMock.SetupProperty(x => x.TargetName);
targetPrefixMock.SetupProperty(x => x.TargetSize);
targetPrefixMock.SetupProperty(x => x.NbElements);

var sut = new TargetPrefixDeserializer(
(m, p) => new DeserializerException(m, p),
Expand All @@ -55,11 +57,67 @@ public void CanRead() {
var targetPrefix = sut.Read(tempStream);

Assert.That(targetPrefix.Signature, Is.EqualTo("Target"));
Assert.That(targetPrefix.AlternateSetting, Is.EqualTo(1));
Assert.That(targetPrefix.TargetNamed, Is.True);
Assert.That(targetPrefix.TargetId, Is.EqualTo(1));
Assert.That(targetPrefix.IsTargetNamed, Is.True);
Assert.That(targetPrefix.TargetName, Is.EqualTo("01234567890123456789"));
Assert.That(targetPrefix.TargetSize, Is.EqualTo(0u));
Assert.That(targetPrefix.NbElements, Is.EqualTo(0u));
Assert.That(targetPrefix.TargetSize, Is.EqualTo(0x12u));
Assert.That(targetPrefix.NbElements, Is.EqualTo(0x34u));
}

[Test]
public void CanReadWithEmptyName() {
var sample = new byte[] {
// Signature.
0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
// Alternate setting.
1,
// Target named.
0, 0, 0, 0,
// Target name.
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Target size.
0x12, 0, 0, 0,
// NbElements.
0x34, 0, 0, 0
};

var tempStream = new MemoryStream(sample, false);

var targetPrefixMock = new Mock<ITargetPrefix>();
targetPrefixMock.SetupProperty(x => x.Signature);
targetPrefixMock.SetupProperty(x => x.TargetId);
targetPrefixMock.SetupProperty(x => x.IsTargetNamed);
targetPrefixMock.SetupProperty(x => x.TargetName);
targetPrefixMock.SetupProperty(x => x.TargetSize);
targetPrefixMock.SetupProperty(x => x.NbElements);

var sut = new TargetPrefixDeserializer(
(m, p) => new DeserializerException(m, p),
() => targetPrefixMock.Object);

var targetPrefix = sut.Read(tempStream);

Assert.That(targetPrefix.Signature, Is.EqualTo("Target"));
Assert.That(targetPrefix.TargetId, Is.EqualTo(1));
Assert.That(targetPrefix.IsTargetNamed, Is.False);
Assert.That(targetPrefix.TargetName, Is.EqualTo(string.Empty));
Assert.That(targetPrefix.TargetSize, Is.EqualTo(0x12u));
Assert.That(targetPrefix.NbElements, Is.EqualTo(0x34u));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public void CanWrite() {
//targetPrefixMock.Setup(x => x.Write(It.IsAny<Stream>(), It.IsAny<IDfuImage>()))
// .Callback<Stream, IDfuImage>((s, i) => i.Write(s));
targetPrefixMock.SetupGet(x => x.Signature).Returns("Target");
targetPrefixMock.SetupGet(x => x.AlternateSetting).Returns(7);
targetPrefixMock.SetupGet(x => x.TargetNamed).Returns(true);
targetPrefixMock.SetupGet(x => x.TargetId).Returns(7);
targetPrefixMock.SetupGet(x => x.IsTargetNamed).Returns(true);
targetPrefixMock.SetupGet(x => x.TargetName).Returns(
string.Join("", Enumerable.Range(0, 50).Select(_ => "SAMPLE")));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public void CanWriteReal() {
};

var targetPrefix = new TargetPrefix {
AlternateSetting = 2,
TargetNamed = true,
TargetId = 2,
IsTargetNamed = true,
TargetName = new string('Q', 256)
};

Expand Down
4 changes: 2 additions & 2 deletions Sources/DfuConvLib.Tests/Serialization/DfuSerializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ public void CanWriteFullMocks() {
dfuSuffixMock.SetupGet(x => x.DfuSignature).Returns("UFD");

var targetPrefixMock = new Mock<ITargetPrefix>();
targetPrefixMock.SetupGet(x => x.AlternateSetting).Returns(2);
targetPrefixMock.SetupGet(x => x.TargetId).Returns(2);
targetPrefixMock.SetupGet(x => x.Signature).Returns("Target");
targetPrefixMock.SetupGet(x => x.TargetNamed).Returns(true);
targetPrefixMock.SetupGet(x => x.IsTargetNamed).Returns(true);
targetPrefixMock.SetupGet(x => x.TargetName).Returns(new string('Q', 256));

var imageElementMock = new Mock<IImageElement>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public void CanWrite() {

var targetPrefixMock = new Mock<ITargetPrefix>();
targetPrefixMock.SetupGet(x => x.Signature).Returns("0123456789");
targetPrefixMock.SetupGet(x => x.AlternateSetting).Returns(1);
targetPrefixMock.SetupGet(x => x.TargetNamed).Returns(true);
targetPrefixMock.SetupGet(x => x.TargetId).Returns(1);
targetPrefixMock.SetupGet(x => x.IsTargetNamed).Returns(true);
targetPrefixMock.SetupGet(x => x.TargetName).Returns("01234567890123456789");

var dfuImageMock = new Mock<IDfuImage>();
Expand Down
12 changes: 7 additions & 5 deletions Sources/DfuConvLib/Deserialization/TargetPrefixDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,25 @@ public ITargetPrefix Read(Stream stream) {
stream.Position - 6);
}

var alternateSetting = reader.ReadByte();
var targetId = reader.ReadByte();

var targetNamed = reader.ReadUInt32();
var isTargetNamed = reader.ReadUInt32();

var targetName = string.Empty;

if (targetNamed != 0) {
if (isTargetNamed != 0) {
targetName = reader.ReadString(255);
} else {
reader.BaseStream.Position += 255;
}

var targetSize = reader.ReadUInt32();
var numberOfElements = reader.ReadUInt32();

var targetPrefix = this._createTargetPrefix();
targetPrefix.Signature = signature;
targetPrefix.AlternateSetting = alternateSetting;
targetPrefix.TargetNamed = targetNamed != 0;
targetPrefix.TargetId = targetId;
targetPrefix.IsTargetNamed = isTargetNamed != 0;
targetPrefix.TargetName = targetName;
targetPrefix.TargetSize = targetSize;
targetPrefix.NbElements = numberOfElements;
Expand Down
8 changes: 4 additions & 4 deletions Sources/DfuConvLib/Interfaces/ITargetPrefix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ public interface ITargetPrefix {
string Signature { get; set; }

/// <summary>
/// The AlternateSetting field gives the device alternate setting for which the associated
/// The TargetId (AlternateSetting) field gives the device alternate setting for which the associated
/// image can be used.
/// </summary>
int AlternateSetting { get; set; }
int TargetId { get; set; }

/// <summary>
/// The TargetNamed field is a boolean value which indicates if the target is named or
/// The IsTargetNamed field is a boolean value which indicates if the target is named or
/// not.
/// </summary>
bool TargetNamed { get; set; }
bool IsTargetNamed { get; set; }

/// <summary>
/// The TargetName field gives the target name.
Expand Down
4 changes: 2 additions & 2 deletions Sources/DfuConvLib/Parts/TargetPrefix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
namespace DfuConvLib.Parts {
internal class TargetPrefix : ITargetPrefix {
public string Signature { get; set; } = "Target";
public int AlternateSetting { get; set; } = 0;
public bool TargetNamed { get; set; } = false;
public int TargetId { get; set; } = 0;
public bool IsTargetNamed { get; set; } = false;
public string TargetName { get; set; } = string.Empty;
public uint TargetSize { get; set; } = 0;
public uint NbElements { get; set; } = 0;
Expand Down
4 changes: 2 additions & 2 deletions Sources/DfuConvLib/Serialization/TargetPrefixSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public void Write(
IEnumerable<IImageElement> imageElements) {
using (var writer = new BinaryWriter(stream, Encoding.ASCII, true)) {
writer.WriteString(targetPrefix.Signature, 6);
writer.Write(Convert.ToByte(targetPrefix.AlternateSetting));
writer.Write(targetPrefix.TargetNamed ? 1 : (uint) 0);
writer.Write(Convert.ToByte(targetPrefix.TargetId));
writer.Write(targetPrefix.IsTargetNamed ? 1 : (uint) 0);
writer.WriteString(targetPrefix.TargetName, 255);
writer.Write(Convert.ToUInt32(imageElements.Sum(x => 4 + 4 + x.Data.Length)));
writer.Write(Convert.ToUInt32(imageElements.Count()));
Expand Down
Loading

0 comments on commit 608b89c

Please sign in to comment.