In-Band Management of IPMI with PowerShell

IPMI (Intelligent Platform Management Interface) is a specification defined by Intel and adopted by a number of companies for standardizing hardware management, particularly in server systems. IPMI supports both in-band (from the operating system) and out-of-band (from the network direct to hardware) management. The protocol IPMI uses for out-of-band management is not based on WS-Management and not the focus of this blog post.

Available since Windows 2003 R2, Microsoft has developed a generic IPMI Driver and IPMI Provider in Windows to enable management of BMCs (Base board Management Controller) that implement IPMI. The IPMI Driver (IPMIdrv.sys) is essentially a light-weight “pass-through” driver which takes IPMI requests and returns IPMI responses. The IPMI Provider (IPMIprv.dll) takes the heavy load of converting between IPMI and CIM.

The IPMI Provider only exposes a subset of the capabilities exposed by IPMI. However, because of the IPMI Driver “pass-through” design, you can take advantage of this and send custom IPMI requests. You can even do this remotely over WS-Management (via the OS) and that’s what I’ll talk about today.

Even though the IPMI Driver runs in the kernel, it exposes a User Mode (meaning Applications can call it) interface as a WMI class (Microsoft_IPMI) in the Root/WMI namespace. It implements a dynamic method (meaning you execute the method against the instance) called RequestResponse() that we’ll use to send IPMI commands. You will need to be in the administrators group to be able to call this method successfully.

I’ve published a PowerShell module (written in PowerShell script) on TechNet that can be used as a sample. One of the main helper functions is this:

 function Invoke-IPMIRequestResponse {
    [CmdletBinding(DefaultParametersetName="CimSession")]
    Param (
        [Parameter(ParameterSetName="CimSession",Position=0)]
        [Microsoft.Management.Infrastructure.CimSession] $CimSession,
        [byte]$Command,
        [byte]$LUN = $DefaultLUN,
        [byte[]]$RequestData,
        [byte]$ResponderAddress = $BMCResponderAddress)

    Process {
        $ErrorActionPreference = "SilentlyContinue"

        if ($CimSession -eq $null) {
            $CimSession = New-CimSession
        }

        $ipmi = Get-CimInstance -Namespace root/wmi -CimSession $CimSession Microsoft_IPMI
        $ErrorActionPreference = "Stop"

        if ($null -eq $ipmi) {
            Write-Error "Microsoft IPMI Driver not running on specified system"
        }

        $arguments = @{Command=$Command;LUN=$LUN;NetworkFunction= `
    $(Get-NetFn $command);RequestData=$RequestData;RequestDataSize= `
   [uint32]$RequestData.Length;ResponderAddress=$ResponderAddress}

        $out = Invoke-CimMethod -InputObject $ipmi -CimSession $CimSession RequestResponse -Arguments $arguments
        if ($out.CompletionCode -ne 0) {
             Write-Error ("IPMI Command failed (0x{0:x}): {1}" -f $out.CompletionCode, `
             (Convert-CompletionCodeToText $out.CompletionCode)) 

        }
        $out.ResponseData
    }
} 

This function takes a CimSession which is a new type we introduced in the Windows Management Framework 3.0 that makes it easy to manage remote management operations as well as using the new CIM cmdlets. If a CimSession is not provided, this function works against the local machine. 

An IPMI request (as defined in the IPMI specification) is essentially split into: Command, LUN, RequestData, and ResponderAddress. For the most part, LUN (Logical Unit Number) is usually 0 and ResponderAddress is usually 32 (meaning the BMC itself responds). Command is the operation (for example, Get LAN Configuration) and RequestData is a byte-array specific to that Command. Additional required data such as NetworkFunction (basically the Command category) is computed automatically. I’m not going to go into details about IPMI itself, but people familiar with IPMI should be able to easily see how to make use of this function. Here is an example of using the PowerShell module:

So what would you do with this? On server systems, the BMC is typically on a different NIC than the host system, so the BMC would have a different network identity than the host system. Given two IP Addresses and even two MAC Addresses, you would not be able to correlate that this BMC manages this particular host. Using IPMI (and this PowerShell module), you can query the IP address of the BMC from the OS and thus be able to correlate the two together. It’s also possible to store information from the OS into the BMC. The example above, I made use of the IPMI Set System Info Parameter Command to store the OS name into the BMC. This means that management software that talks to the BMC remotely would be able to determine what OS is installed and/or running on that system.

If you are using IPMI capable hardware today (in-band or out-of-band), I would appreciate it if you let me know what scenarios are you are trying to enable or are currently exercising. In a future post, I’ll discuss leveraging DASH and SMASH to perform operations similar to what IPMI exposes remotely, but makes use of CIM and WS-Management.

Steve Lee
Principal Test Manager
Standards Based Management Team