49 Commits
Author SHA1 Message Date
Gustave Monce a982c119fb Bump timebomb 2024-09-09 21:08:35 +02:00
Gustave Monce c6dee3fe33 workaround older phone fw issues when retrieving via json rpc and gpt get function failures 2024-09-01 16:49:36 +02:00
Gustave Monce 91961b0e7b fix issues with downloading files 2024-09-01 12:45:46 +02:00
Gustave Monce 29c6ab06d4 fix: Download issues with ENOSW 2024-09-01 10:38:47 +02:00
Gustave Monce b03b561724 fix a few TODOs 2024-08-31 23:17:34 +02:00
Gustave Monce 91f534a7c3 fix: Merge issues from previous commit 2024-08-31 21:58:23 +02:00
Gustave Monce f0f3268924 Split phone info structures for each app type 2024-08-31 21:52:20 +02:00
Gustave Monce c269cfe839 Enable downloading ENOSW via Download Page 2024-08-31 19:45:24 +02:00
Gustave Monce 7d8aad0e88 fix: Modern Flash App Label mode switching 2024-08-31 18:31:56 +02:00
Gustave Monce 310d0b97c5 fix: Mode change detection on specb
resolves a few issues but not all due to the combined app
2024-08-31 17:50:18 +02:00
Gustave Monce 8e50c46357 wip: Refactor FlashApp Logic to account for the 3 split app states 2024-08-31 16:39:44 +02:00
Gustave Monce e6555741b0 fix: PhoneInfo app handling + label parsing issues 2024-08-31 11:00:04 +02:00
Gustave Monce c21692491d fix: Log all silent exceptions 2024-08-30 21:43:30 +02:00
Gustave Monce 350b6e8f1e fix: add missing raise can execute changed for unlock v1 with supported ffu field 2024-08-30 20:42:52 +02:00
Gustave Monce 0101477830 fix: Handle empty flash part list
This is used to clear the red flashing status we need to handle this differently for spec A
2024-08-30 20:42:37 +02:00
Gustave Monce a6c017986b fix: Handle loaders with new lines at the top instead of intel hex style right at the start 2024-08-30 20:42:16 +02:00
Gustave Monce 0174fc8b30 QCParts: Check if signatures are available 2024-08-30 20:41:57 +02:00
Gustave Monce c6f6ef4429 Rework Qualcomm Partition to also work with modern day ed loaders 2024-08-27 10:08:47 +02:00
Gustave Monce ab0c35e879 fix: revert qualcomm partition code changes to account for older ed payloads 2024-08-27 09:55:52 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
676a95dd97 Bump System.Text.Json from 8.0.0 to 8.0.4 in /WPinternals (#74)
Bumps System.Text.Json from 8.0.0 to 8.0.4.

---
updated-dependencies:
- dependency-name: System.Text.Json
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-13 14:53:12 +02:00
Gustave Monce 8981fd02e9 Enable Preview Build 2023-11-26 18:50:46 +01:00
Gustave Monce 16d3f95971 WPinternals v3.0 2023-11-26 18:39:49 +01:00
Gustave Monce 293c649edb Refactor Qualcomm Sahara and Qualcomm Firehose code 2023-11-26 18:37:14 +01:00
Gustave Monce 88efc77887 Cleanup Sahara Implementation 2023-11-26 18:08:50 +01:00
Gustave Monce dc6085f185 Sahara: Implement getting the RKH 2023-11-26 16:51:29 +01:00
Gustave Monce e2cbb9c6fc Alter the list of OS partitions 2023-11-26 14:19:05 +01:00
Gustave Monce 4b7b9621b4 Rebuild the Backup to Custom ROM zip functionality to handle more partitions and be more flexible 2023-11-26 14:04:13 +01:00
Gustave Monce 96c42a29b5 Adopt new C# syntax for array init 2023-11-26 14:03:46 +01:00
Gustave Monce 742c89b9bf CI: Use .NET 8 SDK 2023-11-26 13:09:49 +01:00
Gustave Monce dbd303fd07 Add new feature to generate a GPT xml file from a binary or backup 2023-11-26 13:08:33 +01:00
Gustave Monce 8d35be447a Project: Update to .NET 8 2023-11-26 12:25:14 +01:00
Gustave Monce 83c09bdc81 Improve RKH Reading from Qualcomm Images 2023-03-09 21:40:23 +01:00
Gustave MonceandGitHub 93a5064751 Merge pull request #47 from ungeskriptet/fix-typo 2022-12-23 09:31:24 +01:00
David Wronek ef6a962a01 Fix typo in MassStorageView 2022-12-19 20:35:47 +01:00
Gustave Monce d32788198d Project: Migrate to .NET 7 2022-11-11 02:26:45 -08:00
Gustave Monce 7798dd1c34 RKH: Fix an issue retrieving modern day RKH 2022-11-11 02:22:17 -08:00
Gustave Monce 57cd052d61 About: Show Build and Revision in the version field 2021-11-15 15:06:13 +01:00
Gustave Monce 5eb523530c Remove the Lumia 535 from the supported phone list 2021-11-15 14:53:34 +01:00
Gustave Monce 8a17b05398 Project: Update to .NET 6 2021-11-15 14:47:29 +01:00
Gustave Monce dc5ac1e7d4 CI: Make CI always fetch latest .NET 5 SDK 2021-08-26 09:09:47 +02:00
Gustave Monce 1d14d79fab Flash: Custom ROM: Fix incorrect unlocked check for EFIESP 2021-08-16 11:40:58 +02:00
Gustave Monce 846ea41883 Project: Add SDK 2021-08-14 11:24:02 +02:00
Gustave Monce 452393aaa7 Project: Add RootAccessTestUWP 2021-08-14 11:14:56 +02:00
Gustave Monce 17bc763761 Project: Move WPinternals code to a WPinternals folder 2021-08-14 11:04:37 +02:00
Gustave Monce 668a9b7fe2 Fix an issue with incorrect logging of secure boot state 2021-08-13 13:21:15 +02:00
Gustave Monce 8293c18406 Merge branch 'master' of https://github.com/ReneLergner/WPinternals 2021-08-12 17:43:45 +02:00
Gustave Monce 48fbfa77df Project: remove references to hijacked website/domain to prevent potential malicious activity due to us not controlling the domain anymore. 2021-08-12 17:43:38 +02:00
Gustave MonceandGitHub 709c91cec5 Create bug_report.yml 2021-08-12 08:59:16 +02:00
Gustave MonceandGitHub 611ad122f9 Create README.md 2021-08-12 08:52:54 +02:00
285 changed files with 57278 additions and 48482 deletions
+60
View File
@@ -0,0 +1,60 @@
name: Bug Report
description: Create a bug report to help improve WPinternals
labels: [bug]
body:
- type: textarea
attributes:
label: Description
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1. Go to '....'
2. Click on '....'
3. Scroll down to '....'
4. See the error
validations:
required: false
- type: textarea
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: input
id: wpi-version
attributes:
label: WPinternals Version
description: What version of WPinternals are you using?
placeholder: v2.9.2
validations:
required: true
- type: input
attributes:
label: Windows Version
description: What version of Windows are you using? Press <kbd>Win</kbd> + <kbd>Pause/Break</kbd> and copy.
placeholder: e.g. Windows 11 21H2 22000.132
validations:
required: true
- type: input
attributes:
label: Phone model
description: What phone model did you reproduce the bug on (if applicable)
placeholder: e.g. Lumia 950 XL (RM-1085)
validations:
required: false
- type: textarea
attributes:
label: Relevant Assets
description: |
A list of assets (logs, screenshots) relevant to this bug.
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
placeholder: |
To upload the log
- Copy the `WPinternals.log` files from `%ALLUSERSPROFILE%\WPinternals`
- Drag and drop them into this text area.
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: windows-latest runs-on: windows-latest
strategy: strategy:
matrix: matrix:
architecture: [x86, x64] architecture: [x86, x64, arm64]
platform: [win] platform: [win]
steps: steps:
- name: Checkout - name: Checkout
@@ -20,7 +20,7 @@ jobs:
- name: Install .NET SDK - name: Install .NET SDK
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: "5.0.400" dotnet-version: "8.0.x"
- name: Add MSBuild to PATH - name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v1.0.2 uses: microsoft/setup-msbuild@v1.0.2
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+24
View File
@@ -0,0 +1,24 @@
# Windows Phone Internals
Windows Phone Internals (WPinternals or WPI for short) is a tool designed to unlock the bootloader and/or secure boot of select Lumia devices made by Nokia and Microsoft.
Thanks to specifically crafted exploits/techniques the tool is able to disable Bootloader Security/SecureBoot on select Lumia models.
After unlocking your bootloader you will be able to notably perform the following actions:
- Boot other Operating Systems
- Enable Root Access (on select OS versions)
- Flash Custom ROMs
- Backup your current Windows Phone ROM
- Access your phone internal storage over USB
## Root Access
Root Access is a set of patches/hacks disabling security inside Windows Phone at its root. Kernel Security, Permission checks, application container security, deployment capability security and much gets disabled as part of enabling root access.
## How to get started?
The tool contains all the documentation you need to know more about the tool, we invite you to read the getting started section of the tool to know more.
## Where do I download the tool?
Here: https://github.com/ReneLergner/WPinternals/releases/latest
+8
View File
@@ -0,0 +1,8 @@
<Application
x:Class="RootAccessTestUWP.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RootAccessTestUWP"
RequestedTheme="Dark">
</Application>
+100
View File
@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace RootAccessTestUWP
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+89
View File
@@ -0,0 +1,89 @@
using System;
using System.Runtime.InteropServices;
namespace RootAccessTestUWP
{
public static class Core
{
[DllImport("KERNELBASE.DLL", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int RegQueryValueEx(UIntPtr hKey, string lpValueName, int lpReserved, out Core.RegistryValueKind lpType, IntPtr lpData, ref int lpcbData);
[DllImport("KERNELBASE.DLL", CharSet = CharSet.Unicode)]
private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);
[DllImport("KERNELBASE.DLL", SetLastError = true)]
private static extern int RegCloseKey(UIntPtr hKey);
internal static string RegReadStringValue(UIntPtr rootKey, string keyPath, string valueName)
{
UIntPtr hKey;
int num = Core.RegOpenKeyEx(rootKey, keyPath, 0, Core.KEY_READ, out hKey);
if (num != 0)
{
throw new COMException("Failed to open registry key", num);
}
int cb = 1024;
IntPtr intPtr = Marshal.AllocHGlobal(cb);
Core.RegistryValueKind registryValueKind;
num = Core.RegQueryValueEx(hKey, valueName, 0, out registryValueKind, intPtr, ref cb);
if (num != 0)
{
throw new COMException("Failed to read registry value", num);
}
if (registryValueKind != Core.RegistryValueKind.String)
{
throw new Exception("Wrong registry value type");
}
string result = Marshal.PtrToStringUni(intPtr);
Core.RegCloseKey(hKey);
return result;
}
internal static uint RegReadDwordValue(UIntPtr rootKey, string keyPath, string valueName)
{
UIntPtr hKey;
int num = Core.RegOpenKeyEx(rootKey, keyPath, 0, Core.KEY_READ, out hKey);
if (num != 0)
{
throw new COMException("Failed to open registry key", num);
}
int cb = 1024;
IntPtr intPtr = Marshal.AllocHGlobal(cb);
Core.RegistryValueKind registryValueKind;
num = Core.RegQueryValueEx(hKey, valueName, 0, out registryValueKind, intPtr, ref cb);
if (num != 0)
{
throw new COMException("Failed to read registry value", num);
}
if (registryValueKind != Core.RegistryValueKind.DWord)
{
throw new Exception("Wrong registry value type");
}
uint result = (uint)Marshal.ReadInt32(intPtr);
Core.RegCloseKey(hKey);
return result;
}
public static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)2147483648U;
public static UIntPtr HKEY_CURRENT_USER = (UIntPtr)2147483649U;
public static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)2147483650U;
public static UIntPtr HKEY_USERS = (UIntPtr)2147483651U;
private static int KEY_READ = 131097;
public enum RegistryValueKind
{
Unknown,
String,
ExpandString,
Binary,
DWord,
MultiString = 7,
QWord = 11,
None = -1
}
}
}
+19
View File
@@ -0,0 +1,19 @@
<Page
x:Class="RootAccessTestUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RootAccessTestUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="TextBlock"
Margin="10"
HorizontalAlignment="Stretch"
TextWrapping="Wrap"
Text=""
VerticalAlignment="Stretch"
FontFamily="Courier New" />
</Grid>
</Page>
+65
View File
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace RootAccessTestUWP
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
TextBlock.Text = "Reading: HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\PhoneProvisioner\\ColdBootDone" + Environment.NewLine + Environment.NewLine;
bool flag = false;
try
{
Core.RegReadDwordValue(Core.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\PhoneProvisioner", "ColdBootDone");
flag = true;
}
catch
{
}
if (flag)
{
TextBlock.Text = string.Concat(new string[]
{
TextBlock.Text,
"Success!",
Environment.NewLine,
Environment.NewLine,
"Root Access: Enabled"
});
}
else
{
TextBlock.Text = string.Concat(new string[]
{
TextBlock.Text,
"Failed!",
Environment.NewLine,
Environment.NewLine,
"Root Access: Disabled"
});
}
}
}
}
+49
View File
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
<Identity
Name="66bf96f4-f5ba-41f1-8ceb-ac4e9065ac52"
Publisher="CN=Rene"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="66bf96f4-f5ba-41f1-8ceb-ac4e9065ac52" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>RootAccessTestUWP</DisplayName>
<PublisherDisplayName>Rene</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="RootAccessTestUWP.App">
<uap:VisualElements
DisplayName="RootAccessTestUWP"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="RootAccessTestUWP"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
</Package>
@@ -0,0 +1,29 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("RootAccessTestUWP")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RootAccessTestUWP")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]
@@ -0,0 +1,31 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at https://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Serialize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>
+169
View File
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{8B6AADBB-C750-492E-AF60-82F6323401CC}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RootAccessTestUWP</RootNamespace>
<AssemblyName>RootAccessTestUWP</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.22000.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM64'">
<OutputPath>bin\ARM64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Core.cs" />
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Content Include="Properties\Default.rd.xml" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.13</Version>
</PackageReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+1814 -1
View File
File diff suppressed because it is too large Load Diff
@@ -1518,10 +1518,10 @@ namespace SevenZip.Compression.LZMA
} }
private static readonly string[] kMatchFinderIDs = private static readonly string[] kMatchFinderIDs =
{ [
"BT2", "BT2",
"BT4", "BT4",
}; ];
private static int FindMatchFinder(string s) private static int FindMatchFinder(string s)
{ {
+1 -1
View File
@@ -1,5 +1,5 @@
<!-- <!--
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
+150 -56
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -83,9 +83,13 @@ namespace WPinternals
{ {
FFU FFU = null; FFU FFU = null;
PhoneNotifierViewModel Notifier; PhoneNotifierViewModel Notifier;
NokiaFlashModel FlashModel; LumiaFlashAppModel FlashModel;
LumiaBootManagerAppModel BootMgrModel;
LumiaPhoneInfoAppModel PhoneInfoModel;
NokiaPhoneModel NormalModel; NokiaPhoneModel NormalModel;
PhoneInfo Info; LumiaFlashAppPhoneInfo FlashInfo;
LumiaPhoneInfoAppPhoneInfo PhoneInfo;
LumiaBootManagerPhoneInfo BootManagerInfo;
string ProductType; string ProductType;
string ProductCode; string ProductCode;
string OperatorCode; string OperatorCode;
@@ -114,7 +118,7 @@ namespace WPinternals
return; return;
} }
switch (args[1].ToLower().TrimStart(new char[] { '-', '/' })) switch (args[1].ToLower().TrimStart(['-', '/']))
{ {
#if DEBUG #if DEBUG
case "test": case "test":
@@ -182,23 +186,14 @@ namespace WPinternals
Notifier = new PhoneNotifierViewModel(); Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A
GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException GPT GPT = BootMgrModel.ReadGPT(); // May throw NotSupportedException
foreach (Partition Partition in GPT.Partitions) foreach (Partition Partition in GPT.Partitions)
{ {
LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly); LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly);
} }
if (FlashModel.ReadPhoneInfo(false).FlashAppProtocolVersionMajor >= 2)
{
FlashModel.SwitchToFlashAppContext();
}
else
{
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
}
Notifier.Stop(); Notifier.Stop();
} }
catch (Exception Ex) catch (Exception Ex)
@@ -221,11 +216,14 @@ namespace WPinternals
{ {
Notifier = new PhoneNotifierViewModel(); Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException GPT GPT = BootMgrModel.ReadGPT(); // May throw NotSupportedException
Directory.CreateDirectory(Path.GetDirectoryName(args[2])); string DirPath = Path.GetDirectoryName(args[2]);
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{
Directory.CreateDirectory(DirPath);
}
GPT.WritePartitions(args[2]); GPT.WritePartitions(args[2]);
FlashModel.SwitchToFlashAppContext();
Notifier.Stop(); Notifier.Stop();
} }
catch (Exception Ex) catch (Exception Ex)
@@ -237,6 +235,35 @@ namespace WPinternals
LogFile.EndAction("BackupGPT"); LogFile.EndAction("BackupGPT");
} }
break; break;
case "convertgpt":
if (args.Length < 4)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -ConvertGPT <Path to GPT-file> <Path to xml-file>");
}
LogFile.BeginAction("ConvertGPT");
try
{
using var stream = File.OpenRead(args[2]);
byte[] GPTBuffer = new byte[34 * 0x200];
stream.Read(GPTBuffer, 0, 34 * 0x200);
GPT GPT = new(GPTBuffer);// May throw NotSupportedException
string DirPath = Path.GetDirectoryName(args[3]);
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{
Directory.CreateDirectory(DirPath);
}
GPT.WritePartitions(args[3]);
}
catch (Exception Ex)
{
LogFile.LogException(Ex);
}
finally
{
LogFile.EndAction("ConvertGPT");
}
break;
case "restoregpt": case "restoregpt":
if (args.Length < 3) if (args.Length < 3)
{ {
@@ -248,14 +275,13 @@ namespace WPinternals
{ {
Notifier = new PhoneNotifierViewModel(); Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
byte[] GptChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000); byte[] GptChunk = BootMgrModel.GetGptChunk(0x20000);
GPT GPT = new(GptChunk); GPT GPT = new(GptChunk);
string Xml = File.ReadAllText(args[2]); string Xml = File.ReadAllText(args[2]);
GPT.MergePartitions(Xml, false); GPT.MergePartitions(Xml, false);
GPT.Rebuild(); GPT.Rebuild();
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(Notifier, null, false, false, 0, GptChunk, true, true); await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(Notifier, null, false, false, 0, GptChunk, true, true);
FlashModel.SwitchToFlashAppContext();
Notifier.Stop(); Notifier.Stop();
} }
catch (Exception Ex) catch (Exception Ex)
@@ -285,7 +311,10 @@ namespace WPinternals
s = new FileStream(args[3], FileMode.Open, FileAccess.Read); s = new FileStream(args[3], FileMode.Open, FileAccess.Read);
Archive = new ZipArchive(s); Archive = new ZipArchive(s);
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
if (Archive == null) if (Archive == null)
{ {
@@ -393,7 +422,11 @@ namespace WPinternals
}; };
} }
string EfiPath = Path.Combine(args[3], Name); string EfiPath = Path.Combine(args[3], Name);
Directory.CreateDirectory(Path.GetDirectoryName(EfiPath)); string DirPath = Path.GetDirectoryName(EfiPath);
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{
Directory.CreateDirectory(DirPath);
}
File.WriteAllBytes(EfiPath, EfiBinary); File.WriteAllBytes(EfiPath, EfiBinary);
} }
break; break;
@@ -512,9 +545,9 @@ namespace WPinternals
try try
{ {
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo(); FlashInfo = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly); FlashInfo.Log(LogType.ConsoleOnly);
FFU ProfileFFU = null; FFU ProfileFFU = null;
FFU CurrentFFU; FFU CurrentFFU;
@@ -527,7 +560,7 @@ namespace WPinternals
string PlatformID = CurrentFFU.PlatformID; string PlatformID = CurrentFFU.PlatformID;
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling. // Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase)) if (FlashInfo.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
{ {
ProfileFFU = CurrentFFU; ProfileFFU = CurrentFFU;
} }
@@ -536,7 +569,7 @@ namespace WPinternals
if (ProfileFFU == null) if (ProfileFFU == null)
{ {
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList(); List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
ProfileFFU = FFUs.Count > 0 ProfileFFU = FFUs.Count > 0
? new FFU(FFUs[0].Path) ? new FFU(FFUs[0].Path)
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line."); : throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
@@ -661,9 +694,9 @@ namespace WPinternals
LogFile.Log("Command: Show phone info", LogType.FileAndConsole); LogFile.Log("Command: Show phone info", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel(); Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo(); FlashInfo = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly); FlashInfo.Log(LogType.ConsoleOnly);
Notifier.Stop(); Notifier.Stop();
break; break;
case "unlockbootloader": case "unlockbootloader":
@@ -673,9 +706,9 @@ namespace WPinternals
LogFile.Log("Command: Unlock Bootloader", LogType.FileAndConsole); LogFile.Log("Command: Unlock Bootloader", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel(); Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo(); FlashInfo = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly); FlashInfo.Log(LogType.ConsoleOnly);
FFU ProfileFFU = null; FFU ProfileFFU = null;
FFU SupportedFFU = null; FFU SupportedFFU = null;
@@ -689,7 +722,7 @@ namespace WPinternals
string PlatformID = CurrentFFU.PlatformID; string PlatformID = CurrentFFU.PlatformID;
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling. // Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase)) if (FlashInfo.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
{ {
ProfileFFU = CurrentFFU; ProfileFFU = CurrentFFU;
} }
@@ -704,7 +737,7 @@ namespace WPinternals
if (ProfileFFU == null) if (ProfileFFU == null)
{ {
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList(); List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
ProfileFFU = FFUs.Count > 0 ProfileFFU = FFUs.Count > 0
? new FFU(FFUs[0].Path) ? new FFU(FFUs[0].Path)
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line."); : throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
@@ -746,9 +779,9 @@ namespace WPinternals
LogFile.Log("Custom ROM: " + CustomRomPath, LogType.FileAndConsole); LogFile.Log("Custom ROM: " + CustomRomPath, LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel(); Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo(); FlashInfo = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly); FlashInfo.Log(LogType.ConsoleOnly);
LogFile.Log("Preparing to flash Custom ROM", LogType.FileAndConsole); LogFile.Log("Preparing to flash Custom ROM", LogType.FileAndConsole);
await LumiaV2UnlockBootViewModel.LumiaV2FlashArchive(Notifier, CustomRomPath); await LumiaV2UnlockBootViewModel.LumiaV2FlashArchive(Notifier, CustomRomPath);
LogFile.Log("Custom ROM flashed successfully", LogType.FileAndConsole); LogFile.Log("Custom ROM flashed successfully", LogType.FileAndConsole);
@@ -777,11 +810,11 @@ namespace WPinternals
LogFile.Log("FFU file: " + FFUPath, LogType.FileAndConsole); LogFile.Log("FFU file: " + FFUPath, LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel(); Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo(); FlashInfo = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly); FlashInfo.Log(LogType.ConsoleOnly);
LogFile.Log("Flashing FFU...", LogType.FileAndConsole); LogFile.Log("Flashing FFU...", LogType.FileAndConsole);
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!Info.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0))); await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!FlashInfo.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
LogFile.Log("FFU flashed successfully", LogType.FileAndConsole); LogFile.Log("FFU flashed successfully", LogType.FileAndConsole);
Notifier.Stop(); Notifier.Stop();
} }
@@ -1243,11 +1276,55 @@ namespace WPinternals
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel; NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode"); ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
} }
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)) else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
{ {
FlashModel = (NokiaFlashModel)Notifier.CurrentModel; (Notifier.CurrentModel as LumiaBootManagerAppModel).SwitchToPhoneInfoAppContext();
Info = FlashModel.ReadPhoneInfo();
ProductCode = Info.ProductCode; if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
await Notifier.WaitForArrival();
}
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
throw new WPinternalsException("Unexpected Mode");
}
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
ProductCode = PhoneInfo.ProductCode;
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_PhoneInfo)
{
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
ProductCode = PhoneInfo.ProductCode;
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
bool ModernFlashApp = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
if (ModernFlashApp)
{
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContext();
}
else
{
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
}
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
await Notifier.WaitForArrival();
}
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
throw new WPinternalsException("Unexpected Mode");
}
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
ProductCode = PhoneInfo.ProductCode;
} }
else else
{ {
@@ -1408,11 +1485,19 @@ namespace WPinternals
ProductType = ProductType.Substring(0, ProductType.IndexOf('_')); ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
} }
} }
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)) else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
{ {
FlashModel = (NokiaFlashModel)Notifier.CurrentModel; BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
Info = FlashModel.ReadPhoneInfo(); BootManagerInfo = BootMgrModel.ReadPhoneInfo();
ProductType = Info.Type; //ProductType = BootManagerInfo.Type; // TODO: FIXME
ProductType = "";
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
FlashInfo = FlashModel.ReadPhoneInfo();
//ProductType = FlashInfo.Type; // TODO: FIXME
ProductType = "";
} }
else else
{ {
@@ -1519,11 +1604,19 @@ namespace WPinternals
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel; NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode"); ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
} }
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)) else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
{ {
FlashModel = (NokiaFlashModel)Notifier.CurrentModel; BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
Info = FlashModel.ReadPhoneInfo(); BootManagerInfo = BootMgrModel.ReadPhoneInfo();
ProductCode = Info.ProductCode; //ProductCode = BootManagerInfo.ProductCode; // TODO: FIXME
ProductCode = "";
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
FlashInfo = FlashModel.ReadPhoneInfo();
//ProductCode = FlashInfo.ProductCode; // TODO: FIXME
ProductCode = "";
} }
else else
{ {
@@ -1968,6 +2061,7 @@ namespace WPinternals
LogFile.Log("WPinternals -ClearNV", LogType.ConsoleOnly); LogFile.Log("WPinternals -ClearNV", LogType.ConsoleOnly);
LogFile.Log("WPinternals -ReadGPT", LogType.ConsoleOnly); LogFile.Log("WPinternals -ReadGPT", LogType.ConsoleOnly);
LogFile.Log("WPinternals -BackupGPT <Path to xml-file>", LogType.ConsoleOnly); LogFile.Log("WPinternals -BackupGPT <Path to xml-file>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -ConvertGPT <Path to GPT-file> <Path to xml-file>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -RestoreGPT <Path to xml-file>", LogType.ConsoleOnly); LogFile.Log("WPinternals -RestoreGPT <Path to xml-file>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -MergeGPT <Path to input-xml-file> <Path to input-xml-file>", LogType.ConsoleOnly); LogFile.Log("WPinternals -MergeGPT <Path to input-xml-file> <Path to input-xml-file>", LogType.ConsoleOnly);
LogFile.Log(" <Optional: Path to output-xml-file>", LogType.ConsoleOnly); LogFile.Log(" <Optional: Path to output-xml-file>", LogType.ConsoleOnly);
@@ -68,7 +68,7 @@ namespace DiscUtils.Internal
result.Add(func(sVal)); result.Add(func(sVal));
} }
return result.ToArray(); return [.. result];
} }
/// <summary> /// <summary>
@@ -31,15 +31,15 @@ namespace DiscUtils.Fat
private const byte SpaceByte = 0x20; private const byte SpaceByte = 0x20;
public static readonly FileName SelfEntryName = public static readonly FileName SelfEntryName =
new(new byte[] { 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 0); new([0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20], 0);
public static readonly FileName ParentEntryName = public static readonly FileName ParentEntryName =
new(new byte[] { 0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 0); new([0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20], 0);
public static readonly FileName Null = public static readonly FileName Null =
new(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0); new([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 0);
private static readonly byte[] InvalidBytes = { 0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C }; private static readonly byte[] InvalidBytes = [0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C];
private readonly byte[] _raw; private readonly byte[] _raw;
@@ -33,10 +33,10 @@ namespace DiscUtils.Fat
{ {
if (FatFileSystem.Detect(stream)) if (FatFileSystem.Detect(stream))
{ {
return new FileSystemInfo[] { new VfsFileSystemInfo("FAT", "Microsoft FAT", Open) }; return [new VfsFileSystemInfo("FAT", "Microsoft FAT", Open)];
} }
return System.Array.Empty<FileSystemInfo>(); return [];
} }
private DiscFileSystem Open(Stream stream, VolumeInfo volumeInfo, FileSystemParameters parameters) private DiscFileSystem Open(Stream stream, VolumeInfo volumeInfo, FileSystemParameters parameters)
@@ -80,22 +80,22 @@ namespace DiscUtils.Fat
{ {
// see http://home.teleport.com/~brainy/lfn.htm // see http://home.teleport.com/~brainy/lfn.htm
// NOTE: we assume ordinals are ok here. // NOTE: we assume ordinals are ok here.
char[] chars = new char[13]; char[] chars =
chars[0] = (char)((256 * buffer[2]) + buffer[1]); [
chars[1] = (char)((256 * buffer[4]) + buffer[3]); (char)((256 * buffer[2]) + buffer[1]),
chars[2] = (char)((256 * buffer[6]) + buffer[5]); (char)((256 * buffer[4]) + buffer[3]),
chars[3] = (char)((256 * buffer[8]) + buffer[7]); (char)((256 * buffer[6]) + buffer[5]),
chars[4] = (char)((256 * buffer[10]) + buffer[9]); (char)((256 * buffer[8]) + buffer[7]),
(char)((256 * buffer[10]) + buffer[9]),
chars[5] = (char)((256 * buffer[15]) + buffer[14]); (char)((256 * buffer[15]) + buffer[14]),
chars[6] = (char)((256 * buffer[17]) + buffer[16]); (char)((256 * buffer[17]) + buffer[16]),
chars[7] = (char)((256 * buffer[19]) + buffer[18]); (char)((256 * buffer[19]) + buffer[18]),
chars[8] = (char)((256 * buffer[21]) + buffer[20]); (char)((256 * buffer[21]) + buffer[20]),
chars[9] = (char)((256 * buffer[23]) + buffer[22]); (char)((256 * buffer[23]) + buffer[22]),
chars[10] = (char)((256 * buffer[25]) + buffer[24]); (char)((256 * buffer[25]) + buffer[24]),
(char)((256 * buffer[29]) + buffer[28]),
chars[11] = (char)((256 * buffer[29]) + buffer[28]); (char)((256 * buffer[31]) + buffer[30]),
chars[12] = (char)((256 * buffer[31]) + buffer[30]); ];
string chunk = new(chars); string chunk = new(chars);
int zero = chunk.IndexOf('\0'); int zero = chunk.IndexOf('\0');
return zero >= 0 ? chunk.Substring(0, zero) : chunk; return zero >= 0 ? chunk.Substring(0, zero) : chunk;
@@ -201,7 +201,7 @@ namespace DiscUtils.Fat
} }
} }
return dirs.ToArray(); return [.. dirs];
} }
public DirectoryEntry[] GetFiles() public DirectoryEntry[] GetFiles()
@@ -215,7 +215,7 @@ namespace DiscUtils.Fat
} }
} }
return files.ToArray(); return [.. files];
} }
public DirectoryEntry GetEntry(long id) public DirectoryEntry GetEntry(long id)
@@ -1258,7 +1258,7 @@ namespace DiscUtils.Fat
dirs.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding))); dirs.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
} }
return dirs.ToArray(); return [.. dirs];
} }
/// <summary> /// <summary>
@@ -1275,7 +1275,7 @@ namespace DiscUtils.Fat
List<string> dirs = new(); List<string> dirs = new();
DoSearch(dirs, path, re, searchOption == SearchOption.AllDirectories, true, false); DoSearch(dirs, path, re, searchOption == SearchOption.AllDirectories, true, false);
return dirs.ToArray(); return [.. dirs];
} }
/// <summary> /// <summary>
@@ -1294,7 +1294,7 @@ namespace DiscUtils.Fat
files.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding))); files.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
} }
return files.ToArray(); return [.. files];
} }
/// <summary> /// <summary>
@@ -1311,7 +1311,7 @@ namespace DiscUtils.Fat
List<string> results = new(); List<string> results = new();
DoSearch(results, path, re, searchOption == SearchOption.AllDirectories, false, true); DoSearch(results, path, re, searchOption == SearchOption.AllDirectories, false, true);
return results.ToArray(); return [.. results];
} }
/// <summary> /// <summary>
@@ -1330,7 +1330,7 @@ namespace DiscUtils.Fat
result.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding))); result.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
} }
return result.ToArray(); return [.. result];
} }
/// <summary> /// <summary>
@@ -1356,7 +1356,7 @@ namespace DiscUtils.Fat
} }
} }
return result.ToArray(); return [.. result];
} }
/// <summary> /// <summary>
@@ -1915,9 +1915,7 @@ namespace DiscUtils.Fat
throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "The directory '{0}' was not found", path)); throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "The directory '{0}' was not found", path));
} }
DirectoryEntry[] entries = dir.Entries; foreach (DirectoryEntry de in dir.Entries)
foreach (DirectoryEntry de in entries)
{ {
bool isDir = (de.Attributes & FatAttributes.Directory) != 0; bool isDir = (de.Attributes & FatAttributes.Directory) != 0;
@@ -1,5 +1,5 @@
<!-- <!--
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -316,13 +316,19 @@ namespace WPinternals
{ {
filename = System.IO.Path.GetFileName(Text); filename = System.IO.Path.GetFileName(Text);
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
string directory = ""; string directory = "";
try try
{ {
directory = System.IO.Path.GetDirectoryName(Text); directory = System.IO.Path.GetDirectoryName(Text);
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
FormattedText formatted; FormattedText formatted;
bool widthOK = false; bool widthOK = false;
bool changedWidth = false; bool changedWidth = false;
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -28,6 +28,7 @@ using System.Globalization;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@@ -658,7 +659,7 @@ namespace WPinternals
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." + Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." + Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString(), LogType.FileAndConsole); Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString(), LogType.FileAndConsole);
Log("Copyright Heathcliff74 / wpinternals.net", LogType.FileAndConsole); Log("Copyright Heathcliff74", LogType.FileAndConsole);
} }
internal static void BeginAction(string Action) internal static void BeginAction(string Action)
@@ -673,7 +674,7 @@ namespace WPinternals
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." + Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." + Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString()); Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString());
LogBuilder.AppendLine("Copyright Heathcliff74 / wpinternals.net"); LogBuilder.AppendLine("Copyright Heathcliff74");
LogBuilder.AppendLine("Action: " + Action); LogBuilder.AppendLine("Action: " + Action);
if (App.Config.RegistrationName != null) if (App.Config.RegistrationName != null)
LogBuilder.AppendLine("Name: " + App.Config.RegistrationName); LogBuilder.AppendLine("Name: " + App.Config.RegistrationName);
@@ -924,7 +925,7 @@ namespace WPinternals
{ {
if (proxy?.CheckAccess() == false) if (proxy?.CheckAccess() == false)
{ {
proxy.BeginInvoke(new Action<object, EventHandler>(CallHandler), new object[] { sender, eventHandler }); proxy.BeginInvoke(new Action<object, EventHandler>(CallHandler), [sender, eventHandler]);
} }
else else
{ {
@@ -1890,7 +1891,7 @@ namespace WPinternals
internal static Version GetFileVersion(byte[] PEfile) internal static Version GetFileVersion(byte[] PEfile)
{ {
byte[] version = GetResource(PEfile, new int[] { (int)ResourceType.RT_VERSION, 1, 1033 }); byte[] version = GetResource(PEfile, [(int)ResourceType.RT_VERSION, 1, 1033]);
// RT_VERSION format: // RT_VERSION format:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx
@@ -1906,7 +1907,7 @@ namespace WPinternals
internal static Version GetProductVersion(byte[] PEfile) internal static Version GetProductVersion(byte[] PEfile)
{ {
byte[] version = GetResource(PEfile, new int[] { (int)ResourceType.RT_VERSION, 1, 1033 }); byte[] version = GetResource(PEfile, [(int)ResourceType.RT_VERSION, 1, 1033]);
// RT_VERSION format: // RT_VERSION format:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx
@@ -1940,7 +1941,8 @@ namespace WPinternals
internal static void Upload(string FileName, Stream FileStream) internal static void Upload(string FileName, Stream FileStream)
{ {
Upload(new Uri(@"https://www.wpinternals.net/upload.php", UriKind.Absolute), "uploadedfile", FileName, FileStream); //TODO: Fix
//Upload(new Uri(@"https://www.wpinternals.net/upload.php", UriKind.Absolute), "uploadedfile", FileName, FileStream);
} }
private static void Upload(Uri Address, string InputName, string FileName, Stream FileStream) private static void Upload(Uri Address, string InputName, string FileName, Stream FileStream)
@@ -2221,8 +2223,7 @@ namespace WPinternals
} }
else else
{ {
double width = Math.Max(allowedSpace * (Percentage / totalPercentage), 0); _element.Width = (double)Math.Max(allowedSpace * (Percentage / totalPercentage), 0);
_element.Width = width;
} }
} }
} }

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -332,7 +332,7 @@ namespace WPinternals
return (UInt16)(0x10000 - Checksum); return (UInt16)(0x10000 - Checksum);
} }
private static readonly UInt32[] CRC32Table = new UInt32[] { private static readonly UInt32[] CRC32Table = [
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
@@ -376,7 +376,7 @@ namespace WPinternals
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
}; ];
internal static UInt32 CRC32(byte[] Input, UInt32 Offset, UInt32 Length) internal static UInt32 CRC32(byte[] Input, UInt32 Offset, UInt32 Length)
{ {
+4 -4
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -84,7 +84,7 @@ namespace WPinternals
// Read Store Header // Read Store Header
byte[] ShortStoreHeader = new byte[248]; byte[] ShortStoreHeader = new byte[248];
FFUFile.Read(ShortStoreHeader, 0, 248); FFUFile.Read(ShortStoreHeader, 0, 248);
PlatformID = ByteOperations.ReadAsciiString(ShortStoreHeader, 0x0C, 192).TrimEnd(new char[] { (char)0, ' ' }); PlatformID = ByteOperations.ReadAsciiString(ShortStoreHeader, 0x0C, 192).TrimEnd([(char)0, ' ']);
int WriteDescriptorCount = ByteOperations.ReadInt32(ShortStoreHeader, 208); int WriteDescriptorCount = ByteOperations.ReadInt32(ShortStoreHeader, 208);
UInt32 WriteDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 212); UInt32 WriteDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 212);
UInt32 ValidateDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 220); UInt32 ValidateDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 220);
@@ -455,8 +455,8 @@ namespace WPinternals
if (Offset != null) if (Offset != null)
{ {
uint Start = (uint)Offset + 10; uint Start = (uint)Offset + 10;
uint Length = (uint)ByteOperations.FindPattern(Data, Start, 0x100, new byte[] { 0x00 }, null, null) - Start; uint Length = (uint)ByteOperations.FindPattern(Data, Start, 0x100, [0x00], null, null) - Start;
uint? Offset0D = ByteOperations.FindPattern(Data, Start, 0x100, new byte[] { 0x0D }, null, null); uint? Offset0D = ByteOperations.FindPattern(Data, Start, 0x100, [0x0D], null, null);
if ((Offset0D != null) && (Offset0D < (Start + Length))) if ((Offset0D != null) && (Offset0D < (Start + Length)))
{ {
Length = (uint)Offset0D - Start; Length = (uint)Offset0D - Start;
+29
View File
@@ -0,0 +1,29 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
{
internal enum FlashAppType
{
BootManager = 1,
FlashApp = 2,
PhoneInfoApp = 3
};
}
+30
View File
@@ -0,0 +1,30 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
{
internal class FlashVersion
{
public int ApplicationMajor;
public int ApplicationMinor;
public int ProtocolMajor;
public int ProtocolMinor;
}
}
+25 -8
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -74,7 +74,7 @@ namespace WPinternals
while (PartitionOffset < (TableOffset + TableSize)) while (PartitionOffset < (TableOffset + TableSize))
{ {
string Name = ByteOperations.ReadUnicodeString(GPTBuffer, PartitionOffset + 0x38, 0x48).TrimEnd(new char[] { (char)0, ' ' }); string Name = ByteOperations.ReadUnicodeString(GPTBuffer, PartitionOffset + 0x38, 0x48).TrimEnd([(char)0, ' ']);
if (Name.Length == 0) if (Name.Length == 0)
{ {
break; break;
@@ -275,7 +275,10 @@ namespace WPinternals
{ {
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200; StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
} }
if (NewPartition.LastSector == 0) if (NewPartition.LastSector == 0)
@@ -471,7 +474,10 @@ namespace WPinternals
{ {
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200; StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
DecompressedStream.Close(); DecompressedStream.Close();
UInt64 MaxPartitionSizeInSectors = OldPartition.SizeInSectors; UInt64 MaxPartitionSizeInSectors = OldPartition.SizeInSectors;
@@ -521,7 +527,10 @@ namespace WPinternals
{ {
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200; StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
DecompressedStream.Close(); DecompressedStream.Close();
if (NewPartition.SizeInSectors != StreamLengthInSectors) if (NewPartition.SizeInSectors != StreamLengthInSectors)
{ {
@@ -545,7 +554,7 @@ namespace WPinternals
internal void WritePartitions(string Path) internal void WritePartitions(string Path)
{ {
string DirPath = System.IO.Path.GetDirectoryName(Path); string DirPath = System.IO.Path.GetDirectoryName(Path);
if (!Directory.Exists(DirPath)) if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{ {
Directory.CreateDirectory(DirPath); Directory.CreateDirectory(DirPath);
} }
@@ -559,6 +568,15 @@ namespace WPinternals
FileWriter.Close(); FileWriter.Close();
} }
internal void WritePartitions(Stream Stream)
{
XmlSerializer x = new(typeof(GPT), "");
XmlSerializerNamespaces ns = new();
ns.Add("", "");
x.Serialize(Stream, this, ns);
}
internal static GPT ReadPartitions(string Path) internal static GPT ReadPartitions(string Path)
{ {
XmlSerializer x = new(typeof(GPT), ""); XmlSerializer x = new(typeof(GPT), "");
@@ -570,8 +588,7 @@ namespace WPinternals
{ {
// This is necessary, because the partitions and backup-partitions can exchange. // This is necessary, because the partitions and backup-partitions can exchange.
// This may cause the startsector to be higher than the maximum allowed sector for flashing with a Lumia V1 programmer (hardcoded in programmer) // This may cause the startsector to be higher than the maximum allowed sector for flashing with a Lumia V1 programmer (hardcoded in programmer)
List<string> RevisePartitions = new(new string[] { "SBL1", "SBL2", "SBL3", "UEFI", "TZ", "RPM", "WINSECAPP" }); foreach (string RevisePartitionName in (List<string>)(new(new string[] { "SBL1", "SBL2", "SBL3", "UEFI", "TZ", "RPM", "WINSECAPP" })))
foreach (string RevisePartitionName in RevisePartitions)
{ {
Partition RevisePartition = GetPartition(RevisePartitionName); Partition RevisePartition = GetPartition(RevisePartitionName);
Partition ReviseBackupPartition = GetPartition("BACKUP_" + RevisePartitionName); Partition ReviseBackupPartition = GetPartition("BACKUP_" + RevisePartitionName);
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -110,9 +110,9 @@ namespace WPinternals
if (DictionarySize != 0) if (DictionarySize != 0)
{ {
Encoder.SetCoderProperties( Encoder.SetCoderProperties(
new CoderPropID[8] {CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, [CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits,
CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker}, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker],
new object[8] { DictionarySize, PosStateBits, LitContextBits, LitPosBits, Algorithm, NumFastBytes, MatchFinder, EndMarker }); [DictionarySize, PosStateBits, LitContextBits, LitPosBits, Algorithm, NumFastBytes, MatchFinder, EndMarker]);
} }
Encoder.WriteCoderProperties(stream); Encoder.WriteCoderProperties(stream);
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -158,7 +158,7 @@ namespace WPinternals
return FfuUrl; return FfuUrl;
} }
internal static string SearchENOSW(string ProductType, string PhoneFirmwareRevision) internal static (string SecureWIMUrl, string DPLUrl) SearchENOSW(string ProductType, string PhoneFirmwareRevision)
{ {
if (ProductType?.Length == 0) if (ProductType?.Length == 0)
{ {
@@ -170,7 +170,7 @@ namespace WPinternals
ProductType = ProductType.ToUpper(); ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-")) if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
{ {
ProductType = "RM-" + ProductType[2..]; ProductType = $"RM-{ProductType[2..]}";
} }
} }
@@ -182,6 +182,7 @@ namespace WPinternals
packageClass = "Public", packageClass = "Public",
manufacturerHardwareModel = ProductType manufacturerHardwareModel = ProductType
}; };
DiscoveryParameters DiscoveryParams = new() DiscoveryParameters DiscoveryParams = new()
{ {
query = DiscoveryQueryParams query = DiscoveryQueryParams
@@ -212,10 +213,10 @@ namespace WPinternals
} }
SoftwarePackage Package = null; SoftwarePackage Package = null;
using (MemoryStream JsonStream2 = new(Encoding.UTF8.GetBytes(JsonResultString))) using MemoryStream JsonResultStream = new(Encoding.UTF8.GetBytes(JsonResultString));
{ DataContractJsonSerializer SoftwarePackagesJsonSerializer = new(typeof(SoftwarePackages));
DataContractJsonSerializer Serializer2 = new(typeof(SoftwarePackages)); SoftwarePackages SoftwarePackages = (SoftwarePackages)SoftwarePackagesJsonSerializer.ReadObject(JsonResultStream);
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
if (SoftwarePackages != null) if (SoftwarePackages != null)
{ {
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages) foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
@@ -223,48 +224,46 @@ namespace WPinternals
Package = SoftwarePackages.softwarePackages.FirstOrDefault(); Package = SoftwarePackages.softwarePackages.FirstOrDefault();
} }
} }
}
if (Package == null) if (Package == null)
{ {
throw new WPinternalsException("ENOSW package not found", "No ENOSW package has been found in the remote software repository for the requested model."); throw new WPinternalsException("ENOSW package not found", "No ENOSW package has been found in the remote software repository for the requested model.");
} }
SoftwareFile FileInfo = Package.files.First(f => f.fileName.EndsWith(".secwim", StringComparison.OrdinalIgnoreCase)); SoftwareFile SecureWimSoftwareFile = Package.files.First(f => f.fileName.EndsWith(".secwim", StringComparison.OrdinalIgnoreCase));
SoftwareFile DPLSoftwareFile = Package.files.First(f => f.fileName.EndsWith(".dpl", StringComparison.OrdinalIgnoreCase));
SoftwareFile DPLF = Package.files.First(f => f.fileName.EndsWith(".dpl", StringComparison.OrdinalIgnoreCase)); Uri DPLFileUrlUri = new($"https://api.swrepository.com/rest-api/discovery/fileurl/1/{Package.id}/{DPLSoftwareFile.fileName}");
Uri DPLUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + DPLF.fileName);
Task<string> GetDPLTask = HttpClient.GetStringAsync(DPLUri); Task<string> GetDPLTask = HttpClient.GetStringAsync(DPLFileUrlUri);
GetDPLTask.Wait(); GetDPLTask.Wait();
string DPLString = GetDPLTask.Result;
string DPLUrl = ""; string DPLFileUrlResultContent = GetDPLTask.Result;
FileUrlResult FileUrlDPL = null; FileUrlResult DPLFileUrlResult = null;
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(DPLString))) using MemoryStream DPLFileUrlResultStream = new(Encoding.UTF8.GetBytes(DPLFileUrlResultContent));
DataContractJsonSerializer DPLFileUrlResultSerializer = new(typeof(FileUrlResult));
DPLFileUrlResult = (FileUrlResult)DPLFileUrlResultSerializer.ReadObject(DPLFileUrlResultStream);
string DPLFileUrl = "";
if (DPLFileUrlResult != null)
{ {
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult)); DPLFileUrl = DPLFileUrlResult.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
FileUrlDPL = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
if (FileUrlDPL != null)
{
DPLUrl = FileUrlDPL.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
}
} }
if (DPLUrl?.Length == 0) if (DPLFileUrl?.Length == 0)
{ {
throw new WPinternalsException("DPL not found", "No DPL has been found in the remote software repository for the requested model."); throw new WPinternalsException("DPL not found", "No DPL has been found in the remote software repository for the requested model.");
} }
Task<string> GetDPLStrTask = HttpClient.GetStringAsync(DPLUrl); Task<string> GetDPLStrTask = HttpClient.GetStringAsync(DPLFileUrl);
GetDPLStrTask.Wait(); GetDPLStrTask.Wait();
string DPLStrString = GetDPLStrTask.Result; string DPLStrString = GetDPLStrTask.Result;
DPL.Package dpl; DPL.Package dpl;
XmlSerializer serializer = new(typeof(DPL.Package)); XmlSerializer serializer = new(typeof(DPL.Package));
using (StringReader reader = new(DPLStrString.Replace("ft:", "").Replace("dpl:", "").Replace("typedes:", ""))) using StringReader reader = new(DPLStrString.Replace("ft:", "").Replace("dpl:", "").Replace("typedes:", ""));
{
dpl = (DPL.Package)serializer.Deserialize(reader); dpl = (DPL.Package)serializer.Deserialize(reader);
}
foreach (DPL.File file in dpl.Content.Files.File) foreach (DPL.File file in dpl.Content.Files.File)
{ {
@@ -274,30 +273,30 @@ namespace WPinternals
if (IsFirmwareBetween(PhoneFirmwareRevision, range.From, range.To)) if (IsFirmwareBetween(PhoneFirmwareRevision, range.From, range.To))
{ {
FileInfo = Package.files.First(f => f.fileName.EndsWith(name, StringComparison.OrdinalIgnoreCase)); SecureWimSoftwareFile = Package.files.First(f => f.fileName.EndsWith(name, StringComparison.OrdinalIgnoreCase));
} }
} }
Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + FileInfo.fileName); Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + SecureWimSoftwareFile.fileName);
Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri); Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri);
GetFileInfoTask.Wait(); GetFileInfoTask.Wait();
string FileInfoString = GetFileInfoTask.Result; string FileInfoString = GetFileInfoTask.Result;
string ENOSWUrl = ""; string ENOSWFileUrl = "";
FileUrlResult FileUrl = null; FileUrlResult FileUrl = null;
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(FileInfoString)))
{ using MemoryStream JsonStream4 = new(Encoding.UTF8.GetBytes(FileInfoString));
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult)); DataContractJsonSerializer Serializer4 = new(typeof(FileUrlResult));
FileUrl = (FileUrlResult)Serializer3.ReadObject(JsonStream3); FileUrl = (FileUrlResult)Serializer4.ReadObject(JsonStream4);
if (FileUrl != null) if (FileUrl != null)
{ {
ENOSWUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net"); ENOSWFileUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
}
} }
HttpClient.Dispose(); HttpClient.Dispose();
return ENOSWUrl; return (ENOSWFileUrl, DPLFileUrl);
} }
private static bool IsFirmwareBetween(string PhoneFirmwareRevision, string Limit1, string Limit2) private static bool IsFirmwareBetween(string PhoneFirmwareRevision, string Limit1, string Limit2)
@@ -386,7 +385,7 @@ namespace WPinternals
Result.Add(Src); Result.Add(Src);
} }
return Result.ToArray(); return [.. Result];
} }
} }
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -41,8 +41,7 @@ namespace WPinternals
{ {
try try
{ {
ManagementObjectCollection coll = new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get(); foreach (ManagementObject logical in new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get())
foreach (ManagementObject logical in coll)
{ {
System.Diagnostics.Debug.Print(logical["Name"].ToString()); System.Diagnostics.Debug.Print(logical["Name"].ToString());
@@ -74,7 +73,10 @@ namespace WPinternals
} }
} }
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
} }
internal void AttachQualcommSerial(string DevicePath) internal void AttachQualcommSerial(string DevicePath)
@@ -112,15 +114,18 @@ namespace WPinternals
SerialDevice.EncodeCommands = false; SerialDevice.EncodeCommands = false;
// This will succeed on new models // This will succeed on new models
SerialDevice.SendData(new byte[] { 0x7, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0 }); SerialDevice.SendData([0x7, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0]);
// This will succeed on old models // This will succeed on old models
SerialDevice.SendData(new byte[] { 0x7E, 0xA, 0x0, 0x0, 0xB6, 0xB5, 0x7E }); SerialDevice.SendData([0x7E, 0xA, 0x0, 0x0, 0xB6, 0xB5, 0x7E]);
SerialDevice.Close(); SerialDevice.Close();
SerialDevice.Dispose(); SerialDevice.Dispose();
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
} }
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -40,7 +40,10 @@ namespace WPinternals
{ {
Device = new USBDevice(DevicePath); Device = new USBDevice(DevicePath);
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
} }
private JsonElement? ExecuteJsonMethodAsJsonToken(string JsonMethod, Dictionary<string, object> Params, string ResultElement) private JsonElement? ExecuteJsonMethodAsJsonToken(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
@@ -173,6 +176,11 @@ namespace WPinternals
return null; return null;
} }
if (Token.Value.ValueKind == JsonValueKind.String)
{
return Token.Value.GetString().Equals("true", StringComparison.InvariantCultureIgnoreCase);
}
return Token.Value.GetBoolean(); return Token.Value.GetBoolean();
} }
@@ -335,7 +343,10 @@ namespace WPinternals
Result = new byte[OutputLength]; Result = new byte[OutputLength];
System.Buffer.BlockCopy(Buffer, 0, Result, 0, OutputLength); System.Buffer.BlockCopy(Buffer, 0, Result, 0, OutputLength);
} }
catch { } // Reboot command looses connection catch (Exception ex) // Reboot command looses connection
{
LogFile.LogException(ex, LogType.FileOnly);
}
} }
return Result; return Result;
} }
@@ -363,7 +374,10 @@ namespace WPinternals
pipe.Reset(); pipe.Reset();
} }
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
} }
/// <summary> /// <summary>
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -40,14 +40,14 @@ namespace WPinternals
internal PatchEngine(string PatchDefinitionsXmlString) internal PatchEngine(string PatchDefinitionsXmlString)
{ {
XmlSerializer x = new(PatchDefinitions.GetType(), null, Array.Empty<Type>(), new XmlRootAttribute("PatchDefinitions"), ""); XmlSerializer x = new(PatchDefinitions.GetType(), null, [], new XmlRootAttribute("PatchDefinitions"), "");
MemoryStream s = new(System.Text.Encoding.ASCII.GetBytes(PatchDefinitionsXmlString)); MemoryStream s = new(System.Text.Encoding.ASCII.GetBytes(PatchDefinitionsXmlString));
PatchDefinitions = (List<PatchDefinition>)x.Deserialize(s); PatchDefinitions = (List<PatchDefinition>)x.Deserialize(s);
} }
internal void WriteDefinitions(string FilePath) internal void WriteDefinitions(string FilePath)
{ {
XmlSerializer x = new(PatchDefinitions.GetType(), null, Array.Empty<Type>(), new XmlRootAttribute("PatchDefinitions"), ""); XmlSerializer x = new(PatchDefinitions.GetType(), null, [], new XmlRootAttribute("PatchDefinitions"), "");
XmlSerializerNamespaces ns = new(); XmlSerializerNamespaces ns = new();
ns.Add("", ""); ns.Add("", "");
@@ -58,7 +58,7 @@ namespace WPinternals
FileWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); FileWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
FileWriter.WriteLine(""); FileWriter.WriteLine("");
FileWriter.WriteLine("<!--"); FileWriter.WriteLine("<!--");
FileWriter.WriteLine("Copyright(c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda"); FileWriter.WriteLine("Copyright(c) 2018, Rene Lergner - @Heathcliff74xda");
FileWriter.WriteLine(""); FileWriter.WriteLine("");
FileWriter.WriteLine("Permission is hereby granted, free of charge, to any person obtaining a"); FileWriter.WriteLine("Permission is hereby granted, free of charge, to any person obtaining a");
FileWriter.WriteLine("copy of this software and associated documentation files(the \"Software\"),"); FileWriter.WriteLine("copy of this software and associated documentation files(the \"Software\"),");
@@ -94,7 +94,7 @@ namespace WPinternals
} }
set set
{ {
_TargetPath = value.TrimEnd(new char[] { '\\' }); _TargetPath = value.TrimEnd(['\\']);
} }
} }
@@ -365,7 +365,7 @@ namespace WPinternals
} }
set set
{ {
_RelativePath = value.TrimStart(new char[] { '\\' }).TrimEnd(new char[] { '\\' }); _RelativePath = value.TrimStart(['\\']).TrimEnd(['\\']);
} }
} }
@@ -377,7 +377,7 @@ namespace WPinternals
} }
set set
{ {
_TargetPath = value.TrimEnd(new char[] { '\\' }); _TargetPath = value.TrimEnd(['\\']);
} }
} }
} }
@@ -515,7 +515,7 @@ namespace WPinternals
} }
set set
{ {
_Path = value.TrimStart(new char[] { '\\' }); _Path = value.TrimStart(['\\']);
} }
} }
@@ -0,0 +1,42 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace WPinternals
{
internal class CommonPhoneInfo
{
public PhoneInfoState State = PhoneInfoState.Empty;
public FlashAppType App;
public byte VersionMajor;
public byte VersionMinor;
public byte ProtocolVersionMajor;
public byte ProtocolVersionMinor;
internal void Log(LogType Type)
{
LogFile.Log($"App: {VersionMajor}.{VersionMinor}", Type);
LogFile.Log($"Protocol: {ProtocolVersionMajor}.{ProtocolVersionMinor}", Type);
}
}
}
@@ -0,0 +1,59 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace WPinternals
{
internal class LumiaBootManagerPhoneInfo
{
public PhoneInfoState State = PhoneInfoState.Empty;
public FlashAppType App;
public byte FlashAppVersionMajor;
public byte FlashAppVersionMinor;
public byte FlashAppProtocolVersionMajor;
public byte FlashAppProtocolVersionMinor;
public byte BootManagerVersionMajor;
public byte BootManagerVersionMinor;
public byte BootManagerProtocolVersionMajor;
public byte BootManagerProtocolVersionMinor;
public UInt32 TransferSize;
public bool MmosOverUsbSupported;
internal void Log(LogType Type)
{
switch (App)
{
case FlashAppType.BootManager:
LogFile.Log($"Bootmanager: {BootManagerVersionMajor}.{BootManagerVersionMinor}", Type);
LogFile.Log($"Bootmanager protocol: {BootManagerProtocolVersionMajor}.{BootManagerProtocolVersionMinor}", Type);
LogFile.Log($"Flash app: {FlashAppVersionMajor}.{FlashAppVersionMinor}", Type);
LogFile.Log($"Flash protocol: {FlashAppProtocolVersionMajor}.{FlashAppProtocolVersionMinor}", Type);
LogFile.Log($"Flash app: {FlashAppVersionMajor}.{FlashAppVersionMinor}", Type);
LogFile.Log($"Flash protocol: {FlashAppProtocolVersionMajor}.{FlashAppProtocolVersionMinor}", Type);
break;
}
}
}
}
@@ -0,0 +1,96 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace WPinternals
{
internal class LumiaFlashAppPhoneInfo
{
public PhoneInfoState State = PhoneInfoState.Empty;
public string Firmware; // Extended info
public byte[] RKH; // Extended info
public FlashAppType App;
public byte FlashAppVersionMajor;
public byte FlashAppVersionMinor;
public byte FlashAppProtocolVersionMajor;
public byte FlashAppProtocolVersionMinor;
public UInt32 TransferSize;
public bool MmosOverUsbSupported;
public UInt32 SdCardSizeInSectors;
public UInt32 WriteBufferSize;
public UInt32 EmmcSizeInSectors;
public string PlatformID;
public UInt16 SecureFfuSupportedProtocolMask;
public bool AsyncSupport;
public bool PlatformSecureBootEnabled;
public bool SecureFfuEnabled;
public bool JtagDisabled;
public bool RdcPresent;
public bool Authenticated;
public bool UefiSecureBootEnabled;
public bool SecondaryHardwareKeyPresent;
public bool IsBootloaderSecure;
internal void Log(LogType Type)
{
if (State == PhoneInfoState.Extended)
{
if (RKH != null)
{
LogFile.Log($"Root key hash: {Converter.ConvertHexToString(RKH, "")}", Type);
}
if (Firmware?.Length > 0)
{
LogFile.Log($"Firmware version: {Firmware}", Type);
}
}
switch (App)
{
case FlashAppType.FlashApp:
LogFile.Log($"Flash app: {FlashAppVersionMajor}.{FlashAppVersionMinor}", Type);
LogFile.Log($"Flash protocol: {FlashAppProtocolVersionMajor}.{FlashAppProtocolVersionMinor}", Type);
break;
}
LogFile.Log($"SecureBoot: {((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled")} (Platform Secure Boot: {(PlatformSecureBootEnabled ? "Enabled" : "Disabled")}, UEFI Secure Boot: {(UefiSecureBootEnabled ? "Enabled" : "Disabled")})", Type);
if ((Type == LogType.ConsoleOnly) || (Type == LogType.FileAndConsole))
{
LogFile.Log($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")}", LogType.ConsoleOnly);
}
if ((Type == LogType.FileOnly) || (Type == LogType.FileAndConsole))
{
LogFile.Log($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")} (FFU security: {(SecureFfuEnabled ? "Enabled" : "Disabled")}, RDC: {(RdcPresent ? "Present" : "Not found")}, Authenticated: {(Authenticated ? "True" : "False")})", LogType.FileOnly);
}
LogFile.Log($"JTAG: {(JtagDisabled ? "Disabled" : "Enabled")}", Type);
}
}
}
@@ -0,0 +1,69 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace WPinternals
{
internal class LumiaPhoneInfoAppPhoneInfo
{
public PhoneInfoState State = PhoneInfoState.Empty;
public string Type; // Extended info
public string ProductCode; // Extended info
public string Imei; // Extended info
public FlashAppType App;
public byte PhoneInfoAppVersionMajor;
public byte PhoneInfoAppVersionMinor;
public byte PhoneInfoAppProtocolVersionMajor;
public byte PhoneInfoAppProtocolVersionMinor;
internal void Log(LogType Type)
{
if (State == PhoneInfoState.Extended)
{
if (this.Type != null)
{
LogFile.Log($"Phone type: {this.Type}", Type);
}
if (ProductCode != null)
{
LogFile.Log($"Product code: {ProductCode}", Type);
}
if (Type != LogType.ConsoleOnly && (Imei != null))
{
LogFile.Log($"IMEI: {Imei}", LogType.FileOnly);
}
}
switch (App)
{
case FlashAppType.PhoneInfoApp:
LogFile.Log($"Phone info app: {PhoneInfoAppVersionMajor}.{PhoneInfoAppVersionMinor}", Type);
LogFile.Log($"Phone info protocol: {PhoneInfoAppProtocolVersionMajor}.{PhoneInfoAppProtocolVersionMinor}", Type);
break;
}
}
}
}
+29
View File
@@ -0,0 +1,29 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
{
internal enum PhoneInfoState
{
Empty,
Basic,
Extended
};
}
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@ namespace WPinternals
{ {
try try
{ {
Serial.SendCommand(new byte[] { 0x06 }, new byte[] { 0x02 }); Serial.SendCommand([0x06], [0x02]);
return true; return true;
} }
catch catch
@@ -61,7 +61,7 @@ namespace WPinternals
CurrentLength = Remaining >= 0x100 ? 0x100 : (UInt32)Remaining; CurrentLength = Remaining >= 0x100 ? 0x100 : (UInt32)Remaining;
CurrentLength = (UInt32)Data.Read(Buffer, 7, (int)CurrentLength); CurrentLength = (UInt32)Data.Read(Buffer, 7, (int)CurrentLength);
Serial.SendCommand(Buffer, new byte[] { 0x02 }); Serial.SendCommand(Buffer, [0x02]);
CurrentAddress += CurrentLength; CurrentAddress += CurrentLength;
Remaining -= CurrentLength; Remaining -= CurrentLength;
@@ -100,7 +100,7 @@ namespace WPinternals
System.Buffer.BlockCopy(BitConverter.GetBytes((UInt16)CurrentLength).Reverse().ToArray(), 0, CurrentBytes, 5, 2); // Length is in Big Endian System.Buffer.BlockCopy(BitConverter.GetBytes((UInt16)CurrentLength).Reverse().ToArray(), 0, CurrentBytes, 5, 2); // Length is in Big Endian
System.Buffer.BlockCopy(Data, (int)CurrentOffset, CurrentBytes, 7, (int)CurrentLength); System.Buffer.BlockCopy(Data, (int)CurrentOffset, CurrentBytes, 7, (int)CurrentLength);
Serial.SendCommand(CurrentBytes, new byte[] { 0x02 }); Serial.SendCommand(CurrentBytes, [0x02]);
CurrentAddress += CurrentLength; CurrentAddress += CurrentLength;
CurrentOffset += CurrentLength; CurrentOffset += CurrentLength;
@@ -113,25 +113,25 @@ namespace WPinternals
byte[] Buffer = new byte[5]; byte[] Buffer = new byte[5];
Buffer[0] = 0x05; Buffer[0] = 0x05;
System.Buffer.BlockCopy(BitConverter.GetBytes(Address).Reverse().ToArray(), 0, Buffer, 1, 4); // Address is in Big Endian System.Buffer.BlockCopy(BitConverter.GetBytes(Address).Reverse().ToArray(), 0, Buffer, 1, 4); // Address is in Big Endian
Serial.SendCommand(Buffer, new byte[] { 0x02 }); Serial.SendCommand(Buffer, [0x02]);
} }
// Reset interface. Interface becomes unresponsive. // Reset interface. Interface becomes unresponsive.
public void Reset() public void Reset()
{ {
Serial.SendCommand(new byte[] { 0x0A }, new byte[] { 0x02 }); Serial.SendCommand([0x0A], [0x02]);
} }
// This also resets interface. This does not actually reboot the phone. The interface becomes unresponsive. // This also resets interface. This does not actually reboot the phone. The interface becomes unresponsive.
public void Shutdown() public void Shutdown()
{ {
Serial.SendCommand(new byte[] { 0x0E }, new byte[] { 0x02 }); Serial.SendCommand([0x0E], [0x02]);
} }
// This command only works on 9008 interface. // This command only works on 9008 interface.
public byte[] GetRKH() public byte[] GetRKH()
{ {
byte[] Response = Serial.SendCommand(new byte[] { 0x18 }, new byte[] { 0x18, 0x01, 0x00 }); byte[] Response = Serial.SendCommand([0x18], [0x18, 0x01, 0x00]);
byte[] Result = new byte[0x20]; byte[] Result = new byte[0x20];
Buffer.BlockCopy(Response, 3, Result, 0, 0x20); Buffer.BlockCopy(Response, 3, Result, 0, 0x20);
return Result; return Result;
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -28,165 +28,15 @@ using System.Threading.Tasks;
namespace WPinternals namespace WPinternals
{ {
internal enum SaharaMode : uint internal class QualcommFirehose
{
ImageTransferPending = 0x00,
ImagetransferComplete = 0x01,
MemoryDebug = 0x02,
Command = 0x03
}
internal delegate void ReadyHandler();
internal class QualcommSahara
{ {
private readonly QualcommSerial Serial; private readonly QualcommSerial Serial;
public QualcommSahara(QualcommSerial Serial) public QualcommFirehose(QualcommSerial Serial)
{ {
Serial.EncodeCommands = false;
Serial.DecodeResponses = false;
this.Serial = Serial; this.Serial = Serial;
} }
public bool SendImage(string Path)
{
bool Result = true;
LogFile.Log("Sending programmer: " + Path, LogType.FileOnly);
int Step = 0;
UInt32 Offset = 0;
UInt32 Length = 0;
byte[] ImageBuffer = null;
try
{
Step = 1;
byte[] Hello = Serial.GetResponse(new byte[] { 0x01, 0x00, 0x00, 0x00 });
// Incoming Hello packet:
// 00000001 = Hello command id
// xxxxxxxx = Length
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly);
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly);
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly);
// Packet:
// 00000002 = Hello response command id
// 00000030 = Length
// 00000002 = Protocol version
// 00000001 = Supported version
// 00000000 = Status OK
// 00000000 = Mode
// rest is reserved space
Step = 2;
byte[] HelloResponse = new byte[] {
0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
Serial.SendData(HelloResponse);
Step = 3;
using FileStream FileStream = new(Path, FileMode.Open, FileAccess.Read);
while (true)
{
Step = 4;
byte[] ReadDataRequest = Serial.GetResponse(null);
UInt32 ResponseID = ByteOperations.ReadUInt32(ReadDataRequest, 0);
if (ResponseID == 4)
{
break;
}
if (ResponseID != 3)
{
Step = 5;
throw new BadConnectionException();
}
Offset = ByteOperations.ReadUInt32(ReadDataRequest, 0x0C);
Length = ByteOperations.ReadUInt32(ReadDataRequest, 0x10);
if ((ImageBuffer == null) || (ImageBuffer.Length != Length))
{
ImageBuffer = new byte[Length];
}
if (FileStream.Position != Offset)
{
FileStream.Seek(Offset, SeekOrigin.Begin);
}
Step = 6;
FileStream.Read(ImageBuffer, 0, (int)Length);
Step = 7;
Serial.SendData(ImageBuffer);
}
}
catch (Exception Ex)
{
LogFile.LogException(Ex, LogType.FileAndConsole, Step.ToString() + " 0x" + Offset.ToString("X8") + " 0x" + Length.ToString("X8"));
Result = false;
}
if (Result)
{
LogFile.Log("Programmer loaded into phone memory", LogType.FileOnly);
}
return Result;
}
public bool Handshake()
{
bool Result = true;
try
{
byte[] Hello = Serial.GetResponse(new byte[] { 0x01, 0x00, 0x00, 0x00 });
// Incoming Hello packet:
// 00000001 = Hello command id
// xxxxxxxx = Length
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly);
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly);
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly);
byte[] HelloResponse = new byte[] {
0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
byte[] Ready = Serial.SendCommand(HelloResponse, new byte[] { 0x03, 0x00, 0x00, 0x00 });
}
catch
{
Result = false;
}
return Result;
}
public void ResetSahara()
{
Serial.SendCommand(new byte[] { 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, new byte[] { 0x08, 0x00, 0x00, 0x00 });
}
public bool ConnectToProgrammer(byte[] PacketFromPcToProgrammer) public bool ConnectToProgrammer(byte[] PacketFromPcToProgrammer)
{ {
// Behaviour of old firehose: // Behaviour of old firehose:
@@ -251,7 +101,10 @@ namespace WPinternals
LogFile.Log("Programmer failed to authenticate Digital Signature", LogType.FileOnly); LogFile.Log("Programmer failed to authenticate Digital Signature", LogType.FileOnly);
} }
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
} }
while (!HandshakeCompleted && (HelloSendCount < 6)); while (!HandshakeCompleted && (HelloSendCount < 6));
@@ -280,16 +133,8 @@ namespace WPinternals
return HandshakeCompleted; return HandshakeCompleted;
} }
public async Task<bool> Reset(string ProgrammerPath) public async Task<bool> Reset()
{ {
bool SendImageResult = await Task.Run(() => SendImage(ProgrammerPath));
if (!SendImageResult)
{
return false;
}
await Task.Run(() => StartProgrammer());
bool Connected = await Task.Run(() => ConnectToProgrammerInTestMode()); bool Connected = await Task.Run(() => ConnectToProgrammerInTestMode());
if (!Connected) if (!Connected)
{ {
@@ -317,59 +162,12 @@ namespace WPinternals
return true; return true;
} }
public void SwitchMode(SaharaMode Mode) public bool SendEdPayload(string ProgrammerPath, string PayloadPath)
{
byte[] SwitchModeCommand = new byte[] { 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
ByteOperations.WriteUInt32(SwitchModeCommand, 8, (UInt32)Mode);
byte[] ResponsePattern = null;
switch (Mode)
{
case SaharaMode.ImageTransferPending:
ResponsePattern = new byte[] { 0x04, 0x00, 0x00, 0x00 };
break;
case SaharaMode.MemoryDebug:
ResponsePattern = new byte[] { 0x09, 0x00, 0x00, 0x00 };
break;
case SaharaMode.Command:
ResponsePattern = new byte[] { 0x0B, 0x00, 0x00, 0x00 };
break;
}
Serial.SendCommand(SwitchModeCommand, ResponsePattern);
}
public void StartProgrammer()
{
LogFile.Log("Starting programmer", LogType.FileAndConsole);
byte[] DoneCommand = new byte[] { 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 };
bool Started = false;
int count = 0;
do
{
count++;
try
{
byte[] DoneResponse = Serial.SendCommand(DoneCommand, new byte[] { 0x06, 0x00, 0x00, 0x00 });
Started = true;
}
catch (BadConnectionException)
{
LogFile.Log("Problem while starting programmer. Attempting again.", LogType.FileAndConsole);
}
} while (!Started && count < 3);
if (count >= 3 && !Started)
{
LogFile.Log("Maximum number of attempts to start the programmer exceeded.", LogType.FileAndConsole);
throw new BadConnectionException();
}
LogFile.Log("Programmer being launched on phone", LogType.FileOnly);
}
public async Task<bool> SendEdPayload(string ProgrammerPath, string PayloadPath)
{ {
// First, let's read the Emergency Download payload header and verify its validity // First, let's read the Emergency Download payload header and verify its validity
FileStream PayloadStream = File.OpenRead(PayloadPath); FileStream PayloadStream = File.OpenRead(PayloadPath);
byte[] ValidReferencePayloadHeader = new byte[] { 0x45, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x6E, 0x63, 0x79, 0x20, 0x50, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64 }; byte[] ValidReferencePayloadHeader = [0x45, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x6E, 0x63, 0x79, 0x20, 0x50, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64];
byte[] PayloadHeader = new byte[17]; byte[] PayloadHeader = new byte[17];
PayloadStream.Read(PayloadHeader, 0, 17); PayloadStream.Read(PayloadHeader, 0, 17);
@@ -405,16 +203,6 @@ namespace WPinternals
LogFile.Log("Version: " + version, LogType.FileAndConsole); LogFile.Log("Version: " + version, LogType.FileAndConsole);
LogFile.Log("Info: " + Info, LogType.FileAndConsole); LogFile.Log("Info: " + Info, LogType.FileAndConsole);
// Send the emergency programmer to the phone
bool SendImageResult = await Task.Run(() => SendImage(ProgrammerPath));
if (!SendImageResult)
{
return false;
}
// Start the emergency programmer on the phone
await Task.Run(() => StartProgrammer());
// Wait a few seconds before sending commands // Wait a few seconds before sending commands
LogFile.Log("Waiting...", LogType.FileAndConsole); LogFile.Log("Waiting...", LogType.FileAndConsole);
Thread.Sleep(2000); Thread.Sleep(2000);
@@ -434,7 +222,7 @@ namespace WPinternals
LogFile.Log(ProgrammerCommand, LogType.FileAndConsole); LogFile.Log(ProgrammerCommand, LogType.FileAndConsole);
byte[] PacketFromPcToProgrammer = Array.Empty<byte>(); byte[] PacketFromPcToProgrammer = [];
byte[] temp = new byte[0x200]; byte[] temp = new byte[0x200];
while (true) while (true)
@@ -453,7 +241,7 @@ namespace WPinternals
break; break;
} }
PacketFromPcToProgrammer = PacketFromPcToProgrammer.Concat(temp).ToArray(); PacketFromPcToProgrammer = [.. PacketFromPcToProgrammer, .. temp];
} }
bool ExpectingReplyFromProgrammer = false; bool ExpectingReplyFromProgrammer = false;
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -45,41 +45,37 @@ namespace WPinternals
public void Hello() public void Hello()
{ {
byte[] Command = new byte[] byte[] Command =
{ [
0x01, // Hello command 0x01, // Hello command
0x51, 0x43, 0x4F, 0x4D, 0x20, 0x66, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6F, 0x77, 0x6E, 0x6C, 0x6F, // "QCOM fast download protocol host" 0x51, 0x43, 0x4F, 0x4D, 0x20, 0x66, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6F, 0x77, 0x6E, 0x6C, 0x6F, // "QCOM fast download protocol host"
0x61, 0x64, 0x20, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x61, 0x64, 0x20, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x20, 0x68, 0x6F, 0x73, 0x74,
0x02, 0x02,
0x02, // Protocol version - Must be at least 0x02 0x02, // Protocol version - Must be at least 0x02
0x01 0x01
}; ];
Serial.SendCommand(Command, new byte[] { 0x02 }); Serial.SendCommand(Command, [0x02]);
} }
public void SetSecurityMode(byte Mode) public void SetSecurityMode(byte Mode)
{ {
byte[] Command = new byte[2]; byte[] Command = [0x17, Mode];
Command[0] = 0x17;
Command[1] = Mode;
Serial.SendCommand(Command, new byte[] { 0x18 }); Serial.SendCommand(Command, [0x18]);
} }
// Use PartitionID 0x21 // Use PartitionID 0x21
public void OpenPartition(byte PartitionID) public void OpenPartition(byte PartitionID)
{ {
byte[] Command = new byte[2]; byte[] Command = [0x1B, PartitionID];
Command[0] = 0x1B;
Command[1] = PartitionID;
Serial.SendCommand(Command, new byte[] { 0x1C }); Serial.SendCommand(Command, [0x1C]);
} }
public void ClosePartition() public void ClosePartition()
{ {
Serial.SendCommand(new byte[] { 0x15 }, new byte[] { 0x16 }); Serial.SendCommand([0x15], [0x16]);
} }
public void Flash(UInt32 StartInBytes, Stream Data, UInt32 LengthInBytes = UInt32.MaxValue) public void Flash(UInt32 StartInBytes, Stream Data, UInt32 LengthInBytes = UInt32.MaxValue)
@@ -222,7 +218,7 @@ namespace WPinternals
public void Reboot() public void Reboot()
{ {
Serial.SendCommand(new byte[] { 0x0B }, new byte[] { 0x0C }); Serial.SendCommand([0x0B], [0x0C]);
} }
} }
} }
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -33,8 +33,7 @@ namespace WPinternals
try try
{ {
IEnumerable<string> FilePaths = Directory.EnumerateFiles(Path); foreach (string FilePath in Directory.EnumerateFiles(Path))
foreach (string FilePath in FilePaths)
{ {
try try
{ {
@@ -70,10 +69,16 @@ namespace WPinternals
} }
} }
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
} }
} }
catch { } }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
return Result; return Result;
} }
@@ -90,6 +95,11 @@ namespace WPinternals
foreach (string Line in Lines) foreach (string Line in Lines)
{ {
if (string.IsNullOrEmpty(Line))
{
continue;
}
if (Line[0] != ':') if (Line[0] != ':')
{ {
throw new BadImageFormatException(); throw new BadImageFormatException();
@@ -117,7 +127,10 @@ namespace WPinternals
Result = new byte[BufferSize]; Result = new byte[BufferSize];
System.Buffer.BlockCopy(Buffer, 0, Result, 0, BufferSize); System.Buffer.BlockCopy(Buffer, 0, Result, 0, BufferSize);
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
return Result; return Result;
} }
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -19,6 +19,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Security.Cryptography; using System.Security.Cryptography;
@@ -52,15 +53,15 @@ namespace WPinternals
internal QualcommPartition(byte[] Binary, uint Offset = 0) internal QualcommPartition(byte[] Binary, uint Offset = 0)
{ {
#if DEBUG #if DEBUG
System.Diagnostics.Debug.Print("Loader: " + Converter.ConvertHexToString(new SHA256Managed().ComputeHash(Binary, 0, Binary.Length), "")); System.Diagnostics.Debug.Print("Loader: " + Converter.ConvertHexToString(SHA256.HashData(Binary.AsSpan(0, Binary.Length)), ""));
#endif #endif
this.Binary = Binary; this.Binary = Binary;
byte[] LongHeaderPattern = new byte[] { 0xD1, 0xDC, 0x4B, 0x84, 0x34, 0x10, 0xD7, 0x73, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] LongHeaderPattern = [0xD1, 0xDC, 0x4B, 0x84, 0x34, 0x10, 0xD7, 0x73, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
byte[] LongHeaderMask = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; byte[] LongHeaderMask = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
if (ByteOperations.FindPattern(Binary, Offset, 4, new byte[] { 0x7F, 0x45, 0x4C, 0x46 }, new byte[] { 0x00, 0x00, 0x00, 0x00 }, null) == 0) if (ByteOperations.FindPattern(Binary, Offset, 4, [0x7F, 0x45, 0x4C, 0x46], [0x00, 0x00, 0x00, 0x00], null) == 0)
{ {
// This is an ELF image // This is an ELF image
// First program header is a reference to the elf-header // First program header is a reference to the elf-header
@@ -128,46 +129,59 @@ namespace WPinternals
CertificatesSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X1C); CertificatesSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X1C);
CertificatesOffset = CertificatesAddress - ImageAddress + ImageOffset; CertificatesOffset = CertificatesAddress - ImageAddress + ImageOffset;
uint CurrentCertificateOffset = CertificatesOffset; using MemoryStream fileStream = new(Binary);
uint CertificateSize = 0; using BinaryReader reader = new(fileStream);
while (CurrentCertificateOffset < (CertificatesOffset + CertificatesSize))
{
if ((Binary[CurrentCertificateOffset] == 0x30) && (Binary[CurrentCertificateOffset + 1] == 0x82))
{
CertificateSize = (uint)(Binary[CurrentCertificateOffset + 2] * 0x100) + Binary[CurrentCertificateOffset + 3] + 4; // Big endian!
if ((CurrentCertificateOffset + CertificateSize) == (CertificatesOffset + CertificatesSize)) List<byte[]> Signatures = [];
{ uint LastOffset = 0;
// This is the last certificate. So this is the root key.
RootKeyHash = new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize);
#if DEBUG for (uint i = 0; i < fileStream.Length - 6; i++)
System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
#endif
}
#if DEBUG
else
{ {
System.Diagnostics.Debug.Print("Cert: " + Converter.ConvertHexToString(new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize), "")); fileStream.Seek(i, SeekOrigin.Begin);
}
#endif
CurrentCertificateOffset += CertificateSize;
}
else
{
if ((RootKeyHash == null) && (CurrentCertificateOffset > CertificatesOffset))
{
CurrentCertificateOffset -= CertificateSize;
// This is the last certificate. So this is the root key. ushort offset0 = reader.ReadUInt16();
RootKeyHash = new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize); short offset1 = (short)((reader.ReadByte() << 8) | reader.ReadByte());
ushort offset2 = reader.ReadUInt16();
#if DEBUG if (offset0 == 0x8230 && offset1 >= 0 && offset2 == 0x8230)
System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, "")); {
#endif uint CertificateSize = (uint)offset1 + 4; // Header Size is 4
}
bool IsCertificatePartOfExistingChain = LastOffset == 0 || LastOffset == i;
if (!IsCertificatePartOfExistingChain)
{
break; break;
} }
LastOffset = i + CertificateSize;
fileStream.Seek(i, SeekOrigin.Begin);
Signatures.Add(reader.ReadBytes((int)CertificateSize));
}
}
if (Signatures.Count > 0)
{
byte[] RootCertificate = Signatures[^1];
for (int i = 0; i < Signatures.Count; i++)
{
if (i + 1 != Signatures.Count)
{
#if DEBUG
System.Diagnostics.Debug.Print("Cert: " + Converter.ConvertHexToString(SHA256.HashData(Signatures[i]), ""));
#endif
}
else
{
// This is the last certificate. So this is the root key.
RootKeyHash = SHA256.HashData(Signatures[i]);
#if DEBUG
System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
#endif
}
}
} }
} }
} }
+361
View File
@@ -0,0 +1,361 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace WPinternals
{
internal delegate void ReadyHandler();
internal class QualcommSahara
{
private readonly QualcommSerial Serial;
public QualcommSahara(QualcommSerial Serial)
{
Serial.EncodeCommands = false;
Serial.DecodeResponses = false;
this.Serial = Serial;
}
private static byte[] BuildCommandPacket(QualcommSaharaCommand SaharaCommand, byte[] CommandBuffer = null)
{
UInt32 CommandID = (uint)SaharaCommand;
UInt32 CommandBufferLength = 0;
if (CommandBuffer != null)
{
CommandBufferLength = (UInt32)CommandBuffer.Length;
}
UInt32 Length = 0x8u + CommandBufferLength;
byte[] Packet = new byte[Length];
ByteOperations.WriteUInt32(Packet, 0x00, CommandID);
ByteOperations.WriteUInt32(Packet, 0x04, Length);
if (CommandBuffer != null && CommandBufferLength != 0)
{
Buffer.BlockCopy(CommandBuffer, 0, Packet, 0x08, CommandBuffer.Length);
}
return Packet;
}
private static byte[] BuildHelloResponsePacket(QualcommSaharaMode SaharaMode, UInt32 ProtocolVersion = 2, UInt32 SupportedVersion = 1, UInt32 MaxPacketLength = 0 /* 0: Status OK */)
{
UInt32 Mode = (uint)SaharaMode;
// Hello packet:
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
byte[] Hello = new byte[0x28];
ByteOperations.WriteUInt32(Hello, 0x00, ProtocolVersion);
ByteOperations.WriteUInt32(Hello, 0x04, SupportedVersion);
ByteOperations.WriteUInt32(Hello, 0x08, MaxPacketLength);
ByteOperations.WriteUInt32(Hello, 0x0C, Mode);
ByteOperations.WriteUInt32(Hello, 0x10, 0);
ByteOperations.WriteUInt32(Hello, 0x14, 0);
ByteOperations.WriteUInt32(Hello, 0x18, 0);
ByteOperations.WriteUInt32(Hello, 0x1C, 0);
ByteOperations.WriteUInt32(Hello, 0x20, 0);
ByteOperations.WriteUInt32(Hello, 0x24, 0);
return BuildCommandPacket(QualcommSaharaCommand.HelloResponse, Hello);
}
private static byte[] BuildExecuteRequestPacket(UInt32 RequestID)
{
byte[] Execute = new byte[0x04];
ByteOperations.WriteUInt32(Execute, 0x00, RequestID);
return BuildCommandPacket(QualcommSaharaCommand.ExecuteRequest, Execute);
}
private static byte[] BuildExecuteDataPacket(UInt32 RequestID)
{
byte[] Execute = new byte[0x04];
ByteOperations.WriteUInt32(Execute, 0x00, RequestID);
return BuildCommandPacket(QualcommSaharaCommand.ExecuteData, Execute);
}
public byte[][] GetRKHs()
{
Serial.SendData(BuildExecuteRequestPacket(0x3));
byte[] ReadDataRequest = Serial.GetResponse(null);
UInt32 ResponseID = ByteOperations.ReadUInt32(ReadDataRequest, 0);
if (ResponseID != 0xE)
{
throw new BadConnectionException();
}
uint RKHLength = ByteOperations.ReadUInt32(ReadDataRequest, 0x0C);
Serial.SendData(BuildExecuteDataPacket(0x3));
byte[] Response = Serial.GetResponse(null, Length: (int)RKHLength);
List<byte[]> RootKeyHashes = new();
for (int i = 0; i < RKHLength / 0x20; i++)
{
RootKeyHashes.Add(Response[(i * 0x20)..((i + 1) * 0x20)]);
}
return [.. RootKeyHashes];
}
public byte[] GetRKH()
{
int Step = 0;
UInt32 Offset = 0;
UInt32 Length = 0;
try
{
Step = 1;
byte[] Hello = Serial.GetResponse([0x01, 0x00, 0x00, 0x00]);
// Incoming Hello packet:
// 00000001 = Hello command id
// xxxxxxxx = Length
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly);
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly);
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly);
Step = 2;
byte[] HelloResponse = BuildHelloResponsePacket(QualcommSaharaMode.Command);
Serial.SendData(HelloResponse);
Step = 3;
byte[] ReadDataRequest = Serial.GetResponse(null);
UInt32 ResponseID = ByteOperations.ReadUInt32(ReadDataRequest, 0);
if (ResponseID != 0xB)
{
throw new BadConnectionException();
}
Step = 4;
byte[][] RKHs = GetRKHs();
return RKHs[0];
}
catch (Exception Ex)
{
LogFile.LogException(Ex, LogType.FileAndConsole, Step.ToString() + " 0x" + Offset.ToString("X8") + " 0x" + Length.ToString("X8"));
}
return null;
}
public bool SendImage(string Path)
{
bool Result = true;
LogFile.Log("Sending programmer: " + Path, LogType.FileOnly);
int Step = 0;
UInt32 Offset = 0;
UInt32 Length = 0;
byte[] ImageBuffer = null;
try
{
Step = 1;
byte[] Hello = Serial.GetResponse([0x01, 0x00, 0x00, 0x00]);
// Incoming Hello packet:
// 00000001 = Hello command id
// xxxxxxxx = Length
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly);
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly);
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly);
Step = 2;
byte[] HelloResponse = BuildHelloResponsePacket(QualcommSaharaMode.ImageTransferPending);
Serial.SendData(HelloResponse);
Step = 3;
using FileStream FileStream = new(Path, FileMode.Open, FileAccess.Read);
while (true)
{
Step = 4;
byte[] ReadDataRequest = Serial.GetResponse(null);
UInt32 ResponseID = ByteOperations.ReadUInt32(ReadDataRequest, 0);
if (ResponseID == 4)
{
break;
}
if (ResponseID != 3)
{
Step = 5;
throw new BadConnectionException();
}
Offset = ByteOperations.ReadUInt32(ReadDataRequest, 0x0C);
Length = ByteOperations.ReadUInt32(ReadDataRequest, 0x10);
if ((ImageBuffer == null) || (ImageBuffer.Length != Length))
{
ImageBuffer = new byte[Length];
}
if (FileStream.Position != Offset)
{
FileStream.Seek(Offset, SeekOrigin.Begin);
}
Step = 6;
FileStream.Read(ImageBuffer, 0, (int)Length);
Step = 7;
Serial.SendData(ImageBuffer);
}
}
catch (Exception Ex)
{
LogFile.LogException(Ex, LogType.FileAndConsole, Step.ToString() + " 0x" + Offset.ToString("X8") + " 0x" + Length.ToString("X8"));
Result = false;
}
if (Result)
{
LogFile.Log("Programmer loaded into phone memory", LogType.FileOnly);
}
return Result;
}
public bool Handshake()
{
bool Result = true;
try
{
byte[] Hello = Serial.GetResponse([0x01, 0x00, 0x00, 0x00]);
// Incoming Hello packet:
// 00000001 = Hello command id
// xxxxxxxx = Length
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly);
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly);
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly);
byte[] HelloResponse = BuildHelloResponsePacket(QualcommSaharaMode.ImageTransferPending);
byte[] Ready = Serial.SendCommand(HelloResponse, [0x03, 0x00, 0x00, 0x00]);
}
catch
{
Result = false;
}
return Result;
}
public void ResetSahara()
{
Serial.SendCommand(BuildCommandPacket(QualcommSaharaCommand.ResetRequest), [0x08, 0x00, 0x00, 0x00]);
}
public void SwitchMode(QualcommSaharaMode Mode)
{
byte[] SwitchMode = new byte[0x04];
ByteOperations.WriteUInt32(SwitchMode, 0x00, (UInt32)Mode);
byte[] SwitchModeCommand = BuildCommandPacket(QualcommSaharaCommand.SwitchMode, SwitchMode);
byte[] ResponsePattern = null;
switch (Mode)
{
case QualcommSaharaMode.ImageTransferPending:
ResponsePattern = [0x04, 0x00, 0x00, 0x00];
break;
case QualcommSaharaMode.MemoryDebug:
ResponsePattern = [0x09, 0x00, 0x00, 0x00];
break;
case QualcommSaharaMode.Command:
ResponsePattern = [0x0B, 0x00, 0x00, 0x00];
break;
}
Serial.SendCommand(SwitchModeCommand, ResponsePattern);
}
public void StartProgrammer()
{
LogFile.Log("Starting programmer", LogType.FileAndConsole);
byte[] DoneCommand = BuildCommandPacket(QualcommSaharaCommand.DoneRequest);
bool Started = false;
int count = 0;
do
{
count++;
try
{
byte[] DoneResponse = Serial.SendCommand(DoneCommand, [0x06, 0x00, 0x00, 0x00]);
Started = true;
}
catch (BadConnectionException)
{
LogFile.Log("Problem while starting programmer. Attempting again.", LogType.FileAndConsole);
}
} while (!Started && count < 3);
if (count >= 3 && !Started)
{
LogFile.Log("Maximum number of attempts to start the programmer exceeded.", LogType.FileAndConsole);
throw new BadConnectionException();
}
LogFile.Log("Programmer being launched on phone", LogType.FileOnly);
}
public async Task<bool> LoadProgrammer(string ProgrammerPath)
{
bool SendImageResult = await Task.Run(() => SendImage(ProgrammerPath));
if (!SendImageResult)
{
return false;
}
await Task.Run(() => StartProgrammer());
return true;
}
}
}
@@ -0,0 +1,45 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
{
internal enum QualcommSaharaCommand : uint
{
HelloRequest = 0x01,
HelloResponse = 0x02,
ReadData = 0x03,
EndTransfer = 0x04,
DoneRequest = 0x05,
DoneResponse = 0x06,
ResetRequest = 0x07,
ResetResponse = 0x08,
MemoryDebug = 0x09,
MemoryRead = 0x0A,
CommandReady = 0x0B,
SwitchMode = 0x0C,
ExecuteRequest = 0x0D,
ExecuteResponse = 0x0E,
ExecuteData = 0x0F,
MemoryDebug64 = 0x10,
MemoryRead64 = 0x11,
MemoryReadData64 = 0x12,
ResetStateMachineIdentifier = 0x13
}
}
+30
View File
@@ -0,0 +1,30 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
{
internal enum QualcommSaharaMode : uint
{
ImageTransferPending = 0x00,
ImagetransferComplete = 0x01,
MemoryDebug = 0x02,
Command = 0x03
}
}
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -38,7 +38,7 @@ namespace WPinternals
{ {
CRC16 = new CRC16(0x1189, 0xFFFF, 0xFFFF); CRC16 = new CRC16(0x1189, 0xFFFF, 0xFFFF);
string[] DevicePathElements = DevicePath.Split(new char[] { '#' }); string[] DevicePathElements = DevicePath.Split(['#']);
if (string.Equals(DevicePathElements[3], "{86E0D1E0-8089-11D0-9CE4-08003E301F73}", StringComparison.CurrentCultureIgnoreCase)) if (string.Equals(DevicePathElements[3], "{86E0D1E0-8089-11D0-9CE4-08003E301F73}", StringComparison.CurrentCultureIgnoreCase))
{ {
string PortName = (string)Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\" + DevicePathElements[1] + @"\" + DevicePathElements[2] + @"\Device Parameters", "PortName", null); string PortName = (string)Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\" + DevicePathElements[1] + @"\" + DevicePathElements[2] + @"\Device Parameters", "PortName", null);
@@ -58,7 +58,10 @@ namespace WPinternals
{ {
this.USBDevice = new USBDevice(DevicePath); this.USBDevice = new USBDevice(DevicePath);
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
} }
} }
@@ -84,10 +87,10 @@ namespace WPinternals
return GetResponse(ResponsePattern); return GetResponse(ResponsePattern);
} }
internal byte[] GetResponse(byte[] ResponsePattern) internal byte[] GetResponse(byte[] ResponsePattern, int Length = 0x2000)
{ {
byte[] ResponseBuffer = new byte[0x2000]; byte[] ResponseBuffer = new byte[Length];
int Length = 0; Length = 0;
bool IsIncomplete = false; bool IsIncomplete = false;
do do
@@ -146,7 +149,10 @@ namespace WPinternals
{ {
IsIncomplete = true; IsIncomplete = true;
} }
catch { } // Will be rethrown as BadConnectionException catch (Exception ex) // Will be rethrown as BadConnectionException
{
LogFile.LogException(ex, LogType.FileOnly);
}
} }
while (IsIncomplete); while (IsIncomplete);
@@ -323,7 +329,7 @@ namespace WPinternals
public class CRC16 public class CRC16
{ {
private readonly UInt16[] ChecksumTable = private readonly UInt16[] ChecksumTable =
new UInt16[] { [
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
@@ -356,7 +362,7 @@ namespace WPinternals
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
}; ];
private readonly UInt16 Seed, FinalXor; private readonly UInt16 Seed, FinalXor;
+15 -15
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -29,11 +29,11 @@ namespace WPinternals
internal byte[] GenerateExtraSector(byte[] PartitionHeader) internal byte[] GenerateExtraSector(byte[] PartitionHeader)
{ {
UInt32? Offset = ByteOperations.FindPattern(Binary, UInt32? Offset = ByteOperations.FindPattern(Binary,
new byte[] { [
0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}, null, null); ], null, null);
if (Offset == null) if (Offset == null)
{ {
throw new BadImageFormatException(); throw new BadImageFormatException();
@@ -43,12 +43,12 @@ namespace WPinternals
byte[] FoundPattern = new byte[0x10]; byte[] FoundPattern = new byte[0x10];
Offset = ByteOperations.FindPattern(Binary, Offset = ByteOperations.FindPattern(Binary,
new byte[] { [
0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF 0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF
}, ],
new byte[] { [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF
}, ],
FoundPattern); FoundPattern);
if (Offset == null) if (Offset == null)
{ {
@@ -59,14 +59,14 @@ namespace WPinternals
UInt32 GlobalIsSecurityEnabledAddress = SharedMemoryAddress + 0x28; UInt32 GlobalIsSecurityEnabledAddress = SharedMemoryAddress + 0x28;
Offset = ByteOperations.FindPattern(Binary, Offset = ByteOperations.FindPattern(Binary,
new byte[] { [
0x01, 0xFF, 0xA0, 0xE3, 0xFF, 0xFF, 0xA0, 0xE1, 0x1C, 0xD0, 0x8D, 0xE2, 0xF0, 0x4F, 0xBD, 0xE8, 0x01, 0xFF, 0xA0, 0xE3, 0xFF, 0xFF, 0xA0, 0xE1, 0x1C, 0xD0, 0x8D, 0xE2, 0xF0, 0x4F, 0xBD, 0xE8,
0x1E, 0xFF, 0x2F, 0xE1 0x1E, 0xFF, 0x2F, 0xE1
}, ],
new byte[] { [
0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00
}, ],
null); null);
if (Offset == null) if (Offset == null)
{ {
@@ -78,7 +78,7 @@ namespace WPinternals
byte[] Sector = new byte[0x200]; byte[] Sector = new byte[0x200];
Array.Clear(Sector, 0, 0x200); Array.Clear(Sector, 0, 0x200);
byte[] Content = new byte[] { byte[] Content = [
0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0xBD, 0x02, 0x00, 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0xBD, 0x02, 0x00,
0xD8, 0x01, 0x00, 0x00, 0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x01, 0x00, 0x00, 0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xE3, 0x3C, 0x10, 0x9F, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xE3, 0x3C, 0x10, 0x9F, 0xE5,
@@ -88,11 +88,11 @@ namespace WPinternals
0x04, 0x10, 0x81, 0xE2, 0x03, 0x00, 0x50, 0xE1, 0xF9, 0xFF, 0xFF, 0xBA, 0x14, 0xF0, 0x9F, 0xE5, 0x04, 0x10, 0x81, 0xE2, 0x03, 0x00, 0x50, 0xE1, 0xF9, 0xFF, 0xFF, 0xBA, 0x14, 0xF0, 0x9F, 0xE5,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x90, 0xBF, 0x02, 0x00, 0xD0, 0xBF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x90, 0xBF, 0x02, 0x00, 0xD0, 0xBF, 0x02, 0x00,
0xA0, 0xBD, 0x02, 0x00, 0xA0, 0xBE, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 0xA0, 0xBD, 0x02, 0x00, 0xA0, 0xBE, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
}; ];
byte[] PartitionTypeGuid = new byte[] { byte[] PartitionTypeGuid = [
0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74
}; ];
Buffer.BlockCopy(Content, 0, Sector, 0, Content.Length); Buffer.BlockCopy(Content, 0, Sector, 0, Content.Length);
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -35,12 +35,12 @@ namespace WPinternals
internal byte[] Patch() internal byte[] Patch()
{ {
UInt32? PatchOffset = ByteOperations.FindPattern(Binary, UInt32? PatchOffset = ByteOperations.FindPattern(Binary,
new byte[] { [
0xFF, 0xFF, 0xFF, 0xE3, 0x01, 0x0E, 0x42, 0xE3, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1 0xFF, 0xFF, 0xFF, 0xE3, 0x01, 0x0E, 0x42, 0xE3, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1
}, ],
new byte[] { [
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}, ],
null); null);
if (PatchOffset == null) if (PatchOffset == null)
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -45,13 +45,16 @@ namespace WPinternals
Binary = FFUFile.GetPartition("SBL3"); Binary = FFUFile.GetPartition("SBL3");
} }
} }
catch { } catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
// If not succeeded, then try to parse it as raw image // If not succeeded, then try to parse it as raw image
if (Binary == null) if (Binary == null)
{ {
byte[] SBL3Pattern = new byte[] { 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] SBL3Pattern = [0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF];
byte[] SBL3Mask = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] SBL3Mask = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF];
UInt32? Offset = ByteOperations.FindPatternInFile(FileName, SBL3Pattern, SBL3Mask, out byte[] SBL3Header); UInt32? Offset = ByteOperations.FindPatternInFile(FileName, SBL3Pattern, SBL3Mask, out byte[] SBL3Header);
@@ -72,7 +75,7 @@ namespace WPinternals
internal byte[] Patch() internal byte[] Patch()
{ {
UInt32? PatchOffset = ByteOperations.FindPattern(Binary, UInt32? PatchOffset = ByteOperations.FindPattern(Binary,
new byte[] { 0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1 }, [0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1],
null, null); null, null);
if (PatchOffset == null) if (PatchOffset == null)
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -256,7 +256,7 @@ namespace WPinternals
// but the sections that are used in Windows Phone EFI's all have a header of 4 bytes. // but the sections that are used in Windows Phone EFI's all have a header of 4 bytes.
if (SectionType == 0x15) if (SectionType == 0x15)
{ {
CurrentEFI.Name = ByteOperations.ReadUnicodeString(DecompressedImage, DecompressedSectionHeaderOffset + 0x04, SectionSize - 0x04).TrimEnd(new char[] { (char)0, ' ' }); CurrentEFI.Name = ByteOperations.ReadUnicodeString(DecompressedImage, DecompressedSectionHeaderOffset + 0x04, SectionSize - 0x04).TrimEnd([(char)0, ' ']);
} }
else if ((SectionType == 0x10) || (SectionType == 0x19)) else if ((SectionType == 0x10) || (SectionType == 0x19))
{ {
@@ -599,8 +599,8 @@ namespace WPinternals
ClearEfiChecksum(SecurityDxe); ClearEfiChecksum(SecurityDxe);
UInt32? PatchOffset = ByteOperations.FindPattern(SecurityDxe, UInt32? PatchOffset = ByteOperations.FindPattern(SecurityDxe,
new byte[] { 0xF0, 0x41, 0x2D, 0xE9, 0xFF, 0xFF, 0xB0, 0xE1, 0x28, 0xD0, 0x4D, 0xE2, 0xFF, 0xFF, 0xA0, 0xE1, 0x00, 0x00, 0xFF, 0x13, 0x20, 0xFF, 0xA0, 0xE3 }, [0xF0, 0x41, 0x2D, 0xE9, 0xFF, 0xFF, 0xB0, 0xE1, 0x28, 0xD0, 0x4D, 0xE2, 0xFF, 0xFF, 0xA0, 0xE1, 0x00, 0x00, 0xFF, 0x13, 0x20, 0xFF, 0xA0, 0xE3],
new byte[] { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00 }, [0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00],
null); null);
if (PatchOffset == null) if (PatchOffset == null)
@@ -616,8 +616,8 @@ namespace WPinternals
ClearEfiChecksum(SecurityServicesDxe); ClearEfiChecksum(SecurityServicesDxe);
PatchOffset = ByteOperations.FindPattern(SecurityServicesDxe, PatchOffset = ByteOperations.FindPattern(SecurityServicesDxe,
new byte[] { 0x10, 0xFF, 0xFF, 0xE5, 0x80, 0xFF, 0x10, 0xE3, 0xFF, 0xFF, 0xFF, 0x0A }, [0x10, 0xFF, 0xFF, 0xE5, 0x80, 0xFF, 0x10, 0xE3, 0xFF, 0xFF, 0xFF, 0x0A],
new byte[] { 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00 }, [0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00],
null); null);
if (PatchOffset == null) if (PatchOffset == null)
@@ -628,8 +628,8 @@ namespace WPinternals
ByteOperations.WriteUInt8(SecurityServicesDxe, (UInt32)PatchOffset + 0x0B, 0xEA); ByteOperations.WriteUInt8(SecurityServicesDxe, (UInt32)PatchOffset + 0x0B, 0xEA);
PatchOffset = ByteOperations.FindPattern(SecurityServicesDxe, PatchOffset = ByteOperations.FindPattern(SecurityServicesDxe,
new byte[] { 0x11, 0xFF, 0xFF, 0xE5, 0x40, 0xFF, 0x10, 0xE3, 0xFF, 0xFF, 0xFF, 0x0A }, [0x11, 0xFF, 0xFF, 0xE5, 0x40, 0xFF, 0x10, 0xE3, 0xFF, 0xFF, 0xFF, 0x0A],
new byte[] { 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00 }, [0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00],
null); null);
if (PatchOffset == null) if (PatchOffset == null)
@@ -0,0 +1,399 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using System.Linq;
namespace WPinternals
{
internal class LumiaBootManagerAppModel : NokiaFlashModel
{
internal readonly LumiaBootManagerPhoneInfo BootManagerInfo = new();
internal enum SecureBootKeyType : byte
{
Retail = 0,
Engineering = 1
}
//
// Not valid commands
//
/* NOK */
private const string Signature = "NOK";
/* NOKX */
private const string ExtendedMessageSignature = $"{Signature}X";
/* NOKXB */
private const string LumiaBootManagerExtendedMessageSignature = $"{ExtendedMessageSignature}B";
//
// Normal commands
//
/* NOKA */
private const string ContinueBootSignature = $"{Signature}A";
/* NOKB */
private const string RPMBSignature = $"{Signature}B";
/* NOKC */
private const string BatteryStatusSignature = $"{Signature}C";
/* NOKD */
private const string DisableTimeoutsSignature = $"{Signature}D";
/* NOKI */
private const string HelloSignature = $"{Signature}I";
/* NOKM */
private const string RebootToMassStorageSignature = $"{Signature}M";
/* NOKP */
private const string RebootToPhoneInfoAppSignature = $"{Signature}P";
/* NOKR */
private const string RebootSignature = $"{Signature}R";
/* NOKS */
private const string RebootToFlashAppSignature = $"{Signature}S";
/* NOKT */
private const string GetGPTSignature = $"{Signature}T";
/* NOKV */
private const string InfoQuerySignature = $"{Signature}V";
/* NOKW */
private const string WriteBootFlagFileSignature = $"{Signature}W";
/* NOKY */
private const string MMOSStartCommandSignature = $"{Signature}Y";
/* NOKZ */
private const string ShutdownSignature = $"{Signature}Z";
//
// Lumia Boot Manager extended commands
//
/* NOKXBD */
private const string PlatformSecureBootEnableSignature = $"{LumiaBootManagerExtendedMessageSignature}D";
/* NOKXBH */
private const string WriteRootCertificateHashSignature = $"{LumiaBootManagerExtendedMessageSignature}H";
/* NOKXBK */
private const string UEFIKeysProvisionSignature = $"{LumiaBootManagerExtendedMessageSignature}K";
/* NOKXBR */
private const string ReadManufacturingStateSignature = $"{LumiaBootManagerExtendedMessageSignature}R";
/* NOKXBU */
private const string FlushVariablesSignature = $"{LumiaBootManagerExtendedMessageSignature}U";
/* NOKXBW */
private const string WriteManufacturingStateSignature = $"{LumiaBootManagerExtendedMessageSignature}W";
public LumiaBootManagerAppModel(string DevicePath) : base(DevicePath)
{
}
internal void ContinueBoot()
{
LogFile.Log("Continue boot...");
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, ContinueBootSignature);
ExecuteRawVoidMethod(Request);
}
internal LumiaBootManagerPhoneInfo ReadPhoneInfo(bool ExtendedInfo = true)
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
// NOKV = Info Query
bool PhoneInfoLogged = BootManagerInfo.State != PhoneInfoState.Empty;
ReadPhoneInfoBootManager();
LumiaBootManagerPhoneInfo Result = BootManagerInfo;
if (!PhoneInfoLogged)
{
Result.Log(LogType.FileOnly);
}
return Result;
}
internal LumiaBootManagerPhoneInfo ReadPhoneInfoBootManager()
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
// NOKV = Info Query
LumiaBootManagerPhoneInfo Result = BootManagerInfo;
if (Result.State == PhoneInfoState.Empty)
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
{
Result.App = (FlashAppType)Response[5];
switch (Result.App)
{
case FlashAppType.BootManager:
Result.BootManagerProtocolVersionMajor = Response[6];
Result.BootManagerProtocolVersionMinor = Response[7];
Result.BootManagerVersionMajor = Response[8];
Result.BootManagerVersionMinor = Response[9];
break;
}
byte SubblockCount = Response[10];
int SubblockOffset = 11;
for (int i = 0; i < SubblockCount; i++)
{
byte SubblockID = Response[SubblockOffset + 0x00];
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
UInt16 SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
int SubblockPayloadOffset = SubblockOffset + 3;
byte SubblockVersion;
switch (SubblockID)
{
case 0x01:
Result.TransferSize = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
break;
case 0x04:
Result.FlashAppProtocolVersionMajor = Response[SubblockPayloadOffset + 0x00];
Result.FlashAppProtocolVersionMinor = Response[SubblockPayloadOffset + 0x01];
Result.FlashAppVersionMajor = Response[SubblockPayloadOffset + 0x02];
Result.FlashAppVersionMinor = Response[SubblockPayloadOffset + 0x03];
break;
case 0x1F:
Result.MmosOverUsbSupported = Response[SubblockPayloadOffset] == 1;
break;
case 0x20:
// CRC header info
break;
}
SubblockOffset += SubblockLength + 3;
}
}
Result.State = PhoneInfoState.Basic;
}
return Result;
}
internal GPT ReadGPT()
{
// If this function is used with a locked BootMgr v1,
// then the mode-switching should be done outside this function,
// because the context-switches that are used here are not supported on BootMgr v1.
// Only works in BootLoader-mode or on unlocked bootloaders in Flash-mode!!
byte[] Request = new byte[0x04];
const string Header = GetGPTSignature;
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
}
byte[] GPTBuffer = new byte[Buffer.Length - 0x208];
System.Buffer.BlockCopy(Buffer, 0x208, GPTBuffer, 0, 0x4200);
return new GPT(GPTBuffer); // NOKT message header and MBR are ignored
}
internal byte[] GetGptChunk(UInt32 Size) // TODO!
{
// This function is also used to generate a dummy chunk to flash for testing.
// The dummy chunk will contain the GPT, so it can be flashed to the first sectors for testing.
byte[] GPTChunk = new byte[Size];
byte[] Request = new byte[0x04];
const string Header = "NOKT";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
}
System.Buffer.BlockCopy(Buffer, 8, GPTChunk, 0, 0x4400);
return GPTChunk;
}
internal void ProvisionSecureBootKeys(SecureBootKeyType KeyType) // Only for Flashmode, not BootManager mode.
{
byte[] Request = new byte[8];
ByteOperations.WriteAsciiString(Request, 0, UEFIKeysProvisionSignature);
Request[6] = 0; // Options
Request[7] = (byte)KeyType;
byte[] Response = ExecuteRawMethod(Request);
UInt32 Status = ByteOperations.ReadUInt32(Response, 6);
if (Status != 0)
{
ThrowFlashError((int)Status);
}
}
private void ThrowFlashError(int ErrorCode)
{
string SubMessage = ErrorCode switch
{
0x0008 => "Unsupported protocol / Invalid options",
0x000F => "Invalid sub block count",
0x0010 => "Invalid sub block length",
0x0012 => "Authentication required",
0x000E => "Invalid sub block type",
0x0013 => "Failed async message",
0x1000 => "Invalid header type",
0x1001 => "FFU header contain unknown extra data",
0x0001 => "Couldn't allocate memory",
0x1106 => "Security header validation failed",
0x1105 => "Invalid hash table size",
0x1104 => "Invalid catalog size",
0x1103 => "Invalid chunk size",
0x1102 => "Unsupported algorithm",
0x1101 => "Invalid struct size",
0x1100 => "Invalid signature",
0x1202 => "Invalid struct size",
0x1203 => "Unsupported algorithm",
0x1204 => "Invalid chunk size",
0x1005 => "Data not aligned correctly",
0x0009 => "Locate protocol failed",
0x1003 => "Hash mismatch",
0x1006 => "Couldn't find hash from security header for index",
0x1004 => "Security header import missing / All FFU headers have not been imported",
0x1304 => "Invalid platform ID",
0x1307 => "Invalid write descriptor info",
0x1306 => "Invalid write descriptor info",
0x1305 => "Invalid block size",
0x1303 => "Unsupported FFU version",
0x1302 => "Unsupported struct version",
0x1301 => "Invalid update type",
0x100B => "Too much payload data, all data has already been written",
0x1008 => "Internal error",
0x1007 => "Payload data does not contain all data",
0x0004 => "Flash write failed",
0x000D => "Flash verify failed",
0x0002 => "Flash read failed",
_ => "Unknown error",
};
WPinternalsException Ex = new("Flash failed!");
Ex.SubMessage = "Error 0x" + ErrorCode.ToString("X4") + ": " + SubMessage;
throw Ex;
}
public void Shutdown()
{
byte[] Request = new byte[4];
const string Header = ShutdownSignature;
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
ExecuteRawMethod(Request);
}
internal void ResetPhone()
{
LogFile.Log("Rebooting phone", LogType.FileAndConsole);
try
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootSignature);
ExecuteRawVoidMethod(Request);
}
catch
{
LogFile.Log("Sending reset-request failed", LogType.FileOnly);
LogFile.Log("Assuming automatic reset already in progress", LogType.FileOnly);
}
}
internal void ResetPhoneToFlashMode()
{
LumiaBootManagerPhoneInfo info = ReadPhoneInfoBootManager();
bool ModernFlashApp = info.BootManagerVersionMajor >= 2;
// This only works when the phone is in BootMgr mode. If it is already in FlashApp, it will not reboot. It only makes the phone unresponsive.
LogFile.Log("Rebooting phone to Flash mode...");
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToFlashAppSignature);
ExecuteRawVoidMethod(Request);
if (ModernFlashApp)
{
DisableRebootTimeOut();
info.App = FlashAppType.FlashApp;
RaiseInterfaceChanged(PhoneInterfaces.Lumia_Flash);
}
}
internal void SwitchToPhoneInfoAppContextLegacy()
{
LumiaBootManagerPhoneInfo info = ReadPhoneInfoBootManager();
bool ModernFlashApp = info.BootManagerVersionMajor >= 2;
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToPhoneInfoAppSignature);
ExecuteRawVoidMethod(Request);
if (ModernFlashApp)
{
DisableRebootTimeOut();
info.App = FlashAppType.PhoneInfoApp;
RaiseInterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo);
}
}
internal void RebootToFlashApp()
{
LumiaBootManagerPhoneInfo info = ReadPhoneInfoBootManager();
bool ModernFlashApp = info.BootManagerVersionMajor >= 2;
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToFlashAppSignature); // This will let the phone charge
ExecuteRawVoidMethod(Request); // On phone with bootloader Spec A this triggers a reboot, so DisableRebootTimeOut() cannot be called immediately.
if (ModernFlashApp)
{
DisableRebootTimeOut();
info.App = FlashAppType.FlashApp;
RaiseInterfaceChanged(PhoneInterfaces.Lumia_Flash);
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,239 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace WPinternals
{
internal class LumiaPhoneInfoAppModel : NokiaFlashModel
{
internal readonly LumiaPhoneInfoAppPhoneInfo PhoneInfoAppInfo = new();
//
// Not valid commands
//
/* NOK */
private const string Signature = "NOK";
/* NOKX */
private const string ExtendedMessageSignature = $"{Signature}X";
/* NOKXP */
private const string PhoneInfoAppExtendedMessageSignature = $"{ExtendedMessageSignature}P";
//
// Normal commands
//
/* NOKA */
private const string ContinueBootSignature = $"{Signature}A";
/* NOKD */
private const string DisableTimeoutsSignature = $"{Signature}D";
/* NOKH */
private const string GetPhoneInfoSignature = $"{Signature}H";
/* NOKI */
private const string HelloSignature = $"{Signature}I";
/* NOKV */
private const string InfoQuerySignature = $"{Signature}V";
//
// Phone Info App extended commands
//
/* NOKXPH */
private const string GetVariableSignature = $"{PhoneInfoAppExtendedMessageSignature}H";
public LumiaPhoneInfoAppModel(string DevicePath) : base(DevicePath)
{
}
internal void ContinueBoot()
{
LogFile.Log("Continue boot...");
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, ContinueBootSignature);
ExecuteRawVoidMethod(Request);
}
internal string GetPhoneInfo()
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
// NOKV = Info Query
if (PhoneInfoAppInfo.PhoneInfoAppVersionMajor >= 2)
{
return null;
}
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, GetPhoneInfoSignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response == null) || (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU"))
{
throw new NotSupportedException();
}
UInt16 Length = BigEndian.ToUInt16(Response, 0x04);
string PhoneInfoData = ByteOperations.ReadAsciiString(Response, 0x8, Length);
return PhoneInfoData;
}
internal LumiaPhoneInfoAppPhoneInfo ReadPhoneInfo(bool ExtendedInfo = true)
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
// NOKV = Info Query
bool PhoneInfoLogged = PhoneInfoAppInfo.State != PhoneInfoState.Empty;
ReadPhoneInfoPhoneInfoApp();
LumiaPhoneInfoAppPhoneInfo Result = PhoneInfoAppInfo;
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
{
try
{
if (Result.PhoneInfoAppProtocolVersionMajor >= 2)
{
Result.Type = ReadPhoneInfoVariable("TYPE");
Result.ProductCode = ReadPhoneInfoVariable("CTR");
Result.Imei = ReadPhoneInfoVariable("IMEI");
}
else
{
/*
* Version: 1.1.1.3
* TYPE: RM-885
* BTR: 059R0M0
* LPSN: ...
* HWID: 1000
* CTR: 059S4B1
* MC: 0205354
* IMEI: ...
*/
string PhoneInfoData = GetPhoneInfo();
if (!string.IsNullOrEmpty(PhoneInfoData))
{
string[] Variables = PhoneInfoData.Split("\n");
Dictionary<string, string> FormattedVariables = [];
foreach (string Variable in Variables)
{
if (!Variable.Contains(":"))
{
continue;
}
FormattedVariables.Add(Variable.Split(":")[0].Trim(), Variable.Split(":")[1].Trim());
}
Result.Type = FormattedVariables["TYPE"];
Result.ProductCode = FormattedVariables["CTR"];
Result.Imei = FormattedVariables["IMEI"];
}
}
}
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
Result.State = PhoneInfoState.Extended;
}
if (!PhoneInfoLogged)
{
Result.Log(LogType.FileOnly);
}
return Result;
}
internal LumiaPhoneInfoAppPhoneInfo ReadPhoneInfoPhoneInfoApp()
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
// NOKV = Info Query
LumiaPhoneInfoAppPhoneInfo Result = PhoneInfoAppInfo;
if (Result.State == PhoneInfoState.Empty)
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
{
Result.App = (FlashAppType)Response[5];
switch (Result.App)
{
case FlashAppType.PhoneInfoApp:
Result.PhoneInfoAppProtocolVersionMajor = Response[6];
Result.PhoneInfoAppProtocolVersionMinor = Response[7];
Result.PhoneInfoAppVersionMajor = Response[8];
Result.PhoneInfoAppVersionMinor = Response[9];
break;
}
byte SubblockCount = Response[10];
int SubblockOffset = 11;
for (int i = 0; i < SubblockCount; i++)
{
byte SubblockID = Response[SubblockOffset + 0x00];
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
UInt16 SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
int SubblockPayloadOffset = SubblockOffset + 3;
byte SubblockVersion;
switch (SubblockID)
{
case 0x20:
// CRC header info
break;
}
SubblockOffset += SubblockLength + 3;
}
}
Result.State = PhoneInfoState.Basic;
}
return Result;
}
internal string ReadPhoneInfoVariable(string VariableName)
{
// This function assumes the phone is in Phone Info App context
byte[] Request = new byte[16];
ByteOperations.WriteAsciiString(Request, 0, GetVariableSignature + VariableName + "\0"); // BTR or CTR, CTR is public ProductCode
byte[] Response = ExecuteRawMethod(Request);
UInt16 Length = BigEndian.ToUInt16(Response, 6);
return ByteOperations.ReadAsciiString(Response, 8, Length).Trim([' ', '\0']);
}
internal string ReadProductCode()
{
string Result = ReadPhoneInfoVariable("CTR");
return Result;
}
}
}
@@ -0,0 +1,241 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace WPinternals
{
internal delegate void InterfaceChangedHandler(PhoneInterfaces NewInterface, string DevicePath);
internal class NokiaFlashModel : NokiaPhoneModel
{
private string _devicePath;
private readonly CommonPhoneInfo CommonInfo = new();
internal event InterfaceChangedHandler InterfaceChanged = delegate { };
//
// Not valid commands
//
/* NOK */
private const string Signature = "NOK";
/* NOKX */
private const string ExtendedMessageSignature = $"{Signature}X";
/* NOKXC */
private const string CommonExtendedMessageSignature = $"{ExtendedMessageSignature}C";
//
// Common extended commands
//
/* NOKXCB */
private const string SwitchModeSignature = $"{CommonExtendedMessageSignature}B";
/* NOKXCE */
private const string EchoSignature = $"{CommonExtendedMessageSignature}E";
public NokiaFlashModel(string DevicePath) : base(DevicePath)
{
_devicePath = DevicePath;
}
internal void SwitchToBootManagerContext(bool DisableTimeOut = true)
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}B");
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SwitchToBootManagerContext: Error 0x" + Error.ToString("X4"));
}
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Bootloader, _devicePath);
}
}
internal void SwitchToPhoneInfoAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "P");
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SwitchToPhoneInfoAppContext: Error 0x" + Error.ToString("X4"));
}
if (ModernFlashApp)
{
DisableRebootTimeOut();
CommonInfo.App = FlashAppType.PhoneInfoApp;
InterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo, _devicePath);
}
}
internal void SwitchToMmosContext()
{
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}A");
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SwitchToPhoneInfoAppContext: Error 0x" + Error.ToString("X4"));
}
}
internal void SwitchToFlashAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}F"); // This will stop charging the phone
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SwitchToFlashAppContext: Error 0x" + Error.ToString("X4"));
}
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Flash, _devicePath);
}
}
//
// Normal commands
//
/* NOKD */
private const string DisableTimeoutsSignature = $"{Signature}D";
/* NOKI */
private const string HelloSignature = $"{Signature}I";
/* NOKV */
private const string InfoQuerySignature = $"{Signature}V";
internal FlashAppType GetFlashAppType()
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response == null) || (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU"))
{
throw new NotSupportedException();
}
return (FlashAppType)Response[5];
}
internal CommonPhoneInfo ReadPhoneInfoCommon()
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
// NOKV = Info Query
CommonPhoneInfo Result = CommonInfo;
if (Result.State == PhoneInfoState.Empty)
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
{
Result.App = (FlashAppType)Response[5];
Result.ProtocolVersionMajor = Response[6];
Result.ProtocolVersionMinor = Response[7];
Result.VersionMajor = Response[8];
Result.VersionMinor = Response[9];
}
Result.State = PhoneInfoState.Basic;
}
return Result;
}
public void DisableRebootTimeOut()
{
byte[] Request = new byte[4];
const string Header = DisableTimeoutsSignature;
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
ExecuteRawMethod(Request);
}
internal void Hello()
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, HelloSignature);
byte[] Response = ExecuteRawMethod(Request);
if (Response == null)
{
throw new BadConnectionException();
}
if (ByteOperations.ReadAsciiString(Response, 0, 4) != HelloSignature)
{
throw new WPinternalsException("Bad response from phone!", "The phone did not answer properly to the Hello message sent.");
}
}
internal void RaiseInterfaceChanged(PhoneInterfaces NewInterface)
{
InterfaceChanged(NewInterface, _devicePath);
}
}
}
@@ -0,0 +1,34 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
{
internal class UefiSecurityStatusResponse
{
public byte IsTestDevice;
public bool PlatformSecureBootStatus;
public bool SecureFfuEfuseStatus;
public bool DebugStatus;
public bool RdcStatus;
public bool AuthenticationStatus;
public bool UefiSecureBootStatus;
public bool CryptoHardwareKey;
}
}
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
Copyright(c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda Copyright(c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files(the "Software"), copy of this software and associated documentation files(the "Software"),

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

@@ -10,7 +10,7 @@ using System.Windows;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WPinternals")] [assembly: AssemblyProduct("WPinternals")]
[assembly: AssemblyCopyright("Copyright © 2018-2019")] [assembly: AssemblyCopyright("Copyright © 2018-2023")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@@ -47,5 +47,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.9.*")] [assembly: AssemblyVersion("3.0.*")]
// [assembly: AssemblyFileVersion("1.0.0.0")] // [assembly: AssemblyFileVersion("1.0.0.0")]

Some files were not shown because too many files have changed in this diff Show More