QCT-Update-Management.psm1
<#
.SYNOPSIS <Overview of script> .DESCRIPTION <Brief description of script> .PARAMETER <Parameter_Name> <Brief description of parameter input required. Repeat this attribute if required> .INPUTS <Inputs if any, otherwise state None> .OUTPUTS <Outputs if any, otherwise state None - example: Log file stored in C:\Windows\Temp\<name>.log> .NOTES Version: 1.3.38 Author: Jim.Lin Creation Date: 2021.09.14 Purpose/Change: Bug fix. .EXAMPLE <Example goes here. Repeat this attribute for more than one example> #> #---------------------------------------------------------[Initialisations]-------------------------------------------------------- #Set Error Action to Silently Continue/Stop $ErrorActionPreference = "Stop" #----------------------------------------------------------[Declarations]---------------------------------------------------------- #-----------------------------------------------------------[Functions]------------------------------------------------------------ function callProcessStdin($ProcessPath, $CmdArgs, $StdinArray) { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $ProcessPath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardInput = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = $CmdArgs $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit(3 * 1000) | Out-Null foreach ($command in $StdinArray) { $p.StandardInput.WriteLine($command) $p.WaitForExit(1 * 1000) | Out-Null if ($command.IndexOf("dl -f") -ge 0) { $p.WaitForExit(60 * 1000) | Out-Null } } $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() return $stdout } function callProcess($ProcessPath, $CmdArgs) { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $ProcessPath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = $CmdArgs $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit(3 * 1000) | Out-Null $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() return $stdout } function callProcessWorkingDirectory($ProcessPath, $CmdArgs) { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $ProcessPath $pinfo.WorkingDirectory = Split-Path $ProcessPath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = $CmdArgs $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit(3 * 1000) | Out-Null $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() return $stdout } function Get-Driver_FW() { [CmdletBinding()] Param ( [Parameter(Mandatory = $false, Position = 0)] [ValidateSet('BIOS', 'BMC', 'Disk', 'Expander', 'HBA', 'intelChipset', 'AMDChipset', 'NIC')] [string]$Device = '', [Parameter(Mandatory = $false, Position = 1)] [ValidateNotNullOrEmpty()] [ValidateSet($true, $false, 1, 0)] $SKipCheck = $false ) $SKipCheck = [System.Convert]::ToBoolean($SKipCheck) if (-not $SKipCheck) { CheckVersion } $script:table2 = @() function addRow2($OEMDevice, $OEMName, $DriverFW, $OEMVersion, $OEMPS, $OEMDriverGUID) { $row2 = New-Object -TypeName PSObject $row2 | Add-Member -Name 'Device' -MemberType Noteproperty -Value $OEMDevice $row2 | Add-Member -Name 'Name' -MemberType Noteproperty -Value $OEMName $row2 | Add-Member -Name 'DriverFW' -MemberType Noteproperty -Value $DriverFW $row2 | Add-Member -Name 'Version' -MemberType Noteproperty -Value $OEMVersion $row2 | Add-Member -Name 'PS' -MemberType Noteproperty -Value $OEMPS $row2 | Add-Member -Name 'Location' -MemberType Noteproperty -Value $hostname $row2 | Add-Member -Name 'Location2' -MemberType Noteproperty -Value $hostname2 $row2 | Add-Member -Name 'ServerModel' -MemberType Noteproperty -Value $ServerModel $row2 | Add-Member -Name 'DriverGUID' -MemberType Noteproperty -Value $OEMDriverGUID $script:table2 += $row2 } $Win32_Computersystem = Get-WmiObject Win32_Computersystem $ServerModel = ($Win32_Computersystem | select Model).Model if ($Win32_Computersystem.PartofDomain) { $hostname = $($Win32_Computersystem.DNSHostName + "." + $Win32_Computersystem.Domain) $hostname2 = hostname } else { $hostname = hostname $hostname2 = hostname } #BIOS if (($Device -eq 'BIOS') -or ($Device -eq '')) { $BIOSVersion = $(Get-WmiObject win32_bios).SMBIOSBIOSVersion addRow2 "BIOS" "BIOS" "FW" $BIOSVersion '' '' } #BMC if (($Device -eq 'BMC') -or ($Device -eq '')) { $PcsvDevice = Get-PcsvDevice -ErrorAction SilentlyContinue | select CurrentManagementFirmwareMajorVersion, CurrentManagementFirmwareMinorVersion if ($PcsvDevice) { $BMCVersion = $PcsvDevice.CurrentManagementFirmwareMajorVersion.ToString() + '.' + $PcsvDevice.CurrentManagementFirmwareMinorVersion.ToString() addRow2 "BMC" "BMC" "FW" $BMCVersion '' '' } } $Win32_PnPEntity = Get-WmiObject -Class Win32_PnPEntity if (($Device -eq 'intelChipset') -or ($Device -eq '')) { #Intel Chipset $SysGUID = '4D36E97D-E325-11CE-BFC1-08002BE10318' $intelChipset = Get-ItemProperty -Path "HKLM:\Software\Intel\INFInst" -Name "Version" -ErrorAction SilentlyContinue if ($null -eq $intelChipset) { $intelChipset = ($Win32_PnPEntity | where Caption -like "*Intel*SMB*" | Get-PnpDeviceProperty | where KeyName -eq "DEVPKEY_Device_DriverVersion" | select Data -First 1).data } else { $intelChipset = $intelChipset.Version } if ($intelChipset) { addRow2 "intelChipset" "intelChipset" "Driver" $intelChipset '' $SysGUID } } if (($Device -eq 'AMDChipset') -or ($Device -eq '')) { #AMD Chipset $SysGUID = '4D36E97D-E325-11CE-BFC1-08002BE10318' $AMDChipset = $Win32_PnPEntity | where Caption -like "*AMD GPIO*" | Get-PnpDeviceProperty | where KeyName -eq "DEVPKEY_Device_DriverVersion" | select Data -First 1 if ($AMDChipset) { addRow2 "AMDChipset" "AMD GPIO" "Driver" $AMDChipset.Data '' $SysGUID } $AMDChipset = $Win32_PnPEntity | where Caption -like "*AMD PSP*" | Get-PnpDeviceProperty | where KeyName -eq "DEVPKEY_Device_DriverVersion" | select Data -First 1 if ($AMDChipset) { addRow2 "AMDChipset" "AMD PSP" "Driver" $AMDChipset.Data '' $SysGUID } $AMDChipset = $Win32_PnPEntity | where Caption -like "*AMD CCP*" | Get-PnpDeviceProperty | where KeyName -eq "DEVPKEY_Device_DriverVersion" | select Data -First 1 if ($AMDChipset) { addRow2 "AMDChipset" "AMD CCP" "Driver" $AMDChipset.Data '' $SysGUID } } if (($Device -eq 'NIC') -or ($Device -eq '')) { #Get-NetAdapter | fl name, InterfaceDescription, DriverFileName, DriverDate, DriverVersionString, NdisVersion $NetAdapters = Get-NetAdapter $NICGUID = '4D36E972-E325-11CE-BFC1-08002BE10318' if ($null -ne $($NetAdapters | where InterfaceDescription -like "*Mellanox*")) { $MellanoxFW = callProcess "$PSScriptRoot\mlxup.exe" "--query" $MellanoxFWName = $($MellanoxFW | findstr /c:'Device Type').Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[2] $MellanoxFWVersion = $($MellanoxFW | findstr FW).Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] if ($null -ne $MellanoxFWName) { addRow2 'NIC' $MellanoxFWName "FW" $MellanoxFWVersion '' $NICGUID } $Mellanoxs = $NetAdapters | where InterfaceDescription -Like *Mellanox* | sort InterfaceDescription | Select Name, InterfaceDescription, DriverVersionString foreach ($Mellanox in $Mellanoxs) { addRow2 'NIC' "$($Mellanox[0].InterfaceDescription)" "Driver" $Mellanox[0].DriverVersionString '' $NICGUID break; } } #Qlogic if ($null -ne $($NetAdapters | where InterfaceDescription -like "*Qlogic*")) { $QlogicFW = callProcessStdin "$PSScriptRoot\winfwnx2.exe" "" @('q') $QlogicFW = $QlogicFW -split "`r`n" for ($i = 0; $i -lt $QlogicFW.Length; $i++) { if ($QlogicFW[$i].ToUpper().IndexOf('QLOGIC') -ge 0) { if ($QlogicFW[$i].IndexOf(']') -ge 0) { $QlogicFWName = $($QlogicFW[$i].Split("]")[1].trim() -replace '\s+ ', '_').tostring().split('_')[0] $QlogicFWVersion = $($QlogicFW[$i].Split("]")[1].trim() -replace '\s+ ', '_').tostring().split('_')[1] addRow2 'NIC' $QlogicFWName "FW" $QlogicFWVersion '' $NICGUID } } } $Qlogics = $NetAdapters | where InterfaceDescription -Like *QLogic* | sort InterfaceDescription | Select Name, InterfaceDescription, DriverVersionString foreach ($Qlogic in $Qlogics) { addRow2 'NIC' "$($Qlogic[0].InterfaceDescription)" "Driver" $Qlogic[0].DriverVersionString '' $NICGUID break; } } #Intel if ($null -ne $($NetAdapters | where InterfaceDescription -like "*Intel*")) { $IntelNics = $NetAdapters | where InterfaceDescription -Like *Intel* | sort InterfaceDescription | Select Name, InterfaceDescription, DriverVersionString foreach ($IntelNic in $IntelNics) { addRow2 'NIC' "$($IntelNic[0].InterfaceDescription)" "Driver" $IntelNic[0].DriverVersionString '' $NICGUID break; } } } #Storage Controller if (($Device -eq 'HBA') -or ($Device -eq '')) { $sasinfo1 = $Win32_PnPEntity | where Caption -like "*SAS3*" | Get-PnpDeviceProperty | where KeyName -eq "DEVPKEY_Device_DriverVersion" | select Data $sasGUID = '4D36E97B-E325-11CE-BFC1-08002BE10318' if ($sasinfo1.count) { for ($i = 0; $i -lt $sasinfo1.count; $i++) { $sasinfo = callProcess "$PSScriptRoot\sas3flash.exe" " -c $i -list" $sasController = $($sasinfo | findstr /c:"Controller ").Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $sasfwversion1 = $($sasinfo | findstr /c:"NVDATA Version (Default)").Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $sasfwversion2 = $($sasinfo | findstr /c:"Firmware Product ID").Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $sasfwversion3 = $($sasinfo | findstr /c:"Firmware Version").Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() addRow2 'Storage Controller' $sasController "FW" $($sasfwversion1 + "_" + $sasfwversion3) '' $sasGUID addRow2 'Storage Controller' $sasController "Driver" $($sasinfo1[$i].Data) '' $sasGUID } } else { if ($sasinfo1) { $sasinfo = callProcess "$PSScriptRoot\sas3flash.exe" " -list" $sasController = $($sasinfo | findstr /c:"Controller ").Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $sasfwversion1 = $($sasinfo | findstr /c:"NVDATA Version (Default)").Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $sasfwversion2 = $($sasinfo | findstr /c:"Firmware Product ID").Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $sasfwversion3 = $($sasinfo | findstr /c:"Firmware Version").Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() addRow2 'Storage Controller' $sasController "FW" $($sasfwversion1 + "_" + $sasfwversion3) '' $sasGUID addRow2 'Storage Controller' $sasController "Driver" $($sasinfo1.Data) '' $sasGUID } } } #Expander if (($Device -eq 'Expander') -or ($Device -eq '')) { $commandlist = @" 1 show quit "@ $currentPath = Get-Location cd $PSScriptRoot $output = $commandlist | .\g4Xflash_x64.exe if ($output | findstr /c:"Firmware Version") { $expanderinfo = ($output | findstr /c:"Firmware Version").Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() } cd $currentPath if ($expanderinfo) { addRow2 'Expander' "Expander" "FW" $expanderinfo '' '' } } #Disk if (($Device -eq 'Disk') -or ($Device -eq '')) { $phds = $null $StorageNodes = Get-StorageNode | where Name -like "$(hostname)*" $disks = Get-Disk | where { ($_.BootFromDisk -eq $true) -or ($_.IsBoot -eq $true) } | select UniqueId foreach ($StorageNode in $StorageNodes) { $phds += Get-PhysicalDisk -StorageNode $StorageNode -PhysicallyConnected | where { $_.UniqueId -notin $disks.UniqueId } } $phds = $phds | where { $_.UniqueId -notin $disks.UniqueId } | select * $SSDs = $phds | where { $_.Mediatype -eq "SSD" } #| Get-StorageFirmwareInformation | ft FirmwareVersionInSlot foreach ($SSD in $SSDs) { addRow2 'Disk' $SSD.FriendlyName "FW" $SSD.FirmwareVersion $SSD.SerialNumber '' } $HDDs = $phds | where { $_.Mediatype -eq "HDD" } #| Get-StorageFirmwareInformation | ft FirmwareVersionInSlot foreach ($HDD in $HDDs) { addRow2 'Disk' $HDD.FriendlyName "FW" $HDD.FirmwareVersion $HDD.SerialNumber '' } } $script:table2 } function Get-ClusterDriver_FW() { [CmdletBinding()] [OutputType([Bool])] Param ( [Parameter(Mandatory = $false, Position = 0)] [ValidateSet($false, $true)] $SkipInstallPackage = $false, [Parameter(Mandatory = $true, Position = 1)] [string]$ClusterName = '', [Parameter(Mandatory = $false, Position = 2)] [ValidateNotNullOrEmpty()] [ValidateSet($true, $false, 1, 0)] $SKipCheck = $false ) $SKipCheck = [System.Convert]::ToBoolean($SKipCheck) if (-not $SKipCheck) { CheckVersion } $SkipInstallPackage = [System.Convert]::ToBoolean($SkipInstallPackage) $ClusterNodes = Get-ClusterNode -Cluster $ClusterName if (-not $SkipInstallPackage) { foreach ($ClusterNode in $ClusterNodes) { Invoke-Command -ComputerName $ClusterNode -ScriptBlock { Install-PackageProvider Nuget -Force Install-Module QCT-Update-Management -Force Import-Module QCT-Update-Management -Force } | out-null } } foreach ($CheckItem in $('BIOS', 'BMC', 'intelChipset', 'AMDChipset', 'NIC', 'HBA', 'Expander', 'Disk')) { foreach ($ClusterNode in $ClusterNodes) { $Driver_FWs = Invoke-Command -ComputerName $ClusterNode -ScriptBlock { param($CheckItem) Get-Driver_FW -Device $CheckItem } -ArgumentList $CheckItem foreach ($Driver_FW in $Driver_FWs) { Write-Host "$ClusterNode $CheckItem $($Driver_FW.DriverFW):" $Driver_FW.Version } } Write-Host "----------------------------------------------------------------" } } function Enable-DiskLocate() { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string]$SerialNumber = '' ) # CheckVersion $allController = callProcess "$PSScriptRoot\storcli.exe" "show ctrlcount" $ctrlCount = $($($allController -split "`r`n" | Select-String -Pattern 'Controller') -split '=')[1].ToString().Trim() for ($i = 0; $i -lt $ctrlCount; $i++) { $alldiskStr = callProcess "$PSScriptRoot\storcli.exe" "/c$i show all" $diskStr = $alldiskStr -split "`r`n" | Select-String -Pattern $SerialNumber -Context 6 if ($diskStr) { $disklocation = $($($diskStr.ToString() -split "`r`n" | Select-String "Drive").ToString().Trim() -split " ")[1] if ($disklocation) { return callProcess "$PSScriptRoot\storcli.exe" "$disklocation start locate" } } } return "Failed." } function Disable-DiskLocate() { [CmdletBinding()] Param ( [Parameter(Mandatory = $false, Position = 0)] [string]$SerialNumber = '' ) # CheckVersion $allController = callProcess "$PSScriptRoot\storcli.exe" "show ctrlcount" $ctrlCount = $($($allController -split "`r`n" | Select-String -Pattern 'Controller') -split '=')[1].ToString().Trim() for ($i = 0; $i -lt $ctrlCount; $i++) { $alldiskStr = callProcess "$PSScriptRoot\storcli.exe" "/c$i show all" $diskStr = $alldiskStr -split "`r`n" | Select-String -Pattern $SerialNumber -Context 6 if ($diskStr) { $disklocation = $($($diskStr.ToString() -split "`r`n" | Select-String "Drive").ToString().Trim() -split " ")[1] if ($disklocation) { return callProcess "$PSScriptRoot\storcli.exe" "$disklocation stop locate" } } } return "Failed." } function checkModel($Model) { $Brand = 'unknow' $Series = 'unknow' if ($Model -like '*INTEL*') { $Brand = 'INTEL' } elseif ($Model -like '*SAMSUNG*') { $Brand = 'SAMSUNG' } elseif ($Model -like '*TOSHIBA*') { $Brand = 'TOSHIBA' } else { $Brand = 'unknow' } if ($Brand -eq 'INTEL') { if ($Model -like '*SSDSC2BA*4*') { $Series = 'INTEL_S3710' } elseif ($Model -like '*SSDSC2BB*6*') { $Series = 'INTEL_S3510' } elseif (($Model -like '*SSDSC2BB*7*') -or ($Model -like '*SSDSCKJB*7*')) { $Series = 'INTEL_S3520' } elseif ($Model -like '*SSDSC2KB*7*') { $Series = 'INTEL_S4500' } elseif ($Model -like '*SSDSC2KB*8*') { $Series = 'INTEL_D3-S4510' } elseif ($Model -like '*SSDSC2KG*7*') { $Series = 'INTEL_S4600' } elseif ($Model -like '*SSDSC2KG*8*') { $Series = 'INTEL_D3-S4610' } elseif ($Model -like '*SSDPEKKA512G7*') { $Series = 'INTEL_P3100' } elseif (($Model -like '*SSDPE2MD*4*') -or ($Model -like '*SSDPEDMD*4*')) { $Series = 'INTEL_P3700' } elseif (($Model -like '*SSDPEDKX*7*') -or ($Model -like '*SSDPE2KX*7*')) { $Series = 'INTEL_P4500' } elseif ($Model -like '*SSDPE7KX*7*') { $Series = 'INTEL_P4501' } elseif ($Model -like '*SSDPE2KX*8*') { $Series = 'INTEL_P4510' } elseif ($Model -like '*SSDPELKX*8*') { $Series = 'INTEL_P4511' } elseif (($Model -like '*SSDPE2KE*7*') -or ($Model -like '*SSDPEDKE*7*')) { $Series = 'INTEL_P4600' } elseif ($Model -like '*SSDPE7KE*7*') { $Series = 'INTEL_P4601' } elseif ($Model -like '*SSDPE2KE*8*') { $Series = 'INTEL_P4610' } elseif (($Model -like '*SSDPED1K*A*') -or ($Model -like '*SSDPE21K*A*')) { $Series = 'INTEL_P4800X' } else { $Series = 'unknow' } } elseif ($Brand -eq 'SAMSUNG') { if ($Model -like '*MZ7KM*HA*') { $Series = 'SAMSUNG_SM863' } elseif ($Model -like '*MZ7KM*HM*') { $Series = 'SAMSUNG_SM863a' } elseif ($Model -like '*MZ7KH*HA*') { $Series = 'SAMSUNG_SM883' } elseif ($Model -like '*MZQLB*H*') { $Series = 'SAMSUNG_PM983' } elseif ($Model -like '*MZQLW*H*') { $Series = 'SAMSUNG_PM963' } elseif ($Model -like '*MZ7LH*H*') { $Series = 'SAMSUNG_PM883' } elseif ($Model -like '*MZ7LM*H*') { $Series = 'SAMSUNG_PM863a' } elseif (($Model -like '*MZPLL*HMLA*') -or ($Model -like '*MZPLL*HAJQ*') -or ($Model -like '*MZWLL*HMLA*') -or ($Model -like '*MZWLL*HAJQ*')) { $Series = 'SAMSUNG_PM1725b' } elseif (($Model -like '*MZPLL*HMLS*') -or ($Model -like '*MZPLL*HEHP*') -or ($Model -like '*MZWLL*HEHP*') -or ($Model -like '*MZWLL*HMJP*') -or ($Model -like '*MZWLL*HMLS*')) { $Series = 'SAMSUNG_PM1725a' } elseif ($Model -like '*MZILT*H*') { $Series = 'SAMSUNG_PM1643' } elseif ($Model -like '*MZILS*H*') { $Series = 'SAMSUNG_PM1633a' } else { $Series = 'unknow' } } elseif ($Brand -eq 'TOSHIBA') { if ($Model -like '*THNSNJ800PCSZ*') { $Series = 'Toshiba_HK3E2' } else { $Series = 'unknow' } } else { if ($Model -like '*ST8000*') { $Series = 'SEAGATE_Archive_HDD_v2' } else { $Series = 'unknow' } } return $Series } function checkLifetime($smartInfo) { $Wear_Leveling_Count = 0 $Wear_Leveling_Count_Threshold = 0 if ($null -ne $($smartInfo -split "`r`n" | Select-String "Wear_Leveling_Count")) { # Samsung SSD 99 to 0 $Wear_Leveling_Count = [int] $($smartInfo -split "`r`n" | Select-String "Wear_Leveling_Count").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[3].Trim() $Wear_Leveling_Count_Threshold = [int] $($smartInfo -split "`r`n" | Select-String "Wear_Leveling_Count").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[5].Trim() } elseif ($null -ne $($smartInfo -split "`r`n" | Select-String "Media_Wearout_Indicator")) { # INTEL SSD 100 to 1 $Wear_Leveling_Count = $($smartInfo -split "`r`n" | Select-String "Media_Wearout_Indicator").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[3].Trim() $Wear_Leveling_Count_Threshold = $($smartInfo -split "`r`n" | Select-String "Media_Wearout_Indicator").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[5].Trim() } elseif ($null -ne $($smartInfo -split "`r`n" | Select-String "Available Spare:")) { #INTEL NVME $Wear_Leveling_Count = $($smartInfo -split "`r`n" | Select-String "Available Spare:").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim().Replace('%', '') $Wear_Leveling_Count_Threshold = $($smartInfo -split "`r`n" | Select-String "Available Spare Threshold:").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim().Replace('%', '') } else { $Wear_Leveling_Count = 'none' $Wear_Leveling_Count_Threshold = 'none' } $Wear_Leveling_Count $Wear_Leveling_Count_Threshold } function checkPoweronHour($smartInfo) { if ($smartInfo -split "`r`n" | Select-String "Power_On_Hours") { $Power_On_Hours = $($smartInfo -split "`r`n" | Select-String "Power_On_Hours").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[9].Trim() } elseif ($smartInfo -split "`r`n" | Select-String "Power On Hours:") { $Power_On_Hours = $($smartInfo -split "`r`n" | Select-String "Power On Hours:").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() } else { $Power_On_Hours = "none" } if ($smartInfo -split "`r`n" | Select-String "Power_Cycle_Count") { $Power_Cycle_Count = $($smartInfo -split "`r`n" | Select-String "Power_Cycle_Count").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[9].Trim() } elseif ($smartInfo -split "`r`n" | Select-String "Power Cycles:") { $Power_Cycle_Count = $($smartInfo -split "`r`n" | Select-String "Power Cycles:").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() } else { $Power_Cycle_Count = "none" } $Power_On_Hours $Power_Cycle_Count } function checkUserCapacity($smartInfo) { if ($smartInfo -split "`r`n" | Select-String "User Capacity") { $userCapacity = $($smartInfo -split "`r`n" | Select-String "User Capacity").ToString().Split('[', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim().Replace(']', '').Replace(' ', '_') } elseif ($smartInfo -split "`r`n" | Select-String "Namespace 1 Size/Capacity") { $userCapacity = $($smartInfo -split "`r`n" | Select-String "Namespace 1 Size/Capacity").ToString().Split('[', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim().Replace(']', '').Replace(' ', '_') } else { $userCapacity = 'none' } $userCapacity } function Write-HostColored() { [CmdletBinding(ConfirmImpact = 'None', SupportsShouldProcess = $false, SupportsTransactions = $false)] param( [parameter(Position = 0, ValueFromPipeline = $true)] [string[]] $Text , [switch] $NoNewline , [ConsoleColor] $BackgroundColor = $host.UI.RawUI.BackgroundColor , [ConsoleColor] $ForegroundColor = $host.UI.RawUI.ForegroundColor ) begin { if ($null -ne $Text) { $Text = "$Text" } } process { if ($Text) { $curFgColor = $ForegroundColor $curBgColor = $BackgroundColor $tokens = $Text.split("#") $prevWasColorSpec = $false foreach ($token in $tokens) { if (-not $prevWasColorSpec -and $token -match '^([a-z]+)(:([a-z]+))?$') { # a potential color spec. try { $curFgColor = [ConsoleColor] $matches[1] $prevWasColorSpec = $true } catch {} if ($matches[3]) { try { $curBgColor = [ConsoleColor] $matches[3] $prevWasColorSpec = $true } catch {} } if ($prevWasColorSpec) { continue } } $prevWasColorSpec = $false if ($token) { $argsHash = @{} if ([int] $curFgColor -ne -1) { $argsHash += @{ 'ForegroundColor' = $curFgColor } } if ([int] $curBgColor -ne -1) { $argsHash += @{ 'BackgroundColor' = $curBgColor } } Write-Host -NoNewline @argsHash $token } $curFgColor = $ForegroundColor $curBgColor = $BackgroundColor } } if (-not $NoNewLine) { write-host } } } function Get-SmartInfo() { [CmdletBinding()] [OutputType([Bool])] Param ( [Parameter(Mandatory = $false, Position = 0)] [ValidateSet($false, $true)] $Color = $false ) # CheckVersion $Color = [System.Convert]::ToBoolean($Color) $smartPath = "$PSScriptRoot\smartctl.exe" $disks = callProcess $smartPath "--scan" 1 $diskArray = @() foreach ($disk in $($disks -split "`r`n")) { if ($($disk | select-string '/dev/')) { $disk = $($disk -split ' ' )[0] $smartInfo = callProcess $smartPath " -A -i -H $disk -s on" 0.2 if (-not $($smartInfo -split "`r`n" | Select-String "Open failed")) { $smartResult = $($smartInfo -split "`r`n" | Select-String "SMART overall-health self-assessment test result").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() if ($smartInfo -split "`r`n" | Select-String "Sector Size") { $sectorSize = [int] $($smartInfo -split "`r`n" | Select-String "Sector Size").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[2] } else { $sectorSize = [int] 512 } $Model = $($smartInfo -split "`r`n" | Select-String "Device Model").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim().ToUpper().Replace(' ', '_') $serialNumber = $($smartInfo -split "`r`n" | Select-String "Serial Number").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $return = checkPoweronHour $smartInfo $Power_On_Hours = $return[0] $Power_Cycle_Count = $return[1] $userCapacity = checkUserCapacity $smartInfo if ($smartInfo -split "`r`n" | Select-String "Rotation Rate") { $RotationRate = $($smartInfo -split "`r`n" | Select-String "Rotation Rate").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim().ToUpper() } else { $RotationRate = 'none' } $Series = checkModel $Model if ($RotationRate.IndexOf('RPM') -ge 0) { $diskType = 'HDD' } else { $diskType = 'SSD' } $Reallocated_Sector_Ct = 0 $Current_Pending_Sector = 0 $Offline_Uncorrectable = 0 if ($null -ne $($smartInfo -split "`r`n" | Select-String "Reallocated_Sector_Ct")) { $Reallocated_Sector_Ct = [int] $($smartInfo -split "`r`n" | Select-String "Reallocated_Sector_Ct").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[9].Replace('[', '') } if ($null -ne $($smartInfo -split "`r`n" | Select-String "Current_Pending_Sector")) { $Current_Pending_Sector = [int] $($smartInfo -split "`r`n" | Select-String "Current_Pending_Sector").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[9].Replace('[', '') } if ($null -ne $($smartInfo -split "`r`n" | Select-String "Offline_Uncorrectable")) { $Offline_Uncorrectable = [int] $($smartInfo -split "`r`n" | Select-String "Offline_Uncorrectable").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[9].Replace('[', '') } if ($null -ne $($smartInfo -split "`r`n" | Select-String "Command_Timeout")) { $Command_Timeout = [long] $($smartInfo -split "`r`n" | Select-String "Command_Timeout").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[9].Replace('[', '') } if ($null -ne $($smartInfo -split "`r`n" | Select-String "Spin_Retry_Count")) { $Spin_Retry_Count = [int] $($smartInfo -split "`r`n" | Select-String "Spin_Retry_Count").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[9].Replace('[', '') } if ($null -ne $($smartInfo -split "`r`n" | Select-String "End-to-End_Error")) { $End_to_End_Error = [int] $($smartInfo -split "`r`n" | Select-String "End-to-End_Error").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[9].Replace('[', '') } $smartCaution = '' if ($Reallocated_Sector_Ct + $Current_Pending_Sector + $Offline_Uncorrectable + $Spin_Retry_Count + $End_to_End_Error -gt 0) { $smartResult = 'Caution' #$smartCaution = 'Reallocated Sector Ct:' + $Reallocated_Sector_Ct + "`n" + 'Current Pending Sector:' + $Current_Pending_Sector + "`n" +'Offline Uncorrectable:' + $Offline_Uncorrectable if ($Reallocated_Sector_Ct -gt 0) { $smartCaution += 'Reallocated Sector Ct:' + $Reallocated_Sector_Ct + "`n" } if ($Current_Pending_Sector -gt 0) { $smartCaution += 'Current Pending Sector:' + $Current_Pending_Sector + "`n" } if ($Offline_Uncorrectable -gt 0) { $smartCaution += 'Offline Uncorrectable:' + $Offline_Uncorrectable + "`n" } if ($Spin_Retry_Count -gt 0) { $smartCaution += 'Spin Retry Count:' + $Spin_Retry_Count + "`n" } if ($End_to_End_Error -gt 0) { $smartCaution += 'End-to-End error:' + $End_to_End_Error + "`n" } if ($Command_Timeout -gt 0) { $smartCaution += 'Command Timeout:' + $Command_Timeout + "`n" } } $Total_LBAs_Written = [long] $(($smartInfo -split "`r`n") -like "241 *").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[9] $Total_Host_Write = 0 if (($Model.IndexOf('INTEL') -ge 0) -or ($Model.IndexOf('TOSHIBA') -ge 0)) { $Total_Host_Write = "{0:n2}" -f $($Total_LBAs_Written * 32 / 1024) #GB } else { $Total_Host_Write = "{0:N2}" -f $($Total_LBAs_Written * $($sectorSize / 1024) / 1024 / 1024) #GB } if ($Total_Host_Write -eq "0.00") { $Total_Host_Write = "N/A" } else { $Total_Host_Write = "$Total_Host_Write GB" } $return = checkLifetime $smartInfo $Wear_Leveling_Count = $return[0] $Wear_Leveling_Count_Threshold = $return[1] if ($Color -and ($smartResult -ne 'PASSED')) { Write-HostColored "$disk $Series $userCapacity $Model #yellow#$smartResult# $serialNumber $Total_Host_Write $Wear_Leveling_Count $Wear_Leveling_Count_Threshold $Power_On_Hours $Power_Cycle_Count" } $diskObj = New-Object -TypeName PSObject $diskObj | Add-Member -Name 'Name' -MemberType Noteproperty -Value $disk $diskObj | Add-Member -Name 'Series' -MemberType Noteproperty -Value $Series $diskObj | Add-Member -Name 'userCapacity' -MemberType Noteproperty -Value $disk $diskObj | Add-Member -Name 'Model' -MemberType Noteproperty -Value $Model $diskObj | Add-Member -Name 'smartResult' -MemberType Noteproperty -Value $smartResult $diskObj | Add-Member -Name 'serialNumber' -MemberType Noteproperty -Value $serialNumber $diskObj | Add-Member -Name 'Total_Host_Write' -MemberType Noteproperty -Value $Total_Host_Write $diskObj | Add-Member -Name 'Wear_Leveling_Count' -MemberType Noteproperty -Value $Wear_Leveling_Count $diskObj | Add-Member -Name 'Wear_Leveling_Count_Threshold' -MemberType Noteproperty -Value $Wear_Leveling_Count_Threshold $diskObj | Add-Member -Name 'Power_On_Hours' -MemberType Noteproperty -Value $Power_On_Hours $diskObj | Add-Member -Name 'Power_Cycle_Count' -MemberType Noteproperty -Value $Power_Cycle_Count $diskObj | Add-Member -Name 'SmartCaution' -MemberType Noteproperty -Value $smartCaution $diskArray += $diskObj } } } $disks = callProcess $smartPath "-d nvme --scan" 1 foreach ($disk in $($disks -split "`r`n")) { if ($($disk | select-string '/dev/')) { $disk = $($disk -split ' ' )[0] $smartInfo = callProcess $smartPath " -A -i -H $disk -s on" 0.3 $smartResult = $($smartInfo -split "`r`n" | Select-String "SMART overall-health self-assessment test result").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $sectorSize = [int] 512 # $($smartInfo -split "`r`n" | Select-String "Sector Size").ToString().Split(' ',[System.StringSplitOptions]::RemoveEmptyEntries)[2] $Model = $($smartInfo -split "`r`n" | Select-String "Model").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim().ToUpper().Replace(' ', '_') $serialNumber = $($smartInfo -split "`r`n" | Select-String "Serial Number").ToString().Split(':', [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $return = checkPoweronHour $smartInfo $Power_On_Hours = $return[0] $Power_Cycle_Count = $return[1] $userCapacity = checkUserCapacity $smartInfo $Series = checkModel $Model if ($($smartInfo -split "`r`n" | Select-String "Data Units Written").ToString().IndexOf('PB') -ge 0) { $Data_Units_Written = "{0:n2}" -f $(1024 * 1024 * [int] $($smartInfo -split "`r`n" | Select-String "Data Units Written").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[4].Replace('[', '')) } elseif ($($smartInfo -split "`r`n" | Select-String "Data Units Written").ToString().IndexOf('TB') -ge 0) { $Data_Units_Written = "{0:n2}" -f $(1024 * [int] $($smartInfo -split "`r`n" | Select-String "Data Units Written").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[4].Replace('[', '')) } elseif ($($smartInfo -split "`r`n" | Select-String "Data Units Written").ToString().IndexOf('GB') -ge 0) { $Data_Units_Written = "{0:n2}" -f $([int] $($smartInfo -split "`r`n" | Select-String "Data Units Written").ToString().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[4].Replace('[', '')) } $smartCaution = '' $return = checkLifetime $smartInfo $Wear_Leveling_Count = $return[0] $Wear_Leveling_Count_Threshold = $return[1] if ($Color -and ($smartResult -ne 'PASSED')) { Write-HostColored "$disk $Series $userCapacity $Model #yellow#$smartResult# $serialNumber $Data_Units_Written $Wear_Leveling_Count $Wear_Leveling_Count_Threshold $Power_On_Hours $Power_Cycle_Count" } $diskObj = New-Object -TypeName PSObject $diskObj | Add-Member -Name 'Name' -MemberType Noteproperty -Value $disk $diskObj | Add-Member -Name 'Series' -MemberType Noteproperty -Value $Series $diskObj | Add-Member -Name 'userCapacity' -MemberType Noteproperty -Value $userCapacity $diskObj | Add-Member -Name 'Model' -MemberType Noteproperty -Value $Model $diskObj | Add-Member -Name 'smartResult' -MemberType Noteproperty -Value $smartResult $diskObj | Add-Member -Name 'serialNumber' -MemberType Noteproperty -Value $serialNumber $diskObj | Add-Member -Name 'Total_Host_Write' -MemberType Noteproperty -Value "$Data_Units_Written GB" $diskObj | Add-Member -Name 'Wear_Leveling_Count' -MemberType Noteproperty -Value $Wear_Leveling_Count $diskObj | Add-Member -Name 'Wear_Leveling_Count_Threshold' -MemberType Noteproperty -Value $Wear_Leveling_Count_Threshold $diskObj | Add-Member -Name 'Power_On_Hours' -MemberType Noteproperty -Value $Power_On_Hours $diskObj | Add-Member -Name 'Power_Cycle_Count' -MemberType Noteproperty -Value $Power_Cycle_Count $diskObj | Add-Member -Name 'SmartCaution' -MemberType Noteproperty -Value $smartCaution $diskArray += $diskObj } } $diskArray } function Update-OEMFirmware-LSI { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string]$FwPath = '', [Parameter(Mandatory = $true, Position = 1)] [string]$Mptsas = '', [Parameter(Mandatory = $true, Position = 2)] [string]$Mptx64 = '' ) # CheckVersion $script:tableFW = @() function addRowFW($FWType, $FWVersion, $FWVersionNew) { $row2 = New-Object -TypeName PSObject $row2 | Add-Member -Name 'Type' -MemberType Noteproperty -Value $FWType $row2 | Add-Member -Name 'FWVersion' -MemberType Noteproperty -Value $FWVersion $row2 | Add-Member -Name 'FWVersionNew' -MemberType Noteproperty -Value $FWVersionNew $script:tableFW += $row2 } $OEMStorageControllPath = $PSScriptRoot $sasinfo = callProcess "$OEMStorageControllPath\sas3flash.exe" "-list" + [System.Environment]::NewLine #Invoke-Expression -Command:"cmd.exe /C $OEMStorageControllPath\sas3flash.exe -list" $sasinfo1 = Get-WmiObject Win32_PnPSignedDriver | select devicename, driverversion | where { $_.devicename -like "*SAS3*" } $LsiFWVersion = $($sasinfo -split "`r`n" | Select-String "NVDATA Version" -CaseSensitive).line.Split(":", [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $LsiBIOSVersion = $($sasinfo -split "`r`n" | Select-String "BIOS" -CaseSensitive).line.Split(":", [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $LsiUEFIVersion = $($sasinfo -split "`r`n" | Select-String "UEFI" -CaseSensitive).line.Split(":", [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() if ($sasinfo1.count) { for ($i = 0; $i -lt $sasinfo1.count; $i++) { #LSI Firmware $sasinfo += callProcess "$OEMStorageControllPath\sas3flash.exe" " -c $i -f $FwPath" + [System.Environment]::NewLine #Invoke-Expression -Command:"cmd.exe /C $OEMStorageControllPath\sas3flash.exe -f $FwPath" -Verbose Sleep 5 #LSI Legacy Mode BIOS $sasinfo += callProcess "$OEMStorageControllPath\sas3flash.exe" " -c $i -b $Mptsas" + [System.Environment]::NewLine #Invoke-Expression -Command:"cmd.exe /C $OEMStorageControllPath\sas3flash.exe -b $Mptsas" -Verbose Sleep 5 #LSI UEFI Mode BIOS $sasinfo += callProcess "$OEMStorageControllPath\sas3flash.exe" " -c $i -b $Mptx64" + [System.Environment]::NewLine #Invoke-Expression -Command:"cmd.exe /C $OEMStorageControllPath\sas3flash.exe -b $Mptx64" -Verbose } } else { #LSI Firmware $sasinfo += callProcess "$OEMStorageControllPath\sas3flash.exe" " -f $FwPath" + [System.Environment]::NewLine Sleep 5 #LSI Legacy Mode BIOS $sasinfo += callProcess "$OEMStorageControllPath\sas3flash.exe" " -b $Mptsas" + [System.Environment]::NewLine Sleep 5 #LSI UEFI Mode BIOS $sasinfo += callProcess "$OEMStorageControllPath\sas3flash.exe" " -b $Mptx64" + [System.Environment]::NewLine } $sasinfoNew = callProcess "$OEMStorageControllPath\sas3flash.exe" "-list" #Invoke-Expression -Command:"cmd.exe /C $OEMStorageControllPath\sas3flash.exe -list" $LsiFWVersionNew = $($sasinfoNew -split "`r`n" | Select-String "NVDATA Version" -CaseSensitive).line.Split(":", [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $LsiBIOSVersionNew = $($sasinfoNew -split "`r`n" | Select-String "BIOS" -CaseSensitive).line.Split(":", [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() $LsiUEFIVersionNew = $($sasinfoNew -split "`r`n" | Select-String "UEFI" -CaseSensitive).line.Split(":", [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() addRowFW 'BIOS' $LsiBIOSVersion $LsiBIOSVersionNew addRowFW 'UEFI' $LsiUEFIVersion $LsiUEFIVersionNew addRowFW 'FW' $LsiFWVersion $LsiFWVersionNew $script:tableFW $script:rebootneed = 1 } function Update-OEMFirmware-Mellanox { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string]$FwPath = '' ) # CheckVersion $script:tableFW = @() function addRowFW($FWType, $FWVersion, $FWVersionNew) { $row2 = New-Object -TypeName PSObject $row2 | Add-Member -Name 'Type' -MemberType Noteproperty -Value $FWType $row2 | Add-Member -Name 'FWVersion' -MemberType Noteproperty -Value $FWVersion $row2 | Add-Member -Name 'FWVersionNew' -MemberType Noteproperty -Value $FWVersionNew $script:tableFW += $row2 } #Mellanox Firmware Update $OEMMellanoxPath = $PSScriptRoot $nicinfo = callProcess "$OEMMellanoxPath\mlxup.exe" " -query --sfx-extract-dir C:\Windows\Temp" $MellanoxFWName = $($nicinfo -split "`r`n" | Select-String 'Device Type').line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[2] $MellanoxFWVersion = $($nicinfo -split "`r`n" | Select-String "FW" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxCLPVersion = $($nicinfo -split "`r`n" | Select-String "CLP" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxPXEVersion = $($nicinfo -split "`r`n" | Select-String "PXE" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxUEFIVersion = $($nicinfo -split "`r`n" | Select-String "UEFI" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxFWPSID = $($nicinfo -split "`r`n" | Select-String "PSID" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxPDName = $($nicinfo -split "`r`n" | Select-String "PCI Device Name" -CaseSensitive).line.Split(":", [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() if ($($nicinfo | Select-String "ConnectX3Pro").length) { $result = callProcess "$OEMMellanoxPath\mlxup.exe" " -i $FwPath --sfx-extract-dir C:\Windows\Temp -u -f -y" if ($($result | Select-String "100%Done").length) { $resultNew = callProcess "$OEMMellanoxPath\mlxup.exe" $MellanoxFWVersionNew = $($resultNew -split "`r`n" | Select-String "FW" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxCLPVersionNew = $($resultNew -split "`r`n" | Select-String "CLP" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxPXEVersionNew = $($resultNew -split "`r`n" | Select-String "PXE" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxUEFIVersionNew = $($resultNew -split "`r`n" | Select-String "UEFI" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] addRowFW 'CLP' $MellanoxCLPVersion $MellanoxCLPVersionNew addRowFW 'PXE' $MellanoxPXEVersion $MellanoxPXEVersionNew addRowFW 'UEFI' $MellanoxUEFIVersion $MellanoxUEFIVersionNew addRowFW 'FW' $MellanoxFWVersion $MellanoxFWVersionNew $script:tableFW } $script:rebootneed = 1 } elseif ($($nicinfo | Select-String "ConnectX4").length) { $result = callProcess "$OEMMellanoxPath\mlxup.exe" " -i $FwPath --sfx-extract-dir C:\Windows\Temp -u -f -y" if ($($result | Select-String "100%Done").length) { Reset-OEMFirmware-Mellanox -Verbose $resultNew = callProcess "$OEMMellanoxPath\mlxup.exe" $MellanoxFWVersionNew = $($resultNew -split "`r`n" | Select-String "FW" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxCLPVersionNew = $($resultNew -split "`r`n" | Select-String "CLP" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxPXEVersionNew = $($resultNew -split "`r`n" | Select-String "PXE" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxUEFIVersionNew = $($resultNew -split "`r`n" | Select-String "UEFI" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] addRowFW 'CLP' $MellanoxCLPVersion $MellanoxCLPVersionNew addRowFW 'PXE' $MellanoxPXEVersion $MellanoxPXEVersionNew addRowFW 'UEFI' $MellanoxUEFIVersion $MellanoxUEFIVersionNew addRowFW 'FW' $MellanoxFWVersion $MellanoxFWVersionNew $script:tableFW } $script:rebootneed = 1 } } function Reset-OEMFirmware-Mellanox { # CheckVersion function addRowFW($FWType, $FWVersion, $FWVersionNew) { $row2 = New-Object -TypeName PSObject $row2 | Add-Member -Name 'Type' -MemberType Noteproperty -Value $FWType $row2 | Add-Member -Name 'FWVersion' -MemberType Noteproperty -Value $FWVersion $row2 | Add-Member -Name 'FWVersionNew' -MemberType Noteproperty -Value $FWVersionNew $script:tableFW += $row2 } #Mellanox Firmware Update $OEMMellanoxPath = $PSScriptRoot $nicinfo = callProcess "$OEMMellanoxPath\mlxup.exe" " -query --sfx-extract-dir C:\Windows\Temp" $MellanoxFWName = $($nicinfo -split "`r`n" | Select-String 'Device Type').line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[2] $MellanoxFWVersion = $($nicinfo -split "`r`n" | Select-String "FW" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxFWPSID = $($nicinfo -split "`r`n" | Select-String "PSID" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxPDName = $($nicinfo -split "`r`n" | Select-String "PCI Device Name" -CaseSensitive).line.Split(":", [System.StringSplitOptions]::RemoveEmptyEntries)[1].Trim() # $nicinfo if ($($nicinfo | Select-String "ConnectX4").length) { $result = callProcessWorkingDirectory "$OEMMellanoxPath\mlxfwreset.exe" " -d mt4117_pciconf0 -l 3 reset -y" $resultNew = callProcess "$OEMMellanoxPath\mlxup.exe" $MellanoxFWVersionNew = $($resultNew -split "`r`n" | Select-String "FW" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxCLPVersionNew = $($resultNew -split "`r`n" | Select-String "CLP" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxPXEVersionNew = $($resultNew -split "`r`n" | Select-String "PXE" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] $MellanoxUEFIVersionNew = $($resultNew -split "`r`n" | Select-String "UEFI" -CaseSensitive).line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[1] addRowFW 'CLP' $MellanoxCLPVersion $MellanoxCLPVersionNew addRowFW 'PXE' $MellanoxPXEVersion $MellanoxPXEVersionNew addRowFW 'UEFI' $MellanoxUEFIVersion $MellanoxUEFIVersionNew addRowFW 'FW' $MellanoxFWVersion $MellanoxFWVersionNew $script:tableFW $script:rebootneed = 1 } } function Query-OEMFirmware-Mellanox { # CheckVersion #Mellanox Firmware Update $OEMMellanoxPath = $PSScriptRoot $nicinfo = callProcess "$OEMMellanoxPath\mlxup.exe" " -query --sfx-extract-dir C:\Windows\Temp" $nicinfo } function Update-OEMFirmware-QLogic { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string]$FwPath = '' ) # CheckVersion $script:tableFW = @() function addRowFW($FWType, $FWVersion, $FWVersionNew) { $row2 = New-Object -TypeName PSObject $row2 | Add-Member -Name 'Type' -MemberType Noteproperty -Value $FWType $row2 | Add-Member -Name 'FWVersion' -MemberType Noteproperty -Value $FWVersion $row2 | Add-Member -Name 'FWVersionNew' -MemberType Noteproperty -Value $FWVersionNew $script:tableFW += $row2 } #QLogic Firmware Update $OEMQLogicPath = $PSScriptRoot $QlogicFW = callProcessStdin "$PSScriptRoot\winfwnx2.exe" "" @('q') $QlogicFW = $QlogicFW -split "`r`n" for ($i = 0; $i -lt $QlogicFW.Length; $i++) { if ($QlogicFW[$i].ToUpper().IndexOf('QLOGIC') -ge 0) { if ($QlogicFW[$i].IndexOf(']') -ge 0) { $QlogicFWName = $($QlogicFW[$i].Split("]")[1].trim() -replace '\s+ ', '_').tostring().split('_')[0] $QlogicFWVersion = $($QlogicFW[$i].Split("]")[1].trim() -replace '\s+ ', '_').tostring().split('_')[1] # $QlogicFWVersion } } } $nicinfo = callProcessStdin "$OEMQLogicPath\winfwnx2.exe" "" @('q') $FwPath2 = $FwPath.Replace("\", "/") $nicinfo = callProcess "$OEMQLogicPath\winfwnx2.exe" " -all upgrade -f -mbi $FwPath2 qlgcrestore" $QlogicFW = callProcessStdin "$PSScriptRoot\winfwnx2.exe" "" @('q') $QlogicFW = $QlogicFW -split "`r`n" for ($i = 0; $i -lt $QlogicFW.Length; $i++) { if ($QlogicFW[$i].ToUpper().IndexOf('QLOGIC') -ge 0) { if ($QlogicFW[$i].IndexOf(']') -ge 0) { $QlogicFWNameNew = $($QlogicFW[$i].Split("]")[1].trim() -replace '\s+ ', '_').tostring().split('_')[0] $QlogicFWVersionNew = $($QlogicFW[$i].Split("]")[1].trim() -replace '\s+ ', '_').tostring().split('_')[1] # $QlogicFWVersionNew } } } addRowFW 'FW' $QlogicFWVersion $QlogicFWVersionNew $script:tableFW $script:rebootneed = 1 } function Update-OEMFirmware-Disk { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string]$FwPath = '', [Parameter(Mandatory = $true, Position = 1)] [string]$SerialNumber = '' ) # CheckVersion $script:tableFW = @() function addRowFW($FWType, $FWVersion, $FWVersionNew) { $row2 = New-Object -TypeName PSObject $row2 | Add-Member -Name 'Type' -MemberType Noteproperty -Value $FWType $row2 | Add-Member -Name 'FWVersion' -MemberType Noteproperty -Value $FWVersion $row2 | Add-Member -Name 'FWVersionNew' -MemberType Noteproperty -Value $FWVersionNew $script:tableFW += $row2 } $pd = Get-PhysicalDisk | Where-Object SerialNumber -eq $SerialNumber $SupportsUpdate = ($pd | Get-StorageFirmwareInformation).SupportsUpdate if ($SupportsUpdate) { $pdFWVersion = (Get-PhysicalDisk -SerialNumber $SerialNumber | select FirmwareVersion).FirmwareVersion $pd | Update-StorageFirmware -ImagePath $FwPath -SlotNumber 0 # Get-PhysicalDisk | Where-Object SerialNumber -eq $SerialNumber | Get-StorageFirmwareInformation | select FirmwareVersionInSlot | out-string $pdFWVersionNew = (Get-PhysicalDisk -SerialNumber $SerialNumber | select FirmwareVersion).FirmwareVersion addRowFW 'FW' $pdFWVersion $pdFWVersionNew $script:tableFW } else { $SupportsUpdate | out-string } } function Get-Driver_Information { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string]$Path = '', [Parameter(Mandatory = $false, Position = 1)] [ValidateNotNullOrEmpty()] [ValidateSet($true, $false, 1, 0)] [bool]$Recursive = $false ) # CheckVersion $script:DriverList = @() function addRow2($File2, $Path2, $Provider2, $Version2, $DriverVersion2, $DriverDate2, $GUID2, $Class2) { $row2 = New-Object -TypeName PSObject $row2 | Add-Member -Name 'File' -MemberType Noteproperty -Value $File2 $row2 | Add-Member -Name 'Path' -MemberType Noteproperty -Value $Path2 $row2 | Add-Member -Name 'Provider' -MemberType Noteproperty -Value $Provider2 $row2 | Add-Member -Name 'Version' -MemberType Noteproperty -Value $Version2 $row2 | Add-Member -Name 'DriverVersion' -MemberType Noteproperty -Value $DriverVersion2 $row2 | Add-Member -Name 'DriverDate' -MemberType Noteproperty -Value $DriverDate2 $row2 | Add-Member -Name 'GUID' -MemberType Noteproperty -Value $GUID2 $row2 | Add-Member -Name 'Class' -MemberType Noteproperty -Value $Class2 $script:DriverList += $row2 } $driversCollection = (Get-ChildItem -Path "$Path" -Filter "*.inf" -recurse:$Recursive -ErrorAction SilentlyContinue | select -ExpandProperty FullName) foreach ($Driver in $driversCollection) { if ((Get-Item $Driver) -is [System.IO.DirectoryInfo]) { continue } $GUID = "" $Version = "" $DriverVersion = "" $DriverDate = "" $Provider = "" $Class = "" $content = Get-Content -Path "$Driver" $line = ($content | Select-String "ClassGuid") if ($null -ne $line) { $GUID = $line.Line.Split('=')[-1].Split(' ').Split(';') $GUID = ([string]$GUID).trim().Replace('{', '').Replace('}', '') } $line = ($content | Select-String "DriverVer") if ($null -ne $line) { $Version = $line.Line.Split('=')[-1].Split(' ').Split(';') $Version = ([string]$Version).trim().Replace(' ', '') $DriverVersion = $Version.Split(',')[1].Trim() $DriverDate = $Version.Split(',')[0].Trim() } $line = ($content | Select-String "Provider")[0] if ($null -ne $line) { $Provider = $line.Line.Split('=')[-1].Split(' ').Split(';') $Provider = ([string]$Provider).trim() if ($Provider.IndexOf("%") -ge 0) { $line = ($content | Select-String $Provider)[1] if ($null -ne $line) { $Provider = $line.Line.Split('=')[-1].Split(' ').Split(';') $Provider = ([string]$Provider).trim() } if ($Provider.IndexOf("%") -ge 0) { for ($i = 0; $i -le $content.Length; $i++) { if ($content[$i].IndexOf("[Manufacturer]") -ge 0) { $Provider = $content[$i + 1].Split('=')[-1].Split(' ').Split(';') $Provider = ([string]$Provider).trim() break } } } } } $line = ($content | Select-String "Class") if ($line.Line -gt 1) { foreach ($l in $Line) { if ($l.Line.Split('=')[0].Trim() -eq "Class") { $line = $l break } } } if ($null -ne $line) { $Class = $line.Line.Split('=')[-1].Split(' ').Split(';') $Class = ([string]$Class).trim().Replace('{', '').Replace('}', '') } $FileName = Split-Path $Driver -Leaf addRow2 $FileName $Driver $Provider $Version $DriverVersion $DriverDate $GUID $Class } $script:DriverList } function Install-Driver { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string]$Path = '' ) # CheckVersion $script:updateRecord = @() function addRowUpdateRecord($updateState2, $updateAttempted2, $updateSuccessfully2, $updateResult2) { $rowUpdateRecord = New-Object -TypeName PSObject $rowUpdateRecord | Add-Member -Name 'updateState' -MemberType Noteproperty -Value $updateState2 $rowUpdateRecord | Add-Member -Name 'updateAttempted' -MemberType Noteproperty -Value $updateAttempted2 $rowUpdateRecord | Add-Member -Name 'updateSuccessfully' -MemberType Noteproperty -Value $updateSuccessfully2 $rowUpdateRecord | Add-Member -Name 'updateResult' -MemberType Noteproperty -Value $updateResult2 $script:updateRecord += $rowUpdateRecord } $updateState = "" $updateAttempted = "" $updateSuccessfully = "" $updateResult = "" $updateResult = pnputil.exe -i -a $Path foreach ($line in $updateResult) { if ($line.indexOf("Failed to install the driver") -ge 0) { $updateState = "failed" } if ($line.indexOf("Driver package added successfully") -ge 0) { $updateState = "success" } if ($line.indexOf("Total attempted") -ge 0) { $updateAttempted = $line.Split(':')[1].trim() } if ($line.indexOf("Number successfully imported") -ge 0) { $updateSuccessfully = $line.Split(':')[1].trim() } } addRowUpdateRecord $updateState $updateAttempted $updateSuccessfully $updateResult $script:updateRecord } function CheckVersionOnline() { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string]$filePath = '' ) New-Item -ItemType File -Path $filePath > $null $script:currentVersion = (Get-InstalledModule -Name QCT-Update-Management -ErrorAction SilentlyContinue).version; $script:latestVersion = (Find-Module -Name QCT-Update-Management -ErrorAction SilentlyContinue).version; $script:currentVersion | Out-File $filePath -Append $script:latestVersion | Out-File $filePath -Append } function CheckVersion() { if ($null -ne $script:currentVersion) { $tempPath = [System.IO.Path]::GetTempPath() $name = 'QCT-Update-Management.ver' $filePath = Join-Path $tempPath $name if (Test-Path $filePath) { $lastWritetime = $(Get-Item $filePath).LastWriteTime if ($lastWritetime.Date -ge $(Get-Date).Date) { $content = Get-Content $filePath $script:currentVersion = $content[0] $script:latestVersion = $content[1] } else { Remove-Item $filePath CheckVersionOnline $filePath } } else { CheckVersionOnline $filePath } } if ($script:currentVersion -ne $script:latestVersion) { Write-Warning "Your package version is $script:currentVersion, the latest version is $script:latestVersion.(QCT-Update-Management)" } } $global:SearchResult = $null $global:DownloadUpdate = 0 function Check-WindowsUpdate() { [CmdletBinding()] Param ( [Parameter(Mandatory = $false)] [switch]$OptionalInstallation ) $global:SearchResult = $null if ($OptionalInstallation) { $OptionalInstallationStr = "IsInstalled=0 and DeploymentAction='OptionalInstallation' or " } else { $OptionalInstallationStr = "" } $Searcher = New-Object -ComObject Microsoft.Update.Searcher # https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesearcher-search $SearchCriteriaAllUpdates = "IsInstalled=0 and DeploymentAction='Installation' and BrowseOnly=0 or $OptionalInstallationStr IsPresent=1 and DeploymentAction='Uninstallation' or IsInstalled=1 and DeploymentAction='Installation' and RebootRequired=1 or IsInstalled=0 and DeploymentAction='Uninstallation' and RebootRequired=1" $global:SearchResult = $Searcher.Search($SearchCriteriaAllUpdates).Updates $global:SearchResult | ft if ($global:SearchResult.Count -eq 0) { Write-Warning "There are currently no updates available." } } function Download-WindowsUpdate() { if ($null -eq $global:SearchResult) { Check-WindowsUpdate } elseif ($global:SearchResult.Count -eq 0) { Write-Warning "There are currently no updates available." } $global:DownloadUpdate = 0 if (($null -ne $global:SearchResult) -and ($global:SearchResult.Count -gt 0)) { $Session = New-Object -ComObject Microsoft.Update.Session $Downloader = $Session.CreateUpdateDownloader() $Downloader.Updates = $global:SearchResult $Downloader.Download() $global:DownloadUpdate = $global:SearchResult.Count } } function Install-WindowsUpdate() { if ($global:DownloadUpdate -eq 0) { Download-WindowsUpdate } if ($global:DownloadUpdate -ne 0) { $Installer = New-Object -ComObject Microsoft.Update.Installer $Installer.Updates = $global:SearchResult $Result = $Installer.Install() $Result } } function Get-WindowsUpdateInstalledList() { $script:WindowsUpdates = @() function addRowUWindowsUpdate($HotfixID2, $InstalledDate2, $PS2) { $rowWindowsUpdate = New-Object -TypeName PSObject $rowWindowsUpdate | Add-Member -Name 'HotfixID' -MemberType Noteproperty -Value $HotfixID2 $rowWindowsUpdate | Add-Member -Name 'InstalledDate' -MemberType Noteproperty -Value $InstalledDate2 $rowWindowsUpdate | Add-Member -Name 'PS' -MemberType Noteproperty -Value $PS2 $script:WindowsUpdates += $rowWindowsUpdate } ### $Session = New-Object -ComObject "Microsoft.Update.Session" $Searcher = $Session.CreateUpdateSearcher() $historyCount = $Searcher.GetTotalHistoryCount() $Updates = $Searcher.QueryHistory(0, $historyCount) | Select-Object Title, Description, Date, @{Name = "Operation"; Expression = { switch ($_.operation) { 1 { "Installation" }; 2 { "Uninstallation" }; 3 { "Other" } } } }, @{name = "HotfixID"; expression = { [regex]::match($_.Title, "[a-zA-Z]{2}\d{6,7}").value } } | sort date -Descending $Updates = $Updates | where { ("KB2267602", "KB890830", "KB4052623") -NotContains $_.HotfixID } # KB2267602 Security Intelligence Update for Microsoft Defender Antivirus # KB890830 Windows Malicious Software Removal Tool x64 # KB4052623 Update for Windows Defender Antivirus antimalware platform foreach ($WindowsUpdate in $Updates) { addRowUWindowsUpdate $WindowsUpdate.HotfixID $WindowsUpdate.Date $WindowsUpdate.Title } ### $Updates = Get-WmiObject -Class "win32_quickfixengineering" | Select-Object -Property "Caption", "Description", "HotfixID", @{Name = "InstalledOn"; Expression = { ([DateTime]($_.InstalledOn)).ToLocalTime() } } | sort InstalledOn -Descending foreach ($WindowsUpdate in $Updates) { $updateCatalog = Invoke-WebRequest -Uri $("https://www.catalog.update.microsoft.com/Search.aspx?q=" + $WindowsUpdate.HotfixID) -UseBasicParsing $startIndex = $updateCatalog.Content.IndexOf("<table class=""resultsBorder resultsBackGround""") if ($startIndex -gt 0) { $endIndex = $updateCatalog.Content.IndexOf("</table>", $startIndex) $updateCatalogTable = $updateCatalog.Content.Substring($startIndex, $endIndex - $startIndex + 8) $nl = [Environment]::NewLine $updateCatalogines = $updateCatalogTable.Split($nl, [System.StringSplitOptions]::RemoveEmptyEntries) $updateCatalogines = $updateCatalogines | where { [regex]::match($_, "KB\d{6,7}").Success } | % { $_.Trim() } | select -First 1 | Out-String if ($updateCatalogines.IndexOf("for Windows") -ge 0) { $updateCatalogines = $updateCatalogines.Substring(0, $updateCatalogines.IndexOf("for Windows")) } else { $updateCatalogines = $WindowsUpdate.Description } } else { $updateCatalogines = $WindowsUpdate.Description } addRowUWindowsUpdate $WindowsUpdate.HotfixID $WindowsUpdate.InstalledOn $updateCatalogines } $script:WindowsUpdates | sort InstalledDate -Descending } Export-ModuleMember Get-Driver_FW Export-ModuleMember Enable-DiskLocate Export-ModuleMember Disable-DiskLocate Export-ModuleMember Get-SmartInfo Export-ModuleMember Get-ClusterDriver_FW Export-ModuleMember Update-OEMFirmware-LSI Export-ModuleMember Update-OEMFirmware-Mellanox Export-ModuleMember Update-OEMFirmware-QLogic Export-ModuleMember Update-OEMFirmware-Disk Export-ModuleMember Reset-OEMFirmware-Mellanox Export-ModuleMember Query-OEMFirmware-Mellanox Export-ModuleMember Get-Driver_Information Export-ModuleMember Install-Driver Export-ModuleMember Check-WindowsUpdate Export-ModuleMember Download-WindowsUpdate Export-ModuleMember Install-WindowsUpdate Export-ModuleMember Get-WindowsUpdateInstalledList |