Fix WinUSB driver install: self-signed cert + pnputil approach
Replace DiInstallDriverW (failed with 0xE000022F / no catalog) with proven approach: create self-signed code signing cert via PowerShell New-SelfSignedCertificate, install to TrustedPublisher + Root stores via certutil, then use pnputil /add-driver /install which accepts the unsigned INF when cert is trusted. Removes syscall/unsafe deps. Tested successfully on Windows: KL520 + KL720 drivers installed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9ec1926133
commit
98b89fe104
@ -8,8 +8,6 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func platformDefaultDir() string {
|
||||
@ -89,18 +87,17 @@ func installLibusb(installDir string) error {
|
||||
}
|
||||
|
||||
// installWinUSBDriver extracts the WinUSB driver INF and co-installer files
|
||||
// from the payload, then uses the Windows SetupAPI (DiInstallDriver) to install
|
||||
// the driver. DiInstallDriver can install unsigned drivers — Windows will show
|
||||
// a security prompt asking the user to confirm.
|
||||
// from the payload, then creates a self-signed certificate, installs it to the
|
||||
// TrustedPublisher store, and uses pnputil to install the driver.
|
||||
func installWinUSBDriver(installDir string) {
|
||||
driverDir := filepath.Join(installDir, "drivers")
|
||||
os.MkdirAll(filepath.Join(driverDir, "amd64"), 0755)
|
||||
|
||||
// Extract driver files from embedded payload
|
||||
driverFiles := map[string]string{
|
||||
"payload/drivers/kneron_winusb.inf": filepath.Join(driverDir, "kneron_winusb.inf"),
|
||||
"payload/drivers/amd64/WdfCoInstaller01011.dll": filepath.Join(driverDir, "amd64", "WdfCoInstaller01011.dll"),
|
||||
"payload/drivers/amd64/winusbcoinstaller2.dll": filepath.Join(driverDir, "amd64", "winusbcoinstaller2.dll"),
|
||||
"payload/drivers/kneron_winusb.inf": filepath.Join(driverDir, "kneron_winusb.inf"),
|
||||
"payload/drivers/amd64/WdfCoInstaller01011.dll": filepath.Join(driverDir, "amd64", "WdfCoInstaller01011.dll"),
|
||||
"payload/drivers/amd64/winusbcoinstaller2.dll": filepath.Join(driverDir, "amd64", "winusbcoinstaller2.dll"),
|
||||
}
|
||||
|
||||
for src, dst := range driverFiles {
|
||||
@ -114,41 +111,31 @@ func installWinUSBDriver(installDir string) {
|
||||
}
|
||||
|
||||
infPath := filepath.Join(driverDir, "kneron_winusb.inf")
|
||||
certPath := filepath.Join(driverDir, "kneron_selfsign.cer")
|
||||
|
||||
// Use DiInstallDriver from newdev.dll to pre-install the driver.
|
||||
// This works with unsigned INF files — Windows shows a trust dialog.
|
||||
diInstallDriver(infPath)
|
||||
}
|
||||
// Step 1: Create self-signed code signing certificate via PowerShell
|
||||
psCreateCert := fmt.Sprintf(`
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -eq 'CN=Kneron Edge AI Platform' } | Remove-Item -Force -ErrorAction SilentlyContinue
|
||||
$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=Kneron Edge AI Platform" -CertStoreLocation Cert:\LocalMachine\My -NotAfter (Get-Date).AddYears(10)
|
||||
Export-Certificate -Cert $cert -FilePath '%s' -Force | Out-Null
|
||||
Write-Output $cert.Thumbprint
|
||||
`, certPath)
|
||||
|
||||
// diInstallDriver calls Windows DiInstallDriver API to install a driver INF.
|
||||
// Flags: DIIRFLAG_FORCE_INF (0x00000002) forces the specified INF to be installed
|
||||
// even if it's unsigned, showing a Windows Security prompt to the user.
|
||||
func diInstallDriver(infPath string) {
|
||||
newdev, err := syscall.LoadDLL("newdev.dll")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer newdev.Release()
|
||||
|
||||
proc, err := newdev.FindProc("DiInstallDriverW")
|
||||
if err != nil {
|
||||
return
|
||||
cmd := exec.Command("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", psCreateCert)
|
||||
if _, err := cmd.CombinedOutput(); err != nil {
|
||||
return // non-fatal
|
||||
}
|
||||
|
||||
infPathUTF16, err := syscall.UTF16PtrFromString(infPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Step 2: Install certificate to TrustedPublisher and Root stores
|
||||
exec.Command("certutil", "-addstore", "TrustedPublisher", certPath).Run()
|
||||
exec.Command("certutil", "-addstore", "Root", certPath).Run()
|
||||
|
||||
const DIIRFLAG_FORCE_INF = 0x00000002
|
||||
// DiInstallDriverW(hwndParent, InfPath, Flags, NeedReboot)
|
||||
proc.Call(
|
||||
0, // hwndParent = NULL (no parent window)
|
||||
uintptr(unsafe.Pointer(infPathUTF16)),
|
||||
DIIRFLAG_FORCE_INF,
|
||||
0, // NeedReboot = NULL (don't care)
|
||||
)
|
||||
// Best effort — ignore errors. The user may decline the security prompt.
|
||||
// Step 3: Install driver via pnputil (cert in TrustedPublisher allows unsigned INF)
|
||||
exec.Command("pnputil", "/add-driver", infPath, "/install").Run()
|
||||
|
||||
// Cleanup temp cert file
|
||||
os.Remove(certPath)
|
||||
}
|
||||
|
||||
func checkLibusbInstalled() bool {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user