The Deployment Bunny

OS Deployment, Virtualization, Microsoft based Infrastructure…

  • about.me

    about.me/mikaelnystrom

  • Archives

  • Meta

Archive for the ‘BIOS’ Category

OSD – BIOS upgrade during OS Deployment in MDT/ConfigMgr (v3)

Posted by Mikael Nystrom on July 20, 2016

This is the third version of the script solution; it is very simple. You detect make/model in any way you would like to, create a rule based on BIOS version, if the rule match, nothing happens, otherwise it runs any command you want. That said, you could use this for other task as well. Most common question is “does it work with any Make/Model”`No, there are some vendors that does not provide the ability to run a BIOS upgrade silently without reboot without control, that is, the darn thing reboots immediately and that usually breaks the Task Sequence. I have one thing for those vendors to say “Shame on you!”

here are older posts on the subject

https://deploymentbunny.com/2011/05/20/step-by-step-upgrading-bios-during-litetouch-deployment-for-dell-hewlett-packard-and-lenovo/

https://deploymentbunny.com/2013/12/16/step-by-step-upgrading-bios-during-litetouchzerotouch-deployment-for-dell-hewlett-packard-and-lenovo-v2/

Detect the Model

The detection in the script is actually whatever you want, it is just a “If-then”  here are two sample lines detection that you will find in the script

if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP EliteBook 8560w'){}
if($ModelAlias -eq 'HP EliteBook 8460p'){}

Use the detection method for each model you like, very simple

Detect the BIOS version

This is also not that hard, here are 2 sample lines from the script

if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SCF Ver. F.63'){}
if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '786G1 v01.27'){}

Store the upgrade files

The upgrade files are stored with the model name, like this:

image

The Silent Command

You also need to figure out the command, not really hard, download the bios upgrade, read how to run it from a command line, update the script and you are done, here is a sample of one of those sections.

$Exe = 'hpqflash.exe'
$Location = "$SCRIPTDIR\Source\HP EliteBook 8460p"
$Executable = $Location + "\" + $exe
Set-Location -Path $Location
Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68SCE.CAB" –Verbose

Run the script

in MDT you can import the folder with the script as a application and set this as the command line:

PowerShell.exe -ExecutionPolicy Bypass -File Install-BIOSUpgrade.ps1

In ConfigMgr you can import this as a Package and then run the command line the same way

It is also possible to run this outside of a task sequence if you like, it works as a stand alone script, however, you cannot use the integration with MDT of course.

If you want it is possible to add a custom property in customsettings.ini, something like “NeedReboot”, then you can add the following to happen if the BIOS has been upgraded

$tsenv.Value(“NeedReboot”) = “YES”

If you then in the step after this, set a condition on a reboot step, well then it will reboot when needed, otherwise not, you can read about that in one of my old postings here

https://deploymentbunny.com/2013/12/16/step-by-step-upgrading-bios-during-litetouchzerotouch-deployment-for-dell-hewlett-packard-and-lenovo-v2/

The result

BiosUpgradeResult
It was needed.

BiosUpgradeResultNotNeeded
It was not needed.

The Script


Function Import-SMSTSENV{
    try
    {
        $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
        Write-Output "$ScriptName - tsenv is $tsenv "
        $MDTIntegration = "YES"
        
        #$tsenv.GetVariables() | % { Write-Output "$ScriptName - $_ = $($tsenv.Value($_))" }
    }
    catch
    {
        Write-Output "$ScriptName - Unable to load Microsoft.SMS.TSEnvironment"
        Write-Output "$ScriptName - Running in standalonemode"
        $MDTIntegration = "NO"
    }
    Finally
    {
    if ($MDTIntegration -eq "YES"){
        $Logpath = $tsenv.Value("LogPath")
        $LogFile = $Logpath + "\" + "$ScriptName.log"

    }
    Else{
        $Logpath = $env:TEMP
        $LogFile = $Logpath + "\" + "$ScriptName.log"
    }
    }
}
Function Start-Logging{
    start-transcript -path $LogFile -Force
}
Function Stop-Logging{
    Stop-Transcript
}
Function Invoke-Exe{
    [CmdletBinding(SupportsShouldProcess=$true)]
 
    param(
        [parameter(mandatory=$true,position=0)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Executable,
 
        [parameter(mandatory=$false,position=1)]
        [string]
        $Arguments
    )
 
    if($Arguments -eq "")
    {
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -NoNewWindow -Wait -Passthru
    }else{
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru
    }
    Write-Verbose "Returncode is $($ReturnFromEXE.ExitCode)"
    Return $ReturnFromEXE.ExitCode
}

# Set vars
$SCRIPTDIR = split-path -parent $MyInvocation.MyCommand.Path
$SCRIPTNAME = split-path -leaf $MyInvocation.MyCommand.Path
$SOURCEROOT = "$SCRIPTDIR\Source"
$SettingsFile = $SCRIPTDIR + "\" + $SettingsName
$LANG = (Get-Culture).Name
$OSV = $Null
$ARCHITECTURE = $env:PROCESSOR_ARCHITECTURE

#Try to Import SMSTSEnv
. Import-SMSTSENV

# Set more vars
$Make = $tsenv.Value("Make")
$Model = $tsenv.Value("Model")
$ModelAlias = $tsenv.Value("ModelAlias")
$MakeAlias = $tsenv.Value("MakeAlias")

#Start Transcript Logging
. Start-Logging

#Output base info
Write-Output ""
Write-Output "$ScriptName - ScriptDir: $ScriptDir"
Write-Output "$ScriptName - SourceRoot: $SOURCEROOT"
Write-Output "$ScriptName - ScriptName: $ScriptName"
Write-Output "$ScriptName - Current Culture: $LANG"
Write-Output "$ScriptName - Integration with MDT(LTI/ZTI): $MDTIntegration"
Write-Output "$ScriptName - Log: $LogFile"
Write-Output "$ScriptName - Model (win32_computersystem): $((Get-WmiObject Win32_ComputerSystem).model)"
Write-Output "$ScriptName - Name (Win32_ComputerSystemProduct): $((Get-WmiObject Win32_ComputerSystemProduct).Name)"
Write-Output "$ScriptName - Version (Win32_ComputerSystemProduct): $((Get-WmiObject Win32_ComputerSystemProduct).Version)"
Write-Output "$ScriptName - Model (from TSENV): $Model"
Write-Output "$ScriptName - ModelAlias (from TSENV): $ModelAlias"

#Check Model
if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP EliteBook 8560w'){
    Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)"
    Write-Output "Checking BIOS Version"
    Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)"
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SVD Ver. F.50'){
        Write-Output "Needs upgrade"
        $Exe = 'hpqflash.exe'
        $Location = "$SCRIPTDIR\Source\HP EliteBook 8560w"
        $Executable = $Location + "\" + $exe
        Set-Location -Path $Location
        Invoke-Exe -Executable "$Executable" -Arguments "/s /p LCadmin1.bin" -Verbose
    }
    else
    {
        Write-Output "No Need to upgrade"
    }
}
if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP ProBook 6570b'){
    Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)"
    Write-Output "Checking BIOS Version"
    Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)"
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*ICE*'){
        if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68ICE Ver. F.62'){
            Write-Output "Needs upgrade"
            $Exe = 'hpqflash.exe'
            $Location = "$SCRIPTDIR\Source\HP ProBook 6570b"
            $Executable = $Location + "\" + $exe
            Set-Location -Path $Location
            Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68ICE.cab" -Verbose
        }
        else
        {
            Write-Output "No Need to upgrade"
        }
    }
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*ICF*'){
        if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68ICF Ver. F.62'){
            Write-Output "Needs upgrade"
            $Exe = 'hpqflash.exe'
            $Location = "$SCRIPTDIR\Source\HP ProBook 6570b"
            $Executable = $Location + "\" + $exe
            Set-Location -Path $Location
            Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68ICF.cab" -Verbose
        }
        else
        {
            Write-Output "No Need to upgrade"
        }
    }
}
if($ModelAlias -eq 'HP EliteBook 8460p'){
    Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)"
    Write-Output "Checking BIOS Version"
    Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)"
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*SCF*'){
        if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SCF Ver. F.63'){
            Write-Output "Needs upgrade"
            $Exe = 'hpqflash.exe'
            $Location = "$SCRIPTDIR\Source\HP EliteBook 8460p"
            $Executable = $Location + "\" + $exe
            Set-Location -Path $Location
            Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68SCF.CAB" -Verbose
            }
        else
            {
            Write-Output "No Need to upgrade"
        }
    }
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*SCE*'){
        if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SCE Ver. F.63'){
            Write-Output "Needs upgrade"
            $Exe = 'hpqflash.exe'
            $Location = "$SCRIPTDIR\Source\HP EliteBook 8460p"
            $Executable = $Location + "\" + $exe
            Set-Location -Path $Location
            Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68SCE.CAB" -Verbose
            }
        else
            {
            Write-Output "No Need to upgrade"
        }
    }
}
if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP Compaq dc7900 Small Form Factor'){
    Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)"
    Write-Output "Checking BIOS Version"
    Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)"
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '786G1 v01.27'){
        Write-Output "Needs upgrade"
        $Exe = 'hpqflash.exe'
        $Location = "$SCRIPTDIR\Source\HP Compaq dc7900 Small Form Factor\HPQFlash"
        $Executable = $Location + "\" + $exe
        $SourceFile = $Location + "\" + "Password01.bin"
        $Destination = $env:TEMP
        $DestinationFile = $Destination + "\" + "Password01.bin"
        Copy-Item -Path $SourceFile -Destination $DestinationFile -Force -Verbose 
        Set-Location -Path $Location
        Invoke-Exe -Executable $Executable -Arguments "/s /p $DestinationFile"
    }
    else
    {
        Write-Output "No Need to upgrade"
    }
}

#Stop Logging
. Stop-Logging


/mike

Posted in BIOS, ConfigMgr, MDT, OS Deployment, OSD, PowerShell | Tagged: , , , , , | 3 Comments »

PowerShell is King – Read HP Bios Sensor data from WMI

Posted by Mikael Nystrom on March 16, 2016

I was bored in my hotel room and I ended up browsing WMI, found one cool/fun thing. I have a EliteBook 8570w and it turns out that HP uses WMI to store data and that makes it possible to read the data using PowerShell of course. Here is how:

Read HP Bios Sensor data from WMI using PowerShell

image

So, here is the actual code for you to copy:


#Read HP Bios Sensor data from WMI using PowerShell
$BIOSSensor = Get-WmiObject -Class HP_BIOSSensor -Namespace root\hp\instrumentedbios
$BIOSSensor | Select-Object Name,CurrentState,CurrentReading,Description

/Mike

Posted in BIOS, HP, PowerShell | Tagged: , , | Leave a Comment »

Working in the Datacenter – Application Wrapper for HP BIOS CmdLets – Deploy it during OSD

Posted by Mikael Nystrom on March 7, 2016

In a previous blogpost a shortly described what you can do with the “HP BIOS CmdLets for Windows PowerShell (x64)” and in this post I’ll give you a PowerShell wrapper for LTI/ZTI to deploy it.

Download from installer from

http://h20566.www2.hpe.com/hpsc/swd/public/detail?sp4ts.oid=5440658&swItemId=MTX_1cedc5b3a4ec4bc7a942f6e682&swEnvOid=4168

image

The LTI/ZTI Wrapper:

It is very simple, basically create a folder called “Install – HPBIOSCmdlets”, in the folder, create a folder called “Source” and in that folder you save the MSI file from HP (the download is a EXE, just unzip it and it will be a MSI file inside) and then you save the PowerShell installer in the “Install – HPBIOSCmdlets” folder, like this

image

Here is the:

<#
 Install Wrapper 1.0
 Author: Mikael Nystrom
 http://www.deploymentbunny.com 
#>

Function Invoke-Exe{
    [CmdletBinding(SupportsShouldProcess=$true)]

    param(
        [parameter(mandatory=$true,position=0)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Executable,

        [parameter(mandatory=$false,position=1)]
        [string]
        $Arguments
    )

    if($Arguments -eq "")
    {
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -NoNewWindow -Wait -Passthru
    }else{
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru
    }
    Write-Verbose "Returncode is $($ReturnFromEXE.ExitCode)"
    Return $ReturnFromEXE.ExitCode
}
Function Get-OSVersion([ref]$OSv){
    $OS = Get-WmiObject -class Win32_OperatingSystem
    Switch -Regex ($OS.Version)
    {
    "6.1"
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 7 SP1"}
                Else
            {$OSv.value = "Windows Server 2008 R2"}
        }
    "6.2"
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 8"}
                Else
            {$OSv.value = "Windows Server 2012"}
        }
    "6.3"
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 8.1"}
                Else
            {$OSv.value = "Windows Server 2012 R2"}
        }
    DEFAULT { "Version not listed" }
    } 
}
Function Import-SMSTSENV{
    try
    {
        $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
        Write-Output "$ScriptName - tsenv is $tsenv "
        $MDTIntegration = "YES"
        
        #$tsenv.GetVariables() | % { Write-Output "$ScriptName - $_ = $($tsenv.Value($_))" }
    }
    catch
    {
        Write-Output "$ScriptName - Unable to load Microsoft.SMS.TSEnvironment"
        Write-Output "$ScriptName - Running in standalonemode"
        $MDTIntegration = "NO"
    }
    Finally
    {
    if ($MDTIntegration -eq "YES"){
        $Logpath = $tsenv.Value("LogPath")
        $LogFile = $Logpath + "\" + "$ScriptName.txt"

    }
    Else{
        $Logpath = $env:TEMP
        $LogFile = $Logpath + "\" + "$ScriptName.txt"
    }
    }
}
Function Start-Logging{
    start-transcript -path $LogFile -Force
}
Function Stop-Logging{
    Stop-Transcript
}

# Set Vars
$SCRIPTDIR = split-path -parent $MyInvocation.MyCommand.Path
$SCRIPTNAME = split-path -leaf $MyInvocation.MyCommand.Path
$SOURCEROOT = "$SCRIPTDIR\Source"
$LANG = (Get-Culture).Name
$OSV = $Null
$ARCHITECTURE = $env:PROCESSOR_ARCHITECTURE

#Try to Import SMSTSEnv
. Import-SMSTSENV

#Start Transcript Logging
. Start-Logging

#Detect current OS Version
. Get-OSVersion -osv ([ref]$osv) 

#Output base info
Write-Output ""
Write-Output "$ScriptName - ScriptDir: $ScriptDir"
Write-Output "$ScriptName - SourceRoot: $SOURCEROOT"
Write-Output "$ScriptName - ScriptName: $ScriptName"
Write-Output "$ScriptName - OS Name: $osv"
Write-Output "$ScriptName - OS Architecture: $ARCHITECTURE"
Write-Output "$ScriptName - Current Culture: $LANG"
Write-Output "$ScriptName - Integration with MDT(LTI/ZTI): $MDTIntegration"
Write-Output "$ScriptName - Log: $LogFile"

$Executable = "msiexec.exe"
$Arguments = "/i ""$SOURCEROOT\HPBIOSCmdlets-x64.msi"" /qb"

Write-Output "$ScriptName - Executable: $Executable"
Write-Output "$ScriptName - Arguments: $Arguments"

Invoke-Exe -Executable $Executable -Arguments $Arguments -Verbose

. Stop-Logging

Create the Application in the Task Sequence:

(This how it is done in LiteTouch, but it will be the same in ConfigMgr)

Create a new Application, browse to the folder you created and use this as your command line:

PowerShell.exe -ExecutionPolicy Bypass -File Install-HPBIOSCmdlets-x64.ps1

image
It should look something like this.

The logfile

It will end up in C:\Windows\Temp\Deploymentlogs (for LTI) and should look something like this:

image

/mike

Posted in BIOS, HP, OS Deployment, OSD, PowerShell | Tagged: , , , , , | 2 Comments »

Working in the Datacenter – HP BIOS Cmdlets for Windows PowerShell (x64)

Posted by Mikael Nystrom on March 6, 2016

For customers running HP ProLiant servers in the datacenter (many of my customers do) it is now possible to modify the BIOS settings using PowerShell much easier then it used to be. The reason is that HP have released a PowerShell module that makes it possible to modify many of the settings, it actually also works remotely and even in WinPE. So, after it has been installed on a computer and you open up PowerShell and type Get-Help BIOS, you will get this:

image

Download from:

image

The little trick

It seems to be some confusion on how these CmdLets work, but it is very simple. The first command you need to execute is the Connect- CmdLet and that also applies when you run the command on the localhost and a connection does require name and password, this part actually sucks. it would have been so much smarter of HP to accept that commands that are executed locally did not ask for credentials, but that is how it works right now.

The Cool thing

It is possible to connect to multiple servers at the same time and then all commands will be executed in parallel

Connect to the BIOS

$ComputerName = "SRV01"
$UserName = "Administrator"
$Password = "P@ssw0rd"
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList "$COMPUTERNAME\$UserName", ($Password | ConvertTo-SecureString -AsPlainText -Force)
$Con = Connect-HPBIOS -IP $env:COMPUTERNAME -Credential $Credentials -ErrorAction Stop

Configure for Tree Hugging Mode

Set-HPBIOSPowerProfile -Profile Minimum_Power -Connection $Con
Set-HPBIOSPowerRegulator -Regulator Dynamic_Power_Savings -Connection $Con
Write-Output "$ScriptName - HP PowerProfile is set to $((Get-HPBIOSPowerProfile -Connection $Con).HPPowerProfile)"
Write-Output "$ScriptName - HP PowerRegulator is set to $((Get-HPBIOSPowerRegulator -Connection $Con).HPPowerRegulator)"

Configure for High Performance

Set-HPBIOSPowerProfile -Profile Maximum_Performance -Connection $Con
Set-HPBIOSPowerRegulator -Regulator Static_High_Performance -Connection $Con
Write-Output "$ScriptName - HP PowerProfile is set to $((Get-HPBIOSPowerProfile -Connection $Con).HPPowerProfile)"
Write-Output "$ScriptName - HP PowerRegulator is set to $((Get-HPBIOSPowerRegulator -Connection $Con).HPPowerRegulator)"

/mike

Posted in BIOS, HP, PowerShell | Tagged: , , | Leave a Comment »

PowerShell is King – Convert WIM to VHD/VHDX with support for Gen 1 and Gen 2 (BIOS/UEFI) and then some…

Posted by Mikael Nystrom on December 19, 2013

In my line of work, automation is important, since time is the only thing I don’t have. Many years ago I created the WIM2VHD script and that was ok, so when R2 came out I needed to update it to support UEFI. That was easier said then done. The problem is that the UEFI boot process requires fat32, GPT and a bunch of partitions and when using PowerShell to create them the OS will immediately start protecting them after creation which makes it impossible to copy files to the boot partition since it is “protected”, but since I’m a very creative person I found the solution in diskpart. (read about it further down)

Mounting the ISO

I actually have to scripts in this case, one is to mount the ISO that will return the drive letter, kind of handy to have since I need to know the path to the wim file

image

The script to mount the ISO

image

The script to mount the ISO (Text)

————————————————-

# Mount ISO and get driveletter
Param(
[parameter(mandatory=$true,HelpMessage="Please, provide a path to ISO.")]
[ValidateNotNullOrEmpty()]
$ISO
)
Mount-DiskImage -ImagePath $ISO
Write-host (get-date -Format u)" – Mounting =" $ISO
$ISOImage = Get-DiskImage -ImagePath $ISO | Get-Volume
$ISODrive = [string]$ISOImage.DriveLetter+":"
Write-host (get-date -Format u)" – Driveletter is now =" $ISODrive

———————————————–

Getting the correct Index number in the WIM

After the ISO is mounted you can use the Get-WindowsImage commandlet to see what Indexes you have in the WIM file.
The Command Get-WindowsImage – Path d:\sources\install.wim will give me this list.

image

 

Converting the WIM file to the VHDX file

Besides converting the WIM to a VHDX file it also creates the UEFI style disk layout or the BIOS style disk layout. It also give you the opportunity to add the SXS folder to the drive (makes it a bit easier to add .Net framework without internet access or media access) and it will also ask you to add a Tools folder, if you do it will end up in c:\Tools, extremely handy, I usually put things in there that I need, NP++, Sysinternals, 7-Zip, and such.

If you open the script you will one thing that is a bit strange (actually two), when creating the UEFI style disk partition we create the first partition with the WRONG GUID number and that is the way we need to do it, otherwise windows will start protecting the drive, so we create the partition with the GUID for data drive, later on we create a text file and we let diskpart run against that text file that will then change the GUID number to the correct one. scary…

Sample command to create a BIOS based VHDX

.\Create-VHDX.ps1 -SourceFile d:\sources\install.wim -DestinationFile C:\Test\RWS2012R2BIOS.vhdx -Disklayout BIOS -Index 2 -PathtoSXSFolder d:\sources\sxs -PathtoExtraFolder C:\HYDV4\Tools –Verbose

Sample command to create a UEFI based VHDX

.\Create-VHDX.ps1 -SourceFile d:\sources\install.wim -DestinationFile C:\Test\RWS2012R2BIOS.vhdx -Disklayout UEFI -Index 2 -PathtoSXSFolder d:\sources\sxs -PathtoExtraFolder C:\HYDV4\Tools –Verbose

When running it looks like this

I have tested the script on WS2012R2/W8.1 with Hyper-V but it should work on WS2012/W8 as well, just that I don’t have any of those old systems running at home anymore…

image
Since the script is 255 lines of POSH, you better download it from here http://sdrv.ms/1foJ3Wg
/mike

Posted in BIOS, Deployment, Hyper-V, PowerShell, UEFI, Windows 8.1, Windows Server 2012 R2 | Tagged: , | 10 Comments »

Step-by-Step: Upgrading BIOS during LiteTouch(ZeroTouch) Deployment, for Dell, Hewlett-Packard and Lenovo (v2)

Posted by Mikael Nystrom on December 16, 2013

Long time ago I wrote a post on how to upgrade the BIOS/Firmware during the deployment of a PC in the beginning of a TaskSequence, since then I have been hammered with the question on how to do the same thing but later on, when Windows is running, that has been nagging me, (which obviously paid off for all of you that has been doing that). My friends, here it is, this time in PowerShell, but hey, I don’t do XP anymore.

The basics

The basic Idea is to have a PowerShell script run that will discover what bios version we have and IF we have an update run the update according the that model’s specific way of running a firmware upgrade. It is also possible to just use the PowerShell script as a framework for other similar task of course, or you could use it to kick off something like SSM(HP) to do the job. I did one change, besides using PowerShell and that is to copy down the files to the local drive before running the upgrade, just to be sure that a messy network does not break the upgrade. The script is tested with a couple of HP’s, a Dell and a Lenovo, so there is of course no way I can guarantee it will work with every piece of PC around the globe, but hey, its PowerShell so you can modify it on your own :-). I also created it as an application for MDT LiteTouch, so you need to modify it slightly to run it in SCCM and it also needs the “AliasUserExit.vbs” script since I’m using ModelAlias and MakeAlias. If you don’t like that, just change the lines in he PowerShell code to use Make and Model or anything else that you can read from WMI using PowerShell

The PowerShell script (section One)

This part is just about creating log files, and getting basic data from the TaskSequence/TSEnviroment

image

The PowerShell script (section Two)

Here you can see the function that gets the SMBIOSBIOSVersion, and for all these vendors it is the same, but that could change in the future, so I decided to use the PowerShell Switch to figure out on how to get it. If you look close you can also see that I’m feeding back data to the TSEnviroment, that is not needed for this to work, but hey, you cannot get enough variables to play with, can you :-)

image

The PowerShell script (section three)

Here is when we get serious, you need to add every model that should be upgraded as a Switch Value and then update the $ExpectedBIOSVersion so it match what you should have. Then you need to add the BIOS update files in to the folder structure in the the Application and last you need to create/modify the UpgradeBIOS.cmd for each model so it runs whatever it is suppose to run to make magic happen.

image

The Folder Structure

Here you can see the folder structure, in this case HP Elitebook 8460p also has sub folders, whatever the vendors has a structure I put in the folder and that will then end up on the local drive, where I run the batch file.

image

The Application in MDT

Just a standard “app” in MDT, I don’t use the “Run PowerShell” script since Applications are easier to modify, move, export, import, and play with. But there should no very little work to get it to work as a script instead, basically the only thing you need to to is to store the script in a folder that the TS can reach, all the folder structure and the file copy is based on where the script is located.

image

CustomSettings.ini needs to be updated!

To figure out if a reboot is needed or not I added a reboot step and reads the property RebootNedeed, so you need to add that to customsettings.ini

image

The TaskSequence

As you can see, I did create a folder for this, easy to copy, easy to move, easy to enable/disable. The restart computer step does have a condition, it only executes if RebootNeeded is set to YES, which is set IF you run the BiosUpgrade.CMD batch file, in the PowerShell script I do return 3010 and I also set the RebootNeeded to YES.

image

The Restart computer Condition

image

 

How to?

  • Download the script
  • Unpack
  • Create a new Application in MDT (If you use SCCM or don’t like Apps, modify the script inside the folder first and add it as a script in the TS)
    • CommandLine: powershell.exe -ExecutionPolicy Unrestricted -File ViaMonstraUpgradeBios.ps1
  • Modify the script to fit your computers, versions and download each upgrade into each folder in the folder structure
  • Add it as an application
  • Enjoy

The Download

http://sdrv.ms/1ffLbji

/mike

The “old” Post: https://deploymentbunny.com/2011/05/20/step-by-step-upgrading-bios-during-litetouch-deployment-for-dell-hewlett-packard-and-lenovo/

The link to the AliasUserExit Script: https://deploymentbunny.com/2013/03/06/back-to-basiccustomsettings-inisample-2/

Posted in BIOS, Deployment, Firmware, MDT, SCCM | Tagged: | 3 Comments »