-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGet-HPBIOSUpdate.ps1
More file actions
369 lines (299 loc) · 15.2 KB
/
Get-HPBIOSUpdate.ps1
File metadata and controls
369 lines (299 loc) · 15.2 KB
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
<#
.SYNOPSIS
Check and apply available BIOS updates (or downgrades)
.DESCRIPTION
This function uses an internet service to retrieve the list of BIOS updates available for a platform, and optionally checks it against the current system.
The result is a series of records, with the following definition:
* Ver - the BIOS update version
* Date - the BIOS release date
* Bin - the BIOS update binary file
.PARAMETER Platform
The Platform ID to check. It can be obtained via Get-HPDeviceProductID. The Platform ID cannot be specified for a flash operation. If not specified, current Platform ID is checked.
.PARAMETER Target
Execute the command on specified target computer. If not specified, the command is executed on the local computer.
.PARAMETER Format
The file format (xml, json, csv, list) to output. If not specified, a list of PowerShell objects is returned.
.PARAMETER Latest
If specified, only return or download the latest available BIOS version between remote and local. If -Platform is specified, local BIOS will not be read and the latest BIOS version available remotely will be returned.
.PARAMETER Check
If specified, return true if the latest version corresponds to the installed version or installed version is higher, false otherwise. This check is only valid when comparing against current platform.
.PARAMETER All
Include all known BIOS update information. This may include additional data such as dependencies, rollback support, and criticality.
.PARAMETER Download
Download the BIOS file to the current directory or a path specified by SaveAs.
.PARAMETER Flash
Apply the BIOS update to the current system.
.PARAMETER Password
Specify the BIOS password, if a password is active. This switch is only used when -flash is specified.
- Use single quotes around the password to prevent PowerShell from interpreting special characters in the string.
.PARAMETER Version
The BIOS version to download. If not specified, the latest version available will be downloaded.
.PARAMETER SaveAs
The filename for the downloaded BIOS file. If not specified, the remote file name will be used.
.PARAMETER Quiet
Do not display a progress bar during BIOS file download.
.PARAMETER Overwrite
Force overwriting any existing file with the same name during BIOS file download. This switch is only used when -download is specified.
.PARAMETER Yes
Answer 'yes' to the 'Are you sure you want to flash' prompt.
.PARAMETER Force
Force the BIOS to update, even if the target BIOS is already installed.
.PARAMETER BitLocker
Provide an answer to the BitLocker check prompt (if any). The value may be one of:
stop - stop if BitLocker is detected but not suspended, and prompt.
stop is default when BitLocker switch is provided.
ignore - skip the BitLocker check
suspend - suspend BitLocker if active, and continue
.PARAMETER Url
Alternate Url source to provide platform's BIOS update catalog (xml)
.NOTES
- Flash is only supported on Windows 10 1709 (Fall Creators Updated) and later.
- UEFI boot mode is required for flashing, legacy mode is not supported.
- The flash operation requires 64-bit PowerShell (not supported under 32-bit PowerShell)
**WinPE notes**
- Use '-BitLocker ignore' when using this function in WinPE, as BitLocker checks are not applicable in Windows PE.
- Requires that the WInPE image is built with the WinPE-SecureBootCmdlets.cab component.
.EXAMPLE
Get-HPBIOSUpdates
#>
function Get-HPBIOSUpdates {
[CmdletBinding(DefaultParameterSetName = "ViewSet",
HelpUri = "https://developers.hp.com/hp-client-management/doc/Get%E2%80%90HPBIOSUpdates")]
param(
[Parameter(ParameterSetName = "DownloadSet",Position = 0,Mandatory = $false)]
[Parameter(ParameterSetName = "ViewSet",Position = 0,Mandatory = $false)]
[Parameter(Position = 0,Mandatory = $false)]
[ValidatePattern("^[a-fA-F0-9]{4}$")]
[string]$Platform,
[ValidateSet('Xml','Json','CSV','List')]
[Parameter(ParameterSetName = "ViewSet",Position = 1,Mandatory = $false)]
[string]$Format,
[Parameter(ParameterSetName = "ViewSet",Position = 2,Mandatory = $false)]
[switch]$Latest,
[Parameter(ParameterSetName = "CheckSet",Position = 3,Mandatory = $false)]
[switch]$Check,
[Parameter(ParameterSetName = "FlashSetPassword",Position = 4,Mandatory = $false)]
[Parameter(ParameterSetName = "DownloadSet",Position = 4,Mandatory = $false)]
[Parameter(ParameterSetName = "ViewSet",Position = 4,Mandatory = $false)]
[string]$Target = ".",
[Parameter(ParameterSetName = "ViewSet",Position = 5,Mandatory = $false)]
[switch]$All,
[Parameter(ParameterSetName = "DownloadSet",Position = 6,Mandatory = $true)]
[switch]$Download,
[Parameter(ParameterSetName = "FlashSetPassword",Position = 7,Mandatory = $true)]
[switch]$Flash,
[Parameter(ParameterSetName = 'FlashSetPassword',Position = 8,Mandatory = $false)]
[string]$Password,
[Parameter(ParameterSetName = "FlashSetPassword",Position = 9,Mandatory = $false)]
[Parameter(ParameterSetName = "DownloadSet",Position = 9,Mandatory = $false)]
[string]$Version,
[Parameter(ParameterSetName = "FlashSetPassword",Position = 10,Mandatory = $false)]
[Parameter(ParameterSetName = "DownloadSet",Position = 10,Mandatory = $false)]
[string]$SaveAs,
[Parameter(ParameterSetName = "FlashSetPassword",Position = 11,Mandatory = $false)]
[Parameter(ParameterSetName = "DownloadSet",Position = 11,Mandatory = $false)]
[switch]$Quiet,
[Parameter(ParameterSetName = "FlashSetPassword",Position = 12,Mandatory = $false)]
[Parameter(ParameterSetName = "DownloadSet",Position = 12,Mandatory = $false)]
[switch]$Overwrite,
[Parameter(ParameterSetName = 'FlashSetPassword',Position = 13,Mandatory = $false)]
[switch]$Yes,
[Parameter(ParameterSetName = 'FlashSetPassword',Position = 14,Mandatory = $false)]
[ValidateSet('Stop','Ignore','Suspend')]
[string]$BitLocker = 'Stop',
[Parameter(ParameterSetName = 'FlashSetPassword',Position = 15,Mandatory = $false)]
[switch]$Force,
[Parameter(ParameterSetName = 'FlashSetPassword',Position = 16,Mandatory = $false)]
[string]$Url = "https://ftp.hp.com/pub/pcbios"
)
if ($PSCmdlet.ParameterSetName -eq "FlashSetPassword") {
Test-HPFirmwareFlashSupported -CheckPlatform
if ((Get-HPPrivateIsSureAdminEnabled) -eq $true) {
throw "Sure Admin is enabled, you must use Update-HPFirmware with a payload instead of a password"
}
}
if (-not $platform) {
# if platform is not provided, $platform is current platform
$platform = Get-HPDeviceProductID -Target $target
}
$platform = $platform.ToUpper()
Write-Verbose "Using platform ID $platform"
$uri = [string]"$Url/{0}/{0}.xml" -f $platform.ToUpper()
Write-Verbose "Retrieving catalog file $uri"
$ua = Get-HPPrivateUserAgent
try {
[System.Net.ServicePointManager]::SecurityProtocol = Get-HPPrivateAllowedHttpsProtocols
$data = Invoke-WebRequest -Uri $uri -UserAgent $ua -UseBasicParsing -ErrorAction Stop
}
catch [System.Net.WebException]{
if ($_.Exception.Message.contains("(404) Not Found"))
{
throw [System.Management.Automation.ItemNotFoundException]"Unable to retrieve BIOS data for a platform with ID $platform (data file not found)."
}
throw $_.Exception
}
[xml]$doc = [System.IO.StreamReader]::new($data.RawContentStream).ReadToEnd()
if ((-not $doc) -or (-not (Get-Member -InputObject $doc -Type Property -Name "BIOS")) -or (-not (Get-Member -InputObject $doc.bios -Type Property -Name "Rel")))
{
throw [System.FormatException]"Source data file is unsupported or corrupt"
}
#reach to Rel nodes to find Bin entries in xml
#ignore any entry not ending in *.bin e.g. *.tgz, *.cab
$unwanted_nodes = $doc.SelectNodes("//BIOS/Rel") | Where-Object { -not ($_.Bin -like "*.bin") }
$unwanted_nodes | Where-Object {
$ignore = $_.ParentNode.RemoveChild($_)
}
#trim the 0 from the start of the version and then sort on the version value
$refined_doc = $doc.SelectNodes("//BIOS/Rel") | Select-Object -Property @{ Name = 'Ver'; expr = { $_.Ver.TrimStart("0") } },'Date','Bin','RB','L','DP' `
| Sort-Object -Property Ver -Descending
#latest version
$latestVer = $refined_doc[0]
if (($PSCmdlet.ParameterSetName -eq "ViewSet") -or ($PSCmdlet.ParameterSetName -eq "CheckSet")) {
Write-Verbose "Proceeding with parameter set => view"
if ($check.IsPresent -eq $true) {
[string]$haveVer = Get-HPBIOSVersion -Target $target
#check should return true if local BIOS is same or newer than the latest available remote BIOS.
return ([string]$haveVer.TrimStart("0") -ge [string]$latestVer[0].Ver)
}
$args = @{}
if ($all.IsPresent) {
$args.Property = (@{ Name = 'Ver'; expr = { $_.Ver.TrimStart("0") } },"Date","Bin",`
(@{ Name = 'RollbackAllowed'; expr = { [bool][int]$_.RB.trim() } }),`
(@{ Name = 'Importance'; expr = { [Enum]::ToObject([BiosUpdateCriticality],[int]$_.L.trim()) } }),`
(@{ Name = 'Dependency'; expr = { [string]$_.DP.trim() } }))
}
else {
$args.Property = (@{ Name = 'Ver'; expr = { $_.Ver.TrimStart("0") } },"Date","Bin")
}
# for current platform: latest should return whichever is latest, between local and remote.
# for any other platform specified: latest should return latest entry from SystemID.XML since we don't know local BIOSVersion
if ($latest)
{
if ($PSBoundParameters.ContainsKey('Platform'))
{
# platform specified, do not read information from local system and return latest platform published
$args.First = 1
}
else {
$retrieved = 0
# determine the local BIOS version
[string]$haveVer = Get-HPBIOSVersion -Target $target
# latest should return whichever is latest, between local and remote for current system.
if ([string]$haveVer -ge [string]$latestVer[0].Ver)
{
# local is the latest. So, retrieve attributes other than BIOSVersion to print for latest
for ($i = 0; $i -lt $refined_doc.Length; $i++) {
if ($refined_doc[$i].Ver -eq $haveVer) {
$haveVerFromDoc = $refined_doc[$i]
$pso = [pscustomobject]@{
Ver = $haveVerFromDoc.Ver
Date = $haveVerFromDoc.Date
Bin = $haveVerFromDoc.Bin
}
if ($all) {
$pso | Add-Member -MemberType ScriptProperty -Name RollbackAllowed -Value { [bool][int]$haveVerFromDoc.RB.trim() }
$pso | Add-Member -MemberType ScriptProperty -Name Importance -Value { [Enum]::ToObject([BiosUpdateCriticality],[int]$haveVerFromDoc.L.trim()) }
$pso | Add-Member -MemberType ScriptProperty -Name Dependency -Value { [string]$haveVerFromDoc.DP.trim }
}
$retrieved = 1
if ($pso) {
formatBiosVersionsOutputList ($pso)
return
}
}
}
if ($retrieved -eq 0) {
Write-Verbose "retrieving entry from xml failed, get the information from CIM class."
# calculating date from Win32_BIOS
$year = (Get-CimInstance Win32_BIOS).ReleaseDate.Year
$month = (Get-CimInstance Win32_BIOS).ReleaseDate.Month
$day = (Get-CimInstance Win32_BIOS).ReleaseDate.Day
$date = $year.ToString() + '-' + $month.ToString() + '-' + $day.ToString()
Write-Verbose "date calculated from CIM Class is: $date"
$currentVer = Get-HPBIOSVersion
$pso = [pscustomobject]@{
Ver = $currentVer
Date = $date
Bin = $null
}
if ($all) {
$pso | Add-Member -MemberType ScriptProperty -Name RollbackAllowed -Value { $null }
$pso | Add-Member -MemberType ScriptProperty -Name Importance -Value { $null }
$pso | Add-Member -MemberType ScriptProperty -Name Dependency -Value { $null }
}
if ($pso) {
$retrieved = 1
formatBiosVersionsOutputList ($pso)
return
}
}
}
else {
# remote is the latest
$args.First = 1
}
}
}
formatBiosVersionsOutputList ($refined_doc | Sort-Object -Property ver -Descending | Select-Object @args)
}
else {
$download_params = @{}
if ($version) {
$latestVer = $refined_doc `
| Where-Object { $_.Ver.TrimStart("0") -eq $version } `
| Select-Object -Property Ver,Bin -First 1
}
if (-not $latestVer) { throw [System.ArgumentOutOfRangeException]"Version $version was not found." }
if (($flash.IsPresent) -and (-not $saveAs)) {
$saveAs = Get-HPPrivateTemporaryFileName -FileName $latestVer.Bin
$download_params.NoClobber = "yes"
Write-Verbose "Temporary file name for download is $saveAs"
}
else { $download_params.NoClobber = if ($overwrite.IsPresent) { "yes" } else { "no" } }
Write-Verbose "Proceeding with parameter set => download, overwrite=$($download_params.NoClobber)"
$remote_file = $latestVer.Bin
$local_file = $latestVer.Bin
$remote_ver = $latestVer.Ver
if ($PSCmdlet.ParameterSetName -eq "FlashSetPassword" -or
$PSCmdlet.ParameterSetName -eq "FlashSetSigningKeyFile" -or
$PSCmdlet.ParameterSetName -eq "FlashSetSigningKeyCert") {
$running = Get-HPBIOSVersion
if ((-not $Force.IsPresent) -and ($running.TrimStart("0").trim() -ge $remote_ver.TrimStart("0").trim())) {
Write-Host "This system is already running BIOS version $($remote_ver.TrimStart(`"0`").Trim()) or newer."
Write-Host -ForegroundColor Cyan "You can specify -Force on the command line to proceed anyway."
return
}
}
if ($saveAs) {
$local_file = $saveAs
}
[Environment]::CurrentDirectory = $pwd
#if (-not [System.IO.Path]::IsPathRooted($to)) { $to = ".\$to" }
$download_params.url = [string]"$Url/{0}/{1}" -f $platform,$remote_file
$download_params.Target = [IO.Path]::GetFullPath($local_file)
$download_params.progress = ($quiet.IsPresent -eq $false)
Invoke-HPPrivateDownloadFile @download_params -panic
if ($PSCmdlet.ParameterSetName -eq "FlashSetPassword" -or
$PSCmdlet.ParameterSetName -eq "FlashSetSigningKeyFile" -or
$PSCmdlet.ParameterSetName -eq "FlashSetSigningKeyCert") {
if (-not $yes) {
Write-Host -ForegroundColor Cyan "Are you sure you want to flash this system with version '$remote_ver'?"
Write-Host -ForegroundColor Cyan "Current BIOS version is $(Get-HPBIOSVersion)."
Write-Host -ForegroundColor Cyan "A reboot will be required for the operation to complete."
$response = Read-Host -Prompt "Type 'Y' to continue and anything else to abort. Or specify -Yes on the command line to skip this prompt"
if ($response -ne "Y") {
Write-Verbose "User did not confirm and did not disable confirmation, aborting."
return
}
}
Write-Verbose "Passing to flash process with file $($download_params.target)"
$update_params = @{
file = $download_params.Target
bitlocker = $bitlocker
Force = $Force
Password = $password
}
Update-HPFirmware @update_params -Verbose:$VerbosePreference
}
}
}