-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathcommand.go
155 lines (142 loc) · 4.63 KB
/
command.go
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
package ipmigo
import (
"encoding/hex"
"fmt"
"strings"
)
// Completion Code (Section 5.2)
type CompletionCode uint8
const (
CompletionOK CompletionCode = 0x00
CompletionUnspecifiedError CompletionCode = 0xff
CompletionNodeBusy CompletionCode = iota + 0xc0
CompletionInvalidCommand
CompletionInvalidCommandForLUN
CompletionTimeout
CompletionOutOfSpace
CompletionReservationCancelled
CompletionRequestDataTruncated
CompletionRequestDataInvalidLength
CompletionRequestDataFieldExceedEd
CompletionParameterOutOfRange
CompletionCantReturnDataBytes
CompletionRequestDataNotPresent
CompletionInvalidDataField
CompletionIllegalSendorOrRecord
CompletionCantBeProvided
CompletionDuplicatedRequest
CompletionSDRInUpdateMode
CompletionFirmwareUpdateMode
CompletionBMCInitialization
CompletionDestinationUnavailable
CompletionInsufficientPrivilege
CompletionNotSupportedPresentState
CompletionIllegalCommandDisabled
)
func (c CompletionCode) String() string {
switch c {
case CompletionOK:
return "Command Completed Normally"
case CompletionUnspecifiedError:
return "Unspecified error"
case CompletionNodeBusy:
return "Node Busy"
case CompletionInvalidCommand:
return "Invalid Command"
case CompletionInvalidCommandForLUN:
return "Command invalid for given LUN"
case CompletionTimeout:
return "Timeout"
case CompletionOutOfSpace:
return "Out of space"
case CompletionReservationCancelled:
return "Reservation Canceled or Invalid Reservation ID"
case CompletionRequestDataTruncated:
return "Request data truncated"
case CompletionRequestDataInvalidLength:
return "Request data length invalid"
case CompletionRequestDataFieldExceedEd:
return "Request data field length limit exceeded"
case CompletionParameterOutOfRange:
return "Parameter out of range"
case CompletionCantReturnDataBytes:
return "Cannot return number of requested data bytes"
case CompletionRequestDataNotPresent:
return "Requested Sensor, data, or record not present"
case CompletionInvalidDataField:
return "Invalid data field in Request"
case CompletionIllegalSendorOrRecord:
return "Command illegal for specified sensor or record type"
case CompletionCantBeProvided:
return "Command response could not be provided"
case CompletionDuplicatedRequest:
return "Cannot execute duplicated request"
case CompletionSDRInUpdateMode:
return "SDR Repository in update mode"
case CompletionFirmwareUpdateMode:
return "Device in firmware update mode"
case CompletionBMCInitialization:
return "BMC initialization or initialization agent in progress"
case CompletionDestinationUnavailable:
return "Destination unavailable"
case CompletionInsufficientPrivilege:
return "Cannot execute command due to insufficient privilege level"
case CompletionNotSupportedPresentState:
return "Command not supported in present state"
case CompletionIllegalCommandDisabled:
return "Command sub-function has been disabled or is unavailable"
default:
return fmt.Sprintf("0x%02x", c)
}
}
type Command interface {
Name() string
Code() uint8
NetFnRsLUN() NetFnRsLUN
Marshal() (buf []byte, err error)
Unmarshal(buf []byte) (rest []byte, err error)
String() string
}
type RawCommand struct {
name string
code uint8
netFnRsLUN NetFnRsLUN
input []byte
output []byte
}
func (c *RawCommand) Name() string { return c.name }
func (c *RawCommand) Code() uint8 { return c.code }
func (c *RawCommand) NetFnRsLUN() NetFnRsLUN { return c.netFnRsLUN }
func (c *RawCommand) Input() []byte { return c.input }
func (c *RawCommand) Output() []byte { return c.output }
func (c *RawCommand) Marshal() ([]byte, error) { return c.input, nil }
func (c *RawCommand) Unmarshal(buf []byte) ([]byte, error) {
c.output = make([]byte, len(buf))
copy(c.output, buf)
return nil, nil
}
func (c *RawCommand) String() string {
return fmt.Sprintf(`{"Name":"%s","Code":%d,"NetFnRsRUN":%d,"Input":"%s","Output":"%s"}`,
c.name, c.code, c.netFnRsLUN, hex.EncodeToString(c.input), hex.EncodeToString(c.output))
}
func NewRawCommand(name string, code uint8, fn NetFnRsLUN, input []byte) *RawCommand {
return &RawCommand{
name: name,
code: code,
netFnRsLUN: fn,
input: input,
}
}
func cmdToJSON(c Command) string {
s := fmt.Sprintf(`{"Name":"%s","Code":%d,"NetFnRsLUN":%d,`, c.Name(), c.Code(), c.NetFnRsLUN())
return strings.Replace(toJSON(c), `{`, s, 1)
}
func cmdValidateLength(c Command, msg []byte, min int) error {
if l := len(msg); l < min {
return &MessageError{
Message: fmt.Sprintf("Invalid %s Response size : %d/%d", c.Name(), l, min),
Detail: hex.EncodeToString(msg),
}
}
return nil
}