-
Notifications
You must be signed in to change notification settings - Fork 0
/
DisplayAssignableDevices.cs
39 lines (35 loc) · 9.71 KB
/
DisplayAssignableDevices.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Text;
using System.Windows.Forms;
namespace HyperVPassthoughDevice
{
public partial class DisplayAssignableDevices : Form
{
public DisplayAssignableDevices()
{
InitializeComponent();
ShowDialog();
}
private void CloseDiaglog(object sender, EventArgs e)
{
Close();
}
private void StartChecking(object sender, EventArgs e)
{
richTextBox1.Clear(); //Clear textbox
string script = "#\r\n# These variables are device properties. For people who are very\r\n# curious about this, you can download the Windows Driver Kit headers and\r\n# look for pciprop.h. All of these are contained in that file.\r\n#\r\n$devpkey_PciDevice_DeviceType = \"{3AB22E31-8264-4b4e-9AF5-A8D2D8E33E62} 1\"\r\n$devpkey_PciDevice_BaseClass = \"{3AB22E31-8264-4b4e-9AF5-A8D2D8E33E62} 3\"\r\n$devpkey_PciDevice_RequiresReservedMemoryRegion = \"{3AB22E31-8264-4b4e-9AF5-A8D2D8E33E62} 34\"\r\n$devpkey_PciDevice_AcsCompatibleUpHierarchy = \"{3AB22E31-8264-4b4e-9AF5-A8D2D8E33E62} 31\"\r\n\r\n$devprop_PciDevice_DeviceType_PciConventional = 0\r\n$devprop_PciDevice_DeviceType_PciX = 1\r\n$devprop_PciDevice_DeviceType_PciExpressEndpoint = 2\r\n$devprop_PciDevice_DeviceType_PciExpressLegacyEndpoint = 3\r\n$devprop_PciDevice_DeviceType_PciExpressRootComplexIntegratedEndpoint= 4\r\n$devprop_PciDevice_DeviceType_PciExpressTreatedAsPci = 5\r\n$devprop_PciDevice_BridgeType_PciConventional = 6\r\n$devprop_PciDevice_BridgeType_PciX = 7\r\n$devprop_PciDevice_BridgeType_PciExpressRootPort = 8\r\n$devprop_PciDevice_BridgeType_PciExpressUpstreamSwitchPort = 9\r\n$devprop_PciDevice_BridgeType_PciExpressDownstreamSwitchPort = 10\r\n$devprop_PciDevice_BridgeType_PciExpressToPciXBridge = 11\r\n$devprop_PciDevice_BridgeType_PciXToExpressBridge = 12\r\n$devprop_PciDevice_BridgeType_PciExpressTreatedAsPci = 13\r\n$devprop_PciDevice_BridgeType_PciExpressEventCollector = 14\r\n\r\n$devprop_PciDevice_AcsCompatibleUpHierarchy_NotSupported = 0\r\n$devprop_PciDevice_AcsCompatibleUpHierarchy_SingleFunctionSupported = 1\r\n$devprop_PciDevice_AcsCompatibleUpHierarchy_NoP2PSupported = 2\r\n$devprop_PciDevice_AcsCompatibleUpHierarchy_Supported = 3\r\n\r\n#\r\n# These values are defined in the PCI spec, and are also published in wdm.h\r\n# of the Windows Driver Kit headers.\r\n#\r\n$devprop_PciDevice_BaseClass_DisplayCtlr = 3\r\n\r\nWrite-Host \"Executing SurveyDDA.ps1, revision 1\"\r\n\r\nwrite-host \"Generating a list of PCI Express endpoint devices\"\r\n$pnpdevs = Get-PnpDevice -PresentOnly\r\n$pcidevs = $pnpdevs | Where-Object {$_.InstanceId -like \"PCI*\"}\r\n\r\nforeach ($pcidev in $pcidevs) {\r\n $rmrr = ($pcidev | Get-PnpDeviceProperty $devpkey_PciDevice_RequiresReservedMemoryRegion).Data\r\n if ($rmrr -ne 0) {\r\n write-host -ForegroundColor Red -BackgroundColor Black \"BIOS requires that this device remain attached to BIOS-owned memory. Not assignable.\"\r\n continue\r\n }\r\n\r\n $acsUp = ($pcidev | Get-PnpDeviceProperty $devpkey_PciDevice_AcsCompatibleUpHierarchy).Data\r\n if ($acsUp -eq $devprop_PciDevice_AcsCompatibleUpHierarchy_NotSupported) {\r\n write-host -ForegroundColor Red -BackgroundColor Black \"Traffic from this device may be redirected to other devices in the system. Not assignable.\"\r\n continue\r\n }\r\n\r\n $devtype = ($pcidev | Get-PnpDeviceProperty $devpkey_PciDevice_DeviceType).Data\r\n if ($devtype -eq $devprop_PciDevice_DeviceType_PciExpressEndpoint) {\r\n Write-Host \"Express Endpoint -- more secure.\"\r\n } else {\r\n if ($devtype -eq $devprop_PciDevice_DeviceType_PciExpressRootComplexIntegratedEndpoint) {\r\n Write-Host \"Embedded Endpoint -- less secure.\"\r\n } elseif ($devtype -eq $devprop_PciDevice_DeviceType_PciExpressLegacyEndpoint) {\r\n $devBaseClass = ($pcidev | Get-PnpDeviceProperty $devpkey_PciDevice_BaseClass).Data\r\n\r\n if ($devBaseClass -eq $devprop_PciDevice_BaseClass_DisplayCtlr) {\r\n Write-Host \"Legacy Express Endpoint -- graphics controller.\"\r\n } else {\r\n Write-Host -ForegroundColor Red -BackgroundColor Black \"Legacy, non-VGA PCI device. Not assignable.\"\r\n continue\r\n }\r\n } else {\r\n if ($devtype -eq $devprop_PciDevice_DeviceType_PciExpressTreatedAsPci) {\r\n Write-Host -ForegroundColor Red -BackgroundColor Black \"BIOS kept control of PCI Express for this device. Not assignable.\"\r\n } else {\r\n Write-Host -ForegroundColor Red -BackgroundColor Black \"Old-style PCI device, switch port, etc. Not assignable.\"\r\n }\r\n continue\r\n }\r\n }\r\n\r\n $locationpath = ($pcidev | get-pnpdeviceproperty DEVPKEY_Device_LocationPaths).data[0]\r\n\r\n #\r\n # If the device is disabled, we can't check the resources, report a warning and continue on.\r\n #\r\n #\r\n if ($pcidev.ConfigManagerErrorCode -eq \"CM_PROB_DISABLED\")\r\n {\r\n Write-Host -ForegroundColor Yellow -BackgroundColor Black \"Device is Disabled, unable to check resource requirements, it may be assignable.\"\r\n Write-Host -ForegroundColor Yellow -BackgroundColor Black \"Enable the device and rerun this script to confirm.\"\r\n $locationpath\r\n continue\r\n }\r\n\r\n #\r\n # Now do a check for the interrupts that the device uses. Line-based interrupts\r\n # aren't assignable.\r\n #\r\n $doubleslashDevId = \"*\" + $pcidev.PNPDeviceID.Replace(\"\\\",\"\\\\\") + \"*\"\r\n $irqAssignments = gwmi -query \"select * from Win32_PnPAllocatedResource\" | Where-Object {$_.__RELPATH -like \"*Win32_IRQResource*\"} | Where-Object {$_.Dependent -like $doubleslashDevId}\r\n\r\n #$irqAssignments | Format-Table -Property __RELPATH\r\n\r\n if ($irqAssignments.length -eq 0) {\r\n Write-Host -ForegroundColor Green -BackgroundColor Black \" And it has no interrupts at all -- assignment can work.\"\r\n } else {\r\n #\r\n # Find the message-signaled interrupts. They are reported with a really big number in\r\n # decimal, one which always happens to start with \"42949...\".\r\n #\r\n $msiAssignments = $irqAssignments | Where-Object {$_.Antecedent -like \"*IRQNumber=42949*\"}\r\n \r\n #$msiAssignments | Format-Table -Property __RELPATH\r\n\r\n if ($msiAssignments.length -eq 0) {\r\n Write-Host -ForegroundColor Red -BackgroundColor Black \"All of the interrupts are line-based, no assignment can work.\"\r\n continue\r\n } else {\r\n Write-Host -ForegroundColor Green -BackgroundColor Black \" And its interrupts are message-based, assignment can work.\"\r\n }\r\n }\r\n\r\n #\r\n # Check how much MMIO space the device needs\r\n # not strictly an issue devices, but very useful when you want to set MMIO gap sizes\r\n #\r\n\r\n $mmioAssignments = gwmi -query \"select * from Win32_PnPAllocatedResource\" | Where-Object {$_.__RELPATH -like \"*Win32_DeviceMemoryAddress*\"} | Where-Object {$_.Dependent -like $doubleslashDevId}\r\n $mmioTotal = 0\r\n foreach ($mem in $mmioAssignments) \r\n {\r\n $baseAdd =$mem.Antecedent.SubString($mem.Antecedent.IndexOf(\"\"\"\")+1)\r\n $baseAdd=$baseAdd.SubString(0,$baseAdd.IndexOf(\"\"\"\"))\r\n $mmioRange = gwmi -query \"select * from Win32_DeviceMemoryAddress\" | Where-Object{$_.StartingAddress -like $baseAdd}\r\n $mmioTotal = $mmioTotal + $mmioRange.EndingAddress - $mmioRange.StartingAddress\r\n }\r\n if ($mmioTotal -eq 0)\r\n {\r\n Write-Host -ForegroundColor Green -BackgroundColor Black \" And it has no MMIO space\"\r\n } else {\r\n \t [int]$mmioMB = [math]::ceiling($mmioTotal / 1MB)\r\n Write-Host -ForegroundColor Green -BackgroundColor Black \" And it requires at least:\" $mmioMB \"MB of MMIO gap space\"\r\n }\r\n \r\n\r\n\r\n #\r\n # Print out the location path, as that's the way to refer to this device that won't\r\n # change even if you add or remove devices from the machine or change the way that\r\n # the BIOS is configured.\r\n #\r\n\t\r\n\t$locationpath = $pcidev.FriendlyName + \"`n Location Path: \" + $locationpath + \"`n MMIO Space: \" + $mmioMB + \" MiB`n`n\"\r\n $locationpath\r\n \r\n\t\r\n}\r\n\r\n#\r\n# Now look at the host as a whole. Asking whether the host supports SR-IOV\r\n# is mostly equivalent to asking whether it supports Discrete Device\r\n# Assignment.\r\n#\r\nif ((Get-VMHost).IovSupport -eq $false) {\r\n Write-Host \"\"\r\n write-host \"Unfortunately, this machine doesn't support using them in a VM.\"\r\n Write-Host \"\"\r\n (Get-VMHost).IovSupportReasons\r\n}";
using (PowerShell powerShell = PowerShell.Create())
{
powerShell.AddScript(script);
powerShell.AddCommand("Out-String");
Collection<PSObject> PSOutput = powerShell.Invoke();
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject pSObject in PSOutput)
stringBuilder.AppendLine(pSObject.ToString());
richTextBox1.Text = stringBuilder.ToString() + "\n\n";
}
}
}
}