Skip to content
Merged
144 changes: 99 additions & 45 deletions build/build-installer.ps1
Original file line number Diff line number Diff line change
@@ -1,58 +1,77 @@
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
# SPDX-License-Identifier: BSD-3-Clause

param(
[string]$OutputName = "installer.exe"
[string]$OutputName = "installer.exe",
[ValidateSet("x64", "x86", "arm64")]
[string]$Arch = "x64" # default value (adjust if needed)
)

# ==============================================================================
# Configuration
# ==============================================================================

$Script:OutputRoot = Join-Path $PSScriptRoot "target"
$Script:DriversDir = "drivers"
$Script:ToolsDir = "tools"
$Script:PayloadName = "payload.zip"
$Script:VersionFile = Join-Path $PSScriptRoot "..\src\windows\qcversion.h"

# Files to promote from tools/ to the payload root (alongside drivers/ and tools/)
$Script:PromotedTools = @("qdclr.exe", "qdinstall.exe")
# Items to include in the payload zip (files or directories under target/).
# Promote: optional list of file names to move to the payload root.
$Script:PayloadItems = @(
@{ Path = "drivers"; Arch = $null; Promote = $null }
@{ Path = "tools"; Arch = $null; Promote = @("qdclr.exe", "qdinstall.exe") }
)

# ==============================================================================
# Functions
# ==============================================================================

# Assembles a payload zip from target/drivers and target/tools.
function New-Payload {
Write-Host "========================================"
Write-Host " Packaging Payload"
Write-Host "========================================`n"

$driversSource = Join-Path $Script:OutputRoot $Script:DriversDir
$toolsSource = Join-Path $Script:OutputRoot $Script:ToolsDir

if (-not (Test-Path $driversSource)) {
Write-Error "[ERROR] Drivers directory not found: $driversSource"
exit 1
}
if (-not (Test-Path $toolsSource)) {
Write-Error "[ERROR] Tools directory not found: $toolsSource"
exit 1
}

# Create a temp staging directory
$stagingDir = Join-Path ([System.IO.Path]::GetTempPath()) ([Guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $stagingDir -Force | Out-Null

try {
# Copy drivers/ and tools/ into the staging root
Copy-Item -Path $driversSource -Destination $stagingDir -Recurse -Force
Copy-Item -Path $toolsSource -Destination $stagingDir -Recurse -Force
Write-Host "[COPY] $Script:DriversDir, $Script:ToolsDir -> $stagingDir"

# Promote specified tools to staging root and remove from tools/
$destTools = Join-Path $stagingDir $Script:ToolsDir
foreach ($toolFile in $Script:PromotedTools) {
$srcFile = Join-Path $destTools $toolFile
if (Test-Path $srcFile) {
Copy-Item -Path $srcFile -Destination $stagingDir -Force
Remove-Item -Path $srcFile -Force
Write-Host "[PROMOTE] $toolFile -> payload root"
# Copy all payload items into the staging root.
foreach ($item in $Script:PayloadItems) {
if ($item.Arch) {
$archSource = Join-Path $PSScriptRoot "$($item.Path)\$($item.Arch)"
$destDir = Join-Path $stagingDir $item.Path
if (-not (Test-Path $archSource)) {
Write-Warning "[WARNING] $($item.Path) arch folder not found: $archSource"
continue
}
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
Copy-Item -Path $archSource -Destination $destDir -Recurse -Force
Write-Host "[COPY] $($item.Path)/$($item.Arch) -> staging"
continue
}

$src = Join-Path $Script:OutputRoot $item.Path
if (Test-Path $src) {
Copy-Item -Path $src -Destination $stagingDir -Recurse -Force
Write-Host "[COPY] $($item.Path) -> staging"
} else {
Write-Warning "[WARNING] Promoted tool not found in Tools: $toolFile"
Write-Warning "[WARNING] Payload item not found: $src"
continue
}

if ($item.Promote) {
foreach ($fileName in $item.Promote) {
$srcFile = Join-Path (Join-Path $stagingDir $item.Path) $fileName
if (Test-Path $srcFile) {
Copy-Item -Path $srcFile -Destination $stagingDir -Force
Remove-Item -Path $srcFile -Force
Write-Host "[PROMOTE] $($item.Path)/$fileName -> payload root"
} else {
Write-Warning "[WARNING] Promoted file not found: $($item.Path)/$fileName"
}
}
}
}

Expand Down Expand Up @@ -85,7 +104,10 @@ function New-Payload {
$PayloadFullPath = (Resolve-Path (New-Payload)).Path

# --- Parse version ---
$Version = "1.0.0.0"
$Version = "1.0.0.0"
$ProductName = "Qualcomm USB Kernel Drivers"
$CompanyName = "Qualcomm Technologies, Inc."
$Copyright = "Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries."
if (Test-Path $Script:VersionFile) {
$versionContent = Get-Content $Script:VersionFile -Raw
if ($versionContent -match '#define\s+QCOM_USB_DRIVERS_PRODUCT_VERSION\s+([\d.]+)') {
Expand All @@ -94,6 +116,15 @@ if (Test-Path $Script:VersionFile) {
} else {
Write-Warning "QCOM_USB_DRIVERS_PRODUCT_VERSION not found in $($Script:VersionFile), using default: $Version"
}
if ($versionContent -match '#define\s+QCOM_USB_DRIVERS_PRODUCT_NAME\s+"([^"]+)"') {
$ProductName = $Matches[1]
}
if ($versionContent -match '#define\s+QCOM_USB_DRIVERS_COMPANY_NAME\s+"([^"]+)"') {
$CompanyName = $Matches[1]
}
if ($versionContent -match '#define\s+QCOM_USB_DRIVERS_COPYRIGHT\s+"([^"]+)"') {
$Copyright = $Matches[1]
}
} else {
Write-Warning "[WARNING] Version file not found: $($Script:VersionFile), using default: $Version"
}
Expand All @@ -106,11 +137,11 @@ using System.IO;
using System.IO.Compression;
using System.Reflection;

[assembly: AssemblyTitle("Qualcomm USB Kernel Driver Installer")]
[assembly: AssemblyDescription("Qualcomm USB Kernel Driver Installer")]
[assembly: AssemblyCompany("Qualcomm Technologies, Inc.")]
[assembly: AssemblyProduct("Qualcomm USB Kernel Drivers")]
[assembly: AssemblyCopyright("Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.")]
[assembly: AssemblyTitle("__PRODUCT_NAME__")]
[assembly: AssemblyDescription("__PRODUCT_NAME__")]
[assembly: AssemblyCompany("__COMPANY_NAME__")]
[assembly: AssemblyProduct("__PRODUCT_NAME__")]
[assembly: AssemblyCopyright("__COPYRIGHT__")]
[assembly: AssemblyVersion("__VERSION__")]
[assembly: AssemblyFileVersion("__VERSION__")]
[assembly: AssemblyInformationalVersion("__VERSION__")]
Expand All @@ -133,7 +164,7 @@ namespace PayloadInstaller
"qud.internal"
};

static int RunCommand(string fileName, string arguments)
static int RunCommand(string fileName, string arguments, bool consoleOutput = true)
{
try
{
Expand All @@ -142,6 +173,11 @@ namespace PayloadInstaller
if (arguments != null)
psi.Arguments = arguments;
psi.UseShellExecute = false;
if (!consoleOutput)
{
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
}
Process proc = Process.Start(psi);
proc.WaitForExit();
return proc.ExitCode;
Expand All @@ -153,22 +189,25 @@ namespace PayloadInstaller
}
}

// Uninstall any previous installation.
static int Uninstall()
// Removal of legacy drivers installed by QPM/QSC
static void UninstallLegacy()
{
// Best-effort cleanup of legacy packages
foreach (string pkg in LegacyPackages)
{
Console.WriteLine("\nUninstalling legacy product: " + pkg + "...");
RunCommand("qpm-cli", "--uninstall " + pkg + " --silent");
RunCommand("qsc-cli", "tool uninstall -n " + pkg);
RunCommand("qpm-cli", "--uninstall " + pkg + " --silent", false);
RunCommand("qsc-cli", "tool uninstall -n " + pkg, false);
}
}

// Uninstall any previous installation.
static int Uninstall()
{
int result = 0;
if (File.Exists(QdinstallExe))
{
Console.WriteLine("\nRunning uninstaller: " + QdinstallExe);
result = RunCommand(QdinstallExe, "-x");
result = RunCommand(QdinstallExe, "-u");
}

if (Directory.Exists(InstallPath))
Expand All @@ -194,6 +233,7 @@ namespace PayloadInstaller
// Install drivers and remove previous installation
static int Install()
{
UninstallLegacy();
Uninstall();

try
Expand Down Expand Up @@ -240,6 +280,15 @@ namespace PayloadInstaller

static int Main(string[] args)
{
// Print banner
Console.WriteLine("================================================");
Console.WriteLine(" __PRODUCT_NAME__");
Console.WriteLine(" Version#: __VERSION__");
Console.WriteLine(" Built on: __BUILD_TIME__");
Console.WriteLine(" __COPYRIGHT__");
Console.WriteLine("================================================");
Console.WriteLine();

// Parse arguments
string mode = "install"; // default (no args)
if (args.Length > 0)
Expand Down Expand Up @@ -289,7 +338,12 @@ $outputExe = Join-Path $Script:OutputRoot $OutputName

# Write C# source to a temp file in the system temp directory
$sourceFile = [System.IO.Path]::ChangeExtension([System.IO.Path]::GetTempFileName(), '.cs')
$csharpSource = $csharpSource.Replace("__VERSION__", $Version)
$buildTime = (Get-Date).ToUniversalTime().ToString("yyyy-MM-dd HH:mm UTC")
$csharpSource = $csharpSource.Replace("__VERSION__", $Version)
$csharpSource = $csharpSource.Replace("__PRODUCT_NAME__", $ProductName)
$csharpSource = $csharpSource.Replace("__COMPANY_NAME__", $CompanyName)
$csharpSource = $csharpSource.Replace("__COPYRIGHT__", $Copyright)
$csharpSource = $csharpSource.Replace("__BUILD_TIME__", $buildTime)
$csharpSource = $csharpSource.Replace("__PAYLOAD_NAME__", $Script:PayloadName)
Set-Content -Path $sourceFile -Value $csharpSource -Encoding UTF8

Expand Down
3 changes: 3 additions & 0 deletions build/build_drivers.bat
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
:: Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
:: SPDX-License-Identifier: BSD-3-Clause

@echo off
setlocal

Expand Down
3 changes: 3 additions & 0 deletions build/build_drivers.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
# SPDX-License-Identifier: BSD-3-Clause

#Requires -Version 5.0

param(
Expand Down
3 changes: 3 additions & 0 deletions build/build_installer.bat
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
:: Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
:: SPDX-License-Identifier: BSD-3-Clause

@echo off
setlocal enabledelayedexpansion

Expand Down
3 changes: 3 additions & 0 deletions build/build_tools.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
# SPDX-License-Identifier: BSD-3-Clause

#Requires -Version 5.0

param(
Expand Down
3 changes: 3 additions & 0 deletions build/sign.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
# SPDX-License-Identifier: BSD-3-Clause

#Requires -Version 5.0

param(
Expand Down
4 changes: 2 additions & 2 deletions src/windows/qcversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#define WSTRINGIFY(s) L#s
#define QCWSTR(str) WSTRINGIFY(str)

#define QCOM_USB_DRIVERS_PRODUCT_VERSION 1.00.94.6
#define QCOM_USB_DRIVERS_FILE_VERSION 1,00,94,6
#define QCOM_USB_DRIVERS_PRODUCT_VERSION 1.00.94.7
#define QCOM_USB_DRIVERS_FILE_VERSION 1,00,94,7
#define QCOM_USB_DRIVERS_PRODUCT_VERSION_STRING QCSTR(QCOM_USB_DRIVERS_PRODUCT_VERSION)
#define QCOM_USB_DRIVERS_PRODUCT_VERSION_STRING_W QCWSTR(QCOM_USB_DRIVERS_PRODUCT_VERSION)

Expand Down
44 changes: 40 additions & 4 deletions src/windows/tools/qdinstall/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ DWORD install_drivers(const std::wstring &path)

DWORD uninstall_drivers()
{
printf("Removing drivers ...\n");
DWORD ret = execute_command(COMMAND_QDCLR);

if (ret == ERROR_FILE_NOT_FOUND)
Expand Down Expand Up @@ -155,7 +154,8 @@ static void inline print_usage()
" qdinstall.exe [options]\n\n"
"Options:\n"
" -i -p <path> Install drivers from path\n"
" -x Uninstall drivers\n"
" -u Uninstall drivers\n"
" -x Uninstall drivers and remove installation files\n"
" -v Display version information\n"
);
}
Expand All @@ -170,10 +170,18 @@ static DWORD parse_args(int argc, wchar_t *argv[], Options &opts)
{
opts.install = true;
opts.uninstall = false;
opts.remove = false;
}
else if (arg == L"-x")
else if (arg == L"-u")
{
opts.uninstall = true;
opts.remove = false;
opts.install = false;
}
else if (arg == L"-x")
{
opts.remove = true;
opts.uninstall = false;
opts.install = false;
}
else if (arg == L"-v")
Expand Down Expand Up @@ -320,8 +328,11 @@ int wmain(int argc, wchar_t *argv[])
}
}
}
else if (opts.uninstall)
else if (opts.uninstall || opts.remove)
{
// Read install location from registry before unregistering
std::wstring install_location = get_registered_install_location();

// Stop and unregister WWAN service before driver removal
if (GetFileAttributesW(COMMAND_WWANSVC) != INVALID_FILE_ATTRIBUTES)
{
Expand All @@ -331,18 +342,43 @@ int wmain(int argc, wchar_t *argv[])
execute_command(std::wstring(COMMAND_WWANSVC) + L" uninstall");
}

printf("\nRemoving drivers ...\n");
ret = uninstall_drivers();
if (ret != ERROR_SUCCESS && ret != ERROR_FILE_NOT_FOUND)
{
printf("ERROR: failed to uninstall driver (0x%lX)\n", ret);
return ret;
}

printf("\nCleaning up registry entries ...\n");
ret = unregister_installation();
if (ret != ERROR_SUCCESS)
{
printf("WARNING: failed to clean up registry (0x%lX), continuing...\n", ret);
}

// Schedule deletion of install directory (-x only, cannot delete self while running)
if (opts.remove && !install_location.empty())
{
DWORD attr = GetFileAttributesW(install_location.c_str());
if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
{
// Change working directory away from install path to avoid locking it
SetCurrentDirectoryW(L"C:\\");

printf("\nScheduling removal of: %ws\n", install_location.c_str());
std::wstring del_cmd = L"cmd.exe /c timeout /t 2 /nobreak >nul & rd /s /q \""
+ install_location + L"\"";
STARTUPINFOW si_del = { sizeof(si_del) };
si_del.dwFlags = STARTF_USESHOWWINDOW;
si_del.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi_del = {};
CreateProcessW(nullptr, const_cast<wchar_t*>(del_cmd.c_str()),
nullptr, nullptr, FALSE, CREATE_NEW_CONSOLE,
nullptr, nullptr, &si_del, &pi_del);
if (pi_del.hProcess) { CloseHandle(pi_del.hProcess); CloseHandle(pi_del.hThread); }
}
}
}

return ERROR_SUCCESS;
Expand Down
3 changes: 2 additions & 1 deletion src/windows/tools/qdinstall/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
struct Options
{
bool install = true; // default action
bool uninstall = false;
bool uninstall = false; // -u: uninstall drivers only (no directory deletion)
bool remove = false; // -x: uninstall drivers and remove installation files
bool version = false;
bool getInstallPath = false;
std::wstring installationPath;
Expand Down
Loading