Skip to content

Commit

Permalink
UFPTool
Browse files Browse the repository at this point in the history
  • Loading branch information
gus33000 committed Nov 17, 2024
1 parent db91b1d commit 62c9b11
Show file tree
Hide file tree
Showing 16 changed files with 1,207 additions and 24 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

jobs:
build:
runs-on: windows-latest
strategy:
matrix:
target: [win-x86,win-x64,win-arm64]
include:
- target: win-x86
platform: win
architecture: x86
- target: win-x64
platform: win
architecture: x64
- target: win-arm64
platform: win
architecture: arm64
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: 'recursive'

- name: Install .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"

- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2

- name: Build Utilities
shell: pwsh
run: |
msbuild /m:1 /t:restore,ufptool:publish /p:Platform=${{ matrix.architecture }} /p:RuntimeIdentifier=${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishDir=${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishSingleFile=true /p:PublishTrimmed=false /p:Configuration=Release /p:IncludeNativeLibrariesForSelfExtract=true UnifiedFlashingPlatform.sln
- name: Create PDB Output Directory
shell: pwsh
run: |
mkdir ${{ github.workspace }}\artifacts\${{ matrix.platform }}-${{ matrix.architecture }}-symbols
- name: Move PDBs
shell: pwsh
run: |
move ${{ github.workspace }}\artifacts\${{ matrix.platform }}-${{ matrix.architecture }}\*.pdb ${{ github.workspace }}\artifacts\${{ matrix.platform }}-${{ matrix.architecture }}-symbols
- name: Upload artifact (Binaries)
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.platform }}-${{ matrix.architecture }}-binaries
path: ${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}

- name: Upload artifact (Symbols)
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.platform }}-${{ matrix.architecture }}-symbols
path: ${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}-symbols
217 changes: 217 additions & 0 deletions UFPTool/FlashDevice.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
using Img2Ffu.Reader.Data;
using MadWizard.WinUSBNet;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using UnifiedFlashingPlatform;

namespace UFPTool
{
internal static class FlashDevice
{
internal static void Execute(string[] args)
{
if (args.Contains("-?"))
{
PrintFlashDeviceHelp();
Environment.Exit(0);
}

if (!args.ToList().Any(x => x.Equals("-Path", StringComparison.InvariantCultureIgnoreCase)))
{
Console.WriteLine("Insufficient number of arguments");
Console.WriteLine();
PrintFlashDeviceHelp();
Environment.Exit(1);
}

string FFUPath = "";
bool Reboot = false;
string DevicePath = "";
bool VerifyWrite = false;
bool ForceSynchronousWrite = false;
bool SkipPlatformIDCheck = false;
bool SkipSignatureCheck = false;
bool SkipHash = false;

for (int i = 1; i < args.Length; i++)
{
string arg = args[i];
if (arg.Equals("-Path", StringComparison.InvariantCultureIgnoreCase))
{
if (i + 1 >= args.Length)
{
Console.WriteLine("Insufficient number of arguments");
Console.WriteLine();
PrintFlashDeviceHelp();
Environment.Exit(1);
}

i++;
FFUPath = args[i];
}
else if (arg.Equals("-DevicePath", StringComparison.InvariantCultureIgnoreCase))
{
if (i + 1 >= args.Length)
{
Console.WriteLine("Insufficient number of arguments");
Console.WriteLine();
PrintFlashDeviceHelp();
Environment.Exit(1);
}

i++;
DevicePath = args[i];
}
else if (arg.Equals("-Reboot", StringComparison.InvariantCultureIgnoreCase))
{
Reboot = true;
}
else if (arg.Equals("-VerifyWrite", StringComparison.InvariantCultureIgnoreCase))
{
VerifyWrite = true;
}
else if (arg.Equals("-ForceSynchronousWrite", StringComparison.InvariantCultureIgnoreCase))
{
ForceSynchronousWrite = true;
}
else
{
Console.WriteLine($"Unknown argument: {arg}");
Console.WriteLine();
PrintFlashDeviceHelp();
Environment.Exit(1);
}
}

if (string.IsNullOrEmpty(DevicePath))
{
USBDeviceInfo[] details = USBDevice.GetDevices("{9E3BD5F7-9690-4FCC-8810-3E2650CD6ECC}");
if (details.Length == 0)
{
Console.WriteLine("No UFP devices found");
Environment.Exit(1);
}

if (details.Length > 1)
{
Console.WriteLine("Multiple UFP devices found. Please specify the device path");
Console.WriteLine();
Console.WriteLine("Available devices:");
for (int i = 0; i < details.Length; i++)
{
Console.WriteLine($" {i + 1}. {details[i].DevicePath} {details[i].DeviceDescription} ({details[i].Manufacturer})");
}
Environment.Exit(1);
}

DevicePath = details[0].DevicePath;
}

FlashFlags flashFlags = FlashFlags.Normal;

if (VerifyWrite)
{
flashFlags |= FlashFlags.VerifyWrite;
}

if (ForceSynchronousWrite)
{
flashFlags |= FlashFlags.ForceSynchronousWrite;
}

if (SkipPlatformIDCheck)
{
flashFlags |= FlashFlags.SkipPlatformIDCheck;
}

if (SkipSignatureCheck)
{
flashFlags |= FlashFlags.SkipSignatureCheck;
}

if (SkipHash)
{
flashFlags |= FlashFlags.SkipHash;
}

using FileStream FFUStream = new(FFUPath, FileMode.Open, FileAccess.Read, FileShare.Read);
SignedImage signedImage = new(FFUStream);
int chunkSize = signedImage.ChunkSize;
ulong totalChunkCount = (ulong)FFUStream.Length / (ulong)chunkSize;

FFUStream.Seek(0, SeekOrigin.Begin);

using UnifiedFlashingPlatformTransport ufp = new(DevicePath);

int previousPercentage = -1;

long length = FFUStream.Length;

Stopwatch stopwatch = new();
stopwatch.Start();

Console.WriteLine($"Flashing {DevicePath}");

ufp.FlashFFU(FFUStream, new ProgressUpdater(totalChunkCount, (int percentage, TimeSpan? eta) =>
{
string NewText = null;
if (percentage != null)
{
NewText = $"\rFlash: {percentage:d}% completed...";
}
if (eta != null)
{
if (NewText == null)
{
NewText = "";
}
else
{
NewText += " - ";
}
NewText += $"Estimated time remaining: {eta:h\\:mm\\:ss}";
}
if (NewText != null && previousPercentage != percentage)
{
previousPercentage = percentage;
Console.Write(NewText);
}
}), ResetAfterwards: Reboot, Options: (byte)flashFlags);

stopwatch.Stop();

TimeSpan elapsed = stopwatch.Elapsed;
double num = length / 1048576L / elapsed.TotalSeconds;

Console.WriteLine();
Console.WriteLine($"Device flashed successfully at {num:F3} MB/s in {elapsed.TotalSeconds:F3} seconds");
}

static void PrintFlashDeviceHelp()
{
Console.WriteLine("Flash a FFU to a device via USB or network");
Console.WriteLine();
Console.WriteLine(" UFPTool.exe FlashDevice [-Property] <[Value]> <[-Property] <[Value]>...>");
Console.WriteLine();
Console.WriteLine("Supported properties and their possible values:");
Console.WriteLine();
Console.WriteLine(" Path - Path to the FFU");
Console.WriteLine(" DevicePath - [Optional] Device path");
Console.WriteLine(" Reboot - [Optional] Reboot the device after it is flashed successfully");
Console.WriteLine(" VerifyWrite - [Optional] Verify FFU is written successfully");
Console.WriteLine(" ForceSynchronousWrite - [Optional] Force synchronous write to storage");
Console.WriteLine(" SkipPlatformIDCheck - [Optional] Skip platform ID check between device and FFU file");
Console.WriteLine(" SkipSignatureCheck - [Optional] Skip signature check between device and FFU file");
Console.WriteLine(" SkipHash - [Optional] Skip hash check of FFU file chunks");
Console.WriteLine();
Console.WriteLine("Examples:");
Console.WriteLine();
Console.WriteLine(" UFPTool.exe FlashDevice -Path d:\\flash.ffu");
}
}
}
17 changes: 17 additions & 0 deletions UFPTool/FlashFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;

namespace UFPTool
{
[Flags]
public enum FlashFlags : uint
{
Normal = 0U,
SkipPlatformIDCheck = 1U,
SkipSignatureCheck = 2U,
SkipHash = 4U,
VerifyWrite = 8U,
SkipWrite = 16U,
ForceSynchronousWrite = 32U,
FlashToRAM = 64U
}
}
82 changes: 82 additions & 0 deletions UFPTool/GetDeviceLog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using MadWizard.WinUSBNet;
using System;
using System.IO;
using System.Linq;
using UnifiedFlashingPlatform;

namespace UFPTool
{
internal static class GetDeviceLog
{
internal static void Execute(string[] args)
{
if (args.Contains("-?"))
{
//PrintGetDeviceLogHelp();
Environment.Exit(0);
}

string DevicePath = "";

for (int i = 1; i < args.Length; i++)
{
string arg = args[i];
if (arg.Equals("-DevicePath", StringComparison.InvariantCultureIgnoreCase))
{
if (i + 1 >= args.Length)
{
Console.WriteLine("Insufficient number of arguments");
Console.WriteLine();
//PrintGetDeviceLogHelp();
Environment.Exit(1);
}

i++;
DevicePath = args[i];
}
else
{
Console.WriteLine($"Unknown argument: {arg}");
Console.WriteLine();
//PrintGetDeviceLogHelp();
Environment.Exit(1);
}
}

if (string.IsNullOrEmpty(DevicePath))
{
USBDeviceInfo[] details = USBDevice.GetDevices("{9E3BD5F7-9690-4FCC-8810-3E2650CD6ECC}");
if (details.Length == 0)
{
Console.WriteLine("No UFP devices found");
Environment.Exit(1);
}

if (details.Length > 1)
{
Console.WriteLine("Multiple UFP devices found. Please specify the device path");
Console.WriteLine();
Console.WriteLine("Available devices:");
for (int i = 0; i < details.Length; i++)
{
Console.WriteLine($"[Device {i}]");
Console.WriteLine($"Device Path: {details[i].DevicePath}");
Console.WriteLine($"Can Flash: True");
Console.WriteLine();
}
Environment.Exit(1);
}

DevicePath = details[0].DevicePath;
}

using UnifiedFlashingPlatformTransport ufp = new(DevicePath);
string logContent = ufp.ReadLog()!;

// Example FileName: FlashLog_5_19_2023_12_33_20_PM.log
string fileName = $"FlashLog_{DateTime.Now.Month}_{DateTime.Now.Day}_{DateTime.Now.Year}_{DateTime.Now.Hour}_{DateTime.Now.Minute}_{DateTime.Now.Second}_{DateTime.Now.ToString("tt", System.Globalization.CultureInfo.InvariantCulture)}.log";

File.WriteAllText(fileName, logContent);
}
}
}
Loading

0 comments on commit 62c9b11

Please sign in to comment.