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
strategy:
matrix:
architecture: [x86, x64]
architecture: [x86, x64, arm64]
platform: [win]
steps:
- name: Checkout
@@ -20,7 +20,7 @@ jobs:
- name: Install .NET SDK
uses: actions/setup-dotnet@v1
with:
dotnet-version: "5.0.400"
dotnet-version: "8.0.x"
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
+1 -1
View File
@@ -1,6 +1,6 @@
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
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 =
{
[
"BT2",
"BT4",
};
];
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
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
// 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
// copy of this software and associated documentation files (the "Software"),
@@ -83,9 +83,13 @@ namespace WPinternals
{
FFU FFU = null;
PhoneNotifierViewModel Notifier;
NokiaFlashModel FlashModel;
LumiaFlashAppModel FlashModel;
LumiaBootManagerAppModel BootMgrModel;
LumiaPhoneInfoAppModel PhoneInfoModel;
NokiaPhoneModel NormalModel;
PhoneInfo Info;
LumiaFlashAppPhoneInfo FlashInfo;
LumiaPhoneInfoAppPhoneInfo PhoneInfo;
LumiaBootManagerPhoneInfo BootManagerInfo;
string ProductType;
string ProductCode;
string OperatorCode;
@@ -114,7 +118,7 @@ namespace WPinternals
return;
}
switch (args[1].ToLower().TrimStart(new char[] { '-', '/' }))
switch (args[1].ToLower().TrimStart(['-', '/']))
{
#if DEBUG
case "test":
@@ -182,23 +186,14 @@ namespace WPinternals
Notifier = new PhoneNotifierViewModel();
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)
{
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();
}
catch (Exception Ex)
@@ -221,11 +216,14 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
Directory.CreateDirectory(Path.GetDirectoryName(args[2]));
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
GPT GPT = BootMgrModel.ReadGPT(); // May throw NotSupportedException
string DirPath = Path.GetDirectoryName(args[2]);
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{
Directory.CreateDirectory(DirPath);
}
GPT.WritePartitions(args[2]);
FlashModel.SwitchToFlashAppContext();
Notifier.Stop();
}
catch (Exception Ex)
@@ -237,6 +235,35 @@ namespace WPinternals
LogFile.EndAction("BackupGPT");
}
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":
if (args.Length < 3)
{
@@ -248,14 +275,13 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
byte[] GptChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
byte[] GptChunk = BootMgrModel.GetGptChunk(0x20000);
GPT GPT = new(GptChunk);
string Xml = File.ReadAllText(args[2]);
GPT.MergePartitions(Xml, false);
GPT.Rebuild();
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(Notifier, null, false, false, 0, GptChunk, true, true);
FlashModel.SwitchToFlashAppContext();
Notifier.Stop();
}
catch (Exception Ex)
@@ -285,7 +311,10 @@ namespace WPinternals
s = new FileStream(args[3], FileMode.Open, FileAccess.Read);
Archive = new ZipArchive(s);
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
if (Archive == null)
{
@@ -393,7 +422,11 @@ namespace WPinternals
};
}
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);
}
break;
@@ -512,9 +545,9 @@ namespace WPinternals
try
{
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
FFU ProfileFFU = null;
FFU CurrentFFU;
@@ -527,7 +560,7 @@ namespace WPinternals
string PlatformID = CurrentFFU.PlatformID;
// 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;
}
@@ -536,7 +569,7 @@ namespace WPinternals
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
? 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.");
@@ -661,9 +694,9 @@ namespace WPinternals
LogFile.Log("Command: Show phone info", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
Notifier.Stop();
break;
case "unlockbootloader":
@@ -673,9 +706,9 @@ namespace WPinternals
LogFile.Log("Command: Unlock Bootloader", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
FFU ProfileFFU = null;
FFU SupportedFFU = null;
@@ -689,7 +722,7 @@ namespace WPinternals
string PlatformID = CurrentFFU.PlatformID;
// 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;
}
@@ -704,7 +737,7 @@ namespace WPinternals
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
? 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.");
@@ -746,9 +779,9 @@ namespace WPinternals
LogFile.Log("Custom ROM: " + CustomRomPath, LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
LogFile.Log("Preparing to flash Custom ROM", LogType.FileAndConsole);
await LumiaV2UnlockBootViewModel.LumiaV2FlashArchive(Notifier, CustomRomPath);
LogFile.Log("Custom ROM flashed successfully", LogType.FileAndConsole);
@@ -777,11 +810,11 @@ namespace WPinternals
LogFile.Log("FFU file: " + FFUPath, LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
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);
Notifier.Stop();
}
@@ -1243,11 +1276,55 @@ namespace WPinternals
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
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;
Info = FlashModel.ReadPhoneInfo();
ProductCode = Info.ProductCode;
(Notifier.CurrentModel as LumiaBootManagerAppModel).SwitchToPhoneInfoAppContext();
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
{
@@ -1408,11 +1485,19 @@ namespace WPinternals
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;
Info = FlashModel.ReadPhoneInfo();
ProductType = Info.Type;
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
//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
{
@@ -1519,11 +1604,19 @@ namespace WPinternals
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
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;
Info = FlashModel.ReadPhoneInfo();
ProductCode = Info.ProductCode;
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
//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
{
@@ -1968,6 +2061,7 @@ namespace WPinternals
LogFile.Log("WPinternals -ClearNV", LogType.ConsoleOnly);
LogFile.Log("WPinternals -ReadGPT", 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 -MergeGPT <Path to input-xml-file> <Path to input-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));
}
return result.ToArray();
return [.. result];
}
/// <summary>
@@ -31,15 +31,15 @@ namespace DiscUtils.Fat
private const byte SpaceByte = 0x20;
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 =
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 =
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;
@@ -33,10 +33,10 @@ namespace DiscUtils.Fat
{
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)
@@ -80,22 +80,22 @@ namespace DiscUtils.Fat
{
// see http://home.teleport.com/~brainy/lfn.htm
// NOTE: we assume ordinals are ok here.
char[] chars = new char[13];
chars[0] = (char)((256 * buffer[2]) + buffer[1]);
chars[1] = (char)((256 * buffer[4]) + buffer[3]);
chars[2] = (char)((256 * buffer[6]) + buffer[5]);
chars[3] = (char)((256 * buffer[8]) + buffer[7]);
chars[4] = (char)((256 * buffer[10]) + buffer[9]);
chars[5] = (char)((256 * buffer[15]) + buffer[14]);
chars[6] = (char)((256 * buffer[17]) + buffer[16]);
chars[7] = (char)((256 * buffer[19]) + buffer[18]);
chars[8] = (char)((256 * buffer[21]) + buffer[20]);
chars[9] = (char)((256 * buffer[23]) + buffer[22]);
chars[10] = (char)((256 * buffer[25]) + buffer[24]);
chars[11] = (char)((256 * buffer[29]) + buffer[28]);
chars[12] = (char)((256 * buffer[31]) + buffer[30]);
char[] chars =
[
(char)((256 * buffer[2]) + buffer[1]),
(char)((256 * buffer[4]) + buffer[3]),
(char)((256 * buffer[6]) + buffer[5]),
(char)((256 * buffer[8]) + buffer[7]),
(char)((256 * buffer[10]) + buffer[9]),
(char)((256 * buffer[15]) + buffer[14]),
(char)((256 * buffer[17]) + buffer[16]),
(char)((256 * buffer[19]) + buffer[18]),
(char)((256 * buffer[21]) + buffer[20]),
(char)((256 * buffer[23]) + buffer[22]),
(char)((256 * buffer[25]) + buffer[24]),
(char)((256 * buffer[29]) + buffer[28]),
(char)((256 * buffer[31]) + buffer[30]),
];
string chunk = new(chars);
int zero = chunk.IndexOf('\0');
return zero >= 0 ? chunk.Substring(0, zero) : chunk;
@@ -201,7 +201,7 @@ namespace DiscUtils.Fat
}
}
return dirs.ToArray();
return [.. dirs];
}
public DirectoryEntry[] GetFiles()
@@ -215,7 +215,7 @@ namespace DiscUtils.Fat
}
}
return files.ToArray();
return [.. files];
}
public DirectoryEntry GetEntry(long id)
@@ -1258,7 +1258,7 @@ namespace DiscUtils.Fat
dirs.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
}
return dirs.ToArray();
return [.. dirs];
}
/// <summary>
@@ -1275,7 +1275,7 @@ namespace DiscUtils.Fat
List<string> dirs = new();
DoSearch(dirs, path, re, searchOption == SearchOption.AllDirectories, true, false);
return dirs.ToArray();
return [.. dirs];
}
/// <summary>
@@ -1294,7 +1294,7 @@ namespace DiscUtils.Fat
files.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
}
return files.ToArray();
return [.. files];
}
/// <summary>
@@ -1311,7 +1311,7 @@ namespace DiscUtils.Fat
List<string> results = new();
DoSearch(results, path, re, searchOption == SearchOption.AllDirectories, false, true);
return results.ToArray();
return [.. results];
}
/// <summary>
@@ -1330,7 +1330,7 @@ namespace DiscUtils.Fat
result.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
}
return result.ToArray();
return [.. result];
}
/// <summary>
@@ -1356,7 +1356,7 @@ namespace DiscUtils.Fat
}
}
return result.ToArray();
return [.. result];
}
/// <summary>
@@ -1915,9 +1915,7 @@ namespace DiscUtils.Fat
throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "The directory '{0}' was not found", path));
}
DirectoryEntry[] entries = dir.Entries;
foreach (DirectoryEntry de in entries)
foreach (DirectoryEntry de in dir.Entries)
{
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
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
// copy of this software and associated documentation files (the "Software"),
@@ -316,13 +316,19 @@ namespace WPinternals
{
filename = System.IO.Path.GetFileName(Text);
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
string directory = "";
try
{
directory = System.IO.Path.GetDirectoryName(Text);
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
FormattedText formatted;
bool widthOK = 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
// copy of this software and associated documentation files (the "Software"),
@@ -28,6 +28,7 @@ using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
@@ -658,7 +659,7 @@ namespace WPinternals
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
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)
@@ -673,7 +674,7 @@ namespace WPinternals
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString());
LogBuilder.AppendLine("Copyright Heathcliff74 / wpinternals.net");
LogBuilder.AppendLine("Copyright Heathcliff74");
LogBuilder.AppendLine("Action: " + Action);
if (App.Config.RegistrationName != null)
LogBuilder.AppendLine("Name: " + App.Config.RegistrationName);
@@ -924,7 +925,7 @@ namespace WPinternals
{
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
{
@@ -1890,7 +1891,7 @@ namespace WPinternals
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:
// 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)
{
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:
// 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)
{
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)
@@ -2221,8 +2223,7 @@ namespace WPinternals
}
else
{
double width = Math.Max(allowedSpace * (Percentage / totalPercentage), 0);
_element.Width = width;
_element.Width = (double)Math.Max(allowedSpace * (Percentage / totalPercentage), 0);
}
}
}

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
// copy of this software and associated documentation files (the "Software"),
@@ -332,7 +332,7 @@ namespace WPinternals
return (UInt16)(0x10000 - Checksum);
}
private static readonly UInt32[] CRC32Table = new UInt32[] {
private static readonly UInt32[] CRC32Table = [
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
@@ -376,7 +376,7 @@ namespace WPinternals
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
];
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
// copy of this software and associated documentation files (the "Software"),
@@ -84,7 +84,7 @@ namespace WPinternals
// Read Store Header
byte[] ShortStoreHeader = new byte[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);
UInt32 WriteDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 212);
UInt32 ValidateDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 220);
@@ -455,8 +455,8 @@ namespace WPinternals
if (Offset != null)
{
uint Start = (uint)Offset + 10;
uint Length = (uint)ByteOperations.FindPattern(Data, Start, 0x100, new byte[] { 0x00 }, null, null) - Start;
uint? Offset0D = ByteOperations.FindPattern(Data, Start, 0x100, new byte[] { 0x0D }, null, null);
uint Length = (uint)ByteOperations.FindPattern(Data, Start, 0x100, [0x00], null, null) - Start;
uint? Offset0D = ByteOperations.FindPattern(Data, Start, 0x100, [0x0D], null, null);
if ((Offset0D != null) && (Offset0D < (Start + Length)))
{
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
// copy of this software and associated documentation files (the "Software"),
@@ -74,7 +74,7 @@ namespace WPinternals
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)
{
break;
@@ -275,7 +275,10 @@ namespace WPinternals
{
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
if (NewPartition.LastSector == 0)
@@ -471,7 +474,10 @@ namespace WPinternals
{
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
DecompressedStream.Close();
UInt64 MaxPartitionSizeInSectors = OldPartition.SizeInSectors;
@@ -521,7 +527,10 @@ namespace WPinternals
{
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
DecompressedStream.Close();
if (NewPartition.SizeInSectors != StreamLengthInSectors)
{
@@ -545,7 +554,7 @@ namespace WPinternals
internal void WritePartitions(string Path)
{
string DirPath = System.IO.Path.GetDirectoryName(Path);
if (!Directory.Exists(DirPath))
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{
Directory.CreateDirectory(DirPath);
}
@@ -559,6 +568,15 @@ namespace WPinternals
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)
{
XmlSerializer x = new(typeof(GPT), "");
@@ -570,8 +588,7 @@ namespace WPinternals
{
// 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)
List<string> RevisePartitions = new(new string[] { "SBL1", "SBL2", "SBL3", "UEFI", "TZ", "RPM", "WINSECAPP" });
foreach (string RevisePartitionName in RevisePartitions)
foreach (string RevisePartitionName in (List<string>)(new(new string[] { "SBL1", "SBL2", "SBL3", "UEFI", "TZ", "RPM", "WINSECAPP" })))
{
Partition RevisePartition = GetPartition(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
// copy of this software and associated documentation files (the "Software"),
@@ -110,9 +110,9 @@ namespace WPinternals
if (DictionarySize != 0)
{
Encoder.SetCoderProperties(
new CoderPropID[8] {CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits,
CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker},
new object[8] { DictionarySize, PosStateBits, LitContextBits, LitPosBits, Algorithm, NumFastBytes, MatchFinder, EndMarker });
[CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits,
CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker],
[DictionarySize, PosStateBits, LitContextBits, LitPosBits, Algorithm, NumFastBytes, MatchFinder, EndMarker]);
}
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
// copy of this software and associated documentation files (the "Software"),
@@ -158,7 +158,7 @@ namespace WPinternals
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)
{
@@ -170,7 +170,7 @@ namespace WPinternals
ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
{
ProductType = "RM-" + ProductType[2..];
ProductType = $"RM-{ProductType[2..]}";
}
}
@@ -182,6 +182,7 @@ namespace WPinternals
packageClass = "Public",
manufacturerHardwareModel = ProductType
};
DiscoveryParameters DiscoveryParams = new()
{
query = DiscoveryQueryParams
@@ -212,16 +213,15 @@ namespace WPinternals
}
SoftwarePackage Package = null;
using (MemoryStream JsonStream2 = new(Encoding.UTF8.GetBytes(JsonResultString)))
using MemoryStream JsonResultStream = new(Encoding.UTF8.GetBytes(JsonResultString));
DataContractJsonSerializer SoftwarePackagesJsonSerializer = new(typeof(SoftwarePackages));
SoftwarePackages SoftwarePackages = (SoftwarePackages)SoftwarePackagesJsonSerializer.ReadObject(JsonResultStream);
if (SoftwarePackages != null)
{
DataContractJsonSerializer Serializer2 = new(typeof(SoftwarePackages));
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
if (SoftwarePackages != null)
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
{
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
{
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
}
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
}
}
@@ -230,41 +230,40 @@ namespace WPinternals
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 DPLUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + DPLF.fileName);
Task<string> GetDPLTask = HttpClient.GetStringAsync(DPLUri);
Uri DPLFileUrlUri = new($"https://api.swrepository.com/rest-api/discovery/fileurl/1/{Package.id}/{DPLSoftwareFile.fileName}");
Task<string> GetDPLTask = HttpClient.GetStringAsync(DPLFileUrlUri);
GetDPLTask.Wait();
string DPLString = GetDPLTask.Result;
string DPLUrl = "";
FileUrlResult FileUrlDPL = null;
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(DPLString)))
string DPLFileUrlResultContent = GetDPLTask.Result;
FileUrlResult DPLFileUrlResult = null;
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));
FileUrlDPL = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
if (FileUrlDPL != null)
{
DPLUrl = FileUrlDPL.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
}
DPLFileUrl = DPLFileUrlResult.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.");
}
Task<string> GetDPLStrTask = HttpClient.GetStringAsync(DPLUrl);
Task<string> GetDPLStrTask = HttpClient.GetStringAsync(DPLFileUrl);
GetDPLStrTask.Wait();
string DPLStrString = GetDPLStrTask.Result;
DPL.Package dpl;
XmlSerializer serializer = new(typeof(DPL.Package));
using (StringReader reader = new(DPLStrString.Replace("ft:", "").Replace("dpl:", "").Replace("typedes:", "")))
{
dpl = (DPL.Package)serializer.Deserialize(reader);
}
using StringReader reader = new(DPLStrString.Replace("ft:", "").Replace("dpl:", "").Replace("typedes:", ""));
dpl = (DPL.Package)serializer.Deserialize(reader);
foreach (DPL.File file in dpl.Content.Files.File)
{
@@ -274,30 +273,30 @@ namespace WPinternals
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);
GetFileInfoTask.Wait();
string FileInfoString = GetFileInfoTask.Result;
string ENOSWUrl = "";
string ENOSWFileUrl = "";
FileUrlResult FileUrl = null;
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(FileInfoString)))
using MemoryStream JsonStream4 = new(Encoding.UTF8.GetBytes(FileInfoString));
DataContractJsonSerializer Serializer4 = new(typeof(FileUrlResult));
FileUrl = (FileUrlResult)Serializer4.ReadObject(JsonStream4);
if (FileUrl != null)
{
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
FileUrl = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
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();
return ENOSWUrl;
return (ENOSWFileUrl, DPLFileUrl);
}
private static bool IsFirmwareBetween(string PhoneFirmwareRevision, string Limit1, string Limit2)
@@ -386,7 +385,7 @@ namespace WPinternals
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
// copy of this software and associated documentation files (the "Software"),
@@ -41,8 +41,7 @@ namespace WPinternals
{
try
{
ManagementObjectCollection coll = new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get();
foreach (ManagementObject logical in coll)
foreach (ManagementObject logical in new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get())
{
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)
@@ -112,15 +114,18 @@ namespace WPinternals
SerialDevice.EncodeCommands = false;
// 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
SerialDevice.SendData(new byte[] { 0x7E, 0xA, 0x0, 0x0, 0xB6, 0xB5, 0x7E });
SerialDevice.SendData([0x7E, 0xA, 0x0, 0x0, 0xB6, 0xB5, 0x7E]);
SerialDevice.Close();
SerialDevice.Dispose();
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
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
// 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
// copy of this software and associated documentation files (the "Software"),
@@ -40,7 +40,10 @@ namespace WPinternals
{
Device = new USBDevice(DevicePath);
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
private JsonElement? ExecuteJsonMethodAsJsonToken(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
@@ -173,6 +176,11 @@ namespace WPinternals
return null;
}
if (Token.Value.ValueKind == JsonValueKind.String)
{
return Token.Value.GetString().Equals("true", StringComparison.InvariantCultureIgnoreCase);
}
return Token.Value.GetBoolean();
}
@@ -335,7 +343,10 @@ namespace WPinternals
Result = new byte[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;
}
@@ -363,7 +374,10 @@ namespace WPinternals
pipe.Reset();
}
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
/// <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
// copy of this software and associated documentation files (the "Software"),
@@ -40,14 +40,14 @@ namespace WPinternals
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));
PatchDefinitions = (List<PatchDefinition>)x.Deserialize(s);
}
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();
ns.Add("", "");
@@ -58,7 +58,7 @@ namespace WPinternals
FileWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
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("Permission is hereby granted, free of charge, to any person obtaining a");
FileWriter.WriteLine("copy of this software and associated documentation files(the \"Software\"),");
@@ -94,7 +94,7 @@ namespace WPinternals
}
set
{
_TargetPath = value.TrimEnd(new char[] { '\\' });
_TargetPath = value.TrimEnd(['\\']);
}
}
@@ -365,7 +365,7 @@ namespace WPinternals
}
set
{
_RelativePath = value.TrimStart(new char[] { '\\' }).TrimEnd(new char[] { '\\' });
_RelativePath = value.TrimStart(['\\']).TrimEnd(['\\']);
}
}
@@ -377,7 +377,7 @@ namespace WPinternals
}
set
{
_TargetPath = value.TrimEnd(new char[] { '\\' });
_TargetPath = value.TrimEnd(['\\']);
}
}
}
@@ -515,7 +515,7 @@ namespace WPinternals
}
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
// 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
// copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@ namespace WPinternals
{
try
{
Serial.SendCommand(new byte[] { 0x06 }, new byte[] { 0x02 });
Serial.SendCommand([0x06], [0x02]);
return true;
}
catch
@@ -61,7 +61,7 @@ namespace WPinternals
CurrentLength = Remaining >= 0x100 ? 0x100 : (UInt32)Remaining;
CurrentLength = (UInt32)Data.Read(Buffer, 7, (int)CurrentLength);
Serial.SendCommand(Buffer, new byte[] { 0x02 });
Serial.SendCommand(Buffer, [0x02]);
CurrentAddress += 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(Data, (int)CurrentOffset, CurrentBytes, 7, (int)CurrentLength);
Serial.SendCommand(CurrentBytes, new byte[] { 0x02 });
Serial.SendCommand(CurrentBytes, [0x02]);
CurrentAddress += CurrentLength;
CurrentOffset += CurrentLength;
@@ -113,25 +113,25 @@ namespace WPinternals
byte[] Buffer = new byte[5];
Buffer[0] = 0x05;
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.
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.
public void Shutdown()
{
Serial.SendCommand(new byte[] { 0x0E }, new byte[] { 0x02 });
Serial.SendCommand([0x0E], [0x02]);
}
// This command only works on 9008 interface.
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];
Buffer.BlockCopy(Response, 3, Result, 0, 0x20);
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
// copy of this software and associated documentation files (the "Software"),
@@ -28,165 +28,15 @@ using System.Threading.Tasks;
namespace WPinternals
{
internal enum SaharaMode : uint
{
ImageTransferPending = 0x00,
ImagetransferComplete = 0x01,
MemoryDebug = 0x02,
Command = 0x03
}
internal delegate void ReadyHandler();
internal class QualcommSahara
internal class QualcommFirehose
{
private readonly QualcommSerial Serial;
public QualcommSahara(QualcommSerial Serial)
public QualcommFirehose(QualcommSerial Serial)
{
Serial.EncodeCommands = false;
Serial.DecodeResponses = false;
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)
{
// Behaviour of old firehose:
@@ -251,7 +101,10 @@ namespace WPinternals
LogFile.Log("Programmer failed to authenticate Digital Signature", LogType.FileOnly);
}
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
while (!HandshakeCompleted && (HelloSendCount < 6));
@@ -280,16 +133,8 @@ namespace WPinternals
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());
if (!Connected)
{
@@ -317,59 +162,12 @@ namespace WPinternals
return true;
}
public void SwitchMode(SaharaMode Mode)
{
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)
public bool SendEdPayload(string ProgrammerPath, string PayloadPath)
{
// First, let's read the Emergency Download payload header and verify its validity
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];
PayloadStream.Read(PayloadHeader, 0, 17);
@@ -405,16 +203,6 @@ namespace WPinternals
LogFile.Log("Version: " + version, 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
LogFile.Log("Waiting...", LogType.FileAndConsole);
Thread.Sleep(2000);
@@ -434,7 +222,7 @@ namespace WPinternals
LogFile.Log(ProgrammerCommand, LogType.FileAndConsole);
byte[] PacketFromPcToProgrammer = Array.Empty<byte>();
byte[] PacketFromPcToProgrammer = [];
byte[] temp = new byte[0x200];
while (true)
@@ -453,7 +241,7 @@ namespace WPinternals
break;
}
PacketFromPcToProgrammer = PacketFromPcToProgrammer.Concat(temp).ToArray();
PacketFromPcToProgrammer = [.. PacketFromPcToProgrammer, .. temp];
}
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
// copy of this software and associated documentation files (the "Software"),
@@ -45,41 +45,37 @@ namespace WPinternals
public void Hello()
{
byte[] Command = new byte[]
{
byte[] 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"
0x61, 0x64, 0x20, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x20, 0x68, 0x6F, 0x73, 0x74,
0x02,
0x02, // Protocol version - Must be at least 0x02
0x01
};
];
Serial.SendCommand(Command, new byte[] { 0x02 });
Serial.SendCommand(Command, [0x02]);
}
public void SetSecurityMode(byte Mode)
{
byte[] Command = new byte[2];
Command[0] = 0x17;
Command[1] = Mode;
byte[] Command = [0x17, Mode];
Serial.SendCommand(Command, new byte[] { 0x18 });
Serial.SendCommand(Command, [0x18]);
}
// Use PartitionID 0x21
public void OpenPartition(byte PartitionID)
{
byte[] Command = new byte[2];
Command[0] = 0x1B;
Command[1] = PartitionID;
byte[] Command = [0x1B, PartitionID];
Serial.SendCommand(Command, new byte[] { 0x1C });
Serial.SendCommand(Command, [0x1C]);
}
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)
@@ -222,7 +218,7 @@ namespace WPinternals
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
// copy of this software and associated documentation files (the "Software"),
@@ -33,8 +33,7 @@ namespace WPinternals
try
{
IEnumerable<string> FilePaths = Directory.EnumerateFiles(Path);
foreach (string FilePath in FilePaths)
foreach (string FilePath in Directory.EnumerateFiles(Path))
{
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;
}
@@ -90,6 +95,11 @@ namespace WPinternals
foreach (string Line in Lines)
{
if (string.IsNullOrEmpty(Line))
{
continue;
}
if (Line[0] != ':')
{
throw new BadImageFormatException();
@@ -117,7 +127,10 @@ namespace WPinternals
Result = new byte[BufferSize];
System.Buffer.BlockCopy(Buffer, 0, Result, 0, BufferSize);
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
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
// copy of this software and associated documentation files (the "Software"),
@@ -19,6 +19,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
@@ -52,15 +53,15 @@ namespace WPinternals
internal QualcommPartition(byte[] Binary, uint Offset = 0)
{
#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
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[] LongHeaderMask = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] LongHeaderPattern = [0xD1, 0xDC, 0x4B, 0x84, 0x34, 0x10, 0xD7, 0x73, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
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
// First program header is a reference to the elf-header
@@ -128,45 +129,58 @@ namespace WPinternals
CertificatesSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X1C);
CertificatesOffset = CertificatesAddress - ImageAddress + ImageOffset;
uint CurrentCertificateOffset = CertificatesOffset;
uint CertificateSize = 0;
while (CurrentCertificateOffset < (CertificatesOffset + CertificatesSize))
using MemoryStream fileStream = new(Binary);
using BinaryReader reader = new(fileStream);
List<byte[]> Signatures = [];
uint LastOffset = 0;
for (uint i = 0; i < fileStream.Length - 6; i++)
{
if ((Binary[CurrentCertificateOffset] == 0x30) && (Binary[CurrentCertificateOffset + 1] == 0x82))
fileStream.Seek(i, SeekOrigin.Begin);
ushort offset0 = reader.ReadUInt16();
short offset1 = (short)((reader.ReadByte() << 8) | reader.ReadByte());
ushort offset2 = reader.ReadUInt16();
if (offset0 == 0x8230 && offset1 >= 0 && offset2 == 0x8230)
{
CertificateSize = (uint)(Binary[CurrentCertificateOffset + 2] * 0x100) + Binary[CurrentCertificateOffset + 3] + 4; // Big endian!
uint CertificateSize = (uint)offset1 + 4; // Header Size is 4
if ((CurrentCertificateOffset + CertificateSize) == (CertificatesOffset + CertificatesSize))
bool IsCertificatePartOfExistingChain = LastOffset == 0 || LastOffset == i;
if (!IsCertificatePartOfExistingChain)
{
// This is the last certificate. So this is the root key.
RootKeyHash = new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize);
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("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
System.Diagnostics.Debug.Print("Cert: " + Converter.ConvertHexToString(SHA256.HashData(Signatures[i]), ""));
#endif
}
#if DEBUG
else
{
System.Diagnostics.Debug.Print("Cert: " + Converter.ConvertHexToString(new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize), ""));
}
#endif
CurrentCertificateOffset += CertificateSize;
}
else
{
if ((RootKeyHash == null) && (CurrentCertificateOffset > CertificatesOffset))
{
CurrentCertificateOffset -= CertificateSize;
// This is the last certificate. So this is the root key.
RootKeyHash = new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize);
RootKeyHash = SHA256.HashData(Signatures[i]);
#if DEBUG
System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
#endif
}
break;
}
}
}
+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
// copy of this software and associated documentation files (the "Software"),
@@ -38,7 +38,7 @@ namespace WPinternals
{
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))
{
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);
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
}
@@ -84,10 +87,10 @@ namespace WPinternals
return GetResponse(ResponsePattern);
}
internal byte[] GetResponse(byte[] ResponsePattern)
internal byte[] GetResponse(byte[] ResponsePattern, int Length = 0x2000)
{
byte[] ResponseBuffer = new byte[0x2000];
int Length = 0;
byte[] ResponseBuffer = new byte[Length];
Length = 0;
bool IsIncomplete = false;
do
@@ -146,7 +149,10 @@ namespace WPinternals
{
IsIncomplete = true;
}
catch { } // Will be rethrown as BadConnectionException
catch (Exception ex) // Will be rethrown as BadConnectionException
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
while (IsIncomplete);
@@ -323,7 +329,7 @@ namespace WPinternals
public class CRC16
{
private readonly UInt16[] ChecksumTable =
new UInt16[] {
[
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
@@ -356,7 +362,7 @@ namespace WPinternals
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
];
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
// copy of this software and associated documentation files (the "Software"),
@@ -29,11 +29,11 @@ namespace WPinternals
internal byte[] GenerateExtraSector(byte[] PartitionHeader)
{
UInt32? Offset = ByteOperations.FindPattern(Binary,
new byte[] {
[
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,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}, null, null);
], null, null);
if (Offset == null)
{
throw new BadImageFormatException();
@@ -43,12 +43,12 @@ namespace WPinternals
byte[] FoundPattern = new byte[0x10];
Offset = ByteOperations.FindPattern(Binary,
new byte[] {
[
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
},
],
FoundPattern);
if (Offset == null)
{
@@ -59,14 +59,14 @@ namespace WPinternals
UInt32 GlobalIsSecurityEnabledAddress = SharedMemoryAddress + 0x28;
Offset = ByteOperations.FindPattern(Binary,
new byte[] {
[
0x01, 0xFF, 0xA0, 0xE3, 0xFF, 0xFF, 0xA0, 0xE1, 0x1C, 0xD0, 0x8D, 0xE2, 0xF0, 0x4F, 0xBD, 0xE8,
0x1E, 0xFF, 0x2F, 0xE1
},
new byte[] {
],
[
0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
},
],
null);
if (Offset == null)
{
@@ -78,7 +78,7 @@ namespace WPinternals
byte[] Sector = new byte[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,
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,
@@ -88,11 +88,11 @@ namespace WPinternals
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,
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
};
];
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
// copy of this software and associated documentation files (the "Software"),
@@ -35,12 +35,12 @@ namespace WPinternals
internal byte[] Patch()
{
UInt32? PatchOffset = ByteOperations.FindPattern(Binary,
new byte[] {
[
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
},
],
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
// copy of this software and associated documentation files (the "Software"),
@@ -45,13 +45,16 @@ namespace WPinternals
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 (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[] SBL3Mask = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 = [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);
@@ -72,7 +75,7 @@ namespace WPinternals
internal byte[] Patch()
{
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);
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
// 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.
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))
{
@@ -599,8 +599,8 @@ namespace WPinternals
ClearEfiChecksum(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 },
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 },
[0xF0, 0x41, 0x2D, 0xE9, 0xFF, 0xFF, 0xB0, 0xE1, 0x28, 0xD0, 0x4D, 0xE2, 0xFF, 0xFF, 0xA0, 0xE1, 0x00, 0x00, 0xFF, 0x13, 0x20, 0xFF, 0xA0, 0xE3],
[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);
if (PatchOffset == null)
@@ -616,8 +616,8 @@ namespace WPinternals
ClearEfiChecksum(SecurityServicesDxe);
PatchOffset = ByteOperations.FindPattern(SecurityServicesDxe,
new byte[] { 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 },
[0x10, 0xFF, 0xFF, 0xE5, 0x80, 0xFF, 0x10, 0xE3, 0xFF, 0xFF, 0xFF, 0x0A],
[0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00],
null);
if (PatchOffset == null)
@@ -628,8 +628,8 @@ namespace WPinternals
ByteOperations.WriteUInt8(SecurityServicesDxe, (UInt32)PatchOffset + 0x0B, 0xEA);
PatchOffset = ByteOperations.FindPattern(SecurityServicesDxe,
new byte[] { 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 },
[0x11, 0xFF, 0xFF, 0xE5, 0x40, 0xFF, 0x10, 0xE3, 0xFF, 0xFF, 0xFF, 0x0A],
[0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00],
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"?>
<!--
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 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: AssemblyCompany("")]
[assembly: AssemblyProduct("WPinternals")]
[assembly: AssemblyCopyright("Copyright © 2018-2019")]
[assembly: AssemblyCopyright("Copyright © 2018-2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -47,5 +47,5 @@ using System.Windows;
// 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("2.9.*")]
[assembly: AssemblyVersion("3.0.*")]
// [assembly: AssemblyFileVersion("1.0.0.0")]

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