blob: 5a29eedadf68104c87824521ba83f7bef4b507a5 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package amt
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"github.com/google/uuid"
"go.fuchsia.dev/fuchsia/tools/net/digest"
)
const (
// https://software.intel.com/en-us/node/645995
PowerStateOn = 2
PowerStateLightSleep = 3
PowerStateDeepSleep = 4
PowerStatePowerCycleSoft = 5
PowerStateOffHard = 6
PowerStateHibernate = 7
PowerStateOffSoft = 8
PowerStatePowerCycleHard = 9
PowerStateMasterBusReset = 10
)
// Printf string with placeholders for destination uri, message uuid
const payloadTmpl = `
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:pms="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService">
<s:Header>
<wsa:Action s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService/RequestPowerStateChange</wsa:Action>
<wsa:To s:mustUnderstand="true">%s</wsa:To>
<wsman:ResourceURI s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService</wsman:ResourceURI>
<wsa:MessageID s:mustUnderstand="true">uuid:%s</wsa:MessageID>
<wsa:ReplyTo><wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address></wsa:ReplyTo>
<wsman:SelectorSet>
<wsman:Selector Name="Name">Intel(r) AMT Power Management Service</wsman:Selector>
<wsman:Selector Name="SystemName">Intel(r) AMT</wsman:Selector>
<wsman:Selector Name="CreationClassName">CIM_PowerManagementService</wsman:Selector>
<wsman:Selector Name="SystemCreationClassName">CIM_ComputerSystem</wsman:Selector>
</wsman:SelectorSet>
</s:Header>
<s:Body>
<pms:RequestPowerStateChange_INPUT>
<pms:PowerState>%d</pms:PowerState>
<pms:ManagedElement>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
<wsa:ReferenceParameters>
<wsman:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem</wsman:ResourceURI>
<wsman:SelectorSet>
<wsman:Selector Name="Name">ManagedSystem</wsman:Selector>
<wsman:Selector Name="CreationClassName">CIM_ComputerSystem</wsman:Selector>
</wsman:SelectorSet>
</wsa:ReferenceParameters>
</pms:ManagedElement>
</pms:RequestPowerStateChange_INPUT>
</s:Body>
</s:Envelope>
`
// Reboot sends a Master Bus Reset to an AMT compatible device at host:port.
func Reboot(host, username, password string) error {
// AMT over http always uses port 16992
uri, err := url.Parse(fmt.Sprintf("http://%s:16992/wsman", host))
if err != nil {
return err
}
// Generate MessageID
uuid := uuid.New()
payload := fmt.Sprintf(payloadTmpl, uri.String(), uuid, PowerStatePowerCycleSoft)
t := digest.NewTransport(username, password)
req, err := http.NewRequest("POST", uri.String(), strings.NewReader(payload))
if err != nil {
return err
}
res, err := t.RoundTrip(req)
if err != nil {
return err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
returnValue := string(strings.Split(string(body), "ReturnValue>")[1][0])
if returnValue != "0" {
return fmt.Errorf("amt reboot ReturnValue=%s", returnValue)
}
return nil
}