pax_global_header 0000666 0000000 0000000 00000000064 14741105271 0014514 g ustar 00root root 0000000 0000000 52 comment=bd08d4c38fa1e8407fb8b3834523b1987f3d2c09
golang-github-bougou-go-ipmi-0.7.2/ 0000775 0000000 0000000 00000000000 14741105271 0017106 5 ustar 00root root 0000000 0000000 golang-github-bougou-go-ipmi-0.7.2/.github/ 0000775 0000000 0000000 00000000000 14741105271 0020446 5 ustar 00root root 0000000 0000000 golang-github-bougou-go-ipmi-0.7.2/.github/workflows/ 0000775 0000000 0000000 00000000000 14741105271 0022503 5 ustar 00root root 0000000 0000000 golang-github-bougou-go-ipmi-0.7.2/.github/workflows/build.yml 0000664 0000000 0000000 00000000560 14741105271 0024326 0 ustar 00root root 0000000 0000000 ---
name: Build and Test
on:
push:
branches:
- "main"
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: "1.20"
- name: Build & test
run: |
make dependencies
make build-all
golang-github-bougou-go-ipmi-0.7.2/.github/workflows/release.yml 0000664 0000000 0000000 00000001063 14741105271 0024646 0 ustar 00root root 0000000 0000000 ---
name: Release
on:
push:
tags:
- "v*"
jobs:
release:
name: Build and Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: "1.20"
- name: Build & test
run: |
make dependencies
make build-all
- uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
files: |
_output/*
golang-github-bougou-go-ipmi-0.7.2/.gitignore 0000664 0000000 0000000 00000000667 14741105271 0021107 0 ustar 00root root 0000000 0000000 # Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
cover.out
e2e-reports/
# Translations
*.mo
*.pot
# emacs
.\#*
# vim
*.swp
# ignore bin
/bin/
_output
# ignore vscode
.vscode
# goland
.idea
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
.DS_Store
goipmitest
# asdf
.tool-versions
golang-github-bougou-go-ipmi-0.7.2/CONTRIBUTING.md 0000664 0000000 0000000 00000005052 14741105271 0021341 0 ustar 00root root 0000000 0000000 # Contributing
Each command defined in the IPMI specification is a pair of request/response messages.
These IPMI commands are implemented as methods of the `ipmi.Client` struct in this library.
`ipmitool` as example, some `ipmitool` cmdline are realized by calling just one underlying IPMI command,
but many others are not. Like `ipmitool sdr list`, it's a loop of `GetSDR` IPMI command.
So this library also implements some methods that are not IPMI commands defined
in IPMI specification, but just some common helpers, like `GetSDRs` to get all SDRs.
## IPMI Command Guideline
For a IPMI Command `DoSomething`:
- Must define `DoSomethingRequest` which conforms to the `ipmi.Request` interface, it holds the request message data.
- Must define `DoSomethingResponse` which conforms to the `ipmi.Response` interface, it holds the response message data.
- Must define `DoSomething` method on `ipmi.Client`
For `DoSomething` method, you can pass `DoSomethingRequest` directly as the input parameter, like:
```go
func (c *Client) DoSomething(ctx context.Context, request *DoSomethingRequest) (response *DoSomethingResponse, err error) {
response = &DoSomethingResponse{}
err := c.Exchange(ctx,request, response)
return
}
```
or, you can pass some plain parameters, and construct the `DoSomethingRequest` in method body, like:
```go
func (c *Client) DoSomething(ctx context.Context, param1 string, param2 string) (response *DoSomethingResponse, err error) {
request := &DoSomethingRequest{
// construct by using input params
}
response = &DoSomethingResponse{}
err := c.Exchange(ctx,request, response)
return
}
```
Calling `Exchange` method of `ipmi.Client` will fullfil all other complex underlying works.
## ipmi.Request interface
```go
type Request interface {
// Pack encodes the object to data bytes
Pack() []byte
// Command return the IPMI command info (NetFn/Cmd).
// All IPMI specification specified commands are already predefined in this file.
Command() Command
}
```
## ipmi.Response interface
```go
type Response interface {
// Unpack decodes the object from data bytes
Unpack(data []byte) error
// CompletionCodes returns a map of command-specific completion codes
CompletionCodes() map[uint8]string
// Format return a formatted human friendly string
Format() string
}
```
## IPMI Command Request
## IPMI Command Response
- Define necessary fields per IPMI specification, but DO NOT define the completion code field in Response struct.
- If there is no command-specific completion codes, just return an empty map for `CompletionCodes()` method.
golang-github-bougou-go-ipmi-0.7.2/LICENSE 0000664 0000000 0000000 00000026135 14741105271 0020122 0 ustar 00root root 0000000 0000000 Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
golang-github-bougou-go-ipmi-0.7.2/Makefile 0000664 0000000 0000000 00000003763 14741105271 0020557 0 ustar 00root root 0000000 0000000 APP_VERSION ?= $(shell git describe --abbrev=5 --dirty --tags --always)
GIT_COMMIT := $(shell git rev-parse --short=8 HEAD)
BUILD_TIME := $(shell date -u +'%Y-%m-%dT%H:%M:%SZ')
BINDIR := $(PWD)/bin
OUTPUT_DIR := $(PWD)/_output
GOOS ?= $(shell uname -s | tr '[:upper:]' '[:lower:]')
GOARCH ?= amd64
LDFLAGS := $(LDFLAGS) -X github.com/bougou/go-ipmi/cmd/goipmi/commands.Version=$(APP_VERSION)
LDFLAGS := $(LDFLAGS) -X github.com/bougou/go-ipmi/cmd/goipmi/commands.Commit=$(GIT_COMMIT)
LDFLAGS := $(LDFLAGS) -X github.com/bougou/go-ipmi/cmd/goipmi/commands.BuildAt=$(BUILD_TIME)
PATH := $(BINDIR):$(PATH)
SHELL := env PATH='$(PATH)' /bin/sh
all: build
# Run tests
test: fmt vet
@# Disable --race until https://github.com/kubernetes-sigs/controller-runtime/issues/1171 is fixed.
ginkgo --randomizeAllSpecs --randomizeSuites --failOnPending --flakeAttempts=2 \
--cover --coverprofile cover.out --trace --progress $(TEST_ARGS)\
./pkg/... ./cmd/...
# Build goipmi binary
build: fmt vet
go build -ldflags "$(LDFLAGS)" -o $(OUTPUT_DIR)/goipmi ./cmd/goipmi
# Cross compiler
build-all: fmt vet
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -a -o $(OUTPUT_DIR)/goipmi-$(APP_VERSION)-linux-amd64 ./cmd/goipmi
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -a -o $(OUTPUT_DIR)/goipmi-$(APP_VERSION)-linux-arm64 ./cmd/goipmi
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -a -o $(OUTPUT_DIR)/goipmi-$(APP_VERSION)-darwin-amd64 ./cmd/goipmi
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -a -o $(OUTPUT_DIR)/goipmi-$(APP_VERSION)-darwin-arm64 ./cmd/goipmi
# Run go fmt against code
fmt:
go fmt ./...
# Run go vet against code
vet:
go vet ./...
lint:
$(BINDIR)/golangci-lint run --timeout 2m0s ./...
dependencies:
test -d $(BINDIR) || mkdir $(BINDIR)
GOBIN=$(BINDIR) go install github.com/onsi/ginkgo/ginkgo@v1.16.4
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $(BINDIR) latest
golang-github-bougou-go-ipmi-0.7.2/README.md 0000664 0000000 0000000 00000063764 14741105271 0020405 0 ustar 00root root 0000000 0000000
# [go-ipmi](https://github.com/bougou/go-ipmi)
[`go-ipmi`](https://github.com/bougou/go-ipmi) is a pure golang native IPMI library. It DOES NOT wraps `ipmitool`.
## Usage
```go
import (
"fmt"
"github.com/bougou/go-ipmi"
)
func main() {
host := "10.0.0.1"
port := 623
username := "root"
password := "123456"
client, err := ipmi.NewClient(host, port, username, password)
// Support local mode client if runs directly on linux
// client, err := ipmi.NewOpenClient()
if err != nil {
panic(err)
}
// you can optionally open debug switch
// client.WithDebug(true)
// you can set interface type, enum range: open/lan/lanplus/tool, default open
// client.WithInterface(ipmi.InterfaceLanplus)
// !!! Note !!!,
// From v0.6.0, all IPMI command methods of the Client accept a context as the first argument.
ctx := context.Background()
// Connect will create an authenticated session for you.
if err := client.Connect(ctx); err != nil {
panic(err)
}
// Now you can execute other IPMI commands that need authentication.
res, err := client.GetDeviceID(ctx)
if err != nil {
panic(err)
}
fmt.Println(res.Format())
selEntries, err := client.GetSELEntries(ctx, 0)
if err != nil {
panic(err)
}
fmt.Println(ipmi.FormatSELs(selEntries, nil))
}
```
## `goipmi` binary
The `goipmi` is a binary tool which provides the same command usages like `ipmitool`.
The `goipmi` calls `go-ipmi` library underlying.
The purpose of creating `goipmi` tool was not intended to substitute `ipmitool`.
It was just used to verify the correctness of `go-ipmi` library.
## Functions Comparison with ipmitool
Each command defined in the IPMI specification is a pair of request/response messages.
These IPMI commands are implemented as methods of the `ipmi.Client` struct in this library.
Some `ipmitool` cmdline usages are implemented by calling just one IPMI command,
but others are not. Like `ipmitool sdr list`, it's a loop of `GetSDR` IPMI command.
So this library also implements some methods that are not IPMI commands defined
in IPMI specification, but just some common helpers, like `GetSDRs` to get all SDRs.
These methods are marked with an asterisk (*) after the method name in the following docs.
The implementation logic of IPMI commands are almost same. See [Contributing](./CONTRIBUTING.md)
> More commands are ongoing ...
### IPM Device Global Commands
| Method | Status | corresponding ipmitool usage |
| ---------------------------------- | ------------------ | ----------------------------- |
| GetDeviceID | :white_check_mark: | mc info |
| ColdReset | :white_check_mark: | mc reset cold |
| WarmReset | :white_check_mark: | mc reset warm |
| GetSelfTestResults | :white_check_mark: | mc selftest, chassis selftest |
| ManufacturingTestOn | :white_check_mark: | |
| SetACPIPowerState | :white_check_mark: | |
| GetACPIPowerState | :white_check_mark: | |
| GetDeviceGUID | :white_check_mark: | |
| GetNetFnSupport | :white_check_mark: | |
| GetCommandSupport | :white_check_mark: | |
| GetCommandSubfunctionSupport | | |
| GetConfigurableCommands | :white_check_mark: | |
| GetConfigurableCommandSubfunctions | | |
| SetCommandEnables | | |
| GetCommandEnables | :white_check_mark: | |
| GetCommandSubfunctionsEnables | :white_check_mark: | |
| GetSubfunctionsEnables | | |
| GetOEMNetFnIanaSupport | | |
### BMC Watchdog Timer Commands
| Method | Status | corresponding ipmitool usage |
| ------------------ | ------------------ | ---------------------------- |
| ResetWatchdogTimer | :white_check_mark: | mc watchdog reset |
| SetWatchdogTimer | :white_check_mark: | |
| GetWatchdogTimer | :white_check_mark: | mc watchdog get |
### BMC Device and Messaging Commands
| Method | Status | corresponding ipmitool usage |
| ------------------------------ | ------------------ | ---------------------------- |
| SetBMCGlobalEnables | :white_check_mark: | |
| GetBMCGlobalEnables | :white_check_mark: | |
| ClearMessageFlags | :white_check_mark: | |
| GetMessageFlags | :white_check_mark: | |
| EnableMessageChannelReceive | :white_check_mark: | |
| GetMessage | :white_check_mark: | |
| SendMessage | :white_check_mark: | |
| ReadEventMessageBuffer | :white_check_mark: | |
| GetBTInterfaceCapabilities | | |
| GetSystemGUID | :white_check_mark: | mc guid |
| SetSystemInfoParam | | |
| GetSystemInfoParam | :white_check_mark: | |
| GetSystemInfoParamFor (*) | :white_check_mark: | |
| GetSystemInfoParams (*) | :white_check_mark: | |
| GetSystemInfoParamsFor (*) | :white_check_mark: | |
| GetSystemInfo (*) | :white_check_mark: | |
| GetChannelAuthCapabilities | :white_check_mark: | |
| GetSessionChallenge | :white_check_mark: | |
| ActivateSession | :white_check_mark: | |
| SetSessionPrivilegeLevel | :white_check_mark: | |
| CloseSession | :white_check_mark: | |
| GetSessionInfo | :white_check_mark: | session info |
| GetAuthCode | :white_check_mark: | |
| SetChannelAccess | :white_check_mark: | channel setaccess |
| GetChannelAccess | :white_check_mark: | channel info/getaccess |
| GetChannelInfo | :white_check_mark: | channel info |
| SetUserAccess | :white_check_mark: | |
| GetUserAccess | :white_check_mark: | user summary |
| GetUsers (*) | :white_check_mark: | user list |
| SetUsername | :white_check_mark: | user set name |
| DisableUser (*) | :white_check_mark: | user disable |
| EnableUser (*) | :white_check_mark: | user enable |
| GetUsername | :white_check_mark: |
| SetUserPassword | :white_check_mark: | user set password |
| TestUserPassword (*) | :white_check_mark: | user test |
| ActivatePayload | | |
| DeactivatePayload | | |
| GetPayloadActivationStatus | | |
| GetPayloadInstanceInfo | | |
| SetUserPayloadAccess | | |
| GetUserPayloadAccess | | sol payload status |
| GetChannelPayloadSupport | | |
| GetChannelPayloadVersion | | |
| GetChannelOEMPayloadInfo | | |
| MasterWriteRead | | |
| GetChannelCipherSuites | :white_check_mark: | |
| SuspendOrResumeEncryption | | |
| SetChannelCipherSuites | | |
| GetSystemInterfaceCapabilities | :white_check_mark: | |
### Chassis Device Commands
| Method | Status | corresponding ipmitool usage |
| --------------------------------- | ------------------ | ------------------------------------------------- |
| GetChassisCapabilities | :white_check_mark: | |
| GetChassisStatus | :white_check_mark: | chassis status, chassis power status |
| ChassisControl | :white_check_mark: | chassis power on/off/cycle/reset/diag/soft |
| ChassisReset | :white_check_mark: | |
| ChassisIdentify | :white_check_mark: | chassis identify |
| SetChassisCapabilities | :white_check_mark: | |
| SetPowerRestorePolicy | :white_check_mark: | chassis policy list/always-on/previous/always-off |
| GetSystemRestartCause | :white_check_mark: | chassis restart_cause |
| SetBootParamBootFlags (*) | :white_check_mark: | chassis bootdev |
| SetBootDevice (*) | :white_check_mark: | chassis bootdev |
| SetSystemBootOptionsParam | :white_check_mark: | chassis bootparam set |
| GetSystemBootOptionsParam | :white_check_mark: | chassis bootparam get |
| GetSystemBootOptionsParamFor (*) | :white_check_mark: | chassis bootparam get |
| GetSystemBootOptionsParams (*) | :white_check_mark: | chassis bootparam get |
| GetSystemBootOptionsParamsFor (*) | :white_check_mark: | chassis bootparam get |
| SetFrontPanelEnables | :white_check_mark: | |
| SetPowerCycleInterval | :white_check_mark: | |
| GetPOHCounter | :white_check_mark: | chassis poh |
### Event Commands
| Method | Status | corresponding ipmitool usage |
| -------------------- | ------------------ | ---------------------------- |
| SetEventReceiver | :white_check_mark: | |
| GetEventReceiver | :white_check_mark: | |
| PlatformEventMessage | :white_check_mark: | |
### PEF and Alerting Commands
| Method | Status | corresponding ipmitool usage |
| ------------------------- | ------------------ | ---------------------------- |
| GetPEFCapabilities | :white_check_mark: | pef capabilities |
| ArmPEFPostponeTimer | | |
| SetPEFConfigParam | | |
| GetPEFConfigParam | | |
| GetPEFConfigParamFor (*) | | |
| GetPEFConfigParams (*) | | |
| GetPEFConfigParamsFor (*) | | |
| SetLastProcessedEventId | | |
| GetLastProcessedEventId | | |
| AlertImmediate | | |
| PEFAck | | |
### Sensor Device Commands
| Method | Status | corresponding ipmitool usage |
| ------------------------------ | ------------------ | ---------------------------- |
| GetDeviceSDRInfo | :white_check_mark: | |
| GetDeviceSDR | :white_check_mark: | |
| ReserveDeviceSDRRepo | :white_check_mark: | |
| GetSensorReadingFactors | :white_check_mark: | |
| SetSensorHysteresis | :white_check_mark: | |
| GetSensorHysteresis | :white_check_mark: | |
| SetSensorThresholds | :white_check_mark: | |
| GetSensorThresholds | :white_check_mark: | |
| SetSensorEventEnable | | |
| GetSensorEventEnable | :white_check_mark: | |
| RearmSensorEvents | | |
| GetSensorEventStatus | :white_check_mark: | |
| GetSensorReading | :white_check_mark: | |
| SetSensorType | :white_check_mark: | |
| GetSensorType | :white_check_mark: | |
| SetSensorReadingAndEventStatus | :white_check_mark: | |
| GetSensors (*) | :white_check_mark: | sensor list, sdr type |
| GetSensorByID (*) | :white_check_mark: | |
| GetSensorByName (*) | :white_check_mark: | sensor get |
### FRU Device Commands
| Method | Status | corresponding ipmitool usage |
| ----------------------- | ------------------ | ---------------------------- |
| GetFRUInventoryAreaInfo | :white_check_mark: | |
| ReadFRUData | :white_check_mark: | |
| WriteFRUData | :white_check_mark: | |
| GetFRU (*) | :white_check_mark: | fru print |
| GetFRUs (*) | :white_check_mark: | fru print |
### SDR Device Commands
| Method | Status | corresponding ipmitool usage |
| ---------------------- | ------------------ | ---------------------------- |
| GetSDRRepoInfo | :white_check_mark: | sdr info |
| GetSDRRepoAllocInfo | :white_check_mark: | sdr info |
| ReserveSDRRepo | | |
| GetSDR | :white_check_mark: | |
| GetSDRs (*) | :white_check_mark: | |
| GetSDRBySensorID (*) | :white_check_mark: | |
| GetSDRBySensorName (*) | :white_check_mark: | |
| AddSDR | | |
| PartialAddSDR | | |
| DeleteSDR | | |
| ClearSDRRepo | | |
| GetSDRRepoTime | | |
| SetSDRRepoTime | | |
| EnterSDRRepoUpdateMode | | |
| ExitSDRRepoUpdateMode | | |
| RunInitializationAgent | | |
### SEL Device Commands
| Method | Status | corresponding ipmitool usage |
| ------------------- | ------------------ | ---------------------------- |
| GetSELInfo | :white_check_mark: | sel info |
| GetSELAllocInfo | :white_check_mark: | sel info |
| ReserveSEL | :white_check_mark: | |
| GetSELEntry | :white_check_mark: | |
| AddSELEntry | :white_check_mark: | |
| PartialAddSELEntry | | |
| DeleteSELEntry | :white_check_mark: | |
| ClearSEL | :white_check_mark: | sel clear |
| GetSELTime | :white_check_mark: | |
| SetSELTime | :white_check_mark: | |
| GetAuxLogStatus | | |
| SetAuxLogStatus | | |
| GetSELTimeUTCOffset | :white_check_mark: | |
| SetSELTimeUTCOffset | :white_check_mark: | |
### LAN Device Commands
| Method | Status | corresponding ipmitool usage |
| ------------------------- | ------------------ | ---------------------------- |
| SetLanConfigParam | :white_check_mark: | lan set |
| SetLanConfigParamFor (*) | :white_check_mark: | lan set |
| GetLanConfigParam | :white_check_mark: | |
| GetLanConfigParamFor (*) | :white_check_mark: | lan print |
| GetLanConfigParams (*) | :white_check_mark: | lan print |
| GetLanConfigParamsFor (*) | :white_check_mark: | lan print |
| GetLanConfig (*) | :white_check_mark: | lan print |
| SuspendARPs | :white_check_mark: | |
| GetIPStatistics | :white_check_mark: | |
### Serial/Modem Device Commands
| Method | Status | corresponding ipmitool usage |
| ------------------------- | ------------------ | ---------------------------- |
| SetSerialConfig | | |
| GetSerialConfig | | |
| SetSerialMux | | |
| GetTapResponseCodes | | |
| SetPPPTransmitData | | |
| GetPPPTransmitData | | |
| SendPPPPacket | | |
| GetPPPReceiveData | | |
| SerialConnectionActive | | |
| Callback | | |
| SetUserCallbackOptions | | |
| GetUserCallbackOptions | | |
| SetSerialRoutingMux | | |
| SOLActivating | :white_check_mark: | |
| SetSOLConfigParam | :white_check_mark: | |
| SetSOLConfigParamFor (*) | :white_check_mark: | |
| GetSOLConfigParam | :white_check_mark: | |
| GetSOLConfigParamFor (*) | :white_check_mark: | |
| GetSOLConfigParams (*) | :white_check_mark: | sol info |
| GetSOLConfigParamsFor (*) | :white_check_mark: | sol info |
### Command Forwarding Commands
| Method | Status | corresponding ipmitool usage |
| --------------- | ------ | ---------------------------- |
| Forwarded | | |
| SetForwarded | | |
| GetForwarded | | |
| EnableForwarded | | |
### Bridge Management Commands (ICMB)
| Method | Status | corresponding ipmitool usage |
| --------------------- | ------ | ---------------------------- |
| GetBridgeState | | |
| SetBridgeState | | |
| GetICMBAddress | | |
| SetICMBAddress | | |
| SetBridgeProxyAddress | | |
| GetBridgeStatistics | | |
| GetICMBCapabilities | | |
| ClearBridgeStatistics | | |
| GetBridgeProxyAddress | | |
| GetICMBConnectorInfo | | |
| GetICMBConnectionID | | |
| SendICMBConnectionID | | |
### Discovery Commands (ICMB)
| Method | Status | corresponding ipmitool usage |
| ------------------- | ------ | ---------------------------- |
| PrepareForDiscovery | | |
| GetAddresses | | |
| SetDiscovered | | |
| GetChassisDeviceId | | |
| SetChassisDeviceId | | |
### Bridging Commands (ICMB)
| Method | Status | corresponding ipmitool usage |
| ------------- | ------ | ---------------------------- |
| BridgeRequest | | |
| BridgeMessage | | |
### Event Commands (ICMB)
| Method | Status | corresponding ipmitool usage |
| ---------------------- | ------ | ---------------------------- |
| GetEventCount | | |
| SetEventDestination | | |
| SetEventReceptionState | | |
| SendICMBEventMessage | | |
| GetEventDestination | | |
| GetEventReceptionState | | |
### Other Bridge Commands
| Method | Status | corresponding ipmitool usage |
| ----------- | ------ | ---------------------------- |
| ErrorReport | | |
### DCMI Commands
| Method | Status | corresponding ipmitool usage |
| ------------------------------- | ------------------ | ---------------------------- |
| GetDCMICapParam | :white_check_mark: | dcmi discovery |
| GetDCMICapParamFor (*) | :white_check_mark: | dcmi discovery |
| GetDCMICapParams (*) | :white_check_mark: | dcmi discovery |
| GetDCMICapParamsFor (*) | :white_check_mark: | dcmi discovery |
| GetDCMIPowerReading | :white_check_mark: | dcmi power reading |
| GetDCMIPowerLimit | :white_check_mark: | dcmi power get_limit |
| SetDCMIPowerLimit | :white_check_mark: | dcmi power set_limit |
| ActivateDCMIPowerLimit | :white_check_mark: | dcmi activate/deactivate |
| GetDCMIAssetTag | :white_check_mark: | dcmi asset_tag |
| GetDCMIAssetTagFull (*) | :white_check_mark: | dcmi asset_tag |
| GetDCMISensorInfo | :white_check_mark: | dcmi sensors |
| SetDCMIAssetTag | :white_check_mark: | dcmi set_asset_tag |
| GetDCMIMgmtControllerIdentifier | :white_check_mark: | dcmi get_mc_id_string |
| SetDCMIMgmtControllerIdentifier | :white_check_mark: | dcmi set_mc_id_string |
| SetDCMIThermalLimit | :white_check_mark: | dcmi thermalpolicy get |
| GetDCMIThermalLimit | :white_check_mark: | dcmi thermalpolicy set |
| GetDCMITemperatureReadings | :white_check_mark: | dcmi get_temp_reading |
| SetDCMIConfigParam | :white_check_mark: | dcmi set_conf_param |
| GetDCMIConfigParam | :white_check_mark: | dcmi get_conf_param |
| GetDCMIConfigParamFor (*) | :white_check_mark: | dcmi get_conf_param |
| GetDCMIConfigParams (*) | :white_check_mark: | dcmi get_conf_param |
| GetDCMIConfigParamsFor (*) | :white_check_mark: | dcmi get_conf_param |
## Reference
- [Intelligent Platform Management Interface Specification Second Generation v2.0](https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/ipmi-intelligent-platform-mgt-interface-spec-2nd-gen-v2-0-spec-update.pdf)
- [Platform Management FRU Information Storage Definition](https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/ipmi-platform-mgt-fru-info-storage-def-v1-0-rev-1-3-spec-update.pdf)
- [PC SDRAM Serial Presence Detect (SPD) Specification](https://cdn.hackaday.io/files/10119432931296/Spdsd12b.pdf)
- [DCMI Group Extension Specification v1.5](https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/dcmi-v1-5-rev-spec.pdf)
golang-github-bougou-go-ipmi-0.7.2/_config.yml 0000664 0000000 0000000 00000000515 14741105271 0021236 0 ustar 00root root 0000000 0000000 lsi: false
safe: true
incremental: false
gist:
noscript: false
markdown: kramdown
highlighter: rouge
permalink: pretty
repos:
- name: go-ipmi
description: IPMI library in pure Go
url: https://github.com/bougou/go-ipmi
brand_color: "#DA253B"
kramdown:
math_engine: mathjax
syntax_highlighter: rouge
plugins:
- jemoji
golang-github-bougou-go-ipmi-0.7.2/client.go 0000664 0000000 0000000 00000013120 14741105271 0020710 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"sync"
"time"
"golang.org/x/net/proxy"
)
type Interface string
const (
InterfaceLan Interface = "lan"
InterfaceLanplus Interface = "lanplus"
InterfaceOpen Interface = "open"
InterfaceTool Interface = "tool"
DefaultExchangeTimeoutSec int = 20
DefaultKeepAliveIntervalSec int = 30
DefaultBufferSize int = 1024
)
type Client struct {
Host string
Port int
Username string // length must <= 16
Password string
Interface Interface
debug bool
maxPrivilegeLevel PrivilegeLevel
responderAddr uint8
responderLUN uint8
requesterAddr uint8
requesterLUN uint8
openipmi *openipmi
session *session
// this flags controls which IPMI version (1.5 or 2.0) be used by Client to send Request
v20 bool
udpClient *UDPClient
timeout time.Duration
bufferSize int
l sync.Mutex
// closedCh is closed when Client.Close() is called.
// used to notify other goroutines that Client is closed.
closedCh chan bool
}
func NewOpenClient() (*Client, error) {
myAddr := BMC_SA
return &Client{
Interface: "open",
timeout: time.Second * time.Duration(DefaultExchangeTimeoutSec),
bufferSize: DefaultBufferSize,
openipmi: &openipmi{
myAddr: myAddr,
targetAddr: myAddr,
},
}, nil
}
// NewToolClient creates an IPMI client based ipmitool.
// You should pass the file path of ipmitool binary or path of a wrapper script
// that would be executed.
func NewToolClient(path string) (*Client, error) {
return &Client{
Host: path,
Interface: "tool",
}, nil
}
func NewClient(host string, port int, user string, pass string) (*Client, error) {
if len(user) > IPMI_MAX_USER_NAME_LENGTH {
return nil, fmt.Errorf("user name (%s) too long, exceed (%d) characters", user, IPMI_MAX_USER_NAME_LENGTH)
}
c := &Client{
Host: host,
Port: port,
Username: user,
Password: pass,
Interface: InterfaceLanplus,
v20: true,
timeout: time.Second * time.Duration(DefaultExchangeTimeoutSec),
bufferSize: DefaultBufferSize,
maxPrivilegeLevel: PrivilegeLevelUnspecified,
responderAddr: BMC_SA,
responderLUN: uint8(IPMB_LUN_BMC),
requesterAddr: RemoteConsole_SWID,
requesterLUN: 0x00,
session: &session{
// IPMI Request Sequence, start from 1
ipmiSeq: 1,
v20: v20{
state: SessionStatePreSession,
cipherSuiteID: CipherSuiteIDReserved,
},
v15: v15{
active: false,
},
},
closedCh: make(chan bool),
}
c.udpClient = &UDPClient{
Host: host,
Port: port,
timeout: c.timeout,
bufferSize: c.bufferSize,
}
return c, nil
}
func (c *Client) WithInterface(intf Interface) *Client {
c.Interface = intf
return c
}
func (c *Client) WithDebug(debug bool) *Client {
c.debug = debug
return c
}
func (c *Client) WithUDPProxy(proxy proxy.Dialer) *Client {
if c.udpClient != nil {
c.udpClient.SetProxy(proxy)
}
return c
}
func (c *Client) WithTimeout(timeout time.Duration) *Client {
c.timeout = timeout
if c.udpClient != nil {
c.udpClient.timeout = timeout
}
return c
}
func (c *Client) WithBufferSize(bufferSize int) *Client {
c.bufferSize = bufferSize
if c.udpClient != nil {
c.udpClient.bufferSize = bufferSize
}
return c
}
// WithCipherSuiteID sets a custom cipher suite which is used during OpenSession command.
// It is only valid for client with IPMI lanplus interface.
// For the custom cipherSuiteID to take effect, you must call WithCipherSuiteID before calling Connect method.
func (c *Client) WithCipherSuiteID(cipherSuiteID CipherSuiteID) *Client {
if c.session != nil {
c.session.v20.cipherSuiteID = cipherSuiteID
}
return c
}
// WithMaxPrivilegeLevel sets a specified session privilege level to use.
func (c *Client) WithMaxPrivilegeLevel(privilegeLevel PrivilegeLevel) *Client {
c.maxPrivilegeLevel = privilegeLevel
return c
}
func (c *Client) WithResponderAddr(responderAddr, responderLUN uint8) {
c.responderAddr = responderAddr
c.responderLUN = responderLUN
}
func (c *Client) WithRequesterAddr(requesterAddr, requesterLUN uint8) {
c.requesterAddr = requesterAddr
c.requesterLUN = requesterLUN
}
func (c *Client) SessionPrivilegeLevel() PrivilegeLevel {
return c.maxPrivilegeLevel
}
// Connect connects to the bmc by specified Interface.
func (c *Client) Connect(ctx context.Context) error {
// Optional RMCP Ping/Pong mechanism
// pongRes, err := c.RmcpPing()
// if err != nil {
// return fmt.Errorf("RMCP Ping failed, err: %w", err)
// }
// if pongRes.IPMISupported {
// return fmt.Errorf("ipmi not supported")
// }
switch c.Interface {
case "", InterfaceOpen:
var devnum int32 = 0
return c.ConnectOpen(ctx, devnum)
case InterfaceTool:
var devnum int32 = 0
return c.ConnectTool(ctx, devnum)
case InterfaceLanplus:
c.v20 = true
return c.Connect20(ctx)
case InterfaceLan:
c.v20 = false
return c.Connect15(ctx)
default:
return fmt.Errorf("not supported interface, supported: lan,lanplus,open")
}
}
func (c *Client) Close(ctx context.Context) error {
switch c.Interface {
case "", InterfaceOpen:
return c.closeOpen(ctx)
case InterfaceTool:
return c.closeTool(ctx)
case InterfaceLan, InterfaceLanplus:
return c.closeLAN(ctx)
}
return nil
}
func (c *Client) Exchange(ctx context.Context, request Request, response Response) error {
switch c.Interface {
case "", InterfaceOpen:
return c.exchangeOpen(ctx, request, response)
case InterfaceTool:
return c.exchangeTool(ctx, request, response)
case InterfaceLan, InterfaceLanplus:
return c.exchangeLAN(ctx, request, response)
}
return nil
}
func (c *Client) lock() {
c.l.Lock()
}
func (c *Client) unlock() {
c.l.Unlock()
}
golang-github-bougou-go-ipmi-0.7.2/client_auth_code.go 0000664 0000000 0000000 00000030444 14741105271 0022733 0 ustar 00root root 0000000 0000000 package ipmi
import (
"crypto/md5"
"fmt"
"github.com/bougou/go-ipmi/utils/md2"
)
// 22.17.1 AuthCode Algorithms
// Single Session AuthCode carried in IPMI message data for Activate Session Command
// to fill ActiveSessionRequest.Challenge
type AuthCodeSingleSessionInput struct {
Password string
SessionID uint32
Challenge []byte
}
func (a AuthCodeSingleSessionInput) AuthCode(authType AuthType) []byte {
password := padBytes(a.Password, 16, 0x00)
inputLength := 16 + 4 + len(a.Challenge) + 16
var input = make([]byte, inputLength)
packBytes(password, input, 0)
packUint32L(a.SessionID, input, 16)
packBytes(a.Challenge[:], input, 20)
packBytes(password, input, 20+len(a.Challenge))
var authCode []byte
switch authType {
case AuthTypePassword:
authCode = password
case AuthTypeMD2:
authCode = md2.New().Sum(input)
authCode = authCode[:16]
case AuthTypeMD5:
c := md5.Sum(input) // can not use md5.New().Sum(input)
authCode = c[:]
}
return authCode[:16]
}
// 22.17.1 AuthCode Algorithms
// Multi-Session AuthCode carried in session header for all authenticated packets
type AuthCodeMultiSessionInput struct {
Password string
SessionID uint32
SessionSeq uint32
IPMIData []byte
}
func (i *AuthCodeMultiSessionInput) AuthCode(authType AuthType) []byte {
password := padBytes(i.Password, 16, 0x00)
ipmiData := i.IPMIData
// The Integrity Algorithm Number specifies the algorithm used to generate the contents
// for the AuthCode signature field that accompanies authenticated IPMI v2.0/RMCP+ messages once the session has been
// established.
// Unless otherwise specified, the integrity algorithm is applied to the packet data starting with the
// AuthType/Format field up to and including the field that immediately precedes the AuthCode field itself.
authCodeInputLength := len(password) +
4 + // session od uint32
len(ipmiData) +
4 + // session seq uint32
len(password)
var input = make([]byte, authCodeInputLength)
packBytes(password, input, 0)
packUint32L(i.SessionID, input, 16)
packBytes(ipmiData, input, 20)
packUint32L(i.SessionSeq, input, 20+len(ipmiData))
packBytes(password, input, 20+len(ipmiData)+4)
// c := md5.Sum(input)
// authCode := c[:]
var authCode []byte
switch authType {
case AuthTypePassword:
authCode = password
case AuthTypeMD2:
authCode = md2.New().Sum(input)
authCode = authCode[:16]
case AuthTypeMD5:
c := md5.Sum(input) // can not use md5.New().Sum(input)
authCode = c[:]
}
return authCode[:16]
}
func (c *Client) genAuthCodeForSingleSession() []byte {
input := &AuthCodeSingleSessionInput{
Password: c.Password,
SessionID: c.session.v15.sessionID,
Challenge: c.session.v15.challenge[:],
}
authCode := input.AuthCode(c.session.authType)
c.DebugBytes(fmt.Sprintf("authtype (%d) gen authcode", c.session.authType), authCode, 16)
return authCode
}
// only be used for ActivateSession (IPMI v1.5)
// see 22.17.1 AuthCode Algorithms
func (c *Client) genAuthCodeForMultiSession(ipmiMsg []byte) []byte {
input := &AuthCodeMultiSessionInput{
Password: c.Password,
SessionID: c.session.v15.sessionID,
SessionSeq: c.session.v15.inSeq,
IPMIData: ipmiMsg,
}
authCode := input.AuthCode(c.session.authType)
c.DebugBytes(fmt.Sprintf("authtype (%d) gen authcode", c.session.authType), authCode, 16)
return authCode
}
// When the HMAC-SHA1-96 Integrity Algorithm is used the resulting AuthCode field is 12 bytes (96 bits).
// When the HMAC-SHA256-128 and HMAC-MD5-128 Integrity Algorithms are used the resulting AuthCode field is 16-bytes (128 bits).
func (c *Client) genIntegrityAuthCode(input []byte) ([]byte, error) {
switch c.session.v20.integrityAlg {
case IntegrityAlg_None:
// If the Integrity Algorithm is none the AuthCode value is not calculated and
// the AuthCode field in the message is not present (zero bytes).
return []byte{}, nil
case IntegrityAlg_MD5_128:
data := []byte{}
data = append(data, []byte(c.Password)[:]...)
data = append(data, input...)
data = append(data, []byte(c.Password)[:]...)
h := md5.Sum(data)
return h[:], nil
case IntegrityAlg_HMAC_MD5_128:
b, err := generate_hmac("md5", input, c.session.v20.k1)
if err != nil {
return nil, fmt.Errorf("generate hmac failed")
}
return b[0:16], nil
case IntegrityAlg_HMAC_SHA1_96:
b, err := generate_hmac("sha1", input, c.session.v20.k1)
if err != nil {
return nil, fmt.Errorf("generate hmac failed")
}
return b[0:12], nil
case IntegrityAlg_HMAC_SHA256_128:
b, err := generate_hmac("sha256", input, c.session.v20.k1)
if err != nil {
return nil, fmt.Errorf("generate hmac failed")
}
return b[0:16], nil
default:
return nil, fmt.Errorf("not support for integrity algorithm %x", c.session.v20.integrityAlg)
}
}
// sik (Session Integrity Key)
// Both the remote console and the managed system generate sik by using
// the same hmackey and hmac data, so they should be same.
// see 13.31
func (c *Client) generate_sik() ([]byte, error) {
input := make([]byte, 34+len(c.Username))
packBytes(c.session.v20.consoleRand[:], input, 0) // 16 bytes
packBytes(c.session.v20.bmcRand[:], input, 16) // 16 bytes
packUint8(c.session.v20.role, input, 32) // 1 bytes, Requested privilege level (entire byte)
packUint8(uint8(len(c.Username)), input, 33) // 1 bytes, Username length
packBytes([]byte(c.Username), input, 34) // N bytes, Username (absent for null usernames)
c.DebugBytes("sik mac input", input, 16)
var hmacKey []byte
// hmacKey should use 160-bit key Kg
// and Kuid is used in place of Kg if "one-key" logins are being used.
if len(c.session.v20.bmcKey) != 0 {
hmacKey = c.session.v20.bmcKey
} else {
hmacKey = padBytes(c.Password, 20, 0x00) // 160 bit = 20 bytes
}
c.DebugBytes("sik mac key", hmacKey, 16)
b, err := generate_auth_hmac(c.session.v20.authAlg, input, hmacKey)
if err != nil {
return nil, fmt.Errorf("generate hmac failed, err: %w", err)
}
c.DebugBytes("sik mac computed by the remote console:", b, 16)
return b, nil
}
// see 13.32 Generating Additional Keying Material
//
// generate K1 key, the session integrity key (SIK) is used as hmac key.
func (c *Client) generate_k1() ([]byte, error) {
var CONST_1 = [20]byte{
0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01,
}
if c.session.v20.sik == nil {
return nil, fmt.Errorf("sik not exists, generate sik first")
}
hmacKey := c.session.v20.sik
b, err := generate_auth_hmac(c.session.v20.authAlg, CONST_1[:], hmacKey)
if err != nil {
return nil, fmt.Errorf("generate hmac failed, err: %w", err)
}
c.DebugBytes("generated k1:", b, 16)
return b, nil
}
// see 13.32 Generating Additional Keying Material
//
// generate K2 key, the session integrity key (SIK) is used as hmac key.
func (c *Client) generate_k2() ([]byte, error) {
var CONST_2 = [20]byte{
0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02,
}
if c.session.v20.sik == nil {
return nil, fmt.Errorf("sik not exists, generate sik first")
}
hmacKey := c.session.v20.sik
b, err := generate_auth_hmac(c.session.v20.authAlg, CONST_2[:], hmacKey)
if err != nil {
return nil, fmt.Errorf("generate hmac failed, err: %w", err)
}
c.DebugBytes("generated k2:", b, 16)
return b, nil
}
// used for verify rakp2
func (c *Client) generate_rakp2_authcode() ([]byte, error) {
c.DebugBytes("bmc rand", c.session.v20.bmcRand[:], 16)
bufferLen := 4 + 4 + 16 + 16 + 16 + 1 + 1 + len(c.Username)
var buffer = make([]byte, bufferLen)
packUint32L(c.session.v20.consoleSessionID, buffer, 0) // 4 bytes, Console session ID (SID)
packUint32L(c.session.v20.bmcSessionID, buffer, 4) // 4 bytes, bmc session ID (SID)
packBytes(c.session.v20.consoleRand[:], buffer, 8) // 16 bytes, Remote console random number
packBytes(c.session.v20.bmcRand[:], buffer, 24) // 16 bytes, BMC random number (RC)
packBytes(c.session.v20.bmcGUID[:], buffer, 40) // 16 bytes, BMC guid
packUint8(c.session.v20.role, buffer, 56) // 1 bytes, entire byte of privilege level of rakp1
packUint8(uint8(len(c.Username)), buffer, 57) // 1 bytes, Username length
packBytes([]byte(c.Username), buffer, 58) // N bytes, Username (absent for null usernames)
c.DebugBytes("rakp2 authcode input", buffer, 16)
// The bmc also use user password to calculate authcode, so if the authcode does not match,
// it may indicates the password is not right.
hmacKey := padBytes(c.Password, 20, 0x00)
c.DebugBytes("rakp2 authcode key", hmacKey, 16)
b, err := generate_auth_hmac(c.session.v20.authAlg, buffer, hmacKey)
if err != nil {
return nil, fmt.Errorf("generate hmac failed, err: %w", err)
}
c.DebugBytes("rakp2 generated authcode", b, 16)
var out = b
switch c.session.v20.authAlg {
case AuthAlgRAKP_None:
// nothing need to do
case AuthAlgRAKP_HMAC_MD5:
// need to copy 16 bytes
if len(b) < 16 {
err = fmt.Errorf("hmac md5 length should be at least 16 bytes")
}
out = b[0:16]
case AuthAlgRAKP_HMAC_SHA1:
// need to copy 20 bytes
if len(b) < 20 {
err = fmt.Errorf("hmac sha1 length should be at least 20 bytes")
}
out = b[0:20]
case AuthAlgRAKP_HMAC_SHA256:
if len(b) < 32 {
err = fmt.Errorf("hmac sha256 length should be at least 32 bytes")
}
out = b[0:32]
default:
err = fmt.Errorf("rakp2 message: no support for authentication algorithm 0x%x", c.session.v20.authAlg)
}
c.DebugBytes("rakp2 used authcode", out, 16)
return out, err
}
// 22.17.1 AuthCode Algorithms
func (c *Client) generate_rakp3_authcode() ([]byte, error) {
// The auth code is an HMAC generated with the following content
var input []byte = []byte{}
input = append(input, c.session.v20.bmcRand[:]...) // 16 bytes, BMC random number (RC)
buffer := make([]byte, 4)
packUint32L(c.session.v20.consoleSessionID, buffer, 0)
input = append(input, buffer...) // 4 bytes, Console session ID (SID)
input = append(input, byte(c.session.v20.role)) // 1 bytes, Requested privilege level (entire byte)
input = append(input, byte(len([]byte(c.Username)))) // 1 bytes, Username length
input = append(input, []byte(c.Username)...) // N bytes, Username (absent for null usernames)
c.DebugBytes("rakp3 auth code input", input, 16)
hmacKey := padBytes(c.Password, 20, 0x00)
c.DebugBytes("rakp3 auth code key", hmacKey, 16)
b, err := generate_auth_hmac(c.session.v20.authAlg, input, hmacKey)
if err != nil {
return nil, fmt.Errorf("generate hmac failed, err: %w", err)
}
c.DebugBytes("rakp3 generated authcode", b, 16)
var out = b
c.DebugBytes("rakp3 used authcode", out, 16)
return out, err
}
// 13.31 RMCP+ Authenticated Key-Exchange Protocol (RAKP)
// 13.28
// the client use this method to verify the authcode returned in rakp4
func (c *Client) generate_rakp4_authcode() ([]byte, error) {
var input []byte = []byte{}
input = append(input, c.session.v20.consoleRand[:]...) // 16 bytes, Console random number
buffer := make([]byte, 4)
packUint32L(c.session.v20.bmcSessionID, buffer, 0)
input = append(input, buffer...) // 4 bytes, BMC session ID (SID)
input = append(input, c.session.v20.bmcGUID[:]...) // 16 bytes
c.DebugBytes("rakp4 auth code input", input, 16)
hmacKey := c.session.v20.sik
c.DebugBytes("rakp4 auth code key", hmacKey, 16)
b, err := generate_auth_hmac(c.session.v20.integrityAlg, input, hmacKey)
if err != nil {
return nil, fmt.Errorf("generate hmac failed, err: %w", err)
}
c.DebugBytes("rakp4 generated authcode", b, 16)
var errHmacLen = func(length int, integrityAlg IntegrityAlg) error {
return fmt.Errorf("the length of generated mac is not long enough, should be at least (%d) for integrity algorithm (%0x)", len(b), integrityAlg)
}
var out = b
integrityAlg := c.session.v20.integrityAlg
switch integrityAlg {
case IntegrityAlg_None:
// nothing need to do
case IntegrityAlg_HMAC_MD5_128:
// need to copy 16 bytes
if len(b) < 16 {
err = errHmacLen(len(b), integrityAlg)
}
out = b[0:16]
case IntegrityAlg_HMAC_SHA1_96:
// need to copy 12 bytes
if len(b) < 12 {
err = errHmacLen(len(b), integrityAlg)
}
out = b[0:12]
case IntegrityAlg_HMAC_SHA256_128:
if len(b) < 16 {
err = errHmacLen(len(b), integrityAlg)
}
out = b[0:16]
default:
err = fmt.Errorf("rakp4 message: no support for integrity algorithm %x", c.session.v20.integrityAlg)
}
c.DebugBytes("rakp4 used authcode", out, 16)
return out, err
}
golang-github-bougou-go-ipmi-0.7.2/client_auth_code_test.go 0000664 0000000 0000000 00000004357 14741105271 0023776 0 ustar 00root root 0000000 0000000 package ipmi
import "testing"
func Test_ActivateSessionAuthCode(t *testing.T) {
tests := []struct {
name string
commandRequest Request
ipmiRequest *IPMIRequest
input *AuthCodeMultiSessionInput
expect []byte
}{
{
name: "test1",
commandRequest: &ActivateSessionRequest{
AuthTypeForSession: 0x02,
MaxPrivilegeLevel: 0x04,
Challenge: [16]byte{0x82, 0x8f, 0xa9, 0xbf, 0x25, 0x51, 0x6b, 0x2a, 0xf5, 0xf8, 0xfb, 0x3f, 0x37, 0xae, 0x6e, 0x69},
InitialOutboundSequenceNumber: 0xa2605e12,
},
ipmiRequest: &IPMIRequest{
ResponderAddr: 0x20,
ResponderLUN: 0x0,
NetFn: NetFnAppRequest,
RequesterAddr: 0x81,
RequesterLUN: 0x0,
RequesterSequence: 0x03,
Command: 0x3a,
},
input: &AuthCodeMultiSessionInput{
// cSpell:disable
Password: "vtA9kBPODBPBy",
// cSpell:enable
SessionID: 0xb215d500,
SessionSeq: 0x00000000,
},
expect: []byte{0xec, 0xb1, 0x65, 0xeb, 0xdc, 0xf7, 0x9f, 0xd9, 0x96, 0xa3, 0xfa, 0x6b, 0xae, 0x18, 0x69, 0x54},
},
{
name: "test2",
commandRequest: &SetSessionPrivilegeLevelRequest{
PrivilegeLevel: PrivilegeLevelAdministrator,
},
ipmiRequest: &IPMIRequest{
ResponderAddr: 0x20,
ResponderLUN: 0x0,
NetFn: CommandSetSessionPrivilegeLevel.NetFn,
RequesterAddr: 0x81,
RequesterLUN: 0x0,
RequesterSequence: 0x04,
Command: CommandSetSessionPrivilegeLevel.ID,
},
input: &AuthCodeMultiSessionInput{
// cSpell:disable
Password: "vtA9kBPODBPBy",
// cSpell:enable
SessionID: 0xa26f8e00,
SessionSeq: 0xdabbb496,
},
expect: []byte{0x69, 0xe8, 0x3e, 0x2b, 0x99, 0xe3, 0xf6, 0xa9, 0x3d, 0x1c, 0xf0, 0x47, 0x8b, 0x0e, 0xfe, 0xba},
},
}
for _, tt := range tests {
commandData := tt.commandRequest.Pack()
tt.ipmiRequest.CommandData = commandData
tt.ipmiRequest.ComputeChecksum()
ipmiData := tt.ipmiRequest.Pack()
tt.input.IPMIData = ipmiData
got := tt.input.AuthCode(AuthTypeMD5)
expected := tt.expect
if !isByteSliceEqual(got, expected) {
t.Errorf("test %s failed, not equal, got: %v, expected: %v", tt.name, got, expected)
}
}
}
golang-github-bougou-go-ipmi-0.7.2/cmd/ 0000775 0000000 0000000 00000000000 14741105271 0017651 5 ustar 00root root 0000000 0000000 golang-github-bougou-go-ipmi-0.7.2/cmd/.gitignore 0000664 0000000 0000000 00000000012 14741105271 0021632 0 ustar 00root root 0000000 0000000 testtools
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/ 0000775 0000000 0000000 00000000000 14741105271 0021135 5 ustar 00root root 0000000 0000000 golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/.gitignore 0000664 0000000 0000000 00000000007 14741105271 0023122 0 ustar 00root root 0000000 0000000 goipmi
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/README.md 0000664 0000000 0000000 00000000444 14741105271 0022416 0 ustar 00root root 0000000 0000000 # goipmi
The `goipmi` is a binary tool which provides the same command usages like `ipmitool`.
The `goipmi` calls `go-ipmi` library underlying.
The purpose of creating `goipmi` tool was not intended to substitute `ipmitool`.
It was just used to verify the correctness of `go-ipmi` library.
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/ 0000775 0000000 0000000 00000000000 14741105271 0022736 5 ustar 00root root 0000000 0000000 golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/channel.go 0000664 0000000 0000000 00000005363 14741105271 0024704 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
func NewCmdChannel() *cobra.Command {
cmd := &cobra.Command{
Use: "channel",
Short: "channel",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdChannelInfo())
cmd.AddCommand(NewCmdChannelGetCiphers())
return cmd
}
func NewCmdChannelInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "info",
Short: "info",
Run: func(cmd *cobra.Command, args []string) {
var channelNumber uint8
if len(args) == 0 {
channelNumber = ipmi.ChannelNumberSelf
}
if len(args) >= 1 {
i, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid channel number, err: %w", err))
}
channelNumber = uint8(i)
}
ctx := context.Background()
res, err := client.GetChannelInfo(ctx, channelNumber)
if err != nil {
CheckErr(fmt.Errorf("GetChannelInfo failed, err: %w", err))
}
fmt.Println(res.Format())
if res.SessionSupport == 0 {
return
}
res2, err := client.GetChannelAccess(ctx, channelNumber, ipmi.ChannelAccessOption_Volatile)
if err != nil {
CheckErr(fmt.Errorf("GetChannelAccess failed, err: %w", err))
}
fmt.Println(" Volatile(active) Settings")
fmt.Println(res2.Format())
res3, err := client.GetChannelAccess(ctx, channelNumber, ipmi.ChannelAccessOption_NonVolatile)
if err != nil {
CheckErr(fmt.Errorf("GetChannelAccess failed, err: %w", err))
}
fmt.Println(" Non-Volatile Settings")
fmt.Println(res3.Format())
},
}
return cmd
}
func NewCmdChannelGetCiphers() *cobra.Command {
cmd := &cobra.Command{
Use: "getciphers",
Short: "getciphers",
Run: func(cmd *cobra.Command, args []string) {
var channelNumber uint8
if len(args) == 0 {
channelNumber = ipmi.ChannelNumberSelf
}
if len(args) >= 1 {
i, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid channel number, err: %w", err))
}
channelNumber = uint8(i)
}
ctx := context.Background()
cipherSuiteRecords, err := client.GetAllChannelCipherSuites(ctx, channelNumber)
if err != nil {
CheckErr(fmt.Errorf("GetChannelInfo failed, err: %w", err))
}
fmt.Println("ID IANA Auth Alg Integrity Alg Confidentiality Alg")
for _, record := range cipherSuiteRecords {
fmt.Printf("%-5d%-8d%-16s%-16s%-s\n", record.CipherSuitID, record.OEMIanaID, ipmi.AuthAlg(record.AuthAlg), ipmi.IntegrityAlg(record.IntegrityAlgs[0]), ipmi.CryptAlg(record.CryptAlgs[0]))
}
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/chassis.go 0000664 0000000 0000000 00000026014 14741105271 0024725 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"errors"
"fmt"
"strings"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
const (
bootParamGetUsage = `
bootparam get
available param #
0 : Set In Progress (volatile)
1 : service partition selector (semi-volatile)
2 : service partition scan (non-volatile)
3 : BMC boot flag valid bit clearing (semi-volatile)
4 : boot info acknowledge (semi-volatile)
5 : boot flags (semi-volatile)
6 : boot initiator info (semi-volatile)
7 : boot initiator mailbox (semi-volatile)`
bootParamSetUsage = `
bootparam set bootflag [options=...]
Legal devices are:
none : No override
force_pxe : Force PXE boot
force_disk : Force boot from default Hard-drive
force_safe : Force boot from default Hard-drive, request Safe Mode
force_diag : Force boot from Diagnostic Partition
force_cdrom : Force boot from CD/DVD
force_bios : Force boot into BIOS Setup
Legal options are:
help : print this message
PEF : Clear valid bit on reset/power cycle cause by PEF
timeout : Automatically clear boot flag valid bit on timeout
watchdog: Clear valid bit on reset/power cycle cause by watchdog
reset : Clear valid bit on push button reset/soft reset
power : Clear valid bit on power up via power push button or wake event
Any Option may be prepended with no- to invert sense of operation`
)
func NewCmdChassis() *cobra.Command {
cmd := &cobra.Command{
Use: "chassis",
Short: "chassis",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdChassisStatus())
cmd.AddCommand(NewCmdChassisPolicy())
cmd.AddCommand(NewCmdChassisPower())
cmd.AddCommand(NewCmdChassisCapabilities())
cmd.AddCommand(NewCmdChassisRestartCause())
cmd.AddCommand(NewCmdChassisBootParam())
cmd.AddCommand(NewCmdChassisBootdev())
cmd.AddCommand(NewCmdChassisPoh())
return cmd
}
func NewCmdChassisStatus() *cobra.Command {
cmd := &cobra.Command{
Use: "status",
Short: "status",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
status, err := client.GetChassisStatus(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetChassisStatus failed, err: %w", err))
}
fmt.Println(status.Format())
},
}
return cmd
}
func NewCmdChassisPolicy() *cobra.Command {
usage := `chassis policy
list : return supported policies
always-on : turn on when power is restored
previous : return to previous state when power is restored
always-off : stay off after power is restored`
cmd := &cobra.Command{
Use: "policy",
Short: "policy",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
fmt.Println(usage)
return
}
ctx := context.Background()
if len(args) >= 1 {
switch args[0] {
case "list":
fmt.Printf("Supported chassis power policy: %s\n", strings.Join(ipmi.SupportedPowerRestorePolicies, " "))
return
case "always-on":
_, err := client.SetPowerRestorePolicy(ctx, ipmi.PowerRestorePolicyAlwaysOn)
if err != nil {
CheckErr(fmt.Errorf("SetPowerRestorePolicy failed, err: %w", err))
}
case "previous":
_, err := client.SetPowerRestorePolicy(ctx, ipmi.PowerRestorePolicyPrevious)
if err != nil {
CheckErr(fmt.Errorf("SetPowerRestorePolicy failed, err: %w", err))
}
case "always-off":
_, err := client.SetPowerRestorePolicy(ctx, ipmi.PowerRestorePolicyAlwaysOff)
if err != nil {
CheckErr(fmt.Errorf("SetPowerRestorePolicy failed, err: %w", err))
}
default:
fmt.Println(usage)
}
}
},
}
return cmd
}
func NewCmdChassisPower() *cobra.Command {
usage := "chassis power Commands: status, on, off, cycle, reset, diag, soft"
cmd := &cobra.Command{
Use: "power",
Short: "power",
Run: func(cmd *cobra.Command, args []string) {
var c ipmi.ChassisControl
if len(args) == 0 {
fmt.Println(usage)
return
}
ctx := context.Background()
if len(args) >= 1 {
switch args[0] {
case "status":
status, err := client.GetChassisStatus(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetChassisStatus failed, err: %w", err))
}
powerStatus := "off"
if status.PowerIsOn {
powerStatus = "on"
}
fmt.Printf("Chassis Power is %s\n", powerStatus)
return
case "on":
c = ipmi.ChassisControlPowerUp
case "off":
c = ipmi.ChassisControlPowerDown
case "cycle":
c = ipmi.ChassisControlPowerCycle
case "reset":
c = ipmi.ChassisControlHardReset
case "diag":
c = ipmi.ChassisControlDiagnosticInterrupt
case "soft":
c = ipmi.ChassisControlSoftShutdown
default:
CheckErr(errors.New(usage))
return
}
if _, err := client.ChassisControl(ctx, c); err != nil {
CheckErr(fmt.Errorf("ChassisControl failed, err: %w", err))
return
}
}
},
}
return cmd
}
func NewCmdChassisCapabilities() *cobra.Command {
usage := "chassis cap Commands: get or set"
cmd := &cobra.Command{
Use: "cap",
Short: "cap",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
fmt.Println(usage)
return
}
ctx := context.Background()
if len(args) >= 1 {
switch args[0] {
case "get":
cap, err := client.GetChassisCapabilities(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetChassisCapabilities failed, err: %w", err))
return
}
fmt.Println(cap.Format())
return
case "set":
}
}
},
}
return cmd
}
func NewCmdChassisRestartCause() *cobra.Command {
cmd := &cobra.Command{
Use: "restart_cause",
Short: "restart_cause",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
res, err := client.GetSystemRestartCause(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetSystemRestartCause failed, err: %w", err))
}
fmt.Println(res.Format())
},
}
return cmd
}
func NewCmdChassisBootParam() *cobra.Command {
cmd := &cobra.Command{
Use: "bootparam",
Short: "bootparam",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
fmt.Println(bootParamGetUsage)
fmt.Println(bootParamSetUsage)
return
}
},
}
cmd.AddCommand(NewCmdChassisBootParamGet())
cmd.AddCommand(NewCmdChassisBootParamSet())
return cmd
}
func NewCmdChassisBootParamGet() *cobra.Command {
cmd := &cobra.Command{
Use: "get",
Short: "get",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Println(bootParamGetUsage)
return
}
ctx := context.Background()
paramSelector := args[0]
i, err := parseStringToInt64(paramSelector)
if err != nil {
CheckErr(fmt.Errorf("param %s must be a valid integer in range (0-127), err: %s", paramSelector, err))
}
res, err := client.GetSystemBootOptionsParam(ctx, ipmi.BootOptionParamSelector(i), 0x00, 0x00)
if err != nil {
CheckErr(fmt.Errorf("GetSystemBootOptionsParam failed, err: %w", err))
}
fmt.Println(res.Format())
},
}
return cmd
}
func NewCmdChassisBootParamSet() *cobra.Command {
cmd := &cobra.Command{
Use: "set",
Short: "set",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 3 {
fmt.Println(bootParamSetUsage)
return
}
paramSelector := args[0]
// currently only support set bootflag
if paramSelector != "bootflag" {
fmt.Println(bootParamSetUsage)
return
}
var f = func(bootDevice string) ipmi.BootDeviceSelector {
m := map[string]ipmi.BootDeviceSelector{
"none": ipmi.BootDeviceSelectorNoOverride,
"force_pxe": ipmi.BootDeviceSelectorForcePXE,
"force_disk": ipmi.BootDeviceSelectorForceHardDrive,
"force_safe": ipmi.BootDeviceSelectorForceHardDriveSafe,
"force_diag": ipmi.BootDeviceSelectorForceDiagnosticPartition,
"force_cdrom": ipmi.BootDeviceSelectorForceCDROM,
"force_bios": ipmi.BootDeviceSelectorForceBIOSSetup,
}
if s, ok := m[bootDevice]; ok {
return s
}
return ipmi.BootDeviceSelectorNoOverride
}
bootDeviceSelector := f(args[1])
param := &ipmi.BootOptionParam_BootFlags{
BootFlagsValid: true,
Persist: false,
BIOSBootType: ipmi.BIOSBootTypeLegacy,
BootDeviceSelector: bootDeviceSelector,
}
ctx := context.Background()
if err := client.SetSystemBootOptionsParamFor(ctx, param); err != nil {
CheckErr(fmt.Errorf("SetSystemBootOptionsFor failed, err: %w", err))
}
fmt.Println("Set Succeeded.")
},
}
return cmd
}
func NewCmdChassisPoh() *cobra.Command {
cmd := &cobra.Command{
Use: "poh",
Short: "poh",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
res, err := client.GetPOHCounter(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetSystemRestartCause failed, err: %w", err))
}
fmt.Println(res.Format())
},
}
return cmd
}
func NewCmdChassisBootdev() *cobra.Command {
usage := `bootdev [clear-cmos=yes|no]
bootdev [options=help,...]
none : Do not change boot device order
pxe : Force PXE boot
disk : Force boot from default Hard-drive
safe : Force boot from default Hard-drive, request Safe Mode
diag : Force boot from Diagnostic Partition
cdrom : Force boot from CD/DVD
bios : Force boot into BIOS Setup
floppy: Force boot from Floppy/primary removable media`
cmd := &cobra.Command{
Use: "bootdev",
Short: "bootdev",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Println(usage)
return
}
var dev ipmi.BootDeviceSelector
switch args[0] {
case "none":
dev = ipmi.BootDeviceSelectorNoOverride
case "pxe":
dev = ipmi.BootDeviceSelectorForcePXE
case "disk":
dev = ipmi.BootDeviceSelectorForceHardDrive
case "safe":
dev = ipmi.BootDeviceSelectorForceHardDriveSafe
case "diag":
dev = ipmi.BootDeviceSelectorForceDiagnosticPartition
case "cdrom":
dev = ipmi.BootDeviceSelectorForceCDROM
case "floppy":
dev = ipmi.BootDeviceSelectorForceFloppy
case "bios":
dev = ipmi.BootDeviceSelectorForceBIOSSetup
default:
return
}
bootFlags := &ipmi.BootOptionParam_BootFlags{
BootDeviceSelector: dev,
}
if len(args) > 1 {
var optionsStr string
if args[1] == "clear-cmos=yes" {
optionsStr = "clear-cmos"
} else if strings.HasPrefix(args[1], "options=") {
optionsStr = strings.TrimPrefix(args[1], "options=")
}
options := strings.Split(optionsStr, ",")
for _, option := range options {
if option == "help" {
fmt.Println(bootFlags.OptionsHelp())
return
}
}
if err := bootFlags.ParseFromOptions(options); err != nil {
CheckErr(fmt.Errorf("ParseFromOptions failed, err: %w", err))
return
}
}
ctx := context.Background()
if err := client.SetBootParamBootFlags(ctx, bootFlags); err != nil {
CheckErr(fmt.Errorf("SetBootParamBootFlags failed, err: %w", err))
}
fmt.Printf("Set Boot Device to %s\n", args[0])
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/dcmi.go 0000664 0000000 0000000 00000035023 14741105271 0024204 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
func NewCmdDCMI() *cobra.Command {
cmd := &cobra.Command{
Use: "dcmi",
Short: "dcmi",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
return
}
subcmd := args[0]
if !contains([]string{
"power",
"asset_tag",
"set_asset_tag",
"discover",
"get_conf_param",
"get_mc_id_string",
"set_mc_id_string",
"thermalpolicy",
}, subcmd) {
fmt.Printf("unknown dcmi subcommand (%s)\n", subcmd)
cmd.Help()
return
}
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdDCMIPower())
cmd.AddCommand(NewCmdDCMIAssetTag())
cmd.AddCommand(NewCmdDCMISetAssetTag())
cmd.AddCommand(NewCmdDCMIDiscover())
cmd.AddCommand(NewCmdDCMIGetConfigParam())
cmd.AddCommand(NewCmdDCMISensors())
cmd.AddCommand(NewCmdDCMIGetMCIDString())
cmd.AddCommand(NewCmdDCMISetMCIDString())
cmd.AddCommand(NewCmdDCMIThermalPolicy())
cmd.AddCommand(NewCmdDCMIGetTempReading())
return cmd
}
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
func NewCmdDCMIDiscover() *cobra.Command {
cmd := &cobra.Command{
Use: "discover",
Short: "discover",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
dcmiCapParams, err := client.GetDCMICapParams(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetDCMICapParams failed, err: %w", err))
}
fmt.Println(dcmiCapParams.Format())
},
}
return cmd
}
func NewCmdDCMIGetConfigParam() *cobra.Command {
cmd := &cobra.Command{
Use: "get_conf_param",
Short: "get_conf_param",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
dcmiConfigParams, err := client.GetDCMIConfigParams(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetDCMIConfigParams failed, err: %w", err))
}
fmt.Println(dcmiConfigParams.Format())
},
}
return cmd
}
func NewCmdDCMIPower() *cobra.Command {
cmd := &cobra.Command{
Use: "power",
Short: "power",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
}
},
}
cmd.AddCommand(newCmdDCMIPowerRead())
cmd.AddCommand(newCmdDCMIPowerGetLimit())
cmd.AddCommand(newCmdDCMIPowerSetLimit())
cmd.AddCommand(newCmdDCMIPowerActivate())
cmd.AddCommand(newCmdDCMIPowerDeactivate())
return cmd
}
func newCmdDCMIPowerRead() *cobra.Command {
cmd := &cobra.Command{
Use: "reading",
Short: "reading",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
resp, err := client.GetDCMIPowerReading(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetDCMIPowerReading failed, err: %w", err))
}
fmt.Println(resp.Format())
},
}
return cmd
}
func newCmdDCMIPowerGetLimit() *cobra.Command {
cmd := &cobra.Command{
Use: "get_limit",
Short: "get_limit",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
resp, err := client.GetDCMIPowerLimit(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetDCMIPowerLimit failed, err: %w", err))
}
fmt.Println(resp.Format())
},
}
return cmd
}
func newCmdDCMIPowerSetLimit() *cobra.Command {
cmd := &cobra.Command{
Use: `set_limit
set_limit
action
limit
correction
sample
`,
Short: "set_limit",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
cmd.Help()
return
}
param := args[0]
value := args[1]
if !contains([]string{"action", "limit", "correction", "sample"}, param) {
cmd.Help()
return
}
ctx := context.Background()
req := &ipmi.SetDCMIPowerLimitRequest{}
{
resp, err := client.GetDCMIPowerLimit(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetDCMIPowerLimit failed, err: %w", err))
}
req.ExceptionAction = resp.ExceptionAction
req.PowerLimitRequested = resp.PowerLimitRequested
req.CorrectionTimeLimitMilliSec = resp.CorrectionTimeLimitMilliSec
req.StatisticsSamplingPeriodSec = resp.StatisticsSamplingPeriodSec
}
switch param {
case "action":
if value == "no_action" {
req.ExceptionAction = ipmi.DCMIExceptionAction_NoAction
} else if value == "sel_logging" {
req.ExceptionAction = ipmi.DCMIExceptionAction_LogSEL
} else if value == "power_off" {
req.ExceptionAction = ipmi.DCMIExceptionAction_PowerOffAndLogSEL
} else {
CheckErr(fmt.Errorf("invalid value for parameter action: %s", value))
}
case "limit":
limit, err := parseStringToInt64(value)
if err != nil {
CheckErr(fmt.Errorf("invalid value for parameter limit: %s", value))
}
req.PowerLimitRequested = uint16(limit)
case "correction":
correction, err := parseStringToInt64(value)
if err != nil {
CheckErr(fmt.Errorf("invalid value for parameter correction: %s", value))
}
req.CorrectionTimeLimitMilliSec = uint32(correction)
case "sample":
sample, err := parseStringToInt64(value)
if err != nil {
CheckErr(fmt.Errorf("invalid value for parameter sample: %s", value))
}
req.StatisticsSamplingPeriodSec = uint16(sample)
default:
CheckErr(fmt.Errorf("invalid parameter: %s", param))
}
_, err := client.SetDCMIPowerLimit(ctx, req)
if err != nil {
CheckErr(fmt.Errorf("SetDCMIPowerLimit failed, err: %w", err))
}
resp, err := client.GetDCMIPowerLimit(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetDCMIPowerLimit failed, err: %w", err))
}
fmt.Println(resp.Format())
},
}
return cmd
}
func newCmdDCMIPowerActivate() *cobra.Command {
cmd := &cobra.Command{
Use: "activate",
Short: "activate",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
_, err := client.ActivateDCMIPowerLimit(ctx, true)
if err != nil {
CheckErr(fmt.Errorf("ActivateDCMIPowerLimit (activate) failed, err: %w", err))
}
fmt.Println("Power limit successfully activated")
},
}
return cmd
}
func newCmdDCMIPowerDeactivate() *cobra.Command {
cmd := &cobra.Command{
Use: "deactivate",
Short: "deactivate",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
_, err := client.ActivateDCMIPowerLimit(ctx, false)
if err != nil {
CheckErr(fmt.Errorf("ActivateDCMIPowerLimit (deactivate) failed, err: %w", err))
}
fmt.Println("Power limit successfully deactivated")
},
}
return cmd
}
func NewCmdDCMIAssetTag() *cobra.Command {
cmd := &cobra.Command{
Use: "asset_tag",
Short: "asset_tag",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
assetTagRaw, typeLength, err := client.GetDCMIAssetTagFull(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetDCMIAssetTagFull failed, err: %w", err))
}
assetTag, err := typeLength.Chars(assetTagRaw)
if err != nil {
CheckErr(fmt.Errorf("convert raw to chars failed, err: %w", err))
}
fmt.Printf("Asset tag: %s\nTypeLength: %s\n", assetTag, typeLength)
},
}
return cmd
}
func NewCmdDCMISetAssetTag() *cobra.Command {
cmd := &cobra.Command{
Use: "set_asset_tag [asset_tag]",
Short: "set_asset_tag",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
return
}
var assetTag = []byte(args[0])
ctx := context.Background()
if err := client.SetDCMIAssetTagFull(ctx, assetTag); err != nil {
CheckErr(fmt.Errorf("SetDCMIAssetTagFull failed, err: %w", err))
}
},
}
return cmd
}
func NewCmdDCMISensors() *cobra.Command {
cmd := &cobra.Command{
Use: "sensors",
Short: "sensors",
Run: func(cmd *cobra.Command, args []string) {
const EntityID_DCMI_Inlet ipmi.EntityID = 0x40
const EntityID_DCMI_CPU ipmi.EntityID = 0x41
const EntityID_DCMI_Baseboard ipmi.EntityID = 0x42
ctx := context.Background()
{
sdrs, err := client.GetDCMISensors(ctx, EntityID_DCMI_Inlet)
if err != nil {
CheckErr(fmt.Errorf("GetDCMISensors for entityID (%#02x) failed, err: %s", EntityID_DCMI_Inlet, err))
}
fmt.Printf("Inlet: %d temperature sensors found\n", len(sdrs))
if len(sdrs) > 0 {
fmt.Println(ipmi.FormatSDRs(sdrs))
}
}
{
sdrs, err := client.GetDCMISensors(ctx, EntityID_DCMI_CPU)
if err != nil {
CheckErr(fmt.Errorf("GetDCMISensors for entityID (%#02x) failed, err: %s", EntityID_DCMI_Inlet, err))
}
fmt.Printf("CPU: %d temperature sensors found\n", len(sdrs))
if len(sdrs) > 0 {
fmt.Println(ipmi.FormatSDRs(sdrs))
}
}
{
sdrs, err := client.GetDCMISensors(ctx, EntityID_DCMI_Baseboard)
if err != nil {
CheckErr(fmt.Errorf("GetDCMISensors for entityID (%#02x) failed, err: %s", EntityID_DCMI_Inlet, err))
}
fmt.Printf("Baseboard: %d temperature sensors found\n", len(sdrs))
if len(sdrs) > 0 {
fmt.Println(ipmi.FormatSDRs(sdrs))
}
}
},
}
return cmd
}
func NewCmdDCMIGetMCIDString() *cobra.Command {
cmd := &cobra.Command{
Use: "get_mc_id_string",
Short: "get_mc_id_string",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
id, err := client.GetDCMIMgmtControllerIdentifierFull(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetDCMIMgmtControllerIdentifierFull failed, err: %w", err))
}
fmt.Printf("Management Controller Identifier String: %s\n", id)
},
}
return cmd
}
func NewCmdDCMISetMCIDString() *cobra.Command {
cmd := &cobra.Command{
Use: "set_mc_id_string [id_str]",
Short: "set_mc_id_string",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
return
}
var idStr = []byte(args[0])
ctx := context.Background()
if err := client.SetDCMIMgmtControllerIdentifierFull(ctx, idStr); err != nil {
CheckErr(fmt.Errorf("SetDCMIMgmtControllerIdentifierFull failed, err: %w", err))
}
},
}
return cmd
}
func NewCmdDCMIThermalPolicy() *cobra.Command {
cmd := &cobra.Command{
Use: "thermalpolicy",
Short: "thermalpolicy",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
}
},
}
cmd.AddCommand(newCmdDCMIThermalPolicyGet())
cmd.AddCommand(newCmdDCMIThermalPolicySet())
return cmd
}
func newCmdDCMIThermalPolicyGet() *cobra.Command {
cmd := &cobra.Command{
Use: "get ",
Short: "get",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
cmd.Help()
return
}
entityID, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("parse entityID (%s) failed, err: %s", args[0], err))
}
entityInstance, err := parseStringToInt64(args[1])
if err != nil {
CheckErr(fmt.Errorf("parse entityInstance (%s) failed, err: %s", args[1], err))
}
ctx := context.Background()
resp, err := client.GetDCMIThermalLimit(ctx, ipmi.EntityID(entityID), ipmi.EntityInstance(entityInstance))
if err != nil {
CheckErr(fmt.Errorf("GetDCMIThermalLimit failed, err: %w", err))
}
fmt.Println(resp.Format())
},
}
return cmd
}
func newCmdDCMIThermalPolicySet() *cobra.Command {
cmd := &cobra.Command{
Use: `set
thermalpolicy instance parameters:
valid volatile parameters:
valid poweroff parameters:
valid sel parameters:
volatile Current Power Cycle
nonvolatile Set across power cycles
poweroff Hard Power Off system
nopoweroff No 'Hard Power Off' action
sel Log event to SEL
nosel No 'Log event to SEL' action
disabled Disabled`,
Short: "set",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 7 {
cmd.Help()
return
}
entityID, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("parse entityID (%s) failed, err: %s", args[0], err))
}
entityInstance, err := parseStringToInt64(args[1])
if err != nil {
CheckErr(fmt.Errorf("parse entityInstance (%s) failed, err: %s", args[1], err))
}
var powerOff bool
powerParam := args[3]
switch powerParam {
case "poweroff":
powerOff = true
case "nopoweroff", "disabled":
powerOff = false
case "default":
CheckErr(fmt.Errorf("invalid poweroff parameter: %s", powerParam))
}
var sel bool
selParam := args[4]
switch selParam {
case "sel":
sel = true
case "nosel", "disabled":
sel = false
case "default":
CheckErr(fmt.Errorf("invalid sel parameter: %s", selParam))
}
temperatureLimit, err := parseStringToInt64(args[5])
if err != nil {
CheckErr(fmt.Errorf("parse temperatureLimit (%s) failed, err: %s", args[5], err))
}
exceptionTime, err := parseStringToInt64(args[6])
if err != nil {
CheckErr(fmt.Errorf("parse exceptionTime (%s) failed, err: %s", args[6], err))
}
req := &ipmi.SetDCMIThermalLimitRequest{
EntityID: ipmi.EntityID(entityID),
EntityInstance: ipmi.EntityInstance(entityInstance),
ExceptionAction_PowerOffAndLogSEL: powerOff,
ExceptionAction_LogSELOnly: sel,
TemperatureLimit: uint8(temperatureLimit),
ExceptionTimeSec: uint16(exceptionTime),
}
ctx := context.Background()
if _, err := client.SetDCMIThermalLimit(ctx, req); err != nil {
CheckErr(fmt.Errorf("SetDCMIThermalLimit failed, err: %w", err))
}
fmt.Println("SetDCMIThermalLimit succeeded:")
},
}
return cmd
}
func NewCmdDCMIGetTempReading() *cobra.Command {
cmd := &cobra.Command{
Use: "get_temp_reading",
Short: "get_temp_reading",
Run: func(cmd *cobra.Command, args []string) {
const EntityID_DCMI_Inlet ipmi.EntityID = 0x40
const EntityID_DCMI_CPU ipmi.EntityID = 0x41
const EntityID_DCMI_Baseboard ipmi.EntityID = 0x42
ctx := context.Background()
readings, err := client.GetDCMITemperatureReadingsForEntities(ctx, EntityID_DCMI_Inlet, EntityID_DCMI_CPU, EntityID_DCMI_Baseboard)
if err != nil {
CheckErr(fmt.Errorf("GetDCMISensors for entityID (%#02x) failed, err: %s", EntityID_DCMI_Inlet, err))
}
fmt.Printf("Got: %d temperature readings found\n", len(readings))
fmt.Println(ipmi.FormatDCMITemperatureReadings(readings))
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/fru.go 0000664 0000000 0000000 00000002307 14741105271 0024063 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"github.com/spf13/cobra"
)
func NewCmdFRU() *cobra.Command {
cmd := &cobra.Command{
Use: "fru",
Short: "fru",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdFRUPrint())
return cmd
}
func NewCmdFRUPrint() *cobra.Command {
cmd := &cobra.Command{
Use: "print",
Short: "print",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
if len(args) < 1 {
frus, err := client.GetFRUs(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetFRUs failed, err: %w", err))
}
for _, fru := range frus {
fmt.Println(fru.String())
}
} else {
id, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid FRU Device ID passed, err: %w", err))
}
fruID := uint8(id)
fru, err := client.GetFRU(ctx, fruID, "")
if err != nil {
CheckErr(fmt.Errorf("GetFRU failed, err: %w", err))
}
fmt.Println(fru.String())
}
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/helper.go 0000664 0000000 0000000 00000002720 14741105271 0024545 0 ustar 00root root 0000000 0000000 package commands
import (
"bytes"
"fmt"
"os"
"strings"
"github.com/olekukonko/tablewriter"
)
const (
DefaultErrorExitCode = 1
)
// ErrExit may be passed to CheckErr to instruct it to output nothing but exit with status code 1.
var ErrExit = fmt.Errorf("exit")
func CheckErr(err error) {
checkErr(err, fatalErrHandler)
}
// checkErr formats a given error as a string and calls the passed handleErr
// func with that string and an exit code.
func checkErr(err error, handleErr func(string, int)) {
if err == nil {
return
}
switch {
case err == ErrExit:
handleErr("", DefaultErrorExitCode)
default:
switch err := err.(type) {
// other err type, can return different code
default:
msg := err.Error()
if !strings.HasPrefix(msg, "error: ") {
msg = fmt.Sprintf("error: %s", msg)
}
handleErr(msg, DefaultErrorExitCode)
}
}
}
var fatalErrHandler = fatal
// fatal prints the message (if provided) and then exits.
func fatal(msg string, code int) {
if len(msg) > 0 {
// add newline if needed
if !strings.HasSuffix(msg, "\n") {
msg += "\n"
}
fmt.Fprint(os.Stderr, msg)
}
os.Exit(code)
}
func formatTable(headers []string, rows [][]string) string {
var buf = new(bytes.Buffer)
table := tablewriter.NewWriter(buf)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_RIGHT)
table.SetHeader(headers)
table.SetFooter(headers)
for _, row := range rows {
table.Append(row)
}
table.Render()
return buf.String()
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/lan.go 0000664 0000000 0000000 00000004310 14741105271 0024035 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"github.com/spf13/cobra"
)
func NewCmdLan() *cobra.Command {
cmd := &cobra.Command{
Use: "lan",
Short: "lan",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdLanStats())
cmd.AddCommand(NewCmdLanPrint())
return cmd
}
func NewCmdLanStats() *cobra.Command {
usage := `
stats get []
stats clear []
`
cmd := &cobra.Command{
Use: "stats",
Short: "stats",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
action := args[0]
id, err := parseStringToInt64(args[1])
if err != nil {
CheckErr(fmt.Errorf("invalid channel number passed, err: %w", err))
}
channelNumber := uint8(id)
ctx := context.Background()
switch action {
case "get":
res, err := client.GetIPStatistics(ctx, channelNumber, false)
if err != nil {
CheckErr(fmt.Errorf("GetIPStatistics failed, err: %w", err))
}
fmt.Println(res.Format())
case "clear":
res, err := client.GetIPStatistics(ctx, channelNumber, true)
if err != nil {
CheckErr(fmt.Errorf("GetIPStatistics failed, err: %w", err))
}
fmt.Println(res.Format())
default:
CheckErr(fmt.Errorf("usage: %s", usage))
}
},
}
return cmd
}
func NewCmdLanPrint() *cobra.Command {
usage := `
print []
`
cmd := &cobra.Command{
Use: "print",
Short: "print",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
id, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid channel number passed, err: %w", err))
}
channelNumber := uint8(id)
ctx := context.Background()
lanConfig, err := client.GetLanConfigParams(ctx, channelNumber)
if err != nil {
CheckErr(fmt.Errorf("GetLanConfigParams failed, err: %w", err))
}
client.Debug("Lan Config", lanConfig)
fmt.Println(lanConfig.Format())
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/mc.go 0000664 0000000 0000000 00000006604 14741105271 0023672 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"github.com/spf13/cobra"
)
func NewCmdMC() *cobra.Command {
cmd := &cobra.Command{
Use: "mc",
Short: "mc",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdMCInfo())
cmd.AddCommand(NewCmdMCReset())
cmd.AddCommand(NewCmdMC_ACPI())
cmd.AddCommand(NewCmdMC_GUID())
cmd.AddCommand(NewCmdMC_Watchdog())
return cmd
}
func NewCmdMCInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "info",
Short: "info",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
res, err := client.GetDeviceID(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetDeviceID failed, err: %w", err))
}
fmt.Println(res.Format())
},
}
return cmd
}
func NewCmdMCReset() *cobra.Command {
usage := "reset "
cmd := &cobra.Command{
Use: "reset",
Short: "reset",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
ctx := context.Background()
switch args[0] {
case "warm":
if err := client.WarmReset(ctx); err != nil {
CheckErr(fmt.Errorf("WarmReset failed, err: %w", err))
}
case "cold":
if err := client.ColdReset(ctx); err != nil {
CheckErr(fmt.Errorf("ColdReset failed, err: %w", err))
}
default:
CheckErr(fmt.Errorf("usage: %s", usage))
}
},
}
return cmd
}
func NewCmdMC_ACPI() *cobra.Command {
usage := "acpi "
cmd := &cobra.Command{
Use: "acpi",
Short: "acpi",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
ctx := context.Background()
switch args[0] {
case "get":
res, err := client.GetACPIPowerState(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetACPIPowerState failed, err: %w", err))
}
fmt.Println(res.Format())
case "set":
//
default:
CheckErr(fmt.Errorf("usage: %s", usage))
}
},
}
return cmd
}
func NewCmdMC_GUID() *cobra.Command {
cmd := &cobra.Command{
Use: "guid",
Short: "guid",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
res, err := client.GetSystemGUID(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetSystemGUID failed, err: %w", err))
}
fmt.Println(res.Format())
},
}
return cmd
}
func NewCmdMC_Watchdog() *cobra.Command {
usage := `watchdog
get : Get Current Watchdog settings
reset : Restart Watchdog timer based on most recent settings
off : Shut off a running Watchdog timer
`
cmd := &cobra.Command{
Use: "watchdog",
Short: "watchdog",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
ctx := context.Background()
switch args[0] {
case "get":
res, err := client.GetWatchdogTimer(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetWatchdogTimer failed, err: %w", err))
}
fmt.Println(res.Format())
case "reset":
if _, err := client.ResetWatchdogTimer(ctx); err != nil {
CheckErr(fmt.Errorf("ResetWatchdogTimer failed, err: %w", err))
}
case "off":
//
default:
CheckErr(fmt.Errorf("usage: %s", usage))
}
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/pef.go 0000664 0000000 0000000 00000014717 14741105271 0024051 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"strconv"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
func NewCmdPEF() *cobra.Command {
cmd := &cobra.Command{
Use: "pef",
Short: "pef",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
cmd.Help()
return
}
if !contains([]string{
"capabilities",
"status",
"filter",
"info",
"policy",
}, args[1]) {
cmd.Help()
return
}
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdPEFCapabilities())
cmd.AddCommand(NewCmdPEFStatus())
cmd.AddCommand(NewCmdPEFFilter())
cmd.AddCommand(NewCmdPEFInfo())
cmd.AddCommand(NewCmdPEFPolicy())
return cmd
}
func NewCmdPEFCapabilities() *cobra.Command {
cmd := &cobra.Command{
Use: "capabilities",
Short: "capabilities",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
res, err := client.GetPEFCapabilities(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetPEFCapabilities failed, err: %w", err))
}
fmt.Println(res.Format())
},
}
return cmd
}
func NewCmdPEFStatus() *cobra.Command {
cmd := &cobra.Command{
Use: "status",
Short: "status",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
{
res, err := client.GetLastProcessedEventId(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetLastProcessedEventId failed, err: %w", err))
}
fmt.Println(res.Format())
}
{
param := &ipmi.PEFConfigParam_Control{}
if err := client.GetPEFConfigParamFor(ctx, param); err != nil {
CheckErr(fmt.Errorf("GetLastProcessedEventId failed, err: %w", err))
}
fmt.Println(param.Format())
}
{
param := &ipmi.PEFConfigParam_ActionGlobalControl{}
if err := client.GetPEFConfigParamFor(ctx, param); err != nil {
CheckErr(fmt.Errorf("GetLastProcessedEventId failed, err: %w", err))
}
fmt.Println(param.Format())
}
},
}
return cmd
}
func NewCmdPEFFilter() *cobra.Command {
cmd := &cobra.Command{
Use: "filter",
Short: "filter",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
cmd.Help()
}
},
}
cmd.AddCommand(NewCmdPEFFilterList())
return cmd
}
func NewCmdPEFFilterList() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "list",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
var numberOfEventFilters uint8
{
param := &ipmi.PEFConfigParam_EventFiltersCount{}
if err := client.GetPEFConfigParamFor(ctx, param); err != nil {
CheckErr(fmt.Errorf("get number of event filters failed, err: %w", err))
}
numberOfEventFilters = param.Value
}
var eventFilters = make([]*ipmi.PEFEventFilter, numberOfEventFilters)
for i := uint8(0); i < numberOfEventFilters; i++ {
// 1-based
filterNumber := i + 1
param := &ipmi.PEFConfigParam_EventFilter{
SetSelector: filterNumber,
}
if err := client.GetPEFConfigParamFor(ctx, param); err != nil {
CheckErr(fmt.Errorf("get event filter entry %d failed, err: %s", filterNumber, err))
}
eventFilters[i] = param.Filter
}
fmt.Println(ipmi.FormatEventFilters(eventFilters))
},
}
return cmd
}
func NewCmdPEFInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "info",
Short: "info",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
{
param := &ipmi.PEFConfigParam_SystemGUID{}
if err := client.GetPEFConfigParamFor(ctx, param); err != nil {
CheckErr(err)
}
fmt.Println(param.Format())
if !param.UseGUID {
res, err := client.GetSystemGUID(ctx)
if err != nil {
CheckErr(err)
}
fmt.Println(ipmi.FormatGUIDDetails(res.GUID))
}
}
{
param := &ipmi.PEFConfigParam_AlertPoliciesCount{}
if err := client.GetPEFConfigParamFor(ctx, param); err != nil {
CheckErr(err)
}
fmt.Println(param.Format())
}
{
res, err := client.GetPEFCapabilities(ctx)
if err != nil {
CheckErr(err)
}
fmt.Println(res.Format())
}
},
}
return cmd
}
func NewCmdPEFPolicy() *cobra.Command {
cmd := &cobra.Command{
Use: "policy",
Short: "policy",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
cmd.Help()
}
},
}
cmd.AddCommand(NewCmdPEFPolicyList())
return cmd
}
func NewCmdPEFPolicyList() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "list",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
numberOfAlertPolicies := uint8(0)
{
param := &ipmi.PEFConfigParam_AlertPoliciesCount{}
if err := client.GetPEFConfigParamFor(ctx, param); err != nil {
CheckErr(err)
}
numberOfAlertPolicies = param.Value
}
{
headers := []string{
"Entry",
"PolicyNumber",
"PolicyState",
"PolicyAction",
"Channel",
"ChannelMedium",
"Destination",
"IsEventSpecific",
"AlertStringKey",
}
rows := make([][]string, numberOfAlertPolicies)
for i := uint8(0); i < numberOfAlertPolicies; i++ {
entry := i + 1
param := &ipmi.PEFConfigParam_AlertPolicy{
SetSelector: entry,
}
if err := client.GetPEFConfigParamFor(ctx, param); err != nil {
CheckErr(fmt.Errorf("get alert policy number (%d) failed, err: %s", entry, err))
}
alertPolicy := param.Policy
channelNumber := param.Policy.ChannelNumber
resp, err := client.GetChannelInfo(ctx, channelNumber)
if err != nil {
CheckErr(fmt.Errorf("get channel info (%d) failed, err: %s", channelNumber, err))
}
// Todo Get Lan Config Param
// if resp.ChannelMedium == ipmi.ChannelMediumLAN {
// Number of Destinations : 0x11 (17)
// Destination Type : 0x12 (18)
// Community String : 0x10 (16)
// Destination Address: 0x13 (19)
// }
row := []string{
strconv.Itoa(int(entry)),
fmt.Sprintf("%d", alertPolicy.PolicyNumber),
fmt.Sprintf("%v", alertPolicy.PolicyState),
alertPolicy.PolicyAction.ShortString(),
fmt.Sprintf("%d", alertPolicy.ChannelNumber),
resp.ChannelMedium.String(),
fmt.Sprintf("%d", alertPolicy.Destination),
fmt.Sprintf("%v", alertPolicy.IsEventSpecific),
fmt.Sprintf("%d", alertPolicy.AlertStringKey),
}
rows[i] = row
}
fmt.Println(formatTable(headers, rows))
}
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/root.go 0000664 0000000 0000000 00000007200 14741105271 0024247 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"flag"
"fmt"
"strings"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
const homePage = "https://github.com/bougou/go-ipmi"
var (
host string
port int
username string
password string
intf string
debug bool
privilegeLevel string
showVersion bool
client *ipmi.Client
)
func initClient() error {
if debug {
fmt.Printf("Version: %s\n", Version)
fmt.Printf("Commit: %s\n", Commit)
fmt.Printf("BuildAt: %s\n", BuildAt)
}
switch intf {
case "", "open":
c, err := ipmi.NewOpenClient()
if err != nil {
return fmt.Errorf("create open client failed, err: %w", err)
}
client = c
case "lan", "lanplus":
c, err := ipmi.NewClient(host, port, username, password)
if err != nil {
return fmt.Errorf("create lan or lanplus client failed, err: %w", err)
}
client = c
case "tool":
c, err := ipmi.NewToolClient(host)
if err != nil {
return fmt.Errorf("create client based on ipmitool (%s) failed, err: %s", host, err)
}
client = c
}
client.WithDebug(debug)
client.WithInterface(ipmi.Interface(intf))
var privLevel ipmi.PrivilegeLevel = ipmi.PrivilegeLevelUnspecified
switch strings.ToUpper(privilegeLevel) {
case "CALLBACK":
privLevel = ipmi.PrivilegeLevelCallback
case "USER":
privLevel = ipmi.PrivilegeLevelUser
case "OPERATOR":
privLevel = ipmi.PrivilegeLevelOperator
case "ADMINISTRATOR":
privLevel = ipmi.PrivilegeLevelAdministrator
}
if privLevel != ipmi.PrivilegeLevelUnspecified {
client.WithMaxPrivilegeLevel(privLevel)
}
ctx := context.Background()
if err := client.Connect(ctx); err != nil {
return fmt.Errorf("client connect failed, err: %w", err)
}
return nil
}
func closeClient() error {
ctx := context.Background()
if err := client.Close(ctx); err != nil {
return fmt.Errorf("close client failed, err: %w", err)
}
return nil
}
func NewRootCommand() *cobra.Command {
rootCmd := &cobra.Command{
Use: "goipmi",
Short: "goipmi",
Long: fmt.Sprintf("goipmi\n\nFind more information at: %s\n\n", homePage),
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if showVersion {
fmt.Printf("Version: %s\n", Version)
fmt.Printf("Commit: %s\n", Commit)
fmt.Printf("BuildAt: %s\n", BuildAt)
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
},
}
rootCmd.PersistentFlags().StringVarP(&host, "host", "H", "", "host")
rootCmd.PersistentFlags().IntVarP(&port, "port", "p", 623, "port")
rootCmd.PersistentFlags().StringVarP(&username, "user", "U", "", "username")
rootCmd.PersistentFlags().StringVarP(&password, "pass", "P", "", "password")
rootCmd.PersistentFlags().StringVarP(&intf, "interface", "I", "open", "interface, supported (open,lan,lanplus)")
rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "debug")
rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "V", false, "version")
rootCmd.PersistentFlags().StringVarP(&privilegeLevel, "priv-level", "L", "ADMINISTRATOR", "Force session privilege level. Can be CALLBACK, USER, OPERATOR, ADMINISTRATOR.")
rootCmd.Flags().AddGoFlagSet(flag.CommandLine)
rootCmd.AddCommand(NewCmdMC())
rootCmd.AddCommand(NewCmdSEL())
rootCmd.AddCommand(NewCmdSDR())
rootCmd.AddCommand(NewCmdChassis())
rootCmd.AddCommand(NewCmdChannel())
rootCmd.AddCommand(NewCmdLan())
rootCmd.AddCommand(NewCmdUser())
rootCmd.AddCommand(NewCmdSession())
rootCmd.AddCommand(NewCmdSensor())
rootCmd.AddCommand(NewCmdFRU())
rootCmd.AddCommand(NewCmdSOL())
rootCmd.AddCommand(NewCmdPEF())
rootCmd.AddCommand(NewCmdDCMI())
rootCmd.AddCommand(NewCmdX())
rootCmd.SilenceUsage = true
rootCmd.SilenceErrors = true
return rootCmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/sdr.go 0000664 0000000 0000000 00000014256 14741105271 0024065 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"strconv"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
func NewCmdSDR() *cobra.Command {
cmd := &cobra.Command{
Use: "sdr",
Short: "sdr",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("sdr ...")
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdSDRInfo())
cmd.AddCommand(NewCmdSDRGet())
cmd.AddCommand(NewCmdSDRList())
cmd.AddCommand(NewCmdSDRType())
return cmd
}
func NewCmdSDRInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "info",
Short: "info",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
sdrRepoInfo, err := client.GetSDRRepoInfo(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetSDRRepoInfo failed, err: %w", err))
}
fmt.Println(sdrRepoInfo.Format())
},
}
return cmd
}
func parseStringToInt64(s string) (int64, error) {
if len(s) > 2 {
if s[0] == '0' {
return strconv.ParseInt(s, 0, 64)
}
}
return strconv.ParseInt(s, 10, 64)
}
func NewCmdSDRGet() *cobra.Command {
usage := `sdr get or , sensorName should be quoted if contains space`
cmd := &cobra.Command{
Use: "get",
Short: "get",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(fmt.Errorf("no Sensor ID or Sensor Name supplied, usage: %s", usage))
}
ctx := context.Background()
var sdr *ipmi.SDR
var err error
id, err := parseStringToInt64(args[0])
if err != nil {
// suppose args is sensor name
sdr, err = client.GetSDRBySensorName(ctx, args[0])
if err != nil {
CheckErr(fmt.Errorf("GetSDRBySensorName failed, err: %w", err))
}
} else {
sensorID := uint8(id)
sdr, err = client.GetSDRBySensorID(ctx, sensorID)
if err != nil {
CheckErr(fmt.Errorf("GetSDRBySensorID failed, err: %w", err))
}
}
client.Debug("SDR", sdr)
fmt.Println(sdr)
},
}
return cmd
}
func NewCmdSDRType() *cobra.Command {
sensorTypesText := `
Sensor Types:
Temperature (0x01) Voltage (0x02)
Current (0x03) Fan (0x04)
Physical Security (0x05) Platform Security (0x06)
Processor (0x07) Power Supply (0x08)
Power Unit (0x09) Cooling Device (0x0a)
Other (0x0b) Memory (0x0c)
Drive Slot / Bay (0x0d) POST Memory Resize (0x0e)
System Firmwares (0x0f) Event Logging Disabled (0x10)
Watchdog1 (0x11) System Event (0x12)
Critical Interrupt (0x13) Button (0x14)
Module / Board (0x15) Microcontroller (0x16)
Add-in Card (0x17) Chassis (0x18)
Chip Set (0x19) Other FRU (0x1a)
Cable / Interconnect (0x1b) Terminator (0x1c)
System Boot Initiated (0x1d) Boot Error (0x1e)
OS Boot (0x1f) OS Critical Stop (0x20)
Slot / Connector (0x21) System ACPI Power State (0x22)
Watchdog2 (0x23) Platform Alert (0x24)
Entity Presence (0x25) Monitor ASIC (0x26)
LAN (0x27) Management Subsys Health (0x28)
Battery (0x29) Session Audit (0x2a)
Version Change (0x2b) FRU State (0x2c)
`
// usage := `sdr type [all||]`
cmd := &cobra.Command{
Use: "type",
Short: "type",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
fmt.Println(sensorTypesText)
return
}
if len(args) >= 1 {
ctx := context.Background()
if args[0] == "all" {
sensors, err := client.GetSensors(ctx)
if err != nil {
fmt.Printf("failed to get all sensors: %s", err)
return
}
fmt.Println(ipmi.FormatSensors(true, sensors...))
return
}
sensorType, err := ipmi.SensorTypeFromNameOrNumber(args[0])
if err != nil {
fmt.Printf("invalid sensor type: %s", args[0])
return
}
sensors, err := client.GetSensors(ctx, ipmi.SensorFilterOptionIsSensorType(sensorType))
if err != nil {
fmt.Printf("failed to get (%s) sensors: %s", sensorType, err)
return
}
fmt.Println(ipmi.FormatSensors(true, sensors...))
}
},
}
return cmd
}
func NewCmdSDRList() *cobra.Command {
usage := `sdr list `
cmd := &cobra.Command{
Use: "list",
Short: "list",
Run: func(cmd *cobra.Command, args []string) {
recordTypes := []ipmi.SDRRecordType{}
// default only get Full and Compact SDR
if len(args) == 0 {
recordTypes = append(recordTypes, ipmi.SDRRecordTypeFullSensor, ipmi.SDRRecordTypeCompactSensor)
}
ctx := context.Background()
if len(args) >= 1 {
switch args[0] {
case "all":
// no filter, recordTypes is empty.
case "full":
recordTypes = append(recordTypes, ipmi.SDRRecordTypeFullSensor)
case "compact":
recordTypes = append(recordTypes, ipmi.SDRRecordTypeCompactSensor)
case "event":
recordTypes = append(recordTypes, ipmi.SDRRecordTypeEventOnly)
case "mcloc":
recordTypes = append(recordTypes, ipmi.SDRRecordTypeManagementControllerDeviceLocator)
case "fru":
recordTypes = append(recordTypes, ipmi.SDRRecordTypeFRUDeviceLocator)
sdrs, err := client.GetSDRs(ctx, recordTypes...)
if err != nil {
CheckErr(fmt.Errorf("GetSDRs failed, err: %w", err))
}
fmt.Println(ipmi.FormatSDRs_FRU(sdrs))
return
case "generic":
recordTypes = append(recordTypes, ipmi.SDRRecordTypeGenericLocator)
default:
CheckErr(fmt.Errorf("unknown supported record type (%s), usage: %s", args[0], usage))
return
}
}
sdrs, err := client.GetSDRs(ctx, recordTypes...)
if err != nil {
CheckErr(fmt.Errorf("GetSDRs failed, err: %w", err))
}
fmt.Println(ipmi.FormatSDRs(sdrs))
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/sel.go 0000664 0000000 0000000 00000005364 14741105271 0024060 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"errors"
"fmt"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
func NewCmdSEL() *cobra.Command {
cmd := &cobra.Command{
Use: "sel",
Short: "sel",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdSELInfo())
cmd.AddCommand(NewCmdSELGet())
cmd.AddCommand(NewCmdSELList())
cmd.AddCommand(NewCmdSELElist())
return cmd
}
func NewCmdSELInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "info",
Short: "info",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
selInfo, err := client.GetSELInfo(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetSELInfo failed, err: %w", err))
}
fmt.Println(selInfo.Format())
selAllocInfo, err := client.GetSELAllocInfo(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetSELInfo failed, err: %w", err))
}
fmt.Println(selAllocInfo.Format())
},
}
return cmd
}
func NewCmdSELGet() *cobra.Command {
cmd := &cobra.Command{
Use: "get",
Short: "get",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(errors.New("no Record ID supplied"))
}
id, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid Record ID passed, err: %w", err))
}
recordID := uint16(id)
ctx := context.Background()
selEntryRes, err := client.GetSELEntry(ctx, 0x0, recordID)
if err != nil {
CheckErr(fmt.Errorf("GetSELEntry failed, err: %w", err))
}
sel, err := ipmi.ParseSEL(selEntryRes.Data)
if err != nil {
CheckErr(fmt.Errorf("ParseSEL failed, err: %w", err))
}
fmt.Println(ipmi.FormatSELs([]*ipmi.SEL{sel}, nil))
},
}
return cmd
}
func NewCmdSELList() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "list",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
selEntries, err := client.GetSELEntries(ctx, 0)
if err != nil {
CheckErr(fmt.Errorf("GetSELInfo failed, err: %w", err))
}
fmt.Println(ipmi.FormatSELs(selEntries, nil))
},
}
return cmd
}
func NewCmdSELElist() *cobra.Command {
cmd := &cobra.Command{
Use: "elist",
Short: "elist",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
sdrsMap, err := client.GetSDRsMap(ctx)
if err != nil {
CheckErr(fmt.Errorf("GetSDRsMap failed, err: %w", err))
}
selEntries, err := client.GetSELEntries(ctx, 0)
if err != nil {
CheckErr(fmt.Errorf("GetSELInfo failed, err: %w", err))
}
fmt.Println(ipmi.FormatSELs(selEntries, sdrsMap))
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/sensor.go 0000664 0000000 0000000 00000020400 14741105271 0024572 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
func NewCmdSensor() *cobra.Command {
cmd := &cobra.Command{
Use: "sensor",
Short: "sensor",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdSensorDeviceSDRInfo())
cmd.AddCommand(NewCmdSensorGet())
cmd.AddCommand(NewCmdSensorList())
cmd.AddCommand(NewCmdSensorThreshold())
cmd.AddCommand(NewCmdSensorEventEnable())
cmd.AddCommand(NewCmdSensorEventStatus())
cmd.AddCommand(NewCmdSensorReading())
cmd.AddCommand(NewCmdSensorReadingFactors())
cmd.AddCommand(NewCmdSensorDetail())
return cmd
}
func NewCmdSensorDeviceSDRInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "info",
Short: "info",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
res, err := client.GetDeviceSDRInfo(ctx, true)
if err != nil {
CheckErr(fmt.Errorf("GetDeviceSDRInfo failed, err: %w", err))
}
fmt.Println(res.Format())
},
}
return cmd
}
func NewCmdSensorList() *cobra.Command {
var extended bool
var filterThreshold bool
var filterReadingValid bool
cmd := &cobra.Command{
Use: "list",
Short: "list",
Run: func(cmd *cobra.Command, args []string) {
filterOptions := make([]ipmi.SensorFilterOption, 0)
if filterThreshold {
filterOptions = append(filterOptions, ipmi.SensorFilterOptionIsThreshold)
}
if filterReadingValid {
filterOptions = append(filterOptions, ipmi.SensorFilterOptionIsReadingValid)
}
ctx := context.Background()
sensors, err := client.GetSensors(ctx, filterOptions...)
if err != nil {
CheckErr(fmt.Errorf("GetSensors failed, err: %w", err))
}
fmt.Println(ipmi.FormatSensors(extended, sensors...))
},
}
cmd.PersistentFlags().BoolVarP(&extended, "extended", "", false, "extended print")
cmd.PersistentFlags().BoolVarP(&filterThreshold, "threshold", "", false, "filter threshold sensor class")
cmd.PersistentFlags().BoolVarP(&filterReadingValid, "valid", "", false, "filter sensor that has valid reading")
return cmd
}
func NewCmdSensorGet() *cobra.Command {
usage := `sensor get or , sensorName should be quoted if contains space`
cmd := &cobra.Command{
Use: "get",
Short: "get",
Run: func(cmd *cobra.Command, args []string) {
var sensorNumber uint8
if len(args) < 1 {
CheckErr(fmt.Errorf("no Sensor ID or Sensor Name supplied, usage: %s", usage))
}
ctx := context.Background()
var sensor *ipmi.Sensor
var err error
id, err := parseStringToInt64(args[0])
if err != nil {
// suppose args is sensor name
sensor, err = client.GetSensorByName(ctx, args[0])
if err != nil {
CheckErr(fmt.Errorf("GetSensorByName failed, err: %w", err))
}
} else {
sensorNumber = uint8(id)
sensor, err = client.GetSensorByID(ctx, sensorNumber)
if err != nil {
CheckErr(fmt.Errorf("GetSensorByID failed, err: %w", err))
}
}
client.Debug("sensor", sensor)
fmt.Println(sensor)
},
}
return cmd
}
func NewCmdSensorThreshold() *cobra.Command {
usage := `
sensor threshold get
`
cmd := &cobra.Command{
Use: "threshold",
Short: "threshold",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
action := args[0]
var sensorNumber uint8
i, err := parseStringToInt64(args[1])
if err != nil {
CheckErr(fmt.Errorf("invalid sensor number, err: %w", err))
}
sensorNumber = uint8(i)
ctx := context.Background()
switch action {
case "get":
res, err := client.GetSensorThresholds(ctx, sensorNumber)
if err != nil {
CheckErr(fmt.Errorf("GetSensorThresholds failed, err: %w", err))
}
fmt.Println(res.Format())
case "set":
default:
CheckErr(fmt.Errorf("usage: %s", usage))
}
},
}
return cmd
}
func NewCmdSensorEventStatus() *cobra.Command {
usage := `
sensor event-status get
`
cmd := &cobra.Command{
Use: "event-status ",
Short: "event-status ",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
action := args[0]
var sensorNumber uint8
i, err := parseStringToInt64(args[1])
if err != nil {
CheckErr(fmt.Errorf("invalid sensor number, err: %w", err))
}
sensorNumber = uint8(i)
ctx := context.Background()
switch action {
case "get":
res, err := client.GetSensorEventStatus(ctx, sensorNumber)
if err != nil {
CheckErr(fmt.Errorf("GetSensorEventStatus failed, err: %w", err))
}
fmt.Println(res.Format())
case "set":
default:
CheckErr(fmt.Errorf("usage: %s", usage))
}
},
}
return cmd
}
func NewCmdSensorEventEnable() *cobra.Command {
usage := `
sensor event-enable get
`
cmd := &cobra.Command{
Use: "event-enable ",
Short: "event-enable ",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
action := args[0]
var sensorNumber uint8
i, err := parseStringToInt64(args[1])
if err != nil {
CheckErr(fmt.Errorf("invalid sensor number, err: %w", err))
}
sensorNumber = uint8(i)
ctx := context.Background()
switch action {
case "get":
res, err := client.GetSensorEventEnable(ctx, sensorNumber)
if err != nil {
CheckErr(fmt.Errorf("GetSensorEventEnable failed, err: %w", err))
}
fmt.Println(res.Format())
case "set":
default:
CheckErr(fmt.Errorf("usage: %s", usage))
}
},
}
return cmd
}
func NewCmdSensorReading() *cobra.Command {
usage := `
sensor reading get
`
cmd := &cobra.Command{
Use: "reading",
Short: "reading",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
action := args[0]
var sensorNumber uint8
i, err := parseStringToInt64(args[1])
if err != nil {
CheckErr(fmt.Errorf("invalid sensor number, err: %w", err))
}
sensorNumber = uint8(i)
ctx := context.Background()
switch action {
case "get":
res, err := client.GetSensorReading(ctx, sensorNumber)
if err != nil {
CheckErr(fmt.Errorf("GetSensorReading failed, err: %w", err))
}
fmt.Println(res.Format())
case "set":
default:
CheckErr(fmt.Errorf("usage: %s", usage))
}
},
}
return cmd
}
func NewCmdSensorReadingFactors() *cobra.Command {
usage := `
sensor reading-factors get
`
cmd := &cobra.Command{
Use: "reading-factors",
Short: "reading-factors",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
action := args[0]
var sensorNumber uint8
i, err := parseStringToInt64(args[1])
if err != nil {
CheckErr(fmt.Errorf("invalid sensor number, err: %w", err))
}
sensorNumber = uint8(i)
ctx := context.Background()
switch action {
case "get":
res0, err := client.GetSensorReading(ctx, sensorNumber)
if err != nil {
CheckErr(fmt.Errorf("GetSensorReading failed, err: %w", err))
}
fmt.Println(res0.Format())
res, err := client.GetSensorReadingFactors(ctx, sensorNumber, res0.Reading)
if err != nil {
CheckErr(fmt.Errorf("GetSensorReadingFactors failed, err: %w", err))
}
fmt.Println(res.Format())
case "set":
default:
CheckErr(fmt.Errorf("usage: %s", usage))
}
},
}
return cmd
}
func NewCmdSensorDetail() *cobra.Command {
usage := `
sensor detail
`
cmd := &cobra.Command{
Use: "detail",
Short: "detail",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
var sensorNumber uint8
if len(args) >= 1 {
i, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid sensor number, err: %w", err))
}
sensorNumber = uint8(i)
}
ctx := context.Background()
sensor, err := client.GetSensorByID(ctx, sensorNumber)
if err != nil {
CheckErr(fmt.Errorf("GetSensorByID failed, err: %w", err))
}
fmt.Println(sensor)
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/session.go 0000664 0000000 0000000 00000002263 14741105271 0024753 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
func NewCmdSession() *cobra.Command {
cmd := &cobra.Command{
Use: "session",
Short: "session",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdSessionInfo())
return cmd
}
func NewCmdSessionInfo() *cobra.Command {
// cSpell: disable
usage := `Session Commands: info `
// cSpell: enable
cmd := &cobra.Command{
Use: "info",
Short: "info",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Println(usage)
return
}
ctx := context.Background()
switch args[0] {
case "active":
request := &ipmi.GetSessionInfoRequest{
SessionIndex: 0, // current active
}
res, err := client.GetSessionInfo(ctx, request)
if err != nil {
CheckErr(fmt.Errorf("GetSessionInfo failed, err: %w", err))
}
fmt.Println(res.Format())
}
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/sol.go 0000664 0000000 0000000 00000001527 14741105271 0024067 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"github.com/spf13/cobra"
)
func NewCmdSOL() *cobra.Command {
cmd := &cobra.Command{
Use: "sol",
Short: "sol",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdSOLInfo())
return cmd
}
func NewCmdSOLInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "info",
Short: "info",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
solConfigParams, err := client.GetSOLConfigParams(ctx, 0x0e)
if err != nil {
CheckErr(fmt.Errorf("GetDeviceID failed, err: %w", err))
}
fmt.Println(solConfigParams.Format())
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/user.go 0000664 0000000 0000000 00000003667 14741105271 0024257 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"github.com/bougou/go-ipmi"
"github.com/spf13/cobra"
)
func NewCmdUser() *cobra.Command {
cmd := &cobra.Command{
Use: "user",
Short: "user",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdUserList())
cmd.AddCommand(NewCmdUserSummary())
return cmd
}
func NewCmdUserList() *cobra.Command {
cmd := &cobra.Command{
Use: "list []",
Short: "list []",
Run: func(cmd *cobra.Command, args []string) {
var channelNumber uint8
if len(args) == 0 {
channelNumber = ipmi.ChannelNumberSelf
}
if len(args) > 1 {
id, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid channel number passed, err: %w", err))
}
channelNumber = uint8(id)
}
ctx := context.Background()
users, err := client.ListUser(ctx, channelNumber)
if err != nil {
CheckErr(fmt.Errorf("ListUser failed, err: %w", err))
}
fmt.Println(ipmi.FormatUsers(users))
},
}
return cmd
}
func NewCmdUserSummary() *cobra.Command {
cmd := &cobra.Command{
Use: "summary []",
Short: "summary []",
Run: func(cmd *cobra.Command, args []string) {
var channelNumber uint8
if len(args) == 0 {
channelNumber = ipmi.ChannelNumberSelf
}
if len(args) > 1 {
id, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid channel number passed, err: %w", err))
}
channelNumber = uint8(id)
}
ctx := context.Background()
res, err := client.GetUserAccess(ctx, channelNumber, 0x01)
if err != nil {
CheckErr(fmt.Errorf("GetUserAccess failed, err: %w", err))
}
fmt.Println(res.Format())
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/version.go 0000664 0000000 0000000 00000000112 14741105271 0024744 0 ustar 00root root 0000000 0000000 package commands
var (
Version string
Commit string
BuildAt string
)
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/commands/x.go 0000664 0000000 0000000 00000023655 14741105271 0023547 0 ustar 00root root 0000000 0000000 package commands
import (
"context"
"fmt"
"time"
"github.com/bougou/go-ipmi"
"github.com/kr/pretty"
"github.com/spf13/cobra"
)
const timeFormat = time.RFC3339
// x Experimental commands.
func NewCmdX() *cobra.Command {
cmd := &cobra.Command{
Use: "x",
Short: "x",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initClient()
},
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
}
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return closeClient()
},
}
cmd.AddCommand(NewCmdXGetSDRs())
cmd.AddCommand(NewCmdXGetSensors())
cmd.AddCommand(NewCmdXGetDeviceSDRs())
cmd.AddCommand(NewCmdXGetPayloadActivationStatus())
cmd.AddCommand(NewCmdXGetDeviceGUID())
cmd.AddCommand(NewCmdXGetSystemGUID())
cmd.AddCommand(NewCmdXGetPEFConfigParams())
cmd.AddCommand(NewCmdXGetLanConfigParamsFor())
cmd.AddCommand(NewCmdXGetLanConfigParamsFull())
cmd.AddCommand(NewCmdXGetLanConfig())
cmd.AddCommand(NewCmdXGetDCMIConfigParams())
cmd.AddCommand(NewCmdXGetBootOptions())
cmd.AddCommand(NewCmdXGetSystemInfoParams())
cmd.AddCommand(NewCmdXGetSystemInfoParamsFor())
cmd.AddCommand(NewCmdXGetSystemInfo())
return cmd
}
func NewCmdXGetSDRs() *cobra.Command {
var show bool
var loop bool
cmd := &cobra.Command{
Use: "get-sdr",
Short: "get-sdr",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
for {
fmt.Printf("\n\nGet SDRs at %s\n", time.Now().Format(timeFormat))
res, err := client.GetSDRs(ctx)
if err != nil {
fmt.Printf("GetSDRs failed, err: %s", err)
if loop {
goto WAIT
} else {
return
}
}
fmt.Printf("GetSDRs succeeded, %d records\n", len(res))
if show {
fmt.Println(ipmi.FormatSDRs(res))
}
if loop {
goto WAIT
} else {
return
}
WAIT:
fmt.Println("wait for next loop")
time.Sleep(30 * time.Second)
}
},
}
cmd.PersistentFlags().BoolVarP(&show, "show", "s", false, "show table of result")
cmd.PersistentFlags().BoolVarP(&loop, "loop", "l", false, "loop")
return cmd
}
func NewCmdXGetSensors() *cobra.Command {
var show bool
var loop bool
cmd := &cobra.Command{
Use: "get-sensor",
Short: "get-sensor",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
for {
fmt.Printf("\n\nGet Sensors at %s\n", time.Now().Format(timeFormat))
res, err := client.GetSensors(ctx)
if err != nil {
fmt.Printf("GetSensors failed, err: %s", err)
if loop {
goto WAIT
} else {
return
}
}
fmt.Printf("GetSensors succeeded, %d records\n", len(res))
if show {
fmt.Println(ipmi.FormatSensors(true, res...))
}
if loop {
goto WAIT
} else {
return
}
WAIT:
fmt.Println("wait for next loop")
time.Sleep(30 * time.Second)
}
},
}
cmd.PersistentFlags().BoolVarP(&show, "show", "s", false, "show table of result")
cmd.PersistentFlags().BoolVarP(&loop, "loop", "l", false, "loop")
return cmd
}
func NewCmdXGetDeviceSDRs() *cobra.Command {
var show bool
cmd := &cobra.Command{
Use: "get-device-sdr",
Short: "get-device-sdr",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
fmt.Printf("\n\nGet Device SDR at %s\n", time.Now().Format(timeFormat))
res, err := client.GetDeviceSDRs(ctx)
if err != nil {
fmt.Printf("GetDeviceSDRs failed, err: %s", err)
return
}
fmt.Printf("GetDeviceSDRs succeeded, %d records\n", len(res))
if show {
fmt.Println(ipmi.FormatSDRs(res))
}
},
}
cmd.PersistentFlags().BoolVarP(&show, "show", "s", false, "show table of result")
return cmd
}
func NewCmdXGetPayloadActivationStatus() *cobra.Command {
cmd := &cobra.Command{
Use: "get-payload-activation-status",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Println("usage: get-payload-activation-status {payload-type}")
return
}
payloadType, err := parseStringToInt64(args[0])
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
res, err := client.GetPayloadActivationStatus(ctx, ipmi.PayloadType(payloadType))
if err != nil {
fmt.Println(err)
}
fmt.Println(res.Format())
},
}
return cmd
}
func NewCmdXGetSystemGUID() *cobra.Command {
cmd := &cobra.Command{
Use: "get-system-guid",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
res, err := client.GetSystemGUID(ctx)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(res.Format())
fmt.Println("\nDetail of GUID\n==============")
fmt.Println()
fmt.Println(ipmi.FormatGUIDDetails(res.GUID))
},
}
return cmd
}
func NewCmdXGetDeviceGUID() *cobra.Command {
cmd := &cobra.Command{
Use: "get-device-guid",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
res, err := client.GetDeviceGUID(ctx)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(res.Format())
fmt.Println("\nDetail of GUID\n==============")
fmt.Println()
fmt.Println(ipmi.FormatGUIDDetails(res.GUID))
},
}
return cmd
}
func NewCmdXGetPEFConfigParams() *cobra.Command {
cmd := &cobra.Command{
Use: "get-pef-config-params",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
pefConfigParams, err := client.GetPEFConfigParams(ctx)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(pefConfigParams.Format())
},
}
return cmd
}
func NewCmdXGetLanConfigParamsFor() *cobra.Command {
usage := `
get-lan-config-params-for []
`
cmd := &cobra.Command{
Use: "get-lan-config-params-for",
Short: "get-lan-config-params-for",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
id, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid channel number passed, err: %w", err))
}
channelNumber := uint8(id)
ctx := context.Background()
lanConfigParams := ipmi.LanConfigParams{
IP: &ipmi.LanConfigParam_IP{},
SubnetMask: &ipmi.LanConfigParam_SubnetMask{},
DefaultGatewayIP: &ipmi.LanConfigParam_DefaultGatewayIP{},
}
if err := client.GetLanConfigParamsFor(ctx, channelNumber, &lanConfigParams); err != nil {
CheckErr(fmt.Errorf("GetLanConfigParamsFor failed, err: %w", err))
}
client.Debug("Lan Config", lanConfigParams)
fmt.Println(lanConfigParams.Format())
},
}
return cmd
}
func NewCmdXGetLanConfigParamsFull() *cobra.Command {
usage := `
get-lan-config-params-full []
`
cmd := &cobra.Command{
Use: "get-lan-config-params-full",
Short: "get-lan-config-params-full",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
id, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid channel number passed, err: %w", err))
}
channelNumber := uint8(id)
ctx := context.Background()
lanConfigParams, err := client.GetLanConfigParamsFull(ctx, channelNumber)
if err != nil {
CheckErr(fmt.Errorf("GetLanConfigParamsFull failed, err: %w", err))
}
client.Debug("Lan Config", lanConfigParams)
fmt.Println(lanConfigParams.Format())
},
}
return cmd
}
func NewCmdXGetLanConfig() *cobra.Command {
usage := `
get-lan-config []
`
cmd := &cobra.Command{
Use: "get-lan-config",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
CheckErr(fmt.Errorf("usage: %s", usage))
}
id, err := parseStringToInt64(args[0])
if err != nil {
CheckErr(fmt.Errorf("invalid channel number passed, err: %w", err))
}
channelNumber := uint8(id)
ctx := context.Background()
lanConfig, err := client.GetLanConfig(ctx, channelNumber)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(lanConfig.Format())
},
}
return cmd
}
func NewCmdXGetDCMIConfigParams() *cobra.Command {
cmd := &cobra.Command{
Use: "get-dcmi-config-params",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
dcmiConfigParams, err := client.GetDCMIConfigParams(ctx)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(dcmiConfigParams.Format())
},
}
return cmd
}
func NewCmdXGetBootOptions() *cobra.Command {
cmd := &cobra.Command{
Use: "get-boot-options",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
bootOptionsParams, err := client.GetSystemBootOptionsParams(ctx)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(bootOptionsParams.Format())
},
}
return cmd
}
func NewCmdXGetSystemInfoParams() *cobra.Command {
cmd := &cobra.Command{
Use: "get-system-info-params",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
systemInfoParams, err := client.GetSystemInfoParams(ctx)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(systemInfoParams.Format())
},
}
return cmd
}
func NewCmdXGetSystemInfoParamsFor() *cobra.Command {
cmd := &cobra.Command{
Use: "get-system-info-params-for",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
systemInfoParams := &ipmi.SystemInfoParams{
SetInProgress: nil,
SystemFirmwareVersions: nil,
SystemNames: make([]*ipmi.SystemInfoParam_SystemName, 0),
}
pretty.Println(systemInfoParams)
if err := client.GetSystemInfoParamsFor(ctx, systemInfoParams); err != nil {
fmt.Println(err)
return
}
fmt.Println(systemInfoParams.Format())
},
}
return cmd
}
func NewCmdXGetSystemInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "get-system-info",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
systemInfo, err := client.GetSystemInfo(ctx)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(systemInfo.Format())
},
}
return cmd
}
golang-github-bougou-go-ipmi-0.7.2/cmd/goipmi/main.go 0000664 0000000 0000000 00000000351 14741105271 0022407 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"os"
"github.com/bougou/go-ipmi/cmd/goipmi/commands"
)
func main() {
rootCmd := commands.NewRootCommand()
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
golang-github-bougou-go-ipmi-0.7.2/cmd_activate_dcmi_power_limit.go 0000664 0000000 0000000 00000002576 14741105271 0025500 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// [DCMI specification v1.5]: 6.6.4 Activate/Deactivate Power Limit
type ActivateDCMIPowerLimitRequest struct {
Activate bool
}
type ActivateDCMIPowerLimitResponse struct {
}
func (req *ActivateDCMIPowerLimitRequest) Pack() []byte {
activate := uint8(0x00)
if req.Activate {
activate = 0x01
}
return []byte{GroupExtensionDCMI, activate, 0x00, 0x00}
}
func (req *ActivateDCMIPowerLimitRequest) Command() Command {
return CommandActivateDCMIPowerLimit
}
func (res *ActivateDCMIPowerLimitResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *ActivateDCMIPowerLimitResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
return nil
}
func (res *ActivateDCMIPowerLimitResponse) Format() string {
return ""
}
// ActivateDCMIPowerLimit activate or deactivate the power limit set.
// Setting the param 'activate' to true means to activate the power limit, false means to deactivate the power limit
func (c *Client) ActivateDCMIPowerLimit(ctx context.Context, activate bool) (response *ActivateDCMIPowerLimitResponse, err error) {
request := &ActivateDCMIPowerLimitRequest{
Activate: activate,
}
response = &ActivateDCMIPowerLimitResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_activate_session.go 0000664 0000000 0000000 00000014473 14741105271 0023634 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 22.17
type ActivateSessionRequest struct {
// Authentication Type for session.
// The selected type will be used for session activation and for all subsequent authenticated packets under the session, unless "Per-message Authentication" or "User Level Authentication" are disabled.
// (See 6.12.4, Per-Message and User Level Authentication Disables, for more information.)
//
// This value must match with the Authentication Type used in the Get Session Challenge request for the session. In addition, for multi-session channels this value must also match the authentication type used in the Session Header.
AuthTypeForSession AuthType
// Maximum privilege level requested. Indicates the highest privilege level that
// may be requested for this session. This privilege level must be less than
// or equal to the privilege limit for the channel and the privilege limit for the
// user in order for the Activate Session command to be successful
// (completion code = 00h). Once the Activate Session command has been
// successful, the requested privilege level becomes a 'session limit' that
// cannot be raised beyond the requested level, even if the user and/or
// channel privilege level limits would allow it. I.e. it takes precedence over
// the channel and user privilege level limits.
//
// [7:4] - reserved
// [3:0] - Requested Maximum Privilege Level
// 0h = reserved
// 1h = Callback level
// 2h = User level
// 3h = Operator level
// 4h = Administrator level
// 5h = OEM Proprietary level
// all other = reserved
MaxPrivilegeLevel PrivilegeLevel
// For multi-session channels: (e.g. LAN channel):
// Challenge String data from corresponding Get Session Challenge response.
//
// For single-session channels that lack session header (e.g. serial/modem in Basic Mode):
// Clear text password or AuthCode. See 22.17.1, AuthCode Algorithms.
Challenge [16]byte // uint16
// Initial Outbound Sequence Number = Starting sequence number that remote console wants used for messages from the BMC. (LS byte first). Must be non-null in order to establish a session. 0000_0000h = reserved. Can be any random value.
//
// The BMC must increment the outbound session sequence number by one (1) for
// each subsequent outbound message from the BMC (include ActivateSessionResponse)
//
// The BMC sets the incremented number to Sequence field of SessionHeader.
InitialOutboundSequenceNumber uint32
}
func (req *ActivateSessionRequest) Pack() []byte {
out := make([]byte, 22)
packUint8(uint8(req.AuthTypeForSession), out, 0)
packUint8(uint8(req.MaxPrivilegeLevel), out, 1)
packBytes(req.Challenge[:], out, 2)
packUint32L(req.InitialOutboundSequenceNumber, out, 18)
return out
}
func (req *ActivateSessionRequest) Command() Command {
return CommandActivateSession
}
type ActivateSessionResponse struct {
// Authentication Type for remainder of session
AuthType AuthType
// use this for remainder of session.
// While atypical, the BMC is allowed to change the Session ID from the one that passed in the request.
SessionID uint32
// Initial inbound seq# = Sequence number that BMC wants remote console to use for subsequent messages in the session. The BMC returns a non-null value for multi-session connections and returns null (all 0s) for single-session connections.
//
// The remote console must increment the inbound session sequence number by one (1) for each subsequent message it sends to the BMC.
InitialInboundSequenceNumber uint32
// Maximum privilege level allowed for this session
// [7:4] - reserved
// [3:0] - Maximum Privilege Level allowed
// 0h = reserved
// 1h = Callback level
// 2h = User level
// 3h = Operator level
// 4h = Administrator level
// 5h = OEM Proprietary level
// all other = reserved
MaxPrivilegeLevel uint8
}
func (res *ActivateSessionResponse) Unpack(data []byte) error {
if len(data) < 10 {
return ErrUnpackedDataTooShortWith(len(data), 10)
}
res.AuthType = AuthType(data[0])
res.SessionID, _, _ = unpackUint32L(data, 1)
res.InitialInboundSequenceNumber, _, _ = unpackUint32L(data, 5)
res.MaxPrivilegeLevel = data[9]
return nil
}
func (*ActivateSessionResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "No session slot available (BMC cannot accept any more sessions)",
0x82: "No slot available for given user. (Limit of user sessions allowed under that name has been reached)",
// (An implementation may only be able to support a certain number of
// sessions based on what authentication resources are required. For
// example, if User Level Authentication is disabled, an implementation
// may be able to allow a larger number of users that are limited to User
// Level privilege, than users that require higher privilege.)
0x83: "No slot available to support user due to maximum privilege capability",
0x84: "session sequence number out-of-range",
0x85: "invalid Session ID in request",
0x86: "requested maximum privilege level exceeds user and/or channel privilege limit",
}
}
func (res *ActivateSessionResponse) Format() string {
return fmt.Sprintf("%v", res)
}
// ActivateSession is only used for IPMI v1.5
func (c *Client) ActivateSession(ctx context.Context) (response *ActivateSessionResponse, err error) {
request := &ActivateSessionRequest{
AuthTypeForSession: c.session.authType,
MaxPrivilegeLevel: c.maxPrivilegeLevel,
Challenge: c.session.v15.challenge,
// the outbound session sequence number is set by the remote console and can be any random value.
InitialOutboundSequenceNumber: randomUint32(),
}
c.session.v15.outSeq = request.InitialOutboundSequenceNumber
response = &ActivateSessionResponse{}
// The Activate Session packet is typically authenticated.
// We set session to active here to indicate this request should be authenticated
// but if ActivateSession Command failed, we should set session active to false
err = c.Exchange(ctx, request, response)
if err != nil {
return
}
c.session.v15.active = true
c.session.v15.preSession = false
// to use for the remainder of the session
// Todo, validate the SessionID
c.session.v15.sessionID = response.SessionID
// The remote console must increment the inbound session sequence number
// by one (1) for each subsequent message it sends to the BMC
c.session.v15.inSeq = response.InitialInboundSequenceNumber
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_add_sel_entry.go 0000664 0000000 0000000 00000002170 14741105271 0023074 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 31.6 Add SEL Entry Command
type AddSELEntryRequest struct {
SEL *SEL
}
type AddSELEntryResponse struct {
RecordID uint16 // Record ID for added record, LS Byte first
}
func (req *AddSELEntryRequest) Command() Command {
return CommandAddSELEntry
}
func (req *AddSELEntryRequest) Pack() []byte {
return req.SEL.Pack()
}
func (res *AddSELEntryResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.RecordID, _, _ = unpackUint16L(msg, 0)
return nil
}
func (res *AddSELEntryResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "operation not supported for this Record Type",
0x81: "cannot execute command, SEL erase in progress",
}
}
func (res *AddSELEntryResponse) Format() string {
return fmt.Sprintf("Record ID : %d (%#02x)", res.RecordID, res.RecordID)
}
func (c *Client) AddSELEntry(ctx context.Context, sel *SEL) (response *AddSELEntryResponse, err error) {
request := &AddSELEntryRequest{
SEL: sel,
}
response = &AddSELEntryResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_alert_immediate.go 0000664 0000000 0000000 00000003756 14741105271 0023420 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
type AlertImmediateOperation uint8
const (
AlertImmediateOperationInitiateAlert AlertImmediateOperation = 0b00
AlertImmediateOperationGetStatus AlertImmediateOperation = 0b01
AlertImmediateOperationClearStatus AlertImmediateOperation = 0b10
AlertImmediateOperationReserved AlertImmediateOperation = 0b11
)
type AlertImmediateStatus uint8
const (
AlertImmediateStatusNoStatus AlertImmediateStatus = 0x00
AlertImmediateStatusNormalEnd AlertImmediateStatus = 0x01
AlertImmediateStatusFailedRetry AlertImmediateStatus = 0x02
AlertImmediateStatusFailedWaitACK AlertImmediateStatus = 0x03
AlertImmediateStatusInProgress AlertImmediateStatus = 0xff
)
// 30.7 Alert Immediate Command
type AlertImmediateRequest struct {
ChannelNumber uint8
DestinationSelector uint8
Operation uint8
SendAlertString bool
AlertStringSelector uint8
GeneratorID uint8
EvMRev uint8
SensorType SensorType
SensorNumber SensorNumber
EventDir EventDir
EventReadingType EventReadingType
EventData EventData
}
type AlertImmediateResponse struct {
AlertImmediateStatus uint8
}
func (req *AlertImmediateRequest) Pack() []byte {
out := make([]byte, 1)
return out
}
func (req *AlertImmediateRequest) Command() Command {
return CommandAlertImmediate
}
func (res *AlertImmediateResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "Alert Immediate rejected due to alert already in progress",
0x82: "Alert Immediate rejected due to IPMI messaging session active on this channel",
0x83: "Platform Event Parameters (4:11) not supported",
}
}
func (res *AlertImmediateResponse) Unpack(msg []byte) error {
return nil
}
func (res *AlertImmediateResponse) Format() string {
return ""
}
func (c *Client) AlertImmediate(ctx context.Context, request *AlertImmediateRequest) (response *AlertImmediateResponse, err error) {
response = &AlertImmediateResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_arm_pef_postpone_timer.go 0000664 0000000 0000000 00000004132 14741105271 0025020 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 30.2 Arm PEF Postpone Timer Command
type ArmPEFPostponeTimerRequest struct {
// PEF Postpone Timeout, in seconds. 01h -> 1 second.
//
// 00h = disable Postpone Timer (PEF will immediately handle events, if enabled).
// The BMC automatically disables the timer whenever the system
// enters a sleep state, is powered down, or reset.
// 01h - FDh = arm timer.
// Timer will automatically start counting down from given value
// when the last-processed event Record ID is not equal to the last
// received event's Record ID.
// FEh = Temporary PEF disable.
// The PEF Postpone timer does not countdown from the value.
// The BMC automatically re-enables PEF (if enabled in the PEF configuration parameters)
// and sets the PEF Postpone timeout to 00h whenever the system
// enters a sleep state, is powered down, or reset. Software can
// cancel this disable by setting this parameter to 00h or 01h-FDh.
// FFh = get present countdown value
Timeout uint8
}
type ArmPEFPostponeTimerResponse struct {
// Present timer countdown value
PresentValue uint8
}
func (req *ArmPEFPostponeTimerRequest) Command() Command {
return CommandArmPEFPostponeTimer
}
func (req *ArmPEFPostponeTimerRequest) Pack() []byte {
// empty request data
return []byte{req.Timeout}
}
func (res *ArmPEFPostponeTimerResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShort
}
res.PresentValue = msg[0]
return nil
}
func (r *ArmPEFPostponeTimerResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *ArmPEFPostponeTimerResponse) Format() string {
return fmt.Sprintf(`Present timer countdown value : %d (%#02x)`,
res.PresentValue, res.PresentValue,
)
}
func (c *Client) ArmPEFPostponeTimer(ctx context.Context, timeout uint8) (response *ArmPEFPostponeTimerResponse, err error) {
request := &ArmPEFPostponeTimerRequest{
Timeout: timeout,
}
response = &ArmPEFPostponeTimerResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_chassis_control.go 0000664 0000000 0000000 00000002422 14741105271 0023455 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
type ChassisControl uint8
const (
ChassisControlPowerDown ChassisControl = 0 // down, off
ChassisControlPowerUp ChassisControl = 1
ChassisControlPowerCycle ChassisControl = 2
ChassisControlHardReset ChassisControl = 3
ChassisControlDiagnosticInterrupt ChassisControl = 4
ChassisControlSoftShutdown ChassisControl = 5
)
// 28.3 Chassis Control Command
type ChassisControlRequest struct {
ChassisControl ChassisControl
}
type ChassisControlResponse struct {
}
func (req *ChassisControlRequest) Pack() []byte {
out := make([]byte, 1)
packUint8(uint8(req.ChassisControl), out, 0)
return out
}
func (req *ChassisControlRequest) Command() Command {
return CommandChassisControl
}
func (res *ChassisControlResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *ChassisControlResponse) Unpack(msg []byte) error {
return nil
}
func (res *ChassisControlResponse) Format() string {
return ""
}
func (c *Client) ChassisControl(ctx context.Context, control ChassisControl) (response *ChassisControlResponse, err error) {
request := &ChassisControlRequest{
ChassisControl: control,
}
response = &ChassisControlResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_chassis_identify.go 0000664 0000000 0000000 00000002554 14741105271 0023616 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 28.5 Chassis Identify Command
// 用来定位设备,机箱定位 (机箱定位灯默认亮 interval 秒)
type ChassisIdentifyRequest struct {
IdentifyInterval uint8
ForceIdentifyOn bool
}
type ChassisIdentifyResponse struct {
// empty
}
func (req *ChassisIdentifyRequest) Pack() []byte {
out := make([]byte, 2)
packUint8(uint8(req.IdentifyInterval), out, 0)
var force uint8 = 0
if req.ForceIdentifyOn {
force = 1
}
packUint8(force, out, 1)
return out
}
func (req *ChassisIdentifyRequest) Command() Command {
return CommandChassisIdentify
}
func (res *ChassisIdentifyResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *ChassisIdentifyResponse) Unpack(msg []byte) error {
return nil
}
func (res *ChassisIdentifyResponse) Format() string {
return ""
}
// This command causes the chassis to physically identify itself by a mechanism
// chosen by the system implementation; such as turning on blinking user-visible lights
// or emitting beeps via a speaker, LCD panel, etc.
func (c *Client) ChassisIdentify(ctx context.Context, interval uint8, force bool) (response *ChassisIdentifyResponse, err error) {
request := &ChassisIdentifyRequest{
IdentifyInterval: interval,
ForceIdentifyOn: force,
}
response = &ChassisIdentifyResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_chassis_reset.go 0000664 0000000 0000000 00000001661 14741105271 0023123 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 28.4 Chassis Reset Command
type ChassisResetRequest struct {
// empty
}
type ChassisResetResponse struct {
// empty
}
func (req *ChassisResetRequest) Pack() []byte {
return []byte{}
}
func (req *ChassisResetRequest) Command() Command {
return CommandChassisReset
}
func (res *ChassisResetResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *ChassisResetResponse) Unpack(msg []byte) error {
return nil
}
func (res *ChassisResetResponse) Format() string {
return ""
}
// This command was used with early versions of the ICMB.
// It has been superseded by the Chassis Control command
// For host systems, this corresponds to a system hard reset.
func (c *Client) ChassisReset(ctx context.Context) (response *ChassisResetResponse, err error) {
request := &ChassisResetRequest{}
response = &ChassisResetResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_clear_message_flags.go 0000664 0000000 0000000 00000002606 14741105271 0024232 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.3 Clear Message Flags Command
type ClearMessageFlagsRequest struct {
ClearOEM2 bool
ClearOEM1 bool
ClearOEM0 bool
ClearWatchdogPreTimeoutInterruptFlag bool
ClearEventMessageBuffer bool
ClearReceiveMessageQueue bool
}
type ClearMessageFlagsResponse struct {
}
func (req *ClearMessageFlagsRequest) Command() Command {
return CommandClearMessageFlags
}
func (req *ClearMessageFlagsRequest) Pack() []byte {
var b uint8 = 0
if req.ClearOEM2 {
b = setBit7(b)
}
if req.ClearOEM1 {
b = setBit6(b)
}
if req.ClearOEM0 {
b = setBit5(b)
}
if req.ClearWatchdogPreTimeoutInterruptFlag {
b = setBit3(b)
}
if req.ClearEventMessageBuffer {
b = setBit1(b)
}
if req.ClearReceiveMessageQueue {
b = setBit0(b)
}
return []byte{b}
}
func (res *ClearMessageFlagsResponse) Unpack(msg []byte) error {
return nil
}
func (*ClearMessageFlagsResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *ClearMessageFlagsResponse) Format() string {
// Todo
return ""
}
func (c *Client) ClearMessageFlags(ctx context.Context, request *ClearMessageFlagsRequest) (response *ClearMessageFlagsResponse, err error) {
response = &ClearMessageFlagsResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_clear_sel.go 0000664 0000000 0000000 00000002575 14741105271 0022222 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 31.9 Clear SEL Command
type ClearSELRequest struct {
ReservationID uint16 // LS Byte first
GetErasureStatusFlag bool
}
type ClearSELResponse struct {
ErasureProgressStatus uint8
}
func (req *ClearSELRequest) Pack() []byte {
var out = make([]byte, 6)
packUint16L(req.ReservationID, out, 0)
packUint8('C', out, 2) // fixed 'C' char
packUint8('L', out, 3) // fixed 'L' char
packUint8('R', out, 4) // fixed 'R' char
if req.GetErasureStatusFlag {
packUint8(0x00, out, 5) // get erasure status
} else {
packUint8(0xaa, out, 5) // initiate erase
}
return out
}
func (req *ClearSELRequest) Command() Command {
return CommandClearSEL
}
func (res *ClearSELResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
res.ErasureProgressStatus, _, _ = unpackUint8(msg, 0)
return nil
}
func (res *ClearSELResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *ClearSELResponse) Format() string {
return fmt.Sprintf("%v", res)
}
func (c *Client) ClearSEL(ctx context.Context, reservationID uint16) (response *ClearSELResponse, err error) {
request := &ClearSELRequest{
ReservationID: reservationID,
GetErasureStatusFlag: false,
}
response = &ClearSELResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_close_session.go 0000664 0000000 0000000 00000002520 14741105271 0023127 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.19
type CloseSessionRequest struct {
// For IPMI v2.0/RMCP+ this is the Managed System Session ID value that was generated by the BMC, not the ID from the remote console. If Session ID = 0000_0000h then an implementation can optionally enable this command to take an additional byte of parameter data that allows a session handle to be used to close a session.
SessionID uint32
// Session Handle. (only present if Session ID = 0000_0000h)
SessionHandle uint8
}
type CloseSessionResponse struct {
}
func (req *CloseSessionRequest) Pack() []byte {
msg := make([]byte, 4)
packUint32L(req.SessionID, msg, 0)
if req.SessionID == 0 {
msg = append(msg, 0)
packUint8(req.SessionHandle, msg, 4)
}
return msg
}
func (req *CloseSessionRequest) Command() Command {
return CommandCloseSession
}
func (res *CloseSessionResponse) Unpack(msg []byte) error {
return nil
}
func (res *CloseSessionResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x87: "Invalid session id",
0x88: "Invalid session handle",
}
}
func (res *CloseSessionResponse) Format() string {
return ""
}
func (c *Client) CloseSession(ctx context.Context, request *CloseSessionRequest) (response *CloseSessionResponse, err error) {
response = &CloseSessionResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_cold_reset.go 0000664 0000000 0000000 00000001263 14741105271 0022405 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 20.2 Cold Reset Command
type ColdResetRequest struct {
// empty
}
type ColdResetResponse struct {
}
func (req *ColdResetRequest) Command() Command {
return CommandColdReset
}
func (req *ColdResetRequest) Pack() []byte {
return []byte{}
}
func (res *ColdResetResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *ColdResetResponse) Unpack(msg []byte) error {
return nil
}
func (res *ColdResetResponse) Format() string {
return ""
}
func (c *Client) ColdReset(ctx context.Context) (err error) {
request := &ColdResetRequest{}
response := &ColdResetResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_delete_sel_entry.go 0000664 0000000 0000000 00000002470 14741105271 0023611 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 31.8 Delete SEL Entry Command
type DeleteSELEntryRequest struct {
ReservationID uint16
RecordID uint16
}
type DeleteSELEntryResponse struct {
RecordID uint16
}
func (req *DeleteSELEntryRequest) Command() Command {
return CommandDeleteSELEntry
}
func (req *DeleteSELEntryRequest) Pack() []byte {
out := make([]byte, 4)
packUint16L(req.ReservationID, out, 0)
packUint16L(req.RecordID, out, 2)
return out
}
func (res *DeleteSELEntryResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.RecordID, _, _ = unpackUint16L(msg, 0)
return nil
}
func (res *DeleteSELEntryResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "operation not supported for this Record Type",
0x81: "cannot execute command, SEL erase in progress",
}
}
func (res *DeleteSELEntryResponse) Format() string {
return fmt.Sprintf("Record ID : %d (%#02x)", res.RecordID, res.RecordID)
}
func (c *Client) DeleteSELEntry(ctx context.Context, recordID uint16, reservationID uint16) (response *DeleteSELEntryResponse, err error) {
request := &DeleteSELEntryRequest{
ReservationID: reservationID,
RecordID: recordID,
}
response = &DeleteSELEntryResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_enable_message_channel_receive.go 0000664 0000000 0000000 00000003120 14741105271 0026400 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.5 Enable Message Channel Receive Command
type EnableMessageChannelReceiveRequest struct {
ChannelNumber uint8
// [7:2] - reserved
// [1:0] - 00b = disable channel
// 01b = enable channel
// 10b = get channel enable/disable state
// 11b = reserved
ChannelState uint8
}
type EnableMessageChannelReceiveResponse struct {
ChannelNumber uint8
ChannelEnabled bool
}
func (req *EnableMessageChannelReceiveRequest) Command() Command {
return CommandEnableMessageChannelReceive
}
func (req *EnableMessageChannelReceiveRequest) Pack() []byte {
out := make([]byte, 2)
packUint8(req.ChannelNumber, out, 0)
packUint8(req.ChannelState, out, 1)
return out
}
func (res *EnableMessageChannelReceiveResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.ChannelNumber, _, _ = unpackUint8(msg, 0)
b, _, _ := unpackUint8(msg, 1)
res.ChannelEnabled = isBit0Set(b)
return nil
}
func (*EnableMessageChannelReceiveResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *EnableMessageChannelReceiveResponse) Format() string {
// Todo
return ""
}
func (c *Client) EnableMessageChannelReceive(ctx context.Context, channelNumber uint8, channelState uint8) (response *EnableMessageChannelReceiveResponse, err error) {
request := &EnableMessageChannelReceiveRequest{
ChannelNumber: channelNumber,
ChannelState: channelState,
}
response = &EnableMessageChannelReceiveResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_acpi_power_state.go 0000664 0000000 0000000 00000002546 14741105271 0024456 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 20.7 Get ACPI Power State Command
type GetACPIPowerStateRequest struct {
// empty
}
type GetACPIPowerStateResponse struct {
SystemPowerState SystemPowerState
DevicePowerState DevicePowerState
}
func (req *GetACPIPowerStateRequest) Pack() []byte {
return nil
}
func (req *GetACPIPowerStateRequest) Command() Command {
return CommandGetACPIPowerState
}
func (res *GetACPIPowerStateResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetACPIPowerStateResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
b1, _, _ := unpackUint8(msg, 0)
res.SystemPowerState = SystemPowerState(b1 & 0x7f)
b2, _, _ := unpackUint8(msg, 1)
res.DevicePowerState = DevicePowerState(b2 & 0x7f)
return nil
}
func (res *GetACPIPowerStateResponse) Format() string {
return fmt.Sprintf(`ACPI System Power State: %s
ACPI Device Power State: %s`,
res.SystemPowerState,
res.DevicePowerState,
)
}
// This command is provided to allow system software to tell a controller the present ACPI power state of the system.
func (c *Client) GetACPIPowerState(ctx context.Context) (response *GetACPIPowerStateResponse, err error) {
request := &GetACPIPowerStateRequest{}
response = &GetACPIPowerStateResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_auth_code.go 0000664 0000000 0000000 00000001535 14741105271 0023056 0 ustar 00root root 0000000 0000000 package ipmi
// see 22.21
//
// This command is used to send a block of data to the BMC, whereupon the BMC will
// return a hash of the data together concatenated with the internally stored password for the given channel and user
type GetAuthCodeRequest struct {
AuthType AuthType
ChannelNumber uint8
UserID uint8
// data to hash (must be 16 bytes)
Data [16]byte
}
type GetAuthCodeResponse struct {
CompletionCode
// For IPMI v1.5 AuthCode Number:
AuthCode [16]byte
// ForIPMI v2.0 Integrity Algorithm Number
// Resultant hash, per selected Integrity algorithm. Up to 20 bytes. An
// implementation can elect to return a variable length field based on the size of
// the hash for the given integrity algorithm, or can return a fixed field where the
// hash data is followed by 00h bytes as needed to pad the data to 20 bytes.
Hash []byte
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_bmc_global_enables.go 0000664 0000000 0000000 00000002766 14741105271 0024704 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.2 Get BMC Global Enables Command
type GetBMCGlobalEnablesRequest struct {
// empty
}
type GetBMCGlobalEnablesResponse struct {
OEM2Enabled bool
OEM1Enabled bool
OEM0Enabled bool
SystemEventLoggingEnabled bool
EventMessageBufferEnabled bool
EventMessageBufferFullInterruptEnabled bool
ReceiveMessageQueueInterruptEnabled bool
}
func (req *GetBMCGlobalEnablesRequest) Command() Command {
return CommandGetBMCGlobalEnables
}
func (req *GetBMCGlobalEnablesRequest) Pack() []byte {
return []byte{}
}
func (res *GetBMCGlobalEnablesResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
b, _, _ := unpackUint8(msg, 0)
res.OEM2Enabled = isBit7Set(b)
res.OEM1Enabled = isBit6Set(b)
res.OEM0Enabled = isBit5Set(b)
res.SystemEventLoggingEnabled = isBit3Set(b)
res.EventMessageBufferEnabled = isBit2Set(b)
res.EventMessageBufferFullInterruptEnabled = isBit1Set(b)
res.ReceiveMessageQueueInterruptEnabled = isBit0Set(b)
return nil
}
func (*GetBMCGlobalEnablesResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetBMCGlobalEnablesResponse) Format() string {
// Todo
return ""
}
func (c *Client) GetBMCGlobalEnables(ctx context.Context) (response *GetBMCGlobalEnablesResponse, err error) {
request := &GetBMCGlobalEnablesRequest{}
response = &GetBMCGlobalEnablesResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_bt_interface_capabilities.go 0000664 0000000 0000000 00000003040 14741105271 0026252 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.10 Get BT Interface Capabilities Command
type GetBTInterfaceCapabilitiesRequest struct {
// empty
}
type GetBTInterfaceCapabilitiesResponse struct {
OutstandingRequestsCountSupported uint8
InputBufferMessageSizeBytes uint8
OutputBufferMessageSizeBytes uint8
BMCRequestToResponseTimeSec uint8
RecommendedRetries uint8
}
func (req *GetBTInterfaceCapabilitiesRequest) Command() Command {
return CommandGetBTInterfaceCapabilities
}
func (req *GetBTInterfaceCapabilitiesRequest) Pack() []byte {
return []byte{}
}
func (res *GetBTInterfaceCapabilitiesResponse) Unpack(msg []byte) error {
// at least 3 bytes
if len(msg) < 5 {
return ErrUnpackedDataTooShortWith(len(msg), 5)
}
res.OutstandingRequestsCountSupported, _, _ = unpackUint8(msg, 0)
res.InputBufferMessageSizeBytes, _, _ = unpackUint8(msg, 1)
res.OutputBufferMessageSizeBytes, _, _ = unpackUint8(msg, 2)
res.BMCRequestToResponseTimeSec, _, _ = unpackUint8(msg, 3)
res.RecommendedRetries, _, _ = unpackUint8(msg, 4)
return nil
}
func (*GetBTInterfaceCapabilitiesResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetBTInterfaceCapabilitiesResponse) Format() string {
return ""
}
func (c *Client) GetBTInterfaceCapabilities(ctx context.Context) (response *GetBTInterfaceCapabilitiesResponse, err error) {
request := &GetBTInterfaceCapabilitiesRequest{}
response = &GetBTInterfaceCapabilitiesResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_channel_access.go 0000664 0000000 0000000 00000004132 14741105271 0024050 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 22.23 Get Channel Access Command
type GetChannelAccessRequest struct {
ChannelNumber uint8
AccessOption ChannelAccessOption
}
type GetChannelAccessResponse struct {
PEFAlertingDisabled bool
PerMsgAuthDisabled bool
UserLevelAuthDisabled bool
AccessMode ChannelAccessMode
MaxPrivilegeLevel PrivilegeLevel
}
func (req *GetChannelAccessRequest) Pack() []byte {
out := make([]byte, 2)
packUint8(req.ChannelNumber, out, 0)
packUint8(uint8(req.AccessOption)<<6, out, 1)
return out
}
func (req *GetChannelAccessRequest) Command() Command {
return CommandGetChannelAccess
}
func (res *GetChannelAccessResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x82: "set not supported on selected channel (e.g. channel is session-less.)",
0x83: "access mode not supported",
}
}
func (res *GetChannelAccessResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
b0, _, _ := unpackUint8(msg, 0)
res.PEFAlertingDisabled = isBit5Set(b0)
res.PerMsgAuthDisabled = isBit4Set(b0)
res.UserLevelAuthDisabled = isBit3Set(b0)
res.AccessMode = ChannelAccessMode(b0 & 0x07)
b1, _, _ := unpackUint8(msg, 1)
res.MaxPrivilegeLevel = PrivilegeLevel(b1 & 0x0f)
return nil
}
func (res *GetChannelAccessResponse) Format() string {
return fmt.Sprintf(` Alerting : %s
Per-message Auth : %s
User Level Auth : %s
Access Mode : %s
Max Privilege Level : %s`,
formatBool(res.PEFAlertingDisabled, "disabled", "enabled"),
formatBool(res.PerMsgAuthDisabled, "disabled", "enabled"),
formatBool(res.UserLevelAuthDisabled, "disabled", "enabled"),
res.AccessMode,
res.MaxPrivilegeLevel.String(),
)
}
func (c *Client) GetChannelAccess(ctx context.Context, channelNumber uint8, accessOption ChannelAccessOption) (response *GetChannelAccessResponse, err error) {
request := &GetChannelAccessRequest{
ChannelNumber: channelNumber,
AccessOption: accessOption,
}
response = &GetChannelAccessResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_channel_authentication_capabilities.go 0000664 0000000 0000000 00000016330 14741105271 0030342 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 13.14
// 22.13
type GetChannelAuthenticationCapabilitiesRequest struct {
// [7]
// - 1b = get IPMI v2.0+ extended data.
// If the given channel supports authentication but does not support RMCP+
// (e.g. a serial channel), then the Response data should return with bit [5] of byte 4 = 0b, byte 5 should return 01h,
//
// - 0b = Backward compatible with IPMI v1.5. Response data only returns
// bytes 1:9, bit [7] of byte 3 (Authentication Type Support) and bit [5] of byte 4 returns as 0b, bit [5] of byte byte 5 returns 00h.
// [6:4] - reserved
IPMIv20Extended bool
// [3:0] - channel number.
// 0h-Bh, Fh = channel numbers
// Eh = retrieve information for channel this request was issued on
ChannelNumber uint8
// Requested Maximum Privilege Level
MaximumPrivilegeLevel PrivilegeLevel
}
type GetChannelAuthenticationCapabilitiesResponse struct {
// Channel number that the Authentication Capabilities is being returned for.
// If the channel number in the request was set to Eh, this will return
// the channel number for the channel that the request was received on
ChannelNumber uint8
// Returns the setting of the Authentication Type Enable field from the
// configuration parameters for the given channel that corresponds to
// the Requested Maximum Privilege Level.
// [7] -
// 1b = IPMI v2.0+ extended capabilities available. See Extended Capabilities field, below.
// 0b = IPMI v1.5 support only.
IPMIv20ExtendedAvailable bool
// [5:0] - IPMI v1.5 Authentication type(s) enabled for given Requested Maximum Privilege Level
AuthTypeNoneSupported bool // bit 0
AuthTypeMD2Supported bool // bit 1
AuthTypeMD5Supported bool // bit 2
AuthTypePasswordSupported bool // bit 4
AuthTypeOEMProprietarySupported bool // bit 5
// [5] - Kg status (two-key login status).
// Applies to v2.0/RMCP+ RAKP Authentication only. Otherwise, ignore as reserved.
// 0b = Kg is set to default (all 0s).
// 1b = Kg is set to non-zero value.
KgStatus bool
// [4] - Per-message Authentication status
// 0b = Per-message Authentication is enabled.
// 1b = Per-message Authentication is disabled.
// Authentication Type "none" accepted for packets to the BMC after the session has been activated.
PerMessageAuthenticationDisabled bool
// [3] - User Level Authentication status
// 0b = User Level Authentication is enabled.
// 1b = User Level Authentication is disabled.
// Authentication Type "none" accepted for User Level commands to the BMC.
UserLevelAuthenticationDisabled bool
// [2:0] - Anonymous Login status
// This parameter returns values that tells the remote console whether
// there are users on the system that have "null" usernames.
// This can be used to guide the way the remote console presents login options to the user.
// (see IPMI v1.5 specification sections 6.9.1, "Anonymous Login" Convention and 6.9.2, Anonymous Login )
// [2] - 1b = Non-null usernames enabled. (One or more users are enabled that have non-null usernames).
// [1] - 1b = Null usernames enabled (One or more users that have a null username, but non-null password, are presently enabled)
// [0] - 1b = Anonymous Login enabled (A user that has a null username and null password is presently enabled)
NonNullUsernamesEnabled bool
NullUsernamesEnabled bool
AnonymousLoginEnabled bool
// For IPMI v1.5: - reserved
// For IPMI v2.0+: - Extended Capabilities
// [7:2] - reserved
// [1] - 1b = channel supports IPMI v2.0 connections.
// [0] - 1b = channel supports IPMI v1.5 connections.
SupportIPMIv15 bool
SupportIPMIv20 bool
// IANA Enterprise Number for OEM/Organization that specified the particular
// OEM Authentication Type for RMCP. Least significant byte first.
// ONLY 3 bytes occupied. Return 00h, 00h, 00h if no OEM authentication type available.
OEMID uint32
// Additional OEM-specific information for the OEM Authentication Type for RMCP.
// Return 00h if no OEM authentication type available.
OEMAuxiliaryData uint8
}
func (req *GetChannelAuthenticationCapabilitiesRequest) Pack() []byte {
var msg = make([]byte, 2)
byte1 := req.ChannelNumber
if req.IPMIv20Extended {
byte1 = byte1 | 0x80
}
packUint8(byte1, msg, 0)
packUint8(uint8(req.MaximumPrivilegeLevel), msg, 1)
return msg
}
func (req *GetChannelAuthenticationCapabilitiesRequest) Command() Command {
return CommandGetChannelAuthCapabilities
}
func (res *GetChannelAuthenticationCapabilitiesResponse) Unpack(msg []byte) error {
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
res.ChannelNumber, _, _ = unpackUint8(msg, 0)
b, _, _ := unpackUint8(msg, 1)
res.IPMIv20ExtendedAvailable = isBit7Set(b)
res.AuthTypeOEMProprietarySupported = isBit5Set(b)
res.AuthTypePasswordSupported = isBit4Set(b)
res.AuthTypeMD5Supported = isBit2Set(b)
res.AuthTypeMD2Supported = isBit1Set(b)
c, _, _ := unpackUint8(msg, 2)
res.KgStatus = isBit5Set(c)
res.PerMessageAuthenticationDisabled = isBit4Set(c)
res.UserLevelAuthenticationDisabled = isBit3Set(c)
res.NonNullUsernamesEnabled = isBit2Set(c)
res.NullUsernamesEnabled = isBit1Set(c)
res.AnonymousLoginEnabled = isBit0Set(c)
d, _, _ := unpackUint8(msg, 3)
if res.IPMIv20ExtendedAvailable {
res.SupportIPMIv20 = isBit1Set(d)
res.SupportIPMIv15 = isBit0Set(d)
}
res.OEMID, _, _ = unpackUint24L(msg, 4)
res.OEMAuxiliaryData, _, _ = unpackUint8(msg, 7)
return nil
}
func (*GetChannelAuthenticationCapabilitiesResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetChannelAuthenticationCapabilitiesResponse) chooseAuthType() AuthType {
if res.AuthTypeMD2Supported {
return AuthTypeMD2
}
if res.AuthTypeMD5Supported {
return AuthTypeMD5
}
if res.AuthTypePasswordSupported {
return AuthTypePassword
}
if res.AuthTypeOEMProprietarySupported {
return AuthTypeOEM
}
if res.AuthTypeNoneSupported {
return AuthTypeNone
}
return AuthTypeNone
}
func (res *GetChannelAuthenticationCapabilitiesResponse) Format() string {
return fmt.Sprintf("%v", res)
}
// GetChannelAuthenticationCapabilities is used to retrieve capability information
// about the channel that the message is delivered over, or for a particular channel.
// The command returns the authentication algorithm support for the given privilege level.
//
// This command is sent in unauthenticated (clear) format.
//
// When activating a session, the privilege level passed in this command will
// normally be the same Requested Maximum Privilege level that will be used
// for a subsequent Activate Session command.
func (c *Client) GetChannelAuthenticationCapabilities(ctx context.Context, channelNumber uint8, privilegeLevel PrivilegeLevel) (response *GetChannelAuthenticationCapabilitiesResponse, err error) {
request := &GetChannelAuthenticationCapabilitiesRequest{
IPMIv20Extended: true,
ChannelNumber: channelNumber,
MaximumPrivilegeLevel: privilegeLevel,
}
response = &GetChannelAuthenticationCapabilitiesResponse{}
err = c.Exchange(ctx, request, response)
if err != nil {
return
}
if !response.AnonymousLoginEnabled {
if c.Username == "" {
return nil, fmt.Errorf("anonymous login is not enabled, username (%s) is empty", c.Username)
}
}
c.session.authType = response.chooseAuthType()
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_channel_cipher_suites.go 0000664 0000000 0000000 00000010455 14741105271 0025462 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
const (
MaxCipherSuiteListIndex uint8 = 0x3f
)
// 22.15 Get Channel Cipher Suites Command
type GetChannelCipherSuitesRequest struct {
// 0h-Bh, Fh = channel numbers
// Eh = retrieve information for channel this request was issued on
ChannelNumber uint8
PayloadType PayloadType
ListIndex uint8
}
type GetChannelCipherSuitesResponse struct {
ChannelNumber uint8
CipherSuiteRecords []byte
}
func (req *GetChannelCipherSuitesRequest) Command() Command {
return CommandGetChannelCipherSuites
}
func (req *GetChannelCipherSuitesRequest) Pack() []byte {
var msg = make([]byte, 3)
packUint8(req.ChannelNumber, msg, 0)
packUint8(uint8(req.PayloadType), msg, 1)
packUint8(LIST_ALGORITHMS_BY_CIPHER_SUITE|req.ListIndex, msg, 2)
return msg
}
func (res *GetChannelCipherSuitesResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
res.ChannelNumber, _, _ = unpackUint8(msg, 0)
if len(msg) > 1 {
res.CipherSuiteRecords, _, _ = unpackBytesMost(msg, 1, 16)
}
return nil
}
func (*GetChannelCipherSuitesResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetChannelCipherSuitesResponse) Format() string {
return fmt.Sprintf("%v", res)
}
// This command can be executed prior to establishing a session with the BMC.
// The command is used to look up what authentication, integrity, and confidentiality algorithms are supported.
// The algorithms are used in combination as 'Cipher Suites'.
// This command only applies to implementations that support IPMI v2.0/RMCP+ sessions.
func (c *Client) GetChannelCipherSuites(ctx context.Context, channelNumber uint8, index uint8) (response *GetChannelCipherSuitesResponse, err error) {
request := &GetChannelCipherSuitesRequest{
ChannelNumber: channelNumber,
PayloadType: PayloadTypeIPMI,
ListIndex: index,
}
response = &GetChannelCipherSuitesResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetAllChannelCipherSuites(ctx context.Context, channelNumber uint8) ([]CipherSuiteRecord, error) {
var index uint8 = 0
var cipherSuitesData = make([]byte, 0)
for ; index < MaxCipherSuiteListIndex; index++ {
res, err := c.GetChannelCipherSuites(ctx, channelNumber, index)
if err != nil {
return nil, fmt.Errorf("cmd GetChannelCipherSuites failed, err: %w", err)
}
cipherSuitesData = append(cipherSuitesData, res.CipherSuiteRecords...)
if len(res.CipherSuiteRecords) < 16 {
break
}
}
c.DebugBytes("cipherSuitesData", cipherSuitesData, 16)
return parseCipherSuitesData(cipherSuitesData)
}
func parseCipherSuitesData(cipherSuitesData []byte) ([]CipherSuiteRecord, error) {
offset := 0
records := []CipherSuiteRecord{}
for offset < len(cipherSuitesData) {
csRecord := CipherSuiteRecord{}
startOfRecord := cipherSuitesData[offset]
csRecord.StartOfRecord = startOfRecord
switch startOfRecord {
case StandardCipherSuite:
// id + 3 algs (4 bytes)
if offset+4 > len(cipherSuitesData)-1 {
return records, fmt.Errorf("incomplete cipher suite data")
}
offset++
csRecord.CipherSuitID = CipherSuiteID(cipherSuitesData[offset])
case OEMCipherSuite:
// id + iana (3) + 3 algs (7 bytes)
if offset+7 > len(cipherSuitesData)-1 {
return records, fmt.Errorf("incomplete cipher suite data")
}
offset++
csRecord.CipherSuitID = CipherSuiteID(cipherSuitesData[offset])
offset++
csRecord.OEMIanaID, _, _ = unpackUint24L(cipherSuitesData, offset)
default:
return records, fmt.Errorf("bad start of record byte in the cipher suite data, value %x", startOfRecord)
}
for {
offset++
if offset > len(cipherSuitesData)-1 {
break
}
algByte := cipherSuitesData[offset]
if algByte == StandardCipherSuite || algByte == OEMCipherSuite {
break
}
algTag := algByte & CipherAlgTagBitMask // clear lowest 6 bits
algNumber := algByte & CipherAlgMask // clear highest 2 bits
switch algTag {
case CipherAlgTagBitAuthMask:
csRecord.AuthAlg = algNumber
case CipherAlgTagBitIntegrityMask:
csRecord.IntegrityAlgs = append(csRecord.IntegrityAlgs, algNumber)
case CipherAlgTagBitEncryptionMask:
csRecord.CryptAlgs = append(csRecord.CryptAlgs, algNumber)
}
}
records = append(records, csRecord)
}
return records, nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_channel_info.go 0000664 0000000 0000000 00000005453 14741105271 0023551 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 22.24 Get Channel Info Command
type GetChannelInfoRequest struct {
ChannelNumber uint8
}
type GetChannelInfoResponse struct {
ActualChannelNumber uint8
ChannelMedium ChannelMedium // Channel Medium Type Numbers
ChannelProtocol ChannelProtocol // Channel Protocol Type Numbers
SessionSupport uint8
ActiveSessionCount uint8
VendorID uint32 // (IANA Enterprise Number) for OEM/Organization that specified the Channel Protocol.
// Auxiliary Channel Info
Auxiliary []byte // Auxiliary Channel Info Raw Data, 2 bytes
// For Channel = Fh (System Interface)
SMSInterruptType InterruptType
EventMessageBufferInterruptType InterruptType
}
type InterruptType uint8
func (typ InterruptType) String() string {
if typ <= 0x0f {
return fmt.Sprintf("IRQ %d", uint8(typ))
}
if typ >= 0x10 && typ <= 0x13 {
return fmt.Sprintf("PCI %X", uint8(typ))
}
if typ == 0x14 {
return "SMI"
}
if typ == 0x15 {
return "SCI"
}
if typ >= 20 && typ <= 0x5f {
return fmt.Sprintf("system interrupt %d", uint8(typ-32))
}
if typ == 0x60 {
return "assigned by ACPI / Plug in Play BIOS"
}
if typ == 0xff {
return "no interrupt"
}
return "reserved"
}
func (req *GetChannelInfoRequest) Pack() []byte {
return []byte{req.ChannelNumber}
}
func (req *GetChannelInfoRequest) Command() Command {
return CommandGetChannelInfo
}
func (res *GetChannelInfoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetChannelInfoResponse) Unpack(msg []byte) error {
if len(msg) < 9 {
return ErrUnpackedDataTooShortWith(len(msg), 9)
}
res.ActualChannelNumber, _, _ = unpackUint8(msg, 0)
cm, _, _ := unpackUint8(msg, 1)
res.ChannelMedium = ChannelMedium(cm)
cp, _, _ := unpackUint8(msg, 2)
res.ChannelProtocol = ChannelProtocol(cp)
s, _, _ := unpackUint8(msg, 3)
res.SessionSupport = s >> 6
res.ActiveSessionCount = s & 0x3f
res.VendorID, _, _ = unpackUint24L(msg, 4)
res.Auxiliary, _, _ = unpackBytes(msg, 7, 2)
res.SMSInterruptType = InterruptType(res.Auxiliary[0])
res.EventMessageBufferInterruptType = InterruptType(res.Auxiliary[1])
return nil
}
func (res *GetChannelInfoResponse) Format() string {
return fmt.Sprintf(`Channel %#02x info:
Channel Medium Type : %s
Channel Protocol Type : %s
Session Support : %d
Active Session Count : %d
Protocol Vendor ID : %d`,
res.ActualChannelNumber,
res.ChannelMedium,
res.ChannelProtocol,
res.SessionSupport,
res.ActiveSessionCount,
res.VendorID,
)
}
func (c *Client) GetChannelInfo(ctx context.Context, channelNumber uint8) (response *GetChannelInfoResponse, err error) {
request := &GetChannelInfoRequest{
ChannelNumber: channelNumber,
}
response = &GetChannelInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_chassis_capabilities.go 0000664 0000000 0000000 00000003500 14741105271 0025263 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 28.1 Get Chassis Capabilities Command
type GetChassisCapabilitiesRequest struct {
// empty
}
type GetChassisCapabilitiesResponse struct {
ProvidePowerInterlock bool
ProvideDiagnosticInterrupt bool
ProvideFrontPanelLockout bool
ProvideIntrusionSensor bool
// Chassis FRU Device
FRUDeviceAddress uint8
SDRDeviceAddress uint8
SELDeviceAddress uint8
SystemManagementDeviceAddress uint8
// If this field is not provided, the address is assumed to be the BMC address (20h).
BridgeDeviceAddress uint8
}
func (req *GetChassisCapabilitiesRequest) Pack() []byte {
return []byte{}
}
func (req *GetChassisCapabilitiesRequest) Command() Command {
return CommandGetChassisCapabilities
}
func (res *GetChassisCapabilitiesResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetChassisCapabilitiesResponse) Unpack(msg []byte) error {
if len(msg) < 5 {
return ErrUnpackedDataTooShortWith(len(msg), 5)
}
b1, _, _ := unpackUint8(msg, 0)
res.ProvidePowerInterlock = isBit3Set(b1)
res.ProvideDiagnosticInterrupt = isBit2Set(b1)
res.ProvideFrontPanelLockout = isBit1Set(b1)
res.ProvideIntrusionSensor = isBit0Set(b1)
res.FRUDeviceAddress, _, _ = unpackUint8(msg, 1)
res.SDRDeviceAddress, _, _ = unpackUint8(msg, 2)
res.SELDeviceAddress, _, _ = unpackUint8(msg, 3)
res.SystemManagementDeviceAddress, _, _ = unpackUint8(msg, 4)
if len(msg) == 6 {
res.BridgeDeviceAddress, _, _ = unpackUint8(msg, 5)
}
return nil
}
func (res *GetChassisCapabilitiesResponse) Format() string {
return "todo"
}
func (c *Client) GetChassisCapabilities(ctx context.Context) (response *GetChassisCapabilitiesResponse, err error) {
request := &GetChassisCapabilitiesRequest{}
response = &GetChassisCapabilitiesResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_chassis_status.go 0000664 0000000 0000000 00000014753 14741105271 0024171 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 28.2 Get Chassis Status Command
type GetChassisStatusRequest struct {
// empty
}
type GetChassisStatusResponse struct {
// Current Power State
PowerRestorePolicy PowerRestorePolicy
PowerControlFault bool // Controller attempted to turn system power on or off, but system did not enter desired state.
PowerFault bool // fault detected in main power subsystem
InterLock bool // chassis is presently shut down because a chassis panel interlock switch is active
PowerOverload bool // system shutdown because of power overload condition.
PowerIsOn bool // 系统电源:上电
// Last Power Event
LastPowerOnByCommand bool
LastPowerDownByPowerFault bool
LastPowerDownByPowerInterlockActivated bool
LastPowerDownByPowerOverload bool
ACFailed bool
// Last Power Event
// Misc. Chassis State
ChassisIdentifySupported bool
ChassisIdentifyState ChassisIdentifyState
CollingFanFault bool
DriveFault bool
FrontPanelLockoutActive bool // (power off and reset via chassis push-buttons disabled. 前面板锁定)
ChassisIntrusionActive bool // 机箱入侵:(机箱盖被打开)
// Front Panel Button Capabilities and disable/enable status (Optional)
SleepButtonDisableAllowed bool
DiagnosticButtonDisableAllowed bool
ResetButtonDisableAllowed bool
PoweroffButtonDisableAllowed bool
SleepButtonDisabled bool
DiagnosticButtonDisabled bool
ResetButtonDisabled bool
PoweroffButtonDisabled bool
}
type ChassisIdentifyState uint8
const (
ChassisIdentifyStateOff ChassisIdentifyState = 0
ChassisIdentifyStateTemporaryOn ChassisIdentifyState = 1
ChassisIdentifyStateIndefiniteOn ChassisIdentifyState = 2
)
func (c ChassisIdentifyState) String() string {
m := map[ChassisIdentifyState]string{
0: "Off",
1: "Temporary (timed) On",
2: "Indefinite On",
}
s, ok := m[c]
if ok {
return s
}
return "reserved"
}
// PowerRestorePolicy
// 通电开机策略
type PowerRestorePolicy uint8
const (
PowerRestorePolicyAlwaysOff PowerRestorePolicy = 0 // 保持下电(关机)
PowerRestorePolicyPrevious PowerRestorePolicy = 1 // 与之前保持一致(恢复断电前状态)
PowerRestorePolicyAlwaysOn PowerRestorePolicy = 2 // 保持上电(开机)
)
var SupportedPowerRestorePolicies = []string{
"always-off", "always-on", "previous",
}
func (p PowerRestorePolicy) String() string {
m := map[PowerRestorePolicy]string{
0: "always-off", // chassis stays powered off after AC/mains returns
1: "previous", // after AC returns, power is restored to the state that was in effect when AC/mains was lost
2: "always-on", // chassis always powers up after AC/mains returns
}
s, ok := m[p]
if ok {
return s
}
return "unknown"
}
func (req *GetChassisStatusRequest) Pack() []byte {
return []byte{}
}
func (req *GetChassisStatusRequest) Command() Command {
return CommandGetChassisStatus
}
func (res *GetChassisStatusResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetChassisStatusResponse) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
b1, _, _ := unpackUint8(msg, 0)
// first clear bit 7, then shift right 5 bits
b := (b1 & 0x7f) >> 5
res.PowerRestorePolicy = PowerRestorePolicy(b)
res.PowerControlFault = isBit4Set(b1)
res.PowerFault = isBit3Set(b1)
res.InterLock = isBit2Set(b1)
res.PowerOverload = isBit1Set(b1)
res.PowerIsOn = isBit0Set(b1)
b2, _, _ := unpackUint8(msg, 1)
res.LastPowerOnByCommand = isBit4Set(b2)
res.LastPowerDownByPowerFault = isBit3Set(b2)
res.LastPowerDownByPowerInterlockActivated = isBit2Set(b2)
res.LastPowerDownByPowerOverload = isBit1Set(b2)
res.ACFailed = isBit0Set(b2)
b3, _, _ := unpackUint8(msg, 2)
res.ChassisIdentifySupported = isBit6Set(b3)
res.ChassisIdentifyState = ChassisIdentifyState((b3 & 0x30) >> 4)
res.CollingFanFault = isBit3Set(b3)
res.DriveFault = isBit2Set(b3)
res.FrontPanelLockoutActive = isBit1Set(b3)
res.ChassisIntrusionActive = isBit0Set(b3)
if len(msg) == 4 {
b4, _, _ := unpackUint8(msg, 3)
res.SleepButtonDisableAllowed = isBit7Set(b4)
res.DiagnosticButtonDisableAllowed = isBit6Set(b4)
res.ResetButtonDisableAllowed = isBit5Set(b4)
res.PoweroffButtonDisableAllowed = isBit4Set(b4)
res.SleepButtonDisabled = isBit3Set(b4)
res.DiagnosticButtonDisabled = isBit2Set(b4)
res.ResetButtonDisabled = isBit1Set(b4)
res.PoweroffButtonDisabled = isBit0Set(b4)
}
return nil
}
func (res *GetChassisStatusResponse) Format() string {
return "System Power : " + formatBool(res.PowerIsOn, "on", "off") + "\n" +
"Power Overload : " + fmt.Sprintf("%v", res.PowerOverload) + "\n" +
"Power Interlock : " + formatBool(res.InterLock, "active", "inactive") + "\n" +
"Main Power Fault : " + fmt.Sprintf("%v", res.PowerFault) + "\n" +
"Power Control Fault : " + fmt.Sprintf("%v", res.PowerControlFault) + "\n" +
"Power Restore Policy : " + res.PowerRestorePolicy.String() + "\n" +
"Last Power Event : " + formatBool(res.ChassisIntrusionActive, "active", "inactive") + "\n" +
"Chassis Intrusion : " + formatBool(res.ChassisIntrusionActive, "active", "inactive") + "\n" +
"Front-Panel Lockout : " + formatBool(res.FrontPanelLockoutActive, "active", "inactive") + "\n" +
"Drive Fault : " + fmt.Sprintf("%v", res.DriveFault) + "\n" +
"Cooling/Fan Fault : " + fmt.Sprintf("%v", res.CollingFanFault) + "\n" +
"Sleep Button Disable : " + formatBool(res.SleepButtonDisableAllowed, "allowed", "disallowed") + "\n" +
"Diag Button Disable : " + formatBool(res.DiagnosticButtonDisableAllowed, "allowed", "disallowed") + "\n" +
"Reset Button Disable : " + formatBool(res.ResetButtonDisableAllowed, "allowed", "disallowed") + "\n" +
"Power Button Disable : " + formatBool(res.PoweroffButtonDisableAllowed, "allowed", "disallowed") + "\n" +
"Sleep Button Disabled: " + fmt.Sprintf("%v", res.SleepButtonDisabled) + "\n" +
"Diag Button Disabled : " + fmt.Sprintf("%v", res.DiagnosticButtonDisabled) + "\n" +
"Reset Button Disabled: " + fmt.Sprintf("%v", res.ResetButtonDisabled) + "\n" +
"Power Button Disabled: " + fmt.Sprintf("%v", res.PoweroffButtonDisabled)
}
func (c *Client) GetChassisStatus(ctx context.Context) (response *GetChassisStatusResponse, err error) {
request := &GetChassisStatusRequest{}
response = &GetChassisStatusResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_command_enables.go 0000664 0000000 0000000 00000003456 14741105271 0024236 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 21.8 Get Command Enables Command
type GetCommandEnablesRequest struct {
ChannelNumber uint8
CommandRangeMask CommandRangeMask
NetFn NetFn
LUN uint8
CodeForNetFn2C uint8
OEM_IANA uint32 // 3 bytes only
}
type GetCommandEnablesResponse struct {
// Todo
CommandEnableMask []byte
}
func (req *GetCommandEnablesRequest) Command() Command {
return CommandGetCommandEnables
}
func (req *GetCommandEnablesRequest) Pack() []byte {
out := make([]byte, 6)
packUint8(req.ChannelNumber, out, 0)
netfn := uint8(req.NetFn) & (uint8(req.CommandRangeMask) << 6)
packUint8(netfn, out, 1)
packUint8(req.LUN&0x03, out, 2)
if uint8(req.NetFn) == 0x2c {
packUint8(req.CodeForNetFn2C, out, 3)
return out[0:4]
}
if uint8(req.NetFn) == 0x2e {
packUint24L(req.OEM_IANA, out, 3)
return out[0:6]
}
return out[0:3]
}
func (res *GetCommandEnablesResponse) Unpack(msg []byte) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
res.CommandEnableMask, _, _ = unpackBytes(msg, 0, 16)
return nil
}
func (*GetCommandEnablesResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetCommandEnablesResponse) Format() string {
// Todo
return ""
}
func (c *Client) GetCommandEnables(ctx context.Context, channelNumber uint8, commandRangeMask CommandRangeMask, netFn NetFn, lun uint8, code uint8, oemIANA uint32) (response *GetCommandEnablesResponse, err error) {
request := &GetCommandEnablesRequest{
ChannelNumber: channelNumber,
CommandRangeMask: commandRangeMask,
NetFn: netFn,
LUN: lun,
CodeForNetFn2C: code,
OEM_IANA: oemIANA,
}
response = &GetCommandEnablesResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_command_subfunction_support.go 0000664 0000000 0000000 00000004205 14741105271 0026751 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 21.4 Get Command Sub-function Support Command
type GetCommandSubfunctionSupportRequest struct {
ChannelNumber uint8
NetFn NetFn
LUN uint8
Cmd uint8
CodeForNetFn2C uint8
OEM_IANA uint32 // 3 bytes only
}
type GetCommandSubfunctionSupportResponse struct {
SpecificationType uint8
ErrataVersion uint8
OEMGroupBody uint8
SpecificationVersion uint8
SpecificationRevision uint8
// Todo
SupportMask []byte
}
func (req *GetCommandSubfunctionSupportRequest) Command() Command {
return CommandGetCommandSubfunctionSupport
}
func (req *GetCommandSubfunctionSupportRequest) Pack() []byte {
out := make([]byte, 7)
packUint8(req.ChannelNumber, out, 0)
packUint8(uint8(req.NetFn)&0x3f, out, 1)
packUint8(req.LUN&0x03, out, 2)
packUint8(req.Cmd, out, 3)
if uint8(req.NetFn) == 0x2c {
packUint8(req.CodeForNetFn2C, out, 4)
return out[0:5]
}
if uint8(req.NetFn) == 0x2e {
packUint24L(req.OEM_IANA, out, 4)
return out[0:7]
}
return out[0:4]
}
func (res *GetCommandSubfunctionSupportResponse) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
b, _, _ := unpackUint8(msg, 0)
res.SpecificationType = b >> 4
res.ErrataVersion = b & 0x0f
res.OEMGroupBody = b
res.SpecificationVersion, _, _ = unpackUint8(msg, 1)
res.SpecificationRevision, _, _ = unpackUint8(msg, 2)
res.SupportMask, _, _ = unpackBytes(msg, 3, 4)
return nil
}
func (*GetCommandSubfunctionSupportResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetCommandSubfunctionSupportResponse) Format() string {
// Todo
return ""
}
func (c *Client) GetCommandSubfunctionSupport(ctx context.Context, channelNumber uint8, netFn NetFn, lun uint8, code uint8, oemIANA uint32) (response *GetCommandSubfunctionSupportResponse, err error) {
request := &GetCommandSubfunctionSupportRequest{
ChannelNumber: channelNumber,
NetFn: netFn,
LUN: lun,
CodeForNetFn2C: code,
OEM_IANA: oemIANA,
}
response = &GetCommandSubfunctionSupportResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_command_support.go 0000664 0000000 0000000 00000003636 14741105271 0024341 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 21.3 Get Command Support Command
type GetCommandSupportRequest struct {
ChannelNumber uint8
CommandRangeMask CommandRangeMask
NetFn NetFn
LUN uint8
CodeForNetFn2C uint8
OEM_IANA uint32 // 3 bytes only
}
type GetCommandSupportResponse struct {
// Todo
CommandSupportMask []byte
}
type CommandRangeMask uint8
const (
CommandRangeMask007F uint8 = 0x00
CommandRangeMask80FF uint8 = 0x01
)
func (req *GetCommandSupportRequest) Command() Command {
return CommandGetCommandSupport
}
func (req *GetCommandSupportRequest) Pack() []byte {
out := make([]byte, 6)
packUint8(req.ChannelNumber, out, 0)
netfn := uint8(req.NetFn) & (uint8(req.CommandRangeMask) << 6)
packUint8(netfn, out, 1)
packUint8(req.LUN&0x03, out, 2)
if uint8(req.NetFn) == 0x2c {
packUint8(req.CodeForNetFn2C, out, 3)
return out[0:4]
}
if uint8(req.NetFn) == 0x2e {
packUint24L(req.OEM_IANA, out, 3)
return out[0:6]
}
return out[0:3]
}
func (res *GetCommandSupportResponse) Unpack(msg []byte) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
res.CommandSupportMask, _, _ = unpackBytes(msg, 0, 16)
return nil
}
func (*GetCommandSupportResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetCommandSupportResponse) Format() string {
// Todo
return ""
}
func (c *Client) GetCommandSupport(ctx context.Context, channelNumber uint8, commandRangeMask CommandRangeMask, netFn NetFn, lun uint8, code uint8, oemIANA uint32) (response *GetCommandSupportResponse, err error) {
request := &GetCommandSupportRequest{
ChannelNumber: channelNumber,
CommandRangeMask: commandRangeMask,
NetFn: netFn,
LUN: lun,
CodeForNetFn2C: code,
OEM_IANA: oemIANA,
}
response = &GetCommandSupportResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_configurable_commands.go 0000664 0000000 0000000 00000003576 14741105271 0025453 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 21.5 Get Configurable Commands Command
type GetConfigurableCommandsRequest struct {
ChannelNumber uint8
CommandRangeMask CommandRangeMask
NetFn NetFn
LUN uint8
CodeForNetFn2C uint8
OEM_IANA uint32 // 3 bytes only
}
type GetConfigurableCommandsResponse struct {
// Todo
CommandSupportMask []byte
}
func (req *GetConfigurableCommandsRequest) Command() Command {
return CommandGetConfigurableCommands
}
func (req *GetConfigurableCommandsRequest) Pack() []byte {
out := make([]byte, 6)
packUint8(req.ChannelNumber, out, 0)
netfn := uint8(req.NetFn) & (uint8(req.CommandRangeMask) << 6)
packUint8(netfn, out, 1)
packUint8(req.LUN&0x03, out, 2)
if uint8(req.NetFn) == 0x2c {
packUint8(req.CodeForNetFn2C, out, 3)
return out[0:4]
}
if uint8(req.NetFn) == 0x2e {
packUint24L(req.OEM_IANA, out, 3)
return out[0:6]
}
return out[0:3]
}
func (res *GetConfigurableCommandsResponse) Unpack(msg []byte) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
res.CommandSupportMask, _, _ = unpackBytes(msg, 0, 16)
return nil
}
func (*GetConfigurableCommandsResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetConfigurableCommandsResponse) Format() string {
// Todo
return ""
}
func (c *Client) GetConfigurableCommands(ctx context.Context, channelNumber uint8, commandRangeMask CommandRangeMask, netFn NetFn, lun uint8, code uint8, oemIANA uint32) (response *GetConfigurableCommandsResponse, err error) {
request := &GetConfigurableCommandsRequest{
ChannelNumber: channelNumber,
CommandRangeMask: commandRangeMask,
NetFn: netFn,
LUN: lun,
CodeForNetFn2C: code,
OEM_IANA: oemIANA,
}
response = &GetConfigurableCommandsResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_dcmi_asset_tag.go 0000664 0000000 0000000 00000006440 14741105271 0024071 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// GetDCMIAssetTagRequest represents a "Get Asset Tag" request according
// to section 6.4.2 of the [DCMI specification v1.5].
//
// While the asset tag is allowed to be up to 64 bytes, each request will always
// return at most 16 bytes. The response also indicates the total length of the
// asset tag. If it is greater than 16 bytes, additional requests have to be
// performed, setting the offset accordingly.
//
// [DCMI specification v1.5]: https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/dcmi-v1-5-rev-spec.pdf
type GetDCMIAssetTagRequest struct {
Offset uint8
}
type GetDCMIAssetTagResponse struct {
// At most 16 bytes of the asset tag, starting from the request's offset
AssetTag []byte
// The total length of the asset tag
TotalLength uint8
}
func (req *GetDCMIAssetTagRequest) Pack() []byte {
// Number of bytes to read (16 bytes maximum)
// using the fixed (maximum) value is OK here.
var readBytes = uint8(0x10)
return []byte{GroupExtensionDCMI, req.Offset, readBytes}
}
func (req *GetDCMIAssetTagRequest) Command() Command {
return CommandGetDCMIAssetTag
}
func (res *GetDCMIAssetTagResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "Encoding type in FRU is binary / unspecified",
0x81: "Encoding type in FRU is BCD Plus",
0x82: "Encoding type in FRU is 6-bit ASCII Packed",
0x83: "Encoding type in FRU is set to ASCII+Latin1, but language code is not set to English (indicating data is 2-byte UNICODE)",
}
}
func (res *GetDCMIAssetTagResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
res.TotalLength, _, _ = unpackUint8(msg, 1)
if len(msg) > 2 {
res.AssetTag, _, _ = unpackBytesMost(msg, 2, 16)
}
return nil
}
func (res *GetDCMIAssetTagResponse) Format() string {
return fmt.Sprintf("%s (length: %d, total length: %d)", string(res.AssetTag), len(res.AssetTag), res.TotalLength)
}
// GetDCMIAssetTag sends a DCMI "Get Asset Tag" command.
// See [GetDCMIAssetTagRequest] for details.
func (c *Client) GetDCMIAssetTag(ctx context.Context, offset uint8) (response *GetDCMIAssetTagResponse, err error) {
request := &GetDCMIAssetTagRequest{Offset: offset}
response = &GetDCMIAssetTagResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetDCMIAssetTagFull(ctx context.Context) (assetTagRaw []byte, typeLength TypeLength, err error) {
assetTagRaw = make([]byte, 0)
typeCode := uint8(0)
offset := uint8(0)
for {
resp, err := c.GetDCMIAssetTag(ctx, offset)
if err != nil {
if err, ok := err.(*ResponseError); ok {
cc := uint8(err.CompletionCode())
switch cc {
// align the completion code with the FRU Type Length Byte Format
case 0x80:
typeCode = 0b00
case 0x81:
typeCode = 0b01
case 0x82:
typeCode = 0x10
case 0x83:
typeCode = 0x11
default:
return nil, 0, fmt.Errorf("GetDCMIAssetTag failed, err: %w", err)
}
}
}
assetTagRaw = append(assetTagRaw, resp.AssetTag...)
if resp.TotalLength <= offset+uint8(len(resp.AssetTag)) {
break
}
offset += uint8(len(resp.AssetTag))
}
typeLength = TypeLength(typeCode<<6 | uint8(len(assetTagRaw)))
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_dcmi_cap_param.go 0000664 0000000 0000000 00000011137 14741105271 0024041 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// GetDCMICapParamRequest provides version information for DCMI and information about
// the mandatory and optional DCMI capabilities that are available on the particular platform.
//
// The command is session-less and can be called similar to the Get Authentication Capability command.
// This command is a bare-metal provisioning command, and the availability of features does not imply
// the features are configured.
//
// [DCMI specification v1.5] 6.1.1 Get DCMI Capabilities Info Command
type GetDCMICapParamRequest struct {
ParamSelector DCMICapParamSelector
}
type GetDCMICapParamResponse struct {
MajorVersion uint8
MinorVersion uint8
ParamRevision uint8
ParamData []byte
}
func (req *GetDCMICapParamRequest) Pack() []byte {
return []byte{GroupExtensionDCMI, byte(req.ParamSelector)}
}
func (req *GetDCMICapParamRequest) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
req.ParamSelector = DCMICapParamSelector(msg[1])
return nil
}
func (req *GetDCMICapParamRequest) Command() Command {
return CommandGetDCMICapParam
}
func (res *GetDCMICapParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetDCMICapParamResponse) Pack() []byte {
out := make([]byte, 4+len(res.ParamData))
out[0] = GroupExtensionDCMI
out[1] = res.MajorVersion
out[2] = res.MinorVersion
out[3] = res.ParamRevision
copy(out[4:], res.ParamData)
return out
}
func (res *GetDCMICapParamResponse) Unpack(msg []byte) error {
if len(msg) < 5 {
return ErrUnpackedDataTooShortWith(len(msg), 5)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
res.MajorVersion, _, _ = unpackUint8(msg, 1)
res.MinorVersion, _, _ = unpackUint8(msg, 2)
res.ParamRevision, _, _ = unpackUint8(msg, 3)
res.ParamData, _, _ = unpackBytes(msg, 4, len(msg)-4)
return nil
}
func (res *GetDCMICapParamResponse) Format() string {
return fmt.Sprintf(`
Major version : %d
Minor version : %d
Param revision : %d
Param data : %v`,
res.MajorVersion,
res.MinorVersion,
res.ParamRevision,
res.ParamData,
)
}
func (c *Client) GetDCMICapParam(ctx context.Context, paramSelector DCMICapParamSelector) (response *GetDCMICapParamResponse, err error) {
request := &GetDCMICapParamRequest{ParamSelector: paramSelector}
response = &GetDCMICapParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetDCMICapParamFor(ctx context.Context, param DCMICapParameter) error {
if isNilDCMICapParameter(param) {
return nil
}
paramSelector := param.DCMICapParameter()
request := &GetDCMICapParamRequest{ParamSelector: paramSelector}
response := &GetDCMICapParamResponse{}
if err := c.Exchange(ctx, request, response); err != nil {
return err
}
if err := param.Unpack(response.ParamData); err != nil {
return fmt.Errorf("unpack param data failed, err: %w", err)
}
return nil
}
func (c *Client) GetDCMICapParams(ctx context.Context) (*DCMICapParams, error) {
dcmiCapParams := &DCMICapParams{
SupportedDCMICapabilities: &DCMICapParam_SupportedDCMICapabilities{},
MandatoryPlatformAttributes: &DCMICapParam_MandatoryPlatformAttributes{},
OptionalPlatformAttributes: &DCMICapParam_OptionalPlatformAttributes{},
ManageabilityAccessAttributes: &DCMICapParam_ManageabilityAccessAttributes{},
EnhancedSystemPowerStatisticsAttributes: &DCMICapParam_EnhancedSystemPowerStatisticsAttributes{},
}
if err := c.GetDCMICapParamsFor(ctx, dcmiCapParams); err != nil {
return nil, err
}
return dcmiCapParams, nil
}
func (c *Client) GetDCMICapParamsFor(ctx context.Context, dcmiCapParams *DCMICapParams) error {
if dcmiCapParams == nil {
return nil
}
if dcmiCapParams.SupportedDCMICapabilities != nil {
if err := c.GetDCMICapParamFor(ctx, dcmiCapParams.SupportedDCMICapabilities); err != nil {
return err
}
}
if dcmiCapParams.MandatoryPlatformAttributes != nil {
if err := c.GetDCMICapParamFor(ctx, dcmiCapParams.MandatoryPlatformAttributes); err != nil {
return err
}
}
if dcmiCapParams.OptionalPlatformAttributes != nil {
if err := c.GetDCMICapParamFor(ctx, dcmiCapParams.OptionalPlatformAttributes); err != nil {
return err
}
}
if dcmiCapParams.ManageabilityAccessAttributes != nil {
if err := c.GetDCMICapParamFor(ctx, dcmiCapParams.ManageabilityAccessAttributes); err != nil {
return err
}
}
if dcmiCapParams.EnhancedSystemPowerStatisticsAttributes != nil {
if err := c.GetDCMICapParamFor(ctx, dcmiCapParams.EnhancedSystemPowerStatisticsAttributes); err != nil {
return err
}
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_dcmi_config_params.go 0000664 0000000 0000000 00000007313 14741105271 0024727 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// [DCMI specification v1.5] 6.1.3 Get DCMI Configuration Parameters Command
type GetDCMIConfigParamRequest struct {
ParamSelector DCMIConfigParamSelector
SetSelector uint8 // use 00h for parameters that only have one set
}
type GetDCMIConfigParamResponse struct {
MajorVersion uint8
MinorVersion uint8
ParamRevision uint8
ParamData []byte
}
func (req *GetDCMIConfigParamRequest) Pack() []byte {
out := make([]byte, 3)
packUint8(GroupExtensionDCMI, out, 0)
packUint8(uint8(req.ParamSelector), out, 1)
packUint8(req.SetSelector, out, 2)
return out
}
func (req *GetDCMIConfigParamRequest) Command() Command {
return CommandGetDCMIConfigParam
}
func (res *GetDCMIConfigParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetDCMIConfigParamResponse) Unpack(msg []byte) error {
if len(msg) < 5 {
return ErrUnpackedDataTooShortWith(len(msg), 5)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
res.MajorVersion, _, _ = unpackUint8(msg, 1)
res.MinorVersion, _, _ = unpackUint8(msg, 2)
res.ParamRevision, _, _ = unpackUint8(msg, 3)
res.ParamData, _, _ = unpackBytes(msg, 4, len(msg)-4)
return nil
}
func (res *GetDCMIConfigParamResponse) Format() string {
return ""
}
func (c *Client) GetDCMIConfigParam(ctx context.Context, paramSelector DCMIConfigParamSelector, setSelector uint8) (response *GetDCMIConfigParamResponse, err error) {
request := &GetDCMIConfigParamRequest{
ParamSelector: paramSelector,
SetSelector: setSelector,
}
response = &GetDCMIConfigParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetDCMIConfigParamFor(ctx context.Context, param DCMIConfigParameter) error {
if isNilDCMIConfigParameter(param) {
return nil
}
paramSelector, setSelector := param.DCMIConfigParameter()
request := &GetDCMIConfigParamRequest{ParamSelector: paramSelector, SetSelector: setSelector}
response := &GetDCMIConfigParamResponse{}
if err := c.Exchange(ctx, request, response); err != nil {
return err
}
if err := param.Unpack(response.ParamData); err != nil {
return fmt.Errorf("unpack param (%s[%d]) failed, err: %w", paramSelector.String(), paramSelector, err)
}
return nil
}
func (c *Client) GetDCMIConfigParams(ctx context.Context) (*DCMIConfigParams, error) {
dcmiConfigParams := &DCMIConfigParams{
ActivateDHCP: &DCMIConfigParam_ActivateDHCP{},
DiscoveryConfiguration: &DCMIConfigParam_DiscoveryConfiguration{},
DHCPTiming1: &DCMIConfigParam_DHCPTiming1{},
DHCPTiming2: &DCMIConfigParam_DHCPTiming2{},
DHCPTiming3: &DCMIConfigParam_DHCPTiming3{},
}
if err := c.GetDCMIConfigParamsFor(ctx, dcmiConfigParams); err != nil {
return nil, err
}
return dcmiConfigParams, nil
}
func (c *Client) GetDCMIConfigParamsFor(ctx context.Context, dcmiConfigParams *DCMIConfigParams) error {
if dcmiConfigParams == nil {
return nil
}
if dcmiConfigParams.ActivateDHCP != nil {
if err := c.GetDCMIConfigParamFor(ctx, dcmiConfigParams.ActivateDHCP); err != nil {
return err
}
}
if dcmiConfigParams.DiscoveryConfiguration != nil {
if err := c.GetDCMIConfigParamFor(ctx, dcmiConfigParams.DiscoveryConfiguration); err != nil {
return err
}
}
if dcmiConfigParams.DHCPTiming1 != nil {
if err := c.GetDCMIConfigParamFor(ctx, dcmiConfigParams.DHCPTiming1); err != nil {
return err
}
}
if dcmiConfigParams.DHCPTiming2 != nil {
if err := c.GetDCMIConfigParamFor(ctx, dcmiConfigParams.DHCPTiming2); err != nil {
return err
}
}
if dcmiConfigParams.DHCPTiming3 != nil {
if err := c.GetDCMIConfigParamFor(ctx, dcmiConfigParams.DHCPTiming3); err != nil {
return err
}
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_dcmi_mgmt_controller_identifier.go 0000664 0000000 0000000 00000004662 14741105271 0027534 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// [DCMI specification v1.5]: 6.4.6.1 Get Management Controller Identifier String Command
type GetDCMIMgmtControllerIdentifierRequest struct {
Offset uint8
}
type GetDCMIMgmtControllerIdentifierResponse struct {
// ID String Length Count of non-null characters starting from offset 0 up to the first null.
// Note: The Maximum length of the Identifier String is specified as 64 bytes including the null character,
// therefore the range for this return is 0-63.
IDStrLength uint8
IDStr []byte
}
func (req *GetDCMIMgmtControllerIdentifierRequest) Pack() []byte {
// Number of bytes to read (16 bytes maximum)
// using the fixed (maximum) value is OK here.
var readBytes = uint8(0x10)
return []byte{GroupExtensionDCMI, req.Offset, readBytes}
}
func (req *GetDCMIMgmtControllerIdentifierRequest) Command() Command {
return CommandGetDCMIMgmtControllerIdentifier
}
func (res *GetDCMIMgmtControllerIdentifierResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetDCMIMgmtControllerIdentifierResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
res.IDStrLength = msg[1]
res.IDStr, _, _ = unpackBytes(msg, 2, len(msg)-2)
return nil
}
func (res *GetDCMIMgmtControllerIdentifierResponse) Format() string {
return fmt.Sprintf("[%s] (returned length: %d,total length: %d)", string(res.IDStr), len(res.IDStr), res.IDStrLength)
}
// GetDCMIMgmtControllerIdentifier sends a DCMI "Get Asset Tag" command.
// See [GetDCMIMgmtControllerIdentifierRequest] for details.
func (c *Client) GetDCMIMgmtControllerIdentifier(ctx context.Context, offset uint8) (response *GetDCMIMgmtControllerIdentifierResponse, err error) {
request := &GetDCMIMgmtControllerIdentifierRequest{Offset: offset}
response = &GetDCMIMgmtControllerIdentifierResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetDCMIMgmtControllerIdentifierFull(ctx context.Context) ([]byte, error) {
id := make([]byte, 0)
offset := uint8(0)
for {
resp, err := c.GetDCMIMgmtControllerIdentifier(ctx, offset)
if err != nil {
return nil, fmt.Errorf("GetDCMIMgmtControllerIdentifier failed, err: %w", err)
}
id = append(id, resp.IDStr...)
if resp.IDStrLength <= offset+uint8(len(resp.IDStr)) {
break
}
offset += uint8(len(resp.IDStr))
}
return id, nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_dcmi_power_limit.go 0000664 0000000 0000000 00000004262 14741105271 0024451 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// [DCMI specification v1.5]: 6.6.2 Get Power Limit
type GetDCMIPowerLimitRequest struct {
}
type GetDCMIPowerLimitResponse struct {
ExceptionAction DCMIExceptionAction
// Power Limit Requested in Watts
PowerLimitRequested uint16
// Maximum time taken to limit the power after the platform power has reached
// the power limit before the Exception Action will be taken.
CorrectionTimeLimitMilliSec uint32
// Management application Statistics Sampling period in seconds
StatisticsSamplingPeriodSec uint16
}
func (req *GetDCMIPowerLimitRequest) Pack() []byte {
return []byte{GroupExtensionDCMI, 0x00, 0x00}
}
func (req *GetDCMIPowerLimitRequest) Command() Command {
return CommandGetDCMIPowerLimit
}
func (res *GetDCMIPowerLimitResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "No Active Set Power Limit",
}
}
func (res *GetDCMIPowerLimitResponse) Unpack(msg []byte) error {
if len(msg) < 14 {
return ErrUnpackedDataTooShortWith(len(msg), 14)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
exceptionAction, _, _ := unpackUint8(msg, 3)
res.ExceptionAction = DCMIExceptionAction(exceptionAction)
res.PowerLimitRequested, _, _ = unpackUint16L(msg, 4)
res.CorrectionTimeLimitMilliSec, _, _ = unpackUint32L(msg, 6)
res.StatisticsSamplingPeriodSec, _, _ = unpackUint16L(msg, 12)
return nil
}
func (res *GetDCMIPowerLimitResponse) Format() string {
return "Power limit exception action : " + res.ExceptionAction.String() + "\n" +
"Power limit requested : " + fmt.Sprintf("%d", res.PowerLimitRequested) + " Watts\n" +
"Correction Time Limit : " + fmt.Sprintf("%d", res.CorrectionTimeLimitMilliSec) + " Milliseconds\n" +
"Statistics Sampling period : " + fmt.Sprintf("%d", res.StatisticsSamplingPeriodSec) + " Seconds\n"
}
// GetDCMIPowerLimit sends a DCMI "Get Power Reading" command.
// See [GetDCMIPowerLimitRequest] for details.
func (c *Client) GetDCMIPowerLimit(ctx context.Context) (response *GetDCMIPowerLimitResponse, err error) {
request := &GetDCMIPowerLimitRequest{}
response = &GetDCMIPowerLimitResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_dcmi_power_reading.go 0000664 0000000 0000000 00000007077 14741105271 0024753 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"time"
)
// GetDCMIPowerReadingRequest represents a "Get Power Reading" request according
// to section 6.6.1 of the [DCMI specification v1.5].
//
// Currently, only the basic "System Power Statistics" mode is supported, not
// the extended mode.
//
// [DCMI specification v1.5]: https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/dcmi-v1-5-rev-spec.pdf
type GetDCMIPowerReadingRequest struct {
// TODO add support for extended mode...
}
// GetDCMIPowerReadingResponse represents a response to a [GetDCMIPowerReadingRequest].
type GetDCMIPowerReadingResponse struct {
// Current Power in watts
CurrentPower uint16
// Minimum Power over sampling duration in watts
MinimumPower uint16
// Maximum Power over sampling duration in watts
MaximumPower uint16
// Average Power over sampling duration in watts
AveragePower uint16
// IPMI Specification based Time Stamp
//
// For Mode 02h (not yet supported), the time stamp specifies the end of the
// averaging window.
Timestamp uint32
// Statistics reporting time period
//
// For Mode 01h, time-frame in milliseconds, over which the controller
// collects statistics. For Mode 02h (not yet supported), time-frame reflects
// the Averaging Time period in units.
ReportingPeriod uint32
// True if power measurements are available, false otherwise.
PowerMeasurementActive bool
}
func (req *GetDCMIPowerReadingRequest) Pack() []byte {
// second byte 0x01 = "basic" System Power Statistics
return []byte{GroupExtensionDCMI, 0x01, 0x00, 0x00}
}
func (req *GetDCMIPowerReadingRequest) Command() Command {
return CommandGetDCMIPowerReading
}
func (res *GetDCMIPowerReadingResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetDCMIPowerReadingResponse) Unpack(msg []byte) error {
if len(msg) < 18 {
return ErrUnpackedDataTooShortWith(len(msg), 19)
}
var off int
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
res.CurrentPower, off, _ = unpackUint16L(msg, 1)
res.MinimumPower, off, _ = unpackUint16L(msg, off)
res.MaximumPower, off, _ = unpackUint16L(msg, off)
res.AveragePower, off, _ = unpackUint16L(msg, off)
res.Timestamp, off, _ = unpackUint32L(msg, off)
res.ReportingPeriod, off, _ = unpackUint32L(msg, off)
state, _, _ := unpackUint8(msg, off)
res.PowerMeasurementActive = isBit6Set(state)
return nil
}
func (res *GetDCMIPowerReadingResponse) Format() string {
ts := time.Unix(int64(res.Timestamp), 0)
return "Instantaneous power reading: " + fmt.Sprintf("%5d", res.CurrentPower) + " Watts\n" +
"Minimum during sampling period: " + fmt.Sprintf("%5d", res.MinimumPower) + " Watts\n" +
"Maximum during sampling period: " + fmt.Sprintf("%5d", res.MaximumPower) + " Watts\n" +
"Average power reading over sample period: " + fmt.Sprintf("%5d", res.CurrentPower) + " Watts\n" +
"IPMI timestamp: " + ts.Format("01/02/06 15:04:05 UTC") + "\n" +
"Sampling period: " + fmt.Sprintf("%08d", res.ReportingPeriod/1000) + " Seconds\n" +
"Power reading state is: " + formatBool(res.PowerMeasurementActive, "activated", "deactivated")
}
// GetDCMIPowerReading sends a DCMI "Get Power Reading" command.
// See [GetDCMIPowerReadingRequest] for details.
func (c *Client) GetDCMIPowerReading(ctx context.Context) (response *GetDCMIPowerReadingResponse, err error) {
request := &GetDCMIPowerReadingRequest{}
response = &GetDCMIPowerReadingResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_dcmi_sensor_info.go 0000664 0000000 0000000 00000005540 14741105271 0024443 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// [DCMI specification v1.5]: 6.5.2 Get DCMI Sensor Info Command
type GetDCMISensorInfoRequest struct {
SensorType SensorType
EntityID EntityID
// 00h Retrieve information about all instances associated with Entity ID
// 01h - FFh Retrieve only the information about particular instance.
EntityInstance EntityInstance
EntityInstanceStart uint8
}
type GetDCMISensorInfoResponse struct {
TotalEntityInstances uint8
RecordsCount uint8
SDRRecordID []uint16
}
func (req *GetDCMISensorInfoRequest) Pack() []byte {
out := make([]byte, 5)
packUint8(GroupExtensionDCMI, out, 0)
packUint8(uint8(req.SensorType), out, 1)
packUint8(byte(req.EntityID), out, 2)
packUint8(byte(req.EntityInstance), out, 3)
packUint8(req.EntityInstanceStart, out, 4)
return out
}
func (req *GetDCMISensorInfoRequest) Command() Command {
return CommandGetDCMISensorInfo
}
func (res *GetDCMISensorInfoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetDCMISensorInfoResponse) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
res.TotalEntityInstances = msg[1]
res.RecordsCount = msg[2]
if len(msg) < 3+int(res.RecordsCount)*2 {
return ErrUnpackedDataTooShortWith(len(msg), 3+int(res.RecordsCount)*2)
}
res.SDRRecordID = make([]uint16, res.RecordsCount)
for i := 0; i < int(res.RecordsCount); i++ {
res.SDRRecordID[i], _, _ = unpackUint16L(msg, 3+i*2)
}
return nil
}
func (res *GetDCMISensorInfoResponse) Format() string {
return fmt.Sprintf(`
Total entity instances: %d
Number of records: %d
SDR Record ID: %v
`,
res.TotalEntityInstances,
res.RecordsCount,
res.SDRRecordID,
)
}
// GetDCMISensorInfo sends a DCMI "Get Power Reading" command.
// See [GetDCMISensorInfoRequest] for details.
func (c *Client) GetDCMISensorInfo(ctx context.Context, request *GetDCMISensorInfoRequest) (response *GetDCMISensorInfoResponse, err error) {
response = &GetDCMISensorInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetDCMISensors(ctx context.Context, entityIDs ...EntityID) ([]*SDR, error) {
out := make([]*SDR, 0)
for _, entityID := range entityIDs {
request := &GetDCMISensorInfoRequest{
SensorType: SensorTypeTemperature,
EntityID: entityID,
EntityInstance: 0x00,
EntityInstanceStart: 0,
}
response := &GetDCMISensorInfoResponse{}
if err := c.Exchange(ctx, request, response); err != nil {
return nil, err
}
for _, recordID := range response.SDRRecordID {
sdr, err := c.GetSDREnhanced(ctx, recordID)
if err != nil {
return nil, fmt.Errorf("GetSDRDetail failed for recordID (%#02x), err: %s", recordID, err)
}
out = append(out, sdr)
}
}
return out, nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_dcmi_temperature_readings.go 0000664 0000000 0000000 00000007412 14741105271 0026330 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"context"
"fmt"
"github.com/olekukonko/tablewriter"
)
// [DCMI specification v1.5]: 6.7.3 Get Temperature Readings Command
type GetDCMITemperatureReadingsRequest struct {
SensorType SensorType
EntityID EntityID
EntityInstance EntityInstance
EntityInstanceStart uint8
}
type GetDCMITemperatureReadingsResponse struct {
entityID EntityID
TotalEntityInstances uint8
TemperatureReadingsCount uint8
TemperatureReadings []DCMITemperatureReading
}
type DCMITemperatureReading struct {
TemperatureReading int8
EntityInstance EntityInstance
EntityID EntityID
}
func (req *GetDCMITemperatureReadingsRequest) Pack() []byte {
return []byte{GroupExtensionDCMI, byte(req.SensorType), byte(req.EntityID), byte(req.EntityInstance), req.EntityInstanceStart}
}
func (req *GetDCMITemperatureReadingsRequest) Command() Command {
return CommandGetDCMITemperatureReadings
}
func (res *GetDCMITemperatureReadingsResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "No Active Set Power Limit",
}
}
func (res *GetDCMITemperatureReadingsResponse) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
res.TotalEntityInstances = msg[1]
res.TemperatureReadingsCount = msg[2]
if len(msg) < 3+int(res.TemperatureReadingsCount)*2 {
return ErrUnpackedDataTooShortWith(len(msg), 3+int(res.TemperatureReadingsCount)*2)
}
tempReadings := make([]DCMITemperatureReading, 0)
for i := 0; i < int(res.TemperatureReadingsCount); i++ {
r := DCMITemperatureReading{}
v := msg[3+i*2]
r.TemperatureReading = int8(v)
r.EntityInstance = EntityInstance(msg[3+i*2+1])
r.EntityID = res.entityID
tempReadings = append(tempReadings, r)
}
res.TemperatureReadings = tempReadings
return nil
}
func (res *GetDCMITemperatureReadingsResponse) Format() string {
return fmt.Sprintf(`Total entity instances: %d
Number of temperature readings: %d
Temperature Readings: %v`,
res.TotalEntityInstances,
res.TemperatureReadingsCount,
res.TemperatureReadings)
}
func (c *Client) GetDCMITemperatureReadings(ctx context.Context, request *GetDCMITemperatureReadingsRequest) (response *GetDCMITemperatureReadingsResponse, err error) {
response = &GetDCMITemperatureReadingsResponse{
entityID: request.EntityID,
}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetDCMITemperatureReadingsForEntities(ctx context.Context, entityIDs ...EntityID) ([]DCMITemperatureReading, error) {
out := make([]DCMITemperatureReading, 0)
for _, entityID := range entityIDs {
request := &GetDCMITemperatureReadingsRequest{
SensorType: SensorTypeTemperature,
EntityID: entityID,
EntityInstance: 0x00,
EntityInstanceStart: 0,
}
response, err := c.GetDCMITemperatureReadings(ctx, request)
if err != nil {
return nil, fmt.Errorf("GetDCMITemperatureReadings failed for entityID (%#02x), err: %s", entityID, err)
}
out = append(out, response.TemperatureReadings...)
}
return out, nil
}
func FormatDCMITemperatureReadings(readings []DCMITemperatureReading) string {
var buf = new(bytes.Buffer)
table := tablewriter.NewWriter(buf)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_RIGHT)
headers := []string{
"Entity ID",
"Entity Instance",
"Temp. Readings",
}
table.SetHeader(headers)
table.SetFooter(headers)
for _, reading := range readings {
rowContent := []string{
fmt.Sprintf("%s(%#02x)", reading.EntityID.String(), uint8(reading.EntityID)),
fmt.Sprintf("%d", reading.EntityInstance),
fmt.Sprintf("%+d C", reading.TemperatureReading),
}
table.Append(rowContent)
}
table.Render()
return buf.String()
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_dcmi_thermal_limit.go 0000664 0000000 0000000 00000005513 14741105271 0024751 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"errors"
"fmt"
)
// [DCMI specification v1.5]: 6.7.1 Get Thermal Limit Command
type GetDCMIThermalLimitRequest struct {
EntityID EntityID // Entity ID = 37h or 40h (Inlet Temperature)
EntityInstance EntityInstance
}
type GetDCMIThermalLimitResponse struct {
ExceptionAction_PowerOffAndLogSEL bool
ExceptionAction_LogSELOnly bool // ignored if ExceptionAction_PowerOffAndLogSEL is true
// Temperature Limit set in units defined by the SDR record.
// Note: the management controller is not required to check this parameter for validity against the SDR contents.
TemperatureLimit uint8
// Interval in seconds over which the temperature must continuously be sampled as exceeding the set limit
// before the specified Exception Action will be taken.
// Samples are taken at the rate specified by the sampling frequency value in parameter #5 of the DCMI Capabilities // parameters (see Table 6-3, DCMI Capabilities Parameters).
ExceptionTimeSec uint16
}
func (req *GetDCMIThermalLimitRequest) Pack() []byte {
return []byte{GroupExtensionDCMI, byte(req.EntityID), byte(req.EntityInstance)}
}
func (req *GetDCMIThermalLimitRequest) Command() Command {
return CommandGetDCMIThermalLimit
}
func (res *GetDCMIThermalLimitResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetDCMIThermalLimitResponse) Unpack(msg []byte) error {
if len(msg) < 5 {
return ErrUnpackedDataTooShortWith(len(msg), 5)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
b1, _, _ := unpackUint8(msg, 1)
res.ExceptionAction_PowerOffAndLogSEL = isBit6Set(b1)
res.ExceptionAction_LogSELOnly = isBit5Set(b1)
res.TemperatureLimit, _, _ = unpackUint8(msg, 2)
res.ExceptionTimeSec, _, _ = unpackUint16L(msg, 3)
return nil
}
func (res *GetDCMIThermalLimitResponse) Format() string {
return fmt.Sprintf(`
Exception Actions, taken if the Temperature Limit exceeded:
Hard Power Off system and log event: %s
Log event to SEL only: %s
Temperature Limit %d degrees
Exception Time %d seconds`,
formatBool(res.ExceptionAction_PowerOffAndLogSEL, "active", "inactive"),
formatBool(res.ExceptionAction_LogSELOnly, "active", "inactive"),
res.TemperatureLimit,
res.ExceptionTimeSec)
}
func (c *Client) GetDCMIThermalLimit(ctx context.Context, entityID EntityID, entityInstance EntityInstance) (response *GetDCMIThermalLimitResponse, err error) {
if uint8(entityID) != 0x37 && uint8(entityID) != 0x40 {
return nil, errors.New("only Inlet Temperature entityID (0x37 or 0x40) is supported")
}
request := &GetDCMIThermalLimitRequest{
EntityID: entityID,
EntityInstance: entityInstance,
}
response = &GetDCMIThermalLimitResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_device_guid.go 0000664 0000000 0000000 00000002140 14741105271 0023363 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 20.8 Get Device GUID Command
type GetDeviceGUIDRequest struct {
// empty
}
type GetDeviceGUIDResponse struct {
GUID [16]byte
}
func (req *GetDeviceGUIDRequest) Command() Command {
return CommandGetDeviceGUID
}
func (req *GetDeviceGUIDRequest) Pack() []byte {
return []byte{}
}
func (res *GetDeviceGUIDResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetDeviceGUIDResponse) Unpack(msg []byte) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
guid, _, _ := unpackBytes(msg, 0, 16)
res.GUID = array16(guid)
return nil
}
func (res *GetDeviceGUIDResponse) Format() string {
guidMode := GUIDModeSMBIOS
u, err := ParseGUID(res.GUID[:], guidMode)
if err != nil {
return fmt.Sprintf(" (%s)", err)
}
return fmt.Sprintf("GUID: %s", u.String())
}
func (c *Client) GetDeviceGUID(ctx context.Context) (response *GetDeviceGUIDResponse, err error) {
request := &GetDeviceGUIDRequest{}
response = &GetDeviceGUIDResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_device_id.go 0000664 0000000 0000000 00000016151 14741105271 0023036 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"strings"
)
// 20.1 Get Device ID Command
type GetDeviceIDRequest struct {
// empty
}
type GetDeviceIDResponse struct {
DeviceID uint8
// [7] 1 = device provides Device SDRs
// 0 = device does not provide Device SDRs
// [6:4] reserved. Return as 0.
ProvideDeviceSDRs bool
// [3:0] Device Revision, binary encoded
DeviceRevision uint8
// [7] Device available: 0=normal operation, 1= device firmware, SDR
// Repository update or self-initialization in progress. [Firmware / SDR
// Repository updates can be differentiated by issuing a Get SDR
// command and checking the completion code.]
DeviceAvailable bool
// [6:0] Major Firmware Revision, binary encoded
MajorFirmwareRevision uint8
// BCD encoded
MinorFirmwareRevision uint8
// Holds IPMI Command Specification Version. BCD encoded.
// 00h = reserved.
// Bits 7:4 hold the Least Significant digit of the revision, while
// bits 3:0 hold the Most Significant bits.
// E.g. a value of 51h indicates revision 1.5 functionality.
// 02h for implementations that provide IPMI v2.0 capabilities
// per this specification.
MajorIPMIVersion uint8
MinorIPMIVersion uint8
AdditionalDeviceSupport
// Manufacturer ID, LS Byte first. The manufacturer ID is a 20-bit value that is
// derived from the IANA Private Enterprise ID (see below).
// Most significant four bits = reserved (0000b).
// 000000h = unspecified. 0FFFFFh = reserved. This value is binary encoded.
// E.g. the ID for the IPMI forum is 7154 decimal, which is 1BF2h, which would
// be stored in this record as F2h, 1Bh, 00h for bytes 8 through 10, respectively
ManufacturerID uint32 // only 3 bytes used
// Product ID, LS Byte first. This field can be used to provide a number that
// identifies a particular system, module, add-in card, or board set. The number
// is specified according to the manufacturer given by Manufacturer ID (see
// below).
// 0000h = unspecified. FFFFh = reserved.
ProductID uint16
// Auxiliary Firmware Revision Information. This field is optional. If present, it
// holds additional information about the firmware revision, such as boot block or
// internal data structure version numbers. The meanings of the numbers are
// specific to the vendor identified by Manufacturer ID (see below). When the
// vendor-specific definition is not known, generic utilities should display each
// byte as 2-digit hexadecimal numbers, with byte 13 displayed first as the most-significant byte.
AuxiliaryFirmwareRevision []byte // 4 bytes
}
// Additional Device Support (formerly called IPM Device Support). Lists the
// IPMI 'logical device' commands and functions that the controller supports that
// are in addition to the mandatory IPM and Application commands.
// [7] Chassis Device (device functions as chassis device per ICMB spec.)
// [6] Bridge (device responds to Bridge NetFn commands)
// [5] IPMB Event Generator (device generates event messages [platform
// event request messages] onto the IPMB)
// [4] IPMB Event Receiver (device accepts event messages [platform event
// request messages] from the IPMB)
// [3] FRU Inventory Device
// [2] SEL Device
// [1] SDR Repository Device
// [0] Sensor Device
type AdditionalDeviceSupport struct {
SupportChassis bool
SupportBridge bool
SupportIPMBEventGenerator bool
SupportIPMBEventReceiver bool
SupportFRUInventory bool
SupportSEL bool
SupportSDRRepo bool
SupportSensor bool
}
func (req *GetDeviceIDRequest) Command() Command {
return CommandGetDeviceID
}
func (req *GetDeviceIDRequest) Pack() []byte {
return []byte{}
}
func (res *GetDeviceIDResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetDeviceIDResponse) Unpack(msg []byte) error {
if len(msg) < 11 {
return ErrUnpackedDataTooShortWith(len(msg), 11)
}
res.DeviceID, _, _ = unpackUint8(msg, 0)
b2, _, _ := unpackUint8(msg, 1)
res.ProvideDeviceSDRs = isBit7Set(b2)
res.DeviceRevision = b2 & 0x0f
b3, _, _ := unpackUint8(msg, 2)
res.DeviceAvailable = !isBit7Set(b3)
res.MajorFirmwareRevision = b3 & 0x7f // binary encoded
b4, _, _ := unpackUint8(msg, 3) // BCD encoded
res.MinorFirmwareRevision = bcdUint8(b4)
ipmiVersionBCD, _, _ := unpackUint8(msg, 4) // BCD encoded
res.MajorIPMIVersion = ipmiVersionBCD & 0x0f
res.MinorIPMIVersion = ipmiVersionBCD >> 4
b6, _, _ := unpackUint8(msg, 5)
res.SupportChassis = isBit7Set(b6)
res.SupportBridge = isBit6Set(b6)
res.SupportIPMBEventGenerator = isBit5Set(b6)
res.SupportIPMBEventReceiver = isBit4Set(b6)
res.SupportFRUInventory = isBit3Set(b6)
res.SupportSEL = isBit2Set(b6)
res.SupportSDRRepo = isBit1Set(b6)
res.SupportSensor = isBit0Set(b6)
res.ManufacturerID, _, _ = unpackUint24L(msg, 6)
res.ProductID, _, _ = unpackUint16L(msg, 9)
if len(msg) > 11 && len(msg) < 15 {
return ErrUnpackedDataTooShortWith(len(msg), 15)
} else {
res.AuxiliaryFirmwareRevision, _, _ = unpackBytes(msg, 11, 4)
}
return nil
}
func (res *GetDeviceIDResponse) FirmwareVersionStr() string {
return fmt.Sprintf("%d.%d", res.MajorFirmwareRevision, res.MinorFirmwareRevision)
}
func (res *GetDeviceIDResponse) Format() string {
deviceSupport := []string{}
if res.SupportChassis {
deviceSupport = append(deviceSupport, " Chassis Device")
}
if res.SupportBridge {
deviceSupport = append(deviceSupport, " Bridge Device")
}
if res.SupportIPMBEventGenerator {
deviceSupport = append(deviceSupport, " IPMB Event Generator")
}
if res.SupportIPMBEventReceiver {
deviceSupport = append(deviceSupport, " IPMB Event Receiver")
}
if res.SupportFRUInventory {
deviceSupport = append(deviceSupport, " FRU Inventory Device")
}
if res.SupportSEL {
deviceSupport = append(deviceSupport, " SEL Device")
}
if res.SupportSDRRepo {
deviceSupport = append(deviceSupport, " SDR Repo Device")
}
if res.SupportSensor {
deviceSupport = append(deviceSupport, " Sensor Device")
}
auxFirmwareInfo := []string{}
for _, v := range res.AuxiliaryFirmwareRevision {
auxFirmwareInfo = append(auxFirmwareInfo, fmt.Sprintf(" %#02x", v))
}
return fmt.Sprintf(`Device ID : %d
Device Revision : %d
Firmware Revision : %d.%d
IPMI Version : %d.%d
Manufacturer ID : %d (%#02x)
Manufacturer Name : %s
Product ID : %d (%#04x)
Product Name : %#02x
Device Available : %s
Provides Device SDRs : %s
Additional Device Support :
%s
Aux Firmware Rev Info :
%s`,
res.DeviceID,
res.DeviceRevision,
res.MajorFirmwareRevision, res.MinorFirmwareRevision,
res.MajorIPMIVersion, res.MinorIPMIVersion,
res.ManufacturerID, res.ManufacturerID,
OEM(res.ManufacturerID),
res.ProductID, res.ProductID,
res.ProductID,
formatBool(res.DeviceAvailable, "yes", "no"),
formatBool(res.ProvideDeviceSDRs, "yes", "no"),
strings.Join(deviceSupport, " \n"),
strings.Join(auxFirmwareInfo, " \n"),
)
}
func (c *Client) GetDeviceID(ctx context.Context) (response *GetDeviceIDResponse, err error) {
request := &GetDeviceIDRequest{}
response = &GetDeviceIDResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_device_sdr.go 0000664 0000000 0000000 00000012470 14741105271 0023232 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 35.3 Get Device SDR Command
type GetDeviceSDRRequest struct {
ReservationID uint16
RecordID uint16
ReadOffset uint8
ReadBytes uint8 // FFh means read entire record
}
type GetDeviceSDRResponse struct {
NextRecordID uint16
RecordData []byte
}
func (req *GetDeviceSDRRequest) Command() Command {
return CommandGetDeviceSDR
}
func (req *GetDeviceSDRRequest) Pack() []byte {
out := make([]byte, 6)
packUint16L(req.ReservationID, out, 0)
packUint16L(req.RecordID, out, 2)
packUint8(req.ReadOffset, out, 4)
packUint8(req.ReadBytes, out, 5)
return out
}
func (res *GetDeviceSDRResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.NextRecordID, _, _ = unpackUint16L(msg, 0)
res.RecordData, _, _ = unpackBytes(msg, 2, len(msg)-2)
return nil
}
func (r *GetDeviceSDRResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "record changed",
}
}
func (res *GetDeviceSDRResponse) Format() string {
return ""
}
// The Get Device SDR command allows SDR information for sensors for a Sensor Device
// (typically implemented in a satellite management controller) to be returned.
//
// The Get Device SDR Command can return any type of SDR, not just Types 01h and 02h.
// This is an optional command for Static Sensor Devices, and mandatory for Dynamic Sensor Devices.
// The format and action of this command is similar to that for the Get SDR command
// for SDR Repository Devices.
//
// Sensor Devices that support the Get Device SDR command return SDR Records that
// match the SDR Repository formats.
func (c *Client) GetDeviceSDR(ctx context.Context, recordID uint16) (response *GetDeviceSDRResponse, err error) {
request := &GetDeviceSDRRequest{
ReservationID: 0,
RecordID: recordID,
ReadOffset: 0,
ReadBytes: 0xff,
}
response = &GetDeviceSDRResponse{}
err = c.Exchange(ctx, request, response)
if resErr, ok := err.(*ResponseError); ok {
if resErr.CompletionCode() == CompletionCodeCannotReturnRequestedDataBytes {
return c.getDeviceSDR(ctx, recordID)
}
}
return
}
// getDeviceSDR reads the Device SDR record in partial read way.
func (c *Client) getDeviceSDR(ctx context.Context, recordID uint16) (response *GetDeviceSDRResponse, err error) {
var data []byte
// the actual data length of the SDR can only be determined after the first GetSDR request/response.
dataLength := uint8(0)
reservationID := uint16(0)
readBytes := uint8(16)
readTotal := uint8(0)
readOffset := uint8(0)
for {
request := &GetDeviceSDRRequest{
ReservationID: reservationID,
RecordID: recordID,
ReadOffset: readOffset,
ReadBytes: readBytes,
}
response = &GetDeviceSDRResponse{}
if err = c.Exchange(ctx, request, response); err != nil {
return
}
// determine the total data length by parsing the SDR Header part
if readOffset == 0 {
if len(response.RecordData) < SDRRecordHeaderSize {
return nil, fmt.Errorf("too short record data for SDR header (%d/%d)", len(response.RecordData), SDRRecordHeaderSize)
}
dataLength = response.RecordData[4] + uint8(SDRRecordHeaderSize)
data = make([]byte, dataLength)
}
copy(data[readOffset:readOffset+readBytes], response.RecordData[:])
readOffset += uint8(len(response.RecordData))
readTotal += uint8(len(response.RecordData))
if readTotal >= dataLength {
break
}
if readOffset+readBytes > dataLength {
// decrease the readBytes for the last read.
readBytes = dataLength - readOffset
}
rsp, err := c.ReserveDeviceSDRRepo(ctx)
if err == nil {
reservationID = rsp.ReservationID
} else {
reservationID = 0
}
}
return &GetDeviceSDRResponse{
NextRecordID: response.NextRecordID,
RecordData: data,
}, nil
}
func (c *Client) GetDeviceSDRBySensorID(ctx context.Context, sensorNumber uint8) (*SDR, error) {
if SensorNumber(sensorNumber) == SensorNumberReserved {
return nil, fmt.Errorf("not valid sensorNumber, %#0x is reserved", sensorNumber)
}
var recordID uint16 = 0
for {
res, err := c.GetDeviceSDR(ctx, recordID)
if err != nil {
return nil, fmt.Errorf("GetDeviceSDR for recordID (%#0x) failed, err: %s", recordID, err)
}
sdr, err := ParseSDR(res.RecordData, res.NextRecordID)
if err != nil {
return nil, fmt.Errorf("ParseSDR for recordID (%#0x) failed, err: %s", recordID, err)
}
if uint8(sdr.SensorNumber()) == sensorNumber {
return sdr, nil
}
recordID = res.NextRecordID
if recordID == 0xffff {
break
}
}
return nil, fmt.Errorf("not found SDR for sensor id (%#0x)", sensorNumber)
}
func (c *Client) GetDeviceSDRs(ctx context.Context, recordTypes ...SDRRecordType) ([]*SDR, error) {
var out = make([]*SDR, 0)
var recordID uint16 = 0
for {
res, err := c.GetDeviceSDR(ctx, recordID)
if err != nil {
return nil, fmt.Errorf("GetDeviceSDR for recordID (%#0x) failed, err: %s", recordID, err)
}
sdr, err := ParseSDR(res.RecordData, res.NextRecordID)
if err != nil {
return nil, fmt.Errorf("ParseSDR for recordID (%#0x) failed, err: %s", recordID, err)
}
if len(recordTypes) == 0 {
out = append(out, sdr)
} else {
for _, v := range recordTypes {
if sdr.RecordHeader.RecordType == v {
out = append(out, sdr)
break
}
}
}
recordID = res.NextRecordID
if recordID == 0xffff {
break
}
}
return out, nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_device_sdr_info.go 0000664 0000000 0000000 00000005354 14741105271 0024250 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 35.2 Get Device SDR Info Command
type GetDeviceSDRInfoRequest struct {
// true: Get SDR count. This returns the total number of SDRs in the device.
// false: Get Sensor count. This returns the number of sensors implemented on LUN this command was addressed to.
GetSDRCount bool
}
type GetDeviceSDRInfoResponse struct {
getSDRCount bool
Count uint8
// 0b = static sensor population. The number of sensors handled by this
// device is fixed, and a query shall return records for all sensors.
//
// 1b = dynamic sensor population. This device may have its sensor
// population vary during "run time" (defined as any time other that
// when an install operation is in progress).
DynamicSensorPopulation bool
LUN3HasSensors bool
LUN2HasSensors bool
LUN1HasSensors bool
LUN0HasSensors bool
// Four byte timestamp, or counter. Updated or incremented each time the
// sensor population changes. This field is not provided if the flags indicate a
// static sensor population.
SensorPopulationChangeIndicator uint32
}
func (req *GetDeviceSDRInfoRequest) Command() Command {
return CommandGetDeviceSDRInfo
}
func (req *GetDeviceSDRInfoRequest) Pack() []byte {
var b uint8
if req.GetSDRCount {
b = setBit0(b)
}
return []byte{b}
}
func (res *GetDeviceSDRInfoResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.Count, _, _ = unpackUint8(msg, 0)
b, _, _ := unpackUint8(msg, 1)
res.DynamicSensorPopulation = isBit7Set(b)
res.LUN3HasSensors = isBit3Set(b)
res.LUN2HasSensors = isBit2Set(b)
res.LUN1HasSensors = isBit1Set(b)
res.LUN0HasSensors = isBit0Set(b)
if res.DynamicSensorPopulation {
if len(msg) < 6 {
return ErrUnpackedDataTooShortWith(len(msg), 6)
}
res.SensorPopulationChangeIndicator, _, _ = unpackUint32L(msg, 2)
}
return nil
}
func (r *GetDeviceSDRInfoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetDeviceSDRInfoResponse) Format() string {
return fmt.Sprintf(`
Count : %d (%s)
Dynamic Population : %v
LUN 0 has sensors : %v
LUN 1 has sensors : %v
LUN 2 has sensors : %v
LUN 3 has sensors : %v
`,
res.Count, formatBool(res.getSDRCount, "SDRs", "Sensors"),
res.DynamicSensorPopulation,
res.LUN0HasSensors,
res.LUN1HasSensors,
res.LUN2HasSensors,
res.LUN3HasSensors,
)
}
// This command returns general information about the collection of sensors in a Dynamic Sensor Device.
func (c *Client) GetDeviceSDRInfo(ctx context.Context, getSDRCount bool) (response *GetDeviceSDRInfoResponse, err error) {
request := &GetDeviceSDRInfoRequest{
GetSDRCount: getSDRCount,
}
response = &GetDeviceSDRInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_event_receiver.go 0000664 0000000 0000000 00000001676 14741105271 0024136 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 29.2 Get Event Receiver Command
type GetEventReceiverRequest struct {
}
type GetEventReceiverResponse struct {
SlaveAddress uint8
LUN uint8
}
func (req *GetEventReceiverRequest) Pack() []byte {
return []byte{}
}
func (req *GetEventReceiverRequest) Command() Command {
return CommandGetEventReceiver
}
func (res *GetEventReceiverResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetEventReceiverResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.SlaveAddress = msg[0]
res.LUN = msg[1]
return nil
}
func (res *GetEventReceiverResponse) Format() string {
return ""
}
func (c *Client) GetEventReceiver(ctx context.Context) (response *GetEventReceiverResponse, err error) {
request := &GetEventReceiverRequest{}
response = &GetEventReceiverResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_fru_inventory_area_info.go 0000664 0000000 0000000 00000002745 14741105271 0026043 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 34.1 Get FRU Inventory Area Info Command
type GetFRUInventoryAreaInfoRequest struct {
FRUDeviceID uint8
}
type GetFRUInventoryAreaInfoResponse struct {
AreaSizeBytes uint16
DeviceAccessedByWords bool // false means Device is accessed by Bytes
}
func (req *GetFRUInventoryAreaInfoRequest) Command() Command {
return CommandGetFRUInventoryAreaInfo
}
func (req *GetFRUInventoryAreaInfoRequest) Pack() []byte {
return []byte{req.FRUDeviceID}
}
func (res *GetFRUInventoryAreaInfoResponse) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
res.AreaSizeBytes, _, _ = unpackUint16L(msg, 0)
b, _, _ := unpackUint8(msg, 2)
res.DeviceAccessedByWords = isBit0Set(b)
return nil
}
func (r *GetFRUInventoryAreaInfoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetFRUInventoryAreaInfoResponse) Format() string {
return fmt.Sprintf(`fru.size = %d bytes (accessed by %s)`,
res.AreaSizeBytes,
formatBool(res.DeviceAccessedByWords, "words", "bytes"),
)
}
// This command returns overall the size of the FRU Inventory Area in this device, in bytes.
func (c *Client) GetFRUInventoryAreaInfo(ctx context.Context, fruDeviceID uint8) (response *GetFRUInventoryAreaInfoResponse, err error) {
request := &GetFRUInventoryAreaInfoRequest{
FRUDeviceID: fruDeviceID,
}
response = &GetFRUInventoryAreaInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_frus.go 0000664 0000000 0000000 00000026311 14741105271 0022101 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// GetFRUData return all data bytes, the data size is firstly determined by
// GetFRUInventoryAreaInfoResponse.AreaSizeBytes
func (c *Client) GetFRUData(ctx context.Context, deviceID uint8) ([]byte, error) {
fruAreaInfoRes, err := c.GetFRUInventoryAreaInfo(ctx, deviceID)
if err != nil {
return nil, fmt.Errorf("GetFRUInventoryAreaInfo failed, err: %w", err)
}
c.Debug("", fruAreaInfoRes.Format())
if fruAreaInfoRes.AreaSizeBytes < 1 {
return nil, fmt.Errorf("invalid FRU size %d", fruAreaInfoRes.AreaSizeBytes)
}
data, err := c.readFRUDataByLength(ctx, deviceID, 0, fruAreaInfoRes.AreaSizeBytes)
if err != nil {
return nil, fmt.Errorf("read full fru area data failed, err: %w", err)
}
c.Debugf("Got %d fru data\n", len(data))
return data, nil
}
// GetFRU return FRU for the specified deviceID.
// The deviceName is not a must, pass empty string if not known.
func (c *Client) GetFRU(ctx context.Context, deviceID uint8, deviceName string) (*FRU, error) {
c.Debugf("GetFRU device name (%s) id (%#02x)\n", deviceName, deviceID)
fru := &FRU{
deviceID: deviceID,
deviceName: deviceName,
}
fruAreaInfoRes, err := c.GetFRUInventoryAreaInfo(ctx, deviceID)
if err != nil {
if resErr, ok := err.(*ResponseError); ok {
if resErr.CompletionCode() == CompletionCodeRequestedDataNotPresent {
fru.deviceNotPresent = true
fru.deviceNotPresentReason = "InventoryRecordNotExist"
return fru, nil
}
}
return nil, fmt.Errorf("GetFRUInventoryAreaInfo failed, err: %w", err)
}
c.Debug("", fruAreaInfoRes.Format())
if fruAreaInfoRes.AreaSizeBytes < 1 {
return nil, fmt.Errorf("invalid FRU size %d", fruAreaInfoRes.AreaSizeBytes)
}
// retrieve the FRU header, just fetch FRUCommonHeaderSize bytes to construct a FRU Header
readFRURes, err := c.ReadFRUData(ctx, deviceID, 0, FRUCommonHeaderSize)
if err != nil {
if resErr, ok := err.(*ResponseError); ok {
switch resErr.CompletionCode() {
case CompletionCodeRequestedDataNotPresent:
fru.deviceNotPresent = true
fru.deviceNotPresentReason = "DataNotPresent"
return fru, nil
case CompletionCodeProcessTimeout:
fru.deviceNotPresent = true
fru.deviceNotPresentReason = "Timeout"
return fru, nil
}
}
return nil, fmt.Errorf("ReadFRUData failed, err: %w", err)
}
fruHeader := &FRUCommonHeader{}
if err := fruHeader.Unpack(readFRURes.Data); err != nil {
return nil, fmt.Errorf("unpack fru data failed, err: %w", err)
}
if fruHeader.FormatVersion != FRUFormatVersion {
return nil, fmt.Errorf("unknown FRU header version %#02x", fruHeader.FormatVersion)
}
c.Debug("FRU Common Header", fruHeader)
c.Debugf("%s\n\n", fruHeader.String())
fru.CommonHeader = fruHeader
if offset := uint16(fruHeader.ChassisOffset8B) * 8; offset > 0 && offset < fruAreaInfoRes.AreaSizeBytes {
c.Debugf("Get FRU Area Chassis, offset (%d)\n", offset)
fruChassis, err := c.GetFRUAreaChassis(ctx, deviceID, offset)
if err != nil {
return nil, fmt.Errorf("GetFRUAreaChassis failed, err: %w", err)
}
c.Debug("FRU Area Chassis", fruChassis)
fru.ChassisInfoArea = fruChassis
}
if offset := uint16(fruHeader.BoardOffset8B) * 8; offset > 0 && offset < fruAreaInfoRes.AreaSizeBytes {
c.Debugf("Get FRU Area Board, offset (%d)\n", offset)
fruBoard, err := c.GetFRUAreaBoard(ctx, deviceID, offset)
if err != nil {
return nil, fmt.Errorf("GetFRUAreaBoard failed, err: %w", err)
}
c.Debug("FRU Area Board", fruBoard)
fru.BoardInfoArea = fruBoard
}
if offset := uint16(fruHeader.ProductOffset8B) * 8; offset > 0 && offset < fruAreaInfoRes.AreaSizeBytes {
c.Debugf("Get FRU Area Product, offset (%d)\n", offset)
fruProduct, err := c.GetFRUAreaProduct(ctx, deviceID, offset)
if err != nil {
return nil, fmt.Errorf("GetFRUAreaProduct failed, err: %w", err)
}
c.Debug("FRU Area Product", fruProduct)
fru.ProductInfoArea = fruProduct
}
if offset := uint16(fruHeader.MultiRecordsOffset8B) * 8; offset > 0 && offset < fruAreaInfoRes.AreaSizeBytes {
c.Debugf("Get FRU Area Multi Records, offset (%d)\n", offset)
fruMultiRecords, err := c.GetFRUAreaMultiRecords(ctx, deviceID, offset)
if err != nil {
return nil, fmt.Errorf("GetFRUAreaMultiRecord failed, err: %w", err)
}
c.Debug("FRU Area MultiRecords", fruMultiRecords)
fru.MultiRecords = fruMultiRecords
}
c.Debug("FRU", fru)
return fru, nil
}
func (c *Client) GetFRUs(ctx context.Context) ([]*FRU, error) {
var frus = make([]*FRU, 0)
// Do a Get Device ID command to determine device support
deviceRes, err := c.GetDeviceID(ctx)
if err != nil {
return nil, fmt.Errorf("GetDeviceID failed, err: %w", err)
}
c.Debug("deviceRes", deviceRes)
if deviceRes.AdditionalDeviceSupport.SupportFRUInventory {
// FRU Device ID #00 at LUN 00b is predefined as being the FRU Device
// for the FRU that the management controller is located on.
var deviceID uint8 = 0x00
fru, err := c.GetFRU(ctx, deviceID, "Builtin FRU")
if err != nil {
return nil, fmt.Errorf("GetFRU device id (%#02x) failed, err: %s", deviceID, err)
}
frus = append(frus, fru)
}
// Walk the SDRs to look for FRU Devices and Management Controller Devices.
// For FRU devices, print the FRU from the SDR locator record.
// For MC devices, issue FRU commands to the satellite controller to print FRU data.
sdrs, err := c.GetSDRs(ctx, SDRRecordTypeFRUDeviceLocator, SDRRecordTypeManagementControllerDeviceLocator)
if err != nil {
return nil, fmt.Errorf("GetSDRS failed, err: %w", err)
}
for _, sdr := range sdrs {
switch sdr.RecordHeader.RecordType {
case SDRRecordTypeFRUDeviceLocator:
deviceType := sdr.FRUDeviceLocator.DeviceType
deviceTypeModifier := sdr.FRUDeviceLocator.DeviceTypeModifier
deviceName := string(sdr.FRUDeviceLocator.DeviceIDBytes)
deviceAccessAddress := sdr.FRUDeviceLocator.DeviceAccessAddress // controller
accessLUN := sdr.FRUDeviceLocator.AccessLUN // LUN
privateBusID := sdr.FRUDeviceLocator.PrivateBusID // Private bus
deviceIDOrSlaveAddress := sdr.FRUDeviceLocator.FRUDeviceID_SlaveAddress // device
fruLocation := sdr.FRUDeviceLocator.Location()
c.Debugf("fruLocation: (%s), deviceType: (%s [%#02x]), deviceTypeModifier: (%#02x), deviceIDOrSlaveAddress: (%#02x), deviceName: (%s), isLogical: (%v), "+
"DeviceAccessAddress (%#02x), AccessLUN: (%#02x), PrivateBusID(%#02x)\n",
fruLocation, deviceType.String(), uint8(deviceType), deviceTypeModifier, deviceIDOrSlaveAddress, deviceName, sdr.FRUDeviceLocator.IsLogicalFRUDevice,
deviceAccessAddress, accessLUN, privateBusID,
)
// see 38. Accessing FRU Devices
switch fruLocation {
case FRULocation_MgmtController:
if accessLUN == 0x00 && deviceIDOrSlaveAddress == 0x00 {
// this is the Builtin FRU device, already got
continue
}
// Todo, accessed using Read/Write FRU commands at LUN other than 00b
fru, err := c.GetFRU(ctx, deviceIDOrSlaveAddress, deviceName)
if err != nil {
return nil, fmt.Errorf("GetFRU sdr device id (%#02x) failed, err: %s", deviceIDOrSlaveAddress, err)
}
frus = append(frus, fru)
case FRULocation_PrivateBus:
// Todo,
switch deviceType {
case 0x10:
// Todo, refactor BuildIPMIRequest to use LUN
// if sdr.FRUDeviceLocator.DeviceAccessAddress == BMC_SA && deviceID == 0x00 {
// continue
// }
switch deviceTypeModifier {
// 0x00, 0x02 = IPMI FRU Inventory
case 0x00, 0x02:
// 0x01 = DIMM Memory ID
case 0x01:
// 03h = System Processor Cartridge FRU / PIROM (processor information ROM)
case 0x03:
}
case 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f:
// Todo
}
case FRULocation_IPMB:
}
case SDRRecordTypeManagementControllerDeviceLocator:
}
}
return frus, nil
}
func (c *Client) GetFRUAreaChassis(ctx context.Context, deviceID uint8, offset uint16) (*FRUChassisInfoArea, error) {
// read enough (2 bytes) to check the length field
res, err := c.ReadFRUData(ctx, deviceID, offset, 2)
if err != nil {
return nil, fmt.Errorf("ReadFRUData failed, err: %w", err)
}
length := uint16(res.Data[1]) * 8 // in multiples of 8 bytes
// now read full area data
data, err := c.readFRUDataByLength(ctx, deviceID, offset, length)
if err != nil {
return nil, fmt.Errorf("read full fru area data failed, err: %w", err)
}
c.Debugf("Got %d fru data\n", len(data))
fruChassis := &FRUChassisInfoArea{}
if err := fruChassis.Unpack(data); err != nil {
return nil, fmt.Errorf("unpack fru chassis failed, err: %w", err)
}
return fruChassis, nil
}
func (c *Client) GetFRUAreaBoard(ctx context.Context, deviceID uint8, offset uint16) (*FRUBoardInfoArea, error) {
// read enough (2 bytes) to check the length field
res, err := c.ReadFRUData(ctx, deviceID, offset, 2)
if err != nil {
return nil, fmt.Errorf("ReadFRUData failed, err: %w", err)
}
length := uint16(res.Data[1]) * 8 // in multiples of 8 bytes
// now read full area data
data, err := c.readFRUDataByLength(ctx, deviceID, offset, length)
if err != nil {
return nil, fmt.Errorf("read full fru area data failed, err: %w", err)
}
c.Debugf("Got %d fru data\n", len(data))
fruBoard := &FRUBoardInfoArea{}
if err := fruBoard.Unpack(data); err != nil {
return nil, fmt.Errorf("unpack fru board failed, err: %w", err)
}
return fruBoard, nil
}
func (c *Client) GetFRUAreaProduct(ctx context.Context, deviceID uint8, offset uint16) (*FRUProductInfoArea, error) {
// read enough (2 bytes) to check the length field
res, err := c.ReadFRUData(ctx, deviceID, offset, 2)
if err != nil {
return nil, fmt.Errorf("ReadFRUData failed, err: %w", err)
}
length := uint16(res.Data[1]) * 8 // in multiples of 8 bytes
// now read full area data
data, err := c.readFRUDataByLength(ctx, deviceID, offset, length)
if err != nil {
return nil, fmt.Errorf("read full fru area data failed, err: %w", err)
}
c.Debugf("Got %d fru data\n", len(data))
fruProduct := &FRUProductInfoArea{}
if err := fruProduct.Unpack(data); err != nil {
return nil, fmt.Errorf("unpack fru board failed, err: %w", err)
}
return fruProduct, nil
}
func (c *Client) GetFRUAreaMultiRecords(ctx context.Context, deviceID uint8, offset uint16) ([]*FRUMultiRecord, error) {
records := make([]*FRUMultiRecord, 0)
for {
// read enough (5 bytes) to check the length of each record
// For a MultiRecord, the first 5 bytes contains the Record Header,
// and the third byte holds the data length.
//
// see: FRU/16.1 Record Header
res, err := c.ReadFRUData(ctx, deviceID, offset, 5)
if err != nil {
return nil, fmt.Errorf("ReadFRUData failed, err: %w", err)
}
length := uint16(res.Data[2])
// now read full data for this record
recordSize := 5 + length // Record Header + Data Length
data, err := c.readFRUDataByLength(ctx, deviceID, offset, recordSize)
if err != nil {
return nil, fmt.Errorf("read full fru area data failed, err: %w", err)
}
c.Debugf("Got %d fru data\n", len(data))
record := &FRUMultiRecord{}
if err := record.Unpack(data); err != nil {
return nil, fmt.Errorf("unpack fru multi record failed, err: %w", err)
}
c.Debug("Multi record", record)
records = append(records, record)
// update offset for the next record
offset += uint16(5 + record.RecordLength)
if record.EndOfList {
break
}
}
return records, nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_ip_statistics.go 0000664 0000000 0000000 00000005071 14741105271 0024004 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 23.4 Get IP/UDP/RMCP Statistics Command
type GetIPStatisticsRequest struct {
ChannelNumber uint8
ClearAllStatistics bool
}
type GetIPStatisticsResponse struct {
IPPacketsReceived uint16
IPHeaderErrorsReceived uint16
IPAddressErrorsReceived uint16
IPPacketsFragmentedReceived uint16
IPPacketsTransmitted uint16
UDPPacketsReceived uint16
RMCPPacketsValidReceived uint16
UDPProxyPacketsReceived uint16
UDPProxyPacketsDropped uint16
}
func (req *GetIPStatisticsRequest) Pack() []byte {
out := make([]byte, 2)
packUint8(req.ChannelNumber, out, 0)
var b uint8
if req.ClearAllStatistics {
b = setBit0(b)
}
packUint8(b, out, 1)
return out
}
func (req *GetIPStatisticsRequest) Command() Command {
return CommandGetIPStatistics
}
func (res *GetIPStatisticsResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetIPStatisticsResponse) Unpack(msg []byte) error {
if len(msg) < 18 {
return ErrUnpackedDataTooShortWith(len(msg), 18)
}
res.IPPacketsReceived, _, _ = unpackUint16L(msg, 0)
res.IPHeaderErrorsReceived, _, _ = unpackUint16L(msg, 2)
res.IPAddressErrorsReceived, _, _ = unpackUint16L(msg, 4)
res.IPPacketsFragmentedReceived, _, _ = unpackUint16L(msg, 6)
res.IPPacketsTransmitted, _, _ = unpackUint16L(msg, 8)
res.UDPPacketsReceived, _, _ = unpackUint16L(msg, 10)
res.RMCPPacketsValidReceived, _, _ = unpackUint16L(msg, 12)
res.UDPProxyPacketsReceived, _, _ = unpackUint16L(msg, 14)
res.UDPProxyPacketsDropped, _, _ = unpackUint16L(msg, 16)
return nil
}
func (res *GetIPStatisticsResponse) Format() string {
return fmt.Sprintf(`IP Rx Packet : %d
IP Rx Header Errors : %d
IP Rx Address Errors : %d
IP Rx Fragmented : %d
IP Tx Packet : %d
UDP Rx Packet : %d
RMCP Rx Valid : %d
UDP Proxy Packet Received : %d
UDP Proxy Packet Dropped : %d`,
res.IPPacketsReceived,
res.IPHeaderErrorsReceived,
res.IPAddressErrorsReceived,
res.IPPacketsFragmentedReceived,
res.IPPacketsTransmitted,
res.UDPPacketsReceived,
res.RMCPPacketsValidReceived,
res.UDPProxyPacketsReceived,
res.UDPProxyPacketsDropped,
)
}
func (c *Client) GetIPStatistics(ctx context.Context, channelNumber uint8, clearAllStatistics bool) (response *GetIPStatisticsResponse, err error) {
request := &GetIPStatisticsRequest{
ChannelNumber: channelNumber,
ClearAllStatistics: clearAllStatistics,
}
response = &GetIPStatisticsResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_lan_config_params.go 0000664 0000000 0000000 00000067245 14741105271 0024577 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 23.2 Get LAN Configuration Parameters Command
type GetLanConfigParamRequest struct {
ChannelNumber uint8
ParamSelector LanConfigParamSelector
SetSelector uint8
BlockSelector uint8
}
type GetLanConfigParamResponse struct {
ParamRevision uint8
ParamData []byte
}
func (req *GetLanConfigParamRequest) Pack() []byte {
out := make([]byte, 4)
packUint8(req.ChannelNumber, out, 0)
packUint8(uint8(req.ParamSelector), out, 1)
packUint8(req.SetSelector, out, 2)
packUint8(req.BlockSelector, out, 3)
return out
}
func (req *GetLanConfigParamRequest) Command() Command {
return CommandGetLanConfigParam
}
func (res *GetLanConfigParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "parameter not supported.",
}
}
func (res *GetLanConfigParamResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
res.ParamRevision, _, _ = unpackUint8(msg, 0)
res.ParamData, _, _ = unpackBytes(msg, 1, len(msg)-1)
return nil
}
func (res *GetLanConfigParamResponse) Format() string {
out := `
Parameter Revision : %d
Param Data : %v
Length of Config Data : %d
`
return fmt.Sprintf(out, res.ParamRevision, res.ParamData, len(res.ParamData))
}
func (c *Client) GetLanConfigParam(ctx context.Context, channelNumber uint8, paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) (response *GetLanConfigParamResponse, err error) {
request := &GetLanConfigParamRequest{
ChannelNumber: channelNumber,
ParamSelector: paramSelector,
SetSelector: setSelector,
BlockSelector: blockSelector,
}
response = &GetLanConfigParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
// GetLanConfigParamFor get the lan config for a specific parameter.
//
// The param is a pointer to a struct that implements the LanConfigParameter interface.
func (c *Client) GetLanConfigParamFor(ctx context.Context, channelNumber uint8, param LanConfigParameter) error {
if isNilLanConfigParameter(param) {
return nil
}
paramSelector, setSelector, blockSelector := param.LanConfigParameter()
c.Debugf(">> Get LanConfigParam for paramSelector (%d) %s, setSelector %d, blockSelector %d\n", uint8(paramSelector), paramSelector, setSelector, blockSelector)
response, err := c.GetLanConfigParam(ctx, channelNumber, paramSelector, setSelector, blockSelector)
if err != nil {
c.Debugf("!!! Get LanConfigParam for paramSelector (%d) %s, setSelector %d failed, err: %v\n", uint8(paramSelector), paramSelector, setSelector, err)
return err
}
c.DebugBytes(fmt.Sprintf("<< Got param data for (%s[%d]) ", paramSelector.String(), paramSelector), response.ParamData, 8)
if err := param.Unpack(response.ParamData); err != nil {
return fmt.Errorf("unpack lan config param (%s [%d]) failed, err: %w", paramSelector.String(), paramSelector, err)
}
return nil
}
func (c *Client) GetLanConfig(ctx context.Context, channelNumber uint8) (*LanConfig, error) {
lanConfigParams, err := c.GetLanConfigParams(ctx, channelNumber)
if err != nil {
return nil, fmt.Errorf("GetLanConfigParams failed, err: %w", err)
}
return lanConfigParams.ToLanConfig(), nil
}
func (c *Client) GetLanConfigParams(ctx context.Context, channelNumber uint8) (*LanConfigParams, error) {
lanConfigParams := &LanConfigParams{
SetInProgress: &LanConfigParam_SetInProgress{},
AuthTypeSupport: &LanConfigParam_AuthTypeSupport{},
AuthTypeEnables: &LanConfigParam_AuthTypeEnables{},
IP: &LanConfigParam_IP{},
IPSource: &LanConfigParam_IPSource{},
MAC: &LanConfigParam_MAC{},
SubnetMask: &LanConfigParam_SubnetMask{},
IPv4HeaderParams: &LanConfigParam_IPv4HeaderParams{},
PrimaryRMCPPort: &LanConfigParam_PrimaryRMCPPort{},
SecondaryRMCPPort: &LanConfigParam_SecondaryRMCPPort{},
ARPControl: &LanConfigParam_ARPControl{},
GratuitousARPInterval: &LanConfigParam_GratuitousARPInterval{},
DefaultGatewayIP: &LanConfigParam_DefaultGatewayIP{},
DefaultGatewayMAC: &LanConfigParam_DefaultGatewayMAC{},
BackupGatewayIP: &LanConfigParam_BackupGatewayIP{},
BackupGatewayMAC: &LanConfigParam_BackupGatewayMAC{},
CommunityString: &LanConfigParam_CommunityString{},
// AlertDestinationsCount: &LanConfigParam_AlertDestinationsCount{},
// AlertDestinationTypes: make([]*LanConfigParam_AlertDestinationType, 0),
// AlertDestinationAddresses: make([]*LanConfigParam_AlertDestinationAddress, 0),
VLANID: &LanConfigParam_VLANID{},
VLANPriority: &LanConfigParam_VLANPriority{},
CipherSuitesSupport: &LanConfigParam_CipherSuitesSupport{},
CipherSuitesID: &LanConfigParam_CipherSuitesID{},
CipherSuitesPrivLevel: &LanConfigParam_CipherSuitesPrivLevel{},
AlertDestinationVLANs: make([]*LanConfigParam_AlertDestinationVLAN, 0),
BadPasswordThreshold: &LanConfigParam_BadPasswordThreshold{},
// IPv6Support: &LanConfigParam_IPv6Support{},
// IPv6Enables: &LanConfigParam_IPv6Enables{},
// IPv6StaticTrafficClass: &LanConfigParam_IPv6StaticTrafficClass{},
// IPv6StaticHopLimit: &LanConfigParam_IPv6StaticHopLimit{},
// IPv6FlowLabel: &LanConfigParam_IPv6FlowLabel{},
// IPv6Status: &LanConfigParam_IPv6Status{},
// IPv6StaticAddresses: make([]*LanConfigParam_IPv6StaticAddress, 0),
// IPv6DHCPv6StaticDUIDCount: &LanConfigParam_IPv6DHCPv6StaticDUIDCount{},
// IPv6DHCPv6StaticDUIDs: make([]*LanConfigParam_IPv6DHCPv6StaticDUID, 0),
// IPv6DynamicAddresses: make([]*LanConfigParam_IPv6DynamicAddress, 0),
// IPv6DHCPv6DynamicDUIDCount: &LanConfigParam_IPv6DHCPv6DynamicDUIDCount{},
// IPv6DHCPv6DynamicDUIDs: make([]*LanConfigParam_IPv6DHCPv6DynamicDUID, 0),
// IPv6DHCPv6TimingConfigSupport: &LanConfigParam_IPv6DHCPv6TimingConfigSupport{},
// IPv6DHCPv6TimingConfig: make([]*LanConfigParam_IPv6DHCPv6TimingConfig, 0),
// IPv6RouterAddressConfigControl: &LanConfigParam_IPv6RouterAddressConfigControl{},
// IPv6StaticRouter1IP: &LanConfigParam_IPv6StaticRouter1IP{},
// IPv6StaticRouter1MAC: &LanConfigParam_IPv6StaticRouter1MAC{},
// IPv6StaticRouter1PrefixLength: &LanConfigParam_IPv6StaticRouter1PrefixLength{},
// IPv6StaticRouter1PrefixValue: &LanConfigParam_IPv6StaticRouter1PrefixValue{},
// IPv6StaticRouter2IP: &LanConfigParam_IPv6StaticRouter2IP{},
// IPv6StaticRouter2MAC: &LanConfigParam_IPv6StaticRouter2MAC{},
// IPv6StaticRouter2PrefixLength: &LanConfigParam_IPv6StaticRouter2PrefixLength{},
// IPv6StaticRouter2PrefixValue: &LanConfigParam_IPv6StaticRouter2PrefixValue{},
// IPv6DynamicRouterInfoSets: &LanConfigParam_IPv6DynamicRouterInfoSets{},
// IPv6DynamicRouterInfoIP: make([]*LanConfigParam_IPv6DynamicRouterInfoIP, 0),
// IPv6DynamicRouterInfoMAC: make([]*LanConfigParam_IPv6DynamicRouterInfoMAC, 0),
// IPv6DynamicRouterInfoPrefixLength: make([]*LanConfigParam_IPv6DynamicRouterInfoPrefixLength, 0),
// IPv6DynamicRouterInfoPrefixValue: make([]*LanConfigParam_IPv6DynamicRouterInfoPrefixValue, 0),
// IPv6DynamicRouterReceivedHopLimit: &LanConfigParam_IPv6DynamicRouterReceivedHopLimit{},
// IPv6NDSLAACTimingConfigSupport: &LanConfigParam_IPv6NDSLAACTimingConfigSupport{},
// IPv6NDSLAACTimingConfig: make([]*LanConfigParam_IPv6NDSLAACTimingConfig, 0),
}
if err := c.GetLanConfigParamsFor(ctx, channelNumber, lanConfigParams); err != nil {
return nil, err
}
return lanConfigParams, nil
}
func (c *Client) GetLanConfigParamsFull(ctx context.Context, channelNumber uint8) (*LanConfigParams, error) {
lanConfigParams := &LanConfigParams{
SetInProgress: &LanConfigParam_SetInProgress{},
AuthTypeSupport: &LanConfigParam_AuthTypeSupport{},
AuthTypeEnables: &LanConfigParam_AuthTypeEnables{},
IP: &LanConfigParam_IP{},
IPSource: &LanConfigParam_IPSource{},
MAC: &LanConfigParam_MAC{},
SubnetMask: &LanConfigParam_SubnetMask{},
IPv4HeaderParams: &LanConfigParam_IPv4HeaderParams{},
PrimaryRMCPPort: &LanConfigParam_PrimaryRMCPPort{},
SecondaryRMCPPort: &LanConfigParam_SecondaryRMCPPort{},
ARPControl: &LanConfigParam_ARPControl{},
GratuitousARPInterval: &LanConfigParam_GratuitousARPInterval{},
DefaultGatewayIP: &LanConfigParam_DefaultGatewayIP{},
DefaultGatewayMAC: &LanConfigParam_DefaultGatewayMAC{},
BackupGatewayIP: &LanConfigParam_BackupGatewayIP{},
BackupGatewayMAC: &LanConfigParam_BackupGatewayMAC{},
CommunityString: &LanConfigParam_CommunityString{},
AlertDestinationsCount: &LanConfigParam_AlertDestinationsCount{},
AlertDestinationTypes: make([]*LanConfigParam_AlertDestinationType, 0),
AlertDestinationAddresses: make([]*LanConfigParam_AlertDestinationAddress, 0),
VLANID: &LanConfigParam_VLANID{},
VLANPriority: &LanConfigParam_VLANPriority{},
CipherSuitesSupport: &LanConfigParam_CipherSuitesSupport{},
CipherSuitesID: &LanConfigParam_CipherSuitesID{},
CipherSuitesPrivLevel: &LanConfigParam_CipherSuitesPrivLevel{},
AlertDestinationVLANs: make([]*LanConfigParam_AlertDestinationVLAN, 0),
BadPasswordThreshold: &LanConfigParam_BadPasswordThreshold{},
IPv6Support: &LanConfigParam_IPv6Support{},
IPv6Enables: &LanConfigParam_IPv6Enables{},
IPv6StaticTrafficClass: &LanConfigParam_IPv6StaticTrafficClass{},
IPv6StaticHopLimit: &LanConfigParam_IPv6StaticHopLimit{},
IPv6FlowLabel: &LanConfigParam_IPv6FlowLabel{},
IPv6Status: &LanConfigParam_IPv6Status{},
IPv6StaticAddresses: make([]*LanConfigParam_IPv6StaticAddress, 0),
IPv6DHCPv6StaticDUIDCount: &LanConfigParam_IPv6DHCPv6StaticDUIDCount{},
IPv6DHCPv6StaticDUIDs: make([]*LanConfigParam_IPv6DHCPv6StaticDUID, 0),
IPv6DynamicAddresses: make([]*LanConfigParam_IPv6DynamicAddress, 0),
IPv6DHCPv6DynamicDUIDCount: &LanConfigParam_IPv6DHCPv6DynamicDUIDCount{},
IPv6DHCPv6DynamicDUIDs: make([]*LanConfigParam_IPv6DHCPv6DynamicDUID, 0),
IPv6DHCPv6TimingConfigSupport: &LanConfigParam_IPv6DHCPv6TimingConfigSupport{},
IPv6DHCPv6TimingConfig: make([]*LanConfigParam_IPv6DHCPv6TimingConfig, 0),
IPv6RouterAddressConfigControl: &LanConfigParam_IPv6RouterAddressConfigControl{},
IPv6StaticRouter1IP: &LanConfigParam_IPv6StaticRouter1IP{},
IPv6StaticRouter1MAC: &LanConfigParam_IPv6StaticRouter1MAC{},
IPv6StaticRouter1PrefixLength: &LanConfigParam_IPv6StaticRouter1PrefixLength{},
IPv6StaticRouter1PrefixValue: &LanConfigParam_IPv6StaticRouter1PrefixValue{},
IPv6StaticRouter2IP: &LanConfigParam_IPv6StaticRouter2IP{},
IPv6StaticRouter2MAC: &LanConfigParam_IPv6StaticRouter2MAC{},
IPv6StaticRouter2PrefixLength: &LanConfigParam_IPv6StaticRouter2PrefixLength{},
IPv6StaticRouter2PrefixValue: &LanConfigParam_IPv6StaticRouter2PrefixValue{},
IPv6DynamicRouterInfoSets: &LanConfigParam_IPv6DynamicRouterInfoSets{},
IPv6DynamicRouterInfoIP: make([]*LanConfigParam_IPv6DynamicRouterInfoIP, 0),
IPv6DynamicRouterInfoMAC: make([]*LanConfigParam_IPv6DynamicRouterInfoMAC, 0),
IPv6DynamicRouterInfoPrefixLength: make([]*LanConfigParam_IPv6DynamicRouterInfoPrefixLength, 0),
IPv6DynamicRouterInfoPrefixValue: make([]*LanConfigParam_IPv6DynamicRouterInfoPrefixValue, 0),
IPv6DynamicRouterReceivedHopLimit: &LanConfigParam_IPv6DynamicRouterReceivedHopLimit{},
IPv6NDSLAACTimingConfigSupport: &LanConfigParam_IPv6NDSLAACTimingConfigSupport{},
IPv6NDSLAACTimingConfig: make([]*LanConfigParam_IPv6NDSLAACTimingConfig, 0),
}
if err := c.GetLanConfigParamsFor(ctx, channelNumber, lanConfigParams); err != nil {
return nil, err
}
return lanConfigParams, nil
}
// GetLanConfigParamsFor get the lan config params.
// You can initialize specific fields of LanConfigParams struct, which indicates to only get params for those fields.
func (c *Client) GetLanConfigParamsFor(ctx context.Context, channelNumber uint8, lanConfigParams *LanConfigParams) error {
if lanConfigParams == nil {
return nil
}
var canIgnore = buildCanIgnoreFn(
0x80, // parameter not supported
)
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.SetInProgress); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.AuthTypeSupport); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.AuthTypeEnables); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IP); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPSource); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.MAC); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.SubnetMask); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv4HeaderParams); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.PrimaryRMCPPort); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.SecondaryRMCPPort); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.ARPControl); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.GratuitousARPInterval); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.DefaultGatewayIP); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.DefaultGatewayMAC); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.BackupGatewayIP); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.BackupGatewayMAC); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.CommunityString); canIgnore(err) != nil {
return err
}
alertDestinationsCount := uint8(0)
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.AlertDestinationsCount); err != nil {
if canIgnore(err) != nil {
return err
}
} else {
if lanConfigParams.AlertDestinationsCount != nil {
alertDestinationsCount = lanConfigParams.AlertDestinationsCount.Count
}
}
if lanConfigParams.AlertDestinationTypes != nil {
if len(lanConfigParams.AlertDestinationTypes) == 0 && alertDestinationsCount > 0 {
count := alertDestinationsCount + 1
lanConfigParams.AlertDestinationTypes = make([]*LanConfigParam_AlertDestinationType, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.AlertDestinationTypes[i] = &LanConfigParam_AlertDestinationType{
SetSelector: i,
}
}
}
for _, alertDestinationType := range lanConfigParams.AlertDestinationTypes {
if err := c.GetLanConfigParamFor(ctx, channelNumber, alertDestinationType); err != nil {
return err
}
}
}
if lanConfigParams.AlertDestinationAddresses != nil {
if len(lanConfigParams.AlertDestinationAddresses) == 0 && alertDestinationsCount > 0 {
count := alertDestinationsCount + 1
lanConfigParams.AlertDestinationAddresses = make([]*LanConfigParam_AlertDestinationAddress, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.AlertDestinationAddresses[i] = &LanConfigParam_AlertDestinationAddress{
SetSelector: i,
}
}
}
for _, alertDestinationAddress := range lanConfigParams.AlertDestinationAddresses {
if err := c.GetLanConfigParamFor(ctx, channelNumber, alertDestinationAddress); err != nil {
return err
}
}
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.VLANID); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.VLANPriority); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.CipherSuitesSupport); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.CipherSuitesID); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.CipherSuitesPrivLevel); canIgnore(err) != nil {
return err
}
if lanConfigParams.AlertDestinationVLANs != nil {
if len(lanConfigParams.AlertDestinationVLANs) == 0 && alertDestinationsCount > 0 {
count := alertDestinationsCount + 1
lanConfigParams.AlertDestinationVLANs = make([]*LanConfigParam_AlertDestinationVLAN, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.AlertDestinationVLANs[i] = &LanConfigParam_AlertDestinationVLAN{
SetSelector: i,
}
}
}
for _, alertDestinationVLAN := range lanConfigParams.AlertDestinationVLANs {
if err := c.GetLanConfigParamFor(ctx, channelNumber, alertDestinationVLAN); err != nil {
return err
}
}
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.BadPasswordThreshold); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6Support); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6Enables); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticTrafficClass); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticHopLimit); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6FlowLabel); canIgnore(err) != nil {
return err
}
var ipv6StaticAddressMax uint8
var ipv6DynamicAddressMax uint8
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6Status); err != nil {
if canIgnore(err) != nil {
return err
}
} else {
if lanConfigParams.IPv6Status != nil {
ipv6StaticAddressMax = lanConfigParams.IPv6Status.StaticAddressMax
ipv6DynamicAddressMax = lanConfigParams.IPv6Status.DynamicAddressMax
}
}
if lanConfigParams.IPv6StaticAddresses != nil {
if len(lanConfigParams.IPv6StaticAddresses) == 0 && ipv6StaticAddressMax > 0 {
count := ipv6StaticAddressMax
lanConfigParams.IPv6StaticAddresses = make([]*LanConfigParam_IPv6StaticAddress, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.IPv6StaticAddresses[i] = &LanConfigParam_IPv6StaticAddress{
SetSelector: i,
}
}
}
for _, ipv6StaticAddress := range lanConfigParams.IPv6StaticAddresses {
if err := c.GetLanConfigParamFor(ctx, channelNumber, ipv6StaticAddress); err != nil {
return err
}
}
}
var ipv6DHCPv6StaticDUIDCount uint8
if lanConfigParams.IPv6DHCPv6StaticDUIDCount != nil {
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6DHCPv6StaticDUIDCount); err != nil {
if canIgnore(err) != nil {
return err
}
} else {
ipv6DHCPv6StaticDUIDCount = lanConfigParams.IPv6DHCPv6StaticDUIDCount.Max
}
}
if lanConfigParams.IPv6DHCPv6StaticDUIDs != nil {
if len(lanConfigParams.IPv6DHCPv6StaticDUIDs) == 0 && ipv6DHCPv6StaticDUIDCount > 0 {
count := ipv6DHCPv6StaticDUIDCount
lanConfigParams.IPv6DHCPv6StaticDUIDs = make([]*LanConfigParam_IPv6DHCPv6StaticDUID, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.IPv6DHCPv6StaticDUIDs[i] = &LanConfigParam_IPv6DHCPv6StaticDUID{
SetSelector: i,
}
}
}
for _, ipv6DHCPv6StaticDUID := range lanConfigParams.IPv6DHCPv6StaticDUIDs {
if err := c.GetLanConfigParamFor(ctx, channelNumber, ipv6DHCPv6StaticDUID); err != nil {
return err
}
}
}
if lanConfigParams.IPv6DynamicAddresses != nil {
if len(lanConfigParams.IPv6DynamicAddresses) == 0 && ipv6DynamicAddressMax > 0 {
count := ipv6DynamicAddressMax
lanConfigParams.IPv6DynamicAddresses = make([]*LanConfigParam_IPv6DynamicAddress, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.IPv6DynamicAddresses[i] = &LanConfigParam_IPv6DynamicAddress{
SetSelector: i,
}
}
}
for _, ipv6DynamicAddress := range lanConfigParams.IPv6DynamicAddresses {
if err := c.GetLanConfigParamFor(ctx, channelNumber, ipv6DynamicAddress); err != nil {
return err
}
}
}
var ipv6DHCPv6DynamicDUIDCount uint8
if lanConfigParams.IPv6DHCPv6DynamicDUIDCount != nil {
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6DHCPv6DynamicDUIDCount); err != nil {
if canIgnore(err) != nil {
return err
}
} else {
if lanConfigParams.IPv6DHCPv6DynamicDUIDCount != nil {
ipv6DHCPv6DynamicDUIDCount = lanConfigParams.IPv6DHCPv6DynamicDUIDCount.Max
}
}
}
if lanConfigParams.IPv6DHCPv6DynamicDUIDs != nil {
if len(lanConfigParams.IPv6DHCPv6DynamicDUIDs) == 0 && ipv6DHCPv6DynamicDUIDCount > 0 {
// Todo
// count := ipv6DHCPv6DynamicDUIDCount
// lanConfig.IPv6DHCPv6DynamicDUIDs = make([]*LanConfigParam_IPv6DHCPv6DynamicDUID, count)
// for i := uint8(0); i < count; i++ {
// lanConfig.IPv6DHCPv6DynamicDUIDs[i] = &LanConfigParam_IPv6DHCPv6DynamicDUID{
// SetSelector: i,
// }
// }
// for _, ipv6DHCPv6DynamicDUID := range lanConfig.IPv6DHCPv6DynamicDUIDs {
// if err := c.GetLanConfigParamFor(ctx, channelNumber, ipv6DHCPv6DynamicDUID); err != nil {
// return err
// }
// }
}
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6DHCPv6TimingConfigSupport); canIgnore(err) != nil {
return err
}
if lanConfigParams.IPv6DHCPv6TimingConfig != nil {
// Todo
// if len(lanConfig.IPv6DHCPv6TimingConfig) == 0 && ipv6DynamicAddressMax > 0 {
// count := ipv6DynamicAddressMax
// lanConfig.IPv6DHCPv6TimingConfig = make([]*LanConfigParam_IPv6DHCPv6TimingConfig, count)
// for i := uint8(0); i < count; i++ {
// lanConfig.IPv6DHCPv6TimingConfig[i] = &LanConfigParam_IPv6DHCPv6TimingConfig{
// SetSelector: i,
// }
// }
// for _, ipv6DHCPv6TimingConfig := range lanConfig.IPv6DHCPv6TimingConfig {
// if err := c.GetLanConfigParamFor(ctx, channelNumber, ipv6DHCPv6TimingConfig); err != nil {
// return err
// }
// }
// }
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6RouterAddressConfigControl); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticRouter1IP); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticRouter1MAC); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticRouter1PrefixLength); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticRouter1PrefixValue); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticRouter2IP); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticRouter2MAC); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticRouter2PrefixLength); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6StaticRouter2PrefixValue); canIgnore(err) != nil {
return err
}
var ipv6DynamicRouterInfoCount uint8
if lanConfigParams.IPv6DynamicRouterInfoSets != nil {
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6DynamicRouterInfoSets); err != nil {
if canIgnore(err) != nil {
return err
}
} else {
if lanConfigParams.IPv6DynamicRouterInfoSets != nil {
ipv6DynamicRouterInfoCount = lanConfigParams.IPv6DynamicRouterInfoSets.Count
}
}
}
if lanConfigParams.IPv6DynamicRouterInfoIP != nil {
if len(lanConfigParams.IPv6DynamicRouterInfoIP) == 0 && ipv6DynamicRouterInfoCount > 0 {
count := ipv6DynamicRouterInfoCount
lanConfigParams.IPv6DynamicRouterInfoIP = make([]*LanConfigParam_IPv6DynamicRouterInfoIP, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.IPv6DynamicRouterInfoIP[i] = &LanConfigParam_IPv6DynamicRouterInfoIP{
SetSelector: i,
}
}
for _, ipv6DynamicRouterInfoIP := range lanConfigParams.IPv6DynamicRouterInfoIP {
if err := c.GetLanConfigParamFor(ctx, channelNumber, ipv6DynamicRouterInfoIP); err != nil {
return err
}
}
}
}
if lanConfigParams.IPv6DynamicRouterInfoMAC != nil {
if len(lanConfigParams.IPv6DynamicRouterInfoMAC) == 0 && ipv6DynamicRouterInfoCount > 0 {
count := ipv6DynamicRouterInfoCount
lanConfigParams.IPv6DynamicRouterInfoMAC = make([]*LanConfigParam_IPv6DynamicRouterInfoMAC, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.IPv6DynamicRouterInfoMAC[i] = &LanConfigParam_IPv6DynamicRouterInfoMAC{
SetSelector: i,
}
}
for _, ipv6DynamicRouterInfoMAC := range lanConfigParams.IPv6DynamicRouterInfoMAC {
if err := c.GetLanConfigParamFor(ctx, channelNumber, ipv6DynamicRouterInfoMAC); err != nil {
return err
}
}
}
}
if lanConfigParams.IPv6DynamicRouterInfoPrefixLength != nil {
if len(lanConfigParams.IPv6DynamicRouterInfoPrefixLength) == 0 && ipv6DynamicRouterInfoCount > 0 {
count := ipv6DynamicRouterInfoCount
lanConfigParams.IPv6DynamicRouterInfoPrefixLength = make([]*LanConfigParam_IPv6DynamicRouterInfoPrefixLength, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.IPv6DynamicRouterInfoPrefixLength[i] = &LanConfigParam_IPv6DynamicRouterInfoPrefixLength{
SetSelector: i,
}
}
for _, ipv6DynamicRouterInfoPrefixLength := range lanConfigParams.IPv6DynamicRouterInfoPrefixLength {
if err := c.GetLanConfigParamFor(ctx, channelNumber, ipv6DynamicRouterInfoPrefixLength); err != nil {
return err
}
}
}
}
if lanConfigParams.IPv6DynamicRouterInfoPrefixValue != nil {
if len(lanConfigParams.IPv6DynamicRouterInfoPrefixValue) == 0 && ipv6DynamicRouterInfoCount > 0 {
count := ipv6DynamicRouterInfoCount
lanConfigParams.IPv6DynamicRouterInfoPrefixValue = make([]*LanConfigParam_IPv6DynamicRouterInfoPrefixValue, count)
for i := uint8(0); i < count; i++ {
lanConfigParams.IPv6DynamicRouterInfoPrefixValue[i] = &LanConfigParam_IPv6DynamicRouterInfoPrefixValue{
SetSelector: i,
}
}
for _, ipv6DynamicRouterInfoPrefixValue := range lanConfigParams.IPv6DynamicRouterInfoPrefixValue {
if err := c.GetLanConfigParamFor(ctx, channelNumber, ipv6DynamicRouterInfoPrefixValue); err != nil {
return err
}
}
}
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6DynamicRouterReceivedHopLimit); canIgnore(err) != nil {
return err
}
if err := c.GetLanConfigParamFor(ctx, channelNumber, lanConfigParams.IPv6NDSLAACTimingConfigSupport); canIgnore(err) != nil {
return err
}
if lanConfigParams.IPv6NDSLAACTimingConfig != nil {
// Todo
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_last_processed_event_id.go 0000664 0000000 0000000 00000004021 14741105271 0026003 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"time"
)
// 30.6 Get Last Processed Event ID Command
type GetLastProcessedEventIdRequest struct {
// empty
}
type GetLastProcessedEventIdResponse struct {
MostRecentAdditionTime time.Time
LastRecordID uint16 // Record ID for last record in SEL. Returns FFFFh if SEL is empty.
LastSoftwareProcessedEventRecordID uint16
LastBMCProcessedEventRecordID uint16 // Returns 0000h when event has been processed but could not be logged because the SEL is full or logging has been disabled.
}
func (req *GetLastProcessedEventIdRequest) Command() Command {
return CommandGetLastProcessedEventId
}
func (req *GetLastProcessedEventIdRequest) Pack() []byte {
return []byte{}
}
func (res *GetLastProcessedEventIdResponse) Unpack(msg []byte) error {
if len(msg) < 10 {
return ErrUnpackedDataTooShort
}
ts, _, _ := unpackUint32L(msg, 0)
res.MostRecentAdditionTime = parseTimestamp(ts)
res.LastRecordID, _, _ = unpackUint16L(msg, 4)
res.LastSoftwareProcessedEventRecordID, _, _ = unpackUint16L(msg, 6)
res.LastBMCProcessedEventRecordID, _, _ = unpackUint16L(msg, 8)
return nil
}
func (r *GetLastProcessedEventIdResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "cannot execute command, SEL erase in progress",
}
}
func (res *GetLastProcessedEventIdResponse) Format() string {
return fmt.Sprintf(`
Last SEL addition : %s
Last SEL record ID : %#04x (%d)
Last S/W processed ID : %#04x (%d)
Last BMC processed ID : %#04x (%d)
`,
res.MostRecentAdditionTime.String(),
res.LastRecordID, res.LastRecordID,
res.LastSoftwareProcessedEventRecordID, res.LastSoftwareProcessedEventRecordID,
res.LastBMCProcessedEventRecordID, res.LastBMCProcessedEventRecordID,
)
}
func (c *Client) GetLastProcessedEventId(ctx context.Context) (response *GetLastProcessedEventIdResponse, err error) {
request := &GetLastProcessedEventIdRequest{}
response = &GetLastProcessedEventIdResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_message.go 0000664 0000000 0000000 00000001756 14741105271 0022554 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.6 Get Message Command
type GetMessageRequest struct {
// empty
}
type GetMessageResponse struct {
ChannelNumber uint8
MessageData []byte
}
func (req *GetMessageRequest) Command() Command {
return CommandGetMessage
}
func (req *GetMessageRequest) Pack() []byte {
return []byte{}
}
func (res *GetMessageResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "data not available (queue / buffer empty)",
}
}
func (res *GetMessageResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
res.ChannelNumber, _, _ = unpackUint8(msg, 0)
res.MessageData, _, _ = unpackBytes(msg, 1, len(msg)-1)
return nil
}
func (res *GetMessageResponse) Format() string {
return ""
}
func (c *Client) GetMessage(ctx context.Context) (response *GetMessageResponse, err error) {
request := &GetMessageRequest{}
response = &GetMessageResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_message_flags.go 0000664 0000000 0000000 00000002742 14741105271 0023724 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.4 Get Message Flags Command
type GetMessageFlagsRequest struct {
// empty
}
type GetMessageFlagsResponse struct {
OEM2Available bool
OEM1Available bool
OEM0Available bool
WatchdogPreTimeoutInterruptOccurred bool
EventMessageBufferFull bool
ReceiveMessageQueueAvailable bool // One or more messages ready for reading from Receive Message Queue
}
func (req *GetMessageFlagsRequest) Command() Command {
return CommandGetMessageFlags
}
func (req *GetMessageFlagsRequest) Pack() []byte {
return []byte{}
}
func (res *GetMessageFlagsResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
b, _, _ := unpackUint8(msg, 0)
res.OEM2Available = isBit7Set(b)
res.OEM1Available = isBit6Set(b)
res.OEM0Available = isBit5Set(b)
res.WatchdogPreTimeoutInterruptOccurred = isBit3Set(b)
res.EventMessageBufferFull = isBit1Set(b)
res.ReceiveMessageQueueAvailable = isBit0Set(b)
return nil
}
func (*GetMessageFlagsResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetMessageFlagsResponse) Format() string {
// Todo
return ""
}
func (c *Client) GetMessageFlags(ctx context.Context) (response *GetMessageFlagsResponse, err error) {
request := &GetMessageFlagsRequest{}
response = &GetMessageFlagsResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_netfn_support.go 0000664 0000000 0000000 00000003211 14741105271 0024022 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 21.2 Get NetFn Support Command
type GetNetFnSupportRequest struct {
ChannelNumber uint8
}
type GetNetFnSupportResponse struct {
LUN3Support LUNSupport
LUN2Support LUNSupport
LUN1Support LUNSupport
LUN0Support LUNSupport
// Todo
NetFnPairsSupport []byte
}
type LUNSupport uint8
func (l LUNSupport) String() string {
m := map[LUNSupport]string{
0x00: "no commands supported",
0x01: "commands exist on LUN - no restriction",
0x02: "commands exist on LUN - restricted",
0x03: "reserved",
}
s, ok := m[l]
if ok {
return s
}
return ""
}
func (req *GetNetFnSupportRequest) Command() Command {
return CommandGetNetFnSupport
}
func (req *GetNetFnSupportRequest) Pack() []byte {
return []byte{req.ChannelNumber}
}
func (res *GetNetFnSupportResponse) Unpack(msg []byte) error {
if len(msg) < 17 {
return ErrUnpackedDataTooShortWith(len(msg), 17)
}
b, _, _ := unpackUint8(msg, 0)
res.LUN3Support = LUNSupport(b >> 6)
res.LUN2Support = LUNSupport((b & 0x3f) >> 4)
res.LUN1Support = LUNSupport((b & 0x0f) >> 2)
res.LUN0Support = LUNSupport(b & 0x03)
res.NetFnPairsSupport, _, _ = unpackBytes(msg, 1, 16)
return nil
}
func (*GetNetFnSupportResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetNetFnSupportResponse) Format() string {
// Todo
return ""
}
func (c *Client) GetNetFnSupport(ctx context.Context, channelNumber uint8) (response *GetNetFnSupportResponse, err error) {
request := &GetNetFnSupportRequest{
ChannelNumber: channelNumber,
}
response = &GetNetFnSupportResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_payload_activation_status.go 0000664 0000000 0000000 00000010176 14741105271 0026401 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 24.4 Get Payload Activation Status Command
type GetPayloadActivationStatusRequest struct {
PayloadType PayloadType
}
type GetPayloadActivationStatusResponse struct {
// [3:0] - Number of instances of given payload type that can be simultaneously activated on BMC. 1-based. 0h = reserved.
InstanceCapacity uint8
Instance01Activated bool
Instance02Activated bool
Instance03Activated bool
Instance04Activated bool
Instance05Activated bool
Instance06Activated bool
Instance07Activated bool
Instance08Activated bool
Instance09Activated bool
Instance10Activated bool
Instance11Activated bool
Instance12Activated bool
Instance13Activated bool
Instance14Activated bool
Instance15Activated bool
Instance16Activated bool
// Store the PayloadType specified in GetPayloadActivationStatusRequest
PayloadType PayloadType
}
func (req *GetPayloadActivationStatusRequest) Pack() []byte {
return []byte{byte(req.PayloadType)}
}
func (req *GetPayloadActivationStatusRequest) Command() Command {
return CommandGetPayloadActivationStatus
}
func (res *GetPayloadActivationStatusResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetPayloadActivationStatusResponse) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
res.InstanceCapacity = msg[0] + 1 // plus 1 cause of 1-based.
res.Instance01Activated = isBit0Set(msg[1])
res.Instance02Activated = isBit1Set(msg[1])
res.Instance03Activated = isBit2Set(msg[1])
res.Instance04Activated = isBit3Set(msg[1])
res.Instance05Activated = isBit4Set(msg[1])
res.Instance06Activated = isBit5Set(msg[1])
res.Instance07Activated = isBit6Set(msg[1])
res.Instance08Activated = isBit7Set(msg[1])
res.Instance09Activated = isBit0Set(msg[2])
res.Instance10Activated = isBit1Set(msg[2])
res.Instance11Activated = isBit2Set(msg[2])
res.Instance12Activated = isBit3Set(msg[2])
res.Instance13Activated = isBit4Set(msg[2])
res.Instance14Activated = isBit5Set(msg[2])
res.Instance15Activated = isBit6Set(msg[2])
res.Instance16Activated = isBit7Set(msg[2])
return nil
}
func (res *GetPayloadActivationStatusResponse) Format() string {
return fmt.Sprintf(` Payload Type : %s (%d)
Instance Capacity : %d
Instance 01 : %s
Instance 02 : %s
Instance 03 : %s
Instance 04 : %s
Instance 05 : %s
Instance 06 : %s
Instance 07 : %s
Instance 08 : %s
Instance 09 : %s
Instance 10 : %s
Instance 11 : %s
Instance 12 : %s
Instance 13 : %s
Instance 14 : %s
Instance 15 : %s
Instance 16 : %s`,
res.PayloadType.String(), res.PayloadType,
res.InstanceCapacity,
formatBool(res.Instance01Activated, "activated", "deactivated"),
formatBool(res.Instance02Activated, "activated", "deactivated"),
formatBool(res.Instance03Activated, "activated", "deactivated"),
formatBool(res.Instance04Activated, "activated", "deactivated"),
formatBool(res.Instance05Activated, "activated", "deactivated"),
formatBool(res.Instance06Activated, "activated", "deactivated"),
formatBool(res.Instance07Activated, "activated", "deactivated"),
formatBool(res.Instance08Activated, "activated", "deactivated"),
formatBool(res.Instance09Activated, "activated", "deactivated"),
formatBool(res.Instance10Activated, "activated", "deactivated"),
formatBool(res.Instance11Activated, "activated", "deactivated"),
formatBool(res.Instance12Activated, "activated", "deactivated"),
formatBool(res.Instance13Activated, "activated", "deactivated"),
formatBool(res.Instance14Activated, "activated", "deactivated"),
formatBool(res.Instance15Activated, "activated", "deactivated"),
formatBool(res.Instance16Activated, "activated", "deactivated"),
)
}
func (c *Client) GetPayloadActivationStatus(ctx context.Context, payloadType PayloadType) (response *GetPayloadActivationStatusResponse, err error) {
request := &GetPayloadActivationStatusRequest{
PayloadType: payloadType,
}
response = &GetPayloadActivationStatusResponse{}
response.PayloadType = request.PayloadType
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_pef_capabilities.go 0000664 0000000 0000000 00000004657 14741105271 0024416 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 30.1 Get PEF Capabilities Command
type GetPEFCapabilitiesRequest struct {
// empty
}
type GetPEFCapabilitiesResponse struct {
// PEF Version (BCD encoded, LSN first. 51h version 1.5)
PEFVersion uint8
SupportOEMEventFilter bool
SupportDiagnosticInterrupt bool
SupportOEMAction bool
SupportPowerCycle bool
SupportReset bool
SupportPowerDown bool
SupportAlert bool
EventFilterTableEntries uint8
}
func (req *GetPEFCapabilitiesRequest) Command() Command {
return CommandGetPEFCapabilities
}
func (req *GetPEFCapabilitiesRequest) Pack() []byte {
// empty request data
return []byte{}
}
func (res *GetPEFCapabilitiesResponse) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
res.PEFVersion = msg[0]
b1 := msg[1]
res.SupportOEMEventFilter = isBit7Set(b1)
res.SupportDiagnosticInterrupt = isBit5Set(b1)
res.SupportOEMAction = isBit4Set(b1)
res.SupportPowerCycle = isBit3Set(b1)
res.SupportReset = isBit2Set(b1)
res.SupportPowerDown = isBit1Set(b1)
res.SupportAlert = isBit0Set(b1)
res.EventFilterTableEntries = msg[2]
return nil
}
func (r *GetPEFCapabilitiesResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetPEFCapabilitiesResponse) Format() string {
return fmt.Sprintf(`PEF Version : %#2x
Event Filter Table Entries : %d
Support OEM Event Filtering : %s
Support Diagnostic Interrupt : %s
Support OEM Action : %s
Support Power Cycle : %s
Support Reset : %s
Support Power Down : %s
Support Alert : %s`,
res.PEFVersion,
res.EventFilterTableEntries,
formatBool(res.SupportOEMEventFilter, "supported", "not-supported"),
formatBool(res.SupportDiagnosticInterrupt, "supported", "not-supported"),
formatBool(res.SupportOEMAction, "supported", "not-supported"),
formatBool(res.SupportPowerCycle, "supported", "not-supported"),
formatBool(res.SupportReset, "supported", "not-supported"),
formatBool(res.SupportPowerDown, "supported", "not-supported"),
formatBool(res.SupportAlert, "supported", "not-supported"),
)
}
func (c *Client) GetPEFCapabilities(ctx context.Context) (response *GetPEFCapabilitiesResponse, err error) {
request := &GetPEFCapabilitiesRequest{}
response = &GetPEFCapabilitiesResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_pef_config_params.go 0000664 0000000 0000000 00000022051 14741105271 0024561 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 30.4 Get PEF Configuration Parameters Command
type GetPEFConfigParamRequest struct {
// [7] - 1b = get parameter revision only. 0b = get parameter
// [6:0] - Parameter selector
GetParamRevisionOnly bool
ParamSelector PEFConfigParamSelector
SetSelector uint8 // 00h if parameter does not require a Set Selector
BlockSelector uint8 // 00h if parameter does not require a block number
}
type GetPEFConfigParamResponse struct {
// Parameter revision.
//
// Format:
// - MSN = present revision.
// - LSN = oldest revision parameter is backward compatible with.
// - 11h for parameters in this specification.
ParamRevision uint8
// ParamData not returned when GetParamRevisionOnly is true
ParamData []byte
}
func (req *GetPEFConfigParamRequest) Command() Command {
return CommandGetPEFConfigParam
}
func (req *GetPEFConfigParamRequest) Pack() []byte {
// empty request data
out := make([]byte, 3)
b0 := uint8(req.ParamSelector) & 0x3f
if req.GetParamRevisionOnly {
b0 = setBit7(b0)
}
packUint8(b0, out, 0)
packUint8(req.SetSelector, out, 1)
packUint8(req.BlockSelector, out, 2)
return out
}
func (res *GetPEFConfigParamResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShort
}
res.ParamRevision = msg[0]
if len(msg) > 1 {
res.ParamData, _, _ = unpackBytes(msg, 1, len(msg)-1)
}
return nil
}
func (r *GetPEFConfigParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "parameter not supported",
}
}
func (res *GetPEFConfigParamResponse) Format() string {
return fmt.Sprintf(`
Parameter Revision : %#02x (%d)
Configuration Parameter Data : %# 02x`,
res.ParamRevision, res.ParamRevision,
res.ParamData,
)
}
func (c *Client) GetPEFConfigParam(ctx context.Context, getRevisionOnly bool, paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) (response *GetPEFConfigParamResponse, err error) {
request := &GetPEFConfigParamRequest{
GetParamRevisionOnly: getRevisionOnly,
ParamSelector: paramSelector,
SetSelector: setSelector,
BlockSelector: blockSelector,
}
response = &GetPEFConfigParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetPEFConfigParamFor(ctx context.Context, param PEFConfigParameter) error {
if isNilPEFConfigParameter(param) {
return nil
}
paramSelector, setSelector, blockSelector := param.PEFConfigParameter()
res, err := c.GetPEFConfigParam(ctx, false, paramSelector, setSelector, blockSelector)
if err != nil {
return fmt.Errorf("GetPEFConfigParameters for param (%s) failed, err: %w", paramSelector, err)
}
if err := param.Unpack(res.ParamData); err != nil {
return fmt.Errorf("unpack failed for param (%s), err: %w", paramSelector, err)
}
return nil
}
func (c *Client) GetPEFConfigParams(ctx context.Context) (pefConfigParams *PEFConfigParams, err error) {
pefConfigParams = &PEFConfigParams{
SetInProgress: &PEFConfigParam_SetInProgress{},
Control: &PEFConfigParam_Control{},
ActionGlobalControl: &PEFConfigParam_ActionGlobalControl{},
StartupDelay: &PEFConfigParam_StartupDelay{},
AlertStartupDelay: &PEFConfigParam_AlertStartupDelay{},
EventFiltersCount: &PEFConfigParam_EventFiltersCount{},
EventFilters: []*PEFConfigParam_EventFilter{},
EventFiltersData1: []*PEFConfigParam_EventFilterData1{},
AlertPoliciesCount: &PEFConfigParam_AlertPoliciesCount{},
AlertPolicies: []*PEFConfigParam_AlertPolicy{},
SystemGUID: &PEFConfigParam_SystemGUID{},
AlertStringsCount: &PEFConfigParam_AlertStringsCount{},
AlertStringKeys: []*PEFConfigParam_AlertStringKey{},
AlertStrings: []*PEFConfigParam_AlertString{},
// GroupControlsCount: &PEFConfigParam_GroupControlsCount{},
// GroupControls: []*PEFConfigParam_GroupControl{},
}
if err = c.GetPEFConfigParamsFor(ctx, pefConfigParams); err != nil {
return nil, fmt.Errorf("GetPEFConfigParamsFor failed, err: %w", err)
}
return pefConfigParams, nil
}
func (c *Client) GetPEFConfigParamsFor(ctx context.Context, pefConfigParams *PEFConfigParams) error {
if pefConfigParams == nil {
return nil
}
if pefConfigParams.SetInProgress != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.SetInProgress); err != nil {
return err
}
}
if pefConfigParams.Control != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.Control); err != nil {
return err
}
}
if pefConfigParams.ActionGlobalControl != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.ActionGlobalControl); err != nil {
return err
}
}
if pefConfigParams.StartupDelay != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.StartupDelay); err != nil {
return err
}
}
if pefConfigParams.AlertStartupDelay != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.AlertStartupDelay); err != nil {
return err
}
}
eventFiltersCount := uint8(0)
if pefConfigParams.EventFiltersCount != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.AlertPoliciesCount); err != nil {
return err
}
eventFiltersCount = pefConfigParams.EventFiltersCount.Value
}
if pefConfigParams.EventFilters != nil {
if len(pefConfigParams.EventFilters) == 0 && eventFiltersCount > 0 {
pefConfigParams.EventFilters = make([]*PEFConfigParam_EventFilter, eventFiltersCount)
for i := uint8(0); i < eventFiltersCount; i++ {
pefConfigParams.EventFilters[i] = &PEFConfigParam_EventFilter{
SetSelector: i + 1,
}
}
}
for _, eventFilter := range pefConfigParams.EventFilters {
if err := c.GetPEFConfigParamFor(ctx, eventFilter); err != nil {
return err
}
}
}
if pefConfigParams.EventFiltersData1 != nil {
if len(pefConfigParams.EventFiltersData1) == 0 && eventFiltersCount > 0 {
pefConfigParams.EventFiltersData1 = make([]*PEFConfigParam_EventFilterData1, eventFiltersCount)
for i := uint8(0); i < eventFiltersCount; i++ {
pefConfigParams.EventFiltersData1[i] = &PEFConfigParam_EventFilterData1{
SetSelector: i + 1,
}
}
}
for _, eventFilterData1 := range pefConfigParams.EventFiltersData1 {
if err := c.GetPEFConfigParamFor(ctx, eventFilterData1); err != nil {
return err
}
}
}
alertPoliciesCount := uint8(0)
if pefConfigParams.AlertPoliciesCount != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.AlertPoliciesCount); err != nil {
return err
}
alertPoliciesCount = pefConfigParams.AlertPoliciesCount.Value
}
if pefConfigParams.AlertPolicies != nil {
if len(pefConfigParams.AlertPolicies) == 0 && alertPoliciesCount > 0 {
pefConfigParams.AlertPolicies = make([]*PEFConfigParam_AlertPolicy, alertPoliciesCount)
for i := uint8(0); i < alertPoliciesCount; i++ {
pefConfigParams.AlertPolicies[i] = &PEFConfigParam_AlertPolicy{
SetSelector: i + 1,
}
}
}
for _, alertPolicy := range pefConfigParams.AlertPolicies {
if err := c.GetPEFConfigParamFor(ctx, alertPolicy); err != nil {
return err
}
}
}
if pefConfigParams.SystemGUID != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.SystemGUID); err != nil {
return err
}
}
alertStringsCount := uint8(0)
if pefConfigParams.AlertStringsCount != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.AlertStringsCount); err != nil {
return err
}
}
if pefConfigParams.AlertStringKeys != nil {
if len(pefConfigParams.AlertStringKeys) == 0 && alertStringsCount > 0 {
pefConfigParams.AlertStringKeys = make([]*PEFConfigParam_AlertStringKey, alertStringsCount)
for i := uint8(0); i < alertStringsCount; i++ {
pefConfigParams.AlertStringKeys[i] = &PEFConfigParam_AlertStringKey{
SetSelector: i,
}
}
}
for _, alertStringKey := range pefConfigParams.AlertStringKeys {
if err := c.GetPEFConfigParamFor(ctx, alertStringKey); err != nil {
return err
}
}
}
if pefConfigParams.AlertStrings != nil {
if len(pefConfigParams.AlertStrings) == 0 && alertStringsCount > 0 {
pefConfigParams.AlertStrings = make([]*PEFConfigParam_AlertString, alertStringsCount)
for i := uint8(0); i < alertStringsCount; i++ {
pefConfigParams.AlertStrings[i] = &PEFConfigParam_AlertString{
SetSelector: i,
}
}
}
for _, alertString := range pefConfigParams.AlertStrings {
if err := c.GetPEFConfigParamFor(ctx, alertString); err != nil {
return err
}
}
}
groupControlsCount := uint8(0)
if pefConfigParams.GroupControlsCount != nil {
if err := c.GetPEFConfigParamFor(ctx, pefConfigParams.GroupControlsCount); err != nil {
return err
}
}
if pefConfigParams.GroupControls != nil {
if len(pefConfigParams.GroupControls) == 0 && groupControlsCount > 0 {
pefConfigParams.GroupControls = make([]*PEFConfigParam_GroupControl, groupControlsCount)
for i := uint8(0); i < groupControlsCount; i++ {
pefConfigParams.GroupControls[i] = &PEFConfigParam_GroupControl{
SetSelector: i,
}
}
}
for _, groupControl := range pefConfigParams.GroupControls {
if err := c.GetPEFConfigParamFor(ctx, groupControl); err != nil {
return err
}
}
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_poh_counter.go 0000664 0000000 0000000 00000002751 14741105271 0023451 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 28.14 Get POH Counter Command
type GetPOHCounterRequest struct {
// empty
}
type GetPOHCounterResponse struct {
MinutesPerCount uint8
CounterReading uint32
}
func (res *GetPOHCounterResponse) Minutes() uint32 {
return res.CounterReading * uint32(res.MinutesPerCount)
}
func (req *GetPOHCounterRequest) Command() Command {
return CommandGetPOHCounter
}
func (req *GetPOHCounterRequest) Pack() []byte {
return []byte{}
}
func (res *GetPOHCounterResponse) Unpack(msg []byte) error {
if len(msg) < 5 {
return ErrUnpackedDataTooShortWith(len(msg), 5)
}
res.MinutesPerCount, _, _ = unpackUint8(msg, 0)
res.CounterReading, _, _ = unpackUint32L(msg, 1)
return nil
}
func (r *GetPOHCounterResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetPOHCounterResponse) Format() string {
totalMinutes := res.Minutes()
days := totalMinutes / 1440
minutes := totalMinutes - days*1440
hours := minutes / 60
return fmt.Sprintf(`POH Counter : %d days, %d hours
Minutes per count : %d
Counter reading : %d`,
days, hours,
res.MinutesPerCount,
res.CounterReading,
)
}
// This command returns the present reading of the POH (Power-On Hours) counter, plus the number of counts per hour.
func (c *Client) GetPOHCounter(ctx context.Context) (response *GetPOHCounterResponse, err error) {
request := &GetPOHCounterRequest{}
response = &GetPOHCounterResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sdr.go 0000664 0000000 0000000 00000016533 14741105271 0021717 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 33.12 Get SDR Command
type GetSDRRequest struct {
ReservationID uint16 // LS Byte first
RecordID uint16 // LS Byte first
ReadOffset uint8 // Offset into record
ReadBytes uint8 // FFh means read entire record
}
type GetSDRResponse struct {
NextRecordID uint16
RecordData []byte
}
func (req *GetSDRRequest) Pack() []byte {
msg := make([]byte, 6)
packUint16L(req.ReservationID, msg, 0)
packUint16L(req.RecordID, msg, 2)
packUint8(req.ReadOffset, msg, 4)
packUint8(req.ReadBytes, msg, 5)
return msg
}
func (req *GetSDRRequest) Command() Command {
return CommandGetSDR
}
func (res *GetSDRResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.NextRecordID, _, _ = unpackUint16L(msg, 0)
res.RecordData, _, _ = unpackBytes(msg, 2, len(msg)-2)
return nil
}
func (res *GetSDRResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetSDRResponse) Format() string {
return fmt.Sprintf("%v", res)
}
// GetSDR returns raw SDR record.
func (c *Client) GetSDR(ctx context.Context, recordID uint16) (response *GetSDRResponse, err error) {
request := &GetSDRRequest{
ReservationID: 0,
RecordID: recordID,
ReadOffset: 0,
ReadBytes: 0xff,
}
response = &GetSDRResponse{}
err = c.Exchange(ctx, request, response)
// try read partial data if err (ResponseError and CompletionCode) indicate
// reading full data (0xff) exceeds the maximum transfer length for the interface
if resErr, ok := err.(*ResponseError); ok {
if resErr.CompletionCode() == CompletionCodeCannotReturnRequestedDataBytes {
return c.getSDR(ctx, recordID)
}
}
return
}
func (c *Client) GetSDREnhanced(ctx context.Context, recordID uint16) (*SDR, error) {
res, err := c.GetSDR(ctx, recordID)
if err != nil {
return nil, fmt.Errorf("GetSDR failed for recordID (%#02x), err: %s", recordID, err)
}
sdr, err := ParseSDR(res.RecordData, res.NextRecordID)
if err != nil {
return nil, fmt.Errorf("ParseSDR failed, err: %w", err)
}
if err := c.enhanceSDR(ctx, sdr); err != nil {
return sdr, fmt.Errorf("enhanceSDR failed, err: %w", err)
}
return sdr, nil
}
// getSDR return SDR in a partial read way.
func (c *Client) getSDR(ctx context.Context, recordID uint16) (response *GetSDRResponse, err error) {
var data []byte
// the actual data length of the SDR can only be determined after the first GetSDR request/response.
dataLength := uint8(0)
reservationID := uint16(0)
readBytes := uint8(16)
readTotal := uint8(0)
readOffset := uint8(0)
for {
request := &GetSDRRequest{
ReservationID: reservationID,
RecordID: recordID,
ReadOffset: readOffset,
ReadBytes: readBytes,
}
response = &GetSDRResponse{}
if err = c.Exchange(ctx, request, response); err != nil {
return
}
// determine the total data length by parsing the SDR Header part
if readOffset == 0 {
if len(response.RecordData) < SDRRecordHeaderSize {
return nil, fmt.Errorf("too short record data for SDR header (%d/%d)", len(response.RecordData), SDRRecordHeaderSize)
}
dataLength = response.RecordData[4] + uint8(SDRRecordHeaderSize)
data = make([]byte, dataLength)
}
copy(data[readOffset:readOffset+readBytes], response.RecordData[:])
readOffset += uint8(len(response.RecordData))
readTotal += uint8(len(response.RecordData))
if readTotal >= dataLength {
break
}
if readOffset+readBytes > dataLength {
// decrease the readBytes for the last read.
readBytes = dataLength - readOffset
}
rsp, err := c.ReserveSDRRepo(ctx)
if err == nil {
reservationID = rsp.ReservationID
} else {
reservationID = 0
}
}
return &GetSDRResponse{
NextRecordID: response.NextRecordID,
RecordData: data,
}, nil
}
func (c *Client) GetSDRBySensorID(ctx context.Context, sensorNumber uint8) (*SDR, error) {
if SensorNumber(sensorNumber) == SensorNumberReserved {
return nil, fmt.Errorf("not valid sensorNumber, %#0x is reserved", sensorNumber)
}
var recordID uint16 = 0
for {
res, err := c.GetSDR(ctx, recordID)
if err != nil {
return nil, fmt.Errorf("GetSDR failed for recordID (%#02x), err: %s", recordID, err)
}
sdr, err := ParseSDR(res.RecordData, res.NextRecordID)
if err != nil {
return nil, fmt.Errorf("ParseSDR failed, err: %w", err)
}
if uint8(sdr.SensorNumber()) != sensorNumber {
recordID = sdr.NextRecordID
if recordID == 0xffff {
break
}
continue
}
if err := c.enhanceSDR(ctx, sdr); err != nil {
return sdr, fmt.Errorf("enhanceSDR failed, err: %w", err)
}
return sdr, nil
}
return nil, fmt.Errorf("not found SDR for sensor id (%#0x)", sensorNumber)
}
func (c *Client) GetSDRBySensorName(ctx context.Context, sensorName string) (*SDR, error) {
var recordID uint16 = 0
for {
res, err := c.GetSDR(ctx, recordID)
if err != nil {
return nil, fmt.Errorf("GetSDR failed for recordID (%#02x), err: %s", recordID, err)
}
sdr, err := ParseSDR(res.RecordData, res.NextRecordID)
if err != nil {
return nil, fmt.Errorf("ParseSDR failed, err: %w", err)
}
if sdr.SensorName() != sensorName {
recordID = sdr.NextRecordID
if recordID == 0xffff {
break
}
continue
}
if err := c.enhanceSDR(ctx, sdr); err != nil {
return sdr, fmt.Errorf("enhanceSDR failed, err: %w", err)
}
return sdr, nil
}
return nil, fmt.Errorf("not found SDR for sensor name (%s)", sensorName)
}
// GetSDRs fetches the SDR records with the specified RecordTypes.
// The parameter is a slice of SDRRecordType used as filter.
// Empty means to get all SDR records.
func (c *Client) GetSDRs(ctx context.Context, recordTypes ...SDRRecordType) ([]*SDR, error) {
var recordID uint16 = 0
var out = make([]*SDR, 0)
for {
sdr, err := c.GetSDREnhanced(ctx, recordID)
if err != nil {
return nil, fmt.Errorf("GetSDR for recordID (%#0x) failed, err: %s", recordID, err)
}
if len(recordTypes) == 0 {
out = append(out, sdr)
} else {
for _, v := range recordTypes {
if sdr.RecordHeader.RecordType == v {
out = append(out, sdr)
break
}
}
}
recordID = sdr.NextRecordID
if recordID == 0xffff {
break
}
}
return out, nil
}
// GetSDRsMap returns all Full/Compact SDRs grouped by GeneratorID and SensorNumber.
// The sensor name can only be got from SDR record.
// So use this method to construct a map from which you can get sensor name.
func (c *Client) GetSDRsMap(ctx context.Context) (SDRMapBySensorNumber, error) {
var out = make(map[GeneratorID]map[SensorNumber]*SDR)
var recordID uint16 = 0
for {
sdr, err := c.GetSDREnhanced(ctx, recordID)
if err != nil {
return nil, fmt.Errorf("GetSDR for recordID (%#0x) failed, err: %s", recordID, err)
}
var generatorID GeneratorID
var sensorNumber SensorNumber
recordType := sdr.RecordHeader.RecordType
switch recordType {
case SDRRecordTypeFullSensor:
generatorID = sdr.Full.GeneratorID
sensorNumber = sdr.Full.SensorNumber
case SDRRecordTypeCompactSensor:
generatorID = sdr.Compact.GeneratorID
sensorNumber = sdr.Compact.SensorNumber
}
if recordType == SDRRecordTypeFullSensor || recordType == SDRRecordTypeCompactSensor {
if _, ok := out[generatorID]; !ok {
out[generatorID] = make(map[SensorNumber]*SDR)
}
out[generatorID][sensorNumber] = sdr
}
recordID = sdr.NextRecordID
if recordID == 0xffff {
break
}
}
return out, nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sdr_repo_alloc_info.go 0000664 0000000 0000000 00000002611 14741105271 0025121 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 33.10 Get SDR Repository Allocation Info Command
type GetSDRRepoAllocInfoRequest struct {
// empty
}
type GetSDRRepoAllocInfoResponse struct {
PossibleAllocUnits uint16
AllocUnitsSize uint16 // Allocation unit size in bytes. 0000h indicates unspecified.
FreeAllocUnits uint16
LargestFreeBlock uint16
MaximumRecordSize uint8
}
func (req *GetSDRRepoAllocInfoRequest) Pack() []byte {
return nil
}
func (req *GetSDRRepoAllocInfoRequest) Command() Command {
return CommandGetSDRRepoAllocInfo
}
func (res *GetSDRRepoAllocInfoResponse) Unpack(msg []byte) error {
if len(msg) < 9 {
return ErrUnpackedDataTooShortWith(len(msg), 9)
}
res.PossibleAllocUnits, _, _ = unpackUint16L(msg, 0)
res.AllocUnitsSize, _, _ = unpackUint16L(msg, 2)
res.FreeAllocUnits, _, _ = unpackUint16L(msg, 4)
res.LargestFreeBlock, _, _ = unpackUint16L(msg, 6)
res.MaximumRecordSize, _, _ = unpackUint8(msg, 8)
return nil
}
func (res *GetSDRRepoAllocInfoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSDRRepoAllocInfoResponse) Format() string {
return fmt.Sprintf("%v", res)
}
func (c *Client) GetSDRRepoAllocInfo(ctx context.Context) (response *GetSDRRepoAllocInfoResponse, err error) {
request := &GetSDRRepoAllocInfoRequest{}
response = &GetSDRRepoAllocInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sdr_repo_info.go 0000664 0000000 0000000 00000006733 14741105271 0023760 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"time"
)
// 33.9 Get SDR Repository Info Command
type GetSDRRepoInfoRequest struct {
// empty
}
type GetSDRRepoInfoResponse struct {
SDRVersion uint8 // version number of the SDR command set for the SDR Device. 51h for this specification.
RecordCount uint16 // LS Byte first
FreeSpaceBytes uint16 // LS Byte first
MostRecentAdditionTime time.Time
MostRecentEraseTime time.Time
SDROperationSupport SDROperationSupport
}
type SDROperationSupport struct {
Overflow bool
SupportModalSDRRepoUpdate bool // A modal SDR Repository is only updated when the controller is in an SDR Repository update mode.
SupportNonModalSDRRepoUpdate bool // A non-modal SDR Repository can be written to at any time
SupportDeleteSDR bool
SupportPartialAddSDR bool
SupportReserveSDRRepo bool
SupportGetSDRRepoAllocInfo bool
}
func (req *GetSDRRepoInfoRequest) Pack() []byte {
return []byte{}
}
func (req *GetSDRRepoInfoRequest) Command() Command {
return CommandGetSDRRepoInfo
}
func (res *GetSDRRepoInfoResponse) Unpack(msg []byte) error {
if len(msg) < 14 {
return ErrUnpackedDataTooShortWith(len(msg), 14)
}
res.SDRVersion, _, _ = unpackUint8(msg, 0)
res.RecordCount, _, _ = unpackUint16L(msg, 1)
res.FreeSpaceBytes, _, _ = unpackUint16L(msg, 3)
addTS, _, _ := unpackUint32L(msg, 5)
res.MostRecentAdditionTime = parseTimestamp(addTS)
deleteTS, _, _ := unpackUint32L(msg, 9)
res.MostRecentEraseTime = parseTimestamp(deleteTS)
b, _, _ := unpackUint8(msg, 13)
res.SDROperationSupport = SDROperationSupport{
Overflow: isBit7Set(b),
SupportModalSDRRepoUpdate: isBit6Set(b),
SupportNonModalSDRRepoUpdate: isBit5Set(b),
SupportDeleteSDR: isBit3Set(b),
SupportPartialAddSDR: isBit2Set(b),
SupportReserveSDRRepo: isBit1Set(b),
SupportGetSDRRepoAllocInfo: isBit0Set(b),
}
return nil
}
func (res *GetSDRRepoInfoResponse) Format() string {
s := ""
if res.SDROperationSupport.SupportModalSDRRepoUpdate {
if s != "" {
s += "/ modal"
} else {
s += "modal"
}
}
if res.SDROperationSupport.SupportNonModalSDRRepoUpdate {
if s != "" {
s += "/ non-modal"
} else {
s += "non-modal"
}
}
return fmt.Sprintf(`SDR Version : %#02x
Record Count : %d
Free Space : %d bytes
Most recent Addition : %s
Most recent Erase : %s
SDR overflow : %v
SDR Repository Update Support : %s
Delete SDR supported : %v
Partial Add SDR supported : %v
Reserve SDR repository supported : %v
SDR Repository Alloc info supported : %v`,
res.SDRVersion,
res.RecordCount,
res.FreeSpaceBytes,
res.MostRecentAdditionTime.Format(timeFormat),
res.MostRecentEraseTime.Format(timeFormat),
res.SDROperationSupport.Overflow,
s,
res.SDROperationSupport.SupportDeleteSDR,
res.SDROperationSupport.SupportPartialAddSDR,
res.SDROperationSupport.SupportReserveSDRRepo,
res.SDROperationSupport.SupportGetSDRRepoAllocInfo,
)
}
func (res *GetSDRRepoInfoResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (c *Client) GetSDRRepoInfo(ctx context.Context) (response *GetSDRRepoInfoResponse, err error) {
request := &GetSDRRepoInfoRequest{}
response = &GetSDRRepoInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sel_alloc_info.go 0000664 0000000 0000000 00000003106 14741105271 0024067 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
type GetSELAllocInfoRequest struct {
// empty
}
type GetSELAllocInfoResponse struct {
PossibleAllocUnits uint16
AllocUnitsSize uint16 // Allocation unit size in bytes. 0000h indicates unspecified.
FreeAllocUnits uint16
LargestFreeBlock uint16
MaximumRecordSize uint8
}
func (req *GetSELAllocInfoRequest) Pack() []byte {
return []byte{}
}
func (req *GetSELAllocInfoRequest) Command() Command {
return CommandGetSELAllocInfo
}
func (res *GetSELAllocInfoResponse) Unpack(msg []byte) error {
if len(msg) < 9 {
return ErrUnpackedDataTooShortWith(len(msg), 9)
}
res.PossibleAllocUnits, _, _ = unpackUint16L(msg, 0)
res.AllocUnitsSize, _, _ = unpackUint16L(msg, 2)
res.FreeAllocUnits, _, _ = unpackUint16L(msg, 4)
res.LargestFreeBlock, _, _ = unpackUint16L(msg, 6)
res.MaximumRecordSize, _, _ = unpackUint8(msg, 8)
return nil
}
func (res *GetSELAllocInfoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSELAllocInfoResponse) Format() string {
return fmt.Sprintf(`# of Alloc Units : %d
Alloc Unit Size : %d
# Free Units : %d
Largest Free Blk : %d
Max Record Size : %d`,
res.PossibleAllocUnits,
res.AllocUnitsSize,
res.FreeAllocUnits,
res.LargestFreeBlock,
res.MaximumRecordSize,
)
}
func (c *Client) GetSELAllocInfo(ctx context.Context) (response *GetSELAllocInfoResponse, err error) {
request := &GetSELAllocInfoRequest{}
response = &GetSELAllocInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sel_entry.go 0000664 0000000 0000000 00000006371 14741105271 0023132 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 31.5 Get SEL Entry Command
type GetSELEntryRequest struct {
// LS Byte first. Only required for partial Get. Use 0000h otherwise.
ReservationID uint16
// SEL Record ID, LS Byte first.
// 0000h = GET FIRST ENTRY
// FFFFh = GET LAST ENTRY
RecordID uint16
// Offset into record
Offset uint8
// FFh means read entire record.
ReadBytes uint8
}
type GetSELEntryResponse struct {
NextRecordID uint16
Data []byte // Record Data, 16 bytes for entire record, at least 1 byte
}
func (req *GetSELEntryRequest) Command() Command {
return CommandGetSELEntry
}
func (req *GetSELEntryRequest) Pack() []byte {
var msg = make([]byte, 6)
packUint16L(req.ReservationID, msg, 0)
packUint16L(req.RecordID, msg, 2)
packUint8(req.Offset, msg, 4)
packUint8(req.ReadBytes, msg, 5)
return msg
}
func (res *GetSELEntryResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.NextRecordID, _, _ = unpackUint16L(msg, 0)
res.Data, _, _ = unpackBytesMost(msg, 2, 16)
return nil
}
func (*GetSELEntryResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "cannot execute command, SEL erase in progress",
}
}
func (res *GetSELEntryResponse) Format() string {
return fmt.Sprintf("%v", res)
}
// The reservationID is only required for partial Get, use 0000h otherwise.
func (c *Client) GetSELEntry(ctx context.Context, reservationID uint16, recordID uint16) (response *GetSELEntryResponse, err error) {
if _, err := c.GetSELInfo(ctx); err != nil {
return nil, fmt.Errorf("GetSELInfo failed, err: %w", err)
}
request := &GetSELEntryRequest{
ReservationID: reservationID,
RecordID: recordID,
Offset: 0,
ReadBytes: 0xff,
}
response = &GetSELEntryResponse{}
err = c.Exchange(ctx, request, response)
return
}
// GetSELEntries return all SEL records starting from the specified recordID.
// Pass 0 means retrieve all SEL entries starting from the first record.
func (c *Client) GetSELEntries(ctx context.Context, startRecordID uint16) ([]*SEL, error) {
// Todo
// Notice, this extra GetSELInfo call is used to make sure the GetSELEntry works properly.
// On Huawei TaiShan 200 (Model 2280), the NextRecordID (0xffff) in GetSELEntryResponse is NOT right occasionally.
// $ ipmitool -I lanplus -H x.x.x.x -U xxx -P xxx raw 0x0a 0x43 0x00 0x00 0x01 0x00 0x00 0xff -v
// RAW REQ (channel=0x0 netfn=0xa lun=0x0 cmd=0x43 data_len=6)
// RAW REQUEST (6 bytes)
// 00 00 01 00 00 ff
// RAW RSP (18 bytes)
// ff ff 01 00 02 6d 8e 91 5f 20 00 04 10 79 6f 02
// ff ff
//
// This extra GetSELInfo can avoid it. (I don't known why!)
if _, err := c.GetSELInfo(ctx); err != nil {
return nil, fmt.Errorf("GetSELInfo failed, err: %w", err)
}
var out = make([]*SEL, 0)
var recordID uint16 = startRecordID
for {
selEntry, err := c.GetSELEntry(ctx, 0, recordID)
if err != nil {
return nil, fmt.Errorf("GetSELEntry failed, err: %w", err)
}
c.DebugBytes("sel entry record data", selEntry.Data, 16)
sel, err := ParseSEL(selEntry.Data)
if err != nil {
return nil, fmt.Errorf("unpackSEL record failed, err: %w", err)
}
out = append(out, sel)
recordID = selEntry.NextRecordID
if recordID == 0xffff {
break
}
}
return out, nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sel_info.go 0000664 0000000 0000000 00000005321 14741105271 0022716 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"time"
)
// GetSELInfoRequest (31.2) command returns the number of entries in the SEL.
type GetSELInfoRequest struct {
// empty
}
type GetSELInfoResponse struct {
SELVersion uint8
Entries uint16
FreeBytes uint16
RecentAdditionTime time.Time
RecentEraseTime time.Time
OperationSupport SELOperationSupport
}
type SELOperationSupport struct {
Overflow bool
DeleteSEL bool
PartialAddSEL bool
ReserveSEL bool
GetSELAllocInfo bool
}
func (req *GetSELInfoRequest) Command() Command {
return CommandGetSELInfo
}
func (req *GetSELInfoRequest) Pack() []byte {
// empty request data
return []byte{}
}
func (res *GetSELInfoResponse) Unpack(msg []byte) error {
if len(msg) < 14 {
return ErrUnpackedDataTooShortWith(len(msg), 14)
}
res.SELVersion, _, _ = unpackUint8(msg, 0)
res.Entries, _, _ = unpackUint16L(msg, 1)
res.FreeBytes, _, _ = unpackUint16L(msg, 3)
addTS, _, _ := unpackUint32L(msg, 5)
res.RecentAdditionTime = parseTimestamp(addTS)
eraseTS, _, _ := unpackUint32L(msg, 9)
res.RecentEraseTime = parseTimestamp(eraseTS)
b := msg[13]
res.OperationSupport = SELOperationSupport{
Overflow: isBit7Set(b),
DeleteSEL: isBit3Set(b),
PartialAddSEL: isBit2Set(b),
ReserveSEL: isBit1Set(b),
GetSELAllocInfo: isBit0Set(b),
}
return nil
}
func (r *GetSELInfoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "cannot execute command, SEL erase in progress",
}
}
func (res *GetSELInfoResponse) Format() string {
var version string
if res.SELVersion == 0x51 {
version = "1.5"
}
var usedBytes int = int(res.Entries) * 16
totalBytes := usedBytes + int(res.FreeBytes)
var usedPct float64 = 100 * float64(usedBytes) / float64(totalBytes)
return fmt.Sprintf(`SEL Information
Version : %s (v1.5, v2 compliant)
Entries : %d
Free Space : %d bytes
Percent Used : %.2f%%
Last Add Time : %s
Last Del Time : %s
Overflow : %v
Delete SEL supported: : %v
Partial Add SEL supported: : %v
Reserve SEL supported : %v
Get SEL Alloc Info supported : %v`,
version,
res.Entries,
res.FreeBytes,
usedPct,
res.RecentAdditionTime,
res.RecentEraseTime,
res.OperationSupport.Overflow,
res.OperationSupport.DeleteSEL,
res.OperationSupport.PartialAddSEL,
res.OperationSupport.ReserveSEL,
res.OperationSupport.GetSELAllocInfo,
)
}
func (c *Client) GetSELInfo(ctx context.Context) (response *GetSELInfoResponse, err error) {
request := &GetSELInfoRequest{}
response = &GetSELInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sel_time.go 0000664 0000000 0000000 00000001736 14741105271 0022727 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"time"
)
// 31.10 Get SEL Time Command
type GetSELTimeRequest struct {
// empty
}
type GetSELTimeResponse struct {
// Present Timestamp clock reading
Time time.Time
}
func (req *GetSELTimeRequest) Pack() []byte {
return []byte{}
}
func (req *GetSELTimeRequest) Command() Command {
return CommandGetSELTime
}
func (res *GetSELTimeResponse) Unpack(msg []byte) error {
if len(msg) < 4 {
return ErrUnpackedDataTooShortWith(len(msg), 4)
}
t, _, _ := unpackUint32L(msg, 0)
res.Time = parseTimestamp(t)
return nil
}
func (res *GetSELTimeResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetSELTimeResponse) Format() string {
return fmt.Sprintf("%v", res)
}
func (c *Client) GetSELTime(ctx context.Context) (response *GetSELTimeResponse, err error) {
request := &GetSELTimeRequest{}
response = &GetSELTimeResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sel_time_utc_offset.go 0000664 0000000 0000000 00000002363 14741105271 0025145 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 31.11a Get SEL Time UTC Offset
type GetSELTimeUTCOffsetRequest struct {
// empty
}
type GetSELTimeUTCOffsetResponse struct {
// signed integer for the offset in minutes from UTC to SEL Time.
MinutesOffset int16
}
func (req *GetSELTimeUTCOffsetRequest) Pack() []byte {
return []byte{}
}
func (req *GetSELTimeUTCOffsetRequest) Command() Command {
return CommandGetSELTimeUTCOffset
}
func (res *GetSELTimeUTCOffsetResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
b, _, _ := unpackUint16L(msg, 0)
c := twosComplement(uint32(b), 16)
res.MinutesOffset = int16(c)
return nil
}
func (res *GetSELTimeUTCOffsetResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetSELTimeUTCOffsetResponse) Format() string {
return fmt.Sprintf("Offset : %d", res.MinutesOffset)
}
// GetSELTimeUTCOffset is used to retrieve the SEL Time UTC Offset (timezone)
func (c *Client) GetSELTimeUTCOffset(ctx context.Context) (response *GetSELTimeUTCOffsetResponse, err error) {
request := &GetSELTimeUTCOffsetRequest{}
response = &GetSELTimeUTCOffsetResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_self_test_results.go 0000664 0000000 0000000 00000001777 14741105271 0024704 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 20.4 Get Self Test Results Command
type GetSelfTestResultsRequest struct {
// empty
}
type GetSelfTestResultsResponse struct {
Byte1 uint8
Byte2 uint8
}
func (req *GetSelfTestResultsRequest) Command() Command {
return CommandGetSelfTestResults
}
func (req *GetSelfTestResultsRequest) Pack() []byte {
return []byte{}
}
func (res *GetSelfTestResultsResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSelfTestResultsResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.Byte1, _, _ = unpackUint8(msg, 0)
res.Byte2, _, _ = unpackUint8(msg, 1)
return nil
}
func (res *GetSelfTestResultsResponse) Format() string {
// Todo
return ""
}
func (c *Client) GetSelfTestResults(ctx context.Context) (response *GetSelfTestResultsResponse, err error) {
request := &GetSelfTestResultsRequest{}
response = &GetSelfTestResultsResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sensor_event_enable.go 0000664 0000000 0000000 00000011475 14741105271 0025147 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"strings"
)
// 35.11 Get Sensor Event Enable Command
type GetSensorEventEnableRequest struct {
SensorNumber uint8
}
// For event , true means the event has enabled.
type GetSensorEventEnableResponse struct {
EventMessagesDisabled bool
SensorScanningDisabled bool
SensorEventFlag
}
func (req *GetSensorEventEnableRequest) Command() Command {
return CommandGetSensorEventEnable
}
func (req *GetSensorEventEnableRequest) Pack() []byte {
out := make([]byte, 1)
packUint8(req.SensorNumber, out, 0)
return out
}
func (res *GetSensorEventEnableResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
b1, _, _ := unpackUint8(msg, 0)
res.EventMessagesDisabled = !isBit7Set(b1)
res.SensorScanningDisabled = !isBit6Set(b1)
if len(msg) >= 2 {
b2, _, _ := unpackUint8(msg, 1)
res.SensorEvent_UNC_High_Assert = isBit7Set(b2)
res.SensorEvent_UNC_Low_Assert = isBit6Set(b2)
res.SensorEvent_LNR_High_Assert = isBit5Set(b2)
res.SensorEvent_LNR_Low_Assert = isBit4Set(b2)
res.SensorEvent_LCR_High_Assert = isBit3Set(b2)
res.SensorEvent_LCR_Low_Assert = isBit2Set(b2)
res.SensorEvent_LNC_High_Assert = isBit1Set(b2)
res.SensorEvent_LNC_Low_Assert = isBit0Set(b2)
res.SensorEvent_State_7_Assert = isBit7Set(b2)
res.SensorEvent_State_6_Assert = isBit6Set(b2)
res.SensorEvent_State_5_Assert = isBit5Set(b2)
res.SensorEvent_State_4_Assert = isBit4Set(b2)
res.SensorEvent_State_3_Assert = isBit3Set(b2)
res.SensorEvent_State_2_Assert = isBit2Set(b2)
res.SensorEvent_State_1_Assert = isBit1Set(b2)
res.SensorEvent_State_0_Assert = isBit0Set(b2)
}
if len(msg) >= 3 {
b3, _, _ := unpackUint8(msg, 2)
res.SensorEvent_UNR_High_Assert = isBit3Set(b3)
res.SensorEvent_UNR_Low_Assert = isBit2Set(b3)
res.SensorEvent_UCR_High_Assert = isBit1Set(b3)
res.SensorEvent_UCR_Low_Assert = isBit0Set(b3)
res.SensorEvent_State_14_Assert = isBit6Set(b3)
res.SensorEvent_State_13_Assert = isBit5Set(b3)
res.SensorEvent_State_12_Assert = isBit4Set(b3)
res.SensorEvent_State_11_Assert = isBit3Set(b3)
res.SensorEvent_State_10_Assert = isBit2Set(b3)
res.SensorEvent_State_9_Assert = isBit1Set(b3)
res.SensorEvent_State_8_Assert = isBit0Set(b3)
}
if len(msg) >= 4 {
b4, _, _ := unpackUint8(msg, 3)
res.SensorEvent_UNC_High_Deassert = isBit7Set(b4)
res.SensorEvent_UNC_Low_Deassert = isBit6Set(b4)
res.SensorEvent_LNR_High_Deassert = isBit5Set(b4)
res.SensorEvent_LNR_Low_Deassert = isBit4Set(b4)
res.SensorEvent_LCR_High_Deassert = isBit3Set(b4)
res.SensorEvent_LCR_Low_Deassert = isBit2Set(b4)
res.SensorEvent_LNC_High_Deassert = isBit1Set(b4)
res.SensorEvent_LNC_Low_Deassert = isBit0Set(b4)
res.SensorEvent_State_7_Deassert = isBit7Set(b4)
res.SensorEvent_State_6_Deassert = isBit6Set(b4)
res.SensorEvent_State_5_Deassert = isBit5Set(b4)
res.SensorEvent_State_4_Deassert = isBit4Set(b4)
res.SensorEvent_State_3_Deassert = isBit3Set(b4)
res.SensorEvent_State_2_Deassert = isBit2Set(b4)
res.SensorEvent_State_1_Deassert = isBit1Set(b4)
res.SensorEvent_State_0_Deassert = isBit0Set(b4)
}
if len(msg) >= 5 {
b5, _, _ := unpackUint8(msg, 4)
res.SensorEvent_UNR_High_Deassert = isBit3Set(b5)
res.SensorEvent_UNR_Low_Deassert = isBit2Set(b5)
res.SensorEvent_UCR_High_Deassert = isBit1Set(b5)
res.SensorEvent_UCR_Low_Deassert = isBit0Set(b5)
res.SensorEvent_State_14_Deassert = isBit6Set(b5)
res.SensorEvent_State_13_Deassert = isBit5Set(b5)
res.SensorEvent_State_12_Deassert = isBit4Set(b5)
res.SensorEvent_State_11_Deassert = isBit3Set(b5)
res.SensorEvent_State_10_Deassert = isBit2Set(b5)
res.SensorEvent_State_9_Deassert = isBit1Set(b5)
res.SensorEvent_State_8_Deassert = isBit0Set(b5)
}
return nil
}
func (r *GetSensorEventEnableResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSensorEventEnableResponse) Format() string {
all := res.SensorEventFlag.TrueEvents()
asserted := SensorEvents(all).FilterAssert()
deasserted := SensorEvents(all).FilterDeassert()
var assertedStr = []string{}
var deassertedStr = []string{}
for _, v := range asserted {
assertedStr = append(assertedStr, v.String())
}
for _, v := range deasserted {
deassertedStr = append(deassertedStr, v.String())
}
return fmt.Sprintf(`Event Messages Disabled : %v
Sensor Scanning Disabled : %v
Enabled Assert Event : %s
Enabled Deassert Event : %s`,
res.EventMessagesDisabled,
res.SensorScanningDisabled,
strings.Join(assertedStr, "\n - "),
strings.Join(deassertedStr, "\n - "),
)
}
func (c *Client) GetSensorEventEnable(ctx context.Context, sensorNumber uint8) (response *GetSensorEventEnableResponse, err error) {
request := &GetSensorEventEnableRequest{
SensorNumber: sensorNumber,
}
response = &GetSensorEventEnableResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sensor_event_status.go 0000664 0000000 0000000 00000011712 14741105271 0025236 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"strings"
)
// 35.13 Get Sensor Event Status Command
type GetSensorEventStatusRequest struct {
SensorNumber uint8
}
// For event boolean value, true means the event has occurred.
type GetSensorEventStatusResponse struct {
EventMessagesDisabled bool
SensorScanningDisabled bool
ReadingUnavailable bool
SensorEventFlag
}
func (req *GetSensorEventStatusRequest) Command() Command {
return CommandGetSensorEventStatus
}
func (req *GetSensorEventStatusRequest) Pack() []byte {
out := make([]byte, 1)
packUint8(req.SensorNumber, out, 0)
return out
}
func (res *GetSensorEventStatusResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
b1, _, _ := unpackUint8(msg, 0)
res.EventMessagesDisabled = !isBit7Set(b1)
res.SensorScanningDisabled = !isBit6Set(b1)
res.ReadingUnavailable = isBit5Set(b1)
if len(msg) >= 2 {
b2, _, _ := unpackUint8(msg, 1)
res.SensorEvent_UNC_High_Assert = isBit7Set(b2)
res.SensorEvent_UNC_Low_Assert = isBit6Set(b2)
res.SensorEvent_LNR_High_Assert = isBit5Set(b2)
res.SensorEvent_LNR_Low_Assert = isBit4Set(b2)
res.SensorEvent_LCR_High_Assert = isBit3Set(b2)
res.SensorEvent_LCR_Low_Assert = isBit2Set(b2)
res.SensorEvent_LNC_High_Assert = isBit1Set(b2)
res.SensorEvent_LNC_Low_Assert = isBit0Set(b2)
res.SensorEvent_State_7_Assert = isBit7Set(b2)
res.SensorEvent_State_6_Assert = isBit6Set(b2)
res.SensorEvent_State_5_Assert = isBit5Set(b2)
res.SensorEvent_State_4_Assert = isBit4Set(b2)
res.SensorEvent_State_3_Assert = isBit3Set(b2)
res.SensorEvent_State_2_Assert = isBit2Set(b2)
res.SensorEvent_State_1_Assert = isBit1Set(b2)
res.SensorEvent_State_0_Assert = isBit0Set(b2)
}
if len(msg) >= 3 {
b3, _, _ := unpackUint8(msg, 2)
res.SensorEvent_UNR_High_Assert = isBit3Set(b3)
res.SensorEvent_UNR_Low_Assert = isBit2Set(b3)
res.SensorEvent_UCR_High_Assert = isBit1Set(b3)
res.SensorEvent_UCR_Low_Assert = isBit0Set(b3)
res.SensorEvent_State_14_Assert = isBit6Set(b3)
res.SensorEvent_State_13_Assert = isBit5Set(b3)
res.SensorEvent_State_12_Assert = isBit4Set(b3)
res.SensorEvent_State_11_Assert = isBit3Set(b3)
res.SensorEvent_State_10_Assert = isBit2Set(b3)
res.SensorEvent_State_9_Assert = isBit1Set(b3)
res.SensorEvent_State_8_Assert = isBit0Set(b3)
}
if len(msg) >= 4 {
b4, _, _ := unpackUint8(msg, 3)
res.SensorEvent_UNC_High_Deassert = isBit7Set(b4)
res.SensorEvent_UNC_Low_Deassert = isBit6Set(b4)
res.SensorEvent_LNR_High_Deassert = isBit5Set(b4)
res.SensorEvent_LNR_Low_Deassert = isBit4Set(b4)
res.SensorEvent_LCR_High_Deassert = isBit3Set(b4)
res.SensorEvent_LCR_Low_Deassert = isBit2Set(b4)
res.SensorEvent_LNC_High_Deassert = isBit1Set(b4)
res.SensorEvent_LNC_Low_Deassert = isBit0Set(b4)
res.SensorEvent_State_7_Deassert = isBit7Set(b4)
res.SensorEvent_State_6_Deassert = isBit6Set(b4)
res.SensorEvent_State_5_Deassert = isBit5Set(b4)
res.SensorEvent_State_4_Deassert = isBit4Set(b4)
res.SensorEvent_State_3_Deassert = isBit3Set(b4)
res.SensorEvent_State_2_Deassert = isBit2Set(b4)
res.SensorEvent_State_1_Deassert = isBit1Set(b4)
res.SensorEvent_State_0_Deassert = isBit0Set(b4)
}
if len(msg) >= 5 {
b5, _, _ := unpackUint8(msg, 4)
res.SensorEvent_UNR_High_Deassert = isBit3Set(b5)
res.SensorEvent_UNR_Low_Deassert = isBit2Set(b5)
res.SensorEvent_UCR_High_Deassert = isBit1Set(b5)
res.SensorEvent_UCR_Low_Deassert = isBit0Set(b5)
res.SensorEvent_State_14_Deassert = isBit6Set(b5)
res.SensorEvent_State_13_Deassert = isBit5Set(b5)
res.SensorEvent_State_12_Deassert = isBit4Set(b5)
res.SensorEvent_State_11_Deassert = isBit3Set(b5)
res.SensorEvent_State_10_Deassert = isBit2Set(b5)
res.SensorEvent_State_9_Deassert = isBit1Set(b5)
res.SensorEvent_State_8_Deassert = isBit0Set(b5)
}
return nil
}
func (res *GetSensorEventStatusResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSensorEventStatusResponse) Format() string {
all := res.SensorEventFlag.TrueEvents()
asserted := SensorEvents(all).FilterAssert()
deasserted := SensorEvents(all).FilterDeassert()
var assertedStr = []string{}
var deassertedStr = []string{}
for _, v := range asserted {
assertedStr = append(assertedStr, v.String())
}
for _, v := range deasserted {
deassertedStr = append(deassertedStr, v.String())
}
return fmt.Sprintf(`Event Messages Disabled : %v
Sensor Scanning Disabled : %v
Reading State Unavailable : %v
Occurred Assert Event : %s
Occurred Deassert Event : %s`,
res.EventMessagesDisabled,
res.SensorScanningDisabled,
res.ReadingUnavailable,
strings.Join(assertedStr, "\n -"),
strings.Join(deassertedStr, "\n --"),
)
}
func (c *Client) GetSensorEventStatus(ctx context.Context, sensorNumber uint8) (response *GetSensorEventStatusResponse, err error) {
request := &GetSensorEventStatusRequest{
SensorNumber: sensorNumber,
}
response = &GetSensorEventStatusResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sensor_hysteresis.go 0000664 0000000 0000000 00000003050 14741105271 0024710 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 35.7 Get Sensor Hysteresis Command
type GetSensorHysteresisRequest struct {
SensorNumber uint8
}
type GetSensorHysteresisResponse struct {
PositiveRaw uint8
NegativeRaw uint8
}
func (req *GetSensorHysteresisRequest) Command() Command {
return CommandGetSensorHysteresis
}
func (req *GetSensorHysteresisRequest) Pack() []byte {
out := make([]byte, 2)
packUint8(req.SensorNumber, out, 0)
packUint8(0xff, out, 1) // reserved for future "hysteresis mask" definition. Write as "FFh"
return out
}
func (res *GetSensorHysteresisResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.PositiveRaw, _, _ = unpackUint8(msg, 0)
res.NegativeRaw, _, _ = unpackUint8(msg, 1)
return nil
}
func (r *GetSensorHysteresisResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSensorHysteresisResponse) Format() string {
return fmt.Sprintf(`Positive Hysteresis : %d
Negative Hysteresis : %d`,
res.PositiveRaw,
res.NegativeRaw,
)
}
// This command retrieves the present hysteresis values for the specified sensor.
// If the sensor hysteresis values are "fixed", then the hysteresis values can be obtained from the SDR for the sensor.
func (c *Client) GetSensorHysteresis(ctx context.Context, sensorNumber uint8) (response *GetSensorHysteresisResponse, err error) {
request := &GetSensorHysteresisRequest{
SensorNumber: sensorNumber,
}
response = &GetSensorHysteresisResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sensor_reading.go 0000664 0000000 0000000 00000010431 14741105271 0024120 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 35.14 Get Sensor Reading Command
//
// Retrieve a raw sensor reading (current reading) from ipmb
type GetSensorReadingRequest struct {
SensorNumber uint8
}
type GetSensorReadingResponse struct {
// reading byte. Ignore on read if sensor does not return an numeric (analog) reading
Reading uint8
EventMessagesDisabled bool
// see 16.5 System Software use of Sensor Scanning bits & Entity Info
//
// System software must ignore any sensor that has the sensor scanning bit disabled - if system software didn't disable the sensor.
SensorScanningDisabled bool
ReadingUnavailable bool // Software should use this bit to avoid getting an incorrect status while the first sensor update is in progress.
// The following fields are optionally, they are only meaningful when reading is valid.
Above_UNR bool // at or above UNR threshold
Above_UCR bool // at or above UCR threshold
Above_UNC bool // at or above UNC threshold
Below_LNR bool // at or below LNR threshold
Below_LCR bool // at or below LCR threshold
Below_LNC bool // at or below LNC threshold
// see 42.1
// (Sensor Classes: Discrete)
// It is possible for a discrete sensor to have more than one state active at a time.
ActiveStates Mask_DiscreteEvent
optionalData1 uint8
optionalData2 uint8
}
func (req *GetSensorReadingRequest) Command() Command {
return CommandGetSensorReading
}
func (req *GetSensorReadingRequest) Pack() []byte {
out := make([]byte, 1)
packUint8(req.SensorNumber, out, 0)
return out
}
func (res *GetSensorReadingResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.Reading, _, _ = unpackUint8(msg, 0)
b1, _, _ := unpackUint8(msg, 1)
res.EventMessagesDisabled = !isBit7Set(b1)
res.SensorScanningDisabled = !isBit6Set(b1)
res.ReadingUnavailable = isBit5Set(b1)
if len(msg) >= 3 {
b2, _, _ := unpackUint8(msg, 2)
// For threshold-based sensors, Present threshold comparison status
res.Above_UNR = isBit5Set(b2)
res.Above_UCR = isBit4Set(b2)
res.Above_UNC = isBit3Set(b2)
res.Below_LNR = isBit2Set(b2)
res.Below_LCR = isBit1Set(b2)
res.Below_LNC = isBit0Set(b2)
// For discrete reading sensors
res.ActiveStates.State_7 = isBit7Set(b2)
res.ActiveStates.State_6 = isBit6Set(b2)
res.ActiveStates.State_5 = isBit5Set(b2)
res.ActiveStates.State_4 = isBit4Set(b2)
res.ActiveStates.State_3 = isBit3Set(b2)
res.ActiveStates.State_2 = isBit2Set(b2)
res.ActiveStates.State_1 = isBit1Set(b2)
res.ActiveStates.State_0 = isBit0Set(b2)
res.optionalData1 = b2
}
// For discrete reading sensors only. (Optional)
if len(msg) >= 4 {
b3, _, _ := unpackUint8(msg, 3)
// For discrete reading sensors
res.ActiveStates.State_14 = isBit6Set(b3)
res.ActiveStates.State_13 = isBit5Set(b3)
res.ActiveStates.State_12 = isBit4Set(b3)
res.ActiveStates.State_11 = isBit3Set(b3)
res.ActiveStates.State_10 = isBit2Set(b3)
res.ActiveStates.State_9 = isBit1Set(b3)
res.ActiveStates.State_8 = isBit0Set(b3)
res.optionalData2 = b3
}
return nil
}
func (r *GetSensorReadingResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (r *GetSensorReadingResponse) ThresholdStatus() SensorThresholdStatus {
if r.Above_UCR {
return SensorThresholdStatus_UCR
}
if r.Above_UNC {
return SensorThresholdStatus_UCR
}
if r.Above_UNR {
return SensorThresholdStatus_UCR
}
if r.Below_LCR {
return SensorThresholdStatus_UCR
}
if r.Below_LNC {
return SensorThresholdStatus_UCR
}
if r.Below_LNR {
return SensorThresholdStatus_UCR
}
return SensorThresholdStatus_OK
}
func (res *GetSensorReadingResponse) Format() string {
return fmt.Sprintf(`
Sensor Reading : %d
Event Message Disabled : %v
Scanning Disabled : %v
Reading Unavailable : %v
Threshold Status : %s
Discrete Events : %v
`,
res.Reading,
res.EventMessagesDisabled,
res.SensorScanningDisabled,
res.ReadingUnavailable,
res.ThresholdStatus(),
res.ActiveStates.TrueEvents(),
)
}
func (c *Client) GetSensorReading(ctx context.Context, sensorNumber uint8) (response *GetSensorReadingResponse, err error) {
request := &GetSensorReadingRequest{
SensorNumber: sensorNumber,
}
response = &GetSensorReadingResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sensor_reading_factors.go 0000664 0000000 0000000 00000004303 14741105271 0025642 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 35.5 Get Sensor Reading Factors Command
type GetSensorReadingFactorsRequest struct {
SensorNumber uint8
Reading uint8
}
type GetSensorReadingFactorsResponse struct {
NextReading uint8
ReadingFactors
}
func (req *GetSensorReadingFactorsRequest) Command() Command {
return CommandGetSensorReadingFactors
}
func (req *GetSensorReadingFactorsRequest) Pack() []byte {
out := make([]byte, 2)
packUint8(req.SensorNumber, out, 0)
packUint8(req.Reading, out, 1)
return out
}
func (res *GetSensorReadingFactorsResponse) Unpack(msg []byte) error {
if len(msg) < 7 {
return ErrUnpackedDataTooShortWith(len(msg), 7)
}
res.NextReading, _, _ = unpackUint8(msg, 0)
b1, _, _ := unpackUint8(msg, 1)
b2, _, _ := unpackUint8(msg, 2)
m := uint16(b2&0xc0)<<2 | uint16(b1)
res.M = int16(twosComplement(uint32(m), 10))
res.Tolerance = b2 & 0x3f
b3, _, _ := unpackUint8(msg, 3)
b4, _, _ := unpackUint8(msg, 4)
b5, _, _ := unpackUint8(msg, 5)
b := uint16(b4&0xc0)<<2 | uint16(b3)
res.B = int16(twosComplement(uint32(b), 10))
res.Accuracy = uint16(b5&0xf0)<<2 | uint16(b4&0x3f)
res.Accuracy_Exp = (b5 & 0x0c) >> 2
b6, _, _ := unpackUint8(msg, 6)
rExp := uint8((b6 & 0xf0) >> 4)
res.R_Exp = int8(twosComplement(uint32(rExp), 4))
bExp := uint8(b6 & 0x0f)
res.B_Exp = int8(twosComplement(uint32(bExp), 4))
return nil
}
func (r *GetSensorReadingFactorsResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSensorReadingFactorsResponse) Format() string {
return fmt.Sprintf(`M: %d
B: %d
B_Exp (K1): %d
R_Exp (K2): %d
Tolerance: %d
Accuracy: %d
AccuracyExp: %d`,
res.M,
res.B,
res.B_Exp,
res.R_Exp,
res.Tolerance,
res.Accuracy,
res.Accuracy_Exp,
)
}
// This command returns the Sensor Reading Factors fields for the specified reading value on the specified sensor.
func (c *Client) GetSensorReadingFactors(ctx context.Context, sensorNumber uint8, reading uint8) (response *GetSensorReadingFactorsResponse, err error) {
request := &GetSensorReadingFactorsRequest{
SensorNumber: sensorNumber,
Reading: reading,
}
response = &GetSensorReadingFactorsResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sensor_thresholds.go 0000664 0000000 0000000 00000004773 14741105271 0024702 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 35.9 Get Sensor Thresholds Command
type GetSensorThresholdsRequest struct {
SensorNumber uint8
}
type GetSensorThresholdsResponse struct {
// Readable thresholds mask
UNR_Readable bool
UCR_Readable bool
UNC_Readable bool
LNR_Readable bool
LCR_Readable bool
LNC_Readable bool
// Threshold value
LNC_Raw uint8
LCR_Raw uint8
LNR_Raw uint8
UNC_Raw uint8
UCR_Raw uint8
UNR_Raw uint8
}
func (req *GetSensorThresholdsRequest) Command() Command {
return CommandGetSensorThresholds
}
func (req *GetSensorThresholdsRequest) Pack() []byte {
out := make([]byte, 1)
packUint8(req.SensorNumber, out, 0)
return out
}
func (res *GetSensorThresholdsResponse) Unpack(msg []byte) error {
if len(msg) < 7 {
return ErrUnpackedDataTooShortWith(len(msg), 7)
}
b, _, _ := unpackUint8(msg, 0)
res.UNR_Readable = isBit5Set(b)
res.UCR_Readable = isBit4Set(b)
res.UNC_Readable = isBit3Set(b)
res.LNR_Readable = isBit2Set(b)
res.LCR_Readable = isBit1Set(b)
res.LNC_Readable = isBit0Set(b)
res.LNC_Raw, _, _ = unpackUint8(msg, 1)
res.LCR_Raw, _, _ = unpackUint8(msg, 2)
res.LNR_Raw, _, _ = unpackUint8(msg, 3)
res.UNC_Raw, _, _ = unpackUint8(msg, 4)
res.UCR_Raw, _, _ = unpackUint8(msg, 5)
res.UNR_Raw, _, _ = unpackUint8(msg, 6)
return nil
}
func (r *GetSensorThresholdsResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSensorThresholdsResponse) Format() string {
return fmt.Sprintf(`UNR Readable : %v%s
UCR Readable : %v%s
UNC Readable : %v%s
LNR Readable : %v%s
LCR Readable : %v%s
LNC Readable : %v%s`,
res.UNR_Readable, formatBool(res.UNR_Readable, fmt.Sprintf(", raw: %#02x", res.UNR_Raw), ""),
res.UCR_Readable, formatBool(res.UCR_Readable, fmt.Sprintf(", raw: %#02x", res.UCR_Raw), ""),
res.UNC_Readable, formatBool(res.UNC_Readable, fmt.Sprintf(", raw: %#02x", res.UNC_Raw), ""),
res.LNR_Readable, formatBool(res.LNR_Readable, fmt.Sprintf(", raw: %#02x", res.LNR_Raw), ""),
res.LCR_Readable, formatBool(res.LCR_Readable, fmt.Sprintf(", raw: %#02x", res.LCR_Raw), ""),
res.LNC_Readable, formatBool(res.LNC_Readable, fmt.Sprintf(", raw: %#02x", res.LNC_Raw), ""),
)
}
// This command retrieves the threshold for the given sensor.
func (c *Client) GetSensorThresholds(ctx context.Context, sensorNumber uint8) (response *GetSensorThresholdsResponse, err error) {
request := &GetSensorThresholdsRequest{
SensorNumber: sensorNumber,
}
response = &GetSensorThresholdsResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sensor_type.go 0000664 0000000 0000000 00000002473 14741105271 0023477 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// GetSensorTypeRequest (31.2)
type GetSensorTypeRequest struct {
SensorNumber uint8
}
type GetSensorTypeResponse struct {
SensorType SensorType
EventReadingType EventReadingType
}
func (req *GetSensorTypeRequest) Command() Command {
return CommandGetSensorType
}
func (req *GetSensorTypeRequest) Pack() []byte {
out := make([]byte, 1)
packUint8(req.SensorNumber, out, 0)
return out
}
func (res *GetSensorTypeResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
b1, _, _ := unpackUint8(msg, 0)
res.SensorType = SensorType(b1)
b2, _, _ := unpackUint8(msg, 1)
res.EventReadingType = EventReadingType(b2)
return nil
}
func (r *GetSensorTypeResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSensorTypeResponse) Format() string {
return fmt.Sprintf(`Sensor Type : %s
Event/Reading Type : %#02x (%s)`,
res.SensorType,
uint8(res.EventReadingType), res.EventReadingType,
)
}
func (c *Client) GetSensorType(ctx context.Context, sensorNumber uint8) (response *GetSensorTypeResponse, err error) {
request := &GetSensorTypeRequest{
SensorNumber: sensorNumber,
}
response = &GetSensorTypeResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sensors.go 0000664 0000000 0000000 00000024445 14741105271 0022624 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"strings"
)
type SensorFilterOption func(sensor *Sensor) bool
func SensorFilterOptionIsThreshold(sensor *Sensor) bool {
return sensor.IsThreshold()
}
func SensorFilterOptionIsReadingValid(sensor *Sensor) bool {
return sensor.IsReadingValid()
}
// Sensor is matched if the sensor type of the sensor is one of the given sensor types.
func SensorFilterOptionIsSensorType(sensorTypes ...SensorType) func(sensor *Sensor) bool {
return func(sensor *Sensor) bool {
for _, sensorType := range sensorTypes {
if sensor.SensorType == sensorType {
return true
}
}
return false
}
}
// GetSensors returns all sensors with their current readings and status.
//
// If there's no filter options, it returns all sensors.
//
// If there exists filter options, it returns the sensors those
// passed all filter options, that means the filter options are logically ANDed.
//
// If you want the filter options are logically ORed, use `GetSensorsAny`
func (c *Client) GetSensors(ctx context.Context, filterOptions ...SensorFilterOption) ([]*Sensor, error) {
var out = make([]*Sensor, 0)
sdrs, err := c.GetSDRs(ctx, SDRRecordTypeFullSensor, SDRRecordTypeCompactSensor)
if err != nil {
return nil, fmt.Errorf("GetSDRs failed, err: %w", err)
}
for _, sdr := range sdrs {
sensor, err := c.sdrToSensor(ctx, sdr)
if err != nil {
return nil, fmt.Errorf("sdrToSensor failed, err: %w", err)
}
var choose bool = true
for _, filterOption := range filterOptions {
if !filterOption(sensor) {
choose = false
break
}
}
if choose {
out = append(out, sensor)
}
}
return out, nil
}
// GetSensorsAny returns all sensors with their current readings and status.
//
// If there's no filter options, it returns all sensors.
//
// If there exists filter options, it only returns the sensors those
// passed any one filter option, that means the filter options are logically ORed.
//
// If you want the filter options are logically ANDed, use `GetSensors`.
func (c *Client) GetSensorsAny(ctx context.Context, filterOptions ...SensorFilterOption) ([]*Sensor, error) {
var out = make([]*Sensor, 0)
sdrs, err := c.GetSDRs(ctx, SDRRecordTypeFullSensor, SDRRecordTypeCompactSensor)
if err != nil {
return nil, fmt.Errorf("GetSDRs failed, err: %w", err)
}
for _, sdr := range sdrs {
sensor, err := c.sdrToSensor(ctx, sdr)
if err != nil {
return nil, fmt.Errorf("sdrToSensor failed, err: %w", err)
}
var choose bool = false
for _, filterOption := range filterOptions {
if filterOption(sensor) {
choose = true
break
}
}
if choose {
out = append(out, sensor)
}
}
return out, nil
}
// GetSensorByID returns the sensor with current reading and status by specified sensor number.
func (c *Client) GetSensorByID(ctx context.Context, sensorNumber uint8) (*Sensor, error) {
sdr, err := c.GetSDRBySensorID(ctx, sensorNumber)
if err != nil {
return nil, fmt.Errorf("GetSDRBySensorID failed, err: %w", err)
}
sensor, err := c.sdrToSensor(ctx, sdr)
if err != nil {
return nil, fmt.Errorf("GetSensorFromSDR failed, err: %w", err)
}
return sensor, nil
}
// GetSensorByName returns the sensor with current reading and status by specified sensor name.
func (c *Client) GetSensorByName(ctx context.Context, sensorName string) (*Sensor, error) {
sdr, err := c.GetSDRBySensorName(ctx, sensorName)
if err != nil {
return nil, fmt.Errorf("GetSDRBySensorName failed, err: %w", err)
}
sensor, err := c.sdrToSensor(ctx, sdr)
if err != nil {
return nil, fmt.Errorf("GetSensorFromSDR failed, err: %w", err)
}
return sensor, nil
}
// sdrToSensor convert SDR record to Sensor struct.
//
// Only Full and Compact SDR records are meaningful here. Pass SDRs with other record types will return error.
//
// This function will fetch other sensor-related values which are not stored in SDR by other IPMI commands.
func (c *Client) sdrToSensor(ctx context.Context, sdr *SDR) (*Sensor, error) {
if sdr == nil {
return nil, fmt.Errorf("nil sdr parameter")
}
sensor := &Sensor{
SDRRecordType: sdr.RecordHeader.RecordType,
HasAnalogReading: sdr.HasAnalogReading(),
}
switch sdr.RecordHeader.RecordType {
case SDRRecordTypeFullSensor:
sensor.Number = uint8(sdr.Full.SensorNumber)
sensor.Name = strings.TrimSpace(string(sdr.Full.IDStringBytes))
sensor.SensorUnit = sdr.Full.SensorUnit
sensor.SensorType = sdr.Full.SensorType
sensor.EventReadingType = sdr.Full.SensorEventReadingType
sensor.SensorInitialization = sdr.Full.SensorInitialization
sensor.SensorCapabilities = sdr.Full.SensorCapabilities
sensor.EntityID = sdr.Full.SensorEntityID
sensor.EntityInstance = sdr.Full.SensorEntityInstance
sensor.Threshold.LinearizationFunc = sdr.Full.LinearizationFunc
sensor.Threshold.ReadingFactors = sdr.Full.ReadingFactors
case SDRRecordTypeCompactSensor:
sensor.Number = uint8(sdr.Compact.SensorNumber)
sensor.Name = strings.TrimSpace(string(sdr.Compact.IDStringBytes))
sensor.SensorUnit = sdr.Compact.SensorUnit
sensor.SensorType = sdr.Compact.SensorType
sensor.EventReadingType = sdr.Compact.SensorEventReadingType
sensor.SensorInitialization = sdr.Compact.SensorInitialization
sensor.SensorCapabilities = sdr.Compact.SensorCapabilities
sensor.EntityID = sdr.Compact.SensorEntityID
sensor.EntityInstance = sdr.Compact.SensorEntityInstance
default:
return nil, fmt.Errorf("only support Full or Compact SDR record type, input is %s", sdr.RecordHeader.RecordType)
}
c.Debug("Sensor:", sensor)
c.Debug("Get Sensor", fmt.Sprintf("Sensor Name: %s, Sensor Number: %#02x\n", sensor.Name, sensor.Number))
if err := c.fillSensorReading(ctx, sensor); err != nil {
return nil, fmt.Errorf("fillSensorReading failed, err: %w", err)
}
// scanningDisabled is filled/set by fillSensorReading
if sensor.scanningDisabled {
// Sensor scanning disabled, no need to continue
c.Debug(fmt.Sprintf(":( Sensor [%s](%#02x) scanning disabled\n", sensor.Name, sensor.Number), "")
return sensor, nil
}
if !sensor.EventReadingType.IsThreshold() || !sensor.SensorUnit.IsAnalog() {
if err := c.fillSensorDiscrete(ctx, sensor); err != nil {
return nil, fmt.Errorf("fillSensorDiscrete failed, err: %w", err)
}
} else {
if err := c.fillSensorThreshold(ctx, sensor); err != nil {
return nil, fmt.Errorf("fillSensorThreshold failed, err: %w", err)
}
}
return sensor, nil
}
func (c *Client) fillSensorReading(ctx context.Context, sensor *Sensor) error {
readingRes, err := c.GetSensorReading(ctx, sensor.Number)
if _canIgnoreSensorErr(err) != nil {
return fmt.Errorf("GetSensorReading for sensor %#02x failed, err: %w", sensor.Number, err)
}
sensor.Raw = readingRes.Reading
sensor.Value = sensor.ConvertReading(readingRes.Reading)
sensor.scanningDisabled = readingRes.SensorScanningDisabled
sensor.readingAvailable = !readingRes.ReadingUnavailable
sensor.Threshold.ThresholdStatus = readingRes.ThresholdStatus()
sensor.Discrete.ActiveStates = readingRes.ActiveStates
sensor.Discrete.optionalData1 = readingRes.optionalData1
sensor.Discrete.optionalData2 = readingRes.optionalData2
return nil
}
// fillSensorDiscrete retrieves and fills extra sensor attributes for given discrete sensor.
func (c *Client) fillSensorDiscrete(ctx context.Context, sensor *Sensor) error {
statusRes, err := c.GetSensorEventStatus(ctx, sensor.Number)
if _canIgnoreSensorErr(err) != nil {
return fmt.Errorf("GetSensorEventStatus for sensor %#02x failed, err: %w", sensor.Number, err)
}
sensor.OccurredEvents = statusRes.SensorEventFlag.TrueEvents()
return nil
}
// fillSensorThreshold retrieves and fills sensor attributes for given threshold sensor.
func (c *Client) fillSensorThreshold(ctx context.Context, sensor *Sensor) error {
if sensor.SDRRecordType != SDRRecordTypeFullSensor {
return nil
}
// If Non Linear, should update the ReadingFactors
// see 36.2 Non-Linear Sensors
if sensor.Threshold.LinearizationFunc.IsNonLinear() {
factorsRes, err := c.GetSensorReadingFactors(ctx, sensor.Number, sensor.Raw)
if _canIgnoreSensorErr(err) != nil {
return fmt.Errorf("GetSensorReadingFactors for sensor %#02x failed, err: %w", sensor.Number, err)
}
sensor.Threshold.ReadingFactors = factorsRes.ReadingFactors
}
thresholdRes, err := c.GetSensorThresholds(ctx, sensor.Number)
if _canIgnoreSensorErr(err) != nil {
return fmt.Errorf("GetSensorThresholds for sensor %#02x failed, err: %w", sensor.Number, err)
}
sensor.Threshold.Mask.UNR.Readable = thresholdRes.UNR_Readable
sensor.Threshold.Mask.UCR.Readable = thresholdRes.UCR_Readable
sensor.Threshold.Mask.UNC.Readable = thresholdRes.UNC_Readable
sensor.Threshold.Mask.LNR.Readable = thresholdRes.LNR_Readable
sensor.Threshold.Mask.LCR.Readable = thresholdRes.LCR_Readable
sensor.Threshold.Mask.LNC.Readable = thresholdRes.LNC_Readable
sensor.Threshold.LNC_Raw = thresholdRes.LNC_Raw
sensor.Threshold.LCR_Raw = thresholdRes.LCR_Raw
sensor.Threshold.LNR_Raw = thresholdRes.LNR_Raw
sensor.Threshold.UNC_Raw = thresholdRes.UNC_Raw
sensor.Threshold.UCR_Raw = thresholdRes.UCR_Raw
sensor.Threshold.UNR_Raw = thresholdRes.UNR_Raw
sensor.Threshold.LNC = sensor.ConvertReading(thresholdRes.LNC_Raw)
sensor.Threshold.LCR = sensor.ConvertReading(thresholdRes.LCR_Raw)
sensor.Threshold.LNR = sensor.ConvertReading(thresholdRes.LNR_Raw)
sensor.Threshold.UNC = sensor.ConvertReading(thresholdRes.UNC_Raw)
sensor.Threshold.UCR = sensor.ConvertReading(thresholdRes.UCR_Raw)
sensor.Threshold.UNR = sensor.ConvertReading(thresholdRes.UNR_Raw)
hysteresisRes, err := c.GetSensorHysteresis(ctx, sensor.Number)
if _canIgnoreSensorErr(err) != nil {
return fmt.Errorf("GetSensorHysteresis for sensor %#02x failed, err: %w", sensor.Number, err)
}
sensor.Threshold.PositiveHysteresisRaw = hysteresisRes.PositiveRaw
sensor.Threshold.NegativeHysteresisRaw = hysteresisRes.NegativeRaw
sensor.Threshold.PositiveHysteresis = sensor.ConvertSensorHysteresis(hysteresisRes.PositiveRaw)
sensor.Threshold.NegativeHysteresis = sensor.ConvertSensorHysteresis(hysteresisRes.NegativeRaw)
return nil
}
func _canIgnoreSensorErr(err error) error {
canIgnore := buildCanIgnoreFn(
// the following completion codes CAN be ignored,
// it normally means the sensor device does not exist or the sensor device does not recognize the IPMI command
uint8(CompletionCodeRequestedDataNotPresent),
uint8(CompletionCodeIllegalCommand),
uint8(CompletionCodeInvalidCommand),
)
return canIgnore(err)
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_session_challenge.go 0000664 0000000 0000000 00000003606 14741105271 0024611 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 22.16
type GetSessionChallengeRequest struct {
// Authentication Type for Challenge
// indicating what type of authentication type the console wants to use.
AuthType AuthType
// Sixteen-bytes. All 0s for null user name (User 1)
Username [16]byte
}
type GetSessionChallengeResponse struct {
TemporarySessionID uint32 // LS byte first
Challenge [16]byte
}
func (req *GetSessionChallengeRequest) Command() Command {
return CommandGetSessionChallenge
}
func (req *GetSessionChallengeRequest) Pack() []byte {
out := make([]byte, 17)
packUint8(uint8(req.AuthType), out, 0)
packBytes(req.Username[:], out, 1)
return out
}
func (res *GetSessionChallengeResponse) Unpack(msg []byte) error {
if len(msg) < 20 {
return ErrUnpackedDataTooShortWith(len(msg), 20)
}
res.TemporarySessionID, _, _ = unpackUint32L(msg, 0)
b, _, _ := unpackBytes(msg, 4, 16)
res.Challenge = array16(b)
return nil
}
func (*GetSessionChallengeResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "invalid user name",
0x82: "null user name (User 1) not enabled",
}
}
func (res *GetSessionChallengeResponse) Format() string {
return fmt.Sprintf("%v", res)
}
// The command selects which of the BMC-supported authentication types the Remote Console would like to use,
// and a username that selects which set of user information should be used for the session
func (c *Client) GetSessionChallenge(ctx context.Context) (response *GetSessionChallengeResponse, err error) {
username := padBytes(c.Username, 16, 0x00)
request := &GetSessionChallengeRequest{
AuthType: c.session.authType,
Username: array16(username),
}
response = &GetSessionChallengeResponse{}
err = c.Exchange(ctx, request, response)
if err != nil {
return
}
c.session.v15.sessionID = response.TemporarySessionID
c.session.v15.challenge = response.Challenge
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_session_info.go 0000664 0000000 0000000 00000011263 14741105271 0023620 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"net"
)
// 22.20 Get Session Info Command
type GetSessionInfoRequest struct {
// Session index
// 00h = Return info for active session associated with session this command was received over.
// N = get info for Nth active session
// FEh = Look up session info according to Session Handle passed in this request.
// FFh = Look up session info according to Session ID passed in this request.
SessionIndex uint8
SessionHandle uint8
SessionID uint32
}
type GetSessionInfoResponse struct {
SessionHandle uint8 // Session Handle presently assigned to active session.
PossibleActiveSessions uint8 // This value reflects the number of possible entries (slots) in the sessions table.
CurrentActiveSessions uint8 // Number of currently active sessions on all channels on this controller
UserID uint8
OperatingPrivilegeLevel PrivilegeLevel
// [7:4] - Session protocol auxiliary data
// For Channel Type = 802.3 LAN:
// 0h = IPMI v1.5
// 1h = IPMI v2.0/RMCP+
AuxiliaryData uint8 // 4bits
ChannelNumber uint8 // 4bits
// if Channel Type = 802.3 LAN:
RemoteConsoleIPAddr net.IP // IP Address of remote console (MS-byte first).
RemoteConsoleMacAddr net.HardwareAddr // 6 bytes, MAC Address (MS-byte first)
RemoteConsolePort uint16 // Port Number of remote console (LS-byte first)
// if Channel Type = asynch. serial/modem
SessionChannelActivityType uint8
DestinationSelector uint8
RemoteConsoleIPAddr_PPP uint32 // If PPP connection: IP address of remote console. (MS-byte first) 00h, 00h, 00h, 00h otherwise.
// if Channel Type = asynch. serial/modem and connection is PPP:
RemoteConsolePort_PPP uint16
}
func (req *GetSessionInfoRequest) Command() Command {
return CommandGetSessionInfo
}
func (req *GetSessionInfoRequest) Pack() []byte {
out := make([]byte, 5)
packUint8(req.SessionIndex, out, 0)
if req.SessionIndex == 0xfe {
packUint8(req.SessionHandle, out, 1)
return out[0:2]
}
if req.SessionIndex == 0xff {
packUint32L(req.SessionID, out, 1)
return out[0:5]
}
return out[0:1]
}
func (res *GetSessionInfoResponse) Unpack(msg []byte) error {
// at least 3 bytes
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
res.SessionHandle, _, _ = unpackUint8(msg, 0)
res.PossibleActiveSessions, _, _ = unpackUint8(msg, 1)
res.CurrentActiveSessions, _, _ = unpackUint8(msg, 2)
if len(msg) == 3 {
return nil
}
// if len(msg) > 3, then at least 6 bytes
if len(msg) < 6 {
return ErrUnpackedDataTooShortWith(len(msg), 6)
}
res.UserID, _, _ = unpackUint8(msg, 3)
b5, _, _ := unpackUint8(msg, 4)
res.OperatingPrivilegeLevel = PrivilegeLevel(b5)
b6, _, _ := unpackUint8(msg, 5)
res.AuxiliaryData = b6 >> 4
res.ChannelNumber = b6 & 0x0f
// Channel Type = 802.3 LAN:
if len(msg) >= 18 {
ipBytes, _, _ := unpackBytes(msg, 6, 4)
res.RemoteConsoleIPAddr = net.IP(ipBytes)
macBytes, _, _ := unpackBytes(msg, 10, 6)
res.RemoteConsoleMacAddr = net.HardwareAddr(macBytes)
res.RemoteConsolePort, _, _ = unpackUint16L(msg, 16)
}
if len(msg) >= 14 {
res.SessionChannelActivityType, _, _ = unpackUint8(msg, 6)
res.DestinationSelector, _, _ = unpackUint8(msg, 7)
res.RemoteConsoleIPAddr_PPP, _, _ = unpackUint32(msg, 8)
res.RemoteConsolePort_PPP, _, _ = unpackUint16L(msg, 12)
}
return nil
}
func (res *GetSessionInfoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSessionInfoResponse) Format() string {
var sessionType string
switch res.AuxiliaryData {
case 0:
sessionType = "IPMIv1.5"
case 1:
sessionType = "IPMIv2/RMCP+"
}
return fmt.Sprintf(`session handle : %d
slot count : %d
active sessions : %d
user id : %d
privilege level : %s
session type : %s
channel number : %#02x
console ip : %s
console mac : %s
console port : %d
`,
res.SessionHandle,
res.PossibleActiveSessions,
res.CurrentActiveSessions,
res.UserID,
res.OperatingPrivilegeLevel,
sessionType,
res.ChannelNumber,
res.RemoteConsoleIPAddr,
res.RemoteConsoleMacAddr,
res.RemoteConsolePort,
)
}
func (c *Client) GetSessionInfo(ctx context.Context, request *GetSessionInfoRequest) (response *GetSessionInfoResponse, err error) {
response = &GetSessionInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetCurrentSessionInfo(ctx context.Context) (response *GetSessionInfoResponse, err error) {
request := &GetSessionInfoRequest{
SessionIndex: 0x00,
}
response = &GetSessionInfoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_sol_config_params.go 0000664 0000000 0000000 00000011313 14741105271 0024603 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 26.3 Get SOL Configuration Parameters Command
type GetSOLConfigParamRequest struct {
GetParamRevisionOnly bool
ChannelNumber uint8
ParamSelector SOLConfigParamSelector
SetSelector uint8
BlockSelector uint8
}
type GetSOLConfigParamResponse struct {
ParamRevision uint8
ParamData []byte
}
func (req *GetSOLConfigParamRequest) Command() Command {
return CommandGetSOLConfigParam
}
func (req *GetSOLConfigParamRequest) Pack() []byte {
out := make([]byte, 4)
b := req.ChannelNumber
if req.GetParamRevisionOnly {
b = setBit7(b)
}
packUint8(b, out, 0)
packUint8(uint8(req.ParamSelector), out, 1)
packUint8(req.SetSelector, out, 2)
packUint8(req.BlockSelector, out, 3)
return out
}
func (res *GetSOLConfigParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSOLConfigParamResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
res.ParamRevision = msg[0]
if len(msg) > 1 {
res.ParamData, _, _ = unpackBytes(msg, 1, len(msg)-1)
}
return nil
}
func (res *GetSOLConfigParamResponse) Format() string {
return ""
}
func (c *Client) GetSOLConfigParam(ctx context.Context, channelNumber uint8, paramSelector SOLConfigParamSelector, setSelector, blockSelector uint8) (response *GetSOLConfigParamResponse, err error) {
request := &GetSOLConfigParamRequest{
ChannelNumber: channelNumber,
ParamSelector: paramSelector,
SetSelector: 0x00,
BlockSelector: 0x00,
}
response = &GetSOLConfigParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetSOLConfigParamFor(ctx context.Context, channelNumber uint8, param SOLConfigParameter) error {
if isNilSOLConfigParameter(param) {
return nil
}
paramSelector, setSelector, blockSelector := param.SOLConfigParameter()
res, err := c.GetSOLConfigParam(ctx, channelNumber, paramSelector, setSelector, blockSelector)
if err != nil {
return fmt.Errorf("GetSOLConfigParam for param (%s[%2d]) failed, err: %w", paramSelector.String(), paramSelector, err)
}
if err := param.Unpack(res.ParamData); err != nil {
return fmt.Errorf("unpack param (%s[%2d]) failed, err: %w", paramSelector.String(), paramSelector, err)
}
return nil
}
func (c *Client) GetSOLConfigParams(ctx context.Context, channelNumber uint8) (*SOLConfigParams, error) {
solConfigParams := &SOLConfigParams{
SetInProgress: &SOLConfigParam_SetInProgress{},
SOLEnable: &SOLConfigParam_SOLEnable{},
SOLAuthentication: &SOLConfigParam_SOLAuthentication{},
Character: &SOLConfigParam_Character{},
SOLRetry: &SOLConfigParam_SOLRetry{},
NonVolatileBitRate: &SOLConfigParam_NonVolatileBitRate{},
VolatileBitRate: &SOLConfigParam_VolatileBitRate{},
PayloadChannel: &SOLConfigParam_PayloadChannel{},
PayloadPort: &SOLConfigParam_PayloadPort{},
}
if err := c.GetSOLConfigParamsFor(ctx, channelNumber, solConfigParams); err != nil {
return nil, fmt.Errorf("GetSOLConfigParamFor failed, err: %w", err)
}
return solConfigParams, nil
}
func (c *Client) GetSOLConfigParamsFor(ctx context.Context, channelNumber uint8, solConfigParams *SOLConfigParams) error {
if solConfigParams == nil {
return nil
}
if solConfigParams.SetInProgress != nil {
if err := c.GetSOLConfigParamFor(ctx, channelNumber, solConfigParams.SetInProgress); err != nil {
return err
}
}
if solConfigParams.SOLEnable != nil {
if err := c.GetSOLConfigParamFor(ctx, channelNumber, solConfigParams.SOLEnable); err != nil {
return err
}
}
if solConfigParams.SOLAuthentication != nil {
if err := c.GetSOLConfigParamFor(ctx, channelNumber, solConfigParams.SOLAuthentication); err != nil {
return err
}
}
if solConfigParams.Character != nil {
if err := c.GetSOLConfigParamFor(ctx, channelNumber, solConfigParams.Character); err != nil {
return err
}
}
if solConfigParams.SOLRetry != nil {
if err := c.GetSOLConfigParamFor(ctx, channelNumber, solConfigParams.SOLRetry); err != nil {
return err
}
}
if solConfigParams.NonVolatileBitRate != nil {
if err := c.GetSOLConfigParamFor(ctx, channelNumber, solConfigParams.NonVolatileBitRate); err != nil {
return err
}
}
if solConfigParams.VolatileBitRate != nil {
if err := c.GetSOLConfigParamFor(ctx, channelNumber, solConfigParams.VolatileBitRate); err != nil {
return err
}
}
if solConfigParams.PayloadChannel != nil {
if err := c.GetSOLConfigParamFor(ctx, channelNumber, solConfigParams.PayloadChannel); err != nil {
return err
}
}
if solConfigParams.PayloadPort != nil {
if err := c.GetSOLConfigParamFor(ctx, channelNumber, solConfigParams.PayloadPort); err != nil {
return err
}
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_supermicro_bios_version.go 0000664 0000000 0000000 00000002116 14741105271 0026070 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"strings"
)
type CommandGetSupermicroBiosVersionRequest struct {
}
type CommandGetSupermicroBiosVersionResponse struct {
Version string
}
func (req *CommandGetSupermicroBiosVersionRequest) Command() Command {
return CommandGetSupermicroBiosVersion
}
func (req *CommandGetSupermicroBiosVersionRequest) Pack() []byte {
return []byte{0x00, 0x00}
}
func (res *CommandGetSupermicroBiosVersionResponse) Unpack(msg []byte) error {
res.Version = string(msg)
res.Version = strings.TrimSpace(res.Version)
return nil
}
func (res *CommandGetSupermicroBiosVersionResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *CommandGetSupermicroBiosVersionResponse) Format() string {
return fmt.Sprintf(`bios.version = %s`,
res.Version,
)
}
func (c *Client) GetSupermicroBiosVersion(ctx context.Context) (response *CommandGetSupermicroBiosVersionResponse, err error) {
request := &CommandGetSupermicroBiosVersionRequest{}
response = &CommandGetSupermicroBiosVersionResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_system_boot_options.go 0000664 0000000 0000000 00000014402 14741105271 0025242 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 28.13 Get System Boot Options Command
type GetSystemBootOptionsParamRequest struct {
ParamSelector BootOptionParamSelector
SetSelector uint8
BlockSelector uint8
}
// Table 28-14, Boot Option Parameters
type GetSystemBootOptionsParamResponse struct {
ParameterVersion uint8
// [7] - 1b = mark parameter invalid / locked
// 0b = mark parameter valid / unlocked
ParameterInValid bool
// [6:0] - boot option parameter selector
ParamSelector BootOptionParamSelector
ParamData []byte // origin parameter data
}
func (req *GetSystemBootOptionsParamRequest) Pack() []byte {
out := make([]byte, 3)
packUint8(uint8(req.ParamSelector), out, 0)
packUint8(req.SetSelector, out, 1)
packUint8(req.BlockSelector, out, 2)
return out
}
func (req *GetSystemBootOptionsParamRequest) Command() Command {
return CommandGetSystemBootOptions
}
func (res *GetSystemBootOptionsParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "parameter not supported",
}
}
func (res *GetSystemBootOptionsParamResponse) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
res.ParameterVersion, _, _ = unpackUint8(msg, 0)
b, _, _ := unpackUint8(msg, 1)
res.ParameterInValid = isBit7Set(b)
res.ParamSelector = BootOptionParamSelector(b & 0x7f) // clear bit 7
res.ParamData, _, _ = unpackBytes(msg, 2, len(msg)-2)
return nil
}
func (res *GetSystemBootOptionsParamResponse) Format() string {
var paramDataFormatted string
var param BootOptionParameter
switch res.ParamSelector {
case BootOptionParamSelector_SetInProgress:
param = &BootOptionParam_SetInProgress{}
case BootOptionParamSelector_ServicePartitionSelector:
param = &BootOptionParam_ServicePartitionSelector{}
case BootOptionParamSelector_ServicePartitionScan:
param = &BootOptionParam_ServicePartitionScan{}
case BootOptionParamSelector_BMCBootFlagValidBitClear:
param = &BootOptionParam_BMCBootFlagValidBitClear{}
case BootOptionParamSelector_BootInfoAcknowledge:
param = &BootOptionParam_BootInfoAcknowledge{}
case BootOptionParamSelector_BootFlags:
param = &BootOptionParam_BootFlags{}
case BootOptionParamSelector_BootInitiatorInfo:
param = &BootOptionParam_BootInitiatorInfo{}
case BootOptionParamSelector_BootInitiatorMailbox:
param = &BootOptionParam_BootInitiatorMailbox{}
}
if param != nil {
if err := param.Unpack(res.ParamData); err == nil {
paramDataFormatted = param.Format()
}
}
return fmt.Sprintf(`Boot parameter version: %d
Boot parameter %d is %s
Boot parameter data: %02x
%s : %s`,
res.ParameterVersion,
res.ParamSelector, formatBool(res.ParameterInValid, "invalid/locked", "valid/unlocked"),
res.ParamData,
res.ParamSelector.String(),
paramDataFormatted,
)
}
func (c *Client) GetSystemBootOptionsParam(ctx context.Context, paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8) (response *GetSystemBootOptionsParamResponse, err error) {
request := &GetSystemBootOptionsParamRequest{
ParamSelector: paramSelector,
SetSelector: setSelector,
BlockSelector: blockSelector,
}
response = &GetSystemBootOptionsParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetSystemBootOptionsParamFor(ctx context.Context, param BootOptionParameter) error {
if isNilBootOptionParameter(param) {
return nil
}
paramSelector, setSelector, blockSelector := param.BootOptionParameter()
response, err := c.GetSystemBootOptionsParam(ctx, paramSelector, setSelector, blockSelector)
if err != nil {
return fmt.Errorf("GetSystemBootOptions for param (%s[%d]) failed, err: %w", paramSelector.String(), paramSelector, err)
}
if err := param.Unpack(response.ParamData); err != nil {
return fmt.Errorf("unpack param (%s[%d]) failed, err: %w", paramSelector.String(), paramSelector, err)
}
return nil
}
// GetSystemBootOptionsParams get all parameters of boot options.
func (c *Client) GetSystemBootOptionsParams(ctx context.Context) (*BootOptionsParams, error) {
bootOptionsParams := &BootOptionsParams{
SetInProgress: &BootOptionParam_SetInProgress{},
ServicePartitionSelector: &BootOptionParam_ServicePartitionSelector{},
ServicePartitionScan: &BootOptionParam_ServicePartitionScan{},
BMCBootFlagValidBitClear: &BootOptionParam_BMCBootFlagValidBitClear{},
BootInfoAcknowledge: &BootOptionParam_BootInfoAcknowledge{},
BootFlags: &BootOptionParam_BootFlags{},
BootInitiatorInfo: &BootOptionParam_BootInitiatorInfo{},
BootInitiatorMailbox: &BootOptionParam_BootInitiatorMailbox{},
}
if err := c.GetSystemBootOptionsParamsFor(ctx, bootOptionsParams); err != nil {
return nil, fmt.Errorf("GetBootOptionsFor failed, err: %w", err)
}
return bootOptionsParams, nil
}
func (c *Client) GetSystemBootOptionsParamsFor(ctx context.Context, bootOptionsParams *BootOptionsParams) error {
if bootOptionsParams == nil {
return nil
}
if bootOptionsParams.SetInProgress != nil {
if err := c.GetSystemBootOptionsParamFor(ctx, bootOptionsParams.SetInProgress); err != nil {
return err
}
}
if bootOptionsParams.ServicePartitionSelector != nil {
if err := c.GetSystemBootOptionsParamFor(ctx, bootOptionsParams.ServicePartitionSelector); err != nil {
return err
}
}
if bootOptionsParams.ServicePartitionScan != nil {
if err := c.GetSystemBootOptionsParamFor(ctx, bootOptionsParams.ServicePartitionScan); err != nil {
return err
}
}
if bootOptionsParams.BMCBootFlagValidBitClear != nil {
if err := c.GetSystemBootOptionsParamFor(ctx, bootOptionsParams.BMCBootFlagValidBitClear); err != nil {
return err
}
}
if bootOptionsParams.BootInfoAcknowledge != nil {
if err := c.GetSystemBootOptionsParamFor(ctx, bootOptionsParams.BootInfoAcknowledge); err != nil {
return err
}
}
if bootOptionsParams.BootFlags != nil {
if err := c.GetSystemBootOptionsParamFor(ctx, bootOptionsParams.BootFlags); err != nil {
return err
}
}
if bootOptionsParams.BootInitiatorInfo != nil {
if err := c.GetSystemBootOptionsParamFor(ctx, bootOptionsParams.BootInitiatorInfo); err != nil {
return err
}
}
if bootOptionsParams.BootInitiatorMailbox != nil {
if err := c.GetSystemBootOptionsParamFor(ctx, bootOptionsParams.BootInitiatorMailbox); err != nil {
return err
}
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_system_guid.go 0000664 0000000 0000000 00000003114 14741105271 0023452 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"time"
)
// 22.14 Get System GUID Command
type GetSystemGUIDRequest struct {
// empty
}
type GetSystemGUIDResponse struct {
// Note that the individual fields within the GUID are stored least-significant byte first
GUID [16]byte
}
func (req *GetSystemGUIDRequest) Command() Command {
return CommandGetSystemGUID
}
func (req *GetSystemGUIDRequest) Pack() []byte {
return nil
}
func (res *GetSystemGUIDResponse) Unpack(msg []byte) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
b, _, _ := unpackBytes(msg, 0, 16)
res.GUID = array16(b)
return nil
}
func (*GetSystemGUIDResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetSystemGUIDResponse) Format() string {
out := ""
guidMode := GUIDModeSMBIOS
u, err := ParseGUID(res.GUID[:], guidMode)
if err != nil {
return fmt.Sprintf(" (%s)", err)
}
out += fmt.Sprintf("System GUID : %s\n", u.String())
out += fmt.Sprintf("UUID Encoding : %s\n", guidMode)
out += fmt.Sprintf("UUID Version : %s\n", UUIDVersionString(u))
sec, nsec := u.Time().UnixTime()
out += fmt.Sprintf("Timestamp : %s\n", time.Unix(sec, nsec).Format(timeFormat))
out += fmt.Sprintf("Timestamp(Legacy) : %s\n", IPMILegacyGUIDTime(u).Format(timeFormat))
return out
}
func (c *Client) GetSystemGUID(ctx context.Context) (response *GetSystemGUIDResponse, err error) {
request := &GetSystemGUIDRequest{}
response = &GetSystemGUIDResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_system_info_params.go 0000664 0000000 0000000 00000023307 14741105271 0025026 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"encoding/binary"
"fmt"
"unicode/utf16"
)
type GetSystemInfoParamRequest struct {
GetParamRevisionOnly bool
ParamSelector SystemInfoParamSelector
SetSelector uint8
BlockSelector uint8
}
type GetSystemInfoParamResponse struct {
ParamRevision uint8
ParamData []byte
}
func (req *GetSystemInfoParamRequest) Pack() []byte {
out := make([]byte, 4)
var b uint8
b = setOrClearBit7(b, req.GetParamRevisionOnly)
out[0] = b
out[1] = uint8(req.ParamSelector)
out[2] = req.SetSelector
out[3] = req.BlockSelector
return out
}
func (req *GetSystemInfoParamRequest) Command() Command {
return CommandGetSystemInfoParam
}
func (res *GetSystemInfoParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "parameter not supported",
}
}
func (res *GetSystemInfoParamResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
res.ParamRevision, _, _ = unpackUint8(msg, 0)
if len(msg) > 1 {
res.ParamData, _, _ = unpackBytes(msg, 1, len(msg)-1)
}
return nil
}
func (res *GetSystemInfoParamResponse) Format() string {
return fmt.Sprintf(`
Param Revision: %d
Param Data: %v
`, res.ParamRevision, res.ParamData)
}
func (c *Client) GetSystemInfoParam(ctx context.Context, paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8) (response *GetSystemInfoParamResponse, err error) {
request := &GetSystemInfoParamRequest{
ParamSelector: paramSelector,
SetSelector: setSelector,
BlockSelector: blockSelector,
}
response = &GetSystemInfoParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) GetSystemInfoParamFor(ctx context.Context, param SystemInfoParameter) error {
if isNilSystemInfoParamete(param) {
return nil
}
paramSelector, setSelector, blockSelector := param.SystemInfoParameter()
response, err := c.GetSystemInfoParam(ctx, paramSelector, setSelector, blockSelector)
if err != nil {
return fmt.Errorf("GetSystemInfoParam for param (%s[%d]) failed, err: %w", paramSelector.String(), paramSelector, err)
}
if err := param.Unpack(response.ParamData); err != nil {
return fmt.Errorf("unpack param (%s[%d]) failed, err: %w", paramSelector.String(), paramSelector, err)
}
return nil
}
func (c *Client) GetSystemInfoParams(ctx context.Context) (*SystemInfoParams, error) {
systemInfo := &SystemInfoParams{
SetInProgress: &SystemInfoParam_SetInProgress{},
SystemFirmwareVersions: make([]*SystemInfoParam_SystemFirmwareVersion, 0),
SystemNames: make([]*SystemInfoParam_SystemName, 0),
PrimaryOSNames: make([]*SystemInfoParam_PrimaryOSName, 0),
OSNames: make([]*SystemInfoParam_OSName, 0),
OSVersions: make([]*SystemInfoParam_OSVersion, 0),
BMCURLs: make([]*SystemInfoParam_BMCURL, 0),
ManagementURLs: make([]*SystemInfoParam_ManagementURL, 0),
}
if err := c.GetSystemInfoParamsFor(ctx, systemInfo); err != nil {
return nil, err
}
return systemInfo, nil
}
func (c *Client) GetSystemInfoParamsFor(ctx context.Context, params *SystemInfoParams) error {
if params == nil {
return nil
}
canIgnore := buildCanIgnoreFn(
0x80, // parameter not supported
)
if err := c.GetSystemInfoParamFor(ctx, params.SetInProgress); canIgnore(err) != nil {
return err
}
if params.SystemFirmwareVersions != nil {
if len(params.SystemFirmwareVersions) == 0 {
var setsCount uint8
p := &SystemInfoParam_SystemFirmwareVersion{
SetSelector: 0,
}
if err := c.GetSystemInfoParamFor(ctx, p); canIgnore(err) != nil {
return err
} else {
stringLength := uint8(p.BlockData[1])
setsCount = stringLength/16 + 1
}
params.SystemFirmwareVersions = make([]*SystemInfoParam_SystemFirmwareVersion, setsCount)
for i := uint8(0); i < setsCount; i++ {
p := &SystemInfoParam_SystemFirmwareVersion{
SetSelector: i,
}
params.SystemFirmwareVersions[i] = p
}
}
for _, param := range params.SystemFirmwareVersions {
if err := c.GetSystemInfoParamFor(ctx, param); canIgnore(err) != nil {
return err
}
}
}
if params.SystemNames != nil {
if len(params.SystemNames) == 0 {
var setsCount uint8
p := &SystemInfoParam_SystemName{
SetSelector: 0,
}
if err := c.GetSystemInfoParamFor(ctx, p); canIgnore(err) != nil {
return err
} else {
stringLength := uint8(p.BlockData[1])
setsCount = stringLength/16 + 1
}
params.SystemNames = make([]*SystemInfoParam_SystemName, setsCount)
for i := uint8(0); i < setsCount; i++ {
p := &SystemInfoParam_SystemName{
SetSelector: i,
}
params.SystemNames[i] = p
}
}
for _, param := range params.SystemNames {
if err := c.GetSystemInfoParamFor(ctx, param); canIgnore(err) != nil {
return err
}
}
}
if params.PrimaryOSNames != nil {
if len(params.PrimaryOSNames) == 0 {
var setsCount uint8
p := &SystemInfoParam_PrimaryOSName{
SetSelector: 0,
}
if err := c.GetSystemInfoParamFor(ctx, p); canIgnore(err) != nil {
return err
} else {
stringLength := uint8(p.BlockData[1])
setsCount = stringLength/16 + 1
}
params.PrimaryOSNames = make([]*SystemInfoParam_PrimaryOSName, setsCount)
for i := uint8(0); i < setsCount; i++ {
p := &SystemInfoParam_PrimaryOSName{
SetSelector: i,
}
params.PrimaryOSNames[i] = p
}
}
for _, param := range params.PrimaryOSNames {
if err := c.GetSystemInfoParamFor(ctx, param); canIgnore(err) != nil {
return err
}
}
}
if params.OSNames != nil {
if len(params.OSNames) == 0 {
var setsCount uint8
p := &SystemInfoParam_OSName{
SetSelector: 0,
}
if err := c.GetSystemInfoParamFor(ctx, p); canIgnore(err) != nil {
return err
} else {
stringLength := uint8(p.BlockData[1])
setsCount = stringLength/16 + 1
}
params.OSNames = make([]*SystemInfoParam_OSName, setsCount)
for i := uint8(0); i < setsCount; i++ {
p := &SystemInfoParam_OSName{
SetSelector: i,
}
params.OSNames[i] = p
}
}
for _, param := range params.OSNames {
if err := c.GetSystemInfoParamFor(ctx, param); canIgnore(err) != nil {
return err
}
}
}
if params.OSVersions != nil {
if len(params.OSVersions) == 0 {
var setsCount uint8
p := &SystemInfoParam_OSVersion{
SetSelector: 0,
}
if err := c.GetSystemInfoParamFor(ctx, p); canIgnore(err) != nil {
return err
} else {
stringLength := uint8(p.BlockData[1])
setsCount = stringLength/16 + 1
}
params.OSVersions = make([]*SystemInfoParam_OSVersion, setsCount)
for i := uint8(0); i < setsCount; i++ {
p := &SystemInfoParam_OSVersion{
SetSelector: i,
}
params.OSVersions[i] = p
}
}
for _, param := range params.OSVersions {
if err := c.GetSystemInfoParamFor(ctx, param); canIgnore(err) != nil {
return err
}
}
}
if params.BMCURLs != nil {
if len(params.BMCURLs) == 0 {
p := &SystemInfoParam_BMCURL{
SetSelector: 0,
}
if err := c.GetSystemInfoParamFor(ctx, p); canIgnore(err) != nil {
return err
}
//stringDataType := uint8(p.BlockData[0])
stringLength := uint8(p.BlockData[1]) // string length 1-based
setsCount := stringLength/16 + 1
params.BMCURLs = make([]*SystemInfoParam_BMCURL, setsCount)
for i := uint8(0); i < setsCount; i++ {
p := &SystemInfoParam_BMCURL{
SetSelector: i,
}
params.BMCURLs[i] = p
}
}
for _, param := range params.BMCURLs {
if err := c.GetSystemInfoParamFor(ctx, param); canIgnore(err) != nil {
return err
}
}
}
if params.ManagementURLs != nil {
if len(params.ManagementURLs) == 0 {
p := &SystemInfoParam_ManagementURL{
SetSelector: 0,
}
if err := c.GetSystemInfoParamFor(ctx, p); canIgnore(err) != nil {
return err
}
//stringDataType := uint8(p.BlockData[0])
stringLength := uint8(p.BlockData[1]) // string length 1-based
setsCount := stringLength/16 + 1
params.ManagementURLs = make([]*SystemInfoParam_ManagementURL, setsCount)
for i := uint8(0); i < setsCount; i++ {
p := &SystemInfoParam_ManagementURL{
SetSelector: i,
}
params.ManagementURLs[i] = p
}
}
for _, param := range params.ManagementURLs {
if err := c.GetSystemInfoParamFor(ctx, param); canIgnore(err) != nil {
return err
}
}
}
return nil
}
func (c *Client) GetSystemInfo(ctx context.Context) (*SystemInfo, error) {
systemInfoParams, err := c.GetSystemInfoParams(ctx)
if err != nil {
return nil, fmt.Errorf("GetSystemInfo failed, err: %w", err)
}
return systemInfoParams.ToSystemInfo(), nil
}
func getSystemInfoStringMeta(params []interface{}) (s string, stringDataRaw []byte, stringDataType uint8, stringDataLength uint8) {
if len(params) == 0 {
return
}
array := make([]SystemInfoParameter, 0)
for _, param := range params {
v, ok := param.(SystemInfoParameter)
if ok {
array = append(array, v)
}
}
allBlockData := make([]byte, 0)
for _, p := range array {
_, setSelector, _ := p.SystemInfoParameter()
paramData := p.Pack()
blockData := paramData[1:]
if setSelector == 0 {
stringDataType = blockData[0]
stringDataLength = blockData[1]
}
allBlockData = append(allBlockData, blockData[:]...)
}
stringDataRaw = allBlockData[2 : stringDataLength+2]
switch stringDataType {
// 0h = ASCII+Latin1
// 1h = UTF-8
// 2h = UNICODE
// all other = reserved.
case 0x00:
s = string(stringDataRaw)
case 0x01:
s = string(stringDataRaw)
case 0x02:
// here, suppose UTF-16
u16 := make([]uint16, len(stringDataRaw)/2)
for i := 0; i < len(u16); i++ {
u16[i] = binary.BigEndian.Uint16(stringDataRaw[i*2 : i*2+2])
}
// Decode UTF-16 to UTF-8
runes := utf16.Decode(u16)
s = string(runes)
default:
s = string(stringDataRaw)
}
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_system_interface_capabilities.go 0000664 0000000 0000000 00000004227 14741105271 0027201 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.9 Get System Interface Capabilities Command
type GetSystemInterfaceCapabilitiesRequest struct {
SystemInterfaceType SystemInterfaceType
}
type GetSystemInterfaceCapabilitiesResponse struct {
// For System Interface Type = SSIF
TransactionSupportMask uint8
PECSupported bool
SSIFVersion uint8
InputMessageSizeBytes uint8
OutputMessageSizeBytes uint8
// For System Interface Type = KCS or SMIC
SystemInterfaceVersion uint8
InputMaximumMessageSizeBytes uint8
}
type SystemInterfaceType uint8
const (
SystemInterfaceTypeSSIF SystemInterfaceType = 0x00
SystemInterfaceTypeKCS SystemInterfaceType = 0x01
SystemInterfaceTypeSMIC SystemInterfaceType = 0x02
)
func (req *GetSystemInterfaceCapabilitiesRequest) Command() Command {
return CommandGetSystemInterfaceCapabilities
}
func (req *GetSystemInterfaceCapabilitiesRequest) Pack() []byte {
return []byte{uint8(req.SystemInterfaceType)}
}
func (res *GetSystemInterfaceCapabilitiesResponse) Unpack(msg []byte) error {
// at least 3 bytes
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
// For System Interface Type = SSIF:
b, _, _ := unpackUint8(msg, 1)
res.TransactionSupportMask = b >> 6
res.PECSupported = isBit3Set(b)
res.SSIFVersion = b & 0x07
res.InputMessageSizeBytes, _, _ = unpackUint8(msg, 2)
// For System Interface Type = KCS or SMIC
res.SystemInterfaceVersion = b & 0x07
res.InputMaximumMessageSizeBytes, _, _ = unpackUint8(msg, 2)
if len(msg) >= 4 {
res.OutputMessageSizeBytes, _, _ = unpackUint8(msg, 3)
}
return nil
}
func (*GetSystemInterfaceCapabilitiesResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetSystemInterfaceCapabilitiesResponse) Format() string {
return ""
}
func (c *Client) GetSystemInterfaceCapabilities(ctx context.Context, interfaceType SystemInterfaceType) (response *GetSystemInterfaceCapabilitiesResponse, err error) {
request := &GetSystemInterfaceCapabilitiesRequest{
SystemInterfaceType: interfaceType,
}
response = &GetSystemInterfaceCapabilitiesResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_system_restart_cause.go 0000664 0000000 0000000 00000004706 14741105271 0025376 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 28.11 Get System Restart Cause Command
type GetSystemRestartCauseRequest struct {
// empty
}
type GetSystemRestartCauseResponse struct {
SystemRestartCause SystemRestartCause
ChannelNumber uint8
}
type SystemRestartCause uint8
var systemRestartCauses = map[SystemRestartCause]string{
0x00: "unknown", // unknown (system start/restart detected, but cause unknown)
0x01: "chassis power control command", //
0x02: "reset via pushbutton", //
0x03: "power-up via pushbutton", //
0x04: "watchdog expired", //
0x05: "OEM", //
0x06: "power-up due to always-on restore power policy", // automatic power-up on AC being applied due to 'always restore' power restore policy
0x07: "power-up due to previous restore power policy", // automatic power-up on AC being applied due to 'restore previous power state' power restore policy
0x08: "reset via PEF", //
0x09: "power-cycle via PEF", //
0x0a: "soft reset", // soft reset (e.g. CTRL-ALT-DEL) [optional]
0x0b: "power-up via RTC wakeup", // power-up via RTC (system real time clock) wakeup [optional]
}
func (c SystemRestartCause) String() string {
s, ok := systemRestartCauses[c]
if ok {
return s
}
return "invalid"
}
func (req *GetSystemRestartCauseRequest) Pack() []byte {
return []byte{}
}
func (req *GetSystemRestartCauseRequest) Command() Command {
return CommandGetSystemRestartCause
}
func (res *GetSystemRestartCauseResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetSystemRestartCauseResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
b, _, _ := unpackUint8(msg, 0)
res.SystemRestartCause = SystemRestartCause(b)
res.ChannelNumber, _, _ = unpackUint8(msg, 1)
return nil
}
func (res *GetSystemRestartCauseResponse) Format() string {
return fmt.Sprintf("System restart cause: %s", res.SystemRestartCause.String())
}
func (c *Client) GetSystemRestartCause(ctx context.Context) (response *GetSystemRestartCauseResponse, err error) {
request := &GetSystemRestartCauseRequest{}
response = &GetSystemRestartCauseResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_user_access.go 0000664 0000000 0000000 00000011671 14741105271 0023424 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"context"
"fmt"
"github.com/olekukonko/tablewriter"
)
// 22.27 Get User Access Command
type GetUserAccessRequest struct {
ChannelNumber uint8
UserID uint8
}
type GetUserAccessResponse struct {
// Maximum number of User IDs. 1-based. Count includes User 1. A value of 1
// indicates only User 1 is supported.
MaxUsersIDCount uint8
// [7:6] - User ID Enable status (for IPMI v2.0 errata 3 and later implementations).
// 00b = User ID enable status unspecified. (For backward compatibility
// with pre-errata 3 implementations. IPMI errata 3 and later
// implementations should return the 01b and 10b responses.)
// 01b = User ID enabled via Set User Password command.
// 10b = User ID disabled via Set User Password command.
// 11b = reserved
EnableStatus uint8
// [5:0] - count of currently enabled user IDs on this channel (Indicates how
// many User ID slots are presently in use.)
EnabledUserIDsCount uint8
// Count of User IDs with fixed names, including User 1 (1-based). Fixed names
// in addition to User 1 are required to be associated with sequential user IDs
// starting from User ID 2.
FixedNameUseIDsCount uint8
// [6] - 0b = user access available during call-in or callback direct connection
// 1b = user access available only during callback connection
CallbackOnly bool
// [5] - 0b = user disabled for link authentication
// 1b = user enabled for link authentication
LinkAuthEnabled bool
// [4] - 0b = user disabled for IPMI Messaging
// 1b = user enabled for IPMI Messaging
IPMIMessagingEnabled bool
// [3:0] - User Privilege Limit for given Channel
MaxPrivLevel PrivilegeLevel
}
func (req *GetUserAccessRequest) Command() Command {
return CommandGetUserAccess
}
func (req *GetUserAccessRequest) Pack() []byte {
return []byte{req.ChannelNumber, req.UserID}
}
func (res *GetUserAccessResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetUserAccessResponse) Unpack(msg []byte) error {
if len(msg) < 4 {
return ErrUnpackedDataTooShortWith(len(msg), 4)
}
res.MaxUsersIDCount, _, _ = unpackUint8(msg, 0)
b1, _, _ := unpackUint8(msg, 1)
res.EnableStatus = b1 & 0xc0 >> 6
res.EnabledUserIDsCount = b1 & 0x3f
b2, _, _ := unpackUint8(msg, 2)
res.FixedNameUseIDsCount = b2 & 0x3f
b3, _, _ := unpackUint8(msg, 3)
res.CallbackOnly = isBit6Set(b3)
res.LinkAuthEnabled = isBit5Set(b3)
res.IPMIMessagingEnabled = isBit4Set(b3)
res.MaxPrivLevel = PrivilegeLevel(b3 & 0x0f)
return nil
}
func (res *GetUserAccessResponse) Format() string {
return fmt.Sprintf(`Maximum IDs : %d
Enabled User Count : %d
Fixed Name Count : %d
`,
res.MaxUsersIDCount,
res.EnabledUserIDsCount,
res.FixedNameUseIDsCount,
)
}
func (c *Client) GetUserAccess(ctx context.Context, channelNumber uint8, userID uint8) (response *GetUserAccessResponse, err error) {
request := &GetUserAccessRequest{
ChannelNumber: channelNumber,
UserID: userID,
}
response = &GetUserAccessResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) ListUser(ctx context.Context, channelNumber uint8) ([]*User, error) {
var users = make([]*User, 0)
var userID uint8 = 1
var username string
for {
res, err := c.GetUserAccess(ctx, channelNumber, userID)
if err != nil {
return nil, fmt.Errorf("get user for userID %d failed, err: %s", userID, err)
}
res2, err := c.GetUsername(ctx, userID)
if err != nil {
respErr, ok := err.(*ResponseError)
if !ok || uint8(respErr.CompletionCode()) != 0xcc {
return nil, fmt.Errorf("get user name for userID %d failed, err: %s", userID, err)
}
// Completion Code is 0xcc, means this UserID is not set.
username = ""
} else {
username = res2.Username
}
user := &User{
ID: userID,
Name: username,
Callin: !res.CallbackOnly,
LinkAuthEnabled: res.LinkAuthEnabled,
IPMIMessagingEnabled: res.IPMIMessagingEnabled,
MaxPrivLevel: res.MaxPrivLevel,
}
users = append(users, user)
if userID >= res.MaxUsersIDCount {
break
}
userID += 1
}
return users, nil
}
type User struct {
ID uint8
Name string
Callin bool
LinkAuthEnabled bool
IPMIMessagingEnabled bool
MaxPrivLevel PrivilegeLevel
}
func FormatUsers(users []*User) string {
var buf = new(bytes.Buffer)
table := tablewriter.NewWriter(buf)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_RIGHT)
headers := []string{
"ID",
"Name",
"Callin",
"Link Auth",
"IPMI Msg",
"Channel Priv Limit",
}
table.SetHeader(headers)
table.SetFooter(headers)
for _, user := range users {
table.Append([]string{
fmt.Sprintf("%d", user.ID),
user.Name,
fmt.Sprintf("%v", user.Callin),
fmt.Sprintf("%v", user.LinkAuthEnabled),
fmt.Sprintf("%v", user.IPMIMessagingEnabled),
user.MaxPrivLevel.String(),
})
}
table.Render()
return buf.String()
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_username.go 0000664 0000000 0000000 00000002131 14741105271 0022733 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"context"
)
// 22.29 Get User Name Command
type GetUsernameRequest struct {
// [5:0] - User ID. 000000b = reserved. (User ID 1 is permanently associated with User 1, the null user name).
UserID uint8
}
type GetUsernameResponse struct {
Username string
}
func (req *GetUsernameRequest) Command() Command {
return CommandGetUsername
}
func (req *GetUsernameRequest) Pack() []byte {
return []byte{req.UserID}
}
func (res *GetUsernameResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *GetUsernameResponse) Unpack(msg []byte) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
username, _, _ := unpackBytes(msg, 0, 16)
res.Username = string(bytes.TrimRight(username, "\x00"))
return nil
}
func (res *GetUsernameResponse) Format() string {
return ""
}
func (c *Client) GetUsername(ctx context.Context, userID uint8) (response *GetUsernameResponse, err error) {
request := &GetUsernameRequest{
UserID: userID,
}
response = &GetUsernameResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_get_watchdog_timer.go 0000664 0000000 0000000 00000006600 14741105271 0024121 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 27.7 Get Watchdog Timer Command
type GetWatchdogTimerRequest struct {
// empty
}
func (req *GetWatchdogTimerRequest) Pack() []byte {
return []byte{}
}
func (req *GetWatchdogTimerRequest) Command() Command {
return CommandGetWatchdogTimer
}
type GetWatchdogTimerResponse struct {
DontLog bool
TimerIsStarted bool
TimerUse TimerUse
PreTimeoutInterrupt PreTimeoutInterrupt
TimeoutAction TimeoutAction
PreTimeoutIntervalSec uint8
ExpirationFlags uint8
InitialCountdown uint16
PresentCountdown uint16
}
func (res *GetWatchdogTimerResponse) Unpack(msg []byte) error {
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
res.DontLog = isBit7Set(msg[0])
res.TimerIsStarted = isBit6Set(msg[0])
res.TimerUse = TimerUse(0x07 & msg[0])
res.PreTimeoutInterrupt = PreTimeoutInterrupt((0x70 & msg[1]) >> 4)
res.TimeoutAction = TimeoutAction(0x07 & msg[1])
res.PreTimeoutIntervalSec = msg[2]
res.ExpirationFlags = msg[3]
res.InitialCountdown, _, _ = unpackUint16L(msg, 4)
res.PresentCountdown, _, _ = unpackUint16L(msg, 6)
return nil
}
func (res *GetWatchdogTimerResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetWatchdogTimerResponse) Format() string {
return fmt.Sprintf(`Watchdog Timer Use: %s (%#02x)
Watchdog Timer Is: %s
Watchdog Timer Actions: %s (%#02x)
Pre-timeout interval: %d seconds
Timer Expiration Flags: %#02x
Initial Countdown: %d sec
Present Countdown: %d sec`,
res.TimerUse, uint8(res.TimerUse),
formatBool(res.TimerIsStarted, "Started", "Stopped"),
res.TimeoutAction, uint8(res.TimeoutAction),
res.PreTimeoutIntervalSec,
res.ExpirationFlags,
res.InitialCountdown,
res.PresentCountdown,
)
}
func (c *Client) GetWatchdogTimer(ctx context.Context) (response *GetWatchdogTimerResponse, err error) {
request := &GetWatchdogTimerRequest{}
response = &GetWatchdogTimerResponse{}
err = c.Exchange(ctx, request, response)
return
}
type TimerUse uint8
const (
TimerUseBIOSFRB2 TimerUse = 0x01 // BIOS/FRB2
TimerUseBIOSPOST TimerUse = 0x02 // BIOS/POST
TimerUseOSLoad TimerUse = 0x03
TimerUseSMSOS TimerUse = 0x04 // SMS/OS
TimerUseOEM TimerUse = 0x05
)
func (t TimerUse) String() string {
m := map[TimerUse]string{
0x01: "BIOS FRB2",
0x02: "BIOS/POST",
0x03: "OS Load",
0x04: "SMS/OS",
0x05: "OEM",
}
s, ok := m[t]
if ok {
return s
}
return ""
}
type PreTimeoutInterrupt uint8
const (
PreTimeoutInterruptNone PreTimeoutInterrupt = 0x00
PreTimeoutInterruptSMI PreTimeoutInterrupt = 0x01
PreTimeoutInterruptNMI PreTimeoutInterrupt = 0x02
PreTimeoutInterruptMessaging PreTimeoutInterrupt = 0x03
)
func (t PreTimeoutInterrupt) String() string {
m := map[PreTimeoutInterrupt]string{
0x00: "None",
0x01: "SMI",
0x02: "NMI / Diagnostic Interrupt",
0x03: "Messaging Interrupt",
}
s, ok := m[t]
if ok {
return s
}
return ""
}
type TimeoutAction uint8
const (
TimeoutActionNoAction TimeoutAction = 0x00
TimeoutActionHardReset TimeoutAction = 0x01
TimeoutActionPowerDown TimeoutAction = 0x02
TimeoutActionPowerCycle TimeoutAction = 0x03
)
func (t TimeoutAction) String() string {
m := map[TimeoutAction]string{
0x00: "No action",
0x01: "Hard Reset",
0x02: "Power Down",
0x03: "Power Cycle",
}
s, ok := m[t]
if ok {
return s
}
return ""
}
golang-github-bougou-go-ipmi-0.7.2/cmd_manufacturing_test_on.go 0000664 0000000 0000000 00000001720 14741105271 0024656 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 20.4 20.5 Manufacturing Test On Command
type ManufacturingTestOnRequest struct {
// empty
}
type ManufacturingTestOnResponse struct {
// empty
}
func (req *ManufacturingTestOnRequest) Command() Command {
return CommandManufacturingTestOn
}
func (req *ManufacturingTestOnRequest) Pack() []byte {
return []byte{}
}
func (res *ManufacturingTestOnResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *ManufacturingTestOnResponse) Unpack(msg []byte) error {
return nil
}
func (res *ManufacturingTestOnResponse) Format() string {
// Todo
return ""
}
// If the device supports a "manufacturing test mode", this command is reserved to turn that mode on.
func (c *Client) ManufacturingTestOn(ctx context.Context) (response *ManufacturingTestOnResponse, err error) {
request := &ManufacturingTestOnRequest{}
response = &ManufacturingTestOnResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_master_write_read.go 0000664 0000000 0000000 00000003647 14741105271 0023772 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.11 Master Write-Read Command
type MasterWriteReadRequest struct {
// [7:4] channel number (Ignored when bus type = 1b)
ChannelNumber uint8
// [3:1] bus ID, 0-based (always 000b for public bus [bus type = 0b])
BusID uint8
// [0] bus type:
// - 0b = public (e.g. IPMB or PCI Management Bus.
// The channel number value is used to select the target bus.)
// - 1b = private bus (The bus ID value is used to select the target bus.)
BusTypeIsPrivate bool
SlaveAddress uint8
ReadCount uint8
// Data to write. This command should support at least 35 bytes of write data
Data []byte
}
type MasterWriteReadResponse struct {
// Bytes read from specified slave address.
// This field will be absent if the read count is 0.
// The controller terminates the I2C transaction with a STOP condition after reading the requested number of bytes.
Data []byte
}
func (req *MasterWriteReadRequest) Command() Command {
return CommandMasterWriteRead
}
func (req *MasterWriteReadRequest) Pack() []byte {
out := make([]byte, 3+len(req.Data))
var b uint8 = req.ChannelNumber << 4
b |= (req.BusID << 1) & 0x0e
if req.BusTypeIsPrivate {
b = setBit0(b)
}
packUint8(b, out, 0)
packUint8(req.SlaveAddress, out, 1)
packUint8(req.ReadCount, out, 2)
packBytes(req.Data, out, 3)
return out
}
func (res *MasterWriteReadResponse) Unpack(msg []byte) error {
res.Data, _, _ = unpackBytes(msg, 0, len(msg))
return nil
}
func (*MasterWriteReadResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "Lost Arbitration",
0x82: "Bus Error",
0x83: "NAK on Write",
0x84: "Truncated Read",
}
}
func (res *MasterWriteReadResponse) Format() string {
return ""
}
func (c *Client) MasterWriteRead(ctx context.Context, request *MasterWriteReadRequest) (*MasterWriteReadResponse, error) {
response := &MasterWriteReadResponse{}
err := c.Exchange(ctx, request, response)
return response, err
}
golang-github-bougou-go-ipmi-0.7.2/cmd_open_session.go 0000664 0000000 0000000 00000020341 14741105271 0022764 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 13.17 RMCP+ Open Session Request
type OpenSessionRequest struct {
MessageTag uint8
RequestedMaximumPrivilegeLevel PrivilegeLevel
RemoteConsoleSessionID uint32
AuthenticationPayload
IntegrityPayload
ConfidentialityPayload
}
// 13.18 RMCP+ Open Session Response
type OpenSessionResponse struct {
// The BMC returns the Message Tag value that was passed by the remote console in the Open Session Request message.
MessageTag uint8
// Identifies the status of the previous message.
// If the previous message generated an error, then only the Status Code, Reserved, and Remote Console Session ID fields are returned.
RmcpStatusCode RmcpStatusCode
MaximumPrivilegeLevel uint8
RemoteConsoleSessionID uint32
ManagedSystemSessionID uint32
AuthenticationPayload
IntegrityPayload
ConfidentialityPayload
}
type AuthenticationPayload struct {
// 00h = authentication algorithm
PayloadType uint8
PayloadLength uint8 // Payload Length in bytes (1-based). The total length in bytes of the payload including the header (= 08h for this specification).
AuthAlg uint8
}
type IntegrityPayload struct {
// 01h = integrity algorithm
PayloadType uint8
PayloadLength uint8
IntegrityAlg uint8
}
type ConfidentialityPayload struct {
// 02h = confidentiality algorithm
PayloadType uint8
PayloadLength uint8
CryptAlg uint8
}
const (
RmcpOpenSessionRequestSize int = 32
RmcpOpenSessionResponseSize int = 36
RmcpOpenSessionResponseMinSize int = 8
)
func (req *OpenSessionRequest) Command() Command {
return CommandNone
}
func (req *OpenSessionRequest) Pack() []byte {
var out = make([]byte, RmcpOpenSessionRequestSize)
packUint8(req.MessageTag, out, 0)
packUint8(uint8(req.RequestedMaximumPrivilegeLevel), out, 1)
packUint16(0, out, 2) // 2 bytes reserved
packUint32L(req.RemoteConsoleSessionID, out, 4)
packBytes(req.AuthenticationPayload.Pack(), out, 8)
packBytes(req.IntegrityPayload.Pack(), out, 16)
packBytes(req.ConfidentialityPayload.Pack(), out, 24)
return out
}
func (res *OpenSessionResponse) Unpack(data []byte) error {
if len(data) < RmcpOpenSessionResponseMinSize {
return ErrUnpackedDataTooShortWith(len(data), RmcpOpenSessionResponseMinSize)
}
res.MessageTag, _, _ = unpackUint8(data, 0)
b1, _, _ := unpackUint8(data, 1)
res.RmcpStatusCode = RmcpStatusCode(b1)
res.MaximumPrivilegeLevel, _, _ = unpackUint8(data, 2)
// reserved
res.RemoteConsoleSessionID, _, _ = unpackUint32L(data, 4)
// If the previous message generated an error, then only the Status Code, Reserved, and Remote Console Session ID fields are returned.
// See Table 13-, RMCP+ and RAKP Message Status Codes.
// The session establishment in progress is discarded at the BMC, and the
// remote console will need to start over with a new Open Session Request message.
// (Since the BMC has not yet delivered a Managed System Session ID to the remote console,
// it shouldn't be carrying any state information from the prior Open Session Request,
// but if it has, that state should be discarded.)
if res.RmcpStatusCode != RmcpStatusCodeNoErrors {
return nil
}
if len(data) < RmcpOpenSessionResponseSize {
return ErrUnpackedDataTooShortWith(len(data), RmcpOpenSessionResponseSize)
}
res.ManagedSystemSessionID, _, _ = unpackUint32L(data, 8)
res.AuthenticationPayload.Unpack(data[12:20])
res.IntegrityPayload.Unpack(data[20:28])
res.ConfidentialityPayload.Unpack(data[28:36])
return nil
}
func (*OpenSessionResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *OpenSessionResponse) Format() string {
return fmt.Sprintf(` Message tag : %#02x
RMCP+ status : %#02x %s
Maximum privilege level : %#02x %s
Console Session ID : %#0x
BMC Session ID : %#0x
Negotiated authentication algorithm : %#02x %s
Negotiated integrity algorithm : %#02x %s
Negotiated encryption algorithm : %#02x %s`,
res.MessageTag,
res.RmcpStatusCode, RmcpStatusCode(res.RmcpStatusCode),
res.MaximumPrivilegeLevel, PrivilegeLevel(res.MaximumPrivilegeLevel),
res.RemoteConsoleSessionID,
res.ManagedSystemSessionID,
res.AuthAlg, AuthAlg(res.AuthAlg),
res.IntegrityAlg, IntegrityAlg(res.IntegrityAlg),
res.CryptAlg, CryptAlg(res.CryptAlg),
)
}
func (c *Client) OpenSession(ctx context.Context) (response *OpenSessionResponse, err error) {
cipherSuiteID := c.session.v20.cipherSuiteID
authAlg, integrityAlg, cryptAlg, err := getCipherSuiteAlgorithms(cipherSuiteID)
if err != nil {
return nil, fmt.Errorf("get cipher suite for id %v failed, err: %s", cipherSuiteID, err)
}
c.session.v20.requestedAuthAlg = authAlg
c.session.v20.requestedIntegrityAlg = integrityAlg
c.session.v20.requestedEncryptAlg = cryptAlg
// Choose our session ID for easy recognition in the packet dump
var remoteConsoleSessionID uint32 = 0xa0a1a2a3
request := &OpenSessionRequest{
MessageTag: 0x00,
RequestedMaximumPrivilegeLevel: 0, // Request the highest level matching proposed algorithms
RemoteConsoleSessionID: remoteConsoleSessionID,
AuthenticationPayload: AuthenticationPayload{
PayloadType: 0x00, // 0 means authentication algorithm
PayloadLength: 8,
AuthAlg: uint8(c.session.v20.requestedAuthAlg),
},
IntegrityPayload: IntegrityPayload{
PayloadType: 0x01, // 1 means integrity algorithm
PayloadLength: 8,
IntegrityAlg: uint8(c.session.v20.requestedIntegrityAlg),
},
ConfidentialityPayload: ConfidentialityPayload{
PayloadType: 0x02, // 2 means confidentiality algorithm
PayloadLength: 8,
CryptAlg: uint8(c.session.v20.requestedEncryptAlg),
},
}
response = &OpenSessionResponse{}
c.session.v20.state = SessionStateOpenSessionSent
err = c.Exchange(ctx, request, response)
if err != nil {
return nil, fmt.Errorf("client exchange failed, err: %w", err)
}
c.Debug("OPEN SESSION RESPONSE", response.Format())
if response.RmcpStatusCode != RmcpStatusCodeNoErrors {
err = fmt.Errorf("rakp status code error: (%#02x) %s", uint8(response.RmcpStatusCode), response.RmcpStatusCode)
return
}
c.session.v20.state = SessionStateOpenSessionReceived
c.session.v20.authAlg = AuthAlg(response.AuthAlg)
c.session.v20.integrityAlg = IntegrityAlg(response.IntegrityAlg)
c.session.v20.cryptAlg = CryptAlg(response.CryptAlg)
c.session.v20.consoleSessionID = response.RemoteConsoleSessionID
c.session.v20.bmcSessionID = response.ManagedSystemSessionID
return
}
func (p *AuthenticationPayload) Pack() []byte {
out := make([]byte, 8)
packUint8(p.PayloadType, out, 0)
packUint16(0, out, 1) // 2 bytes reserved
packUint8(p.PayloadLength, out, 3)
packUint8(p.AuthAlg, out, 4)
packUint24(0, out, 5) // 3 bytes reserved
return out
}
func (p *AuthenticationPayload) Unpack(msg []byte) error {
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
p.PayloadType, _, _ = unpackUint8(msg, 0)
// 2 bytes reserved
p.PayloadLength, _, _ = unpackUint8(msg, 3)
p.AuthAlg, _, _ = unpackUint8(msg, 4)
// 3 bytes reserved
return nil
}
func (p *IntegrityPayload) Pack() []byte {
out := make([]byte, 8)
packUint8(p.PayloadType, out, 0)
packUint16(0, out, 1) // 2 bytes reserved
packUint8(p.PayloadLength, out, 3)
packUint8(p.IntegrityAlg, out, 4)
packUint24(0, out, 5) // 3 bytes reserved
return out
}
func (p *IntegrityPayload) Unpack(msg []byte) error {
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
p.PayloadType, _, _ = unpackUint8(msg, 0)
// 2 bytes reserved
p.PayloadLength, _, _ = unpackUint8(msg, 3)
p.IntegrityAlg, _, _ = unpackUint8(msg, 4)
// 3 bytes reserved
return nil
}
func (p *ConfidentialityPayload) Pack() []byte {
out := make([]byte, 8)
packUint8(p.PayloadType, out, 0)
packUint16(0, out, 1) // 2 bytes reserved
packUint8(p.PayloadLength, out, 3)
packUint8(p.CryptAlg, out, 4)
packUint24(0, out, 5) // 3 bytes reserved
return out
}
func (p *ConfidentialityPayload) Unpack(msg []byte) error {
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
p.PayloadType, _, _ = unpackUint8(msg, 0)
// 2 bytes reserved
p.PayloadLength, _, _ = unpackUint8(msg, 3)
p.CryptAlg, _, _ = unpackUint8(msg, 4)
// 3 bytes reserved
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_pet_acknowledge.go 0000664 0000000 0000000 00000004032 14741105271 0023412 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 30.8 PET Acknowledge Command
// This message is used to acknowledge a Platform Event Trap (PET) alert.
type PETAcknowledgeRequest struct {
SequenceNumber uint16
LocalTimestamp uint32
EventSourceType uint8
SensorDevice uint8
SensorNumber uint8
EventData EventData
}
type PETAcknowledgeResponse struct {
PETAcknowledgeStatus uint8
}
func (req *PETAcknowledgeRequest) Pack() []byte {
out := make([]byte, 12)
packUint16L(req.SequenceNumber, out, 0)
packUint32L(req.LocalTimestamp, out, 2)
out[6] = req.EventSourceType
out[7] = req.SensorDevice
out[8] = req.SensorNumber
out[9] = uint8(req.EventData.EventData1)
out[10] = uint8(req.EventData.EventData2)
out[11] = uint8(req.EventData.EventData3)
return out
}
func (req *PETAcknowledgeRequest) Unpack(data []byte) error {
if len(data) < 12 {
return ErrUnpackedDataTooShortWith(len(data), 12)
}
req.SequenceNumber, _, _ = unpackUint16L(data, 0)
req.LocalTimestamp, _, _ = unpackUint32L(data, 2)
req.EventSourceType = data[6]
req.SensorDevice = data[7]
req.SensorNumber = data[8]
req.EventData.EventData1 = data[9]
req.EventData.EventData2 = data[10]
req.EventData.EventData3 = data[11]
return nil
}
func (req *PETAcknowledgeRequest) Command() Command {
return CommandPETAcknowledge
}
func (res *PETAcknowledgeResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "Alert Immediate rejected due to alert already in progress",
0x82: "Alert Immediate rejected due to IPMI messaging session active on this channel",
0x83: "Platform Event Parameters (4:11) not supported",
}
}
func (res *PETAcknowledgeResponse) Unpack(msg []byte) error {
return nil
}
func (res *PETAcknowledgeResponse) Pack() []byte {
return []byte{}
}
func (res *PETAcknowledgeResponse) Format() string {
return ""
}
func (c *Client) PETAcknowledge(ctx context.Context, request *PETAcknowledgeRequest) (response *PETAcknowledgeResponse, err error) {
response = &PETAcknowledgeResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_platform_event_message.go 0000664 0000000 0000000 00000004150 14741105271 0025011 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 29.3 Platform Event Message Command
type PlatformEventMessageRequest struct {
// The Generator ID field is a required element of an Event Request Message.
// This field identifies the device that has generated the Event Message.
// This is the 7-bit Requester's Slave Address (RqSA) and 2-bit Requester's LUN (RqLUN)
// if the message was received from the IPMB, or the 7-bit System Software ID
// if the message was received from system software.
//
// For IPMB messages, this field is equated to the Requester's Slave Address and LUN fields.
// Thus, the Generator ID information is not carried in the data field of an IPMB request message.
//
// For 'system side' interfaces, it is not as useful or appropriate to 'overlay' the Generator ID field
// with the message source address information, and so it is specified as being carried in the data field of the request.
GeneratorID uint8
EvMRev uint8
SensorType uint8
SensorNumber uint8
EventDir EventDir
EventType EventReadingType
EventData EventData
}
type PlatformEventMessageResponse struct {
}
func (req *PlatformEventMessageRequest) Pack() []byte {
out := make([]byte, 8)
out[0] = req.GeneratorID
out[1] = req.EvMRev
out[2] = req.SensorType
out[3] = req.SensorNumber
var b4 = uint8(req.EventType)
if req.EventDir {
b4 |= 0x80
}
out[4] = b4
out[5] = req.EventData.EventData1
out[6] = req.EventData.EventData2
out[7] = req.EventData.EventData3
return []byte{}
}
func (req *PlatformEventMessageRequest) Command() Command {
return CommandPlatformEventMessage
}
func (res *PlatformEventMessageResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *PlatformEventMessageResponse) Unpack(msg []byte) error {
return nil
}
func (res *PlatformEventMessageResponse) Format() string {
return ""
}
func (c *Client) PlatformEventMessage(ctx context.Context, request *PlatformEventMessageRequest) (response *PlatformEventMessageResponse, err error) {
// Todo, consider GeneratorID
response = &PlatformEventMessageResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_rakp_message_1_2.go 0000664 0000000 0000000 00000015736 14741105271 0023376 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
const IPMI_MAX_USER_NAME_LENGTH = 16
const IPMI_RAKP1_MESSAGE_SIZE = 44
// 13.20 RAKP Message 1
type RAKPMessage1 struct {
MessageTag uint8
// The Managed System's Session ID for this session, returned by the Managed System on the
// previous RMCP+ Open Session Response message.
ManagedSystemSessionID uint32
// 16 bytes
RemoteConsoleRandomNumber [16]byte
// bit 4
// 0b = Username/Privilege lookup.
// 1b = Name-only lookup.
NameOnlyLookup bool
RequestedMaximumPrivilegeLevel PrivilegeLevel
UsernameLength uint8
Username []byte
}
type RAKPMessage2 struct {
// authAlg describes the authentication algorithm was agreed upon in
// the open session request/response phase.
// We need to know that here so that we know how many bytes (if any) to read from the packet for KeyExchangeAuthenticationCode
authAlg AuthAlg
MessageTag uint8
// RMCP+ Status Code - Identifies the status of the previous message.
//
// If the previous message generated an error, then only the Completion Code, Reserved, and
// Remote Console Session ID fields are returned.
//
// If the Remote Console Session ID field is indeterminate
// (as would be the case if the Managed System Session ID in RAKP Message 1 were invalid)
// then the Remote Console Session ID field will be set to all zeros.
//
// On error, the remote console can attempt to correct the error and send a new RAKP Message 1.
//
// Note that the remote console must change the Message Tag value to ensure the BMC sees the message as a new message and not as a retry.
//
// See Table 13-15, RMCP+ and RAKP Message Status Codes for the status codes defined for this message.
RmcpStatusCode RmcpStatusCode
// The Remote Console Session ID specified by the RMCP+ Open Session Request message associated with this response.
RemoteConsoleSessionID uint32
// Random number generated/selected by the managed system.
ManagedSystemRandomNumber [16]byte
// The Globally Unique ID (GUID) of the Managed System.
// This value is typically specified by the client system's SMBIOS implementation. See
// 22.14, Get System GUID Command, for additional information
ManagedSystemGUID [16]byte
// An integrity check value over the relevant items specified by the RAKP algorithm for RAKP Message 2.
// The size of this field depends on the specific Authentication Algorithm
// This field may be 0-bytes (absent) for some algorithms (e.g. RAKP-none).
//
// see 13.31 for how the managed system generate this HMAC
KeyExchangeAuthenticationCode []byte
}
func (req *RAKPMessage1) Command() Command {
return CommandNone
}
func (r *RAKPMessage1) Pack() []byte {
var msg = make([]byte, 28+len(r.Username))
packUint8(r.MessageTag, msg, 0)
packUint24L(0, msg, 1) // 3 bytes reserved
packUint32L(r.ManagedSystemSessionID, msg, 4)
packBytes((r.RemoteConsoleRandomNumber[:]), msg, 8)
packUint8(r.Role(), msg, 24)
packUint16L(0, msg, 25) // 2 bytes reserved
packUint8(r.UsernameLength, msg, 27)
packBytes(r.Username, msg, 28)
return msg
}
// the combination of RequestedMaximumPrivilegeLevel and NameOnlyLookup field
// The whole byte should be stored to client session for computing auth code of rakp2
func (r *RAKPMessage1) Role() uint8 {
privilegeLevel := uint8(r.RequestedMaximumPrivilegeLevel)
if r.NameOnlyLookup {
privilegeLevel = setBit4(privilegeLevel)
}
return privilegeLevel
}
func (res *RAKPMessage2) Unpack(msg []byte) error {
// If RAKPMessage1 failed to be validated, the returned RAKPMessage2 only holds 8 bytes.
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
res.MessageTag = msg[0]
res.RmcpStatusCode = RmcpStatusCode(msg[1])
// 2 bytes reserved
res.RemoteConsoleSessionID, _, _ = unpackUint32L(msg, 4)
// Now we can check whether RmcpStatusCode indicates error
if res.RmcpStatusCode != RmcpStatusCodeNoErrors {
return fmt.Errorf("the return status of rakp2 has error: %v", res.RmcpStatusCode)
}
if len(msg) < 40 {
return ErrUnpackedDataTooShortWith(len(msg), 40)
}
res.ManagedSystemRandomNumber = array16(msg[8:24])
res.ManagedSystemGUID = array16(msg[24:40])
var authCodeLen int = 0
switch res.authAlg {
case AuthAlgRAKP_None:
break
case AuthAlgRAKP_HMAC_MD5:
authCodeLen = 16
case AuthAlgRAKP_HMAC_SHA1:
authCodeLen = 20
case AuthAlgRAKP_HMAC_SHA256:
authCodeLen = 32
}
if len(msg) < 40+authCodeLen {
return fmt.Errorf("the unpacked data does not contain enough auth code")
}
res.KeyExchangeAuthenticationCode = make([]byte, authCodeLen)
copy(res.KeyExchangeAuthenticationCode, msg[40:40+authCodeLen])
return nil
}
func (*RAKPMessage2) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *RAKPMessage2) Format() string {
return fmt.Sprintf("%v", res)
}
// ValidateRAKP2 validates RAKPMessage2 returned by BMC.
func (c *Client) ValidateRAKP2(ctx context.Context, rakp2 *RAKPMessage2) (bool, error) {
if c.session.v20.consoleSessionID != rakp2.RemoteConsoleSessionID {
return false, fmt.Errorf("session id not matched, cached console session id: %x, rakp2 returned session id: %x", c.session.v20.consoleSessionID, rakp2.RemoteConsoleSessionID)
}
// rakp2 authcode is valid
authcode, err := c.generate_rakp2_authcode()
if err != nil {
return false, fmt.Errorf("generate rakp2 authcode failed, err: %w", err)
}
c.DebugBytes("rakp2 returned auth code", rakp2.KeyExchangeAuthenticationCode, 16)
if !isByteSliceEqual(authcode, rakp2.KeyExchangeAuthenticationCode) {
return false, fmt.Errorf("rakp2 authcode not equal, console: %x, bmc: %x", authcode, rakp2.KeyExchangeAuthenticationCode)
}
return true, nil
}
func (c *Client) RAKPMessage1(ctx context.Context) (response *RAKPMessage2, err error) {
c.session.v20.consoleRand = array16(randomBytes(16))
c.DebugBytes("console generate console random number", c.session.v20.consoleRand[:], 16)
request := &RAKPMessage1{
MessageTag: 0,
ManagedSystemSessionID: c.session.v20.bmcSessionID, // set by previous RMCP+ Open Session Request
RemoteConsoleRandomNumber: c.session.v20.consoleRand,
RequestedMaximumPrivilegeLevel: c.maxPrivilegeLevel,
NameOnlyLookup: true,
UsernameLength: uint8(len(c.Username)),
Username: []byte(c.Username),
}
c.session.v20.role = request.Role()
response = &RAKPMessage2{
authAlg: c.session.v20.authAlg,
}
c.session.v20.state = SessionStateRakp1Sent
err = c.Exchange(ctx, request, response)
if err != nil {
return nil, err
}
// the following fields must be set before generate_sik/generate_k1/generate_k2
c.session.v20.rakp2ReturnCode = uint8(response.RmcpStatusCode)
c.session.v20.bmcGUID = response.ManagedSystemGUID
c.session.v20.bmcRand = response.ManagedSystemRandomNumber // will be used in rakp3 to generate authCode
if _, err = c.ValidateRAKP2(ctx, response); err != nil {
err = fmt.Errorf("validate rakp2 message failed, err: %w", err)
return
}
c.session.v20.state = SessionStateRakp2Received
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_rakp_message_3_4.go 0000664 0000000 0000000 00000011765 14741105271 0023400 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 13.22 RAKP Message 3
type RAKPMessage3 struct {
// Selected by remote console. Used by remote console to help match
// responses up with requests.
MessageTag uint8
// Identifies the status of the previous message.
RmcpStatusCode RmcpStatusCode
// The Managed System's Session ID for this session, returned by the managed system on the previous RMCP+ Open Session Response message.
ManagedSystemSessionID uint32
// An integrity check value over the relevant items specified by the RAKP
// authentication algorithm identified in RAKP Message 1.
// The size of this field depends on the specific authentication algorithm.
//
// This field may be 0 bytes (absent) for some algorithms (e.g. RAKP-none).
KeyExchangeAuthenticationCode []byte
}
type RAKPMessage4 struct {
authAlg AuthAlg
MessageTag uint8
RmcpStatusCode RmcpStatusCode
MgmtConsoleSessionID uint32
// An integrity check value over the relevant items specified by
// the RAKP authentication algorithm that was identified in RAKP Message 1.
//
// The size of this field depends on the specific authentication algorithm.
//
// For example, the RAKP-HMAC-SHA1 specifies that an HMACSHA1-96 algorithm be used for calculating this field.
// See Section 13.28
// Authentication, Integrity, and Confidentiality Algorithm Numbers for info on
// the algorithm to be used for this field.
//
// This field may be 0 bytes (absent) for some authentication algorithms (e.g. RAKP-none)
IntegrityCheckValue []byte
}
func (req *RAKPMessage3) Command() Command {
return CommandNone
}
func (req *RAKPMessage3) Pack() []byte {
var msg = make([]byte, 8+len(req.KeyExchangeAuthenticationCode))
packUint8(req.MessageTag, msg, 0)
packUint8(uint8(req.RmcpStatusCode), msg, 1)
packUint16(0, msg, 2) // reserved
packUint32L(req.ManagedSystemSessionID, msg, 4)
packBytes(req.KeyExchangeAuthenticationCode, msg, 8)
return msg
}
func (res *RAKPMessage4) Unpack(msg []byte) error {
authCodeLen := 0
switch res.authAlg {
case AuthAlgRAKP_None:
// nothing need to do
case AuthAlgRAKP_HMAC_MD5:
// need to copy 16 bytes
authCodeLen = 16
case AuthAlgRAKP_HMAC_SHA1:
// need to copy 12 bytes
authCodeLen = 12
case AuthAlgRAKP_HMAC_SHA256:
authCodeLen = 16
default:
}
if len(msg) < 8+authCodeLen {
return ErrUnpackedDataTooShortWith(len(msg), 8+authCodeLen)
}
res.MessageTag, _, _ = unpackUint8(msg, 0)
b1, _, _ := unpackUint8(msg, 1)
res.RmcpStatusCode = RmcpStatusCode(b1)
res.MgmtConsoleSessionID, _, _ = unpackUint32L(msg, 4)
res.IntegrityCheckValue, _, _ = unpackBytes(msg, 8, authCodeLen)
return nil
}
func (*RAKPMessage4) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *RAKPMessage4) Format() string {
return fmt.Sprintf("%v", res)
}
// authAlg is used to parse the returned RAKPMessage4 message
func (c *Client) RAKPMessage3(ctx context.Context) (response *RAKPMessage4, err error) {
// create session integrity key
sik, err := c.generate_sik()
if err != nil {
err = fmt.Errorf("generate sik failed, err: %w", err)
return
}
c.session.v20.sik = sik
k1, err := c.generate_k1()
if err != nil {
err = fmt.Errorf("generate k1 failed, err: %w", err)
return
}
c.session.v20.k1 = k1
k2, err := c.generate_k2()
if err != nil {
err = fmt.Errorf("generate k2 failed, err: %w", err)
return
}
c.session.v20.k2 = k2
authCode, err := c.generate_rakp3_authcode()
if err != nil {
return nil, fmt.Errorf("generate rakp3 auth code failed, err: %w", err)
}
request := &RAKPMessage3{
MessageTag: 0,
RmcpStatusCode: RmcpStatusCode(c.session.v20.rakp2ReturnCode),
ManagedSystemSessionID: c.session.v20.bmcSessionID,
KeyExchangeAuthenticationCode: authCode,
}
response = &RAKPMessage4{
authAlg: c.session.v20.authAlg,
}
c.session.v20.state = SessionStateRakp3Sent
err = c.Exchange(ctx, request, response)
if err != nil {
return nil, err
}
if _, err = c.ValidateRAKP4(ctx, response); err != nil {
return nil, fmt.Errorf("validate rakp4 failed, err: %w", err)
}
c.session.v20.state = SessionStateActive
return response, nil
}
func (c *Client) ValidateRAKP4(ctx context.Context, response *RAKPMessage4) (bool, error) {
if response.RmcpStatusCode != RmcpStatusCodeNoErrors {
return false, fmt.Errorf("rakp4 status code not ok, %x", response.RmcpStatusCode)
}
// verify
if c.session.v20.consoleSessionID != response.MgmtConsoleSessionID {
return false, fmt.Errorf("session not activated")
}
authCode, err := c.generate_rakp4_authcode()
if err != nil {
return false, fmt.Errorf("generate rakp4 auth code failed, err: %w", err)
}
c.DebugBytes("rakp4 console computed authcode", authCode, 16)
c.DebugBytes("rakp4 bmc returned authcode", response.IntegrityCheckValue, 16)
if !isByteSliceEqual(response.IntegrityCheckValue, authCode) {
return false, fmt.Errorf("rakp4 returned integrity check not passed, console mac %0x, bmc mac: %0x", authCode, response.IntegrityCheckValue)
}
return true, nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_raw.go 0000664 0000000 0000000 00000002456 14741105271 0021060 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"strings"
)
type CommandRawRequest struct {
NetFn NetFn
Cmd uint8
Data []byte
Name string
}
type CommandRawResponse struct {
Response []byte
}
func (req *CommandRawRequest) Command() Command {
return Command{ID: req.Cmd, NetFn: req.NetFn, Name: req.Name}
}
func (req *CommandRawRequest) Pack() []byte {
out := make([]byte, len(req.Data))
packBytes(req.Data, out, 0)
return out
}
func (res *CommandRawResponse) Unpack(msg []byte) error {
res.Response = msg
return nil
}
func (res *CommandRawResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *CommandRawResponse) Format() string {
// convert the byte array to a slice of hex strings
hexStrings := make([]string, len(res.Response))
for i, b := range res.Response {
hexStrings[i] = fmt.Sprintf("0x%02X", b)
}
// join the hex strings with commas
hexString := strings.Join(hexStrings, ", ")
return fmt.Sprintf(`raw.Response = %s`, hexString)
}
func (c *Client) RawCommand(ctx context.Context, netFn NetFn, cmd uint8, data []byte, name string) (response *CommandRawResponse, err error) {
request := &CommandRawRequest{
NetFn: netFn,
Cmd: cmd,
Data: data,
Name: name,
}
response = &CommandRawResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_read_event_message_buffer.go 0000664 0000000 0000000 00000002172 14741105271 0025433 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.8 Read Event Message Buffer Command
type ReadEventMessageBufferRequest struct {
// empty
}
type ReadEventMessageBufferResponse struct {
// 16 bytes of data in SEL Record format
MessageData [16]byte
}
func (req ReadEventMessageBufferRequest) Command() Command {
return CommandReadEventMessageBuffer
}
func (req *ReadEventMessageBufferRequest) Pack() []byte {
return []byte{}
}
func (res *ReadEventMessageBufferResponse) Unpack(msg []byte) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
b, _, _ := unpackBytes(msg, 0, 16)
res.MessageData = array16(b)
return nil
}
func (*ReadEventMessageBufferResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: " data not available (queue / buffer empty)",
}
}
func (res *ReadEventMessageBufferResponse) Format() string {
return ""
}
func (c *Client) ReadEventMessageBuffer(ctx context.Context) (response *ReadEventMessageBufferResponse, err error) {
request := &ReadEventMessageBufferRequest{}
response = &ReadEventMessageBufferResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_read_fru_data.go 0000664 0000000 0000000 00000006577 14741105271 0023057 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 34.2 Read FRU Data Command
type ReadFRUDataRequest struct {
FRUDeviceID uint8
ReadOffset uint16
ReadCount uint8
}
type ReadFRUDataResponse struct {
CountReturned uint8
Data []byte
}
func (req *ReadFRUDataRequest) Command() Command {
return CommandReadFRUData
}
func (req *ReadFRUDataRequest) Pack() []byte {
out := make([]byte, 4)
packUint8(req.FRUDeviceID, out, 0)
packUint16L(req.ReadOffset, out, 1)
packUint8(req.ReadCount, out, 3)
return out
}
func (res *ReadFRUDataResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
res.CountReturned, _, _ = unpackUint8(msg, 0)
res.Data, _, _ = unpackBytes(msg, 1, len(msg)-1)
return nil
}
func (r *ReadFRUDataResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "FRU device busy",
}
}
func (res *ReadFRUDataResponse) Format() string {
return fmt.Sprintf(`Count returned : %d
Data : %02x`,
res.CountReturned,
res.Data,
)
}
// The command returns the specified data from the FRU Inventory Info area.
func (c *Client) ReadFRUData(ctx context.Context, fruDeviceID uint8, readOffset uint16, readCount uint8) (response *ReadFRUDataResponse, err error) {
request := &ReadFRUDataRequest{
FRUDeviceID: fruDeviceID,
ReadOffset: readOffset,
ReadCount: readCount,
}
response = &ReadFRUDataResponse{}
err = c.Exchange(ctx, request, response)
return
}
// readFRUDataByLength reads FRU Data in loop until reaches the specified data length
func (c *Client) readFRUDataByLength(ctx context.Context, deviceID uint8, offset uint16, length uint16) ([]byte, error) {
var data []byte
c.Debugf("Read FRU Data by Length, offset: (%d), length: (%d)\n", offset, length)
for {
if length <= 0 {
break
}
res, err := c.tryReadFRUData(ctx, deviceID, offset, length)
if err != nil {
return nil, fmt.Errorf("tryReadFRUData failed, err: %w", err)
}
c.Debug("", res.Format())
data = append(data, res.Data...)
length -= uint16(res.CountReturned)
c.Debugf("left length: %d\n", length)
// update offset
offset += uint16(res.CountReturned)
}
return data, nil
}
// tryReadFRUData will try to read FRU data with a read count which starts with
// the minimal number of the specified length and the hard-coded 32, if the
// ReadFRUData failed, it try another request with a decreased read count.
func (c *Client) tryReadFRUData(ctx context.Context, deviceID uint8, readOffset uint16, length uint16) (response *ReadFRUDataResponse, err error) {
var readCount uint8 = 32
if length <= uint16(readCount) {
readCount = uint8(length)
}
for {
if readCount <= 0 {
return nil, fmt.Errorf("nothing to read")
}
c.Debugf("Try Read FRU Data, offset: (%d), count: (%d)\n", readOffset, readCount)
res, err := c.ReadFRUData(ctx, deviceID, readOffset, readCount)
if err == nil {
return res, nil
}
resErr, ok := err.(*ResponseError)
if !ok {
return nil, fmt.Errorf("ReadFRUData failed, err: %w", err)
}
cc := resErr.CompletionCode()
if readFRUDataLength2Big(cc) {
readCount -= 1
continue
} else {
return nil, fmt.Errorf("ReadFRUData failed, err: %w", err)
}
}
}
func readFRUDataLength2Big(cc CompletionCode) bool {
return cc == CompletionCodeRequestDataLengthInvalid ||
cc == CompletionCodeRequestDataLengthLimitExceeded ||
cc == CompletionCodeCannotReturnRequestedDataBytes
}
golang-github-bougou-go-ipmi-0.7.2/cmd_reserve_device_sdr_repo.go 0000664 0000000 0000000 00000002050 14741105271 0025144 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 35.4 Reserve Device SDR Repository Command
type ReserveDeviceSDRRepoRequest struct {
// empty
}
type ReserveDeviceSDRRepoResponse struct {
ReservationID uint16
}
func (req *ReserveDeviceSDRRepoRequest) Command() Command {
return CommandReserveDeviceSDRRepo
}
func (req *ReserveDeviceSDRRepoRequest) Pack() []byte {
return []byte{}
}
func (res *ReserveDeviceSDRRepoResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.ReservationID, _, _ = unpackUint16L(msg, 0)
return nil
}
func (r *ReserveDeviceSDRRepoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *ReserveDeviceSDRRepoResponse) Format() string {
return ""
}
// This command is used to obtain a Reservation ID.
func (c *Client) ReserveDeviceSDRRepo(ctx context.Context) (response *ReserveDeviceSDRRepoResponse, err error) {
request := &ReserveDeviceSDRRepoRequest{}
response = &ReserveDeviceSDRRepoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_reserve_sdr_repo.go 0000664 0000000 0000000 00000001646 14741105271 0023637 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 33.11 Reserve SDR Repository Command
type ReserveSDRRepoRequest struct {
// empty
}
type ReserveSDRRepoResponse struct {
ReservationID uint16
}
func (req *ReserveSDRRepoRequest) Command() Command {
return CommandReserveSDRRepo
}
func (req *ReserveSDRRepoRequest) Pack() []byte {
return []byte{}
}
func (res *ReserveSDRRepoResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.ReservationID, _, _ = unpackUint16L(msg, 0)
return nil
}
func (r *ReserveSDRRepoResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *ReserveSDRRepoResponse) Format() string {
return ""
}
func (c *Client) ReserveSDRRepo(ctx context.Context) (response *ReserveSDRRepoResponse, err error) {
request := &ReserveSDRRepoRequest{}
response = &ReserveSDRRepoResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_reserve_sel.go 0000664 0000000 0000000 00000001670 14741105271 0022602 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 31.4 Reserve SEL Command
type ReserveSELRequest struct {
// empty
}
type ReserveSELResponse struct {
ReservationID uint16
}
func (req *ReserveSELRequest) Command() Command {
return CommandReserveSEL
}
func (req *ReserveSELRequest) Pack() []byte {
return nil
}
func (res *ReserveSELResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
res.ReservationID, _, _ = unpackUint16L(msg, 0)
return nil
}
func (*ReserveSELResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{
0x81: "cannot execute command, SEL erase in progress",
}
}
func (res *ReserveSELResponse) Format() string {
return ""
}
func (c *Client) ReserveSEL(ctx context.Context) (response *ReserveSELResponse, err error) {
request := &ReserveSELRequest{}
response = &ReserveSELResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_reset_watchdog_timer.go 0000664 0000000 0000000 00000001626 14741105271 0024467 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 27.5 Reset Watchdog Timer Command
type ResetWatchdogTimerRequest struct {
// empty
}
type ResetWatchdogTimerResponse struct {
}
func (req *ResetWatchdogTimerRequest) Pack() []byte {
return []byte{}
}
func (req *ResetWatchdogTimerRequest) Command() Command {
return CommandResetWatchdogTimer
}
func (res *ResetWatchdogTimerResponse) Unpack(msg []byte) error {
return nil
}
func (res *ResetWatchdogTimerResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{
0x80: "Attempt to start un-initialized watchdog",
}
}
func (res *ResetWatchdogTimerResponse) Format() string {
return ""
}
func (c *Client) ResetWatchdogTimer(ctx context.Context) (response *ResetWatchdogTimerResponse, err error) {
request := &ResetWatchdogTimerRequest{}
response = &ResetWatchdogTimerResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_rmcp_ping_request.go 0000664 0000000 0000000 00000003625 14741105271 0024014 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// RmcpPingRequest
// 13.2.3 RMCP/ASF Presence Ping Message
type RmcpPingRequest struct {
// empty
}
type RmcpPingResponse struct {
// If no OEM-specific capabilities exist, this field contains the ASF IANA (4542) and the OEM-defined field is set to all zeroes (00000000h). Otherwise, this field contains the OEM's IANA Enterprise Number and the OEM-defined field contains the OEM-specific capabilities.
OEMIANA uint32
// Not used for IPMI.
// This field can contain OEM-defined values; the definition of these values is left to the manufacturer identified by the preceding IANA Enterprise number.
OEMDefined uint32
IPMISupported bool
ASFVersion uint8
RMCPSecurityExtensionsSupported bool
DMTFDashSupported bool
// Reserved for future definition by ASF specification,
// set to 00 00 00 00 00 00h, six bytes
Reserved []byte
}
func (req *RmcpPingRequest) Pack() []byte {
return nil
}
func (req *RmcpPingRequest) Command() Command {
return CommandNone
}
func (res *RmcpPingResponse) Unpack(msg []byte) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
res.OEMIANA, _, _ = unpackUint32L(msg, 0)
res.OEMDefined, _, _ = unpackUint32L(msg, 4)
b, _, _ := unpackUint8(msg, 8)
res.IPMISupported = isBit7Set(b)
res.ASFVersion = b & 0x0f
c, _, _ := unpackUint8(msg, 9)
res.RMCPSecurityExtensionsSupported = isBit7Set(c)
res.DMTFDashSupported = isBit5Set(c)
res.Reserved, _, _ = unpackBytes(msg, 10, 6)
return nil
}
func (r *RmcpPingResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *RmcpPingResponse) Format() string {
return fmt.Sprintf("%v", res)
}
func (c *Client) RmcpPing(ctx context.Context) (response *RmcpPingResponse, err error) {
request := &RmcpPingRequest{}
response = &RmcpPingResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_send_message.go 0000664 0000000 0000000 00000003646 14741105271 0022726 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.7 Send Message Command
type SendMessageRequest struct {
// [7:6] 00b = No tracking
// 01b = Track Request.
// 10b = Send Raw. (optional)
// 11b = reserved
TrackMask uint8
Encrypted bool
Authenticated bool
ChannelNumber uint8
// Todo
MessageData []byte
}
type SendMessageResponse struct {
// This data will only be present when using the Send Message command to
// originate requests from IPMB or PCI Management Bus to other channels
// such as LAN or serial/modem. It is not present in the response to a
// Send Message command delivered via the System Interface.
Data []byte
}
func (req SendMessageRequest) Command() Command {
return CommandSendMessage
}
func (req *SendMessageRequest) Pack() []byte {
out := make([]byte, 1+len(req.MessageData))
var b uint8 = req.ChannelNumber
if req.Authenticated {
b = setBit4(b)
}
if req.Encrypted {
b = setBit5(b)
}
b |= (req.TrackMask << 6)
packUint8(b, out, 0)
packBytes(req.MessageData, out, 1)
return out
}
func (res *SendMessageResponse) Unpack(msg []byte) error {
res.Data, _, _ = unpackBytes(msg, 0, len(msg))
return nil
}
func (*SendMessageResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "Invalid Session Handle. The session handle does not match up with any currently active sessions for this channel.",
0x81: "Lost Arbitration",
0x82: "Bus Error",
0x83: "NAK on Write",
}
}
func (res *SendMessageResponse) Format() string {
return ""
}
func (c *Client) SendMessage(ctx context.Context, channelNumber uint8, authenticated bool, encrypted bool, trackMask uint8, data []byte) (response *SendMessageResponse, err error) {
request := &SendMessageRequest{
ChannelNumber: channelNumber,
Authenticated: authenticated,
Encrypted: encrypted,
TrackMask: trackMask,
MessageData: data,
}
response = &SendMessageResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_acpi_power_state.go 0000664 0000000 0000000 00000007011 14741105271 0024462 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 20.6 Set ACPI Power State Command
type SetACPIPowerStateRequest struct {
SetSystemPowerState bool // false means don't change system power state
SystemPowerState SystemPowerState
SetDevicePowerState bool // false means don't change device power state
DevicePowerState DevicePowerState
}
type SetACPIPowerStateResponse struct {
// empty
}
// see: https://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Global_states
type SystemPowerState uint8
const (
SystemPowerStateS0G0 uint8 = 0x00
SystemPowerStateS1 uint8 = 0x01
SystemPowerStateS2 uint8 = 0x02
SystemPowerStateS3 uint8 = 0x03
SystemPowerStateS4 uint8 = 0x04
SystemPowerStateS5G2 uint8 = 0x05
SystemPowerStateS4S5 uint8 = 0x06
SystemPowerStateG3 uint8 = 0x07
SystemPowerStateSleeping uint8 = 0x08
SystemPowerStateG1Sleeping uint8 = 0x09
SystemPowerStateOverride uint8 = 0x0a
SystemPowerStateLegacyOn uint8 = 0x20
SystemPowerStateLegacyOff uint8 = 0x21
SystemPowerStateUnknown uint8 = 0x2a
SystemPowerStateNoChange uint8 = 0x7f
)
func (s SystemPowerState) String() string {
m := map[SystemPowerState]string{
0x00: "S0/G0, working",
0x01: "S1, hardware context maintained, typically equates to processor/chip set clocks stopped",
0x02: "S2, typically equates to stopped clocks with processor/cache context lost",
0x03: "S3, typically equates to suspend-to-RAM",
0x04: "S4, typically equates to suspend-to-disk",
0x05: "S5/G2, soft off",
0x06: "S4/S5, sent when message source cannot differentiate between S4 and S5",
0x07: "G3, mechanical off",
0x08: "sleeping, sleeping - cannot differentiate between S1-S3",
0x09: "G1 sleeping, sleeping - cannot differentiate between S1-S4",
0x0a: "override, S5 entered by override",
0x20: "Legacy On, Legacy On (indicates On for system that don't support ACPI or have ACPI capabilities disabled)",
0x21: "Legacy Soft-Off",
0x2a: "Unknown, system power state unknown",
0x7f: "No Change",
}
o, ok := m[s]
if ok {
return o
}
return ""
}
type DevicePowerState uint8
const (
DevicePowerStateD0 uint8 = 0x00
DevicePowerStateD1 uint8 = 0x01
DevicePowerStateD2 uint8 = 0x02
DevicePowerStateD3 uint8 = 0x03
DevicePowerStateUnknown uint8 = 0x2a
DevicePowerStateNoChange uint8 = 0x7f
)
func (s DevicePowerState) String() string {
m := map[DevicePowerState]string{
0x00: "D0",
0x01: "D1",
0x02: "D2",
0x03: "D2",
0x2a: "Unknown",
0x7f: "No Change",
}
o, ok := m[s]
if ok {
return o
}
return ""
}
func (req *SetACPIPowerStateRequest) Pack() []byte {
out := make([]byte, 2)
var b1 = uint8(req.SystemPowerState)
if req.SetSystemPowerState {
b1 |= 0x80
}
packUint8(b1, out, 0)
var b2 = uint8(req.DevicePowerState)
if req.SetDevicePowerState {
b2 |= 0x80
}
packUint8(b2, out, 1)
return out
}
func (req *SetACPIPowerStateRequest) Command() Command {
return CommandSetACPIPowerState
}
func (res *SetACPIPowerStateResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetACPIPowerStateResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetACPIPowerStateResponse) Format() string {
return ""
}
// This command is provided to allow system software to tell a controller the present ACPI power state of the system.
func (c *Client) SetACPIPowerState(ctx context.Context, request *SetACPIPowerStateRequest) (err error) {
response := &SetACPIPowerStateResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_bmc_global_enables.go 0000664 0000000 0000000 00000004452 14741105271 0024712 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 22.1 Set BMC Global Enables Command
type SetBMCGlobalEnablesRequest struct {
// Generic system mgmt. software must do a "read-modify-write" using the Get BMC Global Enables and Set BMC Global Enables to avoid altering EnableOEM_X field.
EnableOEM2 bool
EnableOEM1 bool
EnableOEM0 bool
EnableSystemEventLogging bool
EnableEventMessageBuffer bool
EnableEventMessageBufferFullInterrupt bool
EnableReceiveMessageQueueInterrupt bool
}
type SetBMCGlobalEnablesResponse struct {
// empty
}
func (req *SetBMCGlobalEnablesRequest) Command() Command {
return CommandSetBMCGlobalEnables
}
func (req *SetBMCGlobalEnablesRequest) Pack() []byte {
var b uint8 = 0
if req.EnableOEM2 {
b = setBit7(b)
}
if req.EnableOEM1 {
b = setBit6(b)
}
if req.EnableOEM0 {
b = setBit5(b)
}
if req.EnableSystemEventLogging {
b = setBit3(b)
}
if req.EnableEventMessageBuffer {
b = setBit2(b)
}
if req.EnableEventMessageBufferFullInterrupt {
b = setBit1(b)
}
if req.EnableReceiveMessageQueueInterrupt {
b = setBit0(b)
}
return []byte{b}
}
func (res *SetBMCGlobalEnablesResponse) Unpack(msg []byte) error {
return nil
}
func (*SetBMCGlobalEnablesResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *SetBMCGlobalEnablesResponse) Format() string {
// Todo
return ""
}
func (c *Client) SetBMCGlobalEnables(ctx context.Context, enableSystemEventLogging bool, enableEventMessageBuffer bool, enableEventMessageBufferFullInterrupt bool, enableReceiveMessageQueueInterrupt bool) (response *SetBMCGlobalEnablesResponse, err error) {
getRes, err := c.GetBMCGlobalEnables(ctx)
if err != nil {
return nil, fmt.Errorf("GetBMCGlobalEnables failed, err: %w", err)
}
request := &SetBMCGlobalEnablesRequest{
EnableOEM2: getRes.OEM2Enabled,
EnableOEM1: getRes.OEM1Enabled,
EnableOEM0: getRes.OEM0Enabled,
EnableSystemEventLogging: enableSystemEventLogging,
EnableEventMessageBuffer: enableEventMessageBuffer,
EnableEventMessageBufferFullInterrupt: enableEventMessageBufferFullInterrupt,
EnableReceiveMessageQueueInterrupt: enableReceiveMessageQueueInterrupt,
}
response = &SetBMCGlobalEnablesResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_channel_access.go 0000664 0000000 0000000 00000003355 14741105271 0024072 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.22 Set Channel Access Command
type SetChannelAccessRequest struct {
ChannelNumber uint8
// [7:6] - 00b = don't set or change Channel Access
// 01b = set non-volatile Channel Access according to bits [5:0]
// 10b = set volatile (active) setting of Channel Access according to bit [5:0]
// 11b = reserved
AccessOption uint8
DisablePEFAlerting bool
DisablePerMsgAuth bool
DisableUserLevelAuth bool
AccessMode ChannelAccessMode
PrivilegeOption uint8
MaxPrivilegeLevel uint8
}
type SetChannelAccessResponse struct {
}
func (req *SetChannelAccessRequest) Pack() []byte {
out := make([]byte, 3)
packUint8(req.ChannelNumber, out, 0)
var b = req.AccessOption << 6
if req.DisablePEFAlerting {
b = setBit5(b)
}
if req.DisablePerMsgAuth {
b = setBit4(b)
}
if req.DisableUserLevelAuth {
b = setBit3(b)
}
b |= uint8(req.AccessMode) & 0x07
packUint8(b, out, 1)
var b2 = req.PrivilegeOption << 6
b2 |= req.MaxPrivilegeLevel & 0x3f
packUint8(b2, out, 2)
return out
}
func (req *SetChannelAccessRequest) Command() Command {
return CommandSetChannelAccess
}
func (res *SetChannelAccessResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x82: "set not supported on selected channel (e.g. channel is session-less.)",
0x83: "access mode not supported",
}
}
func (res *SetChannelAccessResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetChannelAccessResponse) Format() string {
return ""
}
func (c *Client) SetChannelAccess(ctx context.Context, request *SetChannelAccessRequest) (response *SetChannelAccessResponse, err error) {
response = &SetChannelAccessResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_chassis_capabilities.go 0000664 0000000 0000000 00000002615 14741105271 0025305 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 28.7 Set Chassis Capabilities Command
type SetChassisCapabilitiesRequest struct {
ProvideFrontPanelLockout bool
ProvideIntrusionSensor bool
FRUDeviceAddress uint8
SDRDeviceAddress uint8
SELDeviceAddress uint8
SystemManagementDeviceAddress uint8
BridgeDeviceAddress uint8
}
type SetChassisCapabilitiesResponse struct {
}
func (req *SetChassisCapabilitiesRequest) Pack() []byte {
out := make([]byte, 5)
var b uint8 = 0
if req.ProvideFrontPanelLockout {
b = setBit1(b)
}
if req.ProvideIntrusionSensor {
b = setBit0(b)
}
packUint8(b, out, 0)
packUint8(req.FRUDeviceAddress, out, 1)
packUint8(req.SDRDeviceAddress, out, 2)
packUint8(req.SELDeviceAddress, out, 3)
packUint8(req.SystemManagementDeviceAddress, out, 4)
return out
}
func (req *SetChassisCapabilitiesRequest) Command() Command {
return CommandSetChassisCapabilities
}
func (res *SetChassisCapabilitiesResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetChassisCapabilitiesResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetChassisCapabilitiesResponse) Format() string {
return ""
}
func (c *Client) SetChassisCapabilities(ctx context.Context, request *SetChassisCapabilitiesRequest) (response *SetChassisCapabilitiesResponse, err error) {
response = &SetChassisCapabilitiesResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_dcmi_asset_tag.go 0000664 0000000 0000000 00000006043 14741105271 0024104 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// [DCMI specification v1.5] 6.4.3 Set Asset Tag Command
type SetDCMIAssetTagRequest struct {
// The offset is relative to the first character of the Asset Tag data.
// Offset to write (0 to 62)
// C9h shall be returned if offset >62, offset+bytes to write >63, or bytes to write >16.
Offset uint8
// Number of bytes to write (16 bytes maximum).
// The command shall set the overall length of the Asset Tag (in bytes) to
// the value (offset to write + bytes to write). Any pre-existing Asset Tag
// bytes at offsets past that length are automatically deleted.
WriteBytes uint8
// The Asset Tag shall be encoded using either UTF-8 with Byte Order Mark or ASCII+Latin1 encoding.
// The maximum size of the Asset Tag shall be 63 bytes, including Byte Order Mark, if provided.
AssetTag []byte
}
type SetDCMIAssetTagResponse struct {
// Total Asset Tag Length.
// This is the length in bytes of the stored Asset Tag after the Set operation has completed.
// The Asset Tag length shall be set to the sum of the offset to write plus bytes to write.
// For example, if offset to write is 32 and bytes to write is 4, the Total Asset Tag Length returned will be 36.
TotalLength uint8
}
func (req *SetDCMIAssetTagRequest) Pack() []byte {
out := make([]byte, 3+len(req.AssetTag))
packUint8(GroupExtensionDCMI, out, 0)
packUint8(req.Offset, out, 1)
packUint8(req.WriteBytes, out, 2)
packBytes(req.AssetTag, out, 3)
return out
}
func (req *SetDCMIAssetTagRequest) Command() Command {
return CommandSetDCMIAssetTag
}
func (res *SetDCMIAssetTagResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetDCMIAssetTagResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
res.TotalLength = msg[1]
return nil
}
func (res *SetDCMIAssetTagResponse) Format() string {
return fmt.Sprintf("Total Length: %d", res.TotalLength)
}
func (c *Client) SetDCMIAssetTag(ctx context.Context, offset uint8, writeBytes uint8, assetTag []byte) (response *SetDCMIAssetTagResponse, err error) {
request := &SetDCMIAssetTagRequest{
Offset: offset,
WriteBytes: writeBytes,
AssetTag: assetTag,
}
response = &SetDCMIAssetTagResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) SetDCMIAssetTagFull(ctx context.Context, assetTag []byte) (err error) {
if len(assetTag) > 63 {
return fmt.Errorf("the asset tag must be at most 63 bytes")
}
var offset uint8 = 0
var writeBytes uint8 = 16
if len(assetTag) < 16 {
writeBytes = uint8(len(assetTag))
}
for {
offsetEnd := offset + writeBytes
_, err := c.SetDCMIAssetTag(ctx, offset, writeBytes, assetTag[offset:offsetEnd])
if err != nil {
return fmt.Errorf("SetDCMIAssetTag failed, err: %w", err)
}
offset = offset + writeBytes
if offset >= uint8(len(assetTag)) {
break
}
if offset+writeBytes > uint8(len(assetTag)) {
writeBytes = uint8(len(assetTag)) - offset
}
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_dcmi_config_params.go 0000664 0000000 0000000 00000003730 14741105271 0024742 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// [DCMI specification v1.5] 6.1.2 Set DCMI Configuration Parameters
type SetDCMIConfigParamRequest struct {
ParamSelector DCMIConfigParamSelector
SetSelector uint8 // use 00h for parameters that only have one set
ParamData []byte
}
type SetDCMIConfigParamResponse struct {
}
func (req *SetDCMIConfigParamRequest) Pack() []byte {
out := make([]byte, 3+len(req.ParamData))
packUint8(GroupExtensionDCMI, out, 0)
packUint8(uint8(req.ParamSelector), out, 1)
packUint8(req.SetSelector, out, 2)
packBytes(req.ParamData, out, 3)
return out
}
func (req *SetDCMIConfigParamRequest) Command() Command {
return CommandSetDCMIConfigParam
}
func (res *SetDCMIConfigParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetDCMIConfigParamResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
return nil
}
func (res *SetDCMIConfigParamResponse) Format() string {
return ""
}
func (c *Client) SetDCMIConfigParam(ctx context.Context, paramSelector DCMIConfigParamSelector, setSelector uint8, paramData []byte) (response *SetDCMIConfigParamResponse, err error) {
request := &SetDCMIConfigParamRequest{
ParamSelector: paramSelector,
SetSelector: setSelector,
ParamData: paramData,
}
response = &SetDCMIConfigParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) SetDCMIConfigParamFor(ctx context.Context, param DCMIConfigParameter) (response *SetDCMIConfigParamResponse, err error) {
if isNilDCMIConfigParameter(param) {
return nil, fmt.Errorf("param is nil")
}
paramSelector, setSelector := param.DCMIConfigParameter()
paramData := param.Pack()
response, err = c.SetDCMIConfigParam(ctx, paramSelector, setSelector, paramData)
if err != nil {
return nil, fmt.Errorf("SetDCMIConfigParam failed, err: %w", err)
}
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_dcmi_mgmt_controller_identifier.go 0000664 0000000 0000000 00000005346 14741105271 0027550 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// [DCMI specification v1.5] 6.4.6.2 Set Management Controller Identifier String Command
type SetDCMIMgmtControllerIdentifierRequest struct {
Offset uint8
WriteBytes uint8
IDStr []byte
}
type SetDCMIMgmtControllerIdentifierResponse struct {
// Total Asset Tag Length.
// This is the length in bytes of the stored Asset Tag after the Set operation has completed.
// The Asset Tag length shall be set to the sum of the offset to write plus bytes to write.
// For example, if offset to write is 32 and bytes to write is 4, the Total Asset Tag Length returned will be 36.
TotalLength uint8
}
func (req *SetDCMIMgmtControllerIdentifierRequest) Pack() []byte {
out := make([]byte, 3+len(req.IDStr))
packUint8(GroupExtensionDCMI, out, 0)
packUint8(req.Offset, out, 1)
packUint8(req.WriteBytes, out, 2)
packBytes(req.IDStr, out, 3)
return out
}
func (req *SetDCMIMgmtControllerIdentifierRequest) Command() Command {
return CommandSetDCMIMgmtControllerIdentifier
}
func (res *SetDCMIMgmtControllerIdentifierResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetDCMIMgmtControllerIdentifierResponse) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
res.TotalLength = msg[1]
return nil
}
func (res *SetDCMIMgmtControllerIdentifierResponse) Format() string {
return fmt.Sprintf("Total Length: %d", res.TotalLength)
}
func (c *Client) SetDCMIMgmtControllerIdentifier(ctx context.Context, offset uint8, writeBytes uint8, idStr []byte) (response *SetDCMIMgmtControllerIdentifierResponse, err error) {
request := &SetDCMIMgmtControllerIdentifierRequest{
Offset: offset,
WriteBytes: writeBytes,
IDStr: idStr,
}
response = &SetDCMIMgmtControllerIdentifierResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) SetDCMIMgmtControllerIdentifierFull(ctx context.Context, idStr []byte) (err error) {
if len(idStr) > 63 {
return fmt.Errorf("the id str must be at most 63 bytes")
}
// make sure idStr null terminated
if idStr[len(idStr)-1] != 0x00 {
idStr = append(idStr, 0x00)
}
var offset uint8 = 0
var writeBytes uint8 = 16
if len(idStr) < 16 {
writeBytes = uint8(len(idStr))
}
for {
offsetEnd := offset + writeBytes
_, err := c.SetDCMIMgmtControllerIdentifier(ctx, offset, writeBytes, idStr[offset:offsetEnd])
if err != nil {
return fmt.Errorf("SetDCMIMgmtControllerIdentifier failed, err: %w", err)
}
offset = offset + writeBytes
if offset >= uint8(len(idStr)) {
break
}
if offset+writeBytes > uint8(len(idStr)) {
writeBytes = uint8(len(idStr)) - offset
}
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_dcmi_power_limit.go 0000664 0000000 0000000 00000004501 14741105271 0024461 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// The Set Power Limit command sets the power limit parameters on the system.
// The power limit defines a threshold which, if exceeded for a configurable amount of time,
// will trigger a system power off and/or event logging action.
//
// If the limit is already active, the Set Power Limit command may immediately change the limit that is in effect.
// However, software should always explicitly activate the limit using the Activate/Deactivate power limit
// command to ensure the setting takes effect.
//
// [DCMI specification v1.5]: 6.6.3 Set Power Limit
type SetDCMIPowerLimitRequest struct {
ExceptionAction DCMIExceptionAction
// Power Limit Requested in Watts
PowerLimitRequested uint16
// Maximum time taken to limit the power after the platform power has reached
// the power limit before the Exception Action will be taken.
CorrectionTimeLimitMilliSec uint32
// Management application Statistics Sampling period in seconds
StatisticsSamplingPeriodSec uint16
}
type SetDCMIPowerLimitResponse struct {
}
func (req *SetDCMIPowerLimitRequest) Pack() []byte {
out := make([]byte, 15)
packUint8(GroupExtensionDCMI, out, 0)
packUint8(uint8(req.ExceptionAction), out, 4)
packUint16L(req.PowerLimitRequested, out, 5)
packUint32L(req.CorrectionTimeLimitMilliSec, out, 7)
packUint16L(req.StatisticsSamplingPeriodSec, out, 13)
return out
}
func (req *SetDCMIPowerLimitRequest) Command() Command {
return CommandSetDCMIPowerLimit
}
func (res *SetDCMIPowerLimitResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x84: "Power Limit out of range",
0x85: "Correction Time out of range",
0x89: "Statistics Reporting Period out of range",
}
}
func (res *SetDCMIPowerLimitResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
return nil
}
func (res *SetDCMIPowerLimitResponse) Format() string {
return ""
}
// SetDCMIPowerLimit sends a DCMI "Get Power Reading" command.
// See [SetDCMIPowerLimitRequest] for details.
func (c *Client) SetDCMIPowerLimit(ctx context.Context, request *SetDCMIPowerLimitRequest) (response *SetDCMIPowerLimitResponse, err error) {
response = &SetDCMIPowerLimitResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_dcmi_thermal_limit.go 0000664 0000000 0000000 00000003270 14741105271 0024763 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// [DCMI specification v1.5]: 6.7.2 Set Thermal Limit Command
type SetDCMIThermalLimitRequest struct {
EntityID EntityID // Entity ID = 37h or 40h (Inlet Temperature)
EntityInstance EntityInstance
ExceptionAction_PowerOffAndLogSEL bool
ExceptionAction_LogSELOnly bool // ignored if ExceptionAction_PowerOffAndLogSEL is true
TemperatureLimit uint8
ExceptionTimeSec uint16
}
type SetDCMIThermalLimitResponse struct {
}
func (req *SetDCMIThermalLimitRequest) Pack() []byte {
out := make([]byte, 7)
out[0] = GroupExtensionDCMI
out[1] = byte(req.EntityID)
out[2] = byte(req.EntityInstance)
exceptionAction := uint8(0)
if req.ExceptionAction_PowerOffAndLogSEL {
exceptionAction = setBit6(exceptionAction)
}
if req.ExceptionAction_LogSELOnly {
exceptionAction = setBit5(exceptionAction)
}
out[3] = exceptionAction
out[4] = req.TemperatureLimit
packUint16L(req.ExceptionTimeSec, out, 5)
return out
}
func (req *SetDCMIThermalLimitRequest) Command() Command {
return CommandSetDCMIThermalLimit
}
func (res *SetDCMIThermalLimitResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetDCMIThermalLimitResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
if err := CheckDCMIGroupExenstionMatch(msg[0]); err != nil {
return err
}
return nil
}
func (res *SetDCMIThermalLimitResponse) Format() string {
return ""
}
func (c *Client) SetDCMIThermalLimit(ctx context.Context, request *SetDCMIThermalLimitRequest) (response *SetDCMIThermalLimitResponse, err error) {
response = &SetDCMIThermalLimitResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_event_receiver.go 0000664 0000000 0000000 00000002462 14741105271 0024144 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 29.1 Set Event Receiver Command
type SetEventReceiverRequest struct {
// Event Receiver Slave Address.
// - 0FFh disables Event Message Generation, Otherwise:
// - [7:1] - IPMB (I2C) Slave Address
// - [0] - always 0b when [7:1] hold I2C slave address
SlaveAddress uint8
// [1:0] - Event Receiver LUN
LUN uint8
}
type SetEventReceiverResponse struct {
}
func (req *SetEventReceiverRequest) Pack() []byte {
return []byte{req.SlaveAddress, req.LUN}
}
func (req *SetEventReceiverRequest) Command() Command {
return CommandSetEventReceiver
}
func (res *SetEventReceiverResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetEventReceiverResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetEventReceiverResponse) Format() string {
return ""
}
func (c *Client) SetEventReceiver(ctx context.Context, slaveAddress uint8, lun uint8) (response *SetEventReceiverResponse, err error) {
request := &SetEventReceiverRequest{
SlaveAddress: slaveAddress,
LUN: lun,
}
response = &SetEventReceiverResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) SetEventReceiverDisable(ctx context.Context, lun uint8) (response *SetEventReceiverResponse, err error) {
return c.SetEventReceiver(ctx, 0xff, lun)
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_front_panel_enables.go 0000664 0000000 0000000 00000003160 14741105271 0025133 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 28.6 Set Front Panel Enables
// 定位
type SetFrontPanelEnablesRequest struct {
DisableSleepButton bool
DisableDiagnosticButton bool
DisableResetButton bool
DisablePoweroffButton bool
}
type SetFrontPanelEnablesResponse struct {
// empty
}
func (req *SetFrontPanelEnablesRequest) Pack() []byte {
out := make([]byte, 1)
var b uint8 = 0
if req.DisableSleepButton {
b = setBit3(b)
}
if req.DisableSleepButton {
b = setBit2(b)
}
if req.DisableSleepButton {
b = setBit1(b)
}
if req.DisableSleepButton {
b = setBit0(b)
}
packUint8(b, out, 1)
return out
}
func (req *SetFrontPanelEnablesRequest) Command() Command {
return CommandSetFrontPanelEnables
}
func (res *SetFrontPanelEnablesResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetFrontPanelEnablesResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetFrontPanelEnablesResponse) Format() string {
return ""
}
// The following command is used to enable or disable the buttons on the front panel of the chassis.
func (c *Client) SetFrontPanelEnables(ctx context.Context, disableSleepButton bool, disableDiagnosticButton bool, disableResetButton bool, disablePoweroffButton bool) (response *SetFrontPanelEnablesResponse, err error) {
request := &SetFrontPanelEnablesRequest{
DisableSleepButton: disableSleepButton,
DisableDiagnosticButton: disableDiagnosticButton,
DisableResetButton: disableResetButton,
DisablePoweroffButton: disablePoweroffButton,
}
response = &SetFrontPanelEnablesResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_lan_config_params.go 0000664 0000000 0000000 00000003770 14741105271 0024604 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 23.1 Set LAN Configuration Parameters Command
type SetLanConfigParamRequest struct {
ChannelNumber uint8
ParamSelector LanConfigParamSelector
ParamData []byte
}
type SetLanConfigParamResponse struct {
// empty
}
func (req *SetLanConfigParamRequest) Pack() []byte {
out := make([]byte, 2+len(req.ParamData))
packUint8(req.ChannelNumber, out, 0)
packUint8(uint8(req.ParamSelector), out, 1)
packBytes(req.ParamData, out, 2)
return out
}
func (req *SetLanConfigParamRequest) Command() Command {
return CommandSetLanConfigParam
}
func (res *SetLanConfigParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "parameter not supported.",
0x81: "attempt to set the 'set in progress' value (in parameter #0) when not in the 'set complete' state.",
0x82: "attempt to write read-only parameter",
0x83: "attempt to read write-only parameter",
}
}
func (res *SetLanConfigParamResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetLanConfigParamResponse) Format() string {
return ""
}
func (c *Client) SetLanConfigParam(ctx context.Context, channelNumber uint8, paramSelector LanConfigParamSelector, configData []byte) (response *SetLanConfigParamResponse, err error) {
request := &SetLanConfigParamRequest{
ChannelNumber: channelNumber,
ParamSelector: paramSelector,
ParamData: configData,
}
response = &SetLanConfigParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) SetLanConfigParamFor(ctx context.Context, channelNumber uint8, param LanConfigParameter) error {
paramSelector, _, _ := param.LanConfigParameter()
c.DebugBytes(fmt.Sprintf(">> Set param data for (%s[%d]) ", paramSelector.String(), paramSelector), param.Pack(), 8)
if _, err := c.SetLanConfigParam(ctx, channelNumber, paramSelector, param.Pack()); err != nil {
c.Debugf("!!! Set LanConfigParam for paramSelector (%d) %s failed, err: %v\n", uint8(paramSelector), paramSelector, err)
return err
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_last_processed_event_id.go 0000664 0000000 0000000 00000002467 14741105271 0026033 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 30.5 Set Last Processed Event ID Command
type SetLastProcessedEventIdRequest struct {
// 0b = set Record ID for last record processed by software.
// 1b = set Record ID for last record processed by BMC.
ByBMC bool
RecordID uint16
}
type SetLastProcessedEventIdResponse struct {
// empty
}
func (req *SetLastProcessedEventIdRequest) Command() Command {
return CommandSetLastProcessedEventId
}
func (req *SetLastProcessedEventIdRequest) Pack() []byte {
// empty request data
out := make([]byte, 3)
var b0 uint8 = 0x0
if req.ByBMC {
b0 = 1
}
packUint8(b0, out, 0)
packUint16L(req.RecordID, out, 1)
return out
}
func (res *SetLastProcessedEventIdResponse) Unpack(msg []byte) error {
return nil
}
func (r *SetLastProcessedEventIdResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x81: "cannot execute command, SEL erase in progress",
}
}
func (res *SetLastProcessedEventIdResponse) Format() string {
return ""
}
func (c *Client) SetLastProcessedEventId(ctx context.Context, recordID uint16, byBMC bool) (response *SetLastProcessedEventIdResponse, err error) {
request := &SetLastProcessedEventIdRequest{
ByBMC: byBMC,
RecordID: recordID,
}
response = &SetLastProcessedEventIdResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_pef_config_params.go 0000664 0000000 0000000 00000003057 14741105271 0024602 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 30.3 Set PEF Configuration Parameters Command
type SetPEFConfigParamRequest struct {
ParamSelector PEFConfigParamSelector
ParamData []byte
}
type SetPEFConfigParamResponse struct {
// empty
}
func (req *SetPEFConfigParamRequest) Command() Command {
return CommandSetPEFConfigParam
}
func (req *SetPEFConfigParamRequest) Pack() []byte {
// empty request data
out := make([]byte, 1+len(req.ParamData))
// out[0] = req.ParamSelector
packUint8(uint8(req.ParamSelector), out, 0)
if len(req.ParamData) > 0 {
packBytes(req.ParamData, out, 1)
}
return out
}
func (res *SetPEFConfigParamResponse) Unpack(msg []byte) error {
return nil
}
func (r *SetPEFConfigParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "parameter not supported",
// (This completion code provides a way to recognize that another party has already 'claimed' the parameters)"
0x81: "attempt to set the 'set in progress' value (in parameter #0) when not in the 'set complete' state.",
0x82: "attempt to write read-only parameter",
0x83: "attempt to read write-only parameter",
}
}
func (res *SetPEFConfigParamResponse) Format() string {
return ""
}
// Todo
func (c *Client) SetPEFConfigParam(ctx context.Context, paramSelector PEFConfigParamSelector, paramData []byte) (response *SetPEFConfigParamResponse, err error) {
request := &SetPEFConfigParamRequest{
ParamSelector: paramSelector,
ParamData: paramData,
}
response = &SetPEFConfigParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_power_cycle_interval.go 0000664 0000000 0000000 00000001752 14741105271 0025357 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 28.9 Set Power Cycle Interval
type SetPowerCycleIntervalRequest struct {
IntervalInSec uint8
}
type SetPowerCycleIntervalResponse struct {
// empty
}
func (req *SetPowerCycleIntervalRequest) Pack() []byte {
out := make([]byte, 1)
packUint8(req.IntervalInSec, out, 0)
return out
}
func (req *SetPowerCycleIntervalRequest) Command() Command {
return CommandSetPowerCycleInterval
}
func (res *SetPowerCycleIntervalResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetPowerCycleIntervalResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetPowerCycleIntervalResponse) Format() string {
return ""
}
func (c *Client) SetPowerCycleInterval(ctx context.Context, intervalInSec uint8) (response *SetPowerCycleIntervalResponse, err error) {
request := &SetPowerCycleIntervalRequest{
IntervalInSec: intervalInSec,
}
response = &SetPowerCycleIntervalResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_power_restore_policy.go 0000664 0000000 0000000 00000003477 14741105271 0025424 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 28.8 Set Power Restore Policy Command
type SetPowerRestorePolicyRequest struct {
PowerRestorePolicy
}
type SetPowerRestorePolicyResponse struct {
SupportPolicyAlwaysOn bool // chassis supports always powering up after AC/mains returns
SupportPolicyPrevious bool // chassis supports restoring power to state that was in effect when AC/mains was lost
SupportPolicyAlwaysOff bool // chassis supports staying powered off after AC/mains returns
}
func (req *SetPowerRestorePolicyRequest) Pack() []byte {
out := make([]byte, 1)
packUint8(uint8(req.PowerRestorePolicy), out, 0)
return out
}
func (req *SetPowerRestorePolicyRequest) Command() Command {
return CommandSetPowerRestorePolicy
}
func (res *SetPowerRestorePolicyResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetPowerRestorePolicyResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
b, _, _ := unpackUint8(msg, 0)
res.SupportPolicyAlwaysOff = isBit0Set(b)
res.SupportPolicyPrevious = isBit1Set(b)
res.SupportPolicyAlwaysOn = isBit2Set((b))
return nil
}
func (res *SetPowerRestorePolicyResponse) Format() string {
return fmt.Sprintf(`Policy always-off : %s"
Policy always-on : %s
Policy previous :"%s`,
formatBool(res.SupportPolicyAlwaysOff, "supported", "unsupported"),
formatBool(res.SupportPolicyAlwaysOff, "supported", "unsupported"),
formatBool(res.SupportPolicyAlwaysOff, "supported", "unsupported"),
)
}
func (c *Client) SetPowerRestorePolicy(ctx context.Context, policy PowerRestorePolicy) (response *SetPowerRestorePolicyResponse, err error) {
request := &SetPowerRestorePolicyRequest{
PowerRestorePolicy: policy,
}
response = &SetPowerRestorePolicyResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_sel_time.go 0000664 0000000 0000000 00000001605 14741105271 0022736 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"time"
)
// 31.11 Set SEL Time Command
type SetSELTimeRequest struct {
Time time.Time
}
type SetSELTimeResponse struct {
}
func (req *SetSELTimeRequest) Pack() []byte {
var out = make([]byte, 4)
packUint32L(uint32(req.Time.Unix()), out, 0)
return out
}
func (req *SetSELTimeRequest) Command() Command {
return CommandSetSELTime
}
func (res *SetSELTimeResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetSELTimeResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *SetSELTimeResponse) Format() string {
return fmt.Sprintf("%v", res)
}
func (c *Client) SetSELTime(ctx context.Context, t time.Time) (response *SetSELTimeResponse, err error) {
request := &SetSELTimeRequest{
Time: t,
}
response = &SetSELTimeResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_sel_time_utc_offset.go 0000664 0000000 0000000 00000002357 14741105271 0025164 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 31.11a Set SEL Time UTC Offset
type SetSELTimeUTCOffsetRequest struct {
// signed integer for the offset in minutes from UTC to SEL Time. (ranges from -1440 to 1440)
MinutesOffset int16
}
type SetSELTimeUTCOffsetResponse struct {
// empty
}
func (req *SetSELTimeUTCOffsetRequest) Pack() []byte {
out := make([]byte, 2)
a := twosComplementEncode(int32(req.MinutesOffset), 16)
packUint16L(uint16(a), out, 0)
return out
}
func (req *SetSELTimeUTCOffsetRequest) Command() Command {
return CommandSetSELTimeUTCOffset
}
func (res *SetSELTimeUTCOffsetResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetSELTimeUTCOffsetResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *SetSELTimeUTCOffsetResponse) Format() string {
return ""
}
// SetSELTimeUTCOffset initializes and retrieve a UTC offset (timezone) that is associated with the SEL Time
func (c *Client) SetSELTimeUTCOffset(ctx context.Context, minutesOffset int16) (response *SetSELTimeUTCOffsetResponse, err error) {
request := &SetSELTimeUTCOffsetRequest{
MinutesOffset: minutesOffset,
}
response = &SetSELTimeUTCOffsetResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_sensor_hysteresis.go 0000664 0000000 0000000 00000002740 14741105271 0024731 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 35.6 Set Sensor Hysteresis Command
type SetSensorHysteresisRequest struct {
SensorNumber uint8
PositiveHysteresis uint8
NegativeHysteresis uint8
}
type SetSensorHysteresisResponse struct {
}
func (req *SetSensorHysteresisRequest) Command() Command {
return CommandSetSensorHysteresis
}
func (req *SetSensorHysteresisRequest) Pack() []byte {
out := make([]byte, 4)
packUint8(req.SensorNumber, out, 0)
packUint8(0xff, out, 1) // reserved for future "hysteresis mask" definition. Write as FFh
packUint8(req.PositiveHysteresis, out, 2)
packUint8(req.NegativeHysteresis, out, 3)
return out
}
func (res *SetSensorHysteresisResponse) Unpack(msg []byte) error {
return nil
}
func (r *SetSensorHysteresisResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetSensorHysteresisResponse) Format() string {
return ""
}
// This command provides a mechanism for setting the hysteresis values associated
// with the thresholds of a sensor that has threshold based event generation.
func (c *Client) SetSensorHysteresis(ctx context.Context, sensorNumber uint8, positiveHysteresis uint8, negativeHysteresis uint8) (response *SetSensorHysteresisResponse, err error) {
request := &SetSensorHysteresisRequest{
SensorNumber: sensorNumber,
PositiveHysteresis: positiveHysteresis,
NegativeHysteresis: negativeHysteresis,
}
response = &SetSensorHysteresisResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_sensor_reading_and_event_status.go 0000664 0000000 0000000 00000003542 14741105271 0027567 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 35.17 Set Sensor Reading And Event Status Command
type SetSensorReadingAndEventStatusRequest struct {
SensorNumber uint8
EventDataBytesOperation uint8
AssertionBitsOperation uint8
DeassertionBitsOperation uint8
SensorReadingOperation uint8
SensorReading uint8
SensorEventFlag
EventData1 uint8
EventData2 uint8
EventData3 uint8
}
type SetSensorReadingAndEventStatusResponse struct {
// empty
}
func (req *SetSensorReadingAndEventStatusRequest) Command() Command {
return CommandSetSensorReadingAndEventStatus
}
func (req *SetSensorReadingAndEventStatusRequest) Pack() []byte {
out := make([]byte, 9)
packUint8(req.SensorNumber, out, 0)
var operation uint8
operation |= uint8(req.EventDataBytesOperation) << 6
operation |= (uint8(req.AssertionBitsOperation) & 0x3f) << 4
operation |= (uint8(req.DeassertionBitsOperation) & 0x0f) << 2
operation |= uint8(req.SensorReadingOperation) & 0x03
packUint8(operation, out, 1)
packUint8(req.SensorReading, out, 2)
// Todo determine sensor is threshold based or discrete
return out
}
func (res *SetSensorReadingAndEventStatusResponse) Unpack(msg []byte) error {
return nil
}
func (r *SetSensorReadingAndEventStatusResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "Attempt to change reading or set or clear status bits that are not settable via this command",
0x81: "Attempted to set Event Data Bytes, but setting Event Data Bytes is not supported for this sensor.",
}
}
func (res *SetSensorReadingAndEventStatusResponse) Format() string {
return ""
}
func (c *Client) SetSensorReadingAndEventStatus(ctx context.Context, request *SetSensorReadingAndEventStatusRequest) (response *SetSensorReadingAndEventStatusResponse, err error) {
response = &SetSensorReadingAndEventStatusResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_sensor_thresholds.go 0000664 0000000 0000000 00000004604 14741105271 0024707 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 35.8 Set Sensor Thresholds Command
type SetSensorThresholdsRequest struct {
SensorNumber uint8
// Set Threshold flag
SetUNR bool
SetUCR bool
SetUNC bool
SetLNR bool
SetLCR bool
SetLNC bool
// Threshold value
LNC_Raw uint8
LCR_Raw uint8
LNR_Raw uint8
UNC_Raw uint8
UCR_Raw uint8
UNR_Raw uint8
}
type SetSensorThresholdsResponse struct {
// empty
}
func (req *SetSensorThresholdsRequest) Command() Command {
return CommandSetSensorThresholds
}
func (req *SetSensorThresholdsRequest) Pack() []byte {
out := make([]byte, 8)
packUint8(req.SensorNumber, out, 0)
var b uint8
if req.SetUNR {
b = setBit5(b)
}
if req.SetUCR {
b = setBit4(b)
}
if req.SetUNC {
b = setBit3(b)
}
if req.SetLNR {
b = setBit2(b)
}
if req.SetLCR {
b = setBit1(b)
}
if req.SetLNC {
b = setBit0(b)
}
packUint8(b, out, 1)
packUint8(req.LNC_Raw, out, 2)
packUint8(req.LCR_Raw, out, 3)
packUint8(req.LNR_Raw, out, 4)
packUint8(req.UNC_Raw, out, 5)
packUint8(req.UCR_Raw, out, 6)
packUint8(req.UNR_Raw, out, 7)
return out
}
func (res *SetSensorThresholdsResponse) Unpack(msg []byte) error {
return nil
}
func (r *SetSensorThresholdsResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetSensorThresholdsResponse) Format() string {
return ""
}
// SetSensorThresholds is to set the specified threshold for the given sensor.
// Note that the application issuing this command is responsible for ensuring that
// thresholds for a sensor are set in the proper order (e.g. that
// the upper critical threshold is set higher than the upper non-critical threshold)
//
// Upper Non Recoverable area
// -----------------UNR threshold
// Upper Critical area
// -----------------UCR threshold
// Upper Non Critical area
// -----------------UNC threshold
// OK area
// -----------------LNC threshold
// Lower Non Critical area
// -----------------LCR threshold
// Lower Critical area
// -----------------LNR threshold
// Lower NonRecoverable area
//
// This command provides a mechanism for setting the hysteresis values associated
// with the thresholds of a sensor that has threshold based event generation.
func (c *Client) SetSensorThresholds(ctx context.Context, request *SetSensorThresholdsRequest) (response *SetSensorThresholdsResponse, err error) {
response = &SetSensorThresholdsResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_sensor_type.go 0000664 0000000 0000000 00000002245 14741105271 0023510 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 35.15 Set Sensor Type Command
type SetSensorTypeRequest struct {
SensorNumber uint8
SensorType SensorType
EventReadingType EventReadingType
}
type SetSensorTypeResponse struct {
// empty
}
func (req *SetSensorTypeRequest) Command() Command {
return CommandSetSensorType
}
func (req *SetSensorTypeRequest) Pack() []byte {
out := make([]byte, 3)
packUint8(req.SensorNumber, out, 0)
packUint8(uint8(req.SensorType), out, 1)
packUint8(uint8(req.EventReadingType), out, 2)
return out
}
func (res *SetSensorTypeResponse) Unpack(msg []byte) error {
return nil
}
func (r *SetSensorTypeResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetSensorTypeResponse) Format() string {
return ""
}
func (c *Client) SetSensorType(ctx context.Context, sensorNumber uint8, sensorType SensorType, eventReadingType EventReadingType) (response *SetSensorTypeResponse, err error) {
request := &SetSensorTypeRequest{
SensorNumber: sensorNumber,
SensorType: sensorType,
EventReadingType: eventReadingType,
}
response = &SetSensorTypeResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_session_privilege_level.go 0000664 0000000 0000000 00000002731 14741105271 0026056 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 22.18 Set Session Privilege Level Command
type SetSessionPrivilegeLevelRequest struct {
PrivilegeLevel PrivilegeLevel
}
type SetSessionPrivilegeLevelResponse struct {
// New Privilege Level (or present level if 'return present privilege level' was selected.)
PrivilegeLevel uint8
}
func (req *SetSessionPrivilegeLevelRequest) Command() Command {
return CommandSetSessionPrivilegeLevel
}
func (req *SetSessionPrivilegeLevelRequest) Pack() []byte {
var msg = make([]byte, 1)
packUint8(uint8(req.PrivilegeLevel), msg, 0)
return msg
}
func (res *SetSessionPrivilegeLevelResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
res.PrivilegeLevel = msg[0]
return nil
}
func (*SetSessionPrivilegeLevelResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "Requested level not available for this user",
0x81: "Requested level exceeds Channel and/or User Privilege Limit",
0x82: "Cannot disable User Level authentication",
}
}
func (res *SetSessionPrivilegeLevelResponse) Format() string {
return fmt.Sprintf("%v", res)
}
func (c *Client) SetSessionPrivilegeLevel(ctx context.Context, privilegeLevel PrivilegeLevel) (response *SetSessionPrivilegeLevelResponse, err error) {
request := &SetSessionPrivilegeLevelRequest{
PrivilegeLevel: privilegeLevel,
}
response = &SetSessionPrivilegeLevelResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_sol_config_params.go 0000664 0000000 0000000 00000003526 14741105271 0024626 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 26.2 Set SOL Configuration Parameters Command
type SetSOLConfigParamRequest struct {
ChannelNumber uint8
ParamSelector SOLConfigParamSelector
ParamData []byte
}
type SetSOLConfigParamResponse struct {
}
func (req *SetSOLConfigParamRequest) Command() Command {
return CommandSetSOLConfigParam
}
func (req *SetSOLConfigParamRequest) Pack() []byte {
out := make([]byte, 2+len(req.ParamData))
packUint8(req.ChannelNumber, out, 0)
packUint8(uint8(req.ParamSelector), out, 1)
packBytes(req.ParamData, out, 2)
return out
}
func (res *SetSOLConfigParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "parameter not supported",
0x81: "attempt to set the 'set in progress' value",
0x82: "attempt to write read-only parameter",
0x83: "attempt to read write-only parameter",
}
}
func (res *SetSOLConfigParamResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetSOLConfigParamResponse) Format() string {
return ""
}
func (c *Client) SetSOLConfigParam(ctx context.Context, channelNumber uint8, paramSelector SOLConfigParamSelector, paramData []byte) (response *SetSOLConfigParamResponse, err error) {
request := &SetSOLConfigParamRequest{
ChannelNumber: channelNumber,
ParamSelector: paramSelector,
ParamData: paramData,
}
response = &SetSOLConfigParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) SetSOLConfigParamFor(ctx context.Context, channelNumber uint8, param SOLConfigParameter) error {
if isNilSOLConfigParameter(param) {
return fmt.Errorf("param is nil")
}
paramSelector, _, _ := param.SOLConfigParameter()
paramData := param.Pack()
_, err := c.SetSOLConfigParam(ctx, channelNumber, paramSelector, paramData)
if err != nil {
return fmt.Errorf("SetSOLConfigParam failed, err: %w", err)
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_system_boot_options.go 0000664 0000000 0000000 00000004767 14741105271 0025273 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 28.12 Set System Boot Options Command
type SetSystemBootOptionsParamRequest struct {
// Parameter valid
// - 1b = mark parameter invalid / locked
// - 0b = mark parameter valid / unlocked
MarkParameterInvalid bool
// [6:0] - boot option parameter selector
ParamSelector BootOptionParamSelector
ParamData []byte
}
// Table 28-14, Boot Option Parameters
type SetSystemBootOptionsParamResponse struct {
}
func (req *SetSystemBootOptionsParamRequest) Pack() []byte {
out := make([]byte, 1+len(req.ParamData))
b := uint8(req.ParamSelector)
if req.MarkParameterInvalid {
b = setBit7(b)
} else {
b = clearBit7(b)
}
packUint8(b, out, 0)
packBytes(req.ParamData, out, 1)
return out
}
func (req *SetSystemBootOptionsParamRequest) Command() Command {
return CommandSetSystemBootOptions
}
func (res *SetSystemBootOptionsParamResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "parameter not supported",
0x81: "attempt to set the 'set in progress' value (in parameter #0) when not in the 'set complete' state. (This completion code provides a way to recognize that another party has already 'claimed' the parameters)",
0x82: "attempt to write read-only parameter",
}
}
func (res *SetSystemBootOptionsParamResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetSystemBootOptionsParamResponse) Format() string {
return ""
}
// This command is used to set parameters that direct the system boot following a system power up or reset.
// The boot flags only apply for one system restart. It is the responsibility of the system BIOS
// to read these settings from the BMC and then clear the boot flags
func (c *Client) SetSystemBootOptionsParam(ctx context.Context, request *SetSystemBootOptionsParamRequest) (response *SetSystemBootOptionsParamResponse, err error) {
response = &SetSystemBootOptionsParamResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) SetSystemBootOptionsParamFor(ctx context.Context, param BootOptionParameter) error {
if isNilBootOptionParameter(param) {
return fmt.Errorf("param is nil")
}
paramSelector, _, _ := param.BootOptionParameter()
paramData := param.Pack()
request := &SetSystemBootOptionsParamRequest{
MarkParameterInvalid: false,
ParamSelector: paramSelector,
ParamData: paramData,
}
if _, err := c.SetSystemBootOptionsParam(ctx, request); err != nil {
return fmt.Errorf("SetSystemBootOptionsParam failed, err: %w", err)
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_system_boot_options_others.go 0000664 0000000 0000000 00000004215 14741105271 0026643 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
func (c *Client) SetBootParamSetInProgress(ctx context.Context, setInProgress SetInProgressState) error {
param := &BootOptionParam_SetInProgress{
Value: setInProgress,
}
if err := c.SetSystemBootOptionsParamFor(ctx, param); err != nil {
return fmt.Errorf("SetSystemBootOptionsFor failed, err: %w", err)
}
return nil
}
func (c *Client) SetBootParamBootFlags(ctx context.Context, bootFlags *BootOptionParam_BootFlags) error {
if err := c.SetBootParamSetInProgress(ctx, SetInProgress_SetInProgress); err != nil {
goto OUT
} else {
if err := c.SetSystemBootOptionsParamFor(ctx, bootFlags); err != nil {
return fmt.Errorf("SetSystemBootOptions failed, err: %w", err)
}
}
OUT:
if err := c.SetBootParamSetInProgress(ctx, SetInProgress_SetComplete); err != nil {
return fmt.Errorf("SetBootParamSetInProgress failed, err: %w", err)
}
return nil
}
func (c *Client) SetBootParamClearAck(ctx context.Context, by BootInfoAcknowledgeBy) error {
param := &BootOptionParam_BootInfoAcknowledge{}
switch by {
case BootInfoAcknowledgeByBIOSPOST:
param.ByBIOSPOST = true
case BootInfoAcknowledgeByOSLoader:
param.ByOSLoader = true
case BootInfoAcknowledgeByOSServicePartition:
param.ByOSServicePartition = true
case BootInfoAcknowledgeBySMS:
param.BySMS = true
case BootInfoAcknowledgeByOEM:
param.ByOEM = true
}
if err := c.SetSystemBootOptionsParamFor(ctx, param); err != nil {
return fmt.Errorf("SetSystemBootOptionsFor failed, err: %w", err)
}
return nil
}
// SetBootDevice set the boot device for next boot.
// persist of false means it applies to next boot only.
// persist of true means this setting is persistent for all future boots.
func (c *Client) SetBootDevice(ctx context.Context, bootDeviceSelector BootDeviceSelector, bootType BIOSBootType, persist bool) error {
param := &BootOptionParam_BootFlags{
BootFlagsValid: true,
Persist: persist,
BIOSBootType: bootType,
BootDeviceSelector: bootDeviceSelector,
}
if err := c.SetSystemBootOptionsParamFor(ctx, param); err != nil {
return fmt.Errorf("SetSystemBootOptions failed, err: %w", err)
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_user_access.go 0000664 0000000 0000000 00000003230 14741105271 0023430 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.26 Set User Access Command
type SetUserAccessRequest struct {
EnableChanging bool
RestrictedToCallback bool
EnableLinkAuth bool
EnableIPMIMessaging bool
ChannelNumber uint8
UserID uint8
MaxPrivLevel uint8
SessionLimit uint8
}
type SetUserAccessResponse struct {
}
func (req *SetUserAccessRequest) Command() Command {
return CommandSetUserAccess
}
func (req *SetUserAccessRequest) Pack() []byte {
out := make([]byte, 4)
b := req.ChannelNumber & 0x0f
if req.EnableChanging {
b = setBit7(b)
}
if req.RestrictedToCallback {
b = setBit6(b)
}
if req.EnableLinkAuth {
b = setBit5(b)
}
if req.EnableIPMIMessaging {
b = setBit4(b)
}
packUint8(b, out, 0)
packUint8(req.UserID&0x3f, out, 1)
packUint8(req.MaxPrivLevel&0x3f, out, 2)
packUint8(req.SessionLimit&0x0f, out, 3)
return out
}
func (res *SetUserAccessResponse) CompletionCodes() map[uint8]string {
// Note: an implementation will not return an error completion code if the user
// access level is set higher than the privilege limit for a given channel. If it is
// desired to bring attention to this condition, it is up to software to check the
// channel privilege limits set using the Set Channel Access command and
// provide notification of any mismatch.
return map[uint8]string{}
}
func (res *SetUserAccessResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetUserAccessResponse) Format() string {
return ""
}
func (c *Client) SetUserAccess(ctx context.Context, request *SetUserAccessRequest) (response *SetUserAccessResponse, err error) {
response = &SetUserAccessResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_user_password.go 0000664 0000000 0000000 00000005614 14741105271 0024041 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.30 Set User Password Command
type SetUserPasswordRequest struct {
// [5:0] - User ID. 000000b = reserved. (User ID 1 is permanently associated with User 1, the null user name).
UserID uint8
// The BMC shall maintain an internal tag that indicates whether
// the password was set as a 16-byte or as a 20-byte password.
Stored20 bool
Operation PasswordOperation
Password string
}
type PasswordOperation uint8
const (
PasswordOperationDisableUser PasswordOperation = 0x00
PasswordOperationEnableUser PasswordOperation = 0x01
PasswordOperationSetPassword PasswordOperation = 0x02
PasswordOperationTestPassword PasswordOperation = 0x03
)
type SetUserPasswordResponse struct {
// empty
}
func (req *SetUserPasswordRequest) Command() Command {
return CommandSetUserPassword
}
func (req *SetUserPasswordRequest) Pack() []byte {
out := make([]byte, 2)
b := req.UserID & 0x3f
if req.Stored20 {
b = setBit7(b)
}
packUint8(b, out, 0)
packUint8(uint8(req.Operation)&0x03, out, 1)
if req.Operation == PasswordOperationSetPassword || req.Operation == PasswordOperationTestPassword {
var passwordStored []byte
if req.Stored20 {
passwordStored = padBytes(req.Password, 20, 0x00)
} else {
passwordStored = padBytes(req.Password, 16, 0x00)
}
out = append(out, passwordStored...)
}
return out
}
func (res *SetUserPasswordResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetUserPasswordResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetUserPasswordResponse) Format() string {
return ""
}
func (c *Client) SetUserPassword(ctx context.Context, userID uint8, password string, stored20 bool) (response *SetUserPasswordResponse, err error) {
request := &SetUserPasswordRequest{
UserID: userID,
Stored20: stored20,
Operation: PasswordOperationSetPassword,
Password: password,
}
response = &SetUserPasswordResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) TestUserPassword(ctx context.Context, userID uint8, password string, stored20 bool) (response *SetUserPasswordResponse, err error) {
request := &SetUserPasswordRequest{
UserID: userID,
Stored20: stored20,
Operation: PasswordOperationTestPassword,
Password: password,
}
response = &SetUserPasswordResponse{}
err = c.Exchange(ctx, request, response)
return
}
func (c *Client) DisableUser(ctx context.Context, userID uint8) (err error) {
request := &SetUserPasswordRequest{
UserID: userID,
Operation: PasswordOperationDisableUser,
}
response := &SetUserPasswordResponse{}
err = c.Exchange(ctx, request, response)
return err
}
func (c *Client) EnableUser(ctx context.Context, userID uint8) (err error) {
request := &SetUserPasswordRequest{
UserID: userID,
Operation: PasswordOperationEnableUser,
}
response := &SetUserPasswordResponse{}
err = c.Exchange(ctx, request, response)
return err
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_username.go 0000664 0000000 0000000 00000002635 14741105271 0022760 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.28 Set User Name Command
type SetUsernameRequest struct {
// [5:0] - User ID. 000000b = reserved. (User ID 1 is permanently associated with User 1, the null user name).
UserID uint8
// User Name String in ASCII, 16 bytes, max. Strings with fewer than 16
// characters are terminated with a null (00h) character and 00h padded to 16
// bytes. When the string is read back using the Get User Name command,
// those bytes shall be returned as 0s.
// Here if string length is longer than 16, it would be auto truncated.
Username string
}
type SetUsernameResponse struct {
GUID [16]byte
}
func (req *SetUsernameRequest) Command() Command {
return CommandSetUsername
}
func (req *SetUsernameRequest) Pack() []byte {
out := make([]byte, 17)
packUint8(req.UserID, out, 0)
username := padBytes(req.Username, 16, 0x00)
packBytes(username, out, 1)
return out
}
func (res *SetUsernameResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SetUsernameResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetUsernameResponse) Format() string {
return ""
}
func (c *Client) SetUsername(ctx context.Context, userID uint8, username string) (response *SetUsernameResponse, err error) {
request := &SetUsernameRequest{
UserID: userID,
Username: username,
}
response = &SetUsernameResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_set_watchdog_timer.go 0000664 0000000 0000000 00000002636 14741105271 0024142 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 27.6 Set Watchdog Timer Command
type SetWatchdogTimerRequest struct {
DontLog bool
DontStopTimer bool
TimerUse TimerUse
PreTimeoutInterrupt PreTimeoutInterrupt
TimeoutAction TimeoutAction
PreTimeoutIntervalSec uint8
ExpirationFlags uint8
InitialCountdown uint16
}
type SetWatchdogTimerResponse struct {
}
func (req *SetWatchdogTimerRequest) Pack() []byte {
out := make([]byte, 6)
b0 := uint8(req.TimerUse)
if req.DontLog {
b0 = setBit7(b0)
}
if req.DontStopTimer {
b0 = setBit6(b0)
}
packUint8(b0, out, 0)
b1 := uint8(req.TimeoutAction)
b1 |= uint8(req.PreTimeoutInterrupt) << 4
packUint8(b1, out, 1)
packUint8(req.PreTimeoutIntervalSec, out, 2)
packUint8(req.ExpirationFlags, out, 3)
packUint16L(req.InitialCountdown, out, 4)
return out
}
func (req *SetWatchdogTimerRequest) Command() Command {
return CommandSetWatchdogTimer
}
func (res *SetWatchdogTimerResponse) Unpack(msg []byte) error {
return nil
}
func (res *SetWatchdogTimerResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *SetWatchdogTimerResponse) Format() string {
return ""
}
func (c *Client) SetWatchdogTimer(ctx context.Context) (response *SetWatchdogTimerResponse, err error) {
request := &SetWatchdogTimerRequest{}
response = &SetWatchdogTimerResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_sol_activating.go 0000664 0000000 0000000 00000002022 14741105271 0023262 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 26.1 SOL Activating Command
type SOLActivatingRequest struct {
SessionState uint8
PayloadInstance uint8
FormatVersionMajor uint8
FormatVersionMinor uint8
}
type SOLActivatingResponse struct {
}
func (req *SOLActivatingRequest) Command() Command {
return CommandSOLActivating
}
func (req *SOLActivatingRequest) Pack() []byte {
out := make([]byte, 4)
packUint8(req.SessionState, out, 0)
packUint8(req.PayloadInstance, out, 1)
packUint8(req.FormatVersionMajor, out, 2)
packUint8(req.FormatVersionMinor, out, 3)
return out
}
func (res *SOLActivatingResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *SOLActivatingResponse) Unpack(msg []byte) error {
return nil
}
func (res *SOLActivatingResponse) Format() string {
return ""
}
func (c *Client) SOLActivating(ctx context.Context, request *SOLActivatingRequest) (response *SOLActivatingResponse, err error) {
response = &SOLActivatingResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_suspend_bmc_arps.go 0000664 0000000 0000000 00000002756 14741105271 0023621 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 23.3 Suspend BMC ARPs Command
type SuspendARPsRequest struct {
ChannelNumber uint8
SuspendARP bool
SuspendGratuitousARP bool
}
type SuspendARPsResponse struct {
// Present state of ARP suspension
IsARPOccurring bool
IsGratuitousARPOccurring bool
}
func (req *SuspendARPsRequest) Pack() []byte {
out := make([]byte, 2)
packUint8(req.ChannelNumber, out, 0)
var b uint8
if req.SuspendARP {
b = setBit1(b)
}
if req.SuspendGratuitousARP {
b = setBit0(b)
}
packUint8(b, out, 1)
return out
}
func (req *SuspendARPsRequest) Command() Command {
return CommandSuspendARPs
}
func (res *SuspendARPsResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "parameter not supported.",
}
}
func (res *SuspendARPsResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
b, _, _ := unpackUint8(msg, 0)
res.IsARPOccurring = isBit1Set(b)
res.IsGratuitousARPOccurring = isBit0Set(b)
return nil
}
func (res *SuspendARPsResponse) Format() string {
return ""
}
func (c *Client) SuspendARPs(ctx context.Context, channelNumber uint8, suspendARP bool, suspendGratuitousARP bool) (response *SuspendARPsResponse, err error) {
request := &SuspendARPsRequest{
ChannelNumber: channelNumber,
SuspendARP: suspendARP,
SuspendGratuitousARP: suspendGratuitousARP,
}
response = &SuspendARPsResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_warm_reset.go 0000664 0000000 0000000 00000001263 14741105271 0022432 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 20.3 Warm Reset Command
type WarmResetRequest struct {
// empty
}
type WarmResetResponse struct {
}
func (req *WarmResetRequest) Command() Command {
return CommandWarmReset
}
func (req *WarmResetRequest) Pack() []byte {
return []byte{}
}
func (res *WarmResetResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{}
}
func (res *WarmResetResponse) Unpack(msg []byte) error {
return nil
}
func (res *WarmResetResponse) Format() string {
return ""
}
func (c *Client) WarmReset(ctx context.Context) (err error) {
request := &WarmResetRequest{}
response := &WarmResetResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cmd_write_fru_data.go 0000664 0000000 0000000 00000003165 14741105271 0023264 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
// 34.3 Write FRU Data Command
type WriteFRUDataRequest struct {
FRUDeviceID uint8
WriteOffset uint16
WriteData []byte
}
type WriteFRUDataResponse struct {
CountWritten uint8
}
func (req *WriteFRUDataRequest) Command() Command {
return CommandWriteFRUData
}
func (req *WriteFRUDataRequest) Pack() []byte {
out := make([]byte, 3+len(req.WriteData))
packUint8(req.FRUDeviceID, out, 0)
packUint16L(req.WriteOffset, out, 1)
if len(req.WriteData) > 0 {
packBytes(req.WriteData, out, 3)
}
return out
}
func (res *WriteFRUDataResponse) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
res.CountWritten, _, _ = unpackUint8(msg, 0)
return nil
}
func (r *WriteFRUDataResponse) CompletionCodes() map[uint8]string {
return map[uint8]string{
0x80: "write-protected offset",
0x81: "FRU device busy",
}
}
func (res *WriteFRUDataResponse) Format() string {
return fmt.Sprintf(`Count written : %d`, res.CountWritten)
}
// The command writes the specified byte or word to the FRU Inventory Info area. This is a low level direct interface to a non-volatile storage area. This means that the interface does not interpret or check any semantics or formatting for the data being written.
func (c *Client) WriteFRUData(ctx context.Context, fruDeviceID uint8, writeOffset uint16, writeData []byte) (response *WriteFRUDataResponse, err error) {
request := &WriteFRUDataRequest{
FRUDeviceID: fruDeviceID,
WriteOffset: writeOffset,
WriteData: writeData,
}
response = &WriteFRUDataResponse{}
err = c.Exchange(ctx, request, response)
return
}
golang-github-bougou-go-ipmi-0.7.2/cspell.json 0000664 0000000 0000000 00000005463 14741105271 0021273 0 ustar 00root root 0000000 0000000 {
"version": "0.2",
"ignorePaths": [],
"dictionaryDefinitions": [],
"dictionaries": [],
"words": [
"ACPI",
"Addin",
"Algs",
"Alloc",
"ASIC",
"asynch",
"authcode",
"authtype",
"backpane",
"backplane",
"Bexp",
"BIOSFRB",
"BIOSPOST",
"BIOSSMI",
"BIST",
"blocksize",
"bootable",
"Bootdev",
"bootflag",
"bootparam",
"bougou",
"buflen",
"Busv",
"Callin",
"ccode",
"CDROM",
"CHANS",
"cmdline",
"CMDSPEC",
"cmos",
"Colling",
"datasheet",
"DCMI",
"Deassert",
"Deasserted",
"Deassertion",
"Deassertions",
"Debugf",
"devnum",
"DIMM",
"DMTF",
"Dont",
"DUID",
"dword",
"EEPROM",
"efiboot",
"EISA",
"elist",
"Firmwares",
"fluidounce",
"freeipmi",
"frus",
"Gbit",
"getaccess",
"getciphers",
"goipmi",
"heceta",
"hmackey",
"HMACSHA",
"Huan",
"ICMB",
"IERR",
"intf",
"IOWR",
"IPMB",
"IPMICTL",
"ipmidev",
"ipmitool",
"kbps",
"KBPS",
"Kuid",
"lanplus",
"libfreeipmi",
"linearization",
"lockkbd",
"lockoutreset",
"mcloc",
"mgmt",
"microcontroller",
"Milli",
"msbit",
"NDSLAAC",
"netfn",
"nopoweroff",
"nosel",
"nsec",
"nvmexpress",
"OEMIANA",
"OEMID",
"olekukonko",
"openipmi",
"opensession",
"overtemperature",
"PASR",
"PERR",
"PIROM",
"PowerGood",
"Poweroff",
"Preboot",
"Println",
"qword",
"Rakp",
"rerr",
"resetbuttons",
"Rexp",
"Rmcp",
"RMCP",
"RMCPACK",
"screenblank",
"SDRBMC",
"SDRFRU",
"SDROEM",
"SDRR",
"sdrs",
"SEEPROM",
"selftest",
"SELOEM",
"sensorclass",
"SERR",
"sess",
"setaccess",
"SETTIME",
"sievert",
"SLAAC",
"SMIC",
"SMSOS",
"SNMP",
"SSIF",
"sterad",
"struct",
"submatches",
"subsys",
"Supermicro",
"SWID",
"tablewriter",
"thermalpolicy",
"TMODE",
"Truong",
"twobyte",
"typecode",
"typelength",
"UEFI",
"Unitsbased",
"VLANID",
"wakeup"
],
"ignoreWords": [],
"import": []
}
golang-github-bougou-go-ipmi-0.7.2/errors.go 0000664 0000000 0000000 00000001551 14741105271 0020753 0 ustar 00root root 0000000 0000000 package ipmi
import (
"errors"
"fmt"
)
var (
ErrUnpackedDataTooShort = errors.New("unpacked data is too short")
ErrDCMIGroupExtensionIDMismatch = errors.New("DCMI group extension ID mismatch")
)
func ErrUnpackedDataTooShortWith(actual int, expected int) error {
return fmt.Errorf("%w (%d/%d)", ErrUnpackedDataTooShort, actual, expected)
}
func ErrNotEnoughDataWith(msg string, actual int, expected int) error {
return fmt.Errorf("not enough data for %s (%d/%d)", msg, actual, expected)
}
func ErrDCMIGroupExtensionIDMismatchWith(expected uint8, actual uint8) error {
return fmt.Errorf("%w: expected %#02x, got %#02x", ErrDCMIGroupExtensionIDMismatch, expected, actual)
}
func CheckDCMIGroupExenstionMatch(grpExt uint8) error {
if grpExt != GroupExtensionDCMI {
return ErrDCMIGroupExtensionIDMismatchWith(GroupExtensionDCMI, grpExt)
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/go.mod 0000664 0000000 0000000 00000001037 14741105271 0020215 0 ustar 00root root 0000000 0000000 module github.com/bougou/go-ipmi
replace github.com/bougou/go-ipmi v0.0.0 => ./
go 1.20
require (
github.com/google/uuid v1.1.2
github.com/kr/pretty v0.3.0
github.com/olekukonko/tablewriter v0.0.5
github.com/spf13/cobra v1.3.0
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d
)
require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/rogpeppe/go-internal v1.6.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
golang-github-bougou-go-ipmi-0.7.2/go.sum 0000664 0000000 0000000 00000226030 14741105271 0020244 0 ustar 00root root 0000000 0000000 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0=
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
golang-github-bougou-go-ipmi-0.7.2/helpers.go 0000664 0000000 0000000 00000036502 14741105271 0021105 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"encoding/base32"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"math"
"math/rand"
"strconv"
"time"
"github.com/kr/pretty"
"github.com/olekukonko/tablewriter"
)
const timeFormat = time.RFC3339
func bytesForPrint(data []byte) string {
out := ""
for k, v := range data {
if k%8 == 0 && k != 0 {
out += "\n"
}
out += fmt.Sprintf("%02x ", v)
}
out += "\n"
return out
}
func debugBytes(header string, data []byte, width int) {
fmt.Printf("%s (%d bytes)\n", header, len(data))
for k, v := range data {
if k%width == 0 && k != 0 {
fmt.Printf("\n")
}
fmt.Printf("%02x ", v)
}
fmt.Printf("\n")
}
// debugf pretty print any object
func debugf(format string, object ...interface{}) {
pretty.Printf(format, object...)
}
func debug(header string, object interface{}) {
if header == "" {
pretty.Printf("%# v\n", object)
} else {
pretty.Printf("%s: \n%# v\n", header, object)
}
}
func (c *Client) Debugf(format string, object ...interface{}) {
if !c.debug {
return
}
debugf(format, object...)
}
func (c *Client) Debug(header string, object interface{}) {
if !c.debug {
return
}
debug(header, object)
}
// DebugBytes print byte slices with a fixed width of bytes on each line.
func (c *Client) DebugBytes(header string, data []byte, width int) {
if !c.debug {
return
}
debugBytes(header, data, width)
}
func (c *Client) DebugfRed(format string, object ...interface{}) {
if !c.debug {
return
}
const colorRed = "\033[0;31m"
fmt.Printf(colorRed+format+"\033[0m", object...)
}
func (c *Client) DebugfGreen(format string, object ...interface{}) {
if !c.debug {
return
}
const colorGreen = "\033[0;32m"
fmt.Printf(colorGreen+format+"\033[0m", object...)
}
func (c *Client) DebugfYellow(format string, object ...interface{}) {
if !c.debug {
return
}
const colorYellow = "\033[0;33m"
fmt.Printf(colorYellow+format+"\033[0m", object...)
}
// 37 Timestamp Format
func parseTimestamp(timestamp uint32) time.Time {
return time.Unix(int64(timestamp), 0)
}
func formatBool(b bool, trueStr string, falseStr string) string {
if b {
return trueStr
}
return falseStr
}
// padBytes will padding the origin "s" string to fixed "width" length,
// with "pad" as the padding byte.
func padBytes(s string, width int, pad byte) []byte {
o := []byte(s)
if len(s) >= width {
return o[:width]
}
for i := 0; i < width-len(s); i++ {
o = append(o, pad)
}
return o
}
func isByteSliceEqual(b1 []byte, b2 []byte) bool {
// not equal if both are nil
if b1 == nil || b2 == nil {
return false
}
if len(b1) != len(b2) {
return false
}
for k := range b1 {
if b1[k] != b2[k] {
return false
}
}
return true
}
func array16(s []byte) [16]byte {
var out [16]byte
copy(out[:16], s[:])
return out
}
func randomUint32() uint32 {
r := rand.New(rand.NewSource(time.Now().Unix()))
return r.Uint32()
}
func randomBytes(n int) []byte {
r := rand.New(rand.NewSource(time.Now().Unix()))
b := make([]byte, n)
r.Read(b)
return b
}
// onesComplement returns the signed integer of the input number encoded with 1's complement.
// The lowest significant 'bitSize' bits of the input number i is considered.
func onesComplement(i uint32, bitSize uint8) int32 {
var leftBitSize uint8 = 32 - bitSize
var temp uint32 = i << uint32(leftBitSize) >> uint32(leftBitSize)
var mask uint32 = 1 << (bitSize - 1)
if temp&mask == 0 {
// means the bit at `bitSize-1` (from left starting at 0) is 0
// so the result should be a positive value
return int32(temp)
}
// means the bit at `bitSize-1` (from left starting at 0) is 1
// so the result should be a negative value
t := temp ^ 0xffff
t = t << uint32(leftBitSize) >> uint32(leftBitSize)
return -int32(t)
}
// twosComplement returns the signed integer of the input number encoded with 2's complement.
// The lowest significant 'bitSize' bits of the input number i is considered.
func twosComplement(i uint32, bitSize uint8) int32 {
var leftBitSize uint8 = 32 - bitSize
var temp uint32 = i << uint32(leftBitSize) >> uint32(leftBitSize)
var mask uint32 = 1 << (bitSize - 1)
if temp&mask == 0 {
// means the bit at `bitSize-1` (from left starting at 0) is 0
// so the result should be a positive value
return int32(temp)
}
// means the bit at `bitSize-1` (from left starting at 0) is 1
// so the result should be a negative value
t := temp ^ 0xffff + 1
t = t << uint32(leftBitSize) >> uint32(leftBitSize)
return -int32(t)
}
func onesComplementEncode(i int32, bitSize uint8) uint32 {
if i >= 0 {
return uint32(i)
}
var total int32 = int32(math.Pow(2, float64(bitSize))) - 1
return uint32(total + i)
}
func twosComplementEncode(i int32, bitSize uint8) uint32 {
if i >= 0 {
return uint32(i)
}
var total int32 = int32(math.Pow(2, float64(bitSize)))
return uint32(total + i)
}
// The TCP/IP standard network byte order is big-endian.
var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding)
func fromBase32(s []byte) (buf []byte, err error) {
for i, b := range s {
if b >= 'a' && b <= 'z' {
s[i] = b - 32
}
}
buflen := base32HexNoPadEncoding.DecodedLen(len(s))
buf = make([]byte, buflen)
n, err := base32HexNoPadEncoding.Decode(buf, s)
buf = buf[:n]
return
}
func toBase32(b []byte) string {
return base32HexNoPadEncoding.EncodeToString(b)
}
func fromBase64(s []byte) (buf []byte, err error) {
buflen := base64.StdEncoding.DecodedLen(len(s))
buf = make([]byte, buflen)
n, err := base64.StdEncoding.Decode(buf, s)
buf = buf[:n]
return
}
func toBase64(b []byte) string {
return base64.StdEncoding.EncodeToString(b)
}
func setBit7(b uint8) uint8 {
return b | 0x80
}
func setBit6(b uint8) uint8 {
return b | 0x40
}
func setBit5(b uint8) uint8 {
return b | 0x20
}
func setBit4(b uint8) uint8 {
return b | 0x10
}
func setBit3(b uint8) uint8 {
return b | 0x08
}
func setBit2(b uint8) uint8 {
return b | 0x04
}
func setBit1(b uint8) uint8 {
return b | 0x02
}
func setBit0(b uint8) uint8 {
return b | 0x01
}
func clearBit7(b uint8) uint8 {
return b & 0x7f
}
func clearBit6(b uint8) uint8 {
return b & 0xbf
}
func clearBit5(b uint8) uint8 {
return b & 0xdf
}
func clearBit4(b uint8) uint8 {
return b & 0xef
}
func clearBit3(b uint8) uint8 {
return b & 0xf7
}
func clearBit2(b uint8) uint8 {
return b & 0xfb
}
func clearBit1(b uint8) uint8 {
return b & 0xfd
}
func clearBit0(b uint8) uint8 {
return b & 0xfe
}
func setOrClearBit7(b uint8, cond bool) uint8 {
if cond {
return b | 0x80
}
return b & 0x7f
}
func setOrClearBit6(b uint8, cond bool) uint8 {
if cond {
return b | 0x40
}
return b & 0xbf
}
func setOrClearBit5(b uint8, cond bool) uint8 {
if cond {
return b | 0x20
}
return b & 0xdf
}
func setOrClearBit4(b uint8, cond bool) uint8 {
if cond {
return b | 0x10
}
return b & 0xef
}
func setOrClearBit3(b uint8, cond bool) uint8 {
if cond {
return b | 0x08
}
return b & 0xf7
}
func setOrClearBit2(b uint8, cond bool) uint8 {
if cond {
return b | 0x04
}
return b & 0xfb
}
func setOrClearBit1(b uint8, cond bool) uint8 {
if cond {
return b | 0x02
}
return b & 0xfd
}
func setOrClearBit0(b uint8, cond bool) uint8 {
if cond {
return b | 0x01
}
return b & 0xfe
}
func isBit7Set(b uint8) bool {
return b&0x80 == 0x80
}
func isBit6Set(b uint8) bool {
return b&0x40 == 0x40
}
func isBit5Set(b uint8) bool {
return b&0x20 == 0x20
}
func isBit4Set(b uint8) bool {
return b&0x10 == 0x10
}
func isBit3Set(b uint8) bool {
return b&0x08 == 0x08
}
func isBit2Set(b uint8) bool {
return b&0x04 == 0x04
}
func isBit1Set(b uint8) bool {
return b&0x02 == 0x02
}
func isBit0Set(b uint8) bool {
return b&0x01 == 0x01
}
func unpackUint8(msg []byte, off int) (uint8, int, error) {
if off+1 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint8")
}
return msg[off], off + 1, nil
}
// packUint8 fills an uint8 value (i) into byte slice (msg) at the index of (offset)
func packUint8(i uint8, msg []byte, off int) (int, error) {
if off+1 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint8")
}
msg[off] = i
return off + 1, nil
}
func packBytes(v []byte, msg []byte, off int) (int, error) {
if off+len(v) > len(msg) {
return len(msg), fmt.Errorf("overflow packing byte slice")
}
for k, b := range v {
msg[off+k] = b
}
return off + len(v), nil
}
func unpackBytes(msg []byte, off int, length int) ([]byte, int, error) {
out := []byte{}
if off+length > len(msg) {
return out, off, fmt.Errorf("overflow unpacking %d bytes", length)
}
out = append(out, msg[off:off+length]...)
return out, off + length, nil
}
// unpackBytesMost unpacks most length of bytes from msg starting from off index.
// It stops when reaching the msg end or reaching the most length.
// This functions never failed, it always return nil error.
// The caller should check the length of the returned out byte
func unpackBytesMost(msg []byte, off int, length int) ([]byte, int, error) {
out := make([]byte, length)
var i int = 0
for ; i < length; i++ {
if off+i >= len(msg) {
break
}
out[i] = msg[off+i]
}
return out[:i], off + len(out), nil
}
func unpackUint16(msg []byte, off int) (uint16, int, error) {
if off+2 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint16")
}
return binary.BigEndian.Uint16(msg[off:]), off + 2, nil
}
func unpackUint16L(msg []byte, off int) (uint16, int, error) {
if off+2 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint16")
}
return binary.LittleEndian.Uint16(msg[off:]), off + 2, nil
}
func packUint16(i uint16, msg []byte, off int) (int, error) {
if off+2 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint16")
}
binary.BigEndian.PutUint16(msg[off:], i)
return off + 2, nil
}
func packUint16L(i uint16, msg []byte, off int) (int, error) {
if off+2 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint16")
}
binary.LittleEndian.PutUint16(msg[off:], i)
return off + 2, nil
}
func unpackUint24(msg []byte, off int) (uint32, int, error) {
if off+3 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint32 as uint24")
}
i := uint32(msg[off])<<16 | uint32(msg[off+1])<<8 | uint32(msg[off+2])
off += 3
return i, off, nil
}
func unpackUint24L(msg []byte, off int) (uint32, int, error) {
if off+3 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint32 as uint24")
}
i := uint32(msg[off]) | uint32(msg[off+1])<<8 | uint32(msg[off+2])<<16
off += 3
return i, off, nil
}
func packUint24(i uint32, msg []byte, off int) (int, error) {
if off+3 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint32 as uint24")
}
msg[off] = byte(i >> 16)
msg[off+1] = byte(i >> 8)
msg[off+2] = byte(i)
off += 3
return off, nil
}
func packUint24L(i uint32, msg []byte, off int) (int, error) {
if off+3 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint32 as uint24")
}
msg[off] = byte(i)
msg[off+1] = byte(i >> 8)
msg[off+2] = byte(i >> 16)
off += 3
return off, nil
}
func unpackUint32(msg []byte, off int) (uint32, int, error) {
if off+4 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint32")
}
return binary.BigEndian.Uint32(msg[off:]), off + 4, nil
}
func unpackUint32L(msg []byte, off int) (uint32, int, error) {
if off+4 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint32")
}
return binary.LittleEndian.Uint32(msg[off:]), off + 4, nil
}
func packUint32(i uint32, msg []byte, off int) (int, error) {
if off+4 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint32")
}
binary.BigEndian.PutUint32(msg[off:], i)
return off + 4, nil
}
func packUint32L(i uint32, msg []byte, off int) (int, error) {
if off+4 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint32")
}
binary.LittleEndian.PutUint32(msg[off:], i)
return off + 4, nil
}
func unpackUint48(msg []byte, off int) (uint64, int, error) {
if off+6 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint64 as uint48")
}
i := uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
uint64(msg[off+4])<<8 | uint64(msg[off+5])
off += 6
return i, off, nil
}
func unpackUint48L(msg []byte, off int) (uint64, int, error) {
if off+6 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint64 as uint48")
}
i := uint64(msg[off]) | uint64(msg[off+1])<<8 | uint64(msg[off+2])<<16 | uint64(msg[off+3])<<24 |
uint64(msg[off+4])<<32 | uint64(msg[off+5])<<40
off += 6
return i, off, nil
}
func packUint48(i uint64, msg []byte, off int) (int, error) {
if off+6 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint64 as uint48")
}
msg[off] = byte(i >> 40)
msg[off+1] = byte(i >> 32)
msg[off+2] = byte(i >> 24)
msg[off+3] = byte(i >> 16)
msg[off+4] = byte(i >> 8)
msg[off+5] = byte(i)
off += 6
return off, nil
}
func packUint48L(i uint64, msg []byte, off int) (int, error) {
if off+6 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint64 as uint48")
}
msg[off] = byte(i)
msg[off+1] = byte(i >> 8)
msg[off+2] = byte(i >> 16)
msg[off+3] = byte(i >> 24)
msg[off+4] = byte(i >> 32)
msg[off+5] = byte(i >> 40)
off += 6
return off, nil
}
func unpackUint64(msg []byte, off int) (uint64, int, error) {
if off+8 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint64")
}
return binary.BigEndian.Uint64(msg[off:]), off + 8, nil
}
func unpackUint64L(msg []byte, off int) (uint64, int, error) {
if off+8 > len(msg) {
return 0, len(msg), fmt.Errorf("overflow unpacking uint64")
}
return binary.LittleEndian.Uint64(msg[off:]), off + 8, nil
}
func packUint64(i uint64, msg []byte, off int) (int, error) {
if off+8 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint64")
}
binary.BigEndian.PutUint64(msg[off:], i)
off += 8
return off, nil
}
func packUint64L(i uint64, msg []byte, off int) (int, error) {
if off+8 > len(msg) {
return len(msg), fmt.Errorf("overflow packing uint64")
}
binary.LittleEndian.PutUint64(msg[off:], i)
off += 8
return off, nil
}
// 8421 BCD
// bcdUint8 decodes BCD encoded integer to normal unsigned integer.
func bcdUint8(i uint8) uint8 {
msb4 := i >> 4
lsb4 := i & 0x0f
return msb4*10 + lsb4
}
func parseStringToInt64(s string) (int64, error) {
if len(s) > 2 {
if s[0] == '0' {
return strconv.ParseInt(s, 0, 64)
}
}
return strconv.ParseInt(s, 10, 64)
}
func formatTable(headers []string, rows [][]string) string {
var buf = new(bytes.Buffer)
table := tablewriter.NewWriter(buf)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_RIGHT)
table.SetHeader(headers)
table.SetFooter(headers)
for _, row := range rows {
table.Append(row)
}
table.Render()
return buf.String()
}
// buildCanIgnoreFn returns a `canIgnore` function that can be used to check if a err
// is a ResponseError with CompletionCode in specified codes.
// If so, the `canIgnore` function returns nil, otherwise it returns the original err.
func buildCanIgnoreFn(codes ...uint8) func(err error) error {
return func(err error) error {
if err == nil {
return nil
}
var respErr *ResponseError
if errors.As(err, &respErr) {
cc := respErr.CompletionCode()
for _, code := range codes {
if uint8(cc) == code {
return nil
}
}
}
return err
}
}
// Generic function to convert a slice of any type to a slice of interface{}
func convertToInterfaceSlice[T any](input []T) []interface{} {
result := make([]interface{}, len(input))
for i, v := range input {
result[i] = v
}
return result
}
golang-github-bougou-go-ipmi-0.7.2/helpers_hmac.go 0000664 0000000 0000000 00000007361 14741105271 0022076 0 ustar 00root root 0000000 0000000 package ipmi
import (
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/md5"
"crypto/rc4"
"crypto/sha1"
"crypto/sha256"
"fmt"
)
// generate_hmac generates message authentication code.
// Currently supported algorithms are: "md5", "sha1", "sha256"
//
// hmac, hash-based message authentication code
// mac, message authentication code
// md, message digest
func generate_hmac(alg string, data []byte, key []byte) ([]byte, error) {
switch alg {
case "md5":
h := hmac.New(md5.New, key)
_, err := h.Write(data)
if err != nil {
return nil, fmt.Errorf("hmac md5 failed, err: %w", err)
}
return h.Sum(nil), nil
case "sha1":
h := hmac.New(sha1.New, key)
_, err := h.Write(data)
if err != nil {
return nil, fmt.Errorf("hmac sha1 failed, err: %w", err)
}
return h.Sum(nil), nil
case "sha256":
h := hmac.New(sha256.New, key)
_, err := h.Write(data)
if err != nil {
return nil, fmt.Errorf("hmac sha256 failed, err: %w", err)
}
return h.Sum(nil), nil
default:
return nil, fmt.Errorf("not support for hmac algorithm %s", alg)
}
}
func generate_auth_hmac(authAlg interface{}, data []byte, key []byte) ([]byte, error) {
algorithm := ""
switch authAlg.(type) {
case AuthAlg:
switch authAlg {
case AuthAlgRAKP_HMAC_SHA1:
algorithm = "sha1"
case AuthAlgRAKP_HMAC_MD5:
algorithm = "md5"
case AuthAlgRAKP_HMAC_SHA256:
algorithm = "sha256"
default:
return nil, fmt.Errorf("not support for authentication algorithm %x", authAlg)
}
case IntegrityAlg:
switch authAlg {
case IntegrityAlg_HMAC_SHA1_96:
algorithm = "sha1"
case IntegrityAlg_HMAC_MD5_128:
algorithm = "md5"
case IntegrityAlg_HMAC_SHA256_128:
algorithm = "sha256"
default:
return nil, fmt.Errorf("not support for integrity algorithm %x", authAlg)
}
}
if len(algorithm) == 0 {
return []byte{}, nil
} else {
return generate_hmac(algorithm, data, key)
}
}
// The plainText must be already padded.
// The cipherKey length is either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
func encryptAES(plainText []byte, cipherKey []byte, iv []byte) ([]byte, error) {
if len(plainText)%aes.BlockSize != 0 {
return nil, fmt.Errorf("input plainText must be multiple of aes block size (16)")
}
l := len(cipherKey)
if l != 16 && l != 24 && l != 32 {
return nil, fmt.Errorf("cipherKey length must be either 16, 24, 32")
}
cipherBlock, err := aes.NewCipher(cipherKey)
if err != nil {
return nil, fmt.Errorf("NewCipher failed, err: %w", err)
}
cipherText := make([]byte, len(plainText))
mode := cipher.NewCBCEncrypter(cipherBlock, iv)
mode.CryptBlocks(cipherText, plainText)
return cipherText, nil
}
func decryptAES(cipherText []byte, cipherKey []byte, iv []byte) ([]byte, error) {
l := len(cipherKey)
if l != 16 && l != 24 && l != 32 {
return nil, fmt.Errorf("cipherKey length must be either 16, 24, 32")
}
cipherBlock, err := aes.NewCipher(cipherKey)
if err != nil {
return nil, fmt.Errorf("NewCipher failed, err: %w", err)
}
plainText := make([]byte, len(cipherText))
mode := cipher.NewCBCDecrypter(cipherBlock, iv)
mode.CryptBlocks(plainText, cipherText)
return plainText, nil
}
func encryptRC4(plainText []byte, cipherKey []byte, iv []byte) ([]byte, error) {
rc4Cipher, err := rc4.NewCipher(cipherKey)
if err != nil {
return nil, fmt.Errorf("NewCipher failed, err: %w", err)
}
cipherText := make([]byte, len(plainText))
rc4Cipher.XORKeyStream(cipherText, plainText)
return cipherText, nil
}
func decryptRC4(cipherText []byte, cipherKey []byte, iv []byte) ([]byte, error) {
rc4Cipher, err := rc4.NewCipher(cipherKey)
if err != nil {
return nil, fmt.Errorf("NewCipher failed, err: %w", err)
}
plainText := make([]byte, len(cipherText))
rc4Cipher.XORKeyStream(plainText, cipherText)
return plainText, nil
}
golang-github-bougou-go-ipmi-0.7.2/helpers_hmac_test.go 0000664 0000000 0000000 00000005770 14741105271 0023137 0 ustar 00root root 0000000 0000000 package ipmi
import (
"fmt"
"testing"
)
func Test_encryptAES(t *testing.T) {
cases := []struct {
name string
ipmiRequestBody []byte
iv []byte
key []byte
expected []byte
}{
{
name: "test1",
ipmiRequestBody: []byte{
0x20, 0x18, 0xc8, 0x81, 0x04, 0x3b, 0x04, 0x3c, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x07,
},
iv: []byte{
0x00, 0xdf, 0x5e, 0x2a, 0x2b, 0x37, 0x2e, 0x80, 0x7a, 0xe5, 0x5b, 0x0c, 0x37, 0x3c, 0x37, 0x69,
},
key: []byte{
0x12, 0x0e, 0x6b, 0x20, 0xe1, 0xe5, 0x2d, 0x13, 0xa0, 0x4a, 0x2b, 0xb8, 0x3d, 0x0d, 0x38, 0xa1,
},
expected: []byte{
0x47, 0x9c, 0x2f, 0x65, 0xfb, 0x59, 0x75, 0x19, 0x71, 0xa2, 0x96, 0xa3, 0x77, 0x15, 0x55, 0x69,
},
},
{
name: "test2",
ipmiRequestBody: []byte{
0x20, 0x18, 0xc8, 0x81, 0x04, 0x3b, 0x04, 0x3c, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x07,
},
iv: []byte{
0x00, 0xdf, 0x5e, 0x2a, 0x2b, 0x37, 0x2e, 0x80, 0x7a, 0xe5, 0x5b, 0x0c, 0x37, 0x3c, 0x37, 0x69,
},
key: []byte{
0x12, 0x0e, 0x6b, 0x20, 0xe1, 0xe5, 0x2d, 0x13, 0xa0, 0x4a, 0x2b, 0xb8, 0x3d, 0x0d, 0x38, 0xa1,
},
expected: []byte{
0x47, 0x9c, 0x2f, 0x65, 0xfb, 0x59, 0x75, 0x19, 0x71, 0xa2, 0x96, 0xa3, 0x77, 0x15, 0x55, 0x69,
},
},
}
for _, v := range cases {
got, err := encryptAES(v.ipmiRequestBody, v.key, v.iv)
if err != nil {
t.Errorf("encryptAES failed, err: %s", err)
}
if !isByteSliceEqual(got, v.expected) {
t.Errorf("got does not match expected, got: %v, want: %v", got, v.expected)
}
}
}
func Test_AES_Decrypt(t *testing.T) {
ivStr := "1234567890123456"
cipherKey := "12345678901234567890123456789012"
plainText := "abcdefghijklmnopqrstuvwxyzABCDEF"
cipherText, err := encryptAES([]byte(plainText), []byte(cipherKey), []byte(ivStr))
if err != nil {
t.Error(err)
}
p, err := decryptAES([]byte(cipherText), []byte(cipherKey), []byte(ivStr))
if err != nil {
t.Error(err)
}
if len(plainText) != len(p) {
t.Error("Not equal")
}
for k, v := range []byte(plainText) {
if v != p[k] {
t.Errorf("not equal at %d", k)
}
}
}
func Test_RC4_Encrypt(t *testing.T) {
ivStr := "1234567890123456"
cipherKey := "12345678901234567890123456789012"
plainText := "abcdefghijklmnopqrstuvwxyzABCDEF"
cipherText, err := encryptRC4([]byte(plainText), []byte(cipherKey), []byte(ivStr))
if err != nil {
t.Error(err)
}
fmt.Println(string(cipherText))
fmt.Println(cipherText)
}
func Test_RC4_Decrypt(t *testing.T) {
ivStr := "1234567890123456"
cipherKey := "12345678901234567890123456789012"
plainText := "abcdefghijklmnopqrstuvwxyzABCDEF"
cipherText, err := encryptRC4([]byte(plainText), []byte(cipherKey), []byte(ivStr))
if err != nil {
t.Error(err)
}
p, err := decryptRC4([]byte(cipherText), []byte(cipherKey), []byte(ivStr))
if err != nil {
t.Error(err)
}
fmt.Println(string(p))
if len(plainText) != len(p) {
t.Error("Not equal")
}
for k, v := range []byte(plainText) {
if v != p[k] {
t.Errorf("not equal at %d", k)
}
}
}
golang-github-bougou-go-ipmi-0.7.2/helpers_test.go 0000664 0000000 0000000 00000006527 14741105271 0022150 0 ustar 00root root 0000000 0000000 package ipmi
import (
"testing"
)
func Test_onesComplement(t *testing.T) {
// https://en.wikipedia.org/wiki/Ones%27_complement
tests := []struct {
name string
input uint32
bitSize uint8
expected int32
}{
{"test1", 127, 8, 127},
{"test2", 126, 8, 126},
{"test3", 2, 8, 2},
{"test4", 1, 8, 1},
{"test5", 0, 8, 0},
{"test6", 255, 8, -0},
{"test7", 254, 8, -1},
{"test8", 253, 8, -2},
{"test9", 129, 8, -126},
{"test10", 128, 8, -127},
}
for _, test := range tests {
got := onesComplement(test.input, test.bitSize)
if got != test.expected {
t.Errorf("test %s not matched, got: %d, expected: %d", test.name, got, test.expected)
}
}
}
func Test_twosComplement(t *testing.T) {
// https://en.wikipedia.org/wiki/Two%27s_complement
tests := []struct {
name string
input uint32
bitSize uint8
expected int32
}{
{"test1", 0, 8, 0},
{"test2", 1, 8, 1},
{"test3", 2, 8, 2},
{"test4", 126, 8, 126},
{"test5", 127, 8, 127},
{"test6", 128, 8, -128},
{"test7", 129, 8, -127},
{"test8", 130, 8, -126},
{"test9", 254, 8, -2},
{"test10", 255, 8, -1},
}
for _, test := range tests {
got := twosComplement(test.input, test.bitSize)
if got != test.expected {
t.Errorf("test %s not matched, got: %d, expected: %d", test.name, got, test.expected)
}
}
}
func Test_onesComplementEncode(t *testing.T) {
// https://en.wikipedia.org/wiki/Ones%27_complement
tests := []struct {
name string
expected uint32
bitSize uint8
input int32
}{
{"test1", 127, 8, 127},
{"test2", 126, 8, 126},
{"test3", 2, 8, 2},
{"test4", 1, 8, 1},
{"test5", 0, 8, 0},
// {"test6", 255, 8, -0},
{"test7", 254, 8, -1},
{"test8", 253, 8, -2},
{"test9", 129, 8, -126},
{"test10", 128, 8, -127},
}
for _, test := range tests {
got := onesComplementEncode(test.input, test.bitSize)
if got != test.expected {
t.Errorf("test %s not matched, got: %d, expected: %d", test.name, got, test.expected)
}
}
}
func Test_twosComplementEncode(t *testing.T) {
// https://en.wikipedia.org/wiki/Two%27s_complement
tests := []struct {
name string
expected uint32
bitSize uint8
input int32
}{
{"test1", 0, 8, 0},
{"test2", 1, 8, 1},
{"test3", 2, 8, 2},
{"test4", 126, 8, 126},
{"test5", 127, 8, 127},
{"test6", 128, 8, -128},
{"test7", 129, 8, -127},
{"test8", 130, 8, -126},
{"test9", 254, 8, -2},
{"test10", 255, 8, -1},
}
for _, test := range tests {
got := twosComplementEncode(test.input, test.bitSize)
if got != test.expected {
t.Errorf("test %s not matched, got: %d, expected: %d", test.name, got, test.expected)
}
}
}
func Test_unpackBytes(t *testing.T) {
tests := []struct {
name string
expected []byte
input []uint8
offset int
length int
}{
{"test1", []byte{0x03, 0x04}, []uint8{0x01, 0x02, 0x03, 0x04}, 2, 2},
{"test2", []byte{0x04, 0x05, 0x06, 0x07}, []uint8{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 3, 4},
{"test3", []byte{}, []uint8{}, 0, 0},
{"test4", []byte{0x01}, []uint8{0x01}, 0, 1},
}
for _, tt := range tests {
got, _, err := unpackBytes(tt.input, tt.offset, tt.length)
if err != nil {
t.Errorf("test (%s) unpackBytes failed, err: %s", tt.name, err)
return
}
if !isByteSliceEqual(got, tt.expected) {
t.Errorf("test %s not matched, got: %v, expected: %v", tt.name, got, tt.expected)
return
}
}
}
golang-github-bougou-go-ipmi-0.7.2/interface_lan.go 0000664 0000000 0000000 00000023226 14741105271 0022234 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"context"
"errors"
"fmt"
"time"
)
const (
IPMIVersion15 = 0x15
IPMIVersion20 = 0x20
)
// session holds data exchanged during Session Activation stage when using lan/lanplus interface.
// see: 13.14 IPMI v1.5 LAN Session Activation, 13.15 IPMI v2.0/RMCP+ Session Activation
type session struct {
// filled after GetChannelAuthenticationCapabilities
authType AuthType
ipmiSeq uint8
v20 v20
v15 v15
}
type v15 struct {
// indicate whether or not the session is in Pre-Session stage,
// that is between "GetSessionChallenge" and "ActivateSession"
preSession bool
// indicate whether or not the IPMI 1.5 session is activated.
active bool
sessionID uint32
// Sequence number that BMC wants remote console to use for subsequent messages in the session.
// Remote console use "inSeq" and increment it when sending Request to BMC.
// "inSeq" is first updated by returned ActivateSession response.
inSeq uint32
// "outSeq" is set by Remote Console to indicate the sequence number should picked by BMC.
// 6.12.12 IPMI v1.5 Outbound Session Sequence Number Tracking and Handling.
outSeq uint32
challenge [16]byte
}
type v20 struct {
// specific to IPMI v2 / RMCP+ sessions
state SessionState
sequence uint32 // session sequence number
// the cipher suite used during OpenSessionRequest
cipherSuiteID CipherSuiteID
// filled by RmcpOpenSessionRequest
requestedAuthAlg AuthAlg
requestedIntegrityAlg IntegrityAlg
requestedEncryptAlg CryptAlg
// filled by RmcpOpenSessionResponse
// RMCP Open Session is used for exchanging session ids
authAlg AuthAlg
integrityAlg IntegrityAlg
cryptAlg CryptAlg
role uint8 // whole byte of privilege level in RAKP1, will be used for computing authcode of rakp2, rakp3
consoleSessionID uint32
bmcSessionID uint32
// values required for RAKP messages
// filed in rakp1
consoleRand [16]byte // Random number generated by the console
// filled after rakp2
bmcRand [16]byte // Random number generated by the BMC
bmcGUID [16]byte // bmc GUID
sik []byte // SIK, session integrity key
k1 []byte // K1 key
k2 []byte // K2 key
rakp2ReturnCode uint8 // will be used in rakp3 message
// see 13.33
// Kuid vs Kg
// - ipmi user password (the pre-shared key), known as Kuid, which are set using the Set User Password command.
// - BMC key, known as Kg, Kg is set using the Set Channel Security Keys command.
bmcKey []byte
accumulatedPayloadSize uint32
// for xRC4 encryption
rc4EncryptIV [16]byte
rc4DecryptIV [16]byte
}
// buildRawPayload returns the PayloadType and the raw payload bytes for Command Request.
// Most command requests are of IPMI PayloadType, but some requests like RAKP messages are not.
func (c *Client) buildRawPayload(ctx context.Context, reqCmd Request) (PayloadType, []byte, error) {
var payloadType PayloadType
if _, ok := reqCmd.(*OpenSessionRequest); ok {
payloadType = PayloadTypeRmcpOpenSessionRequest
} else if _, ok := reqCmd.(*RAKPMessage1); ok {
payloadType = PayloadTypeRAKPMessage1
} else if _, ok := reqCmd.(*RAKPMessage3); ok {
payloadType = PayloadTypeRAKPMessage3
} else {
payloadType = PayloadTypeIPMI
}
var rawPayload []byte
switch payloadType {
case
PayloadTypeRmcpOpenSessionRequest,
PayloadTypeRAKPMessage1,
PayloadTypeRAKPMessage3:
// Session Setup Payload Types
rawPayload = reqCmd.Pack()
case PayloadTypeIPMI:
// Standard Payload Types
ipmiReq, err := c.BuildIPMIRequest(ctx, reqCmd)
if err != nil {
return 0, nil, fmt.Errorf("BuildIPMIRequest failed, err: %w", err)
}
c.Debug(">>>> IPMI Request", ipmiReq)
rawPayload = ipmiReq.Pack()
}
return payloadType, rawPayload, nil
}
func (c *Client) exchangeLAN(ctx context.Context, request Request, response Response) error {
c.Debug(">> Command Request", request)
rmcp, err := c.BuildRmcpRequest(ctx, request)
if err != nil {
return fmt.Errorf("build RMCP+ request msg failed, err: %w", err)
}
c.Debug(">>>>>> RMCP Request", rmcp)
sent := rmcp.Pack()
c.DebugBytes("sent", sent, 16)
recv, err := c.udpClient.Exchange(ctx, bytes.NewReader(sent))
if err != nil {
return fmt.Errorf("client udp exchange msg failed, err: %w", err)
}
c.DebugBytes("recv", recv, 16)
if err := c.ParseRmcpResponse(ctx, recv, response); err != nil {
// Warn, must directly return err. (DO NOT wrap err to another error)
// The error returned by ParseRmcpResponse might be of *ResponseError type.
return err
}
c.Debug("<< Command Response", response)
return nil
}
// 13.14
// IPMI v1.5 LAN Session Activation
// 1. RmcpPresencePing - RmcpPresencePong
// 2. Get Channel Authentication Capabilities
// 3. Get Session Challenge
// 4. Activate Session
func (c *Client) Connect15(ctx context.Context) error {
var (
err error
channelNumber uint8 = ChannelNumberSelf
)
if c.maxPrivilegeLevel == PrivilegeLevelUnspecified {
c.maxPrivilegeLevel = PrivilegeLevelAdministrator
}
_, err = c.GetChannelAuthenticationCapabilities(ctx, channelNumber, c.maxPrivilegeLevel)
if err != nil {
return fmt.Errorf("GetChannelAuthenticationCapabilities failed, err: %w", err)
}
_, err = c.GetSessionChallenge(ctx)
if err != nil {
return fmt.Errorf("GetSessionChallenge failed, err: %w", err)
}
c.session.v15.preSession = true
_, err = c.ActivateSession(ctx)
if err != nil {
return fmt.Errorf("ActivateSession failed, err: %w", err)
}
_, err = c.SetSessionPrivilegeLevel(ctx, c.maxPrivilegeLevel)
if err != nil {
return fmt.Errorf("SetSessionPrivilegeLevel to (%s) failed, err: %s", c.maxPrivilegeLevel, err)
}
go func() {
c.keepSessionAlive(ctx, DefaultKeepAliveIntervalSec)
}()
return nil
}
// see 13.15 IPMI v2.0/RMCP+ Session Activation
func (c *Client) Connect20(ctx context.Context) error {
var (
err error
channelNumber uint8 = ChannelNumberSelf
)
if c.maxPrivilegeLevel == PrivilegeLevelUnspecified {
c.maxPrivilegeLevel = PrivilegeLevelAdministrator
}
_, err = c.GetChannelAuthenticationCapabilities(ctx, channelNumber, c.maxPrivilegeLevel)
if err != nil {
return fmt.Errorf("cmd: Get Channel Authentication Capabilities failed, err: %w", err)
}
tryCiphers := c.findBestCipherSuites(ctx)
if c.session.v20.cipherSuiteID != CipherSuiteIDReserved {
// client explicitly specified a cipher suite to use
tryCiphers = []CipherSuiteID{c.session.v20.cipherSuiteID}
}
c.DebugfGreen("\n\ntry ciphers (%v)\n", tryCiphers)
var success bool
errs := []error{}
// try different cipher suites for opensession/rakp1/rakp3
for _, cipherSuiteID := range tryCiphers {
c.DebugfGreen("\n\ntry cipher suite id (%v)\n\n\n", cipherSuiteID)
c.session.v20.cipherSuiteID = cipherSuiteID
_, err = c.OpenSession(ctx)
if err != nil {
errs = append(errs, fmt.Errorf("cmd: RMCP+ Open Session failed with cipher suite id (%v), err: %s", cipherSuiteID, err))
continue
}
_, err = c.RAKPMessage1(ctx)
if err != nil {
errs = append(errs, fmt.Errorf("cmd: rakp1 failed with cipher suite id (%v), err: %s", cipherSuiteID, err))
continue
}
_, err = c.RAKPMessage3(ctx)
if err != nil {
errs = append(errs, fmt.Errorf("cmd: rakp3 failed with cipher suite id (%v), err: %s", cipherSuiteID, err))
continue
}
c.DebugfGreen("\n\nconnect20 success with cipher suite id (%v)\n\n\n", cipherSuiteID)
success = true
break
}
if !success {
return fmt.Errorf("connect20 failed after try all cipher suite ids (%v), errs: \n%v", tryCiphers, errors.Join(errs...))
}
_, err = c.SetSessionPrivilegeLevel(ctx, c.maxPrivilegeLevel)
if err != nil {
return fmt.Errorf("SetSessionPrivilegeLevel to (%s) failed, err: %s", c.maxPrivilegeLevel, err)
}
go func() {
c.keepSessionAlive(ctx, DefaultKeepAliveIntervalSec)
}()
return nil
}
// ConnectAuto detects the IPMI version supported by BMC by using
// GetChannelAuthenticationCapabilities command, then decide to use v1.5 or v2.0
// for subsequent requests.
func (c *Client) ConnectAuto(ctx context.Context) error {
var (
err error
channelNumber uint8 = ChannelNumberSelf
privilegeLevel PrivilegeLevel = PrivilegeLevelAdministrator
)
// force use IPMI v1.5 first
c.v20 = false
cap, err := c.GetChannelAuthenticationCapabilities(ctx, channelNumber, privilegeLevel)
if err != nil {
return fmt.Errorf("cmd: Get Channel Authentication Capabilities failed, err: %w", err)
}
if cap.SupportIPMIv20 {
c.v20 = true
return c.Connect20(ctx)
}
if cap.SupportIPMIv15 {
return c.Connect15(ctx)
}
return fmt.Errorf("client does not support IPMI v1.5 and IPMI v.20")
}
// closeLAN closes session used in LAN communication.
func (c *Client) closeLAN(ctx context.Context) error {
// close the channel to notify the keepAliveSession goroutine to stop
close(c.closedCh)
var sessionID uint32
if c.v20 {
sessionID = c.session.v20.bmcSessionID
} else {
sessionID = c.session.v15.sessionID
}
request := &CloseSessionRequest{
SessionID: sessionID,
}
if _, err := c.CloseSession(ctx, request); err != nil {
return fmt.Errorf("CloseSession failed, err: %w", err)
}
if err := c.udpClient.Close(); err != nil {
return fmt.Errorf("close udp connection failed, err: %w", err)
}
return nil
}
// 6.12.15 Session Inactivity Timeouts
func (c *Client) keepSessionAlive(ctx context.Context, intervalSec int) {
var period = time.Duration(intervalSec) * time.Second
ticker := time.NewTicker(period)
defer ticker.Stop()
c.Debugf("keepSessionAlive started")
for {
select {
case <-ticker.C:
if _, err := c.GetCurrentSessionInfo(ctx); err != nil {
c.DebugfRed("keepSessionAlive failed, GetCurrentSessionInfo failed, err: %w", err)
}
case <-c.closedCh:
c.Debugf("got close signal, keepSessionAlive stopped")
return
}
}
}
golang-github-bougou-go-ipmi-0.7.2/interface_system.go 0000664 0000000 0000000 00000007267 14741105271 0023015 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"math/rand"
"os"
"unsafe"
"github.com/bougou/go-ipmi/open"
)
type openipmi struct {
myAddr uint8
msgID int64
targetAddr uint8
targetChannel uint8
targetIPMBAddr uint8
transitAddr uint8
transitLUN uint8
file *os.File // /dev/ipmi0
}
// ConnectOpen try to initialize the client by open the device of linux ipmi driver.
func (c *Client) ConnectOpen(ctx context.Context, devnum int32) error {
c.Debugf("Using ipmi device %d\n", devnum)
// try the following devices
var (
ipmiDev1 string = fmt.Sprintf("/dev/ipmi%d", devnum)
ipmiDev2 string = fmt.Sprintf("/dev/ipmi/%d", devnum)
ipmiDev3 string = fmt.Sprintf("/dev/ipmidev/%d", devnum)
)
var file *os.File
var tryOpenFile = func(ipmiDev string) {
if file != nil {
return
}
if f, err := os.OpenFile(ipmiDev, os.O_RDWR, 0); err != nil {
c.Debugf("can not open ipmi dev (%s), err: %s\n", ipmiDev, err)
} else {
file = f
c.Debugf("opened ipmi dev file: %v\n", ipmiDev)
}
}
tryOpenFile(ipmiDev1)
tryOpenFile(ipmiDev2)
tryOpenFile(ipmiDev3)
if file == nil {
return fmt.Errorf("ipmi dev file not opened")
}
c.Debugf("opened ipmi dev file: %v, descriptor is: %d\n", file, file.Fd())
// set opened ipmi dev file
c.openipmi.file = file
var receiveEvents uint32 = 1
if err := open.IOCTL(c.openipmi.file.Fd(), open.IPMICTL_SET_GETS_EVENTS_CMD, uintptr(unsafe.Pointer(&receiveEvents))); err != nil {
return fmt.Errorf("ioctl failed, cloud not enable event receiver, err: %w", err)
}
return nil
}
// closeOpen closes the ipmi dev file.
func (c *Client) closeOpen(ctx context.Context) error {
if err := c.openipmi.file.Close(); err != nil {
return fmt.Errorf("close open file failed, err: %w", err)
}
return nil
}
func (c *Client) exchangeOpen(ctx context.Context, request Request, response Response) error {
if c.openipmi.targetAddr != 0 && c.openipmi.targetAddr != c.openipmi.myAddr {
} else {
// otherwise use system interface
c.Debugf("\nSending request [%s] (%#02x) to System Interface\n", request.Command().Name, request.Command().ID)
}
recv, err := c.openSendRequest(ctx, request)
if err != nil {
return fmt.Errorf("openSendRequest failed, err: %w", err)
}
c.DebugBytes("recv data", recv, 16)
c.Debugf("\n\n")
// recv[0] is cc
if len(recv) < 1 {
return fmt.Errorf("recv data at least contains one completion code byte")
}
ccode := recv[0]
if ccode != 0x00 {
return &ResponseError{
completionCode: CompletionCode(ccode),
description: fmt.Sprintf("ipmiRes CompletionCode (%#02x) is not normal: %s", ccode, StrCC(response, ccode)),
}
}
var unpackData = []byte{}
if len(recv) > 1 {
unpackData = recv[1:]
}
if err := response.Unpack(unpackData); err != nil {
return &ResponseError{
completionCode: CompletionCode(recv[0]),
description: fmt.Sprintf("unpack response failed, err: %s", err),
}
}
c.Debug("<< Command Response", response)
return nil
}
func (c *Client) openSendRequest(ctx context.Context, request Request) ([]byte, error) {
var dataPtr *byte
cmdData := request.Pack()
c.DebugBytes("cmdData", cmdData, 16)
if len(cmdData) > 0 {
dataPtr = &cmdData[0]
}
c.DebugBytes("cmd data", cmdData, 16)
msg := &open.IPMI_MSG{
NetFn: uint8(request.Command().NetFn),
Cmd: uint8(request.Command().ID),
Data: dataPtr,
DataLen: uint16(len(cmdData)),
}
addr := &open.IPMI_SYSTEM_INTERFACE_ADDR{
AddrType: open.IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
Channel: open.IPMI_BMC_CHANNEL,
}
req := &open.IPMI_REQ{
Addr: addr,
AddrLen: int(unsafe.Sizeof(addr)),
MsgID: rand.Int63(),
Msg: *msg,
}
c.Debug("IPMI_REQ", req)
return open.SendCommand(c.openipmi.file, req, c.timeout)
}
golang-github-bougou-go-ipmi-0.7.2/interface_tool.go 0000664 0000000 0000000 00000005101 14741105271 0022427 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"context"
"encoding/hex"
"fmt"
"os/exec"
"regexp"
"strconv"
"strings"
)
var (
toolError = regexp.MustCompile(`^Unable to send RAW command \(channel=0x(?P[0-9a-fA-F]+) netfn=0x(?P[0-9a-fA-F]+) lun=0x(?P[0-9a-fA-F]+) cmd=0x(?P[0-9a-fA-F]+) rsp=0x(?P[0-9a-fA-F]+)\): (?P.*)`)
)
// ConnectTool try to initialize the client.
func (c *Client) ConnectTool(ctx context.Context, devnum int32) error {
return nil
}
// closeTool closes the ipmi dev file.
func (c *Client) closeTool(ctx context.Context) error {
return nil
}
func (c *Client) exchangeTool(ctx context.Context, request Request, response Response) error {
data := request.Pack()
msg := make([]byte, 2+len(data))
msg[0] = uint8(request.Command().NetFn)
msg[1] = uint8(request.Command().ID)
copy(msg[2:], data)
args := append([]string{"raw"}, rawEncode(msg)...)
path := c.Host
if path == "" {
path = "ipmitool"
}
cmd := exec.Command(path, args...)
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
c.Debugf(">>> Run cmd: \n>>> %s\n", cmd.String())
err := cmd.Run()
if err != nil {
if bytes.HasPrefix(stderr.Bytes(), []byte("Unable to send RAW command")) {
submatches := toolError.FindSubmatch(stderr.Bytes())
if len(submatches) == 7 && len(submatches[5]) == 2 {
code, err := strconv.ParseUint(string(submatches[5]), 16, 0)
if err != nil {
return fmt.Errorf("CompletionCode parse failed, err: %w", err)
}
return &ResponseError{
completionCode: CompletionCode(uint8(code)),
description: fmt.Sprintf("Raw command failed, err: %s", string(submatches[6])),
}
}
}
return fmt.Errorf("ipmitool run failed, err: %w", err)
}
output := stdout.String()
resp, err := rawDecode(strings.TrimSpace(output))
if err != nil {
return fmt.Errorf("decode response failed, err: %w", err)
}
if err := response.Unpack(resp); err != nil {
return fmt.Errorf("unpack response failed, err: %w", err)
}
return nil
}
func rawDecode(data string) ([]byte, error) {
var buf bytes.Buffer
data = strings.ReplaceAll(data, "\n", "")
for _, s := range strings.Split(data, " ") {
b, err := hex.DecodeString(s)
if err != nil {
return nil, err
}
_, err = buf.Write(b)
if err != nil {
return nil, err
}
}
return buf.Bytes(), nil
}
func rawEncode(data []byte) []string {
n := len(data)
buf := make([]string, 0, n)
// ipmitool needs every byte to be a separate argument
for i := 0; i < n; i++ {
buf = append(buf, "0x"+hex.EncodeToString(data[i:i+1]))
}
return buf
}
golang-github-bougou-go-ipmi-0.7.2/open/ 0000775 0000000 0000000 00000000000 14741105271 0020047 5 ustar 00root root 0000000 0000000 golang-github-bougou-go-ipmi-0.7.2/open/ioctl.go 0000664 0000000 0000000 00000004117 14741105271 0021513 0 ustar 00root root 0000000 0000000 package open
// see: https://github.com/torvalds/linux/blob/master/arch/alpha/include/uapi/asm/ioctl.h
// cSpell:disable
const (
IOC_NRBITS = 8
IOC_TYPEBITS = 8
IOC_SIZEBITS = 14
IOC_DIRBITS = 2
// Direction bits
// NOTE, if IOC_DIRBITS=3, then IOC_NONE=0, IOC_READ=2, IOC_WRITE=4
IOC_NONE = 0x0
IOC_READ = 0x1
IOC_WRITE = 0x2
IOC_NRMASK = ((1 << IOC_NRBITS) - 1)
IOC_TYPEMASK = ((1 << IOC_TYPEBITS) - 1)
IOC_SIZEMASK = ((1 << IOC_SIZEBITS) - 1)
IOC_DIRMASK = ((1 << IOC_DIRBITS) - 1)
IOC_NRSHIFT = 0
IOC_TYPESHIFT = (IOC_NRSHIFT + IOC_NRBITS)
IOC_SIZESHIFT = (IOC_TYPESHIFT + IOC_TYPEBITS)
IOC_DIRSHIFT = (IOC_SIZESHIFT + IOC_SIZEBITS)
// ...and for the drivers/sound files...
IOC_IN = (IOC_WRITE << IOC_DIRSHIFT)
IOC_OUT = (IOC_READ << IOC_DIRSHIFT)
IOC_INOUT = ((IOC_WRITE | IOC_READ) << IOC_DIRSHIFT)
IOCSIZE_MASK = (IOC_SIZEMASK << IOC_SIZESHIFT)
IOCSIZE_SHIFT = (IOC_SIZESHIFT)
)
func IOC(dir uintptr, typ uintptr, nr uintptr, size uintptr) uintptr {
// 00000000 00000000 00000000 00000000
// |- NR
// |- TYPE
// |- SIZE
// |- DIR
return (dir << IOC_DIRSHIFT) | (typ << IOC_TYPESHIFT) | (nr << IOC_NRSHIFT) | (size << IOC_SIZESHIFT)
}
// used to create numbers
func IO(typ, nr uintptr) uintptr {
return IOC(IOC_NONE, typ, nr, 0)
}
func IOR(typ, nr, size uintptr) uintptr {
return IOC(IOC_READ, typ, nr, size)
}
func IOW(typ, nr, size uintptr) uintptr {
return IOC(IOC_WRITE, typ, nr, size)
}
func IOWR(typ, nr, size uintptr) uintptr {
return IOC(IOC_READ|IOC_WRITE, typ, nr, size)
}
// IOC_DIR is used to decode DIR from nr
func IOC_DIR(nr uintptr) uintptr {
return (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
}
// IOC_TYPE is used to decode TYPE from nr
func IOC_TYPE(nr uintptr) uintptr {
return (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
}
// IOC_NR is used to decode NR from nr
func IOC_NR(nr uintptr) uintptr {
return (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
}
// IOC_SIZE is used to decode SIZE from nr
func IOC_SIZE(nr uintptr) uintptr {
return (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
}
golang-github-bougou-go-ipmi-0.7.2/open/ioctl_unix.go 0000664 0000000 0000000 00000000642 14741105271 0022555 0 ustar 00root root 0000000 0000000 //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package open
import (
"fmt"
"syscall"
)
func IOCTL(fd, name, data uintptr) error {
_, _, ep := syscall.Syscall(syscall.SYS_IOCTL, fd, name, data)
if ep != 0 {
return fmt.Errorf("syscall err: (%#02x) %s", uint8(ep), syscall.Errno(ep))
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/open/ioctl_windows.go 0000664 0000000 0000000 00000000147 14741105271 0023264 0 ustar 00root root 0000000 0000000 package open
func IOCTL(fd, name, data uintptr) error {
// Todo, implement for windows
return nil
}
golang-github-bougou-go-ipmi-0.7.2/open/ipmi.go 0000664 0000000 0000000 00000014616 14741105271 0021344 0 ustar 00root root 0000000 0000000 package open
import (
"fmt"
"time"
"unsafe"
)
// see: https://github.com/u-root/u-root/blob/v0.8.0/pkg/ipmi/ipmi.go
// Note, this file basically is a Go conversion of https://github.com/torvalds/linux/blob/master/include/uapi/linux/ipmi.h
const (
IPMI_IOC_MAGIC uintptr = 'i'
IPMI_BUF_SIZE = 1024
IPMI_FILE_READ_TIMEOUT time.Duration = time.Second * 10
IPMI_MAX_ADDR_SIZE = 32
// Channel for talking directly with the BMC. When using this
// channel, This is for the system interface address type only.
IPMI_BMC_CHANNEL = 0xf
IPMI_NUM_CHANNELS = 0x10
// Receive types for messages coming from the receive interface.
// This is used for the receive in-kernel interface and in the receive IOCTL.
//
// The "IPMI_RESPONSE_RESPONSE_TYPE" is a little strange sounding, but
// it allows you to get the message results when you send a response message.
IPMI_RESPONSE_RECV_TYPE = 1
IPMI_ASYNC_EVENT_RECV_TYPE = 2
IPMI_CMD_RECV_TYPE = 3
IPMI_RESPONSE_RESPONSE_TYPE = 4
IPMI_OEM_RECV_TYPE = 5
IPMI_MAINTENANCE_MODE_AUTO = 0
IPMI_MAINTENANCE_MODE_OFF = 1
IPMI_MAINTENANCE_MODE_ON = 2
)
var (
IPMICTL_SEND_COMMAND = IOW(IPMI_IOC_MAGIC, 13, unsafe.Sizeof(IPMI_REQ{}))
IPMICTL_SEND_COMMAND_SETTIME = IOW(IPMI_IOC_MAGIC, 21, unsafe.Sizeof(IPMI_REQ_SETTIME{}))
IPMICTL_RECEIVE_MSG = IOWR(IPMI_IOC_MAGIC, 12, unsafe.Sizeof(IPMI_RECV{}))
IPMICTL_RECEIVE_MSG_TRUNC = IOWR(IPMI_IOC_MAGIC, 11, unsafe.Sizeof(IPMI_RECV{}))
IPMICTL_REGISTER_FOR_CMD = IOR(IPMI_IOC_MAGIC, 14, unsafe.Sizeof(IPMI_CMDSPEC{}))
IPMICTL_UNREGISTER_FOR_CMD = IOR(IPMI_IOC_MAGIC, 15, unsafe.Sizeof(IPMI_CMDSPEC{}))
IPMICTL_REGISTER_FOR_CMD_CHANS = IOR(IPMI_IOC_MAGIC, 28, unsafe.Sizeof(IPMI_CMDSPEC_CHANS{}))
IPMICTL_UNREGISTER_FOR_CMD_CHANS = IOR(IPMI_IOC_MAGIC, 29, unsafe.Sizeof(IPMI_CMDSPEC_CHANS{}))
IPMICTL_SET_GETS_EVENTS_CMD = IOW(IPMI_IOC_MAGIC, 16, unsafe.Sizeof(uint32(0)))
IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD = IOR(IPMI_IOC_MAGIC, 24, unsafe.Sizeof(IPMI_CHANNEL_LUN_ADDRESS_SET{}))
IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD = IOR(IPMI_IOC_MAGIC, 25, unsafe.Sizeof(IPMI_CHANNEL_LUN_ADDRESS_SET{}))
IPMICTL_SET_MY_CHANNEL_LUN_CMD = IOR(IPMI_IOC_MAGIC, 26, unsafe.Sizeof(IPMI_CHANNEL_LUN_ADDRESS_SET{}))
IPMICTL_GET_MY_CHANNEL_LUN_CMD = IOR(IPMI_IOC_MAGIC, 27, unsafe.Sizeof(IPMI_CHANNEL_LUN_ADDRESS_SET{}))
/* Legacy interfaces, these only set IPMB 0. */
IPMICTL_SET_MY_ADDRESS_CMD = IOR(IPMI_IOC_MAGIC, 17, unsafe.Sizeof(uint32(0)))
IPMICTL_GET_MY_ADDRESS_CMD = IOR(IPMI_IOC_MAGIC, 18, unsafe.Sizeof(uint32(0)))
IPMICTL_SET_MY_LUN_CMD = IOR(IPMI_IOC_MAGIC, 19, unsafe.Sizeof(uint32(0)))
IPMICTL_GET_MY_LUN_CMD = IOR(IPMI_IOC_MAGIC, 20, unsafe.Sizeof(uint32(0)))
IPMICTL_SET_TIMING_PARAMS_CMD = IOR(IPMI_IOC_MAGIC, 22, unsafe.Sizeof(IPMI_TIMING_PARAMS{}))
IPMICTL_GET_TIMING_PARAMS_CMD = IOR(IPMI_IOC_MAGIC, 23, unsafe.Sizeof(IPMI_TIMING_PARAMS{}))
IPMICTL_GET_MAINTENANCE_MODE_CMD = IOR(IPMI_IOC_MAGIC, 30, unsafe.Sizeof(uint32(0)))
IPMICTL_SET_MAINTENANCE_MODE_CMD = IOW(IPMI_IOC_MAGIC, 31, unsafe.Sizeof(uint32(0)))
)
// IPMI_ADDR wraps different IPMI ADDR TYPE data to one struct.
// IPMI ADDR TYPE (Channel Medium Type), see: 6.5 Channel Medium Type
type IPMI_ADDR struct {
AddrType int32
Channel uint16
Data [IPMI_MAX_ADDR_SIZE]byte // Addr Data
}
const IPMI_SYSTEM_INTERFACE_ADDR_TYPE = 0x0c
// IPMI_SYSTEM_INTERFACE_ADDR holds addr data of addr type IPMI_SYSTEM_INTERFACE_ADDR_TYPE.
type IPMI_SYSTEM_INTERFACE_ADDR struct {
AddrType int32
Channel uint16
LUN uint8
}
const IPMI_IPMB_ADDR_TYPE = 0x01
const IPMI_IPMB_BROADCAST_ADDR_TYPE = 0x41 // Used for broadcast get device id as described in section 17.9 of the IPMI 1.5 manual.
// IPMI_IPMB_ADDR holds addr data of addr type IPMI_IPMB_ADDR_TYPE or IPMI_IPMB_BROADCAST_ADDR_TYPE.
//
// It represents an IPMB address.
type IPMI_IPMB_ADDR struct {
AddrType int32
Channel uint16
SlaveAddr uint8
LUN uint8
}
const IPMI_IPMB_DIRECT_ADDR_TYPE = 0x81
// IPMI_IPMB_DIRECT_ADDR holds addr data of addr type IPMI_IPMB_DIRECT_ADDR_TYPE.
//
// Used for messages received directly from an IPMB that have not gone
// through a MC. This is for systems that sit right on an IPMB so
// they can receive commands and respond to them.
type IPMI_IPMB_DIRECT_ADDR struct {
AddrType int32
Channel uint16
SlaveAddr uint8
RsLUN uint8
RqLUN uint8
}
const IPMI_LAN_ADDR_TYPE = 0x04
// IPMI_LAN_ADDR holds addr data of addr type IPMI_LAN_ADDR_TYPE.
//
// A LAN Address. This is an address to/from a LAN interface bridged
// by the BMC, not an address actually out on the LAN.
type IPMI_LAN_ADDR struct {
AddrType int32
Channel uint16
Privilege uint8
SessionHandle uint8
RemoteSWID uint8
LocalSWID uint8
LUN uint8
}
// IPMI_MSG holds a raw IPMI message without any addressing. This covers both
// commands and responses. The completion code is always the first
// byte of data in the response (as the spec shows the messages laid out).
//
// unsafe.Sizeof of IPMI_MSG is 1+1+2+(4)+8=16.
type IPMI_MSG struct {
NetFn uint8
Cmd uint8
DataLen uint16
Data *byte
}
func (msg *IPMI_MSG) MsgData() ([]byte, error) {
if msg.DataLen >= IPMI_BUF_SIZE {
return nil, fmt.Errorf("received data length longer than buf size: %d > %d", msg.DataLen, IPMI_BUF_SIZE)
}
recvBuf := unsafe.Slice(msg.Data, msg.DataLen)
return recvBuf[:msg.DataLen:msg.DataLen], nil
}
// unsafe.Sizeof of IPMI_REQ is 8+8(4+4)+8+16 = 40.
type IPMI_REQ struct {
Addr *IPMI_SYSTEM_INTERFACE_ADDR
AddrLen int
// The sequence number for the message. This
// exact value will be reported back in the
// response to this request if it is a command.
// If it is a response, this will be used as
// the sequence value for the response.
MsgID int64
Msg IPMI_MSG
}
// unsafe.Sizeof of IPMI_RECV is 8(4+4)+8+8(4+4)+8+16 = 48.
type IPMI_RECV struct {
RecvType int
Addr *IPMI_SYSTEM_INTERFACE_ADDR
AddrLen int
MsgID int64
Msg IPMI_MSG
}
type IPMI_REQ_SETTIME struct {
Req IPMI_REQ
Retries int32
RetryTimeMillis uint32
}
// Register to get commands from other entities on this interface
type IPMI_CMDSPEC struct {
NetFn uint8
Cmd uint8
}
type IPMI_CMDSPEC_CHANS struct {
NetFn int
Cmd int
Chans int
}
type IPMI_CHANNEL_LUN_ADDRESS_SET struct {
Channel uint16
Value uint8
}
type IPMI_TIMING_PARAMS struct {
Retries int
RetryTimeMillis uint
}
golang-github-bougou-go-ipmi-0.7.2/open/send.go 0000664 0000000 0000000 00000003650 14741105271 0021333 0 ustar 00root root 0000000 0000000 package open
import (
"fmt"
"os"
"runtime"
"syscall"
"time"
"unsafe"
)
func SetReq(fd uintptr, op uintptr, req *IPMI_REQ) error {
err := IOCTL(fd, op, uintptr(unsafe.Pointer(req)))
runtime.KeepAlive(req)
return err
}
func GetRecv(fd uintptr, op uintptr, recv *IPMI_RECV) error {
err := IOCTL(fd, op, uintptr(unsafe.Pointer(recv)))
runtime.KeepAlive(recv)
return err
}
func SendCommand(file *os.File, req *IPMI_REQ, timeout time.Duration) ([]byte, error) {
if timeout == 0 {
timeout = IPMI_FILE_READ_TIMEOUT
}
fd := file.Fd()
for {
switch err := SetReq(fd, IPMICTL_SEND_COMMAND, req); {
case err == syscall.EINTR:
continue
case err != nil:
return nil, fmt.Errorf("SetReq failed, err: %w", err)
}
break
}
recvBuf := make([]byte, IPMI_BUF_SIZE)
recv := &IPMI_RECV{
Addr: req.Addr,
AddrLen: req.AddrLen,
Msg: IPMI_MSG{
Data: &recvBuf[0],
DataLen: IPMI_BUF_SIZE,
},
}
var result []byte
var rerr error
readMsgFunc := func(fd uintptr) bool {
if err := GetRecv(fd, IPMICTL_RECEIVE_MSG_TRUNC, recv); err != nil {
rerr = fmt.Errorf("GetRecv failed, err: %w", err)
return false
}
if recv.MsgID != req.MsgID {
rerr = fmt.Errorf("received msg id not match")
return false
}
if recv.Msg.DataLen >= IPMI_BUF_SIZE {
rerr = fmt.Errorf("received data length longer than buf size: %d > %d", recv.Msg.DataLen, IPMI_BUF_SIZE)
} else {
// recvBuf[0] is completion code.
result = recvBuf[:recv.Msg.DataLen:recv.Msg.DataLen]
rerr = nil
}
return true
}
conn, err := file.SyscallConn()
if err != nil {
return nil, fmt.Errorf("failed to get syscall conn from file: %s", err)
}
if err := file.SetReadDeadline(time.Now().Add(timeout)); err != nil {
return nil, fmt.Errorf("failed to set read deadline on file: %s", err)
}
if err := conn.Read(readMsgFunc); err != nil {
return nil, fmt.Errorf("failed to read from syscall conn: %s", err)
}
return result, rerr
}
golang-github-bougou-go-ipmi-0.7.2/types_boot_option.go 0000664 0000000 0000000 00000007321 14741105271 0023217 0 ustar 00root root 0000000 0000000 package ipmi
type BootInfoAcknowledgeBy uint8
const (
BootInfoAcknowledgeByBIOSPOST BootInfoAcknowledgeBy = 1 << 0
BootInfoAcknowledgeByOSLoader BootInfoAcknowledgeBy = 1 << 1
BootInfoAcknowledgeByOSServicePartition BootInfoAcknowledgeBy = 1 << 2
BootInfoAcknowledgeBySMS BootInfoAcknowledgeBy = 1 << 3
BootInfoAcknowledgeByOEM BootInfoAcknowledgeBy = 1 << 4
)
type BIOSVerbosity uint8 // only 2 bits, occupied 0-3
const (
BIOSVerbosityDefault BIOSVerbosity = 0
BIOSVerbosityQuiet BIOSVerbosity = 1
BIOSVerbosityVerbose BIOSVerbosity = 2
)
func (v BIOSVerbosity) String() string {
switch v {
case 0:
return "System Default"
case 1:
return "Request Quiet Display"
case 2:
return "Request Verbose Display"
default:
return "Flag error"
}
}
type BIOSBootType bool
const (
BIOSBootTypeLegacy BIOSBootType = false // PC compatible boot (legacy)
BIOSBootTypeEFI BIOSBootType = true // Extensible Firmware Interface Boot (EFI)
)
func (t BIOSBootType) String() string {
if t {
return "BIOS EFI boot"
}
return "BIOS PC Compatible (legacy) boot"
}
type BootDeviceSelector uint8 // only 4 bits occupied
const (
BootDeviceSelectorNoOverride BootDeviceSelector = 0x00
BootDeviceSelectorForcePXE BootDeviceSelector = 0x01
BootDeviceSelectorForceHardDrive BootDeviceSelector = 0x02
BootDeviceSelectorForceHardDriveSafe BootDeviceSelector = 0x03
BootDeviceSelectorForceDiagnosticPartition BootDeviceSelector = 0x04
BootDeviceSelectorForceCDROM BootDeviceSelector = 0x05
BootDeviceSelectorForceBIOSSetup BootDeviceSelector = 0x06
BootDeviceSelectorForceRemoteFloppy BootDeviceSelector = 0x07
BootDeviceSelectorForceRemoteCDROM BootDeviceSelector = 0x08
BootDeviceSelectorForceRemoteMedia BootDeviceSelector = 0x09
BootDeviceSelectorForceRemoteHardDrive BootDeviceSelector = 0x0b
BootDeviceSelectorForceFloppy BootDeviceSelector = 0x0f
)
func (s BootDeviceSelector) String() string {
switch s {
case 0x00:
return "No override"
case 0x01:
return "Force PXE"
case 0x02:
return "Force Boot from default Hard-Drive"
case 0x03:
return "Force Boot from default Hard-Drive, request Safe-Mode"
case 0x04:
return "Force Boot from Diagnostic Partition"
case 0x05:
return "Force Boot from CD/DVD"
case 0x06:
return "Force Boot into BIOS Setup"
case 0x07:
return "Force Boot from remotely connected Floppy/primary removable media"
case 0x08:
return "Force Boot from remotely connected CD/DVD"
case 0x09:
return "Force Boot from primary remote media"
case 0x0b:
return "Force Boot from remotely connected Hard-Drive"
case 0x0f:
return "Force Boot from Floppy/primary removable media"
default:
return "Flag error"
}
}
type ConsoleRedirectionControl uint8
const (
ConsoleRedirectionControl_Default ConsoleRedirectionControl = 0
ConsoleRedirectionControl_Skip ConsoleRedirectionControl = 1
ConsoleRedirectionControl_Enable ConsoleRedirectionControl = 2
)
func (c ConsoleRedirectionControl) String() string {
switch c {
case 0:
return "Console redirection occurs per BIOS configuration setting (default)"
case 1:
return "Suppress (skip) console redirection if enabled"
case 2:
return "Request console redirection be enabled"
default:
return "Flag error"
}
}
type BIOSMuxControl uint8
func (b BIOSMuxControl) String() string {
switch b {
case 0:
return "BIOS uses recommended setting of the mux at the end of POST"
case 1:
return "Requests BIOS to force mux to BMC at conclusion of POST/start of OS boot"
case 2:
return "Requests BIOS to force mux to system at conclusion of POST/start of OS boot"
default:
return "Flag error"
}
}
golang-github-bougou-go-ipmi-0.7.2/types_boot_option_params.go 0000664 0000000 0000000 00000052517 14741105271 0024571 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"fmt"
"strings"
"time"
)
type BootOptionParamSelector uint8 // only 7 bits occupied, 0-127
const (
BootOptionParamSelector_SetInProgress BootOptionParamSelector = 0x00
BootOptionParamSelector_ServicePartitionSelector BootOptionParamSelector = 0x01
BootOptionParamSelector_ServicePartitionScan BootOptionParamSelector = 0x02
BootOptionParamSelector_BMCBootFlagValidBitClear BootOptionParamSelector = 0x03
BootOptionParamSelector_BootInfoAcknowledge BootOptionParamSelector = 0x04
BootOptionParamSelector_BootFlags BootOptionParamSelector = 0x05
BootOptionParamSelector_BootInitiatorInfo BootOptionParamSelector = 0x06
BootOptionParamSelector_BootInitiatorMailbox BootOptionParamSelector = 0x07
// OEM Parameters, 96:127
)
func (bop BootOptionParamSelector) String() string {
m := map[BootOptionParamSelector]string{
BootOptionParamSelector_SetInProgress: "Set In Progress",
BootOptionParamSelector_ServicePartitionSelector: "Service Partition Selector",
BootOptionParamSelector_ServicePartitionScan: "Service Partition Scan",
BootOptionParamSelector_BMCBootFlagValidBitClear: "BMC Boot Flag Valid bit Clearing",
BootOptionParamSelector_BootInfoAcknowledge: "Boot Info Acknowledge",
BootOptionParamSelector_BootFlags: "Boot Flags",
BootOptionParamSelector_BootInitiatorInfo: "Boot Initiator Info",
BootOptionParamSelector_BootInitiatorMailbox: "Boot Initiator Mailbox",
}
s, ok := m[bop]
if ok {
return s
}
return "Unknown"
}
type BootOptionParameter interface {
BootOptionParameter() (paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8)
Parameter
}
var (
_ BootOptionParameter = (*BootOptionParam_SetInProgress)(nil)
_ BootOptionParameter = (*BootOptionParam_ServicePartitionSelector)(nil)
_ BootOptionParameter = (*BootOptionParam_ServicePartitionScan)(nil)
_ BootOptionParameter = (*BootOptionParam_BMCBootFlagValidBitClear)(nil)
_ BootOptionParameter = (*BootOptionParam_BootInfoAcknowledge)(nil)
_ BootOptionParameter = (*BootOptionParam_BootFlags)(nil)
_ BootOptionParameter = (*BootOptionParam_BootInitiatorInfo)(nil)
_ BootOptionParameter = (*BootOptionParam_BootInitiatorMailbox)(nil)
)
func isNilBootOptionParameter(param BootOptionParameter) bool {
switch v := param.(type) {
case *BootOptionParam_SetInProgress:
return v == nil
case *BootOptionParam_ServicePartitionSelector:
return v == nil
case *BootOptionParam_ServicePartitionScan:
return v == nil
case *BootOptionParam_BMCBootFlagValidBitClear:
return v == nil
case *BootOptionParam_BootInfoAcknowledge:
return v == nil
case *BootOptionParam_BootFlags:
return v == nil
case *BootOptionParam_BootInitiatorInfo:
return v == nil
case *BootOptionParam_BootInitiatorMailbox:
return v == nil
default:
return false
}
}
// Table 28-14, Boot Option Parameters
type BootOptionsParams struct {
SetInProgress *BootOptionParam_SetInProgress
ServicePartitionSelector *BootOptionParam_ServicePartitionSelector
ServicePartitionScan *BootOptionParam_ServicePartitionScan
BMCBootFlagValidBitClear *BootOptionParam_BMCBootFlagValidBitClear
BootInfoAcknowledge *BootOptionParam_BootInfoAcknowledge
BootFlags *BootOptionParam_BootFlags
BootInitiatorInfo *BootOptionParam_BootInitiatorInfo
BootInitiatorMailbox *BootOptionParam_BootInitiatorMailbox
}
func (bootOptionsParams *BootOptionsParams) Format() string {
format := func(param BootOptionParameter) string {
if isNilBootOptionParameter(param) {
return ""
}
paramSelector, _, _ := param.BootOptionParameter()
content := param.Format()
if content[len(content)-1] != '\n' {
content += "\n"
}
return fmt.Sprintf("[%02d] %-24s : %s", paramSelector, paramSelector.String(), content)
}
out := ""
out += format(bootOptionsParams.SetInProgress)
out += format(bootOptionsParams.ServicePartitionSelector)
out += format(bootOptionsParams.ServicePartitionScan)
out += format(bootOptionsParams.BMCBootFlagValidBitClear)
out += format(bootOptionsParams.BootInfoAcknowledge)
out += format(bootOptionsParams.BootFlags)
out += format(bootOptionsParams.BootInitiatorInfo)
out += format(bootOptionsParams.BootInitiatorMailbox)
return out
}
type BootOptionParam_SetInProgress struct {
Value SetInProgressState
}
func (p *BootOptionParam_SetInProgress) BootOptionParameter() (paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8) {
return BootOptionParamSelector_SetInProgress, 0, 0
}
func (p *BootOptionParam_SetInProgress) Unpack(paramData []byte) error {
if len(paramData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
p.Value = SetInProgressState(paramData[0])
return nil
}
func (p *BootOptionParam_SetInProgress) Pack() []byte {
return []byte{uint8(p.Value)}
}
func (p *BootOptionParam_SetInProgress) Format() string {
return p.Value.String()
}
// This value is used to select which service partition BIOS should boot using.
type BootOptionParam_ServicePartitionSelector struct {
Selector uint8
}
func (p *BootOptionParam_ServicePartitionSelector) BootOptionParameter() (paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8) {
return BootOptionParamSelector_ServicePartitionSelector, 0, 0
}
func (p *BootOptionParam_ServicePartitionSelector) Pack() []byte {
return []byte{p.Selector}
}
func (p *BootOptionParam_ServicePartitionSelector) Unpack(paramData []byte) error {
if len(paramData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
p.Selector = paramData[0]
return nil
}
func (p *BootOptionParam_ServicePartitionSelector) Format() string {
switch p.Selector {
case 0:
return "unspecified"
default:
return fmt.Sprintf("%#02x", p)
}
}
type BootOptionParam_ServicePartitionScan struct {
// data 1 [7:2] - reserved
// - [1] - 1b = Request BIOS to scan for specified service partition.
// BIOS clears this bit after the requested scan has been performed.
// - [0] - 1b = Service Partition discovered.
// BIOS sets this bit to indicate it has discovered the specified service partition.
// The bit retains the value from the last scan.
// Therefore, to get up-to-date status of the discovery state, a scan may need to be requested.
RequestBIOSScan bool
ServicePartitionDiscovered bool
}
func (p *BootOptionParam_ServicePartitionScan) BootOptionParameter() (paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8) {
return BootOptionParamSelector_ServicePartitionScan, 0, 0
}
func (p *BootOptionParam_ServicePartitionScan) Pack() []byte {
var b uint8
if p.RequestBIOSScan {
b = setBit1(b)
}
if p.ServicePartitionDiscovered {
b = setBit0(b)
}
return []byte{b}
}
func (p *BootOptionParam_ServicePartitionScan) Unpack(paramData []byte) error {
if len(paramData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
p.RequestBIOSScan = isBit1Set(paramData[0])
p.ServicePartitionDiscovered = isBit0Set(paramData[0])
return nil
}
func (p BootOptionParam_ServicePartitionScan) Format() string {
s := "\n"
if p.RequestBIOSScan {
s += " - Request BIOS to scan\n"
}
if p.ServicePartitionDiscovered {
s += " - Service Partition Discoverd\n"
}
if s == "\n" {
s += " No flag set\n"
}
return s
}
type BootOptionParam_BMCBootFlagValidBitClear struct {
DontClearOnResetPEFOrPowerCyclePEF bool // corresponding to restart cause: 0x08, 0x09
DontClearOnCommandReceivedTimeout bool // corresponding to restart cause: 0x01
DontClearOnWatchdogTimeout bool // corresponding to restart cause: 0x04
DontClearOnResetPushButtonOrSoftReset bool // corresponding to restart cause: 0x02, 0x0a
DontClearOnPowerUpPushButtonOrWakeEvent bool // corresponding to restart cause: 0x03, 0x0b
}
func (p *BootOptionParam_BMCBootFlagValidBitClear) BootOptionParameter() (paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8) {
return BootOptionParamSelector_BMCBootFlagValidBitClear, 0, 0
}
func (p *BootOptionParam_BMCBootFlagValidBitClear) Format() string {
s := "\n"
if p.DontClearOnResetPEFOrPowerCyclePEF {
s += " - Don't clear valid bit on reset/power cycle cause by PEF\n"
}
if p.DontClearOnCommandReceivedTimeout {
s += " - Don't automatically clear boot flag valid bit on timeout\n"
}
if p.DontClearOnWatchdogTimeout {
s += " - Don't clear valid bit on reset/power cycle cause by watchdog\n"
}
if p.DontClearOnResetPushButtonOrSoftReset {
s += " - Don't clear valid bit on push button reset // soft reset\n"
}
if p.DontClearOnPowerUpPushButtonOrWakeEvent {
s += " - Don't clear valid bit on power up via power push button or wake event\n"
}
// When any flag was set, then at least one of the above condition will be true, thus 's' would not be empty.
if s == "\n" {
s += " No flag set\n"
}
return s
}
func (p *BootOptionParam_BMCBootFlagValidBitClear) Pack() []byte {
var b uint8
if p.DontClearOnResetPEFOrPowerCyclePEF {
b = setBit4(b)
}
if p.DontClearOnCommandReceivedTimeout {
b = setBit3(b)
}
if p.DontClearOnWatchdogTimeout {
b = setBit2(b)
}
if p.DontClearOnResetPushButtonOrSoftReset {
b = setBit1(b)
}
if p.DontClearOnPowerUpPushButtonOrWakeEvent {
b = setBit0(b)
}
return []byte{b}
}
func (p *BootOptionParam_BMCBootFlagValidBitClear) Unpack(parameterData []byte) error {
if len(parameterData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
b := parameterData[0]
p.DontClearOnResetPEFOrPowerCyclePEF = isBit4Set(b)
p.DontClearOnCommandReceivedTimeout = isBit3Set(b)
p.DontClearOnWatchdogTimeout = isBit2Set(b)
p.DontClearOnResetPushButtonOrSoftReset = isBit1Set(b)
p.DontClearOnPowerUpPushButtonOrWakeEvent = isBit0Set(b)
return nil
}
type BootOptionParam_BootInfoAcknowledge struct {
// The boot initiator should typically write FFh to this parameter prior to initiating the boot.
// The boot initiator may write 0 s if it wants to intentionally direct a given party to ignore the
// boot info.
// This field is automatically initialized to 00h when the management controller if first powered up or reset.
ByOEM bool
BySMS bool
ByOSServicePartition bool
ByOSLoader bool
ByBIOSPOST bool
}
func (p *BootOptionParam_BootInfoAcknowledge) BootOptionParameter() (paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8) {
return BootOptionParamSelector_BootInfoAcknowledge, 0, 0
}
func (p *BootOptionParam_BootInfoAcknowledge) Format() string {
s := "\n"
if p.ByOEM {
s += " - OEM has handled boot info\n"
}
if p.BySMS {
s += " - SMS has handled boot info\n"
}
if p.ByOSServicePartition {
s += " - OS // service partition has handled boot info\n"
}
if p.ByOSLoader {
s += " - OS Loader has handled boot info\n"
}
if p.ByBIOSPOST {
s += " - BIOS/POST has handled boot info\n"
}
if s == "\n" {
s += " No flag set\n"
}
return fmt.Sprint(s)
}
func (p *BootOptionParam_BootInfoAcknowledge) Pack() []byte {
var out = make([]byte, 2)
var b uint8 = 0x00
var b1 uint8 = 0xe0 // bit 7,6,5 is reserved, write s 1b
if p.ByOEM {
b = setBit4(b)
b1 = setBit4(b1)
}
if p.BySMS {
b = setBit3(b)
b1 = setBit3(b1)
}
if p.ByOSServicePartition {
b = setBit2(b)
b1 = setBit2(b1)
}
if p.ByOSLoader {
b = setBit1(b)
b1 = setBit1(b1)
}
if p.ByBIOSPOST {
b = setBit0(b)
b1 = setBit0(b1)
}
packUint8(b, out, 0)
packUint8(b1, out, 1)
return out
}
func (p *BootOptionParam_BootInfoAcknowledge) Unpack(parameterData []byte) error {
if len(parameterData) != 2 {
return fmt.Errorf("the parameter data length must be 2 bytes")
}
b, _, _ := unpackUint8(parameterData, 1)
p.ByOEM = isBit4Set(b)
p.BySMS = isBit3Set(b)
p.ByOSServicePartition = isBit2Set(b)
p.ByOSLoader = isBit1Set(b)
p.ByBIOSPOST = isBit0Set(b)
return nil
}
type BootOptionParam_BootFlags struct {
// 1b = boot flags valid.
// The bit should be set to indicate that valid flag data is present.
// This bit may be automatically cleared based on the boot flag valid bit clearing parameter, above.
BootFlagsValid bool
// 0b = options apply to next boot only.
// 1b = options requested to be persistent for all future boots (i.e. requests BIOS to change its boot settings)
Persist bool
// 0b = "PC compatible" boot (legacy)
// 1b = Extensible Firmware Interface Boot (EFI)
BIOSBootType BIOSBootType
CMOSClear bool
LockKeyboard bool
BootDeviceSelector BootDeviceSelector // 4 bits
ScreenBlank bool
LockoutResetButton bool
LockoutPowerOff bool
BIOSVerbosity BIOSVerbosity
ForceProgressEventTraps bool
BypassUserPassword bool
LockoutSleepButton bool
ConsoleRedirectionControl ConsoleRedirectionControl // only 2 bits
BIOSSharedModeOverride bool
BIOSMuxControl BIOSMuxControl // only 3 bits
DeviceInstanceSelector uint8 // only 5 bits
}
func (p *BootOptionParam_BootFlags) BootOptionParameter() (paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8) {
return BootOptionParamSelector_BootFlags, 0, 0
}
func (p *BootOptionParam_BootFlags) Pack() []byte {
out := make([]byte, 5)
var b1 uint8
if p.BootFlagsValid {
b1 = setBit7(b1)
}
if p.Persist {
b1 = setBit6(b1)
}
if p.BIOSBootType {
b1 = setBit5(b1)
}
packUint8(b1, out, 0)
var b2 = uint8(p.BootDeviceSelector) << 2
if p.CMOSClear {
b2 = setBit7(b2)
}
if p.LockKeyboard {
b2 = setBit6(b2)
}
if p.ScreenBlank {
b2 = setBit1(b2)
}
if p.LockoutResetButton {
b2 = setBit0(b2)
}
packUint8(b2, out, 1)
var b3 = uint8(p.BIOSVerbosity) << 5
if p.LockoutPowerOff {
b3 = setBit7(b3)
}
if p.ForceProgressEventTraps {
b3 = setBit4(b3)
}
if p.BypassUserPassword {
b3 = setBit3(b3)
}
if p.LockoutResetButton {
b3 = setBit2(b3)
}
b3 |= uint8(p.ConsoleRedirectionControl)
packUint8(b3, out, 2)
var b4 uint8
if p.BIOSSharedModeOverride {
b4 = setBit3(b4)
}
b4 |= uint8(p.BIOSMuxControl)
packUint8(b4, out, 3)
var b5 = uint8(p.DeviceInstanceSelector)
packUint8(b5, out, 4)
return out
}
func (p *BootOptionParam_BootFlags) Unpack(parameterData []byte) error {
if len(parameterData) != 5 {
return fmt.Errorf("the parameter data length must be 5 bytes")
}
b1, _, _ := unpackUint8(parameterData, 0)
p.BootFlagsValid = isBit7Set(b1)
p.Persist = isBit6Set(b1)
p.BIOSBootType = BIOSBootType(isBit5Set(b1))
b2, _, _ := unpackUint8(parameterData, 1)
p.CMOSClear = isBit7Set(b2)
p.LockKeyboard = isBit6Set(b2)
p.BootDeviceSelector = BootDeviceSelector((b2 & 0x3f) >> 2) // bit 5,4,3,2
p.ScreenBlank = isBit1Set(b2)
p.LockoutResetButton = isBit0Set(b2)
b3, _, _ := unpackUint8(parameterData, 2)
p.LockoutPowerOff = isBit7Set(b3)
p.BIOSVerbosity = BIOSVerbosity((b3 & 0x7f) >> 5)
p.ForceProgressEventTraps = isBit4Set(b3)
p.BypassUserPassword = isBit3Set(b3)
p.LockoutResetButton = isBit2Set(b3)
p.ConsoleRedirectionControl = ConsoleRedirectionControl(b3 & 0x03)
b4, _, _ := unpackUint8(parameterData, 3)
p.BIOSSharedModeOverride = isBit3Set(b4)
p.BIOSMuxControl = BIOSMuxControl(b4 & 0x07)
b5, _, _ := unpackUint8(parameterData, 4)
p.DeviceInstanceSelector = b5 & 0x1f
return nil
}
func (p *BootOptionParam_BootFlags) Format() string {
s := "\n"
s += fmt.Sprintf(" - Boot Flag %s\n", formatBool(p.BootFlagsValid, "Valid", "Invalid"))
s += fmt.Sprintf(" - Options apply to %s\n", formatBool(p.Persist, "all future boots", "only next boot"))
s += fmt.Sprintf(" - %s\n", p.BIOSBootType.String())
if p.CMOSClear {
s += " - CMOS Clear\n"
}
if p.LockKeyboard {
s += " - Lock Keyboard\n"
}
s += fmt.Sprintf(" - Boot Device Selector : %s\n", p.BootDeviceSelector.String())
if p.ScreenBlank {
s += " - Screen blank\n"
}
if p.LockoutResetButton {
s += " - Lock out Reset buttons\n"
}
if p.LockoutPowerOff {
s += " - Lock out (power off/sleep request) via Power Button\n"
}
s += fmt.Sprintf(" - BIOS verbosity : %s\n", p.BIOSVerbosity.String())
if p.ForceProgressEventTraps {
s += " - Force progress event traps\n"
}
if p.BypassUserPassword {
s += " - User password bypass\n"
}
if p.LockoutSleepButton {
s += " - Lock Out Sleep Button\n"
}
s += fmt.Sprintf(" - Console Redirection control : %s\n", p.ConsoleRedirectionControl.String())
if p.BIOSSharedModeOverride {
s += " - BIOS Shared Mode Override\n"
}
s += fmt.Sprintf(" - BIOS Mux Control Override : %s\n", p.BIOSMuxControl.String())
return s
}
func (bootFlags *BootOptionParam_BootFlags) OptionsHelp() string {
supportedOptions := []struct {
name string
help string
}{
{"help", "print help message"},
{"valid", "Boot flags valid"},
{"persistent", "Changes are persistent for all future boots"},
{"efiboot", "Extensible Firmware Interface Boot (EFI)"},
{"clear-cmos", "CMOS clear"},
{"lockkbd", "Lock Keyboard"},
{"screenblank", "Screen Blank"},
{"lockoutreset", "Lock out Resetbuttons"},
{"lockout_power", "Lock out (power off/sleep request) via Power Button"},
{"verbose=default", "Request quiet BIOS display"},
{"verbose=no", "Request quiet BIOS display"},
{"verbose=yes", "Request verbose BIOS display"},
{"force_pet", "Force progress event traps"},
{"upw_bypass", "User password bypass"},
{"lockout_sleep", "Log Out Sleep Button"},
{"cons_redirect=default", "Console redirection occurs per BIOS configuration setting"},
{"cons_redirect=skip", "Suppress (skip) console redirection if enabled"},
{"cons_redirect=enable", "Suppress (skip) console redirection if enabled"},
}
var buf bytes.Buffer
buf.WriteString("Legal options settings are:\n")
for _, o := range supportedOptions {
buf.WriteString(fmt.Sprintf(" %-22s : %s\n", o.name, o.help))
}
return buf.String()
}
func (bootFlags *BootOptionParam_BootFlags) ParseFromOptionsStr(optionsStr string) error {
options := strings.Split(optionsStr, ",")
return bootFlags.ParseFromOptions(options)
}
func (bootFlags *BootOptionParam_BootFlags) ParseFromOptions(options []string) error {
for _, option := range options {
switch option {
case "valid":
bootFlags.BootFlagsValid = true
case "persistent":
bootFlags.Persist = true
case "efiboot":
bootFlags.BIOSBootType = BIOSBootTypeEFI
case "clear-cmos":
bootFlags.CMOSClear = true
case "lockkbd":
bootFlags.LockKeyboard = true
case "screenblank":
bootFlags.ScreenBlank = true
case "lockoutreset":
bootFlags.LockoutResetButton = true
case "lockout_power":
bootFlags.LockoutPowerOff = true
case "verbose=default":
bootFlags.BIOSVerbosity = BIOSVerbosityDefault
case "verbose=no":
bootFlags.BIOSVerbosity = BIOSVerbosityQuiet
case "verbose=yes":
bootFlags.BIOSVerbosity = BIOSVerbosityVerbose
case "force_pet":
bootFlags.ForceProgressEventTraps = true
case "upw_bypass":
bootFlags.BypassUserPassword = true
case "lockout_sleep":
bootFlags.LockoutSleepButton = true
case "cons_redirect=default":
bootFlags.ConsoleRedirectionControl = ConsoleRedirectionControl_Default
case "cons_redirect=skip":
bootFlags.ConsoleRedirectionControl = ConsoleRedirectionControl_Skip
case "cons_redirect=enable":
bootFlags.ConsoleRedirectionControl = ConsoleRedirectionControl_Enable
default:
return fmt.Errorf("unsupported boot flag option, supported options: \n%s", bootFlags.OptionsHelp())
}
}
return nil
}
type BootOptionParam_BootInitiatorInfo struct {
ChannelNumber uint8
SessionID uint32
BootInfoTimestamp time.Time
}
func (p *BootOptionParam_BootInitiatorInfo) BootOptionParameter() (paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8) {
return BootOptionParamSelector_BootInitiatorInfo, 0, 0
}
func (p *BootOptionParam_BootInitiatorInfo) Format() string {
return fmt.Sprintf(`
Channel Number : %d
Session Id : %d
Timestamp : %s`, p.ChannelNumber, p.SessionID, p.BootInfoTimestamp)
}
func (p *BootOptionParam_BootInitiatorInfo) Pack() []byte {
out := make([]byte, 9)
packUint8(p.ChannelNumber, out, 0)
packUint32L(p.SessionID, out, 1)
ts := uint32(p.BootInfoTimestamp.Unix())
packUint32L(ts, out, 5)
return out
}
func (p *BootOptionParam_BootInitiatorInfo) Unpack(parameterData []byte) error {
if len(parameterData) != 9 {
return fmt.Errorf("the parameter data length must be 9 bytes")
}
p.ChannelNumber, _, _ = unpackUint8(parameterData, 0)
p.SessionID, _, _ = unpackUint32L(parameterData, 1)
ts, _, _ := unpackUint32L(parameterData, 5)
p.BootInfoTimestamp = parseTimestamp(ts)
return nil
}
type BootOptionParam_BootInitiatorMailbox struct {
SetSelector uint8
BlockData []byte
}
func (p *BootOptionParam_BootInitiatorMailbox) BootOptionParameter() (paramSelector BootOptionParamSelector, setSelector uint8, blockSelector uint8) {
return BootOptionParamSelector_BootInitiatorMailbox, 0, 0
}
func (p *BootOptionParam_BootInitiatorMailbox) Format() string {
return fmt.Sprintf(`
Selector : %d
Block Data : %02x
`, p.SetSelector, p.BlockData)
}
func (p *BootOptionParam_BootInitiatorMailbox) Pack() []byte {
out := make([]byte, 1+len(p.BlockData))
packUint8(p.SetSelector, out, 0)
packBytes(p.BlockData, out, 1)
return out
}
func (p *BootOptionParam_BootInitiatorMailbox) Unpack(parameterData []byte) error {
if len(parameterData) < 1 {
return fmt.Errorf("the parameter data length must be at least 1 bytes")
}
p.SetSelector, _, _ = unpackUint8(parameterData, 0)
p.BlockData, _, _ = unpackBytes(parameterData, 1, len(parameterData)-1)
return nil
}
golang-github-bougou-go-ipmi-0.7.2/types_channel.go 0000664 0000000 0000000 00000013422 14741105271 0022273 0 ustar 00root root 0000000 0000000 package ipmi
const (
// 0h-Bh,Fh = specific channel number
// Eh = retrieve information for channel this request was issued on
ChannelNumberSelf uint8 = 0x0e
)
type LUN uint8
// 7.2 BMC IPMB LUNs
const (
IPMB_LUN_BMC LUN = 0x00 // BMC commands and Event Request Messages
IPMB_LUN_OEM_1 LUN = 0x01 // OEM LUN 1
IPMB_LUN_SMS LUN = 0x10 // SMS Message LUN (Intended for messages to System Management Software)
IPMB_LUN_OEM_2 LUN = 0x11 // OEM LUN 2
// the least significant bit
// 0b (ID is a slave address)
// 1b (ID is a Software ID)
BMC_SA uint8 = 0x20 // BMC's responder address
RemoteConsole_SWID uint8 = 0x81 // Remote Console Software ID
)
// 6.3 Channel Numbers
// Only the channel number assignments for the primary IPMB and the System Interface are fixed,
// the assignment of other channel numbers can vary on a per-platform basis
type Channel uint8
const (
ChannelPrimaryIPMB Channel = 0x0
ChannelSystem Channel = 0xf
)
// 6.4 Channel Protocol Type
type ChannelProtocol uint8
const (
ChannelProtocolIPMB ChannelProtocol = 0x01
ChannelProtocolICMB ChannelProtocol = 0x02 // 03 reserved
ChannelProtocolSMBus ChannelProtocol = 0x04
ChannelProtocolKCS ChannelProtocol = 0x05
ChannelProtocolSMIC ChannelProtocol = 0x06
ChannelProtocolBTv10 ChannelProtocol = 0x07
ChannelProtocolBTv15 ChannelProtocol = 0x08
ChannelProtocolTMode ChannelProtocol = 0x09
ChannelProtocolOEM1 ChannelProtocol = 0x1c
ChannelProtocolOEM2 ChannelProtocol = 0x1d
ChannelProtocolOEM3 ChannelProtocol = 0x1e
ChannelProtocolOEM4 ChannelProtocol = 0x1f
)
func (cp ChannelProtocol) String() string {
m := map[ChannelProtocol]string{
0x01: "IPMB-1.0",
0x02: "ICMB-1.0",
0x04: "IPMI-SMBus",
0x05: "KCS",
0x06: "SMIC",
0x07: "BT-10",
0x08: "BT-15",
0x09: "TMode",
0x1c: "OEM Protocol 1",
0x1d: "OEM Protocol 2",
0x1e: "OEM Protocol 3",
0x1f: "OEM Protocol 4",
}
s, ok := m[cp]
if ok {
return s
}
return "reserved"
}
// 6.5 Channel Medium Type
type ChannelMedium uint8
const (
ChannelMediumIPMB ChannelMedium = 0x01
ChannelMediumICMBv10 ChannelMedium = 0x02
ChannelMediumICMBv09 ChannelMedium = 0x03
ChannelMediumLAN ChannelMedium = 0x04
ChannelMediumSerial ChannelMedium = 0x05
ChannelMediumOtherLAN ChannelMedium = 0x06
ChannelMediumSMBus ChannelMedium = 0x07
ChannelMediumSMBusv10 ChannelMedium = 0x08
ChannelMediumSMBusv20 ChannelMedium = 0x09
ChannelMediumUSBv1 ChannelMedium = 0x0a
ChannelMediumUSBv2 ChannelMedium = 0x0b
ChannelMediumSystemInterface ChannelMedium = 0x0c
)
func (cp ChannelMedium) String() string {
m := map[ChannelMedium]string{
0x01: "IPMB (I2C)",
0x02: "ICMB v1.0",
0x03: "ICMB v0.9",
0x04: "802.3 LAN",
0x05: "Asynch. Serial/Modem (RS-232)",
0x06: "Other LAN",
0x07: "PCI SMBus",
0x08: "SMBus v1.0/1.1",
0x09: "SMBus v2.0",
0x0a: "USB 1.x",
0x0b: "USB 2.x",
0x0c: "System Interface (KCS, SMIC, or BT)",
}
s, ok := m[cp]
if ok {
return s
}
if cp >= 0x60 && cp <= 0x7f {
return "OEM"
}
return "reserved"
}
// 6.8 Channel Privilege Levels
//
// - The `SetChannelAccess` command is used to set the maximum privilege level limit for a channel.
// - The `SetSessionPrivilegeLevel` Command is used to request the ability to perform operations
// at a particular privilege level.
// - The `SetSessionPrivilegeLevel` command can only be used to set privilege levels that are
// less than or equal to the privilege level limit for the entire channel,
// regardless of the privilege level of the user.
type PrivilegeLevel uint8
const (
PrivilegeLevelUnspecified PrivilegeLevel = 0x00
PrivilegeLevelCallback PrivilegeLevel = 0x01
PrivilegeLevelUser PrivilegeLevel = 0x02
PrivilegeLevelOperator PrivilegeLevel = 0x03
PrivilegeLevelAdministrator PrivilegeLevel = 0x04
PrivilegeLevelOEM PrivilegeLevel = 0x05
)
func (l PrivilegeLevel) Short() string {
// : X=Cipher Suite Unused
// : c=CALLBACK
// : u=USER
// : o=OPERATOR
// : a=ADMIN
// : O=OEM
m := map[PrivilegeLevel]string{
0x00: "X",
0x01: "c",
0x02: "u",
0x03: "o",
0x04: "a",
0x05: "O",
}
s, ok := m[l]
if ok {
return s
}
return "-"
}
func (l PrivilegeLevel) String() string {
m := map[PrivilegeLevel]string{
0x00: "Unspecified",
0x01: "CALLBACK",
0x02: "USER",
0x03: "OPERATOR",
0x04: "ADMINISTRATOR",
0x05: "OEM",
}
s, ok := m[l]
if ok {
return s
}
return "NO ACCESS"
}
func (l PrivilegeLevel) Symbol() string {
m := map[PrivilegeLevel]string{
0x00: "X",
0x01: "c",
0x02: "u",
0x03: "o",
0x04: "a",
0x05: "O",
}
s, ok := m[l]
if ok {
return s
}
return "-"
}
// see: Table 22-28, Get Channel Access Command
type ChannelAccessOption uint8
const (
ChannelAccessOption_NoChange ChannelAccessOption = 0
ChannelAccessOption_NonVolatile ChannelAccessOption = 1 // get non-volatile Channel Access
ChannelAccessOption_Volatile ChannelAccessOption = 2 // get present volatile (active) setting of Channel Access
)
// 6.6 Channel Access Modes
type ChannelAccessMode uint8
const (
ChannelAccessMode_Disabled ChannelAccessMode = 0
ChannelAccessMode_PrebootOnly ChannelAccessMode = 1
ChannelAccessMode_AlwaysAvailable ChannelAccessMode = 2
ChannelAccessMode_Shared ChannelAccessMode = 3
)
func (mode ChannelAccessMode) String() string {
m := map[ChannelAccessMode]string{
0: "disabled",
1: "pre-boot only",
2: "always available",
3: "shared",
}
s, ok := m[mode]
if ok {
return s
}
return ""
}
type ChannelPrivilegeOption uint8
const (
ChannelPrivilegeOption_NoChange ChannelPrivilegeOption = 0
ChannelPrivilegeOption_NonVolatile ChannelPrivilegeOption = 1
ChannelPrivilegeOption_Volatile ChannelPrivilegeOption = 2
)
golang-github-bougou-go-ipmi-0.7.2/types_cipher_suite_id.go 0000664 0000000 0000000 00000014605 14741105271 0024026 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
// 22.15.2 Cipher Suite IDs
type CipherSuiteID uint8
const (
CipherSuiteID0 CipherSuiteID = 0
CipherSuiteID1 CipherSuiteID = 1
CipherSuiteID2 CipherSuiteID = 2
CipherSuiteID3 CipherSuiteID = 3
CipherSuiteID4 CipherSuiteID = 4
CipherSuiteID5 CipherSuiteID = 5
CipherSuiteID6 CipherSuiteID = 6
CipherSuiteID7 CipherSuiteID = 7
CipherSuiteID8 CipherSuiteID = 8
CipherSuiteID9 CipherSuiteID = 9
CipherSuiteID10 CipherSuiteID = 10
CipherSuiteID11 CipherSuiteID = 11
CipherSuiteID12 CipherSuiteID = 12
CipherSuiteID13 CipherSuiteID = 13
CipherSuiteID14 CipherSuiteID = 14
CipherSuiteID15 CipherSuiteID = 15
CipherSuiteID16 CipherSuiteID = 16
CipherSuiteID17 CipherSuiteID = 17
CipherSuiteID18 CipherSuiteID = 18
CipherSuiteID19 CipherSuiteID = 19
CipherSuiteIDReserved CipherSuiteID = 0xff
)
const (
StandardCipherSuite uint8 = 0xc0
OEMCipherSuite uint8 = 0xc1
CipherAlgMask uint8 = 0x3f // [5:0]=111111b
CipherAlgTagBitMask uint8 = 0xc0 // [7:6]=11b
CipherAlgTagBitAuthMask uint8 = 0x00 // [7:6]=00b
CipherAlgTagBitIntegrityMask uint8 = 0x40 // [7:6]=01b
CipherAlgTagBitEncryptionMask uint8 = 0x80 // [7:6]=10b
LIST_ALGORITHMS_BY_CIPHER_SUITE uint8 = 0x80
)
// getCipherSuiteAlgorithms returns AuthAlg, IntegrityAlg and CryptAlg of the specified cipherSuiteID.
func getCipherSuiteAlgorithms(cipherSuiteID CipherSuiteID) (authAlg AuthAlg, integrity IntegrityAlg, encryptionAlg CryptAlg, err error) {
switch cipherSuiteID {
case CipherSuiteID0:
return AuthAlgRAKP_None, IntegrityAlg_None, CryptAlg_None, nil
case CipherSuiteID1:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_None, CryptAlg_None, nil
case CipherSuiteID2:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_HMAC_SHA1_96, CryptAlg_None, nil
case CipherSuiteID3:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_HMAC_SHA1_96, CryptAlg_AES_CBC_128, nil
case CipherSuiteID4:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_HMAC_SHA1_96, CryptAlg_xRC4_128, nil
case CipherSuiteID5:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_HMAC_SHA1_96, CryptAlg_xRC4_40, nil
case CipherSuiteID6:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_None, CryptAlg_None, nil
case CipherSuiteID7:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_HMAC_MD5_128, CryptAlg_None, nil
case CipherSuiteID8:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_HMAC_MD5_128, CryptAlg_AES_CBC_128, nil
case CipherSuiteID9:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_HMAC_MD5_128, CryptAlg_xRC4_128, nil
case CipherSuiteID10:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_HMAC_MD5_128, CryptAlg_xRC4_40, nil
case CipherSuiteID11:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_MD5_128, CryptAlg_None, nil
case CipherSuiteID12:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_MD5_128, CryptAlg_AES_CBC_128, nil
case CipherSuiteID13:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_MD5_128, CryptAlg_xRC4_128, nil
case CipherSuiteID14:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_MD5_128, CryptAlg_xRC4_40, nil
case CipherSuiteID15:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_None, CryptAlg_None, nil
case CipherSuiteID16:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_HMAC_SHA256_128, CryptAlg_None, nil
case CipherSuiteID17:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_HMAC_SHA256_128, CryptAlg_AES_CBC_128, nil
case CipherSuiteID18:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_HMAC_SHA256_128, CryptAlg_xRC4_128, nil
case CipherSuiteID19:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_HMAC_SHA256_128, CryptAlg_xRC4_40, nil
case CipherSuiteIDReserved:
return 0, 0, 0, nil
default:
return 0, 0, 0, nil
}
}
// 22.15.1 Cipher Suite Records
// The size of a CipherSuiteRecord is
type CipherSuiteRecord struct {
// If StartOfRecord is C0h, indicating that the Start Of Record byte is followed by an Cipher Suite ID
// If StartOfRecord is C1h, indicating that the Start Of Record byte is followed by a OEM Cipher Suite ID plus OEM IANA
StartOfRecord uint8
// a numeric way of identifying the Cipher Suite on the platform
CipherSuitID CipherSuiteID
OEMIanaID uint32 // Least significant byte first. 3-byte IANA for the OEM or body that defined the Cipher Suite.
// an authentication algorithm number is required for all Cipher Suites.
// It is possible that a given Cipher Suite may not specify use of an integrity or confidentiality algorithm.
AuthAlg uint8 // Tag bits: [7:6]=00b
IntegrityAlgs []uint8 // Tag bits: [7:6]=01b
CryptAlgs []uint8 // Tag bits: [7:6]=10b
}
func (c *Client) findBestCipherSuites(ctx context.Context) []CipherSuiteID {
cipherSuiteRecords, err := c.GetAllChannelCipherSuites(ctx, ChannelNumberSelf)
if err != nil {
return preferredCiphers
}
cipherSuiteIDs := make([]CipherSuiteID, len(cipherSuiteRecords))
for i, cipherSuiteRecord := range cipherSuiteRecords {
cipherSuiteIDs[i] = cipherSuiteRecord.CipherSuitID
}
return sortCipherSuites(cipherSuiteIDs)
}
// sortCipherSuites return cipher suites in order of preference.
// the cipher suite not in the preferredCiphers list would be excluded.
func sortCipherSuites(cipherSuites []CipherSuiteID) []CipherSuiteID {
sorted := make([]CipherSuiteID, 0)
for _, preferredCipher := range preferredCiphers {
for _, cipherSuiteID := range cipherSuites {
if preferredCipher == cipherSuiteID {
sorted = append(sorted, cipherSuiteID)
}
}
}
return sorted
}
var preferredCiphers = []CipherSuiteID{
// Todo
// cipher suite best order is chosen with this criteria:
// xRC4 is bad
// AES128 is required
// HMAC-SHA256 > HMAC-SHA1
// secure authentication > encrypted content
// With xRC4 out, all cipher suites with MD5 out, and cipher suite 3
// being required by the spec, the only better defined standard cipher
// suite is 17. So if SHA256 is available, we should try to use that,
// otherwise, fall back to 3.
CipherSuiteID17,
// IPMI 2.0 spec requires that cipher suite 3 is implemented
// so we should always be able to fall back to that if better
// options are not available.
// CipherSuiteID3 -> 01h, 01h, 01h
CipherSuiteID3,
CipherSuiteID15,
CipherSuiteID16,
CipherSuiteID18,
CipherSuiteID19,
CipherSuiteID6,
CipherSuiteID7,
CipherSuiteID8,
CipherSuiteID11,
CipherSuiteID12,
// xRC4 is bad, so we don't use it
// CipherSuiteID4,
// CipherSuiteID5,
// CipherSuiteID9,
// CipherSuiteID10,
// CipherSuiteID13,
// CipherSuiteID14,
}
golang-github-bougou-go-ipmi-0.7.2/types_command.go 0000664 0000000 0000000 00000060207 14741105271 0022304 0 ustar 00root root 0000000 0000000 package ipmi
// Command is the field in an IPMI message
type Command struct {
ID uint8
NetFn NetFn
Name string
}
type Request interface {
// Pack encodes the object to data bytes
Pack() []byte
// Command return the IPMI command info (NetFn/Cmd).
// All IPMI specification specified commands are already predefined in this file.
Command() Command
}
type Response interface {
// Unpack decodes the object from data bytes
Unpack(data []byte) error
// CompletionCodes returns a map of command-specific completion codes
CompletionCodes() map[uint8]string
// Format return a formatted human friendly string
Format() string
}
type Parameter interface {
Pack() []byte
Unpack(paramData []byte) error
Format() string
}
// ResponseError encapsulate the CompletionCode of IPMI Response Msg
// alongside with error description.
type ResponseError struct {
completionCode CompletionCode
description string
}
// Error implements the error interface
func (e *ResponseError) Error() string {
return e.description
}
func (e *ResponseError) CompletionCode() CompletionCode {
return e.completionCode
}
// Appendix G - Command Assignments
// Command Number Assignments (Appendix G, table G-1)
var (
// a faked command for RAKP messages
CommandNone = Command{}
// IPM Device Global Commands
CommandGetDeviceID = Command{ID: 0x01, NetFn: NetFnAppRequest, Name: "Get Device ID"}
CommandColdReset = Command{ID: 0x02, NetFn: NetFnAppRequest, Name: "Cold Reset"}
CommandWarmReset = Command{ID: 0x03, NetFn: NetFnAppRequest, Name: "Warm Reset"}
CommandGetSelfTestResults = Command{ID: 0x04, NetFn: NetFnAppRequest, Name: "Get Self Test Results"}
CommandManufacturingTestOn = Command{ID: 0x05, NetFn: NetFnAppRequest, Name: "Manufacturing Test On"}
CommandSetACPIPowerState = Command{ID: 0x06, NetFn: NetFnAppRequest, Name: "Set ACPI Power State"}
CommandGetACPIPowerState = Command{ID: 0x07, NetFn: NetFnAppRequest, Name: "Get ACPI Power State"}
CommandGetDeviceGUID = Command{ID: 0x08, NetFn: NetFnAppRequest, Name: "Get Device GUID"}
CommandGetNetFnSupport = Command{ID: 0x09, NetFn: NetFnAppRequest, Name: "Get NetFn Support"}
CommandGetCommandSupport = Command{ID: 0x0a, NetFn: NetFnAppRequest, Name: "Get Command Support"}
CommandGetCommandSubfunctionSupport = Command{ID: 0x0b, NetFn: NetFnAppRequest, Name: "Get Command Sub-function Support"}
CommandGetConfigurableCommands = Command{ID: 0x0c, NetFn: NetFnAppRequest, Name: "Get Configurable Commands"}
CommandGetConfigurableCommandSubfunctions = Command{ID: 0x0d, NetFn: NetFnAppRequest, Name: "Get Configurable Command Sub-functions"} // 0Eh - 0Fh reserved
CommandSetCommandEnables = Command{ID: 0x60, NetFn: NetFnAppRequest, Name: "Set Command Enables"}
CommandGetCommandEnables = Command{ID: 0x61, NetFn: NetFnAppRequest, Name: "Get Command Enables"}
CommandSetCommandSubfunctionsEnables = Command{ID: 0x62, NetFn: NetFnAppRequest, Name: "Set Command Sub-function Enables"}
CommandGetCommandSubfunctionsEnables = Command{ID: 0x63, NetFn: NetFnAppRequest, Name: "Get Command Sub-function Enables"}
CommandGetOEMNetFnIanaSupport = Command{ID: 0x64, NetFn: NetFnAppRequest, Name: "Get OEM NetFn IANA Support"}
// BMC Watchdog Timer Commands
CommandResetWatchdogTimer = Command{ID: 0x22, NetFn: NetFnAppRequest, Name: "Reset Watchdog Timer"}
CommandSetWatchdogTimer = Command{ID: 0x24, NetFn: NetFnAppRequest, Name: "Set Watchdog Timer"}
CommandGetWatchdogTimer = Command{ID: 0x25, NetFn: NetFnAppRequest, Name: "Get Watchdog Timer"}
// BMC Device and Messaging Commands
CommandSetBMCGlobalEnables = Command{ID: 0x2e, NetFn: NetFnAppRequest, Name: "Set BMC Global Enables"}
CommandGetBMCGlobalEnables = Command{ID: 0x2f, NetFn: NetFnAppRequest, Name: "Get BMC Global Enables"}
CommandClearMessageFlags = Command{ID: 0x30, NetFn: NetFnAppRequest, Name: "Clear Message Flags"}
CommandGetMessageFlags = Command{ID: 0x31, NetFn: NetFnAppRequest, Name: "Get Message Flags"}
CommandEnableMessageChannelReceive = Command{ID: 0x32, NetFn: NetFnAppRequest, Name: "Enable Message Channel Receive"}
CommandGetMessage = Command{ID: 0x33, NetFn: NetFnAppRequest, Name: "Get Message"}
CommandSendMessage = Command{ID: 0x34, NetFn: NetFnAppRequest, Name: "Send Message"}
CommandReadEventMessageBuffer = Command{ID: 0x35, NetFn: NetFnAppRequest, Name: "Read Event Message Buffer"}
CommandGetBTInterfaceCapabilities = Command{ID: 0x36, NetFn: NetFnAppRequest, Name: "Get BT Interface Capabilities"}
CommandGetSystemGUID = Command{ID: 0x37, NetFn: NetFnAppRequest, Name: "Get System GUID"}
CommandSetSystemInfoParam = Command{ID: 0x58, NetFn: NetFnAppRequest, Name: "Set System Info Param"}
CommandGetSystemInfoParam = Command{ID: 0x59, NetFn: NetFnAppRequest, Name: "Get System Info Param"}
CommandGetChannelAuthCapabilities = Command{ID: 0x38, NetFn: NetFnAppRequest, Name: "Get Channel Authentication Capabilities"}
CommandGetSessionChallenge = Command{ID: 0x39, NetFn: NetFnAppRequest, Name: "Get Session Challenge"}
CommandActivateSession = Command{ID: 0x3a, NetFn: NetFnAppRequest, Name: "Activate Session"}
CommandSetSessionPrivilegeLevel = Command{ID: 0x3b, NetFn: NetFnAppRequest, Name: "Set Session Privilege Level"}
CommandCloseSession = Command{ID: 0x3c, NetFn: NetFnAppRequest, Name: "Close Session"}
CommandGetSessionInfo = Command{ID: 0x3d, NetFn: NetFnAppRequest, Name: "Get Session Info"} // 3e unassigned
CommandGetAuthCode = Command{ID: 0x3f, NetFn: NetFnAppRequest, Name: "Get AuthCode"}
CommandSetChannelAccess = Command{ID: 0x40, NetFn: NetFnAppRequest, Name: "Set Channel Access"}
CommandGetChannelAccess = Command{ID: 0x41, NetFn: NetFnAppRequest, Name: "Get Channel Access"}
CommandGetChannelInfo = Command{ID: 0x42, NetFn: NetFnAppRequest, Name: "Get Channel Info Command"}
CommandSetUserAccess = Command{ID: 0x43, NetFn: NetFnAppRequest, Name: "Set User Access Command"}
CommandGetUserAccess = Command{ID: 0x44, NetFn: NetFnAppRequest, Name: "Get User Access Command"}
CommandSetUsername = Command{ID: 0x45, NetFn: NetFnAppRequest, Name: "Set User Name"}
CommandGetUsername = Command{ID: 0x46, NetFn: NetFnAppRequest, Name: "Get User Name Command"}
CommandSetUserPassword = Command{ID: 0x47, NetFn: NetFnAppRequest, Name: "Set User Password Command"}
CommandActivatePayload = Command{ID: 0x48, NetFn: NetFnAppRequest, Name: "Activate Payload"}
CommandDeactivatePayload = Command{ID: 0x49, NetFn: NetFnAppRequest, Name: "Deactivate Payload"}
CommandGetPayloadActivationStatus = Command{ID: 0x4a, NetFn: NetFnAppRequest, Name: "Get Payload Activation Status"}
CommandGetPayloadInstanceInfo = Command{ID: 0x4b, NetFn: NetFnAppRequest, Name: "Get Payload Instance Info"}
CommandSetUserPayloadAccess = Command{ID: 0x4c, NetFn: NetFnAppRequest, Name: "Set User Payload Access"}
CommandGetUserPayloadAccess = Command{ID: 0x4d, NetFn: NetFnAppRequest, Name: "Get User Payload Access"}
CommandGetChannelPayloadSupport = Command{ID: 0x4e, NetFn: NetFnAppRequest, Name: "Get Channel Payload Support"}
CommandGetChannelPayloadVersion = Command{ID: 0x4f, NetFn: NetFnAppRequest, Name: "Get Channel Payload Version"}
CommandGetChannelOEMPayloadInfo = Command{ID: 0x50, NetFn: NetFnAppRequest, Name: "Get Channel OEM Payload Info"} // 51 unassigned
CommandMasterWriteRead = Command{ID: 0x52, NetFn: NetFnAppRequest, Name: "Master Write-Read"} // 53 unassigned
CommandGetChannelCipherSuites = Command{ID: 0x54, NetFn: NetFnAppRequest, Name: "Get Channel Cipher Suites"}
CommandSuspendOrResumeEncryption = Command{ID: 0x55, NetFn: NetFnAppRequest, Name: "Suspend/Resume Payload Encryption"}
CommandSetChannelCipherSuites = Command{ID: 0x56, NetFn: NetFnAppRequest, Name: "Set Channel Security Keys"}
CommandGetSystemInterfaceCapabilities = Command{ID: 0x57, NetFn: NetFnAppRequest, Name: "Get System Interface Capabilities"}
// Chassis Device Commands
CommandGetChassisCapabilities = Command{ID: 0x00, NetFn: NetFnChassisRequest, Name: "Get Chassis Capabilities"}
CommandGetChassisStatus = Command{ID: 0x01, NetFn: NetFnChassisRequest, Name: "Get Chassis Status"}
CommandChassisControl = Command{ID: 0x02, NetFn: NetFnChassisRequest, Name: "Chassis Control"}
CommandChassisReset = Command{ID: 0x03, NetFn: NetFnChassisRequest, Name: "Chassis Reset"}
CommandChassisIdentify = Command{ID: 0x04, NetFn: NetFnChassisRequest, Name: "Chassis Identify"}
CommandSetChassisCapabilities = Command{ID: 0x05, NetFn: NetFnChassisRequest, Name: "Set Chassis Capabilities"}
CommandSetPowerRestorePolicy = Command{ID: 0x06, NetFn: NetFnChassisRequest, Name: "Set Power Restore Policy"}
CommandGetSystemRestartCause = Command{ID: 0x07, NetFn: NetFnChassisRequest, Name: "Get System Restart Cause"}
CommandSetSystemBootOptions = Command{ID: 0x08, NetFn: NetFnChassisRequest, Name: "Set System Boot Options"}
CommandGetSystemBootOptions = Command{ID: 0x09, NetFn: NetFnChassisRequest, Name: "Get System Boot Options"}
CommandSetFrontPanelEnables = Command{ID: 0x0a, NetFn: NetFnChassisRequest, Name: "Set Front Panel Button Enables"}
CommandSetPowerCycleInterval = Command{ID: 0x0b, NetFn: NetFnChassisRequest, Name: "Set Power Cycle Interval"} // 0ch -0eh unassigned
CommandGetPOHCounter = Command{ID: 0x0f, NetFn: NetFnChassisRequest, Name: "Get POH Counter"}
// Event Commands
CommandSetEventReceiver = Command{ID: 0x00, NetFn: NetFnSensorEventRequest, Name: "Set Event Receiver"}
CommandGetEventReceiver = Command{ID: 0x01, NetFn: NetFnSensorEventRequest, Name: "Get Event Receiver"}
CommandPlatformEventMessage = Command{ID: 0x02, NetFn: NetFnSensorEventRequest, Name: "Platform Event (Event Message)"} // 03h -0fh unassigned
// PEF and Alerting Commands
CommandGetPEFCapabilities = Command{ID: 0x10, NetFn: NetFnSensorEventRequest, Name: "Get PEF Capabilities"}
CommandArmPEFPostponeTimer = Command{ID: 0x11, NetFn: NetFnSensorEventRequest, Name: "Arm PEF Postpone Timer"}
CommandSetPEFConfigParam = Command{ID: 0x12, NetFn: NetFnSensorEventRequest, Name: "Set PEF Configuration Param"}
CommandGetPEFConfigParam = Command{ID: 0x13, NetFn: NetFnSensorEventRequest, Name: "Get PEF Configuration Param"}
CommandSetLastProcessedEventId = Command{ID: 0x14, NetFn: NetFnSensorEventRequest, Name: "Set Last Processed Event ID"}
CommandGetLastProcessedEventId = Command{ID: 0x15, NetFn: NetFnSensorEventRequest, Name: "Get Last Processed Event ID"}
CommandAlertImmediate = Command{ID: 0x16, NetFn: NetFnSensorEventRequest, Name: "Alert Immediate"}
CommandPETAcknowledge = Command{ID: 0x17, NetFn: NetFnSensorEventRequest, Name: "PET Acknowledge"}
// Sensor Device Commands
CommandGetDeviceSDRInfo = Command{ID: 0x20, NetFn: NetFnSensorEventRequest, Name: "Get Device SDR Info"}
CommandGetDeviceSDR = Command{ID: 0x21, NetFn: NetFnSensorEventRequest, Name: "Get Device SDR"}
CommandReserveDeviceSDRRepo = Command{ID: 0x22, NetFn: NetFnSensorEventRequest, Name: "Reserve Device SDR Repository"}
CommandGetSensorReadingFactors = Command{ID: 0x23, NetFn: NetFnSensorEventRequest, Name: "Get Sensor Reading Factors"}
CommandSetSensorHysteresis = Command{ID: 0x24, NetFn: NetFnSensorEventRequest, Name: "Set Sensor Hysteresis"}
CommandGetSensorHysteresis = Command{ID: 0x25, NetFn: NetFnSensorEventRequest, Name: "Get Sensor Hysteresis"}
CommandSetSensorThresholds = Command{ID: 0x26, NetFn: NetFnSensorEventRequest, Name: "Set Sensor Threshold"}
CommandGetSensorThresholds = Command{ID: 0x27, NetFn: NetFnSensorEventRequest, Name: "Get Sensor Threshold"}
CommandSetSensorEventEnable = Command{ID: 0x28, NetFn: NetFnSensorEventRequest, Name: "Set Sensor Event Enable"}
CommandGetSensorEventEnable = Command{ID: 0x29, NetFn: NetFnSensorEventRequest, Name: "Get Sensor Event Enable"}
CommandRearmSensorEvents = Command{ID: 0x2a, NetFn: NetFnSensorEventRequest, Name: "Re-arm Sensor Events"}
CommandGetSensorEventStatus = Command{ID: 0x2b, NetFn: NetFnSensorEventRequest, Name: "Get Sensor Event Status"} // no 2c
CommandGetSensorReading = Command{ID: 0x2d, NetFn: NetFnSensorEventRequest, Name: "Get Sensor Reading"}
CommandSetSensorType = Command{ID: 0x2e, NetFn: NetFnSensorEventRequest, Name: "Set Sensor Type"}
CommandGetSensorType = Command{ID: 0x2f, NetFn: NetFnSensorEventRequest, Name: "Get Sensor Type"}
CommandSetSensorReadingAndEventStatus = Command{ID: 0x30, NetFn: NetFnSensorEventRequest, Name: "Set Sensor Reading And Event Status"}
// FRU Device Commands
CommandGetFRUInventoryAreaInfo = Command{ID: 0x10, NetFn: NetFnStorageRequest, Name: "Get FRU Inventory Area Info"}
CommandReadFRUData = Command{ID: 0x11, NetFn: NetFnStorageRequest, Name: "Read FRU Data"}
CommandWriteFRUData = Command{ID: 0x12, NetFn: NetFnStorageRequest, Name: "Write FRU Data"}
// SDR Device Commands
CommandGetSDRRepoInfo = Command{ID: 0x20, NetFn: NetFnStorageRequest, Name: "Get SDR Repository Info"}
CommandGetSDRRepoAllocInfo = Command{ID: 0x21, NetFn: NetFnStorageRequest, Name: "Get SDR Repository Allocation Info"}
CommandReserveSDRRepo = Command{ID: 0x22, NetFn: NetFnStorageRequest, Name: "Reserve SDR Repository"}
CommandGetSDR = Command{ID: 0x23, NetFn: NetFnStorageRequest, Name: "Get SDR"}
CommandAddSDR = Command{ID: 0x24, NetFn: NetFnStorageRequest, Name: "Add SDR"}
CommandPartialAddSDR = Command{ID: 0x25, NetFn: NetFnStorageRequest, Name: "Partial Add SDR"}
CommandDeleteSDR = Command{ID: 0x26, NetFn: NetFnStorageRequest, Name: "Delete SDR"}
CommandClearSDRRepo = Command{ID: 0x27, NetFn: NetFnStorageRequest, Name: "Clear SDR Repository"}
CommandGetSDRRepoTime = Command{ID: 0x28, NetFn: NetFnStorageRequest, Name: "Get SDR Repository Time"}
CommandSetSDRRepoTime = Command{ID: 0x29, NetFn: NetFnStorageRequest, Name: "Set SDR Repository Time"}
CommandEnterSDRRepoUpdateMode = Command{ID: 0x2a, NetFn: NetFnStorageRequest, Name: "Enter SDR Repository Update Mode"}
CommandExitSDRRepoUpdateMode = Command{ID: 0x2b, NetFn: NetFnStorageRequest, Name: "Exit SDR Repository Update Mode"}
CommandRunInitializationAgent = Command{ID: 0x2c, NetFn: NetFnStorageRequest, Name: "Run Initialization Agent"}
// SEL Device Commands
CommandGetSELInfo = Command{ID: 0x40, NetFn: NetFnStorageRequest, Name: "Get SEL Info"}
CommandGetSELAllocInfo = Command{ID: 0x41, NetFn: NetFnStorageRequest, Name: "Get SEL Allocation Info"}
CommandReserveSEL = Command{ID: 0x42, NetFn: NetFnStorageRequest, Name: "Reserve SEL"}
CommandGetSELEntry = Command{ID: 0x43, NetFn: NetFnStorageRequest, Name: "Get SEL Entry"}
CommandAddSELEntry = Command{ID: 0x44, NetFn: NetFnStorageRequest, Name: "Add SEL Entry"}
CommandPartialAddSELEntry = Command{ID: 0x45, NetFn: NetFnStorageRequest, Name: "Partial Add SEL Entry"}
CommandDeleteSELEntry = Command{ID: 0x46, NetFn: NetFnStorageRequest, Name: "Delete SEL Entry"}
CommandClearSEL = Command{ID: 0x47, NetFn: NetFnStorageRequest, Name: "Clear SEL"}
CommandGetSELTime = Command{ID: 0x48, NetFn: NetFnStorageRequest, Name: "Get SEL Time"}
CommandSetSELTime = Command{ID: 0x49, NetFn: NetFnStorageRequest, Name: "Set SEL Time"}
CommandGetAuxLogStatus = Command{ID: 0x5a, NetFn: NetFnStorageRequest, Name: "Get Auxiliary Log Status"}
CommandSetAuxLogStatus = Command{ID: 0x5b, NetFn: NetFnStorageRequest, Name: "Set Auxiliary Log Status"}
CommandGetSELTimeUTCOffset = Command{ID: 0x5c, NetFn: NetFnStorageRequest, Name: "Get SEL Time UTC Offset"}
CommandSetSELTimeUTCOffset = Command{ID: 0x5d, NetFn: NetFnStorageRequest, Name: "Set SEL Time UTC Offset"}
// LAN Device Commands
CommandSetLanConfigParam = Command{ID: 0x01, NetFn: NetFnTransportRequest, Name: "Set LAN Configuration Param"}
CommandGetLanConfigParam = Command{ID: 0x02, NetFn: NetFnTransportRequest, Name: "Get LAN Configuration Param"}
CommandSuspendARPs = Command{ID: 0x03, NetFn: NetFnTransportRequest, Name: "Suspend BMC ARPs"}
CommandGetIPStatistics = Command{ID: 0x04, NetFn: NetFnTransportRequest, Name: "Get IP/UDP/RMCP Statistics"}
// Serial/Modem Device Commands
CommandSetSerialConfig = Command{ID: 0x10, NetFn: NetFnTransportRequest, Name: "Set Serial/Modem Configuration"}
CommandGetSerialConfig = Command{ID: 0x11, NetFn: NetFnTransportRequest, Name: "Get Serial/Modem Configuration"}
CommandSetSerialMux = Command{ID: 0x12, NetFn: NetFnTransportRequest, Name: "Set Serial/Modem Mux"}
CommandGetTapResponseCodes = Command{ID: 0x13, NetFn: NetFnTransportRequest, Name: "Get TAP Response Codes"}
CommandSetPPPTransmitData = Command{ID: 0x14, NetFn: NetFnTransportRequest, Name: "Set PPP UDP Proxy Transmit Data"}
CommandGetPPPTransmitData = Command{ID: 0x15, NetFn: NetFnTransportRequest, Name: "Get PPP UDP Proxy Transmit Data"}
CommandSendPPPPacket = Command{ID: 0x16, NetFn: NetFnTransportRequest, Name: "Send PPP UDP Proxy Packet"}
CommandGetPPPReceiveData = Command{ID: 0x17, NetFn: NetFnTransportRequest, Name: "Get PPP UDP Proxy Receive Data"}
CommandSerialConnectionActive = Command{ID: 0x18, NetFn: NetFnTransportRequest, Name: "Serial/Modem Connection Active"}
CommandCallback = Command{ID: 0x19, NetFn: NetFnTransportRequest, Name: "Callback"}
CommandSetUserCallbackOptions = Command{ID: 0x1a, NetFn: NetFnTransportRequest, Name: "Set User Callback Options"}
CommandGetUserCallbackOptions = Command{ID: 0x1b, NetFn: NetFnTransportRequest, Name: "Get User Callback Options"}
CommandSetSerialRoutingMux = Command{ID: 0x1c, NetFn: NetFnTransportRequest, Name: "Set Serial Routing Mux"}
CommandSOLActivating = Command{ID: 0x20, NetFn: NetFnTransportRequest, Name: "SOL Activating"}
CommandSetSOLConfigParam = Command{ID: 0x21, NetFn: NetFnTransportRequest, Name: "Set SOL Configuration Param"}
CommandGetSOLConfigParam = Command{ID: 0x22, NetFn: NetFnTransportRequest, Name: "Get SOL Configuration Param"}
// Command Forwarding Commands
CommandForwarded = Command{ID: 0x30, NetFn: NetFnTransportRequest, Name: "Forwarded Command"}
CommandSetForwarded = Command{ID: 0x31, NetFn: NetFnTransportRequest, Name: "Set Forwarded Commands"}
CommandGetForwarded = Command{ID: 0x32, NetFn: NetFnTransportRequest, Name: "Get Forwarded Commands"}
CommandEnableForwarded = Command{ID: 0x33, NetFn: NetFnTransportRequest, Name: "Enable Forwarded Commands"}
// Bridge Management Commands (ICMB)
CommandGetBridgeState = Command{ID: 0x00, NetFn: NetFnBridgeRequest, Name: "Get Bridge State"}
CommandSetBridgeState = Command{ID: 0x01, NetFn: NetFnBridgeRequest, Name: "Set Bridge State"}
CommandGetICMBAddress = Command{ID: 0x02, NetFn: NetFnBridgeRequest, Name: "Get ICMB Address"}
CommandSetICMBAddress = Command{ID: 0x03, NetFn: NetFnBridgeRequest, Name: "Set ICMB Address"}
CommandSetBridgeProxyAddress = Command{ID: 0x04, NetFn: NetFnBridgeRequest, Name: "Set Bridge ProxyAddress"}
CommandGetBridgeStatistics = Command{ID: 0x05, NetFn: NetFnBridgeRequest, Name: "Get Bridge Statistics"}
CommandGetICMBCapabilities = Command{ID: 0x06, NetFn: NetFnBridgeRequest, Name: "Get ICMB Capabilities"}
CommandClearBridgeStatistics = Command{ID: 0x08, NetFn: NetFnBridgeRequest, Name: "Clear Bridge Statistics"}
CommandGetBridgeProxyAddress = Command{ID: 0x09, NetFn: NetFnBridgeRequest, Name: "Get Bridge Proxy Address"}
CommandGetICMBConnectorInfo = Command{ID: 0x0a, NetFn: NetFnBridgeRequest, Name: "Get ICMB Connector Info"}
CommandGetICMBConnectionID = Command{ID: 0x0b, NetFn: NetFnBridgeRequest, Name: "Get ICMB Connection ID"}
CommandSendICMBConnectionID = Command{ID: 0x0c, NetFn: NetFnBridgeRequest, Name: "Send ICMB Connection ID"}
// Discovery Commands (ICMB)
CommandPrepareForDiscovery = Command{ID: 0x10, NetFn: NetFnBridgeRequest, Name: "Prepare For Discovery"}
CommandGetAddresses = Command{ID: 0x11, NetFn: NetFnBridgeRequest, Name: "Get Addresses"}
CommandSetDiscovered = Command{ID: 0x12, NetFn: NetFnBridgeRequest, Name: "Set Discovered"}
CommandGetChassisDeviceId = Command{ID: 0x13, NetFn: NetFnBridgeRequest, Name: "Get Chassis DeviceId"}
CommandSetChassisDeviceId = Command{ID: 0x14, NetFn: NetFnBridgeRequest, Name: "Set Chassis DeviceId"}
// Bridging Commands (ICMB)
CommandBridgeRequest = Command{ID: 0x20, NetFn: NetFnBridgeRequest, Name: "Bridge Request"}
CommandBridgeMessage = Command{ID: 0x21, NetFn: NetFnBridgeRequest, Name: "Bridge Message"}
// Event Commands (ICMB)
CommandGetEventCount = Command{ID: 0x30, NetFn: NetFnBridgeRequest, Name: "Get Event Count"}
CommandSetEventDestination = Command{ID: 0x31, NetFn: NetFnBridgeRequest, Name: "Set Event Destination"}
CommandSetEventReceptionState = Command{ID: 0x32, NetFn: NetFnBridgeRequest, Name: "Set Event Reception State"}
CommandSendICMBEventMessage = Command{ID: 0x33, NetFn: NetFnBridgeRequest, Name: "Send ICMB Event Message"}
CommandGetEventDestination = Command{ID: 0x34, NetFn: NetFnBridgeRequest, Name: "Get Event Destination"}
CommandGetEventReceptionState = Command{ID: 0x35, NetFn: NetFnBridgeRequest, Name: "Get Event Reception State"}
// OEM Commands for Bridge NetFn
// C0h-FEh
// Other Bridge Commands
CommandErrorReport = Command{ID: 0xff, NetFn: NetFnBridgeRequest, Name: "Error Report"}
// Intel DCMI extensions (https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/dcmi-v1-5-rev-spec.pdf)
CommandGetDCMICapParam = Command{ID: 0x01, NetFn: NetFnGroupExtensionRequest, Name: "Get DCMI Cap Param"}
CommandGetDCMIPowerReading = Command{ID: 0x02, NetFn: NetFnGroupExtensionRequest, Name: "Get DCMI Power Reading"}
CommandGetDCMIPowerLimit = Command{ID: 0x03, NetFn: NetFnGroupExtensionRequest, Name: "Get DCMI Power Limit"}
CommandSetDCMIPowerLimit = Command{ID: 0x04, NetFn: NetFnGroupExtensionRequest, Name: "Set DCMI Power Limit"}
CommandActivateDCMIPowerLimit = Command{ID: 0x05, NetFn: NetFnGroupExtensionRequest, Name: "Activate/Deactivate DCMI Power Limit"}
CommandGetDCMIAssetTag = Command{ID: 0x06, NetFn: NetFnGroupExtensionRequest, Name: "Get DCMI Asset Tag"}
CommandGetDCMISensorInfo = Command{ID: 0x07, NetFn: NetFnGroupExtensionRequest, Name: "Get DCMI Sensor Info"}
CommandSetDCMIAssetTag = Command{ID: 0x08, NetFn: NetFnGroupExtensionRequest, Name: "Set DCMI Asset Tag"}
CommandGetDCMIMgmtControllerIdentifier = Command{ID: 0x09, NetFn: NetFnGroupExtensionRequest, Name: "Get DCMI Management Controller Identifier String"}
CommandSetDCMIMgmtControllerIdentifier = Command{ID: 0x0A, NetFn: NetFnGroupExtensionRequest, Name: "Set DCMI Management Controller Identifier String"}
CommandSetDCMIThermalLimit = Command{ID: 0x0B, NetFn: NetFnGroupExtensionRequest, Name: "Set DCMI Thermal Limit"}
CommandGetDCMIThermalLimit = Command{ID: 0x0C, NetFn: NetFnGroupExtensionRequest, Name: "Get DCMI Thermal Limit"}
CommandGetDCMITemperatureReadings = Command{ID: 0x10, NetFn: NetFnGroupExtensionRequest, Name: "Get DCMI Temperature Readings"}
CommandSetDCMIConfigParam = Command{ID: 0x12, NetFn: NetFnGroupExtensionRequest, Name: "Set DCMI Configuration Param"}
CommandGetDCMIConfigParam = Command{ID: 0x13, NetFn: NetFnGroupExtensionRequest, Name: "Get DCMI Configuration Param"}
// Vendor Specific Commands
CommandGetSupermicroBiosVersion = Command{ID: 0xAC, NetFn: NetFnOEMSupermicroRequest, Name: "Get Supermicro BIOS Version"}
)
golang-github-bougou-go-ipmi-0.7.2/types_completion_code.go 0000664 0000000 0000000 00000006653 14741105271 0024036 0 ustar 00root root 0000000 0000000 package ipmi
type CompletionCode uint8
// 5.2 Table 5 for generic completion codes
const (
// GENERIC COMPLETION CODES 00h, C0h-FFh
CompletionCodeNormal CompletionCode = 0x00
CompletionCodeNodeBusy CompletionCode = 0xC0
CompletionCodeInvalidCommand CompletionCode = 0xC1
CompletionCodeInvalidCommandForLUN CompletionCode = 0xC2
CompletionCodeProcessTimeout CompletionCode = 0xC3
CompletionCodeOutOfSpace CompletionCode = 0xC4
CompletionCodeReservationCanceled CompletionCode = 0xC5
CompletionCodeRequestDataTruncated CompletionCode = 0xC6
CompletionCodeRequestDataLengthInvalid CompletionCode = 0xC7
CompletionCodeRequestDataLengthLimitExceeded CompletionCode = 0xC8
CompletionCodeParameterOutOfRange CompletionCode = 0xC9
CompletionCodeCannotReturnRequestedDataBytes CompletionCode = 0xCA
CompletionCodeRequestedDataNotPresent CompletionCode = 0xCB
CompletionCodeRequestDataFieldInvalid CompletionCode = 0xCC
CompletionCodeIllegalCommand CompletionCode = 0xCD
CompletionCodeCannotProvideResponse CompletionCode = 0xCE
CompletionCodeCannotExecuteDuplicatedRequest CompletionCode = 0xCF
CompletionCodeCannotProvideResponseSDRRInUpdate CompletionCode = 0xD0 // SDRR, SDR Repository
CompletionCodeCannotProvideResponseFirmwareUpdate CompletionCode = 0xD1
CompletionCodeCannotProvideResponseBMCInitialize CompletionCode = 0xD2
CompletionCodeDestinationUnavailable CompletionCode = 0xD3
CompletionCodeCannotExecuteCommandSecurityRestrict CompletionCode = 0xD4
CompletionCodeCannotExecuteCommandNotSupported CompletionCode = 0xD5
CompletionCodeCannotExecuteCommandSubFnDisabled CompletionCode = 0xD6
CompletionCodeUnspecifiedError CompletionCode = 0xFF
// DEVICE-SPECIFIC (OEM) CODES 01h-7Eh
// COMMAND-SPECIFIC CODES 80h-BEh
)
var CC = map[uint8]string{
0x00: "Command completed normally",
0xc0: "Node busy",
0xc1: "Invalid command",
0xc2: "Invalid command on LUN",
0xc3: "Timeout",
0xc4: "Out of space",
0xc5: "Reservation cancelled or invalid",
0xc6: "Request data truncated",
0xc7: "Request data length invalid",
0xc8: "Request data field length limit exceeded",
0xc9: "Parameter out of range",
0xca: "Cannot return number of requested data bytes",
0xcb: "Requested sensor, data, or record not found",
0xcc: "Invalid data field in request",
0xcd: "Command illegal for specified sensor or record type",
0xce: "Command response could not be provided",
0xcf: "Cannot execute duplicated request",
0xd0: "SDR Repository in update mode",
0xd1: "Device firmware in update mode",
0xd2: "BMC initialization in progress",
0xd3: "Destination unavailable",
0xd4: "Cannot execute command, insufficient privilege level or other security-based restriction",
0xd5: "Cannot execute command, command or request parameters not supported in present state",
0xd6: "Cannot execute command, command disabled or is unavailable",
0xff: "Unspecified error",
}
// String return description of global completion code.
// Please use StrCC function to get description for any completion code
// returned for specific command response.
func (cc CompletionCode) String() string {
if s, ok := CC[uint8(cc)]; ok {
return s
}
return ""
}
golang-github-bougou-go-ipmi-0.7.2/types_dcmi.go 0000664 0000000 0000000 00000001230 14741105271 0021571 0 ustar 00root root 0000000 0000000 package ipmi
// [DCMI specification v1.5]: 6.6.3 Set Power Limit
// Exception Actions, taken if the Power Limit is exceeded and cannot be controlled within the Correction Time Limit
type DCMIExceptionAction uint8
const (
DCMIExceptionAction_NoAction DCMIExceptionAction = 0x00
DCMIExceptionAction_PowerOffAndLogSEL DCMIExceptionAction = 0x01
DCMIExceptionAction_LogSEL DCMIExceptionAction = 0x11
)
func (a DCMIExceptionAction) String() string {
m := map[DCMIExceptionAction]string{
0x00: "No Action",
0x01: "Hard Power Off & Log Event to SEL",
0x11: "Log Event to SEL",
}
s, ok := m[a]
if ok {
return s
}
return "unknown"
}
golang-github-bougou-go-ipmi-0.7.2/types_dcmi_cap_params.go 0000664 0000000 0000000 00000027150 14741105271 0023770 0 ustar 00root root 0000000 0000000 package ipmi
import (
"fmt"
)
type DCMICapParameter interface {
DCMICapParameter() DCMICapParamSelector
Parameter
}
var (
_ DCMICapParameter = (*DCMICapParam_SupportedDCMICapabilities)(nil)
_ DCMICapParameter = (*DCMICapParam_MandatoryPlatformAttributes)(nil)
_ DCMICapParameter = (*DCMICapParam_OptionalPlatformAttributes)(nil)
_ DCMICapParameter = (*DCMICapParam_ManageabilityAccessAttributes)(nil)
_ DCMICapParameter = (*DCMICapParam_EnhancedSystemPowerStatisticsAttributes)(nil)
)
func isNilDCMICapParameter(param DCMICapParameter) bool {
switch v := param.(type) {
case *DCMICapParam_SupportedDCMICapabilities:
return v == nil
case *DCMICapParam_MandatoryPlatformAttributes:
return v == nil
case *DCMICapParam_OptionalPlatformAttributes:
return v == nil
case *DCMICapParam_ManageabilityAccessAttributes:
return v == nil
case *DCMICapParam_EnhancedSystemPowerStatisticsAttributes:
return v == nil
default:
return false
}
}
type DCMICapParamSelector uint8
const (
DCMICapParamSelector_SupportedDCMICapabilities = DCMICapParamSelector(0x01)
DCMICapParamSelector_MandatoryPlatformAttributes = DCMICapParamSelector(0x02)
DCMICapParamSelector_OptionalPlatformAttributes = DCMICapParamSelector(0x03)
DCMICapParamSelector_ManageabilityAccessAttributes = DCMICapParamSelector(0x04)
DCMICapParamSelector_EnhancedSystemPowerStatisticsAttributes = DCMICapParamSelector(0x05)
)
func (dcmiCapParamSelector DCMICapParamSelector) String() string {
m := map[DCMICapParamSelector]string{
DCMICapParamSelector_SupportedDCMICapabilities: "Supported DCMI capabilities",
DCMICapParamSelector_MandatoryPlatformAttributes: "Mandatory platform attributes",
DCMICapParamSelector_OptionalPlatformAttributes: "Optional platform attributes",
DCMICapParamSelector_ManageabilityAccessAttributes: "Manageability access attributes",
DCMICapParamSelector_EnhancedSystemPowerStatisticsAttributes: "Enhanced system power statistics attributes",
}
s, ok := m[dcmiCapParamSelector]
if ok {
return s
}
return "Unknown"
}
type DCMICapParams struct {
SupportedDCMICapabilities *DCMICapParam_SupportedDCMICapabilities
MandatoryPlatformAttributes *DCMICapParam_MandatoryPlatformAttributes
OptionalPlatformAttributes *DCMICapParam_OptionalPlatformAttributes
ManageabilityAccessAttributes *DCMICapParam_ManageabilityAccessAttributes
EnhancedSystemPowerStatisticsAttributes *DCMICapParam_EnhancedSystemPowerStatisticsAttributes
}
func (dcmiCapParams *DCMICapParams) Format() string {
format := func(param DCMICapParameter) string {
if isNilDCMICapParameter(param) {
return ""
}
paramSelector := param.DCMICapParameter()
content := param.Format()
if content[len(content)-1] != '\n' {
content += "\n"
}
content += "\n"
return fmt.Sprintf("[%02d] %-44s: %s", paramSelector, paramSelector.String(), content)
}
out := ""
out += format(dcmiCapParams.SupportedDCMICapabilities)
out += format(dcmiCapParams.MandatoryPlatformAttributes)
out += format(dcmiCapParams.OptionalPlatformAttributes)
out += format(dcmiCapParams.ManageabilityAccessAttributes)
out += format(dcmiCapParams.EnhancedSystemPowerStatisticsAttributes)
return out
}
type DCMICapParam_SupportedDCMICapabilities struct {
SupportPowerManagement bool
SupportInBandKCS bool
SupportOutOfBandSerial bool
SupportOutOfBandLAN bool
}
func (param *DCMICapParam_SupportedDCMICapabilities) DCMICapParameter() DCMICapParamSelector {
return DCMICapParamSelector_SupportedDCMICapabilities
}
func (param *DCMICapParam_SupportedDCMICapabilities) Pack() []byte {
return []byte{}
}
func (param *DCMICapParam_SupportedDCMICapabilities) Unpack(paramData []byte) error {
if len(paramData) < 3 {
return ErrUnpackedDataTooShortWith(len(paramData), 3)
}
param.SupportPowerManagement = isBit0Set(paramData[1])
param.SupportInBandKCS = isBit0Set(paramData[2])
param.SupportOutOfBandSerial = isBit1Set(paramData[2])
param.SupportOutOfBandLAN = isBit2Set(paramData[2])
return nil
}
func (param *DCMICapParam_SupportedDCMICapabilities) Format() string {
return fmt.Sprintf(`
Optional platform capabilities
Power management (%s)
Manageability access capabilities
In-band KCS channel (%s)
Out-of-band serial TMODE (%s)
Out-of-band secondary LAN channel (%s)
`,
formatBool(param.SupportPowerManagement, "available", "unavailable"),
formatBool(param.SupportInBandKCS, "available", "unavailable"),
formatBool(param.SupportOutOfBandSerial, "available", "unavailable"),
formatBool(param.SupportOutOfBandLAN, "available", "unavailable"),
)
}
type DCMICapParam_MandatoryPlatformAttributes struct {
SELAutoRolloverEnabled bool
EntireSELFlushUponRollOver bool
RecordLevelSELFlushUponRollOver bool
SELEntriesCount uint16 //only 12 bits, [11-0] Number of SEL entries (Maximum 4096)
TemperatrureSamplingFrequencySec uint8
}
func (param *DCMICapParam_MandatoryPlatformAttributes) DCMICapParameter() DCMICapParamSelector {
return DCMICapParamSelector_MandatoryPlatformAttributes
}
func (param *DCMICapParam_MandatoryPlatformAttributes) Pack() []byte {
out := make([]byte, 5)
// byte 0 and byte 1
out[0] = byte(param.SELEntriesCount) & 0xFF
var b1 uint8
b1 = setOrClearBit7(b1, param.SELAutoRolloverEnabled)
b1 = setOrClearBit6(b1, param.EntireSELFlushUponRollOver)
b1 = setOrClearBit5(b1, param.RecordLevelSELFlushUponRollOver)
out[1] = b1 | (byte(param.SELEntriesCount>>8) & 0x0F)
// byte 2 and byte 3 is reserved
out[4] = param.TemperatrureSamplingFrequencySec
return out
}
func (param *DCMICapParam_MandatoryPlatformAttributes) Unpack(paramData []byte) error {
if len(paramData) < 5 {
return ErrUnpackedDataTooShortWith(len(paramData), 5)
}
// byte 0 and byte 1
b_0_1, _, _ := unpackUint16L(paramData, 0)
param.SELEntriesCount = b_0_1 & 0x0FFF
b1 := paramData[1]
param.SELAutoRolloverEnabled = isBit7Set(b1)
param.EntireSELFlushUponRollOver = isBit6Set(b1)
param.RecordLevelSELFlushUponRollOver = isBit5Set(b1)
// byte 2 and byte 3 is reserved
param.TemperatrureSamplingFrequencySec = paramData[4]
return nil
}
func (param *DCMICapParam_MandatoryPlatformAttributes) Format() string {
return fmt.Sprintf(`
SEL Attributes:
SEL automatic rollover is (%s)
%d SEL entries
Identification Attributes:
Temperature Monitoring Attributes:
Temperature sampling frequency is %d seconds
`,
formatBool(param.SELAutoRolloverEnabled, "enabled", "disabled"),
param.SELEntriesCount,
param.TemperatrureSamplingFrequencySec,
)
}
type DCMICapParam_OptionalPlatformAttributes struct {
PowerMgmtDeviceSlaveAddr uint8
PewerMgmtControllerChannelNumber uint8
DeviceRevision uint8
}
func (param *DCMICapParam_OptionalPlatformAttributes) DCMICapParameter() DCMICapParamSelector {
return DCMICapParamSelector_OptionalPlatformAttributes
}
func (param *DCMICapParam_OptionalPlatformAttributes) Pack() []byte {
out := make([]byte, 2)
out[0] = param.PowerMgmtDeviceSlaveAddr
out[1] = (param.PewerMgmtControllerChannelNumber & 0xF0) | (param.DeviceRevision & 0x0F)
return out
}
func (param *DCMICapParam_OptionalPlatformAttributes) Unpack(paramData []byte) error {
if len(paramData) < 2 {
return ErrUnpackedDataTooShortWith(len(paramData), 3)
}
param.PowerMgmtDeviceSlaveAddr = paramData[0]
param.PewerMgmtControllerChannelNumber = paramData[1] & 0xF0
param.DeviceRevision = paramData[1] & 0x0F
return nil
}
func (param *DCMICapParam_OptionalPlatformAttributes) Format() string {
return fmt.Sprintf(`
Power Management:
Slave address of device : %#02x
Channel number is : %#02x %s
Device revision is : %d
`,
param.PowerMgmtDeviceSlaveAddr,
param.PewerMgmtControllerChannelNumber,
formatBool(param.PewerMgmtControllerChannelNumber == 0, "(Primary BMC)", ""),
param.DeviceRevision,
)
}
type DCMICapParam_ManageabilityAccessAttributes struct {
PrimaryLANChannelNumber uint8
SecondaryLANChannelNumber uint8
SerialChannelNumber uint8
}
func (param *DCMICapParam_ManageabilityAccessAttributes) DCMICapParameter() DCMICapParamSelector {
return DCMICapParamSelector_ManageabilityAccessAttributes
}
func (param *DCMICapParam_ManageabilityAccessAttributes) Pack() []byte {
return []byte{
param.PrimaryLANChannelNumber,
param.SecondaryLANChannelNumber,
param.SerialChannelNumber,
}
}
func (param *DCMICapParam_ManageabilityAccessAttributes) Unpack(paramData []byte) error {
if len(paramData) < 3 {
return ErrUnpackedDataTooShortWith(len(paramData), 3)
}
param.PrimaryLANChannelNumber = paramData[0]
param.SecondaryLANChannelNumber = paramData[1]
param.SerialChannelNumber = paramData[2]
return nil
}
func (param *DCMICapParam_ManageabilityAccessAttributes) Format() string {
return fmt.Sprintf(`
Primary LAN channel number : %d is %s
Secondary LAN channel number : %d is %s
Serial channel number : %d is %s
`,
param.PrimaryLANChannelNumber,
formatBool(param.PrimaryLANChannelNumber != 0xFF, "available", "unavailable"),
param.SecondaryLANChannelNumber,
formatBool(param.SecondaryLANChannelNumber != 0xFF, "available", "unavailable"),
param.SerialChannelNumber,
formatBool(param.SerialChannelNumber != 0xFF, "available", "unavailable"),
)
}
type DCMICapParam_EnhancedSystemPowerStatisticsAttributes struct {
RollingCount uint8
RollingAverageTimePeriodsSec []int
}
func (param *DCMICapParam_EnhancedSystemPowerStatisticsAttributes) DCMICapParameter() DCMICapParamSelector {
return DCMICapParamSelector_EnhancedSystemPowerStatisticsAttributes
}
func (param *DCMICapParam_EnhancedSystemPowerStatisticsAttributes) Pack() []byte {
out := make([]byte, 1+len(param.RollingAverageTimePeriodsSec))
out[0] = param.RollingCount
for i, periodSec := range param.RollingAverageTimePeriodsSec {
unit := uint8(0b00)
period := uint8(0)
if periodSec > 60*60*24 {
unit = 0b11 // days
period = uint8(periodSec / 60 / 60 / 24)
} else if periodSec > 60*60 {
unit = 0b10 // hours
period = uint8(periodSec / 60 / 60)
} else if periodSec > 60 {
unit = 0b01 // minutes
period = uint8(periodSec / 60)
} else {
unit = 0b00 // seconds
period = uint8(periodSec)
}
out[1+i] = unit<<6 | period
}
return out
}
func (param *DCMICapParam_EnhancedSystemPowerStatisticsAttributes) Unpack(paramData []byte) error {
if len(paramData) < 1 {
return ErrUnpackedDataTooShortWith(len(paramData), 1)
}
param.RollingCount = paramData[0]
rollingCount := int(param.RollingCount)
if len(paramData) < 1+rollingCount {
return ErrNotEnoughDataWith("rolling average time periods", len(paramData), 1+rollingCount)
}
periodsData, _, _ := unpackBytes(paramData, 1, rollingCount)
for _, periodData := range periodsData {
durationUnit := periodData >> 6
durationNumber := periodData & 0x3F
durationSec := 0
switch durationUnit {
case 0b00: // seconds
durationSec = int(durationNumber)
case 0b01: // minutes
durationSec = int(durationNumber) * 60
case 0b10: // hours
durationSec = int(durationNumber) * 60 * 60
case 0b11: // days
durationSec = int(durationNumber) * 60 * 60 * 24
}
param.RollingAverageTimePeriodsSec = append(param.RollingAverageTimePeriodsSec, durationSec)
}
return nil
}
func (param *DCMICapParam_EnhancedSystemPowerStatisticsAttributes) Format() string {
return fmt.Sprintf(`
Rolling count : %d
Rolling average time periods : %v
`,
param.RollingCount,
param.RollingAverageTimePeriodsSec,
)
}
golang-github-bougou-go-ipmi-0.7.2/types_dcmi_config_params.go 0000664 0000000 0000000 00000021647 14741105271 0024477 0 ustar 00root root 0000000 0000000 package ipmi
import "fmt"
type DCMIConfigParameter interface {
DCMIConfigParameter() (paramSelector DCMIConfigParamSelector, setSelector uint8)
Parameter
}
var (
_ DCMIConfigParameter = (*DCMIConfigParam_ActivateDHCP)(nil)
_ DCMIConfigParameter = (*DCMIConfigParam_DiscoveryConfiguration)(nil)
_ DCMIConfigParameter = (*DCMIConfigParam_DHCPTiming1)(nil)
_ DCMIConfigParameter = (*DCMIConfigParam_DHCPTiming2)(nil)
_ DCMIConfigParameter = (*DCMIConfigParam_DHCPTiming3)(nil)
)
func isNilDCMIConfigParameter(param DCMIConfigParameter) bool {
switch v := param.(type) {
case *DCMIConfigParam_ActivateDHCP:
return v == nil
case *DCMIConfigParam_DiscoveryConfiguration:
return v == nil
case *DCMIConfigParam_DHCPTiming1:
return v == nil
case *DCMIConfigParam_DHCPTiming2:
return v == nil
case *DCMIConfigParam_DHCPTiming3:
return v == nil
default:
return false
}
}
type DCMIConfigParamSelector uint8
const (
DCMIConfigParamSelector_ActivateDHCP DCMIConfigParamSelector = 0x01
DCMIConfigParamSelector_DiscoveryConfiguration DCMIConfigParamSelector = 0x02
DCMIConfigParamSelector_DHCPTiming1 DCMIConfigParamSelector = 0x03
DCMIConfigParamSelector_DHCPTiming2 DCMIConfigParamSelector = 0x04
DCMIConfigParamSelector_DHCPTiming3 DCMIConfigParamSelector = 0x05
)
func (paramSelector DCMIConfigParamSelector) String() string {
m := map[DCMIConfigParamSelector]string{
DCMIConfigParamSelector_ActivateDHCP: "Activate DHCP",
DCMIConfigParamSelector_DiscoveryConfiguration: "Discovery Configuration",
DCMIConfigParamSelector_DHCPTiming1: "DHCP Timing1",
DCMIConfigParamSelector_DHCPTiming2: "DHCP Timing2",
DCMIConfigParamSelector_DHCPTiming3: "DHCP Timing3",
}
if v, ok := m[paramSelector]; ok {
return v
}
return "Unknown"
}
type DCMIConfigParams struct {
ActivateDHCP *DCMIConfigParam_ActivateDHCP
DiscoveryConfiguration *DCMIConfigParam_DiscoveryConfiguration
DHCPTiming1 *DCMIConfigParam_DHCPTiming1
DHCPTiming2 *DCMIConfigParam_DHCPTiming2
DHCPTiming3 *DCMIConfigParam_DHCPTiming3
}
func (dcmiConfigParams *DCMIConfigParams) Format() string {
format := func(param DCMIConfigParameter) string {
if isNilDCMIConfigParameter(param) {
return ""
}
paramSelector, _ := param.DCMIConfigParameter()
content := param.Format()
if content[len(content)-1] != '\n' {
content += "\n"
}
return fmt.Sprintf("[%02d] %-24s: %s", paramSelector, paramSelector.String(), content)
}
out := ""
out = format(dcmiConfigParams.ActivateDHCP)
out += format(dcmiConfigParams.DiscoveryConfiguration)
out += format(dcmiConfigParams.DHCPTiming1)
out += format(dcmiConfigParams.DHCPTiming2)
out += format(dcmiConfigParams.DHCPTiming3)
return out
}
type DCMIConfigParam_ActivateDHCP struct {
// Writing 01h to this parameter will trigger DHCP protocol restart using the latest parameter
// settings, if DHCP is enabled. This can be used to ensure that the other DHCP configuration
// parameters take effect immediately. Otherwise, the parameters may not take effect until the
// next time the protocol restarts or a protocol timeout or lease expiration occurs. This is not a
// non-volatile setting. It is only used to trigger a restart of the DHCP protocol.
//
// This parameter shall always return 0x00 when read.
Activate bool
}
func (param *DCMIConfigParam_ActivateDHCP) DCMIConfigParameter() (paramSelector DCMIConfigParamSelector, setSelector uint8) {
return DCMIConfigParamSelector_ActivateDHCP, 0
}
func (param *DCMIConfigParam_ActivateDHCP) Pack() []byte {
b := uint8(0)
if param.Activate {
b = 1
}
return []byte{b}
}
func (param *DCMIConfigParam_ActivateDHCP) Unpack(paramData []byte) error {
if len(paramData) < 1 {
return ErrUnpackedDataTooShortWith(len(paramData), 1)
}
param.Activate = paramData[0] == 1
return nil
}
func (param *DCMIConfigParam_ActivateDHCP) Format() string {
return fmt.Sprintf(`%v`, param.Activate)
}
type DCMIConfigParam_DiscoveryConfiguration struct {
RandomBackoffEnabled bool
IncludeDHCPOption60And43 bool
IncludeDHCPOption12 bool
}
func (param *DCMIConfigParam_DiscoveryConfiguration) DCMIConfigParameter() (paramSelector DCMIConfigParamSelector, setSelector uint8) {
return DCMIConfigParamSelector_DiscoveryConfiguration, 0
}
func (param *DCMIConfigParam_DiscoveryConfiguration) Pack() []byte {
b := uint8(0)
if param.RandomBackoffEnabled {
b = setBit7(b)
}
if param.IncludeDHCPOption60And43 {
b = setBit1(b)
}
if param.IncludeDHCPOption12 {
b = setBit0(b)
}
return []byte{b}
}
func (param *DCMIConfigParam_DiscoveryConfiguration) Unpack(paramData []byte) error {
if len(paramData) < 1 {
return ErrUnpackedDataTooShortWith(len(paramData), 1)
}
param.RandomBackoffEnabled = isBit7Set(paramData[0])
param.IncludeDHCPOption60And43 = isBit1Set(paramData[0])
param.IncludeDHCPOption12 = isBit0Set(paramData[0])
return nil
}
func (param *DCMIConfigParam_DiscoveryConfiguration) Format() string {
return fmt.Sprintf(`
Random Backoff Enabled : %v
Include DHCPOption60AndOption43 : %v (Vendor class identifier using DCMI IANA, plus Vendor class-specific Information)
Include DHCPOption12 : %v (Management Controller ID String)
`,
param.RandomBackoffEnabled,
formatBool(param.IncludeDHCPOption60And43, "enabled", "disabled"),
formatBool(param.IncludeDHCPOption12, "enabled", "disabled"),
)
}
type DCMIConfigParam_DHCPTiming1 struct {
// This parameter sets the amount of time between the first attempt to reach a server and the
// second attempt to reach a server.
//
// Each time a message is sent the timeout interval between messages is incremented by
// twice the current interval multiplied by a pseudo random number between zero and one
// if random back-off is enabled, or multiplied by one if random back-off is disabled.
//
// The recommended default is four seconds
InitialTimeoutIntervalSec uint8
}
func (param *DCMIConfigParam_DHCPTiming1) DCMIConfigParameter() (paramSelector DCMIConfigParamSelector, setSelector uint8) {
return DCMIConfigParamSelector_DHCPTiming1, 0
}
func (param *DCMIConfigParam_DHCPTiming1) Pack() []byte {
return []byte{param.InitialTimeoutIntervalSec}
}
func (param *DCMIConfigParam_DHCPTiming1) Unpack(paramData []byte) error {
if len(paramData) < 1 {
return ErrUnpackedDataTooShortWith(len(paramData), 1)
}
param.InitialTimeoutIntervalSec = paramData[0]
return nil
}
func (param *DCMIConfigParam_DHCPTiming1) Format() string {
return fmt.Sprintf(`
Initial timeout interval : %d seconds
`,
param.InitialTimeoutIntervalSec,
)
}
type DCMIConfigParam_DHCPTiming2 struct {
// This parameter determines the amount of time that must pass between the time that the
// client initially tries to determine its address and the time that it decides that it cannot contact
// a server. If the last lease is expired, the client will restart the protocol after the defined retry
// interval. The recommended default timeout is two minutes. After server contact timeout, the
// client must wait for Server Contact Retry Interval before attempting to contact the server
// again.
ServerContactTimeoutIntervalSec uint8
}
func (param *DCMIConfigParam_DHCPTiming2) DCMIConfigParameter() (paramSelector DCMIConfigParamSelector, setSelector uint8) {
return DCMIConfigParamSelector_DHCPTiming2, 0
}
func (param *DCMIConfigParam_DHCPTiming2) Pack() []byte {
return []byte{param.ServerContactTimeoutIntervalSec}
}
func (param *DCMIConfigParam_DHCPTiming2) Unpack(paramData []byte) error {
if len(paramData) < 1 {
return ErrUnpackedDataTooShortWith(len(paramData), 1)
}
param.ServerContactTimeoutIntervalSec = paramData[0]
return nil
}
func (param *DCMIConfigParam_DHCPTiming2) Format() string {
return fmt.Sprintf(`
Server contact timeout interval: %d seconds
`,
param.ServerContactTimeoutIntervalSec)
}
type DCMIConfigParam_DHCPTiming3 struct {
// This is the period between DHCP retries after Server contact timeout interval expires. This
// parameter determines the time that must pass after the client has determined that there is no
// DHCP server present before it tries again to contact a DHCP server.
//
// The recommended default timeout is sixty-four seconds
ServerContactRetryIntervalSec uint8
}
func (param *DCMIConfigParam_DHCPTiming3) DCMIConfigParameter() (paramSelector DCMIConfigParamSelector, setSelector uint8) {
return DCMIConfigParamSelector_DHCPTiming3, 0
}
func (param *DCMIConfigParam_DHCPTiming3) Pack() []byte {
return []byte{param.ServerContactRetryIntervalSec}
}
func (param *DCMIConfigParam_DHCPTiming3) Unpack(paramData []byte) error {
if len(paramData) < 1 {
return ErrUnpackedDataTooShortWith(len(paramData), 1)
}
param.ServerContactRetryIntervalSec = paramData[0]
return nil
}
func (param *DCMIConfigParam_DHCPTiming3) Format() string {
return fmt.Sprintf(`
Server contact retry interval: %d seconds
`,
param.ServerContactRetryIntervalSec,
)
}
golang-github-bougou-go-ipmi-0.7.2/types_entity.go 0000664 0000000 0000000 00000016443 14741105271 0022205 0 ustar 00root root 0000000 0000000 package ipmi
import "fmt"
// 43.14 Entity IDs
// 39. Using Entity IDs
// EntityID can be seen as Entity Type
//
// 1. An Entity ID is a standardized numeric code that is used in SDRs to identify
// the types of physical entities or FRUs in the system.
//
// 2. The Entity ID is associated with an Entity Instance value that is used to
// indicate the particular instance of an entity
//
// 3. The SDR for a sensor includes Entity ID and Entity Instance fields that
// identify the entity associated with the sensor.
type EntityID uint8
func (e EntityID) String() string {
// 43.14 Entity IDs
var entityIDMap = map[EntityID]string{
0x00: "unspecified",
0x01: "other",
0x02: "unspecified",
0x03: "processor",
0x04: "disk or disk bay", // 磁盘托架
0x05: "peripheral bay", // 外围托架
0x06: "system management module",
0x07: "system board",
0x08: "memory module",
0x09: "processor module",
0x0a: "power supply", // DMI refers to this as a 'power unit', but it's used to represent a power supply
0x0b: "add-in card", // 附加卡
0x0c: "front panel board", // 前面板
0x0d: "back panel board", // 背板
0x0e: "power system board", // 电源系统板
0x0f: "drive backplane", // 驱动器背板
0x10: "system internal expansion board", //
0x11: "other system board",
0x12: "processor board",
0x13: "power unit / power domain",
0x14: "power module / DC-to-DC converter",
0x15: "power management / power distribution board",
0x16: "chassis back panel board", // 机箱后面板
0x17: "system chassis", //
0x18: "sub-chassis",
0x19: "other chassis board",
0x1a: "Disk Drive bay",
0x1b: "Peripheral bay",
0x1c: "Device bay",
0x1d: "fan / cooling device",
0x1e: "cooling unit / cooling domain",
0x1f: "cable / interconnect",
0x20: "memory device",
0x21: "System Management Software",
0x22: "System Firmware", // eg BIOS/EFI
0x23: "Operating System",
0x24: "system bus",
0x25: "Group",
0x26: "Remote (Out of Band) Management Communication Device",
0x27: "External Environment",
0x28: "battery",
0x29: "Processing blade",
0x2a: "Connectivity switch",
0x2b: "Processor/memory module",
0x2c: "I/O module",
0x2d: "Processor / IO module",
0x2e: "Management Controller Firmware",
0x2f: "IPMI Channel",
0x30: "PCI Bus",
0x31: "PCI Express Bus",
0x32: "SCSI Bus (parallel)",
0x33: "SATA / SAS bus",
0x34: "Processor / front-side bus",
0x35: "Real Time Clock (RTC)",
0x36: "System Firmware", // reserved. This value was previously a duplicate of 22h (System Firmware).
0x37: "air inlet",
0x38: "System Firmware", // reserved. This value was previously a duplicate of 22h (System Firmware).
0x40: "air inlet", // This Entity ID value is equivalent to Entity ID 37h. It is provided for interoperability with the DCMI 1.0 specifications.
0x41: "processor", // This Entity ID value is equivalent to Entity ID 03h (processor). It is provided for interoperability with the DCMI 1.0 specifications.
0x42: "system board", // This Entity ID value is equivalent to Entity ID 07h (system board). It is provided for interoperability with the DCMI 1.0 specifications.
}
out, ok := entityIDMap[e]
if ok {
return out
}
if e >= 0x90 && e <= 0xaf {
// These IDs are system specific and can be assigned by the chassis provider.
return fmt.Sprintf("Chassis-specific Entities (#%#02x)", uint8(e))
}
if e >= 0xb0 && e <= 0xcf {
// These IDs are system specific and can be assigned by the Board-set provider
return fmt.Sprintf("Board-set specific Entities (#%#02x)", uint8(e))
}
if e >= 0xd0 && e <= 0xff {
// These IDs are system specific and can be assigned by the system integrator, or OEM.
return fmt.Sprintf("OEM System Integrator defined (#%#02x)", uint8(e))
}
return fmt.Sprintf("reserved (#%#02x)", uint8(e))
}
// see: 39.1 System- and Device-relative Entity Instance Values
//
// Entity Instance values in the system-relative range are required to be unique for all entities with the same Entity ID in the system.
//
// Device-relative Entity Instance values are only required to be unique among all entities that have the same Entity ID within a given device (management controller).
//
// For example, management controller A and B could both have FAN entities that have an Entity Instance value of 60h.
//
// EntityInstance only occupy 7 bits, range is 0x00 ~ 0x7f
type EntityInstance uint8
// 39.1 System- and Device-relative Entity Instance Values
func isEntityInstanceSystemRelative(e EntityInstance) bool {
return e <= 0x5f
}
func isEntityInstanceDeviceRelative(e EntityInstance) bool {
return e >= 0x60 && e <= 0x7f
}
func (e EntityInstance) Type() string {
if isEntityInstanceSystemRelative(e) {
return "system-relative"
}
if isEntityInstanceDeviceRelative(e) {
return "device-relative"
}
return "'"
}
func canonicalEntityString(entityID EntityID, entityInstance EntityInstance) string {
if isEntityInstanceSystemRelative(entityInstance) {
return fmt.Sprintf("System, %s, %d", entityID.String(), entityInstance)
}
if isEntityInstanceDeviceRelative(entityInstance) {
return fmt.Sprintf("Controller 1, %s, %d", entityID.String(), entityInstance)
}
return "unknown"
}
// 43.13 Device Type Codes
// DeviceType codes are used to identify different types of devices on
// an IPMB, PCI Management Bus, or Private Management Bus connection
// to an IPMI management controller
type DeviceType uint16
func (d DeviceType) String() string {
var deviceTypeMap = map[DeviceType]string{
0x00: "Reserved",
0x01: "Reserved",
0x02: "DS1624 temperature sensor",
0x03: "DS1621 temperature sensor",
0x04: "LM75 Temperature Sensor",
0x05: "Heceta ASIC",
0x06: "Reserved",
0x07: "Reserved",
// modifier codes for deviceTye 0x08 ~ 0x0f
// 00h = unspecified
// 01h = DIMM Memory ID
// 02h = IPMI FRU Inventory
// 03h = System Processor Cartridge FRU / PIROM (processor information ROM)
// (processor information ROM)
// all other = reserved
0x08: "EEPROM, 24C01",
0x09: "EEPROM, 24C02",
0x0a: "EEPROM, 24C04",
0x0b: "EEPROM, 24C08",
0x0c: "EEPROM, 24C16",
0x0d: "EEPROM, 24C17",
0x0e: "EEPROM, 24C32",
0x0f: "EEPROM, 24C64",
// modifier codes for deviceType 0x10
// 00h = IPMI FRU Inventory [1]
// 01h = DIMM Memory ID
// 02h = IPMI FRU Inventory[1]
// 03h = System Processor Cartridge FRU / PIROM
// (processor information ROM)
// all other = reserved
// FFh = unspecified
0x10: "FRU Inventory Device behind management controller", // (accessed using Read/Write FRU commands at LUN other than 00b)
0x11: "Reserved",
0x12: "Reserved",
0x13: "Reserved",
0x14: "PCF 8570 256 byte RAM",
0x15: "PCF 8573 clock/calendar",
0x16: "PCF 8574A I/O Port",
0x17: "PCF 8583 clock/calendar",
0x18: "PCF 8593 clock/calendar",
0x19: "Clock calendar",
0x1a: "PCF 8591 A/D, D/A Converter",
0x1b: "I/O Port",
0x1c: "A/D Converter",
0x1d: "D/A Converter",
0x1e: "A/D, D/A Converter",
0x1f: "LCD Controller/Driver",
0x20: "Core Logic (Chip set) Device",
0x21: "LMC6874 Intelligent Battery controller",
0x22: "Intelligent Batter controller",
0x23: "Combo Management ASIC",
0x24: "Maxim 1617 Temperature Sensor",
0xbf: "Other/Unspecified",
}
s, ok := deviceTypeMap[d]
if ok {
return s
}
return ""
}
golang-github-bougou-go-ipmi-0.7.2/types_event.go 0000664 0000000 0000000 00000016551 14741105271 0022012 0 ustar 00root root 0000000 0000000 package ipmi
import "fmt"
// 31.6.1 SEL Record Type Ranges
type SELRecordType uint8
type SELRecordTypeRange string
const (
// Range reserved for standard SEL Record Types.
// As of this writing, only type 02h is defined.
// Records are automatically timestamped unless otherwise indicated
// 00h - BFh
SELRecordTypeRangeStandard SELRecordTypeRange = "standard"
// 32.2 OEM SEL Record - Type C0h-DFh
// Range reserved for timestamped OEM SEL records.
// These records are automatically timestamped by the SEL Device
// C0h - DFh
SELRecordTypeRangeTimestampedOEM SELRecordTypeRange = "timestamped OEM"
// 32.3 OEM SEL Record - Type E0h-FFh
// Range reserved for non-timestamped OEM SEL records.
// The SEL Device does not automatically timestamp these records.
// The four bytes passed in the byte locations for the timestamp will be directly entered into the SEL.
// E0h - FFh
SELRecordTypeRangeNonTimestampedOEM SELRecordTypeRange = "non-timestamped OEM"
)
// The SELRecordType can be categorized into 3 ranges according to the SELRecordType value.
// - 00h - BFh -> standard
// - C0h - DFh -> timestamped OEM
// - E0h - FFh -> none-timestamped OEM
func (typ SELRecordType) Range() SELRecordTypeRange {
t := uint8(typ)
if t <= 0xbf {
return SELRecordTypeRangeStandard
}
if t >= 0xc0 && t <= 0xdf {
return SELRecordTypeRangeTimestampedOEM
}
// t >= 0xe0 && t <= 0xff
return SELRecordTypeRangeNonTimestampedOEM
}
func (typ SELRecordType) String() string {
return string(typ.Range())
}
// Event direction
type EventDir bool
const (
EventDirDeassertion = true
EventDirAssertion = false
)
func (d EventDir) String() string {
if d {
return "Deassertion"
}
return "Assertion"
}
// 29.7 Event Data Field Formats
type EventData struct {
EventData1 uint8
EventData2 uint8
EventData3 uint8
}
// 29.7 Event Data Field Formats
// Event Data 1
// [3:0] -
// for threshold sensors: Offset from Event/Reading Code for threshold event.
// for discrete sensors: Offset from Event/Reading Code for discrete event state (corresponding 15 possible discrete events)
func (ed *EventData) EventReadingOffset() uint8 {
return ed.EventData1 & 0x0f
}
func (ed *EventData) String() string {
return fmt.Sprintf("%02x%02x%02x", ed.EventData1, ed.EventData2, ed.EventData3)
}
// 41.2 Event/Reading Type Code
// 42.1 Event/Reading Type Codes
type EventReadingType uint8
const (
// Unspecified
EventReadingTypeUnspecified EventReadingType = 0x00
// Threshold
EventReadingTypeThreshold EventReadingType = 0x01
// Generic
EventReadingTypeTransitionState EventReadingType = 0x02
EventReadingTypeState EventReadingType = 0x03
EventReadingTypePredictiveFailure EventReadingType = 0x04
EventReadingTypeLimit EventReadingType = 0x05
EventReadingTypePerformance EventReadingType = 0x06
EventReadingTypeTransitionSeverity EventReadingType = 0x07
EventReadingTypeDevicePresent EventReadingType = 0x08
EventReadingTypeDeviceEnabled EventReadingType = 0x09
EventReadingTypeTransitionAvailability EventReadingType = 0x0a
EventReadingTypeRedundancy EventReadingType = 0x0b
EventReadingTypeACPIPowerState EventReadingType = 0x0c
EventReadingTypeSensorSpecific EventReadingType = 0x6f
// OEM
EventReadingTypeOEMMin EventReadingType = 0x70
EventReadingTypeOEMMax EventReadingType = 0x7f
// Reserved
)
func (typ EventReadingType) String() string {
var c string
switch typ {
case EventReadingTypeUnspecified:
c = "Unspecified"
case EventReadingTypeThreshold:
c = "Threshold"
case EventReadingTypeSensorSpecific:
c = "Sensor Specific"
default:
if typ >= 0x02 && typ <= 0x0c {
c = "Generic"
} else if typ >= EventReadingTypeOEMMin && typ <= EventReadingTypeOEMMax {
c = "OEM"
} else {
c = "Reserved"
}
}
return c
}
func (typ EventReadingType) SensorClass() SensorClass {
if typ == EventReadingTypeThreshold {
return SensorClassThreshold
}
return SensorClassDiscrete
}
func (typ EventReadingType) IsThreshold() bool {
return typ == EventReadingTypeThreshold
}
// EventString returns description of the event
func (typ EventReadingType) EventString(sensorType SensorType, eventData EventData) string {
event := typ.Event(sensorType, eventData)
if event == nil {
return ""
}
return event.EventName
}
// EventSeverity return the severity for the event.
// Todo, refactor
func (typ EventReadingType) EventSeverity(sensorType SensorType, eventData EventData, eventDir EventDir) EventSeverity {
event := typ.Event(sensorType, eventData)
if event == nil {
return EventSeverityInfo
}
switch typ {
case EventReadingTypeUnspecified:
return EventSeverityInfo
case EventReadingTypeThreshold:
if eventDir {
if v, ok := event.AssertionSeverityMap[sensorType]; ok {
return v
}
if v, ok := event.AssertionSeverityMap[SensorTypeReserved]; ok {
return v
}
return EventSeverityInfo
} else {
if v, ok := event.DeassertionSeverityMap[sensorType]; ok {
return v
}
if v, ok := event.DeassertionSeverityMap[SensorTypeReserved]; ok {
return v
}
return EventSeverityInfo
}
case EventReadingTypeSensorSpecific:
if eventDir {
return event.AssertionSeverity
}
return event.DeassertionSeverity
default:
if typ >= 0x02 && typ <= 0x0c {
if eventDir {
if v, ok := event.AssertionSeverityMap[sensorType]; ok {
return v
}
if v, ok := event.AssertionSeverityMap[SensorTypeReserved]; ok {
return v
}
return EventSeverityInfo
} else {
if v, ok := event.DeassertionSeverityMap[sensorType]; ok {
return v
}
if v, ok := event.DeassertionSeverityMap[SensorTypeReserved]; ok {
return v
}
return EventSeverityInfo
}
} else if typ >= EventReadingTypeOEMMin && typ <= EventReadingTypeOEMMax {
return EventSeverityInfo
} else {
return EventSeverityInfo
}
}
}
// Event return the predefined Event description struct.
func (typ EventReadingType) Event(sensorType SensorType, eventData EventData) *Event {
offset := eventData.EventReadingOffset()
return typ.EventForOffset(sensorType, offset)
}
func (typ EventReadingType) EventForOffset(sensorType SensorType, eventOffset uint8) *Event {
switch typ {
case EventReadingTypeUnspecified:
return nil
case EventReadingTypeThreshold:
return genericEvent(typ, eventOffset)
case EventReadingTypeSensorSpecific:
return sensorSpecificEvent(sensorType, eventOffset)
default:
if typ >= 0x02 && typ <= 0x0c {
return genericEvent(typ, eventOffset)
} else if typ >= EventReadingTypeOEMMin && typ <= EventReadingTypeOEMMax {
return oemEvent(sensorType, eventOffset)
} else {
return nil
}
}
}
type EventSeverity string
const (
EventSeverityInfo EventSeverity = "Info"
EventSeverityOK EventSeverity = "OK"
EventSeverityWarning EventSeverity = "Warning"
EventSeverityCritical EventSeverity = "Critical"
EventSeverityDegraded EventSeverity = "Degraded"
EventSeverityNonFatal EventSeverity = "Non-fatal"
)
type Event struct {
EventName string
EventDesc string
// for generic event, different sensor type may means different severity
AssertionSeverityMap map[SensorType]EventSeverity
DeassertionSeverityMap map[SensorType]EventSeverity
// for sensor specific event, severity is certain.
AssertionSeverity EventSeverity
DeassertionSeverity EventSeverity
ED2 map[uint8]string // EventData2
ED3 map[uint8]string // EventData3
}
golang-github-bougou-go-ipmi-0.7.2/types_event_consts.go 0000664 0000000 0000000 00000155016 14741105271 0023403 0 ustar 00root root 0000000 0000000 package ipmi
// For example, a 'button' sensor supports a set of sensor-specific event offsets:
// 0 for Power Button pressed, for Sleep Button pressed, and 2 for Reset Button pressed.
// When an event is generated, it could have a 0, 1, or 2 in the event offset field
// depending on what button press occurred.
// type EventOffset uint8
func genericEvent(typ EventReadingType, offset uint8) *Event {
e, ok := GenericEvents[typ]
if !ok {
return nil
}
event, ok := e[offset]
if !ok {
return nil
}
return &event
}
func oemEvent(sensorType SensorType, offset uint8) *Event {
return nil
}
func sensorSpecificEvent(sensorType SensorType, offset uint8) *Event {
e, ok := SensorSpecificEvents[sensorType]
if !ok {
return nil
}
event, ok := e[offset]
if !ok {
return nil
}
return &event
}
// Table 42-2, Generic Event/Reading Type Codes
// Including Generic threshold-based events (0x01)
// and Generic discrete-based events (0x02 - 0x0c)
//
// map[EventReadingType]: map[Offset]Event
//
// The severity is copied from
// freeipmi/libfreeipmi/interpret/ipmi-interpret-config-sel.c
var GenericEvents = map[EventReadingType]map[uint8]Event{
EventReadingTypeThreshold: {
0x00: {
EventName: "Lower Non-critical - going low",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x01: {
EventName: "Lower Non-critical - going high",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x02: {
EventName: "Lower Critical - going low",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x03: {
EventName: "Lower Critical - going high",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x04: {
EventName: "Lower Non-recoverable - going low",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x5: {
EventName: "Lower Non-recoverable - going high",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x06: {
EventName: "Upper Non-critical - going low",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x07: {
EventName: "Upper Non-critical - going high",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x08: {
EventName: "Upper Critical - going low",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x09: {
EventName: "Upper Critical - going high",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x0a: {
EventName: "Upper Non-recoverable - going low",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x0b: {
EventName: "Upper Non-recoverable - going high",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
},
EventReadingTypeTransitionState: {
0x00: {
EventName: "Transition to Idle",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityInfo,
},
},
0x01: {
EventName: "Transition to Active",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityInfo,
},
},
0x02: {
EventName: "Transition to Busy",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityInfo,
},
},
},
EventReadingTypeState: {
0x00: {
EventName: "State Deasserted",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityInfo,
SensorTypeButtonSwitch: EventSeverityInfo,
SensorTypeModuleBoard: EventSeverityInfo,
SensorTypeBootError: EventSeverityInfo,
SensorTypeOSStopShutdown: EventSeverityInfo,
SensorTypePlatformAlert: EventSeverityInfo,
SensorTypeTemperature: EventSeverityInfo,
SensorTypeVoltage: EventSeverityInfo,
SensorTypeFan: EventSeverityInfo,
SensorTypeProcessor: EventSeverityInfo,
SensorTypePowerSupply: EventSeverityInfo,
SensorTypePowerUnit: EventSeverityInfo,
SensorTypeMemory: EventSeverityInfo,
SensorTypeDriveSlot: EventSeverityWarning,
SensorTypePostMemoryResize: EventSeverityInfo,
SensorTypeSystemFirmwareProgress: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityInfo,
SensorTypeButtonSwitch: EventSeverityInfo,
SensorTypeModuleBoard: EventSeverityInfo,
SensorTypeBootError: EventSeverityInfo,
SensorTypeOSStopShutdown: EventSeverityInfo,
SensorTypePlatformAlert: EventSeverityInfo,
SensorTypeTemperature: EventSeverityInfo,
SensorTypeVoltage: EventSeverityInfo,
SensorTypeFan: EventSeverityInfo,
SensorTypeProcessor: EventSeverityInfo,
SensorTypePowerSupply: EventSeverityInfo,
SensorTypePowerUnit: EventSeverityInfo,
SensorTypeMemory: EventSeverityInfo,
SensorTypeDriveSlot: EventSeverityWarning,
SensorTypePostMemoryResize: EventSeverityInfo,
SensorTypeSystemFirmwareProgress: EventSeverityInfo,
},
},
0x01: {
EventName: "State Asserted",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityWarning,
SensorTypeButtonSwitch: EventSeverityInfo,
SensorTypeModuleBoard: EventSeverityCritical,
SensorTypeBootError: EventSeverityCritical,
SensorTypeOSStopShutdown: EventSeverityCritical,
SensorTypePlatformAlert: EventSeverityCritical,
SensorTypeTemperature: EventSeverityWarning,
SensorTypeVoltage: EventSeverityWarning,
SensorTypeFan: EventSeverityWarning,
SensorTypeProcessor: EventSeverityCritical,
SensorTypePowerSupply: EventSeverityWarning,
SensorTypePowerUnit: EventSeverityWarning,
SensorTypeMemory: EventSeverityCritical,
SensorTypeDriveSlot: EventSeverityInfo,
SensorTypePostMemoryResize: EventSeverityWarning,
SensorTypeSystemFirmwareProgress: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeSystemEvent: EventSeverityWarning,
SensorTypeButtonSwitch: EventSeverityInfo,
SensorTypeModuleBoard: EventSeverityCritical,
SensorTypeBootError: EventSeverityCritical,
SensorTypeOSStopShutdown: EventSeverityCritical,
SensorTypePlatformAlert: EventSeverityCritical,
SensorTypeTemperature: EventSeverityWarning,
SensorTypeVoltage: EventSeverityWarning,
SensorTypeFan: EventSeverityWarning,
SensorTypeProcessor: EventSeverityCritical,
SensorTypePowerSupply: EventSeverityWarning,
SensorTypePowerUnit: EventSeverityWarning,
SensorTypeMemory: EventSeverityCritical,
SensorTypeDriveSlot: EventSeverityInfo,
SensorTypePostMemoryResize: EventSeverityWarning,
SensorTypeSystemFirmwareProgress: EventSeverityWarning,
},
},
},
EventReadingTypePredictiveFailure: {
0x00: {
EventName: "Predictive Failure de-asserted",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeDriveSlot: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeDriveSlot: EventSeverityInfo,
},
},
0x01: {
EventName: "Predictive Failure asserted",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
SensorTypeDriveSlot: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
SensorTypeDriveSlot: EventSeverityCritical,
},
},
},
EventReadingTypeLimit: {
0x00: {
EventName: "Limit Not Exceeded",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeTemperature: EventSeverityInfo,
SensorTypeVoltage: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeTemperature: EventSeverityInfo,
SensorTypeVoltage: EventSeverityInfo,
},
},
0x01: {
EventName: "Limit Exceeded",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
SensorTypeTemperature: EventSeverityCritical,
SensorTypeVoltage: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
SensorTypeTemperature: EventSeverityCritical,
SensorTypeVoltage: EventSeverityCritical,
},
},
},
EventReadingTypePerformance: {
0x00: {
EventName: "Performance Met",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeVoltage: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
SensorTypeVoltage: EventSeverityInfo,
},
},
0x01: {
EventName: "Performance Lags",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
SensorTypeVoltage: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
SensorTypeVoltage: EventSeverityCritical,
},
},
},
EventReadingTypeTransitionSeverity: {
0x00: {
EventName: "transition to OK",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x01: {
EventName: "transition to Non-Critical from OK",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x02: {
EventName: "transition to Critical from less severe",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x03: {
EventName: "transition to Non-recoverable from less severe",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x04: {
EventName: "transition to Non-Critical from more severe",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x05: {
EventName: "transition to Critical from Non-recoverable",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x06: {
EventName: "transition to Non-recoverable",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x07: {
EventName: "Monitor",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x08: {
EventName: "Informational",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
},
EventReadingTypeDevicePresent: {
0x00: {
EventName: "Device Removed / Device Absent",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x01: {
EventName: "Device Inserted / Device Present",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
},
EventReadingTypeDeviceEnabled: {
0x00: {
EventName: "Device Disabled",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x01: {
EventName: "Device Enabled",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
},
EventReadingTypeTransitionAvailability: {
0x00: {
EventName: "transition to Running",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x01: {
EventName: "transition to In Test",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x02: {
EventName: "transition to Power Off",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x03: {
EventName: "transition to On Line",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x04: {
EventName: "transition to Off Line",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x05: {
EventName: "transition to Off Duty",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x06: {
EventName: "transition to Degraded",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
0x07: {
EventName: "transition to Power Save",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x08: {
EventName: "Install Error",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
},
},
EventReadingTypeRedundancy: {
0x00: {
EventName: "Fully Redundant",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x01: {
EventName: "Redundancy Lost",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x02: {
EventName: "Redundancy Degraded",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x03: {
EventName: "Non-redundant (Sufficient Resources from Redundant)",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x04: {
EventName: "Non-redundant (Sufficient Resources from Insufficient Resources)",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x05: {
EventName: "Non-redundant (Insufficient Resources)",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityCritical,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x06: {
EventName: "Redundancy Degraded from Fully Redundant",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
0x07: {
EventName: "Redundancy Degraded from Non-redundant",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityWarning,
},
},
},
EventReadingTypeACPIPowerState: {
0x00: {
EventName: "D0 Power State",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x01: {
EventName: "D1 Power State",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x02: {
EventName: "D2 Power State",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
0x03: {
EventName: "D3 Power State",
AssertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
DeassertionSeverityMap: map[SensorType]EventSeverity{
SensorTypeReserved: EventSeverityInfo,
},
},
},
}
// 42.2 Sensor Type Codes and Data
// Sensor Specific Events
// SensorType, Offset
var SensorSpecificEvents = map[SensorType]map[uint8]Event{
SensorTypeReserved: {},
SensorTypeTemperature: {},
SensorTypeVoltage: {},
SensorTypeCurrent: {},
SensorTypeFan: {},
SensorTypePhysicalSecurity: {
0x00: {
EventName: "General Chassis Intrusion",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "Drive Bay intrusion",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "I/O Card area intrusion",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Processor area intrusion",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x04: {
EventName: "LAN Leash Lost (system is unplugged from LAN)",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x05: {
EventName: "Unauthorized dock",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x06: {
EventName: "FAN area intrusion",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypePlatformSecurity: {
0x00: {
EventName: "Secure Mode (Front Panel Lockout) Violation attempt",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "Pre-boot Password Violation - user password",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "Pre-boot Password Violation attempt - setup password",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Pre-boot Password Violation - network boot password",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x04: {
EventName: "Other pre-boot Password Violation",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x05: {
EventName: "Out-of-band Access Password Violation",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeProcessor: {
0x00: {
EventName: "IERR",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "Thermal Trip",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "FRB1/BIST failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "FRB2/Hang in POST failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x04: {
EventName: "FRB3/Processor Startup/Initialization failure (CPU didn't start)",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x05: {
EventName: "Configuration Error",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x06: {
EventName: "SM BIOS 'Uncorrectable CPU-complex Error'",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x07: {
EventName: "Processor Presence detected",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x08: {
EventName: "Processor disabled",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x09: {
EventName: "Terminator Presence Detected",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x0a: {
EventName: "Processor Automatically Throttled",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x0b: {
EventName: "Machine Check Exception (Uncorrectable)",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x0c: {
EventName: "Correctable Machine Check Error",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
},
SensorTypePowerSupply: {
0x00: {
EventName: "Presence detected",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "Power Supply Failure detected",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "Predictive Failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Power Supply input lost (AC/DC)",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityWarning,
},
0x04: {
EventName: "Power Supply input lost or out-of-range",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityWarning,
},
0x05: {
EventName: "Power Supply input out-of-range, but present",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityWarning,
},
0x06: {
EventName: "Configuration error",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x07: {
EventName: "Power Supply Inactive (in standby state)",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
},
SensorTypePowerUnit: {
0x00: {
EventName: "Power Off / Power Dow",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "Power Cycle",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x02: {
EventName: "240VA Power Down",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityInfo,
},
0x03: {
EventName: "Interlock Power Down",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x04: {
EventName: "AC lost / Power input lost ",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityWarning,
},
0x05: {
EventName: "Soft Power Control Failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x06: {
EventName: "Power Unit Failure detected",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x07: {
EventName: "Predictive Failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeCollingDevice: {},
// Other Units-based Sensor (per units given in SDR)
SensorTypeOtherUnitsbased: {},
SensorTypeMemory: {
0x00: {
EventName: "Correctable ECC / other correctable memory error",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x01: {
EventName: "Uncorrectable ECC / other uncorrectable memory error",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "Parity",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Memory Scrub Failed (stuck bit)",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x04: {
EventName: "Memory Device Disabled",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x05: {
EventName: "Correctable ECC / other correctable memory error logging limit reached",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x06: {
EventName: "Presence detected",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x07: {
EventName: "Configuration error",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x08: {
EventName: "Spare",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x09: {
EventName: "Memory Automatically Throttled",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x0a: {
EventName: "Critical Overtemperature",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeDriveSlot: {
0x00: {
EventName: "Drive Presence",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "Drive Fault",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "Predictive Failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Hot Spare",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x04: {
EventName: "Consistency Check / Parity Check in progress",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x05: {
EventName: "In Critical Array",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x06: {
EventName: "In Failed Array",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x07: {
EventName: "Rebuild/Remap in progress",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x08: {
EventName: "Rebuild/Remap Aborted (was not completed normally)",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypePostMemoryResize: {},
SensorTypeSystemFirmwareProgress: {
0x00: {
EventName: "System Firmware Error (POST Error)",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "System Firmware Hang",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "System Firmware Progress",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
},
SensorTypeEventLoggingDisabled: {
0x00: {
EventName: "Correctable Memory Error Logging Disabled",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "Event 'Type' Logging Disabled",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "Log Area Reset/Cleared",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x03: {
EventName: "All Event Logging Disabled",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x04: {
EventName: "SEL Full",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x05: {
EventName: "SEL Almost Full",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x06: {
EventName: "Correctable Machine Check Error Logging Disabled",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeWatchdog1: {
0x00: {
EventName: "BIOS Watchdog Reset",
},
0x01: {
EventName: "OS Watchdog Reset",
},
0x02: {
EventName: "OS Watchdog Shut Down",
},
0x03: {
EventName: "OS Watchdog Power Down",
},
0x04: {
EventName: "OS Watchdog Power Cycle",
},
0x05: {
EventName: "OS Watchdog NMI / Diagnostic Interrupt",
},
0x06: {
EventName: "OS Watchdog Expired, status only",
},
0x07: {
EventName: "OS Watchdog pre-timeout Interrupt, non-NMI",
},
},
SensorTypeSystemEvent: {
0x00: {
EventName: "System Reconfigured",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x01: {
EventName: "OEM System Boot Event",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x02: {
EventName: "Undetermined system hardware failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Entry added to Auxiliary Log",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x04: {
EventName: "PEF Action",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x05: {
EventName: "Timestamp Clock Synch",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
},
SensorTypeCriticalInterrupt: {
0x00: {
EventName: "Front Panel NMI / Diagnostic Interrupt",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "Bus Timeout",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "I/O channel check NMI",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Software NMI",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x04: {
EventName: "PCI PERR",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x05: {
EventName: "PCI SERR",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x06: {
EventName: "EISA Fail Safe Timeout",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x07: {
EventName: "Bus Correctable Error",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x08: {
EventName: "Bus Uncorrectable Error",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x09: {
EventName: "Fatal NMI",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x0a: {
EventName: "Bus Fatal Error",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x0b: {
EventName: "Bus Degraded",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
},
SensorTypeButtonSwitch: {
0x00: {
EventName: "Power Button pressed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "Sleep Button pressed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x02: {
EventName: "Reset Button pressed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x03: {
EventName: "FRU latch open",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x04: {
EventName: "FRU service request button",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
},
SensorTypeModuleBoard: {},
SensorTypeMicrocontrollerCoprocessor: {},
SensorTypeAddinCard: {},
SensorTypeChassis: {},
SensorTypeChipSet: {
0x00: {
EventName: "Soft Power Control Failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "Thermal Trip",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeOtherFRU: {},
SensorTypeCableInterconnect: {
0x00: {
EventName: "Cable/Interconnect is connected",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "Configuration Error - Incorrect cable connected / Incorrect interconnection",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeTerminator: {},
SensorTypeSystemBootRestartInitiated: {
0x00: {
EventName: "Initiated by power up",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "Initiated by hard reset",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x02: {
EventName: "Initiated by warm reset",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x03: {
EventName: "User requested PXE boot",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x04: {
EventName: "Automatic boot to diagnostic",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x05: {
EventName: "OS / run-time software initiated hard reset",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x06: {
EventName: "OS / run-time software initiated warm reset",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x07: {
EventName: "System Restart",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
},
SensorTypeBootError: {
0x00: {
EventName: "No bootable media",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "Non-bootable diskette left in drive",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "PXE Server not found",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Invalid boot sector",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x04: {
EventName: "Timeout waiting for user selection of boot source",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
},
SensorTypeBaseOSBootInstallationStatus: {
0x00: {
EventName: "A: boot completed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "C: boot completed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x02: {
EventName: "PXE boot completed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x03: {
EventName: "Diagnostic boot completed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x04: {
EventName: "CD-ROM boot completed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x05: {
EventName: "ROM boot completed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x06: {
EventName: "boot completed - boot device not specified",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x07: {
EventName: "Base OS/Hypervisor Installation started",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x08: {
EventName: "Base OS/Hypervisor Installation completed",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x09: {
EventName: "Base OS/Hypervisor Installation aborted",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x0a: {
EventName: "Base OS/Hypervisor Installation failed",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeOSStopShutdown: {
0x00: {
EventName: "Critical stop during OS load / initialization",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "Run-time Critical Stop",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "OS Graceful Stop",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x03: {
EventName: "OS Graceful Shutdown",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x04: {
EventName: "Soft Shutdown initiated by PEF",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x05: {
EventName: "Agent Not Responding",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeSlotConnector: {
0x00: {
EventName: "Fault Status asserted",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "Identify Status asserted",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x02: {
EventName: "Slot / Connector Device installed/attached",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x03: {
EventName: "Slot / Connector Ready for Device Installation",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x04: {
EventName: "Slot/Connector Ready for Device Removal",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x05: {
EventName: "Slot Power is Off",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x06: {
EventName: "Slot / Connector Device Removal Request",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x07: {
EventName: "Interlock asserted",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x08: {
EventName: "Slot is Disabled",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x09: {
EventName: "Slot holds spare device",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
},
SensorTypeSystemACPIPowerState: {
0x00: {
EventName: "S0 / G0 (working)",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "S1 (sleeping with system h/w & processor context maintained)",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x02: {
EventName: "S2 (sleeping, processor context lost)",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x03: {
EventName: "S3 (sleeping, processor & h/w context lost, memory retained)",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x04: {
EventName: "S4 (non-volatile sleep / suspend-to disk)",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x05: {
EventName: "S5 / G2 (soft-off)",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x06: {
EventName: "S4 / S5 soft-off, particular S4 / S5 state cannot be determined",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x07: {
EventName: "G3 / Mechanical Off",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x08: {
EventName: "Sleeping in an S1, S2, or S3 states",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x09: {
EventName: "G1 sleeping",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x0a: {
EventName: "S5 entered by override",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x0b: {
EventName: "Legacy ON state",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x0c: {
EventName: "Legacy OFF state",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x0e: {
EventName: "Unknown",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeWatchdog2: {
0x00: {
EventName: "Timer expired, status only (no action, no interrupt)",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x01: {
EventName: "Hard Reset",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "Power Down",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Power Cycle",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x08: {
EventName: "Timer interrupt",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
},
SensorTypePlatformAlert: {
0x00: {
EventName: "platform generated page",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "platform generated LAN alert",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x02: {
EventName: "Platform Event Trap generated",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x03: {
EventName: "platform generated SNMP trap",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
},
SensorTypeEntityPresence: {
0x00: {
EventName: "Entity Present",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "Entity Absent",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "Entity Disable",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeMonitorASIC: {},
SensorTypeLAN: {
0x00: {
EventName: "LAN Heartbeat Lost",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x01: {
EventName: "LAN Heartbeat",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
},
SensorTypeManagementSubsystemHealth: {
0x00: {
EventName: "sensor access degraded or unavailable",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "controller access degraded or unavailable",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "management controller off-line",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "management controller unavailable",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x04: {
EventName: "Sensor failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x05: {
EventName: "FRU failure",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeBattery: {
0x00: {
EventName: "battery low (predictive failure)",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x01: {
EventName: "battery failed",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "battery presence detected",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
},
SensorTypeSessionAudit: {
0x00: {
EventName: "Session Activated",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x01: {
EventName: "Session Deactivated",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x02: {
EventName: "Invalid Username or Password",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x03: {
EventName: "Invalid password disable",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
SensorTypeVersionChange: {
0x00: {
EventName: "Hardware change detected with associated Entity",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x01: {
EventName: "Firmware or software change detected with associated Entity",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x02: {
EventName: "Hardware incompatibility detected with associated Entity",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x03: {
EventName: "Firmware or software incompatibility detected with associated Entity",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x04: {
EventName: "Entity is of an invalid or unsupported hardware version",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x05: {
EventName: "Entity contains an invalid or unsupported firmware or software version",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x06: {
EventName: "Hardware Change detected with associated Entity was successful",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x07: {
EventName: "Software or F/W Change detected with associated Entity was successful",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
},
SensorTypeFRUState: {
0x00: {
EventName: "FRU Not Installed",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x01: {
EventName: "FRU Inactive (in standby or 'hot spare' state)",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
0x02: {
EventName: "FRU Activation Requested",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x03: {
EventName: "FRU Activation In Progress",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x04: {
EventName: "FRU Active",
AssertionSeverity: EventSeverityInfo,
DeassertionSeverity: EventSeverityInfo,
},
0x05: {
EventName: "FRU Deactivation Requested",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x06: {
EventName: "FRU Deactivation In Progress",
AssertionSeverity: EventSeverityWarning,
DeassertionSeverity: EventSeverityWarning,
},
0x07: {
EventName: "FRU Communication Lost",
AssertionSeverity: EventSeverityCritical,
DeassertionSeverity: EventSeverityCritical,
},
},
}
golang-github-bougou-go-ipmi-0.7.2/types_fru.go 0000664 0000000 0000000 00000101015 14741105271 0021453 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"fmt"
"time"
)
// 38. Accessing FRU Devices
//
// FRU devices can located in three different types of location.
type FRULocation string
const (
// FRU Location: FRU Device behind a management controller
//
// only logical FRU Device can be accessed via FRU commands to mgmt controller
//
// Access Method:
// Read/Write FRU Data commands to management controller providing access to the FRU Device.
//
// Use Read/WriteFRUData command to access FRU.
// DeviceAccessAddress (Slave Address of IPMB)
// FRUDeviceID_SlaveAddress
FRULocation_MgmtController FRULocation = "on management controller"
// FRU Location: SEEPROM On private bus behind a management controller
//
// Access Method:
// Master Write-Read command to management controller that provides access to the private bus.
//
// Use MasterWriteRead command to access FRU.
// DeviceAccessAddress (Slave Address of IPMB)
// PrivateBusID
// FRUDeviceID_SlaveAddress (Slave Address of SEEPROM on the Private Bus)
FRULocation_PrivateBus FRULocation = "on private bus"
// FRU Location : SEEPROM Device directly on IPMB
//
// Access Method:
// Master Write-Read command through BMC from system software, or access via other interface
// providing low-level I2C access to the IPMB.
//
// Use MasterWriteRead command to access FRU.
// FRUDeviceID_SlaveAddress (slave address Of SEEPROM on the IPMB)
FRULocation_IPMB FRULocation = "directly on IPMB"
)
const (
FRUFormatVersion uint8 = 0x01
FRUAreaFieldsEndMark uint8 = 0xc1
FRUCommonHeaderSize uint8 = 8
)
type FRU struct {
deviceID uint8
deviceName string
deviceNotPresent bool
deviceNotPresentReason string
// FRU/17. FRU Information Layout
CommonHeader *FRUCommonHeader
InternalUseArea *FRUInternalUseArea
ChassisInfoArea *FRUChassisInfoArea
BoardInfoArea *FRUBoardInfoArea
ProductInfoArea *FRUProductInfoArea
MultiRecords []*FRUMultiRecord
}
func (fru *FRU) Present() bool {
return !fru.deviceNotPresent
}
func (fru *FRU) DeviceName() string {
return fru.deviceName
}
func (fru *FRU) DeviceID() uint8 {
return fru.deviceID
}
func (fru *FRU) String() string {
var buf = new(bytes.Buffer)
buf.WriteString(fmt.Sprintf("FRU Device Description : %s (ID %d)\n", fru.deviceName, fru.deviceID))
if !fru.Present() {
buf.WriteString(" Device not present\n")
return buf.String()
}
if fru.ChassisInfoArea != nil {
buf.WriteString(fmt.Sprintf(" Chassis Type : %s\n", fru.ChassisInfoArea.ChassisType.String()))
buf.WriteString(fmt.Sprintf(" Chassis Part Number : %s\n", fru.ChassisInfoArea.PartNumber))
buf.WriteString(fmt.Sprintf(" Chassis Serial Number: %s\n", fru.ChassisInfoArea.SerialNumber))
for _, v := range fru.ChassisInfoArea.Custom {
buf.WriteString(fmt.Sprintf(" Chassis Extra : %s\n", v))
}
}
if fru.BoardInfoArea != nil {
buf.WriteString(fmt.Sprintf(" Board Mfg Date : %s\n", fru.BoardInfoArea.MfgDateTime.String()))
buf.WriteString(fmt.Sprintf(" Board Mfg : %s\n", fru.BoardInfoArea.Manufacturer))
buf.WriteString(fmt.Sprintf(" Board Product : %s\n", fru.BoardInfoArea.ProductName))
buf.WriteString(fmt.Sprintf(" Board Serial : %s\n", fru.BoardInfoArea.SerialNumber))
buf.WriteString(fmt.Sprintf(" Board Part Number : %s\n", fru.BoardInfoArea.PartNumber))
for _, v := range fru.BoardInfoArea.Custom {
buf.WriteString(fmt.Sprintf(" Board Extra : %s\n", v))
}
}
if fru.ProductInfoArea != nil {
buf.WriteString(fmt.Sprintf(" Product Mfg : %s\n", fru.ProductInfoArea.Manufacturer))
buf.WriteString(fmt.Sprintf(" Product Name : %s\n", fru.ProductInfoArea.Name))
buf.WriteString(fmt.Sprintf(" Product Version : %s\n", fru.ProductInfoArea.Version))
buf.WriteString(fmt.Sprintf(" Product Part Number : %s\n", fru.ProductInfoArea.PartModel))
buf.WriteString(fmt.Sprintf(" Product Serial : %s\n", fru.ProductInfoArea.SerialNumber))
assetTag, _ := fru.ProductInfoArea.AssetTagTypeLength.Chars(fru.ProductInfoArea.AssetTag)
buf.WriteString(fmt.Sprintf(" Product Asset Tag : %s\n", string(assetTag)))
buf.WriteString(fmt.Sprintf(" Product Asset Tag TL : %s\n", fru.ProductInfoArea.AssetTagTypeLength))
for _, v := range fru.ProductInfoArea.Custom {
buf.WriteString(fmt.Sprintf(" Product Extra : %s\n", v))
}
}
for _, multiRecord := range fru.MultiRecords {
buf.WriteString(fmt.Sprintf(" Multi Record : %s\n", multiRecord.RecordType.String()))
}
return buf.String()
}
// FRUCommonHeader is mandatory for all FRU Information Device implementations.
// It holds version information for the overall information format specification
// and offsets to the other information areas.
//
// The other areas may or may not be present based on the application of the device.
// The offset unit in wire is in multiples of 8 bytes, offset value 0x0 indicates
// that this area is not present.
//
// ref: FRU/8. Common Header Format
type FRUCommonHeader struct {
FormatVersion uint8
InternalOffset8B uint8
ChassisOffset8B uint8
BoardOffset8B uint8
ProductOffset8B uint8
MultiRecordsOffset8B uint8
Checksum uint8
}
func (s *FRUCommonHeader) Pack() []byte {
out := make([]byte, 8)
packUint8(s.FormatVersion, out, 0)
packUint8(s.InternalOffset8B, out, 1)
packUint8(s.ChassisOffset8B, out, 2)
packUint8(s.BoardOffset8B, out, 3)
packUint8(s.ProductOffset8B, out, 4)
packUint8(s.MultiRecordsOffset8B, out, 5)
// a pad byte at index 6
packUint8(s.Checksum, out, 7)
return out
}
func (s *FRUCommonHeader) Unpack(msg []byte) error {
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
s.FormatVersion, _, _ = unpackUint8(msg, 0)
s.InternalOffset8B, _, _ = unpackUint8(msg, 1)
s.ChassisOffset8B, _, _ = unpackUint8(msg, 2)
s.BoardOffset8B, _, _ = unpackUint8(msg, 3)
s.ProductOffset8B, _, _ = unpackUint8(msg, 4)
s.MultiRecordsOffset8B, _, _ = unpackUint8(msg, 5)
s.Checksum, _, _ = unpackUint8(msg, 7)
return nil
}
func (s *FRUCommonHeader) Valid() bool {
var checksumFn = func(msg []byte, start int, end int) uint8 {
c := 0
for i := start; i < end; i++ {
c = (c + int(msg[i])) % 256
}
return -uint8(c)
}
msg := s.Pack()
return s.Checksum == checksumFn(msg, 0, 6)
}
func (s *FRUCommonHeader) String() string {
return fmt.Sprintf(`Version : %#02x
Offset Internal : %#02x
Offset Chassis : %#02x
Offset Board : %#02x
Offset Product : %#02x
Offset MultiRecord : %#02x`,
s.FormatVersion,
s.InternalOffset8B*8,
s.ChassisOffset8B*8,
s.BoardOffset8B*8,
s.ProductOffset8B*8,
s.MultiRecordsOffset8B*8,
)
}
// FRUInternalUseArea provides private, implementation-specific information storage
// for other devices that exist on the same FRU as the FRU Information Device.
//
// The Internal Use Area is usually used to provide private non-volatile storage
// for a management controller.
//
// see: FRU/9. Internal Use Area Format
type FRUInternalUseArea struct {
FormatVersion uint8
Data []byte
}
// FRUChassisInfoArea is used to hold Serial Number, Part Number, and other
// information about the system chassis. A system can have multiple FRU
// Information Devices within a chassis, but only one device should provide
// the Chassis Info Area.
//
// see: FRU/10. Chassis Info Area Format
type FRUChassisInfoArea struct {
FormatVersion uint8
Length8B uint8
ChassisType ChassisType
PartNumberTypeLength TypeLength
PartNumber []byte
SerialNumberTypeLength TypeLength
SerialNumber []byte
Custom [][]byte
Unused []byte
Checksum uint8
}
func (fruChassis *FRUChassisInfoArea) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
// Chassis Info Area Length (in multiples of 8 bytes)
if len(msg) < int(msg[1])*8 {
return ErrUnpackedDataTooShortWith(len(msg), int(msg[1])*8)
}
fruChassis.FormatVersion = msg[0]
fruChassis.Length8B = msg[1]
fruChassis.ChassisType = ChassisType(msg[2])
var offset uint16 = 3
var err error
offset, fruChassis.PartNumberTypeLength, fruChassis.PartNumber, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru chassis part number field failed, err: %w", err)
}
offset, fruChassis.SerialNumberTypeLength, fruChassis.SerialNumber, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru chassis serial number field failed, err: %w", err)
}
fruChassis.Custom, fruChassis.Unused, fruChassis.Checksum, err = getFRUCustomUnusedChecksumFields(msg, offset)
if err != nil {
return fmt.Errorf("getFRUCustomUnusedChecksumFields failed, err: %w", err)
}
return nil
}
type ChassisType uint8
func (chassisType ChassisType) String() string {
// SMBIOS Specification: Table 17 - System Enclosure or Chassis Types
var chassisTypeMaps = map[ChassisType]string{
0x00: "Unspecified",
0x01: "Other",
0x02: "Unknown",
0x03: "Desktop",
0x04: "Low Profile Desktop",
0x05: "Pizza Box",
0x06: "Mini Tower",
0x07: "Tower",
0x08: "Portable",
0x09: "Laptop",
0x0a: "Notebook",
0x0b: "Hand Held",
0x0c: "Docking Station",
0x0d: "All in One",
0x0e: "Sub Notebook",
0x0f: "Space-saving",
0x10: "Lunch Box",
0x11: "Main Server Chassis",
0x12: "Expansion Chassis",
0x13: "SubChassis",
0x14: "Bus Expansion Chassis",
0x15: "Peripheral Chassis",
0x16: "RAID Chassis",
0x17: "Rack Mount Chassis",
0x18: "Sealed-case PC",
0x19: "Multi-system chassis",
0x1a: "Compact PCI",
0x1b: "Advanced TCA",
0x1c: "Blade",
0x1d: "Blade Enclosure",
0x1e: "Tablet",
0x1f: "Convertible",
0x20: "Detachable",
0x21: "IoT Gateway",
0x22: "Embedded PC",
0x23: "Mini PC",
0x24: "Stick PC",
}
s, ok := chassisTypeMaps[chassisType]
if ok {
return s
}
return ""
}
type ChassisState uint8
func (chassisState ChassisState) String() string {
// SMBIOS Specification: Table 18 - System Enclosure or Chassis States
var chassisStateMap = map[ChassisState]string{
0x01: "Other",
0x02: "Unknown",
0x03: "Safe",
0x04: "Warning",
0x05: "Critical",
0x06: "Non-recoverable",
}
if s, ok := chassisStateMap[chassisState]; ok {
return s
}
return ""
}
type ChassisSecurityStatus uint8
func (chassisSecurityStatus ChassisSecurityStatus) String() string {
// SMBIOS Specification: // Table 19 - System Enclosure or Chassis Security Status field
var chassisSecurityStatusMap = map[ChassisSecurityStatus]string{
0x01: "Other",
0x02: "Unknown",
0x03: "None",
0x04: "External interface locked out",
0x05: "External interface enabled",
}
if s, ok := chassisSecurityStatusMap[chassisSecurityStatus]; ok {
return s
}
return ""
}
// FRUBoardInfoArea provides Serial Number, Part Number, and other information about
// the board that the FRU Information Device is located on.
// The name 'Board Info Area' is somewhat a misnomer, because the usage is not
// restricted to just circuit boards. This area is also typically used to
// provide FRU information for any replaceable entities, boards, or sub-assemblies
// that are not sold as standalone products separate from other components.
// For example, individual boards from a board set, or a sub-chassis or backplane
// that's part of a larger chassis.1
//
// see: FRU/11. Board Info Area Format
type FRUBoardInfoArea struct {
FormatVersion uint8
Length8B uint8
LanguageCode uint8
MfgDateTime time.Time
ManufacturerTypeLength TypeLength
Manufacturer []byte
ProductNameTypeLength TypeLength
ProductName []byte
SerialNumberTypeLength TypeLength
SerialNumber []byte
PartNumberTypeLength TypeLength
PartNumber []byte
FRUFileIDTypeLength TypeLength
FRUFileID []byte
Custom [][]byte
Unused []byte
Checksum uint8
}
func (fruBoard *FRUBoardInfoArea) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
// Board Area Length (in multiples of 8 bytes)
if len(msg) < int(msg[1])*8 {
return ErrUnpackedDataTooShortWith(len(msg), int(msg[1])*8)
}
fruBoard.FormatVersion = msg[0]
fruBoard.Length8B = msg[1]
fruBoard.LanguageCode = msg[2]
m, _, _ := unpackUint24L(msg, 3) // Number of minutes from 0:00 hrs 1/1/96.
const secsFrom1970To1996 uint32 = 820454400
fruBoard.MfgDateTime = parseTimestamp(secsFrom1970To1996 + m*60)
var offset uint16 = 6
var err error
offset, fruBoard.ManufacturerTypeLength, fruBoard.Manufacturer, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru board manufacturer field failed, err: %w", err)
}
offset, fruBoard.ProductNameTypeLength, fruBoard.ProductName, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru board product name field failed, err: %w", err)
}
offset, fruBoard.SerialNumberTypeLength, fruBoard.SerialNumber, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru board serial number field failed, err: %w", err)
}
offset, fruBoard.PartNumberTypeLength, fruBoard.PartNumber, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru board part number field failed, err: %w", err)
}
offset, fruBoard.FRUFileIDTypeLength, fruBoard.FRUFileID, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru board file id field failed, err: %w", err)
}
fruBoard.Custom, fruBoard.Unused, fruBoard.Checksum, err = getFRUCustomUnusedChecksumFields(msg, offset)
if err != nil {
return fmt.Errorf("getFRUCustomUnusedChecksumFields failed, err: %w", err)
}
return nil
}
type BoardType uint8
func (boardType BoardType) String() string {
var boardTypeMap = map[BoardType]string{
0x01: "Unknown",
0x02: "Other",
0x03: "Server Blade",
0x04: "Connectivity Switch",
0x05: "System Management Module",
0x06: "Processor Module",
0x07: "I/O Module",
0x08: "Memory Module",
0x09: "Daughter board",
0x0a: "Motherboard",
0x0b: "Processor/Memory Module",
0x0c: "Processor/IO Module",
0x0d: "Interconnect board",
}
if s, ok := boardTypeMap[boardType]; ok {
return s
}
return ""
}
// The Product Info Area is present if the FRU itself is a separate product.
// This is typically seen when the FRU is an add-in card, sub-assembly, or
// a power supply from a separate vendor, etc.
// When this area is provided in the FRU Information Device that contains the
// Chassis Info Area, the product info is for the overall system, as initially manufactured.
//
// see: FRU/12. Product Info Area Format
type FRUProductInfoArea struct {
FormatVersion uint8
Length8B uint8
LanguageCode uint8
ManufacturerTypeLength TypeLength
Manufacturer []byte
NameTypeLength TypeLength
Name []byte
PartModelTypeLength TypeLength
PartModel []byte
VersionTypeLength TypeLength
Version []byte
SerialNumberTypeLength TypeLength
SerialNumber []byte
AssetTagTypeLength TypeLength
AssetTag []byte
FRUFileIDTypeLength TypeLength
FRUFileID []byte
Custom [][]byte
Unused []byte
Checksum uint8
}
func (fruProduct *FRUProductInfoArea) Unpack(msg []byte) error {
if len(msg) < 2 {
return ErrUnpackedDataTooShortWith(len(msg), 2)
}
// Product Area Length (in multiples of 8 bytes)
if len(msg) < int(msg[1])*8 {
return ErrUnpackedDataTooShortWith(len(msg), int(msg[1])*8)
}
fruProduct.FormatVersion = msg[0]
fruProduct.Length8B = msg[1]
fruProduct.LanguageCode = msg[2]
var offset uint16 = 3
var err error
offset, fruProduct.ManufacturerTypeLength, fruProduct.Manufacturer, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru product manufacturer field failed, err: %w", err)
}
offset, fruProduct.NameTypeLength, fruProduct.Name, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru product name field failed, err: %w", err)
}
offset, fruProduct.PartModelTypeLength, fruProduct.PartModel, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru product part model field failed, err: %w", err)
}
offset, fruProduct.VersionTypeLength, fruProduct.Version, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru product version field failed, err: %w", err)
}
offset, fruProduct.SerialNumberTypeLength, fruProduct.SerialNumber, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru product serial number field failed, err: %w", err)
}
offset, fruProduct.AssetTagTypeLength, fruProduct.AssetTag, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru product asset tag field failed, err: %w", err)
}
offset, fruProduct.FRUFileIDTypeLength, fruProduct.FRUFileID, err = getFRUTypeLengthField(msg, offset)
if err != nil {
return fmt.Errorf("get fru product file id field failed, err: %w", err)
}
fruProduct.Custom, fruProduct.Unused, fruProduct.Checksum, err = getFRUCustomUnusedChecksumFields(msg, offset)
if err != nil {
return fmt.Errorf("getFRUCustomUnusedChecksumFields failed, err: %w", err)
}
return nil
}
// The MultiRecord Info Area provides a region that holds one or more records
// where the type and format of the information is specified in the individual
// headers for the records.
//
// see: FRU/16. MultiRecord Area
type FRUMultiRecord struct {
RecordType FRURecordType // used to identify the information contained in the record
EndOfList bool // indicates if this record is the last record in the MultiRecord area
// Record Format version (=2h unless otherwise specified)
// This field is used to identify the revision level of information stored in this area.
// This number will start at zero for each new area. If changes need to be made to the record,
// e.g. fields added/removed, the version number will be increased to reflect the change.
FormatVersion uint8
// RecordLength indicates the number of bytes of data in the record. This byte can also be used to find the
// next area in the list. If the "End of List" bit is zero, the length can be added the starting offset of the current
// Record Data to get the offset of the next Record Header. This field allows for 0 to 255 bytes of data for
// each record.
RecordLength uint8
RecordChecksum uint8
HeaderChecksum uint8
RecordData []byte
}
func (fruMultiRecord *FRUMultiRecord) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
// RecordLength
if len(msg) < int(msg[2]) {
return ErrUnpackedDataTooShortWith(len(msg), int(msg[2]))
}
fruMultiRecord.RecordType = FRURecordType(msg[0])
b1 := msg[1]
fruMultiRecord.EndOfList = isBit7Set(b1)
fruMultiRecord.FormatVersion = b1 & 0x0f
fruMultiRecord.RecordLength = msg[2]
fruMultiRecord.RecordChecksum = msg[3]
fruMultiRecord.HeaderChecksum = msg[4]
dataLen := int(fruMultiRecord.RecordLength)
fruMultiRecord.RecordData, _, _ = unpackBytes(msg, 5, dataLen)
return nil
}
type FRURecordType uint8
func (t FRURecordType) String() string {
// fru: Table 16-2, MultiRecord Area Record Types
m := map[FRURecordType]string{
0x00: "Power Supply",
0x01: "DC Output",
0x02: "DC Load",
0x03: "Management Access",
0x04: "Base Compatibility",
0x05: "Extended Compatibility",
0x06: "ASF Fixed SMBus Device", // see [ASF_2.0] for definition
0x07: "ASF Legacy-Device Alerts", // see [ASF_2.0] for definition
0x08: "ASF Remote Control", // see [ASF_2.0] for definition
0x09: "Extended DC Output",
0x0a: "Extended DC Load",
// 0x0b-0x0f reserved for definition by working group, Refer to specifications from the NVM Express™ working group (www.nvmexpress.org)
// 0x10-0xbf reserved
// 0xc0-0xff OEM Record Types
}
s, ok := m[t]
if ok {
return s
}
return ""
}
// fru: 18.1 Power Supply Information (Record Type 0x00)
type FRURecordTypePowerSupply struct {
// This field allows for Power Supplies with capacities from 0 to 4095 watts.
OverallCapacity uint16
// The highest instantaneous VA value that this supply draws during operation (other than during Inrush). In integer units. FFFFh if not specified.
PeakVA uint16
// Maximum inrush of current, in Amps, into the power supply. FFh if not specified.
InrushCurrent uint8 // 涌入电流
// Number of milliseconds before power supply loading enters non-startup operating range. Set to 0 if no inrush current specified.
InrushIntervalMilliSecond uint8
// This specifies the low end of acceptable voltage into the power supply. The units are 10mV.
LowEndInputVoltageRange1 uint16
// This specifies the high end of acceptable voltage into the power supply. The units are 10mV.
HighEndInputVoltageRange1 uint16
// This specifies the low end of acceptable voltage into the power supply. This field would be used if the power supply did not support auto-switch. Range 1 would define the 110V range, while range 2 would be used for 220V. The units are 10mV.
LowEndInputVoltageRange2 uint16
// This specifies the high end of acceptable voltage into the power supply. This field would be used if the power supply did not support auto-switch. Range 1 would define the 110V range, while range 2 would be used for 220V. The units are 10mV.
HighEndInputVoltageRange2 uint16
// This specifies the low end of acceptable frequency range into the power supply. Use 00h if supply accepts a DC input.
LowEndInputFrequencyRange uint8
// This specifies the high end of acceptable frequency range into the power supply. Use 00h for both Low End and High End frequency range if supply only takes a DC input.
HighEndInputFrequencyRange uint8
// Minimum number of milliseconds the power supply can hold up POWERGOOD (and maintain valid DC output) after input power is lost.
InputDropoutToleranceMilliSecond uint8
HotSwapSupport bool
AutoSwitch bool
PowerFactorCorrection bool
PredictiveFailSupport bool
// the number of seconds peak wattage can be sustained (0-15 seconds)
PeakWattageHoldupSecond uint8
// the peak wattage the power supply can produce during this time period
PeakCapacity uint16
CombinedWattageVoltage1 uint8 // bit 7:4 - Voltage 1
CombinedWattageVoltage2 uint8 // bit 3:0 - Voltage 2
// 0000b (0) 12V
// 0001b (1) -12V
// 0010b (2) 5V
// 0011b (3) 3.3V
TotalCombinedWattage uint16
// This field serves two purposes.
// It clarifies what type of predictive fail the power supply supports
// (pass/fail signal or the tachometer output of the power supply fan)
// and indicates the predictive failing point for tach outputs.
// This field should be written as zero and ignored if the
// predictive failure pin of the power supply is not supported.
//
// 0x00 Predictive fail pin indicates pass/fail
// 0x01 - 0xFF Lower threshold to indicate predictive failure (Rotations per second)
PredictiveFailTachometerLowerThreshold uint8 // RPS
}
// FRU: 18.2 DC Output (Record Type 0x01)
type FRURecordTypeDCOutput struct {
// if the power supply provides this output even when the power supply is switched off.
OutputWhenOff bool
OutputNumber uint8
// Expected voltage from the power supply. Value is a signed short given in 10 millivolt increments.
// 额定电压 毫-伏特
NominalVoltage10mV int16
MaxNegativeVoltage10mV int16
MaxPositiveVoltage10mV int16
RippleNoise1mV uint16
// 毫-安培
MinCurrentDraw1mA uint16
MaxCurrentDraw1mA uint16
}
func (output *FRURecordTypeDCOutput) Unpack(msg []byte) error {
if len(msg) < 12 {
return ErrUnpackedDataTooShortWith(len(msg), 12)
}
b, _, _ := unpackUint8(msg, 0)
output.OutputWhenOff = isBit7Set(b)
output.OutputNumber = b & 0x0f
b1, _, _ := unpackUint16L(msg, 1)
output.NominalVoltage10mV = int16(b1)
b3, _, _ := unpackUint16L(msg, 3)
output.MaxNegativeVoltage10mV = int16(b3)
b5, _, _ := unpackUint16L(msg, 5)
output.MaxPositiveVoltage10mV = int16(b5)
output.RippleNoise1mV, _, _ = unpackUint16L(msg, 7)
output.MinCurrentDraw1mA, _, _ = unpackUint16L(msg, 9)
output.MaxCurrentDraw1mA, _, _ = unpackUint16L(msg, 11)
return nil
}
// FRU: 18.2a Extended DC Output (Record Type 0x09)
type FRURecordTypeExtendedDCOutput struct {
// if the power supply provides this output even when the power supply is switched off.
OutputWhenOff bool
// This record can be used to support power supplies with outputs that exceed 65.535 Amps.
// 0b = 10 mA
// 1b = 100 mA
CurrentUnits100 bool
OutputNumber uint8
// Expected voltage from the power supply. Value is a signed short given in 10 millivolt increments.
// 毫-伏特
NominalVoltage10mV int16
MaxNegativeVoltage10mV int16
MaxPositiveVoltage10mV int16
RippleNoise uint16
// The unit is determined by CurrentUnits100 field.
MinCurrentDraw uint16
MaxCurrentDraw uint16
}
func (output *FRURecordTypeExtendedDCOutput) Unpack(msg []byte) error {
if len(msg) < 12 {
return ErrUnpackedDataTooShortWith(len(msg), 12)
}
b, _, _ := unpackUint8(msg, 0)
output.OutputWhenOff = isBit7Set(b)
output.CurrentUnits100 = isBit4Set(b)
output.OutputNumber = b & 0x0f
b1, _, _ := unpackUint16L(msg, 1)
output.NominalVoltage10mV = int16(b1)
b3, _, _ := unpackUint16L(msg, 3)
output.MaxNegativeVoltage10mV = int16(b3)
b5, _, _ := unpackUint16L(msg, 5)
output.MaxPositiveVoltage10mV = int16(b5)
output.RippleNoise, _, _ = unpackUint16L(msg, 7)
output.MinCurrentDraw, _, _ = unpackUint16L(msg, 9)
output.MaxCurrentDraw, _, _ = unpackUint16L(msg, 11)
return nil
}
// FRU: 18.3 DC Load (Record Type 0x02)
type FRURecordTypeDCLoad struct {
OutputNumber uint8
NominalVoltage10mV int16
MinTolerableVoltage10mV int16
MaxTolerableVoltage10mV int16
RippleNoise1mV uint16
MinCurrentLoad1mA uint16
MaxCurrentLoad1mA uint16
}
func (output *FRURecordTypeDCLoad) Unpack(msg []byte) error {
if len(msg) < 12 {
return ErrUnpackedDataTooShortWith(len(msg), 12)
}
b, _, _ := unpackUint8(msg, 0)
output.OutputNumber = b & 0x0f
b1, _, _ := unpackUint16L(msg, 1)
output.NominalVoltage10mV = int16(b1)
b3, _, _ := unpackUint16L(msg, 3)
output.MinTolerableVoltage10mV = int16(b3)
b5, _, _ := unpackUint16L(msg, 5)
output.MaxTolerableVoltage10mV = int16(b5)
output.RippleNoise1mV, _, _ = unpackUint16L(msg, 7)
output.MinCurrentLoad1mA, _, _ = unpackUint16L(msg, 9)
output.MaxCurrentLoad1mA, _, _ = unpackUint16L(msg, 11)
return nil
}
// FRU: 18.3a Extended DC Load (Record Type 0x0A)
type FRURecordTypeExtendedDCLoad struct {
IsCurrentUnit100mA bool // current units: true = 100 mA , false = 10 mA
OutputNumber uint8
NominalVoltage10mV int16
MinVoltage10mV int16
MaxVoltage10mV int16
RippleNoise1mV int16
MinCurrentLoad uint16 // units is determined by IsCurrentUnit100mA field
MaxCurrentLoad uint16 // units is determined by IsCurrentUnit100mA field
}
func (f *FRURecordTypeExtendedDCLoad) Unpack(msg []byte) error {
if len(msg) < 13 {
return ErrUnpackedDataTooShortWith(len(msg), 13)
}
f.IsCurrentUnit100mA = isBit7Set(msg[0])
f.OutputNumber = msg[0] & 0x0f
b1, _, _ := unpackUint16L(msg, 1)
f.NominalVoltage10mV = int16(b1)
b3, _, _ := unpackUint16L(msg, 3)
f.MinVoltage10mV = int16(b3)
b5, _, _ := unpackUint16L(msg, 5)
f.MaxVoltage10mV = int16(b5)
b7, _, _ := unpackUint16L(msg, 7)
f.RippleNoise1mV = int16(b7)
f.MinCurrentLoad, _, _ = unpackUint16L(msg, 9)
f.MaxCurrentLoad, _, _ = unpackUint16L(msg, 11)
return nil
}
type ManagementAccessSubRecordType uint8
func (t ManagementAccessSubRecordType) String() string {
m := map[ManagementAccessSubRecordType]string{
// SystemMgmtURL []byte
// A name to identify the system that contains this FRU. (same as DMI
// DMTF|General Information|001 - System Name)
0x01: "System Management URL",
// SystemName []byte
// The IP network address of the system that contains this FRU. Can be either the IP
// address or the host name + domain name (eg. finance.sc.hp.com)
0x02: "System Name",
// SystemPingAddr []byte
// The Internet Uniform Resource Locator string that can be used through a World
// Wide Web browser to obtain management information about this FRU. (same as DMI
// DMTF|Field Replaceable Unit|002 - FRU Internet Uniform Resource Locator)
0x03: "System Ping Address",
// ComponentMgmtURL []byte
// A clear description of this FRU. (same asDMI "DMTF|Field Replaceable Unit|002 - Description")
0x04: "Component Management URL",
// ComponentName []byte
// The IP network address of this FRU. Can be either the IP address or the host name
// + domain name (e.g. critter.sc.hp.com).
0x05: "Component Name",
// ComponentPingAddr []byte
// This is a copy of the system GUID from [SMBIOS]
0x06: "Component Ping Address",
// SystemUniqueID [16]byte
0x07: "System Unique ID",
}
s, ok := m[t]
if ok {
return s
}
return ""
}
// FRU: 18.4 Management Access Record (Record Type 0x03)
type FRURecordTypeManagementAccess struct {
SubRecordType ManagementAccessSubRecordType
Data []byte // the size is MultiRecord.TypeLength.Length() - 1
}
func (f *FRURecordTypeManagementAccess) Unpack(msg []byte) error {
if len(msg) < 1 {
return ErrUnpackedDataTooShortWith(len(msg), 1)
}
f.SubRecordType = ManagementAccessSubRecordType(msg[0])
f.Data, _, _ = unpackBytes(msg, 1, len(msg)-1)
return nil
}
// FRU: 18.5 Base Compatibility Record (Record Type 0x04)
type FRURecordTypeBaseCompatibility struct {
ManufacturerID uint32
EntityID EntityID
CompatibilityBase uint8
CompatibilityCodeStart uint8
CodeRangeMask uint8
}
func (f *FRURecordTypeBaseCompatibility) Unpack(msg []byte) error {
if len(msg) < 7 {
return ErrUnpackedDataTooShortWith(len(msg), 7)
}
f.ManufacturerID, _, _ = unpackUint24L(msg, 0)
f.EntityID = EntityID(msg[3])
f.CompatibilityBase = msg[4]
f.CompatibilityCodeStart = msg[5]
f.CodeRangeMask = msg[6]
return nil
}
// FRU: 18.6 Extended Compatibility Record (Record Type 0x05)
type FRURecordTypeExtendedCompatibilityRecord struct {
ManufacturerID uint32
EntityID EntityID
CompatibilityBase uint8
CompatibilityCodeStart uint8
CodeRangeMask uint8
}
func (f *FRURecordTypeExtendedCompatibilityRecord) Unpack(msg []byte) error {
if len(msg) < 7 {
return ErrUnpackedDataTooShortWith(len(msg), 7)
}
f.ManufacturerID, _, _ = unpackUint24L(msg, 0)
f.EntityID = EntityID(msg[3])
f.CompatibilityBase = msg[4]
f.CompatibilityCodeStart = msg[5]
f.CodeRangeMask = msg[6]
return nil
}
// FRU: 18.7 OEM Record (Record Types 0xC0-0xFF)
type FRURecordTypeOEM struct {
ManufacturerID uint32
Data []byte
}
func (f *FRURecordTypeOEM) Unpack(msg []byte) error {
if len(msg) < 3 {
return ErrUnpackedDataTooShortWith(len(msg), 3)
}
f.ManufacturerID, _, _ = unpackUint24L(msg, 0)
f.Data, _, _ = unpackBytes(msg, 3, len(msg)-3)
return nil
}
// getFRUTypeLengthField return a field data bytes whose length is determined by
// a TypeLength byte. The offset index SHOULD points to the TypeLength field.
func getFRUTypeLengthField(fruData []byte, offset uint16) (nextOffset uint16, typeLength TypeLength, fieldData []byte, err error) {
if len(fruData) < int(offset+1) {
err = ErrUnpackedDataTooShortWith(len(fruData), int(offset+1))
return
}
typeLength = TypeLength(fruData[offset])
length := typeLength.Length()
if len(fruData) < int(offset)+int(length)+1 {
err = ErrUnpackedDataTooShortWith(len(fruData), int(offset)+int(length)+1)
return
}
dataStart := int(offset) + 1
dataEnd := dataStart + int(length)
fieldDataRaw := fruData[dataStart:dataEnd]
fieldData, err = typeLength.Chars(fieldDataRaw)
if err != nil {
err = fmt.Errorf("get chars from typelength failed, err: %w", err)
return
}
nextOffset = offset + uint16(length) + 1
return
}
// getFRUCustomUnusedChecksumFields is a helper function to get
// custom, unused, and checksum these three fields from fru data.
// The offset SHOULD points to the start of the custom area fields.
func getFRUCustomUnusedChecksumFields(fruData []byte, offset uint16) (custom [][]byte, unused []byte, checksum uint8, err error) {
if len(fruData) < int(offset+1) {
err = ErrUnpackedDataTooShortWith(len(fruData), int(offset+1))
return
}
for {
if fruData[offset] == FRUAreaFieldsEndMark {
break
}
nextOffset, _, fieldData, e := getFRUTypeLengthField(fruData, offset)
if e != nil {
err = fmt.Errorf("getFRUTypeLengthField failed, err: %s", e)
return
}
offset = nextOffset
if len(fieldData) == 0 {
break
}
custom = append(custom, fieldData)
}
unusedBytesOffset := int(offset) + 1
unusedBytesLen := len(fruData) - int(offset) - 2
unused, _, _ = unpackBytes(fruData, unusedBytesOffset, unusedBytesLen)
checksum = fruData[len(fruData)-1]
return
}
golang-github-bougou-go-ipmi-0.7.2/types_generator.go 0000664 0000000 0000000 00000007550 14741105271 0022656 0 ustar 00root root 0000000 0000000 package ipmi
// 5.4 Sensor Owner Identification
// the "owner" of the sensor.
// The combination of Sensor Owner ID and Sensor Number uniquely identify a sensor in the system.
// the Sensor Data Record and SEL information must contain information to identify the "owner" of the sensor.
//
// For management controllers, a Slave Address and LUN identify the owner of a sensor on the IPMB.
//
// For system software, a Software ID identifies the owner of a sensor.
//
// These fields are used in Event Messages, where events from management controllers or the IPMB are identified by an eight-bit field where the upper 7-bits are the Slave Address or System Software ID.
//
// The least significant bit is a 0 if the value represents a Slave Address and a 1 if the value represents a System Software ID.
// So all Software IDs are odd numbers (because the bit 0 is fixed to 1b),
// and all slave addresses are even numbers (because bit 0 is fixed to 0b)
//
// 5.5 Software IDs (SWIDs)
type SoftwareID uint8
type SoftwareType string
const (
SoftwareTypeBIOS SoftwareType = "BIOS"
SoftwareTypeSMIHandler SoftwareType = "SMI Handler"
SoftwareTypeSMS SoftwareType = "System Management Software"
SoftwareTypeOEM SoftwareType = "OEM"
SoftwareTypeRCS SoftwareType = "Remote Console Software"
SoftwareTypeTerminalRCS SoftwareType = "Terminal Mode Remote Console Software"
SoftwareTypeReserved SoftwareType = "Reserved"
)
// Software IDs can be cla
func (i SoftwareID) Type() SoftwareType {
if i >= SoftwareID(0x01) && i <= SoftwareID(0x1f) {
return SoftwareTypeBIOS
}
if i >= SoftwareID(0x21) && i <= SoftwareID(0x3f) {
return SoftwareTypeSMIHandler
}
if i >= SoftwareID(0x41) && i <= SoftwareID(0x5f) {
return SoftwareTypeSMS
}
if i >= SoftwareID(0x61) && i <= SoftwareID(0x7f) {
return SoftwareTypeOEM
}
if i >= SoftwareID(0x81) && i <= SoftwareID(0x8d) {
return SoftwareTypeRCS
}
if i == SoftwareID(0x8f) {
return SoftwareTypeTerminalRCS
}
return SoftwareTypeReserved
}
// GeneratorID is 2 bytes.
// the LSB means: Slave Address (for IPMB) or Software ID (for system software);
// the MSB means: Channel Number / LUN (for IPMB) or always 0 (for system software)
//
// In some scenario, the GeneratorID is used as 1 byte, because
// for IPMB, the Slave Address and LUN info are carried in IPMI Request/Response Messages;
// and for system software, the MSB is always 0, so only LSB is need.
// 32.1 SEL Event Records
//
// Byte 1
// [7:1] - 7-bit Slave Address, or 7-bit system software ID
// [0] 0b = IPMB Slave Address, 1b = system software ID
// Byte 2
// [7:4] - Channel number. Channel that event message was received over. 0h if the
// event message was received via the system interface, primary IPMB, or
// internally generated by the BMC. (New for IPMI v1.5. These bits were reserved
// in IPMI v1.0)
// [3:2] - reserved. Write as 00b.
// [1:0] - IPMB device LUN if byte 1 holds Slave Address. 00b otherwise
type GeneratorID uint16
const (
GeneratorBMC GeneratorID = 0x0020
GeneratorBIOSPOST GeneratorID = 0x0001
GeneratorBIOSSMIHandler GeneratorID = 0x0033
GeneratorIntelNMFirmware GeneratorID = 0x002c // Node Manager
GeneratorIntelMEFirmware GeneratorID = 0x602c // Management Engine
// With Microsoft Windows Server* 2003 R2 and later versions, an Intelligent Platform Management Interface (IPMI) driver was added.
// This added the capability of logging some operating system events to the SEL.
GeneratorMicrosoftOS GeneratorID = 0x0041
// The **Open IPMI driver** supports the ability to put semi-custom and custom events in the system event log if a panic occurs.
GeneratorLinuxKernelPanic GeneratorID = 0x0021
)
// see: Intel System Event Log (SEL) Troubleshooting Guide Rev 3.4 September 2019 section 3.1
type SensorNumber uint8
const SensorNumberReserved = 0xff
type SDRMapBySensorNumber map[GeneratorID]map[SensorNumber]*SDR
golang-github-bougou-go-ipmi-0.7.2/types_guid.go 0000664 0000000 0000000 00000012264 14741105271 0021616 0 ustar 00root root 0000000 0000000 package ipmi
import (
"encoding/binary"
"fmt"
"time"
"github.com/google/uuid"
)
// GUIDMode is the way how to decode the 16 bytes GUID
type GUIDMode uint8
const (
GUIDModeRFC4122 GUIDMode = iota
GUIDModeIPMI
GUIDModeSMBIOS
)
func (guidMode GUIDMode) String() string {
m := map[GUIDMode]string{
GUIDModeRFC4122: "RFC4122",
GUIDModeIPMI: "IPMI",
GUIDModeSMBIOS: "SMBIOS",
}
if s, ok := m[guidMode]; ok {
return s
}
return ""
}
// ParseGUID parses the raw guid data with the specified encoding mode.
// Different GUIDMode would interpret the [16]byte data into different layout of uuid.
//
// see: https://github.com/ipmitool/ipmitool/issues/25
func ParseGUID(data []byte, guidMode GUIDMode) (*uuid.UUID, error) {
if len(data) != 16 {
return nil, fmt.Errorf("the length of GUID data must be 16 (%d)", len(data))
}
d := array16(data)
switch guidMode {
case GUIDModeRFC4122:
return parseGUID_RFC4122(d)
case GUIDModeIPMI:
return parseGUID_IPMI(d)
case GUIDModeSMBIOS:
return parseGUID_SMBIOS(d)
default:
return nil, fmt.Errorf("unknown GUIDMode: (%s)", guidMode)
}
}
func parseGUID_RFC4122(data [16]byte) (*uuid.UUID, error) {
u, err := uuid.FromBytes(data[:])
if err != nil {
return nil, err
}
return &u, nil
}
// see: 20.8 Get Device GUID Command
func parseGUID_IPMI(data [16]byte) (*uuid.UUID, error) {
var rfc4122Data [16]byte
// time_low
rfc4122Data[0] = data[15]
rfc4122Data[1] = data[14]
rfc4122Data[2] = data[13]
rfc4122Data[3] = data[12]
// time_mid
rfc4122Data[4] = data[11]
rfc4122Data[5] = data[10]
// time_high_and_version
rfc4122Data[6] = data[9]
rfc4122Data[7] = data[8]
// clock_seq_hi_and_reserved
rfc4122Data[8] = data[7]
// clock_seq_low
rfc4122Data[9] = data[6]
// node
rfc4122Data[10] = data[5]
rfc4122Data[11] = data[4]
rfc4122Data[12] = data[3]
rfc4122Data[13] = data[2]
rfc4122Data[14] = data[1]
rfc4122Data[15] = data[0]
return parseGUID_RFC4122(rfc4122Data)
}
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.2.0.pdf
//
// 921 7.2.1 System — UUID
//
// 928 Although RFC4122 recommends network byte order for all fields, the PC industry (including the ACPI,
// 929 UEFI, and Microsoft specifications) has consistently used little-endian byte encoding for the first three
// 930 fields: time_low, time_mid, time_hi_and_version. The same encoding, also known as wire format, should
// 931 also be used for the SMBIOS representation of the UUID.
// 932 The UUID {00112233-4455-6677-8899-AABBCCDDEEFF} would thus be represented as:
// 933 33 22 11 00 55 44 77 66 88 99 AA BB CC DD EE FF.
// 934 If the value is all FFh, the ID is not currently present in the system, but it can be set. If the value is all 00h,
// 935 the ID is not present in the system.
func parseGUID_SMBIOS(data [16]byte) (*uuid.UUID, error) {
var rfc4122Data [16]byte
// time_low
rfc4122Data[0] = data[3]
rfc4122Data[1] = data[2]
rfc4122Data[2] = data[1]
rfc4122Data[3] = data[0]
// time_mid
rfc4122Data[4] = data[5]
rfc4122Data[5] = data[4]
// time_hi_and_version
rfc4122Data[6] = data[7]
rfc4122Data[7] = data[6]
// clock_seq_hi_and_reserved
rfc4122Data[8] = data[8]
// clock_seq_low
rfc4122Data[9] = data[9]
// node
rfc4122Data[10] = data[10]
rfc4122Data[11] = data[11]
rfc4122Data[12] = data[12]
rfc4122Data[13] = data[13]
rfc4122Data[14] = data[14]
rfc4122Data[15] = data[15]
return parseGUID_RFC4122(rfc4122Data)
}
// see https://github.com/ipmitool/ipmitool/issues/25#issuecomment-409703163
func IPMILegacyGUIDTime(u *uuid.UUID) time.Time {
sec := int64(binary.BigEndian.Uint32(u[0:4]))
return time.Unix(sec, 0)
}
// see: https://uuid.ramsey.dev/en/stable/rfc4122.html
func UUIDVersionString(u *uuid.UUID) string {
v := u.Version()
var name string
switch v {
case 1:
name = "Time-based Gregorian Time"
case 2:
name = "Time-based DCE Security with POSIX UIDs"
case 3:
name = "Name-based MD5"
case 4:
name = "Random"
case 5:
name = "Name-based SHA-1"
case 6:
name = "Reordered Time"
case 7:
name = "Unix Epoch Time"
case 8:
name = "Custom"
default:
name = "Unknown"
}
return fmt.Sprintf("%s (%s)", v.String(), name)
}
func FormatGUIDDetails(guid [16]byte) string {
formatGUID := func(u *uuid.UUID, mode GUIDMode) string {
out := fmt.Sprintf("UUID Encoding : %s\n", mode)
out += fmt.Sprintf("GUID : %s\n", u.String())
out += fmt.Sprintf("UUID Version : %s\n", UUIDVersionString(u))
out += fmt.Sprintf("UUID Variant : %s\n", u.Variant().String())
sec, nsec := u.Time().UnixTime()
out += fmt.Sprintf("Timestamp : %s\n", time.Unix(sec, nsec).Format(timeFormat))
out += fmt.Sprintf("Timestamp(Legacy) : %s\n", IPMILegacyGUIDTime(u).Format(timeFormat))
return out
}
out := ""
u, err := ParseGUID(guid[:], GUIDModeSMBIOS)
if err != nil {
return ""
}
out += formatGUID(u, GUIDModeSMBIOS)
out += "\n-------------------\n"
u, err = ParseGUID(guid[:], GUIDModeIPMI)
if err != nil {
return ""
}
out += "\n"
out += formatGUID(u, GUIDModeIPMI)
out += "\n-------------------\n"
u, err = ParseGUID(guid[:], GUIDModeRFC4122)
if err != nil {
return ""
}
out += "\n"
out += formatGUID(u, GUIDModeRFC4122)
out += "\n-------------------\n"
return out
}
golang-github-bougou-go-ipmi-0.7.2/types_guid_test.go 0000664 0000000 0000000 00000004440 14741105271 0022652 0 ustar 00root root 0000000 0000000 package ipmi
import (
"fmt"
"strings"
"testing"
"time"
)
func Test_ParseGUID(t *testing.T) {
tests := []struct {
input [16]byte
expecteds map[GUIDMode]string
}{
{
input: [16]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
expecteds: map[GUIDMode]string{
GUIDModeRFC4122: "00112233-4455-6677-8899-AABBCCDDEEFF",
GUIDModeIPMI: "FFEEDDCC-BBAA-9988-7766-554433221100",
GUIDModeSMBIOS: "33221100-5544-7766-8899-AABBCCDDEEFF",
},
},
}
for _, tt := range tests {
for _, mode := range []GUIDMode{
GUIDModeRFC4122,
GUIDModeIPMI,
GUIDModeSMBIOS,
} {
u, err := ParseGUID(tt.input[:], mode)
if err != nil {
t.Error(err)
return
}
actual := strings.ToUpper(u.String())
expected := tt.expecteds[mode]
sec, nsec := u.Time().UnixTime()
uTime := time.Unix(sec, nsec)
fmt.Printf("mode: %s, string: %s, version: %s, variant: %s, time: %v\n", mode, actual, u.Version(), u.Variant(), uTime)
if actual != expected {
t.Errorf("not matched for GUIDMode (%s), actual (%s), expected (%s)", mode, actual, expected)
return
}
}
}
}
func Test_ParseGUID2(t *testing.T) {
tests := []struct {
inputs map[GUIDMode][16]byte
mode GUIDMode
expected string
}{
{
inputs: map[GUIDMode][16]byte{
GUIDModeRFC4122: {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
GUIDModeIPMI: {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00},
GUIDModeSMBIOS: {0x33, 0x22, 0x11, 0x00, 0x55, 0x44, 0x77, 0x66, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
},
expected: "00112233-4455-6677-8899-AABBCCDDEEFF",
},
}
for _, tt := range tests {
for mode, input := range tt.inputs {
u, err := ParseGUID(input[:], mode)
if err != nil {
t.Error(err)
return
}
actual := strings.ToUpper(u.String())
expected := tt.expected
sec, nsec := u.Time().UnixTime()
uTime := time.Unix(sec, nsec)
fmt.Printf("mode: %s, string: %s, version: %s, variant: %s, time: %v\n", mode, actual, u.Version(), u.Variant(), uTime)
if actual != expected {
t.Errorf("not matched for GUIDMode (%s), actual (%s), expected (%s)", mode, actual, expected)
return
}
}
}
}
golang-github-bougou-go-ipmi-0.7.2/types_ipmb.go 0000664 0000000 0000000 00000002214 14741105271 0021607 0 ustar 00root root 0000000 0000000 package ipmi
// see: https://community.infineon.com/t5/Knowledge-Base-Articles/Difference-between-7-bit-vs-8-bit-I2C-addressing/ta-p/798072
//
// I2CAddress7Bit is a 7-bit I2C address, the bit 0 to bit 6 take effect, bit 7 is always 0.
//
// eg: `var a I2CAddress7Bit = 0x35`
// - 0 011 0101 = 0x35
// - 7 654 3210 bit position
type I2CAddress7Bit uint8
// I2CAddress8Bit represents 8-bit I2C address, the 7-bit I2CAddress occupies bit 1 to bit 7, bit 0 indicates for write or read.
//
// eg: `var a I2CAddress7Bit = 0x35`
// - 0110 101 0 = 0x6A (for write)
// - 0110 101 1 = 0x6B (fore read)
// - 7654 321 0 bit position
type I2CAddress8Bit uint8
// To8BitForWrite convert 7-bit I2C address to 8-bit I2C address, bit 1 to bit 7 for I2C address, bit 0 set to 0
func (a I2CAddress7Bit) To8BitForWrite() I2CAddress8Bit {
return I2CAddress8Bit(a << 1)
}
// To8BitForRead convert 7-bit I2C address to 8-bit I2C address, bit 1 to bit 7 for I2C address, bit 0 set to 1
func (a I2CAddress7Bit) To8BitForRead() I2CAddress8Bit {
return I2CAddress8Bit(a<<1 | 0x01)
}
func (a I2CAddress8Bit) To7Bit() I2CAddress7Bit {
return I2CAddress7Bit(a >> 1)
}
golang-github-bougou-go-ipmi-0.7.2/types_ipmi.go 0000664 0000000 0000000 00000014516 14741105271 0021626 0 ustar 00root root 0000000 0000000 package ipmi
import "context"
const (
IPMIRequesterSequenceMax uint8 = 0x3f // RequesterSequence only occupy 6 bits
)
// 13.8 IPMI LAN Message Format
type IPMIRequest struct {
// SlaveAddress or SoftwareID
// Responder's Slave Address. 1 byte. LS bit is 0 for Slave Addresses and 1 for Software IDs. Upper 7-bits hold Slave Address or Software ID, respectively. This byte is always 20h when the BMC is the responder.
ResponderAddr uint8 // SlaveAddress or SoftwareID
// The lower 2-bits of the netFn byte identify the logical unit number, which provides further sub-addressing within the target node.
NetFn NetFn // (even) / rsLUN
ResponderLUN uint8 // lower 2 bits
// Checksum1 is filled by calling ComputeChecksum method
Checksum1 uint8
// SlaveAddress or SoftwareID
// Requester's Address. 1 byte. LS bit is 0 for Slave Addresses and 1 for Software IDs. Upper 7-bits hold Slave Address or Software ID, respectively. This byte is always 20h when the BMC is the requester.
RequesterAddr uint8 // rqSA
RequesterSequence uint8 // rqSeq, occupies the highest 6 bits, (so should left shit 2 bits)
RequesterLUN uint8 // rqLUN, occupies the lowest 2 bits
Command uint8 // Command ID
// Command Request Body Data defined by each command.
CommandData []byte // optional, 0 or more
// Checksum2 is filled by calling ComputeChecksum method
Checksum2 uint8
}
// IPMIResponse represent IPMI PayloadType msg response
type IPMIResponse struct {
// Requester's Address. 1 byte. LS bit is 0 for Slave Addresses and 1 for Software IDs. Upper 7-bits hold Slave Address or Software ID, respectively. This byte is always 20h when the BMC is the requester.
RequesterAddr uint8 // SlaveAddress or SoftwareID
// Network Function code
// The lower 2-bits of the netFn byte identify the logical unit number, which provides further sub-addressing within the target node.
NetFn NetFn // (odd) higher 6 bits
// Requester's LUN
RequestLUN uint8 // lower 2 bits
// 8-bit checksum algorithm: Initialize checksum to 0. For each byte, checksum = (checksum + byte) modulo 256. Then checksum = - checksum. When the checksum and the bytes are added together, modulo 256, the result should be 0.
Checksum1 uint8
// Responder's Slave Address. 1 byte. LS bit is 0 for Slave Addresses and 1 for Software IDs. Upper 7-bits hold Slave Address or Software ID, respectively. This byte is always 20h when the BMC is the responder.
ResponderAddr uint8 // // SlaveAddress or SoftwareID
// Sequence number. This field is used to verify that a response is for a particular instance of a request. Refer to [IPMB] for additional information on use and operation of the Seq field.
RequesterSequence uint8 // higher 6 bits
ResponderLUN uint8 // lower 2 bits
Command uint8
// Completion code returned in the response to indicated success/failure status of the request.
CompletionCode uint8
// Response Data
Data []byte // optional
Checksum2 uint8
}
func (req *IPMIRequest) Pack() []byte {
msgLen := 6 + len(req.CommandData) + 1
msg := make([]byte, msgLen)
packUint8(req.ResponderAddr, msg, 0)
netFn := uint8(req.NetFn) << 2
resLun := req.ResponderLUN & 0x03
packUint8(netFn|resLun, msg, 1)
packUint8(req.Checksum1, msg, 2)
packUint8(req.RequesterAddr, msg, 3)
var seq uint8 = req.RequesterSequence << 2
reqLun := req.RequesterLUN & 0x03
packUint8(seq|reqLun, msg, 4)
packUint8(uint8(req.Command), msg, 5)
if req.CommandData != nil {
packBytes(req.CommandData, msg, 6)
}
packUint8(req.Checksum2, msg, msgLen-1)
return msg
}
func (req *IPMIRequest) ComputeChecksum() {
// 8-bit checksum algorithm: Initialize checksum to 0. For each byte, checksum = (checksum + byte) modulo 256. Then checksum = - checksum. When the checksum and the bytes are added together, modulo 256, the result should be 0.
//
// the position end is not included
var checksumFn = func(msg []byte, start int, end int) uint8 {
c := 0
for i := start; i < end; i++ {
c = (c + int(msg[i])) % 256
}
return -uint8(c)
}
tempData := req.Pack()
cs1Start, cs1End := 0, 2
req.Checksum1 = checksumFn(tempData, cs1Start, cs1End)
cs2Start, cs2End := 3, len(tempData)-1
req.Checksum2 = checksumFn(tempData, cs2Start, cs2End)
}
func (res *IPMIResponse) Unpack(msg []byte) error {
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
res.RequesterAddr, _, _ = unpackUint8(msg, 0)
b, _, _ := unpackUint8(msg, 1)
res.NetFn = NetFn(b >> 2) // the most 6 bit
res.RequestLUN = b & 0x03 // the least 2 bit
res.Checksum1, _, _ = unpackUint8(msg, 2)
res.ResponderAddr, _, _ = unpackUint8(msg, 3)
b4, _, _ := unpackUint8(msg, 4)
res.RequesterSequence = b4 >> 2
res.ResponderLUN = b4 & 0x03
res.Command, _, _ = unpackUint8(msg, 5)
res.CompletionCode, _, _ = unpackUint8(msg, 6)
dataLen := len(msg) - 7 - 1
res.Data, _, _ = unpackBytes(msg, 7, dataLen)
res.Checksum2, _, _ = unpackUint8(msg, len(msg)-1)
return nil
}
// BuildIPMIRequest creates IPMIRequest for a Command Request.
// It also fills the Checksum1 and Checksum2 fields of IPMIRequest.
func (c *Client) BuildIPMIRequest(ctx context.Context, reqCmd Request) (*IPMIRequest, error) {
c.lock()
defer c.unlock()
ipmiReq := &IPMIRequest{
ResponderAddr: c.responderAddr,
NetFn: reqCmd.Command().NetFn,
ResponderLUN: c.responderLUN,
RequesterAddr: c.requesterAddr,
RequesterSequence: c.session.ipmiSeq,
RequesterLUN: c.requesterLUN,
Command: reqCmd.Command().ID,
CommandData: reqCmd.Pack(),
}
c.session.ipmiSeq += 1
if c.session.ipmiSeq > IPMIRequesterSequenceMax {
c.session.ipmiSeq = 1
}
ipmiReq.ComputeChecksum()
return ipmiReq, nil
}
// AllCC returns all possible completion codes for the specified response.
// i.e.:
//
// the generic completion codes for all ipmi cmd response
// +
// the specific completion codes for specified cmd response.
func AllCC(response Response) map[uint8]string {
out := map[uint8]string{}
for k, v := range CC {
out[k] = v
}
for k, v := range response.CompletionCodes() {
out[k] = v
}
return out
}
// StrCC return the description of ccode for the specified response.
// The available completion codes set consists of general completion codes (CC) for all
// commands response and specific completion codes for this response.
func StrCC(response Response, ccode uint8) string {
s, ok := AllCC(response)[ccode]
if ok {
return s
}
return "unknown completion code"
}
golang-github-bougou-go-ipmi-0.7.2/types_lan_config.go 0000664 0000000 0000000 00000057707 14741105271 0023000 0 ustar 00root root 0000000 0000000 package ipmi
import (
"fmt"
"net"
)
type SetInProgressState uint8
const (
SetInProgress_SetComplete SetInProgressState = 0x00
SetInProgress_SetInProgress SetInProgressState = 0x01
SetInProgress_CommitWrite SetInProgressState = 0x02
SetInProgress_Reserved SetInProgressState = 0x03
)
func (p SetInProgressState) String() string {
m := map[SetInProgressState]string{
0x00: "set complete",
0x01: "set in progress",
0x02: "commit write",
0x03: "reserved",
}
s, ok := m[p]
if ok {
return s
}
return ""
}
type CommunityString [18]byte
func (c CommunityString) String() string {
s := []byte{}
for _, v := range c {
if v == 0x00 { // null
break
}
s = append(s, v)
}
return string(s)
}
func NewCommunityString(s string) CommunityString {
o := [18]byte{}
b := []byte(s)
for i := 0; i < 18; i++ {
if i < len(b) {
o[i] = b[i]
}
o[i] = 0x00
}
return CommunityString(o)
}
type AuthTypesEnabled struct {
OEM bool
Password bool
MD5 bool
MD2 bool
None bool
}
func (authTypeEnabled AuthTypesEnabled) String() string {
if authTypeEnabled.OEM {
return "OEM"
}
if authTypeEnabled.Password {
return "Password"
}
if authTypeEnabled.MD5 {
return "MD5"
}
if authTypeEnabled.MD2 {
return "MD2"
}
if authTypeEnabled.None {
return "None"
}
return "Unknown"
}
func packAuthTypesEnabled(a *AuthTypesEnabled) byte {
b := uint8(0)
b = setOrClearBit5(b, a.OEM)
b = setOrClearBit4(b, a.Password)
b = setOrClearBit2(b, a.MD5)
b = setOrClearBit1(b, a.MD2)
b = setOrClearBit0(b, a.None)
return b
}
func unpackAuthTypesEnabled(b byte) *AuthTypesEnabled {
return &AuthTypesEnabled{
OEM: isBit5Set(b),
Password: isBit4Set(b),
MD5: isBit2Set(b),
MD2: isBit1Set(b),
None: isBit0Set(b),
}
}
// see: LanConfigParameter_IPAddressSource (#4)
type LanIPAddressSource uint8
const (
IPAddressSourceUnspecified LanIPAddressSource = 0x00
IPAddressSourceStatic LanIPAddressSource = 0x01
IPAddressSourceDHCP LanIPAddressSource = 0x02
IPAddressSourceBIOS LanIPAddressSource = 0x03
IPAddressSourceOther LanIPAddressSource = 0x04
)
func (i LanIPAddressSource) String() string {
m := map[LanIPAddressSource]string{
0x00: "unspecified",
0x01: "static",
0x02: "dhcp",
0x03: "bios",
0x04: "other",
}
s, ok := m[i]
if ok {
return s
}
return ""
}
type LanIPv6EnableMode uint8
const (
// 00h = IPv6 addressing disabled.
LanIPv6EnableMode_IPv6Disabled LanIPv6EnableMode = 0
// 01h = Enable IPv6 addressing only. IPv4 addressing is disabled.
LanIPv6EnableMode_IPv6Only LanIPv6EnableMode = 1
// 02h = Enable IPv6 and IPv4 addressing simultaneously.
LanIPv6EnableMode_IPv4AndIPv6 LanIPv6EnableMode = 2
)
// Address Status (Read-only parameter)
// - 00h = Active (in-use)
// - 01h = Disabled
// - 02h = Pending (currently undergoing DAD [duplicate address detection], optional)
// - 03h = Failed (duplicate address found, optional)
// - 04h = Deprecated (preferred timer has expired, optional)
// - 05h = Invalid (validity timer has expired, optional)
// - All other = reserved
type LanIPv6AddressStatus uint8
const (
LanIPv6AddressStatus_Active LanIPv6AddressStatus = 0
LanIPv6AddressStatus_Disabled LanIPv6AddressStatus = 1
LanIPv6AddressStatus_Pending LanIPv6AddressStatus = 2
LanIPv6AddressStatus_Failed LanIPv6AddressStatus = 3
LanIPv6AddressStatus_Deprecated LanIPv6AddressStatus = 4
LanIPv6AddressStatus_Invalid LanIPv6AddressStatus = 5
)
func (addressStatus LanIPv6AddressStatus) String() string {
m := map[LanIPv6AddressStatus]string{
0x00: "active",
0x01: "disabled",
0x02: "pending",
0x03: "failed",
0x04: "deprecated",
0x05: "invalid",
}
s, ok := m[addressStatus]
if ok {
return s
}
return "reserved"
}
// IPv6 Static Address Source
// - 0h = Static
// - All other = reserved
type LanIPv6StaticAddressSource uint8
const (
LanIPv6StaticAddressSource_Static LanIPv6StaticAddressSource = 0
)
func (addressSource LanIPv6StaticAddressSource) String() string {
m := map[LanIPv6StaticAddressSource]string{
0: "static",
}
s, ok := m[addressSource]
if ok {
return s
}
return "reserved"
}
// Address source/type
// - 0 - Reserved
// - 1 - SLAAC (StateLess Address Auto Configuration)
// - 2 - DHCPv6 (optional)
// - Other - reserved
type LanIPv6DynamicAddressSource uint8
const (
LanIPv6AddressSource_SLAAC LanIPv6DynamicAddressSource = 1
LanIPv6AddressSource_DHCPv6 LanIPv6DynamicAddressSource = 2
)
func (addressSource LanIPv6DynamicAddressSource) String() string {
m := map[LanIPv6DynamicAddressSource]string{
1: "SLAAC",
2: "DHCPv6",
}
s, ok := m[addressSource]
if ok {
return s
}
return "reserved"
}
// DHCPv6 Timing Configuration Mode
// - 00b = `Not Supported`
// DHCPv6 timing configuration per IPMI is not supported.
// - 01b = `Global`
// Timing configuration applies across all interfaces (IAs) that use
// dynamic addressing and have DHCPv6 is enabled.
// - 10b = `Per Interface`
// Timing is configurable for each interface and used when DHCPv6 is enabled for the given interface (IA).
// - 11b = reserved
type LanIPv6DHCPv6TimingConfigMode uint8
const (
LanIPv6DHCPv6TimingConfigMode_NotSupported LanIPv6DHCPv6TimingConfigMode = 0
LanIPv6DHCPv6TimingConfigMode_Global LanIPv6DHCPv6TimingConfigMode = 1
LanIPv6DHCPv6TimingConfigMode_PerInterface LanIPv6DHCPv6TimingConfigMode = 2
)
func (mode LanIPv6DHCPv6TimingConfigMode) String() string {
m := map[LanIPv6DHCPv6TimingConfigMode]string{
0: "not supported",
1: "global",
2: "per interface",
}
s, ok := m[mode]
if ok {
return s
}
return "reserved"
}
type LanIPv6NDSLAACTimingConfigMode uint8
const (
LanIPv6NDSLAACTimingConfigMode_NotSupported LanIPv6DHCPv6TimingConfigMode = 0
LanIPv6NDSLAACTimingConfigMode_Global LanIPv6NDSLAACTimingConfigMode = 1
LanIPv6NDSLAACTimingConfigMode_PerInterface LanIPv6NDSLAACTimingConfigMode = 2
)
func (mode LanIPv6NDSLAACTimingConfigMode) String() string {
m := map[LanIPv6NDSLAACTimingConfigMode]string{
0: "not supported",
1: "global",
2: "per interface",
}
s, ok := m[mode]
if ok {
return s
}
return "reserved"
}
type LanConfigParams struct {
SetInProgress *LanConfigParam_SetInProgress // #0, Read Only
AuthTypeSupport *LanConfigParam_AuthTypeSupport // #1
AuthTypeEnables *LanConfigParam_AuthTypeEnables // #2
IP *LanConfigParam_IP // #3
IPSource *LanConfigParam_IPSource // #4
MAC *LanConfigParam_MAC // #5, can be Read Only. An implementation can either allow this parameter to be settable, or it can be implemented as Read Only.
SubnetMask *LanConfigParam_SubnetMask // #6
IPv4HeaderParams *LanConfigParam_IPv4HeaderParams // #7
PrimaryRMCPPort *LanConfigParam_PrimaryRMCPPort // #8
SecondaryRMCPPort *LanConfigParam_SecondaryRMCPPort // #9
ARPControl *LanConfigParam_ARPControl // #10
GratuitousARPInterval *LanConfigParam_GratuitousARPInterval // #11
DefaultGatewayIP *LanConfigParam_DefaultGatewayIP // #12
DefaultGatewayMAC *LanConfigParam_DefaultGatewayMAC // #13
BackupGatewayIP *LanConfigParam_BackupGatewayIP // #14
BackupGatewayMAC *LanConfigParam_BackupGatewayMAC // #15
CommunityString *LanConfigParam_CommunityString // #16
AlertDestinationsCount *LanConfigParam_AlertDestinationsCount // #17, Read Only
AlertDestinationTypes []*LanConfigParam_AlertDestinationType // #18
AlertDestinationAddresses []*LanConfigParam_AlertDestinationAddress // #19
VLANID *LanConfigParam_VLANID // #20
VLANPriority *LanConfigParam_VLANPriority // #21
CipherSuitesSupport *LanConfigParam_CipherSuitesSupport // #22, Read Only
CipherSuitesID *LanConfigParam_CipherSuitesID // #23, Read Only
CipherSuitesPrivLevel *LanConfigParam_CipherSuitesPrivLevel // #24
AlertDestinationVLANs []*LanConfigParam_AlertDestinationVLAN // #25, can be READ ONLY
BadPasswordThreshold *LanConfigParam_BadPasswordThreshold // #26
IPv6Support *LanConfigParam_IPv6Support // #50, Read Only
IPv6Enables *LanConfigParam_IPv6Enables // #51
IPv6StaticTrafficClass *LanConfigParam_IPv6StaticTrafficClass // #52
IPv6StaticHopLimit *LanConfigParam_IPv6StaticHopLimit // #53
IPv6FlowLabel *LanConfigParam_IPv6FlowLabel // #54
IPv6Status *LanConfigParam_IPv6Status // #55, Read Only
IPv6StaticAddresses []*LanConfigParam_IPv6StaticAddress // #56
IPv6DHCPv6StaticDUIDCount *LanConfigParam_IPv6DHCPv6StaticDUIDCount // #57, Read Only
IPv6DHCPv6StaticDUIDs []*LanConfigParam_IPv6DHCPv6StaticDUID // #58
IPv6DynamicAddresses []*LanConfigParam_IPv6DynamicAddress // #59, Read Only
IPv6DHCPv6DynamicDUIDCount *LanConfigParam_IPv6DHCPv6DynamicDUIDCount // #60, Read Only
IPv6DHCPv6DynamicDUIDs []*LanConfigParam_IPv6DHCPv6DynamicDUID // #61
IPv6DHCPv6TimingConfigSupport *LanConfigParam_IPv6DHCPv6TimingConfigSupport // #62, Read Only
IPv6DHCPv6TimingConfig []*LanConfigParam_IPv6DHCPv6TimingConfig // #63
IPv6RouterAddressConfigControl *LanConfigParam_IPv6RouterAddressConfigControl // #64
IPv6StaticRouter1IP *LanConfigParam_IPv6StaticRouter1IP // #65
IPv6StaticRouter1MAC *LanConfigParam_IPv6StaticRouter1MAC // #66
IPv6StaticRouter1PrefixLength *LanConfigParam_IPv6StaticRouter1PrefixLength // #67
IPv6StaticRouter1PrefixValue *LanConfigParam_IPv6StaticRouter1PrefixValue // #68
IPv6StaticRouter2IP *LanConfigParam_IPv6StaticRouter2IP // #69
IPv6StaticRouter2MAC *LanConfigParam_IPv6StaticRouter2MAC // #70
IPv6StaticRouter2PrefixLength *LanConfigParam_IPv6StaticRouter2PrefixLength // #71
IPv6StaticRouter2PrefixValue *LanConfigParam_IPv6StaticRouter2PrefixValue // #72
IPv6DynamicRouterInfoSets *LanConfigParam_IPv6DynamicRouterInfoSets // #73, Read Only
IPv6DynamicRouterInfoIP []*LanConfigParam_IPv6DynamicRouterInfoIP // #74
IPv6DynamicRouterInfoMAC []*LanConfigParam_IPv6DynamicRouterInfoMAC // #75
IPv6DynamicRouterInfoPrefixLength []*LanConfigParam_IPv6DynamicRouterInfoPrefixLength // #76
IPv6DynamicRouterInfoPrefixValue []*LanConfigParam_IPv6DynamicRouterInfoPrefixValue // #77
IPv6DynamicRouterReceivedHopLimit *LanConfigParam_IPv6DynamicRouterReceivedHopLimit // #78
IPv6NDSLAACTimingConfigSupport *LanConfigParam_IPv6NDSLAACTimingConfigSupport // #79, Read Only
IPv6NDSLAACTimingConfig []*LanConfigParam_IPv6NDSLAACTimingConfig // #80
}
type LanConfig struct {
SetInProgress SetInProgressState // #0, Read Only
AuthTypeSupport LanConfigParam_AuthTypeSupport // #1
AuthTypeEnables LanConfigParam_AuthTypeEnables // #2
IP net.IP // #3
IPSource LanIPAddressSource // #4
MAC net.HardwareAddr // #5, can be Read Only.
SubnetMask net.IP // #6
IPv4HeaderParams LanConfigParam_IPv4HeaderParams // #7
PrimaryRMCPPort uint16 // #8
SecondaryRMCPPort uint16 // #9
ARPControl LanConfigParam_ARPControl // #10
GratuitousARPIntervalMilliSec uint32 // #11
DefaultGatewayIP net.IP // #12
DefaultGatewayMAC net.HardwareAddr // #13
BackupGatewayIP net.IP // #14
BackupGatewayMAC net.HardwareAddr // #15
CommunityString CommunityString // #16
AlertDestinationsCount uint8 // #17, Read Only
VLANEnabled bool // #20
VLANID uint16 // #20
VLANPriority uint8 // #21
CipherSuitesSupport uint8 // #22, Read Only
CipherSuitesID LanConfigParam_CipherSuitesID // #23, Read Only
CipherSuitesPrivLevel LanConfigParam_CipherSuitesPrivLevel // #24
BadPasswordThreshold LanConfigParam_BadPasswordThreshold // #26
}
func (lanConfigParams *LanConfigParams) ToLanConfig() *LanConfig {
lanConfig := &LanConfig{}
if lanConfigParams.SetInProgress != nil {
lanConfig.SetInProgress = lanConfigParams.SetInProgress.Value
}
if lanConfigParams.AuthTypeSupport != nil {
lanConfig.AuthTypeSupport = *lanConfigParams.AuthTypeSupport
}
if lanConfigParams.AuthTypeEnables != nil {
lanConfig.AuthTypeEnables = *lanConfigParams.AuthTypeEnables
}
if lanConfigParams.IP != nil {
lanConfig.IP = lanConfigParams.IP.IP
}
if lanConfigParams.IPSource != nil {
lanConfig.IPSource = lanConfigParams.IPSource.Source
}
if lanConfigParams.MAC != nil {
lanConfig.MAC = lanConfigParams.MAC.MAC
}
if lanConfigParams.SubnetMask != nil {
lanConfig.SubnetMask = lanConfigParams.SubnetMask.SubnetMask
}
if lanConfigParams.IPv4HeaderParams != nil {
lanConfig.IPv4HeaderParams = *lanConfigParams.IPv4HeaderParams
}
if lanConfigParams.PrimaryRMCPPort != nil {
lanConfig.PrimaryRMCPPort = lanConfigParams.PrimaryRMCPPort.Port
}
if lanConfigParams.SecondaryRMCPPort != nil {
lanConfig.SecondaryRMCPPort = lanConfigParams.SecondaryRMCPPort.Port
}
if lanConfigParams.ARPControl != nil {
lanConfig.ARPControl = *lanConfigParams.ARPControl
}
if lanConfigParams.GratuitousARPInterval != nil {
lanConfig.GratuitousARPIntervalMilliSec = lanConfigParams.GratuitousARPInterval.MilliSec
}
if lanConfigParams.DefaultGatewayIP != nil {
lanConfig.DefaultGatewayIP = lanConfigParams.DefaultGatewayIP.IP
}
if lanConfigParams.DefaultGatewayMAC != nil {
lanConfig.DefaultGatewayMAC = lanConfigParams.DefaultGatewayMAC.MAC
}
if lanConfigParams.BackupGatewayIP != nil {
lanConfig.BackupGatewayIP = lanConfigParams.BackupGatewayIP.IP
}
if lanConfigParams.BackupGatewayMAC != nil {
lanConfig.BackupGatewayMAC = lanConfigParams.BackupGatewayMAC.MAC
}
if lanConfigParams.CommunityString != nil {
lanConfig.CommunityString = lanConfigParams.CommunityString.CommunityString
}
if lanConfigParams.AlertDestinationsCount != nil {
lanConfig.AlertDestinationsCount = lanConfigParams.AlertDestinationsCount.Count
}
if lanConfigParams.VLANID != nil {
lanConfig.VLANEnabled = lanConfigParams.VLANID.Enabled
lanConfig.VLANID = lanConfigParams.VLANID.ID
}
if lanConfigParams.VLANPriority != nil {
lanConfig.VLANPriority = lanConfigParams.VLANPriority.Priority
}
if lanConfigParams.CipherSuitesSupport != nil {
lanConfig.CipherSuitesSupport = lanConfigParams.CipherSuitesSupport.Count
}
if lanConfigParams.CipherSuitesID != nil {
lanConfig.CipherSuitesID = *lanConfigParams.CipherSuitesID
}
if lanConfigParams.CipherSuitesPrivLevel != nil {
lanConfig.CipherSuitesPrivLevel = *lanConfigParams.CipherSuitesPrivLevel
}
if lanConfigParams.BadPasswordThreshold != nil {
lanConfig.BadPasswordThreshold = *lanConfigParams.BadPasswordThreshold
}
return lanConfig
}
func (lanConfigParams *LanConfigParams) Format() string {
format := func(param LanConfigParameter) string {
if isNilLanConfigParameter(param) {
return ""
}
paramSelector, _, _ := param.LanConfigParameter()
content := param.Format()
if content[len(content)-1] != '\n' {
content += "\n"
}
return fmt.Sprintf("[%2d] %-40s: %s", paramSelector, paramSelector.String(), content)
}
out := ""
out += format(lanConfigParams.SetInProgress)
out += format(lanConfigParams.AuthTypeSupport)
out += format(lanConfigParams.AuthTypeEnables)
out += format(lanConfigParams.IP)
out += format(lanConfigParams.IPSource)
out += format(lanConfigParams.MAC)
out += format(lanConfigParams.SubnetMask)
out += format(lanConfigParams.IPv4HeaderParams)
out += format(lanConfigParams.PrimaryRMCPPort)
out += format(lanConfigParams.SecondaryRMCPPort)
out += format(lanConfigParams.ARPControl)
out += format(lanConfigParams.GratuitousARPInterval)
out += format(lanConfigParams.DefaultGatewayIP)
out += format(lanConfigParams.DefaultGatewayMAC)
out += format(lanConfigParams.BackupGatewayIP)
out += format(lanConfigParams.BackupGatewayMAC)
out += format(lanConfigParams.CommunityString)
out += format(lanConfigParams.AlertDestinationsCount)
for _, alertDestinationType := range lanConfigParams.AlertDestinationTypes {
out += format(alertDestinationType)
}
if lanConfigParams.AlertDestinationAddresses != nil {
for _, alertDestinationAddress := range lanConfigParams.AlertDestinationAddresses {
out += format(alertDestinationAddress)
}
}
out += format(lanConfigParams.VLANID)
out += format(lanConfigParams.VLANPriority)
out += format(lanConfigParams.CipherSuitesSupport)
out += format(lanConfigParams.CipherSuitesID)
out += format(lanConfigParams.CipherSuitesPrivLevel)
if lanConfigParams.AlertDestinationVLANs != nil {
for _, alertDestinationVLAN := range lanConfigParams.AlertDestinationVLANs {
out += format(alertDestinationVLAN)
}
}
out += format(lanConfigParams.BadPasswordThreshold)
out += format(lanConfigParams.IPv6Support)
out += format(lanConfigParams.IPv6Enables)
out += format(lanConfigParams.IPv6StaticTrafficClass)
out += format(lanConfigParams.IPv6StaticHopLimit)
out += format(lanConfigParams.IPv6FlowLabel)
out += format(lanConfigParams.IPv6Status)
if lanConfigParams.IPv6StaticAddresses != nil {
for _, ipv6StaticAddress := range lanConfigParams.IPv6StaticAddresses {
out += format(ipv6StaticAddress)
}
}
out += format(lanConfigParams.IPv6DHCPv6StaticDUIDCount)
if lanConfigParams.IPv6DHCPv6StaticDUIDs != nil {
for _, ipv6DHCPv6StaticDUID := range lanConfigParams.IPv6DHCPv6StaticDUIDs {
out += format(ipv6DHCPv6StaticDUID)
}
}
if lanConfigParams.IPv6DynamicAddresses != nil {
for _, ipv6DynamicAddress := range lanConfigParams.IPv6DynamicAddresses {
out += format(ipv6DynamicAddress)
}
}
out += format(lanConfigParams.IPv6DHCPv6DynamicDUIDCount)
if lanConfigParams.IPv6DHCPv6DynamicDUIDs != nil {
for _, ipv6DHCPv6DynamicDUID := range lanConfigParams.IPv6DHCPv6DynamicDUIDs {
out += format(ipv6DHCPv6DynamicDUID)
}
}
out += format(lanConfigParams.IPv6DHCPv6TimingConfigSupport)
if lanConfigParams.IPv6DHCPv6TimingConfig != nil {
for _, ipv6DHCPv6TimingConfig := range lanConfigParams.IPv6DHCPv6TimingConfig {
out += format(ipv6DHCPv6TimingConfig)
}
}
out += format(lanConfigParams.IPv6RouterAddressConfigControl)
out += format(lanConfigParams.IPv6StaticRouter1IP)
out += format(lanConfigParams.IPv6StaticRouter1MAC)
out += format(lanConfigParams.IPv6StaticRouter1PrefixLength)
out += format(lanConfigParams.IPv6StaticRouter1PrefixValue)
out += format(lanConfigParams.IPv6StaticRouter2IP)
out += format(lanConfigParams.IPv6StaticRouter2MAC)
out += format(lanConfigParams.IPv6StaticRouter2PrefixLength)
out += format(lanConfigParams.IPv6StaticRouter2PrefixValue)
out += format(lanConfigParams.IPv6DynamicRouterInfoSets)
if lanConfigParams.IPv6DynamicRouterInfoIP != nil {
for _, ipv6DynamicRouterInfoIP := range lanConfigParams.IPv6DynamicRouterInfoIP {
out += format(ipv6DynamicRouterInfoIP)
}
}
if lanConfigParams.IPv6DynamicRouterInfoMAC != nil {
for _, ipv6DynamicRouterInfoMAC := range lanConfigParams.IPv6DynamicRouterInfoMAC {
out += format(ipv6DynamicRouterInfoMAC)
}
}
if lanConfigParams.IPv6DynamicRouterInfoPrefixLength != nil {
for _, ipv6DynamicRouterInfoPrefixLength := range lanConfigParams.IPv6DynamicRouterInfoPrefixLength {
out += format(ipv6DynamicRouterInfoPrefixLength)
}
}
if lanConfigParams.IPv6DynamicRouterInfoPrefixValue != nil {
for _, ipv6DynamicRouterInfoPrefixValue := range lanConfigParams.IPv6DynamicRouterInfoPrefixValue {
out += format(ipv6DynamicRouterInfoPrefixValue)
}
}
out += format(lanConfigParams.IPv6DynamicRouterReceivedHopLimit)
out += format(lanConfigParams.IPv6NDSLAACTimingConfigSupport)
if lanConfigParams.IPv6NDSLAACTimingConfig != nil {
for _, ipv6NDSLAACTimingConfig := range lanConfigParams.IPv6NDSLAACTimingConfig {
out += format(ipv6NDSLAACTimingConfig)
}
}
return out
}
func (lanConfig *LanConfig) Format() string {
out := ""
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_SetInProgress, lanConfig.SetInProgress)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_AuthTypeSupport, lanConfig.AuthTypeSupport.Format())
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_AuthTypeEnables, lanConfig.AuthTypeEnables.Format())
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_IP, lanConfig.IP)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_IPSource, lanConfig.IPSource)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_MAC, lanConfig.MAC)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_SubnetMask, lanConfig.SubnetMask)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_IPv4HeaderParams, lanConfig.IPv4HeaderParams.Format())
out += fmt.Sprintf("%-40s : %d\n", LanConfigParamSelector_PrimaryRMCPPort, lanConfig.PrimaryRMCPPort)
out += fmt.Sprintf("%-40s : %d\n", LanConfigParamSelector_SecondaryRMCPPort, lanConfig.SecondaryRMCPPort)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_ARPControl, lanConfig.ARPControl.Format())
out += fmt.Sprintf("%-40s : %d\n", LanConfigParamSelector_GratuitousARPInterval, lanConfig.GratuitousARPIntervalMilliSec)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_DefaultGatewayIP, lanConfig.DefaultGatewayIP)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_DefaultGatewayMAC, lanConfig.DefaultGatewayMAC)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_BackupGatewayIP, lanConfig.BackupGatewayIP)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_BackupGatewayMAC, lanConfig.BackupGatewayMAC)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_CommunityString, lanConfig.CommunityString)
out += fmt.Sprintf("%-40s : %d\n", LanConfigParamSelector_AlertDestinationsCount, lanConfig.AlertDestinationsCount)
out += fmt.Sprintf("%-40s : %d\n", LanConfigParamSelector_VLANID, lanConfig.VLANID)
out += fmt.Sprintf("%-40s : %d\n", LanConfigParamSelector_VLANPriority, lanConfig.VLANPriority)
out += fmt.Sprintf("%-40s : %d\n", LanConfigParamSelector_CipherSuitesSupport, lanConfig.CipherSuitesSupport)
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_CipherSuitesID, lanConfig.CipherSuitesID.Format())
out += fmt.Sprintf("%-40s : %s\n", LanConfigParamSelector_CipherSuitesPrivLevel, lanConfig.CipherSuitesPrivLevel.Format())
out += fmt.Sprintf("%-40s : %d\n", LanConfigParamSelector_BadPasswordThreshold, lanConfig.BadPasswordThreshold.Threshold)
return out
}
golang-github-bougou-go-ipmi-0.7.2/types_lan_config_params.go 0000664 0000000 0000000 00000226665 14741105271 0024344 0 ustar 00root root 0000000 0000000 package ipmi
import (
"fmt"
"net"
"strconv"
"strings"
)
type LanConfigParameter interface {
LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8)
Parameter
}
// Table 23-4, LAN Configuration Parameters
// Parameter selector
type LanConfigParamSelector uint8
const (
LanConfigParamSelector_SetInProgress LanConfigParamSelector = 0
LanConfigParamSelector_AuthTypeSupport LanConfigParamSelector = 1 // read only
LanConfigParamSelector_AuthTypeEnables LanConfigParamSelector = 2
LanConfigParamSelector_IP LanConfigParamSelector = 3
LanConfigParamSelector_IPSource LanConfigParamSelector = 4
LanConfigParamSelector_MAC LanConfigParamSelector = 5 // can be read only
LanConfigParamSelector_SubnetMask LanConfigParamSelector = 6
LanConfigParamSelector_IPv4HeaderParams LanConfigParamSelector = 7
LanConfigParamSelector_PrimaryRMCPPort LanConfigParamSelector = 8
LanConfigParamSelector_SecondaryRMCPPort LanConfigParamSelector = 9
LanConfigParamSelector_ARPControl LanConfigParamSelector = 10
LanConfigParamSelector_GratuitousARPInterval LanConfigParamSelector = 11
LanConfigParamSelector_DefaultGatewayIP LanConfigParamSelector = 12
LanConfigParamSelector_DefaultGatewayMAC LanConfigParamSelector = 13
LanConfigParamSelector_BackupGatewayIP LanConfigParamSelector = 14
LanConfigParamSelector_BackupGatewayMAC LanConfigParamSelector = 15
LanConfigParamSelector_CommunityString LanConfigParamSelector = 16
LanConfigParamSelector_AlertDestinationsCount LanConfigParamSelector = 17 // read only
LanConfigParamSelector_AlertDestinationType LanConfigParamSelector = 18
LanConfigParamSelector_AlertDestinationAddress LanConfigParamSelector = 19
LanConfigParamSelector_VLANID LanConfigParamSelector = 20
LanConfigParamSelector_VLANPriority LanConfigParamSelector = 21
LanConfigParamSelector_CipherSuitesSupport LanConfigParamSelector = 22 // read only
LanConfigParamSelector_CipherSuitesID LanConfigParamSelector = 23 // read only
LanConfigParamSelector_CipherSuitesPrivLevel LanConfigParamSelector = 24
LanConfigParamSelector_AlertDestinationVLAN LanConfigParamSelector = 25 // can be read only
LanConfigParamSelector_BadPasswordThreshold LanConfigParamSelector = 26
LanConfigParamSelector_IPv6Support LanConfigParamSelector = 50 // read only
LanConfigParamSelector_IPv6Enables LanConfigParamSelector = 51
LanConfigParamSelector_IPv6StaticTrafficClass LanConfigParamSelector = 52
LanConfigParamSelector_IPv6StaticHopLimit LanConfigParamSelector = 53
LanConfigParamSelector_IPv6FlowLabel LanConfigParamSelector = 54
LanConfigParamSelector_IPv6Status LanConfigParamSelector = 55 // read only
LanConfigParamSelector_IPv6StaticAddress LanConfigParamSelector = 56
LanConfigParamSelector_IPv6DHCPv6StaticDUIDCount LanConfigParamSelector = 57 // read only
LanConfigParamSelector_IPv6DHCPv6StaticDUID LanConfigParamSelector = 58
LanConfigParamSelector_IPv6DynamicAddress LanConfigParamSelector = 59 // read only
LanConfigParamSelector_IPv6DHCPv6DynamicDUIDCount LanConfigParamSelector = 60 // read only
LanConfigParamSelector_IPv6DHCPv6DynamicDUID LanConfigParamSelector = 61
LanConfigParamSelector_IPv6DHCPv6TimingConfigSupport LanConfigParamSelector = 62 // read only
LanConfigParamSelector_IPv6DHCPv6TimingConfig LanConfigParamSelector = 63
LanConfigParamSelector_IPv6RouterAddressConfigControl LanConfigParamSelector = 64
LanConfigParamSelector_IPv6StaticRouter1IP LanConfigParamSelector = 65
LanConfigParamSelector_IPv6StaticRouter1MAC LanConfigParamSelector = 66
LanConfigParamSelector_IPv6StaticRouter1PrefixLength LanConfigParamSelector = 67
LanConfigParamSelector_IPv6StaticRouter1PrefixValue LanConfigParamSelector = 68
LanConfigParamSelector_IPv6StaticRouter2IP LanConfigParamSelector = 69
LanConfigParamSelector_IPv6StaticRouter2MAC LanConfigParamSelector = 70
LanConfigParamSelector_IPv6StaticRouter2PrefixLength LanConfigParamSelector = 71
LanConfigParamSelector_IPv6StaticRouter2PrefixValue LanConfigParamSelector = 72
LanConfigParamSelector_IPv6DynamicRouterInfoCount LanConfigParamSelector = 73 // read only
LanConfigParamSelector_IPv6DynamicRouterInfoIP LanConfigParamSelector = 74 // read only
LanConfigParamSelector_IPv6DynamicRouterInfoMAC LanConfigParamSelector = 75 // read only
LanConfigParamSelector_IPv6DynamicRouterInfoPrefixLength LanConfigParamSelector = 76 // read only
LanConfigParamSelector_IPv6DynamicRouterInfoPrefixValue LanConfigParamSelector = 77 // read only
LanConfigParamSelector_IPv6DynamicRouterReceivedHopLimit LanConfigParamSelector = 78 // read only
LanConfigParamSelector_IPv6NDSLAACTimingConfigSupport LanConfigParamSelector = 79 // read only, IPv6 Neighbor Discovery / SLAAC
LanConfigParamSelector_IPv6NDSLAACTimingConfig LanConfigParamSelector = 80
// OEM Parameters 192:255
// This range is available for special OEM configuration parameters. The OEM is identified
// according to the Manufacturer ID field returned by the Get Device ID command.
)
func (lanConfigParam LanConfigParamSelector) String() string {
m := map[LanConfigParamSelector]string{
LanConfigParamSelector_SetInProgress: "Set In Progress",
LanConfigParamSelector_AuthTypeSupport: "Authentication Type Support",
LanConfigParamSelector_AuthTypeEnables: "Authentication Type Enables",
LanConfigParamSelector_IP: "IP Address",
LanConfigParamSelector_IPSource: "IP Address Source",
LanConfigParamSelector_MAC: "MAC Address",
LanConfigParamSelector_SubnetMask: "Subnet Mask",
LanConfigParamSelector_IPv4HeaderParams: "IPv4 Header Params",
LanConfigParamSelector_PrimaryRMCPPort: "Primary RMCP Port",
LanConfigParamSelector_SecondaryRMCPPort: "Secondary RMCP Port",
LanConfigParamSelector_ARPControl: "ARP Control",
LanConfigParamSelector_GratuitousARPInterval: "Gratuitous ARP Interval",
LanConfigParamSelector_DefaultGatewayIP: "Default Gateway IP",
LanConfigParamSelector_DefaultGatewayMAC: "Default Gateway MAC",
LanConfigParamSelector_BackupGatewayIP: "Backup Gateway IP",
LanConfigParamSelector_BackupGatewayMAC: "Backup Gateway MAC",
LanConfigParamSelector_CommunityString: "Community String",
LanConfigParamSelector_AlertDestinationsCount: "Alert Destinations Count",
LanConfigParamSelector_AlertDestinationType: "Alert Destination Type",
LanConfigParamSelector_AlertDestinationAddress: "Alert Destination Address",
LanConfigParamSelector_VLANID: "802.1q VLAN ID",
LanConfigParamSelector_VLANPriority: "802.1q VLAN Priority",
LanConfigParamSelector_CipherSuitesSupport: "Cipher Suite Entries Support",
LanConfigParamSelector_CipherSuitesID: "Cipher Suite Entries",
LanConfigParamSelector_CipherSuitesPrivLevel: "Cipher Suite Privilege Levels",
LanConfigParamSelector_AlertDestinationVLAN: "Alert Destination VLAN",
LanConfigParamSelector_BadPasswordThreshold: "Bad Password Threshold",
LanConfigParamSelector_IPv6Support: "IPv6 Support",
LanConfigParamSelector_IPv6Enables: "IPv6 Enables",
LanConfigParamSelector_IPv6StaticTrafficClass: "IPv6 Static Traffic Class",
LanConfigParamSelector_IPv6StaticHopLimit: "IPv6 Static Hop Limit",
LanConfigParamSelector_IPv6FlowLabel: "IPv6 Flow Label",
LanConfigParamSelector_IPv6Status: "IPv6 Status",
LanConfigParamSelector_IPv6StaticAddress: "IPv6 Static Address",
LanConfigParamSelector_IPv6DHCPv6StaticDUIDCount: "IPv6 DHCPv6 Static DUID Count",
LanConfigParamSelector_IPv6DHCPv6StaticDUID: "IPv6 DHCPv6 Static DUID",
LanConfigParamSelector_IPv6DynamicAddress: "IPv6 Dynamic Address",
LanConfigParamSelector_IPv6DHCPv6DynamicDUIDCount: "IPv6 DHCPv6 Dynamic DUID Count",
LanConfigParamSelector_IPv6DHCPv6DynamicDUID: "IPv6 DHCPv6 Dynamic DUID",
LanConfigParamSelector_IPv6DHCPv6TimingConfigSupport: "IPv6 DHCPv6 Timing Config Support",
LanConfigParamSelector_IPv6DHCPv6TimingConfig: "IPv6 DHCPv6 Timing Config",
LanConfigParamSelector_IPv6RouterAddressConfigControl: "IPv6 Router Address Config Control",
LanConfigParamSelector_IPv6StaticRouter1IP: "IPv6 Static Router1 IP",
LanConfigParamSelector_IPv6StaticRouter1MAC: "IPv6 Static Router1 MAC",
LanConfigParamSelector_IPv6StaticRouter1PrefixLength: "IPv6 Static Router1 Prefix Length",
LanConfigParamSelector_IPv6StaticRouter1PrefixValue: "IPv6 Static Router1 Prefix Value",
LanConfigParamSelector_IPv6StaticRouter2IP: "IPv6 Static Router2 IP",
LanConfigParamSelector_IPv6StaticRouter2MAC: "IPv6 Static Router2 MAC",
LanConfigParamSelector_IPv6StaticRouter2PrefixLength: "IPv6 Static Router2 Prefix Length",
LanConfigParamSelector_IPv6StaticRouter2PrefixValue: "IPv6 Static Router2 Prefix Value",
LanConfigParamSelector_IPv6DynamicRouterInfoCount: "IPv6 Dynamic Router Sets Number",
LanConfigParamSelector_IPv6DynamicRouterInfoIP: "IPv6 Dynamic Router IP",
LanConfigParamSelector_IPv6DynamicRouterInfoMAC: "IPv6 Dynamic Router MAC",
LanConfigParamSelector_IPv6DynamicRouterInfoPrefixLength: "IPv6 Dynamic Router Prefix Length",
LanConfigParamSelector_IPv6DynamicRouterInfoPrefixValue: "IPv6 Dynamic Router Prefix Value",
LanConfigParamSelector_IPv6DynamicRouterReceivedHopLimit: "IPv6 Dynamic Router Received Hop Limit",
LanConfigParamSelector_IPv6NDSLAACTimingConfigSupport: "IPv6 ND/SLAAC Timing Config Support",
LanConfigParamSelector_IPv6NDSLAACTimingConfig: "IPv6 ND/SLAAC Timing Config",
}
if s, ok := m[lanConfigParam]; ok {
return s
}
return "Unknown"
}
var (
_ LanConfigParameter = (*LanConfigParam_SetInProgress)(nil)
_ LanConfigParameter = (*LanConfigParam_AuthTypeSupport)(nil)
_ LanConfigParameter = (*LanConfigParam_AuthTypeEnables)(nil)
_ LanConfigParameter = (*LanConfigParam_IP)(nil)
_ LanConfigParameter = (*LanConfigParam_IPSource)(nil)
_ LanConfigParameter = (*LanConfigParam_MAC)(nil)
_ LanConfigParameter = (*LanConfigParam_SubnetMask)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv4HeaderParams)(nil)
_ LanConfigParameter = (*LanConfigParam_PrimaryRMCPPort)(nil)
_ LanConfigParameter = (*LanConfigParam_SecondaryRMCPPort)(nil)
_ LanConfigParameter = (*LanConfigParam_ARPControl)(nil)
_ LanConfigParameter = (*LanConfigParam_GratuitousARPInterval)(nil)
_ LanConfigParameter = (*LanConfigParam_DefaultGatewayIP)(nil)
_ LanConfigParameter = (*LanConfigParam_DefaultGatewayMAC)(nil)
_ LanConfigParameter = (*LanConfigParam_BackupGatewayIP)(nil)
_ LanConfigParameter = (*LanConfigParam_BackupGatewayMAC)(nil)
_ LanConfigParameter = (*LanConfigParam_CommunityString)(nil)
_ LanConfigParameter = (*LanConfigParam_AlertDestinationsCount)(nil)
_ LanConfigParameter = (*LanConfigParam_AlertDestinationType)(nil)
_ LanConfigParameter = (*LanConfigParam_AlertDestinationAddress)(nil)
_ LanConfigParameter = (*LanConfigParam_VLANID)(nil)
_ LanConfigParameter = (*LanConfigParam_VLANPriority)(nil)
_ LanConfigParameter = (*LanConfigParam_CipherSuitesSupport)(nil)
_ LanConfigParameter = (*LanConfigParam_CipherSuitesID)(nil)
_ LanConfigParameter = (*LanConfigParam_CipherSuitesPrivLevel)(nil)
_ LanConfigParameter = (*LanConfigParam_AlertDestinationVLAN)(nil)
_ LanConfigParameter = (*LanConfigParam_BadPasswordThreshold)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6Support)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6Enables)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticTrafficClass)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticHopLimit)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6FlowLabel)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6Status)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticAddress)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DHCPv6StaticDUIDCount)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DHCPv6StaticDUID)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DynamicAddress)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DHCPv6DynamicDUIDCount)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DHCPv6DynamicDUID)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DHCPv6TimingConfigSupport)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DHCPv6TimingConfig)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6RouterAddressConfigControl)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticRouter1IP)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticRouter1MAC)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticRouter1PrefixLength)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticRouter1PrefixValue)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticRouter2IP)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticRouter2MAC)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticRouter2PrefixLength)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6StaticRouter2PrefixValue)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DynamicRouterInfoSets)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DynamicRouterInfoIP)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DynamicRouterInfoMAC)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DynamicRouterInfoPrefixLength)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DynamicRouterInfoPrefixValue)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6DynamicRouterReceivedHopLimit)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6NDSLAACTimingConfigSupport)(nil)
_ LanConfigParameter = (*LanConfigParam_IPv6NDSLAACTimingConfig)(nil)
)
func isNilLanConfigParameter(param LanConfigParameter) bool {
switch v := param.(type) {
case *LanConfigParam_SetInProgress:
return v == nil
case *LanConfigParam_AuthTypeSupport:
return v == nil
case *LanConfigParam_AuthTypeEnables:
return v == nil
case *LanConfigParam_IP:
return v == nil
case *LanConfigParam_IPSource:
return v == nil
case *LanConfigParam_MAC:
return v == nil
case *LanConfigParam_SubnetMask:
return v == nil
case *LanConfigParam_IPv4HeaderParams:
return v == nil
case *LanConfigParam_PrimaryRMCPPort:
return v == nil
case *LanConfigParam_SecondaryRMCPPort:
return v == nil
case *LanConfigParam_ARPControl:
return v == nil
case *LanConfigParam_GratuitousARPInterval:
return v == nil
case *LanConfigParam_DefaultGatewayIP:
return v == nil
case *LanConfigParam_DefaultGatewayMAC:
return v == nil
case *LanConfigParam_BackupGatewayIP:
return v == nil
case *LanConfigParam_BackupGatewayMAC:
return v == nil
case *LanConfigParam_CommunityString:
return v == nil
case *LanConfigParam_AlertDestinationsCount:
return v == nil
case *LanConfigParam_AlertDestinationType:
return v == nil
case *LanConfigParam_AlertDestinationAddress:
return v == nil
case *LanConfigParam_VLANID:
return v == nil
case *LanConfigParam_VLANPriority:
return v == nil
case *LanConfigParam_CipherSuitesSupport:
return v == nil
case *LanConfigParam_CipherSuitesID:
return v == nil
case *LanConfigParam_CipherSuitesPrivLevel:
return v == nil
case *LanConfigParam_AlertDestinationVLAN:
return v == nil
case *LanConfigParam_BadPasswordThreshold:
return v == nil
case *LanConfigParam_IPv6Support:
return v == nil
case *LanConfigParam_IPv6Enables:
return v == nil
case *LanConfigParam_IPv6StaticTrafficClass:
return v == nil
case *LanConfigParam_IPv6StaticHopLimit:
return v == nil
case *LanConfigParam_IPv6FlowLabel:
return v == nil
case *LanConfigParam_IPv6Status:
return v == nil
case *LanConfigParam_IPv6StaticAddress:
return v == nil
case *LanConfigParam_IPv6DHCPv6StaticDUIDCount:
return v == nil
case *LanConfigParam_IPv6DHCPv6StaticDUID:
return v == nil
case *LanConfigParam_IPv6DynamicAddress:
return v == nil
case *LanConfigParam_IPv6DHCPv6DynamicDUIDCount:
return v == nil
case *LanConfigParam_IPv6DHCPv6DynamicDUID:
return v == nil
case *LanConfigParam_IPv6DHCPv6TimingConfigSupport:
return v == nil
case *LanConfigParam_IPv6DHCPv6TimingConfig:
return v == nil
case *LanConfigParam_IPv6RouterAddressConfigControl:
return v == nil
case *LanConfigParam_IPv6StaticRouter1IP:
return v == nil
case *LanConfigParam_IPv6StaticRouter1MAC:
return v == nil
case *LanConfigParam_IPv6StaticRouter1PrefixLength:
return v == nil
case *LanConfigParam_IPv6StaticRouter1PrefixValue:
return v == nil
case *LanConfigParam_IPv6StaticRouter2IP:
return v == nil
case *LanConfigParam_IPv6StaticRouter2MAC:
return v == nil
case *LanConfigParam_IPv6StaticRouter2PrefixLength:
return v == nil
case *LanConfigParam_IPv6StaticRouter2PrefixValue:
return v == nil
case *LanConfigParam_IPv6DynamicRouterInfoSets:
return v == nil
case *LanConfigParam_IPv6DynamicRouterInfoIP:
return v == nil
case *LanConfigParam_IPv6DynamicRouterInfoMAC:
return v == nil
case *LanConfigParam_IPv6DynamicRouterInfoPrefixLength:
return v == nil
case *LanConfigParam_IPv6DynamicRouterInfoPrefixValue:
return v == nil
case *LanConfigParam_IPv6DynamicRouterReceivedHopLimit:
return v == nil
case *LanConfigParam_IPv6NDSLAACTimingConfigSupport:
return v == nil
case *LanConfigParam_IPv6NDSLAACTimingConfig:
return v == nil
default:
return false
}
}
type LanConfigParam_SetInProgress struct {
Value SetInProgressState
}
func (param *LanConfigParam_SetInProgress) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_SetInProgress, 0, 0
}
func (param *LanConfigParam_SetInProgress) Pack() []byte {
return []byte{byte(param.Value)}
}
func (param *LanConfigParam_SetInProgress) Unpack(data []byte) error {
if len(data) != 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Value = SetInProgressState(data[0])
return nil
}
func (param *LanConfigParam_SetInProgress) Format() string {
return param.Value.String()
}
type LanConfigParam_AuthTypeSupport struct {
OEM bool
Password bool
MD5 bool
MD2 bool
None bool
}
func (param *LanConfigParam_AuthTypeSupport) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_AuthTypeSupport, 0, 0
}
func (param *LanConfigParam_AuthTypeSupport) Pack() []byte {
b := uint8(0)
b = setOrClearBit5(b, param.OEM)
b = setOrClearBit4(b, param.Password)
b = setOrClearBit2(b, param.MD5)
b = setOrClearBit1(b, param.MD2)
b = setOrClearBit0(b, param.None)
return []byte{b}
}
func (param *LanConfigParam_AuthTypeSupport) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
b := data[0]
param.OEM = isBit5Set(b)
param.Password = isBit4Set(b)
// Bit 3 Reserved
param.MD5 = isBit2Set(b)
param.MD2 = isBit1Set(b)
param.None = isBit0Set(b)
return nil
}
func (param *LanConfigParam_AuthTypeSupport) Format() string {
var s string
if param.OEM {
s = "OEM"
} else if param.Password {
s = "Password"
} else if param.MD5 {
s = "MD5"
} else if param.MD2 {
s = "MD2"
} else if param.None {
s = "None"
}
return fmt.Sprintf(`%s, (OEM: %v, Password: %v, MD5: %v, MD2: %v, Non: %v)`,
s, param.OEM, param.Password, param.MD5, param.MD2, param.None)
}
type LanConfigParam_AuthTypeEnables struct {
Callback *AuthTypesEnabled
User *AuthTypesEnabled
Operator *AuthTypesEnabled
Admin *AuthTypesEnabled
OEM *AuthTypesEnabled
}
func (param *LanConfigParam_AuthTypeEnables) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_AuthTypeEnables, 0, 0
}
func (param *LanConfigParam_AuthTypeEnables) Unpack(data []byte) error {
if len(data) < 5 {
return ErrUnpackedDataTooShortWith(len(data), 5)
}
param.Callback = unpackAuthTypesEnabled(data[0])
param.User = unpackAuthTypesEnabled(data[1])
param.Operator = unpackAuthTypesEnabled(data[2])
param.Admin = unpackAuthTypesEnabled(data[3])
param.OEM = unpackAuthTypesEnabled(data[4])
return nil
}
func (param *LanConfigParam_AuthTypeEnables) Pack() []byte {
out := make([]byte, 5)
out[0] = packAuthTypesEnabled(param.Callback)
out[1] = packAuthTypesEnabled(param.User)
out[2] = packAuthTypesEnabled(param.Operator)
out[3] = packAuthTypesEnabled(param.Admin)
out[4] = packAuthTypesEnabled(param.OEM)
return out
}
func (param *LanConfigParam_AuthTypeEnables) Format() string {
return fmt.Sprintf("Callback: %s, User: %s, Operator: %s, Admin: %s, OEM: %s",
param.Callback.String(), param.User.String(), param.Operator.String(), param.Admin.String(), param.OEM.String())
}
type LanConfigParam_IP struct {
IP net.IP
}
func (param *LanConfigParam_IP) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IP, 0, 0
}
func (param *LanConfigParam_IP) Unpack(data []byte) error {
if len(data) < 4 {
return ErrUnpackedDataTooShortWith(len(data), 4)
}
param.IP = net.IPv4(data[0], data[1], data[2], data[3])
return nil
}
func (param *LanConfigParam_IP) Pack() []byte {
return []byte{param.IP[0], param.IP[1], param.IP[2], param.IP[3]}
}
func (param *LanConfigParam_IP) Format() string {
return param.IP.String()
}
type LanConfigParam_IPSource struct {
Source LanIPAddressSource
}
func (param *LanConfigParam_IPSource) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPSource, 0, 0
}
func (param *LanConfigParam_IPSource) Pack() []byte {
return []byte{byte(param.Source)}
}
func (param *LanConfigParam_IPSource) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Source = LanIPAddressSource(data[0])
return nil
}
func (param *LanConfigParam_IPSource) Format() string {
return param.Source.String()
}
type LanConfigParam_MAC struct {
MAC net.HardwareAddr
}
func (param *LanConfigParam_MAC) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_MAC, 0, 0
}
func (param *LanConfigParam_MAC) Unpack(data []byte) error {
if len(data) < 6 {
return ErrUnpackedDataTooShortWith(len(data), 6)
}
param.MAC = net.HardwareAddr(data[0:6])
return nil
}
func (param *LanConfigParam_MAC) Pack() []byte {
return param.MAC
}
func (param *LanConfigParam_MAC) Format() string {
return param.MAC.String()
}
type LanConfigParam_SubnetMask struct {
SubnetMask net.IP
}
func (param *LanConfigParam_SubnetMask) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_SubnetMask, 0, 0
}
func (param *LanConfigParam_SubnetMask) Unpack(data []byte) error {
if len(data) < 4 {
return ErrUnpackedDataTooShortWith(len(data), 4)
}
param.SubnetMask = net.IPv4(data[0], data[1], data[2], data[3])
return nil
}
func (param *LanConfigParam_SubnetMask) Pack() []byte {
return []byte{param.SubnetMask[0], param.SubnetMask[1], param.SubnetMask[2], param.SubnetMask[3]}
}
func (param *LanConfigParam_SubnetMask) Format() string {
return param.SubnetMask.String()
}
type LanConfigParam_IPv4HeaderParams struct {
// data 1 - Time-to-live. 1-based. (Default = 40h)
// Value for time-to-live parameter in IP Header for RMCP packets and PET Traps
// transmitted from this channel.
TTL uint8
// data 2
// - [7:5] - Flags. Sets value of bit 1 in the Flags field in the IP Header for packets transmitted
// by this channel. (Default = 010b don't fragment)
// - [4:0] - reserved
Flags uint8
// data 3
// - [7:5] - Precedence (Default = 000b)
Precedence uint8
// data 3
// - [4:1] - Type of Service (Default = 1000b, 'minimize delay')
// - [0] - reserved
TOS uint8
}
func (param *LanConfigParam_IPv4HeaderParams) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv4HeaderParams, 0, 0
}
func (param *LanConfigParam_IPv4HeaderParams) Unpack(data []byte) error {
if len(data) < 3 {
return ErrUnpackedDataTooShortWith(len(data), 3)
}
param.TTL = data[0]
param.Flags = data[1]
param.Precedence = data[2] >> 5
param.TOS = data[2] & 0x1f
return nil
}
func (param *LanConfigParam_IPv4HeaderParams) Pack() []byte {
out := make([]byte, 3)
out[0] = param.TTL
out[1] = param.Flags
out[2] = (param.Precedence << 5) | (param.TOS & 0x1f)
return out
}
func (param *LanConfigParam_IPv4HeaderParams) Format() string {
return fmt.Sprintf("TTL=%#02x Flags=%#02x Precedence=%#02x TOS=%#02x",
param.TTL, param.Flags, param.Precedence, param.TOS)
}
type LanConfigParam_PrimaryRMCPPort struct {
Port uint16
}
func (param *LanConfigParam_PrimaryRMCPPort) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_PrimaryRMCPPort, 0, 0
}
func (param *LanConfigParam_PrimaryRMCPPort) Unpack(data []byte) error {
if len(data) < 2 {
return ErrUnpackedDataTooShortWith(len(data), 2)
}
param.Port, _, _ = unpackUint16L(data, 0)
return nil
}
func (param *LanConfigParam_PrimaryRMCPPort) Pack() []byte {
out := make([]byte, 2)
packUint16L(param.Port, out, 0)
return out
}
func (param *LanConfigParam_PrimaryRMCPPort) Format() string {
return fmt.Sprintf("%d", param.Port)
}
type LanConfigParam_SecondaryRMCPPort struct {
Port uint16
}
func (param *LanConfigParam_SecondaryRMCPPort) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_SecondaryRMCPPort, 0, 0
}
func (param *LanConfigParam_SecondaryRMCPPort) Unpack(data []byte) error {
if len(data) < 2 {
return ErrUnpackedDataTooShortWith(len(data), 2)
}
param.Port, _, _ = unpackUint16L(data, 0)
return nil
}
func (param *LanConfigParam_SecondaryRMCPPort) Pack() []byte {
out := make([]byte, 2)
packUint16L(param.Port, out, 0)
return out
}
func (param *LanConfigParam_SecondaryRMCPPort) Format() string {
return fmt.Sprintf("%d", param.Port)
}
type LanConfigParam_ARPControl struct {
ARPResponseEnabled bool
GratuitousARPEnabled bool
}
func (param *LanConfigParam_ARPControl) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_ARPControl, 0, 0
}
func (param *LanConfigParam_ARPControl) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.ARPResponseEnabled = isBit1Set(data[0])
param.GratuitousARPEnabled = isBit0Set(data[0])
return nil
}
func (param *LanConfigParam_ARPControl) Pack() []byte {
out := make([]byte, 1)
b := uint8(0)
b = setOrClearBit1(b, param.ARPResponseEnabled)
b = setOrClearBit0(b, param.GratuitousARPEnabled)
out[0] = b
return out
}
func (param *LanConfigParam_ARPControl) Format() string {
return fmt.Sprintf("ARP Responses %s, Gratuitous ARP %s",
formatBool(param.ARPResponseEnabled, "enabled", "disabled"),
formatBool(param.GratuitousARPEnabled, "enabled", "disabled"))
}
type LanConfigParam_GratuitousARPInterval struct {
// Gratuitous ARP interval in 500 millisecond increments. 0-based.
MilliSec uint32
}
func (param *LanConfigParam_GratuitousARPInterval) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_GratuitousARPInterval, 0, 0
}
func (param *LanConfigParam_GratuitousARPInterval) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.MilliSec = uint32(data[0]) * 500
return nil
}
func (param *LanConfigParam_GratuitousARPInterval) Pack() []byte {
out := make([]byte, 1)
out[0] = uint8(param.MilliSec / 500)
return out
}
func (param *LanConfigParam_GratuitousARPInterval) Format() string {
return fmt.Sprintf("%.1f seconds", float64(param.MilliSec/1000.0))
}
type LanConfigParam_DefaultGatewayIP struct {
IP net.IP
}
func (param *LanConfigParam_DefaultGatewayIP) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_DefaultGatewayIP, 0, 0
}
func (param *LanConfigParam_DefaultGatewayIP) Unpack(data []byte) error {
if len(data) < 4 {
return ErrUnpackedDataTooShortWith(len(data), 4)
}
param.IP = net.IPv4(data[0], data[1], data[2], data[3])
return nil
}
func (param *LanConfigParam_DefaultGatewayIP) Pack() []byte {
out := make([]byte, 4)
out[0] = param.IP[0]
out[1] = param.IP[1]
out[2] = param.IP[2]
out[3] = param.IP[3]
return out
}
func (param *LanConfigParam_DefaultGatewayIP) Format() string {
return param.IP.String()
}
type LanConfigParam_DefaultGatewayMAC struct {
MAC net.HardwareAddr
}
func (param *LanConfigParam_DefaultGatewayMAC) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_DefaultGatewayMAC, 0, 0
}
func (param *LanConfigParam_DefaultGatewayMAC) Unpack(data []byte) error {
if len(data) < 6 {
return ErrUnpackedDataTooShortWith(len(data), 6)
}
param.MAC = net.HardwareAddr(data[0:6])
return nil
}
func (param *LanConfigParam_DefaultGatewayMAC) Pack() []byte {
out := make([]byte, 6)
out[0] = param.MAC[0]
out[1] = param.MAC[1]
out[2] = param.MAC[2]
out[3] = param.MAC[3]
out[4] = param.MAC[4]
out[5] = param.MAC[5]
return out
}
func (param *LanConfigParam_DefaultGatewayMAC) Format() string {
return param.MAC.String()
}
type LanConfigParam_BackupGatewayIP struct {
IP net.IP
}
func (param *LanConfigParam_BackupGatewayIP) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_BackupGatewayIP, 0, 0
}
func (param *LanConfigParam_BackupGatewayIP) Unpack(data []byte) error {
if len(data) < 4 {
return ErrUnpackedDataTooShortWith(len(data), 4)
}
param.IP = net.IPv4(data[0], data[1], data[2], data[3])
return nil
}
func (param *LanConfigParam_BackupGatewayIP) Pack() []byte {
out := make([]byte, 4)
out[0] = param.IP[0]
out[1] = param.IP[1]
out[2] = param.IP[2]
out[3] = param.IP[3]
return out
}
func (param *LanConfigParam_BackupGatewayIP) Format() string {
return param.IP.String()
}
type LanConfigParam_BackupGatewayMAC struct {
MAC net.HardwareAddr
}
func (param *LanConfigParam_BackupGatewayMAC) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_BackupGatewayMAC, 0, 0
}
func (param *LanConfigParam_BackupGatewayMAC) Unpack(data []byte) error {
if len(data) < 6 {
return ErrUnpackedDataTooShortWith(len(data), 6)
}
param.MAC = net.HardwareAddr(data[0:6])
return nil
}
func (param *LanConfigParam_BackupGatewayMAC) Pack() []byte {
out := make([]byte, 6)
out[0] = param.MAC[0]
out[1] = param.MAC[1]
out[2] = param.MAC[2]
out[3] = param.MAC[3]
out[4] = param.MAC[4]
out[5] = param.MAC[5]
return out
}
func (param *LanConfigParam_BackupGatewayMAC) Format() string {
return param.MAC.String()
}
type LanConfigParam_CommunityString struct {
CommunityString CommunityString
}
func (param *LanConfigParam_CommunityString) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_CommunityString, 0, 0
}
func (param *LanConfigParam_CommunityString) Unpack(data []byte) error {
if len(data) < 18 {
return ErrUnpackedDataTooShortWith(len(data), 18)
}
var cs CommunityString
for i := 0; i < 18; i++ {
cs[i] = data[i]
}
param.CommunityString = cs
return nil
}
func (param *LanConfigParam_CommunityString) Pack() []byte {
return param.CommunityString[:]
}
func (param *LanConfigParam_CommunityString) Format() string {
return string(param.CommunityString[:])
}
// Number of LAN Alert Destinations supported on this channel. (Read Only).
//
// At least one set of non-volatile destination information is required if LAN alerting is supported.
//
// Additional non-volatile destination parameters can optionally be provided for supporting an
// alert 'call down' list policy.
//
// A maximum of fifteen (1h to Fh) non-volatile destinations are supported in this specification.
// Destination 0 is always present as a volatile destination that is used with the Alert Immediate command.
type LanConfigParam_AlertDestinationsCount struct {
// [7:4] - reserved.
// [3:0] - Number LAN Destinations. A count of 0h indicates LAN Alerting is not supported.
// This value is number of non-volatile destinations.
Count uint8
}
func (param *LanConfigParam_AlertDestinationsCount) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_AlertDestinationsCount, 0, 0
}
func (param *LanConfigParam_AlertDestinationsCount) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Count = data[0] & 0x0f
return nil
}
func (param *LanConfigParam_AlertDestinationsCount) Pack() []byte {
out := make([]byte, 1)
out[0] = param.Count & 0x0f
return out
}
func (param *LanConfigParam_AlertDestinationsCount) Format() string {
return fmt.Sprintf("%d", param.Count)
}
type LanConfigParam_AlertDestinationType struct {
// Destination selector, 0 based.
// Destination 0 is always present as a volatile destination that is used with the Alert Immediate command.
SetSelector uint8
// Alert Acknowledge
// - 0b = Unacknowledged.
// Alert is assumed successful if transmission occurs without error.
// This value is also used with Callback numbers.
// - 1b = Acknowledged.
// Alert is assumed successful only if acknowledged is returned.
// Note, some alert types, such as Dial Page, do not support an acknowledge
AlertAcknowledged bool
// Destination Type
// - 000b = PET Trap destination
// - 001b - 101b = reserved
// - 110b = OEM 1
// - 111b = OEM 2
DestinationType uint8
// Alert Acknowledge Timeout / Retry Interval, in seconds, 0-based (i.e. minimum
// timeout = 1 second)
AlertAcknowledgeTimeout uint8
// Number of times to retry alert to given destination.
Retries uint8
}
func (param *LanConfigParam_AlertDestinationType) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_AlertDestinationType, param.SetSelector, 0
}
func (param *LanConfigParam_AlertDestinationType) Unpack(data []byte) error {
if len(data) < 4 {
return ErrUnpackedDataTooShortWith(len(data), 4)
}
param.SetSelector = data[0]
param.AlertAcknowledged = isBit7Set(data[1])
param.DestinationType = data[1] & 0x03
param.AlertAcknowledgeTimeout = data[2]
param.Retries = data[3] & 0x07
return nil
}
func (param *LanConfigParam_AlertDestinationType) Pack() []byte {
out := make([]byte, 4)
out[0] = param.SetSelector
b := param.DestinationType & 0x03
b = setOrClearBit7(b, param.AlertAcknowledged)
out[1] = b
out[2] = param.AlertAcknowledgeTimeout
out[3] = param.Retries
return out
}
func (param *LanConfigParam_AlertDestinationType) Format() string {
return fmt.Sprintf("%12s %2d, %v, %d, %d, %d",
formatBool(param.SetSelector == 0, "volatile", "non-volatile"),
param.SetSelector,
formatBool(param.AlertAcknowledged, "acknowledged", "unacknowledged"),
param.DestinationType,
param.AlertAcknowledgeTimeout,
param.Retries,
)
}
type LanConfigParam_AlertDestinationAddress struct {
SetSelector uint8
IsIPv6 bool
// - 0b = use default gateway first, then backup gateway
// (Note: older implementations (errata 4 or earlier) may only send to the default gateway.)
// - 1b = use backup gateway
UseBackupGateway bool
IPv4 net.IP
MAC net.HardwareAddr
IPv6 net.IP
}
func (param *LanConfigParam_AlertDestinationAddress) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_AlertDestinationAddress, param.SetSelector, 0
}
func (param *LanConfigParam_AlertDestinationAddress) Unpack(data []byte) error {
if len(data) < 13 {
return ErrUnpackedDataTooShortWith(len(data), 13)
}
param.SetSelector = data[0]
param.IsIPv6 = isBit4Set(data[1])
if param.IsIPv6 {
if len(data) < 18 {
return ErrUnpackedDataTooShortWith(len(data), 18)
}
param.IPv6 = net.IP(data[3:18])
} else {
param.UseBackupGateway = isBit7Set(data[2])
param.IPv4 = net.IP(data[3:7])
param.MAC = net.HardwareAddr(data[7:13])
}
return nil
}
func (param *LanConfigParam_AlertDestinationAddress) Pack() []byte {
out := make([]byte, 2)
return out
}
func (param *LanConfigParam_AlertDestinationAddress) Format() string {
return fmt.Sprintf("%12s %2d, %s, %s, %s",
formatBool(param.SetSelector == 0, "volatile", "non-volatile"),
param.SetSelector,
formatBool(param.UseBackupGateway, "backup gateway", "default gateway"),
formatBool(param.IsIPv6, "IPv6", "IPv4"),
formatBool(param.IsIPv6, param.IPv6.String(), fmt.Sprintf("%s/%s", param.IPv4, param.MAC)),
)
}
type LanConfigParam_VLANID struct {
Enabled bool
ID uint16
}
func (param *LanConfigParam_VLANID) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_VLANID, 0, 0
}
func (param *LanConfigParam_VLANID) Unpack(data []byte) error {
if len(data) < 2 {
return ErrUnpackedDataTooShortWith(len(data), 2)
}
param.Enabled = isBit7Set(data[1])
id := uint16(data[1]) & 0x0f
id <<= 12
id |= uint16(data[0])
param.ID = id
return nil
}
func (param *LanConfigParam_VLANID) Pack() []byte {
out := make([]byte, 2)
out[0] = byte(param.ID & 0xff)
b := byte(param.ID >> 8)
b = setOrClearBit7(b, param.Enabled)
out[1] = b
return out
}
func (param *LanConfigParam_VLANID) Format() string {
return formatBool(param.Enabled, fmt.Sprintf("%d", param.ID), "disabled")
}
type LanConfigParam_VLANPriority struct {
Priority uint8
}
func (param *LanConfigParam_VLANPriority) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_VLANPriority, 0, 0
}
func (param *LanConfigParam_VLANPriority) Pack() []byte {
out := make([]byte, 1)
out[0] = param.Priority & 0x07
return out
}
func (param *LanConfigParam_VLANPriority) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Priority = data[0] & 0x07
return nil
}
func (param *LanConfigParam_VLANPriority) Format() string {
return fmt.Sprintf("%#2x", param.Priority)
}
type LanConfigParam_CipherSuitesSupport struct {
// Cipher Suite Entry count. Number of Cipher Suite entries, 1-based, 10h max.
Count uint8
}
func (param *LanConfigParam_CipherSuitesSupport) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_CipherSuitesSupport, 0, 0
}
func (param *LanConfigParam_CipherSuitesSupport) Pack() []byte {
out := make([]byte, 1)
out[0] = param.Count & 0x1f
return out
}
func (param *LanConfigParam_CipherSuitesSupport) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Count = data[0] & 0x1f
return nil
}
func (param *LanConfigParam_CipherSuitesSupport) Format() string {
return fmt.Sprintf("%d", param.Count)
}
type LanConfigParam_CipherSuitesID struct {
IDs [16]CipherSuiteID
}
func (param *LanConfigParam_CipherSuitesID) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_CipherSuitesID, 0, 0
}
func (param *LanConfigParam_CipherSuitesID) Pack() []byte {
out := make([]uint8, 17)
out[0] = 0
for i, id := range param.IDs {
out[i+1] = uint8(id)
}
return out
}
func (param *LanConfigParam_CipherSuitesID) Unpack(data []byte) error {
if len(data) > 17 {
data = data[:17]
}
for i, v := range data {
if i == 0 {
// first byte is reserved
continue
}
param.IDs[i-1] = CipherSuiteID(v)
}
return nil
}
func (param *LanConfigParam_CipherSuitesID) Format() string {
ss := make([]string, 0)
for i, v := range param.IDs[:] {
if i != 0 && v == 0 {
// Only the first ID can be CipherSuiteID0, all other 0s means empty slot.
continue
}
ss = append(ss, strconv.Itoa(int(v)))
}
return strings.Join(ss, ",")
}
type LanConfigParam_CipherSuitesPrivLevel struct {
PrivLevels [16]PrivilegeLevel
}
func (param *LanConfigParam_CipherSuitesPrivLevel) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_CipherSuitesPrivLevel, 0, 0
}
func (param *LanConfigParam_CipherSuitesPrivLevel) Pack() []byte {
out := make([]byte, 9)
out[0] = 0
for i := 0; i < 8; i++ {
o := byte(param.PrivLevels[2*i] & 0x0f)
o |= byte(param.PrivLevels[2*i+1] & 0x0f)
out[i+1] = o
}
return out
}
func (param *LanConfigParam_CipherSuitesPrivLevel) Unpack(data []byte) error {
if len(data) < 9 {
return ErrUnpackedDataTooShortWith(len(data), 9)
}
for i, v := range data[0:9] {
if i == 0 {
// first byte is reserved
continue
}
param.PrivLevels[2*i-2] = PrivilegeLevel(v & 0x0f)
param.PrivLevels[2*i-1] = PrivilegeLevel(v & 0xf0 >> 4)
}
return nil
}
func (param *LanConfigParam_CipherSuitesPrivLevel) Format() string {
ss := []string{}
for _, v := range param.PrivLevels[:] {
ss = append(ss, v.Symbol())
}
return fmt.Sprintf(`%s
: X=Cipher Suite Unused
: c=CALLBACK
: u=USER
: o=OPERATOR
: a=ADMIN
: O=OEM`,
strings.Join(ss, ""))
}
type LanConfigParam_AlertDestinationVLAN struct {
// data 1 - Set Selector = Destination Selector.
// - [7:4] - reserved
// - [3:0] - Destination selector.
// Destination 0 is always present as a volatile destination that is used with the Alert Immediate command.
SetSelector uint8
// Address Format.
// VLAN ID is used with this destination
// - 0h = VLAN ID not used with this destination
// - 1h = 802.1q VLAN TAG
Enabled bool
// data 3-4 - VLAN TAG
// - [7:0] - VLAN ID, least-significant byte
// - [11:8] - VLAN ID, most-significant nibble
// - [12] - CFI (Canonical Format Indicator. Set to 0b)
// - [15:13] - User priority (000b, typical)
VLANID uint16
CFI bool
Priority uint8
}
func (param *LanConfigParam_AlertDestinationVLAN) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_AlertDestinationVLAN, param.SetSelector, 0
}
func (param *LanConfigParam_AlertDestinationVLAN) Pack() []byte {
out := make([]byte, 4)
out[0] = param.SetSelector
b1 := uint8(0)
b1 = setOrClearBit5(b1, param.Enabled)
out[1] = b1
out[2] = uint8(param.VLANID)
b3 := uint8(param.VLANID>>8) & 0x0f
b3 = setOrClearBit4(b3, param.CFI)
b3 |= param.Priority << 5
out[3] = b3
return out
}
func (param *LanConfigParam_AlertDestinationVLAN) Unpack(data []byte) error {
if len(data) < 4 {
return ErrUnpackedDataTooShortWith(len(data), 4)
}
param.SetSelector = data[0]
param.Enabled = isBit4Set(data[1])
param.CFI = isBit4Set(data[3])
param.Priority = data[3] >> 5
param.VLANID = uint16(data[3]&0x0f) << 12
param.VLANID |= uint16(data[2])
return nil
}
func (param *LanConfigParam_AlertDestinationVLAN) Format() string {
return fmt.Sprintf("%12s %d, %s, %d, %s, %d",
formatBool(param.SetSelector == 0, "volatile", "non-volatile"),
param.SetSelector,
formatBool(param.Enabled, "enabled", "disabled"),
param.VLANID,
formatBool(param.CFI, "1", "0"),
param.Priority,
)
}
type LanConfigParam_BadPasswordThreshold struct {
// Generate Session Audit Event
// - 0b = do not generate an event message when the user is disabled.
// - 1b = generate a Session Audit sensor "Invalid password disable" event message.
GenerateSessionAuditEvent bool
// Bad Password Threshold number
Threshold uint8
// Attempt Count Reset Interval.
// The raw data occupies 2 bytes, and the unit is in tens of seconds.
//
// 0 means the Attempt Count Reset Interval is disabled.
// The count of bad password attempts is retained as long as
// the BMC remains powered and is not reinitialized.
AttemptCountResetIntervalSec uint32
// User Lockout Interval
// The raw data occupies 2 bytes, and the unit is in tens of seconds.
//
// 0 means the User Lockout Interval is disabled.
// If a user was automatically disabled due to the Bad Password threshold,
// the user will remain disabled until re-enabled via the Set User Access command.
UserLockoutIntervalSec uint32
}
func (param *LanConfigParam_BadPasswordThreshold) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_BadPasswordThreshold, 0, 0
}
func (param *LanConfigParam_BadPasswordThreshold) Pack() []byte {
out := make([]byte, 0)
b := uint8(0)
b = setOrClearBit0(b, param.GenerateSessionAuditEvent)
out[0] = b
out[1] = param.Threshold
resetInterval := uint16(param.AttemptCountResetIntervalSec / 10)
lockInterval := uint16(param.UserLockoutIntervalSec / 10)
packUint16L(resetInterval, out, 2)
packUint16L(lockInterval, out, 4)
return out
}
func (param *LanConfigParam_BadPasswordThreshold) Unpack(data []byte) error {
if len(data) < 6 {
return ErrUnpackedDataTooShortWith(len(data), 6)
}
param.GenerateSessionAuditEvent = isBit0Set(data[0])
param.Threshold = data[1]
resetInterval, _, _ := unpackUint16L(data, 2)
lockInterval, _, _ := unpackUint16L(data, 4)
param.AttemptCountResetIntervalSec = uint32(resetInterval) * 10
param.UserLockoutIntervalSec = uint32(lockInterval) * 10
return nil
}
func (param *LanConfigParam_BadPasswordThreshold) Format() string {
return fmt.Sprintf(`
Threshold : %d
Generate Session Audit Event : %v
Attempt Count Reset Interval : %d
User Lockout Interval : %d
`,
param.Threshold,
param.GenerateSessionAuditEvent,
param.AttemptCountResetIntervalSec,
param.UserLockoutIntervalSec,
)
}
type LanConfigParam_IPv6Support struct {
// Implementation supports IPv6 Destination Addresses for LAN Alerting.
SupportIPv6AlertDestination bool
// Implementation can be configured to use both IPv4 and IPv6 addresses simultaneously
CanUseBothIPv4AndIPv6 bool
// Implementation can be configured to use IPv6 addresses only.
CanUseIPv6Only bool
}
func (param *LanConfigParam_IPv6Support) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6Support, 0, 0
}
func (param *LanConfigParam_IPv6Support) Pack() []byte {
out := make([]byte, 1)
var b byte
b = setOrClearBit2(b, param.SupportIPv6AlertDestination)
b = setOrClearBit1(b, param.CanUseBothIPv4AndIPv6)
b = setOrClearBit0(b, param.CanUseIPv6Only)
out[1] = b
return out
}
func (param *LanConfigParam_IPv6Support) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.SupportIPv6AlertDestination = isBit2Set(data[0])
param.CanUseBothIPv4AndIPv6 = isBit1Set(data[0])
param.CanUseIPv6Only = isBit0Set(data[0])
return nil
}
func (param *LanConfigParam_IPv6Support) Format() string {
return fmt.Sprintf("%s %s %s",
formatBool(param.SupportIPv6AlertDestination, "ipv6(supported)", "ipv6(not-supported)"),
formatBool(param.CanUseBothIPv4AndIPv6, "ipv4-and-ipv6(supported)", "ipv4-and-ipv6(not-supported)"),
formatBool(param.CanUseIPv6Only, "ipv6-only(supported)", "ipv6-only(not-supported)"),
)
}
type LanConfigParam_IPv6Enables struct {
EnableMode LanIPv6EnableMode
}
func (enableMode LanIPv6EnableMode) String() string {
m := map[LanIPv6EnableMode]string{
LanIPv6EnableMode_IPv6Disabled: "IPv6 disabled",
LanIPv6EnableMode_IPv6Only: "IPv6 only",
LanIPv6EnableMode_IPv4AndIPv6: "IPv4 and IPv6",
}
s, ok := m[enableMode]
if ok {
return s
}
return "Unknown"
}
func (param *LanConfigParam_IPv6Enables) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6Enables, 0, 0
}
func (param *LanConfigParam_IPv6Enables) Pack() []byte {
out := make([]byte, 1)
out[0] = uint8(param.EnableMode)
return out
}
func (param *LanConfigParam_IPv6Enables) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.EnableMode = LanIPv6EnableMode(data[0])
return nil
}
func (param *LanConfigParam_IPv6Enables) Format() string {
return param.EnableMode.String()
}
type LanConfigParam_IPv6StaticTrafficClass struct {
TrafficClass uint8
}
func (param *LanConfigParam_IPv6StaticTrafficClass) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticTrafficClass, 0, 0
}
func (param *LanConfigParam_IPv6StaticTrafficClass) Pack() []byte {
out := make([]byte, 1)
out[0] = param.TrafficClass
return out
}
func (param *LanConfigParam_IPv6StaticTrafficClass) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.TrafficClass = data[0]
return nil
}
func (param *LanConfigParam_IPv6StaticTrafficClass) Format() string {
return fmt.Sprintf("%d", param.TrafficClass)
}
type LanConfigParam_IPv6StaticHopLimit struct {
HopLimit uint8
}
func (param *LanConfigParam_IPv6StaticHopLimit) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticHopLimit, 0, 0
}
func (param *LanConfigParam_IPv6StaticHopLimit) Pack() []byte {
out := make([]byte, 1)
out[0] = param.HopLimit
return out
}
func (param *LanConfigParam_IPv6StaticHopLimit) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.HopLimit = data[0]
return nil
}
func (param *LanConfigParam_IPv6StaticHopLimit) Format() string {
return fmt.Sprintf("%d", param.HopLimit)
}
type LanConfigParam_IPv6FlowLabel struct {
// Flow Label, 20-bits, right justified, MS Byte first. Default = 0.
//
// Three bytes.
//
// If this configuration parameter is not supported, the Flow Label shall be set to 0 per [RFC2460].
// Bits [23:20] = reserved - set to 0b.
// see: https://datatracker.ietf.org/doc/html/rfc2460#page-25
FlowLabel uint32
}
func (param *LanConfigParam_IPv6FlowLabel) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6FlowLabel, 0, 0
}
func (param *LanConfigParam_IPv6FlowLabel) Pack() []byte {
out := make([]byte, 3)
packUint24(param.FlowLabel, out, 0)
return out
}
func (param *LanConfigParam_IPv6FlowLabel) Unpack(data []byte) error {
if len(data) < 3 {
return ErrUnpackedDataTooShortWith(len(data), 3)
}
param.FlowLabel, _, _ = unpackUint24(data, 0)
return nil
}
func (param *LanConfigParam_IPv6FlowLabel) Format() string {
return fmt.Sprintf("%d", param.FlowLabel)
}
type LanConfigParam_IPv6Status struct {
// Maximum number of static IPv6 addresses for establishing connections to the BMC.
// Note: in some implementations this may exceed the number of simultaneous sessions supported on
// the channel. 0 indicates that static address configuration is not available.
StaticAddressMax uint8
// Maximum number of Dynamic (SLAAC/ DHCPv6) IPv6 addresses that can be obtained for
// establishing connections to the BMC.
//Note: in some implementations this may exceed the number of simultaneous sessions supported on the channel.
// 0 = Dynamic addressing is not supported by the BMC.
DynamicAddressMax uint8
// data 3: -
// - [7:2] - reserved
// - [1] - 1b = SLAAC addressing is supported by the BMC
// - [0] - 1b = DHCPv6 addressing is supported by the BMC (optional)
SupportSLAACAddressing bool
SupportDHCPv6Addressing bool
}
func (param *LanConfigParam_IPv6Status) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6Status, 0, 0
}
func (param *LanConfigParam_IPv6Status) Unpack(data []byte) error {
if len(data) < 3 {
return ErrUnpackedDataTooShortWith(len(data), 3)
}
param.StaticAddressMax = data[0]
param.DynamicAddressMax = data[1]
param.SupportSLAACAddressing = isBit1Set(data[2])
param.SupportDHCPv6Addressing = isBit0Set(data[2])
return nil
}
func (param *LanConfigParam_IPv6Status) Pack() []byte {
out := make([]byte, 3)
out[0] = param.StaticAddressMax
out[1] = param.DynamicAddressMax
var b uint8
b = setOrClearBit1(b, param.SupportSLAACAddressing)
b = setOrClearBit0(b, param.SupportDHCPv6Addressing)
out[2] = b
return out
}
func (param *LanConfigParam_IPv6Status) Format() string {
return fmt.Sprintf("Static Addr Max: %d, Dynamic Addr Max: %d, SupportSLAAC: %v, SupportDHCPv6: %v",
param.StaticAddressMax, param.DynamicAddressMax, param.SupportSLAACAddressing, param.SupportDHCPv6Addressing)
}
type LanConfigParam_IPv6StaticAddress struct {
SetSelector uint8
// Address Enabled
// - [7]- enable=1/disable=0
Enabled bool
// Address Source
// [3:0]- source/type
// - 0h = Static
// - All other = reserved
Source LanIPv6StaticAddressSource
IPv6 net.IP
PrefixLength uint8
Status LanIPv6AddressStatus
}
func (param *LanConfigParam_IPv6StaticAddress) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticAddress, param.SetSelector, 0
}
func (param *LanConfigParam_IPv6StaticAddress) Pack() []byte {
out := make([]byte, 20)
out[0] = param.SetSelector
var b1 uint8
b1 = setOrClearBit7(b1, param.Enabled)
b1 |= uint8(param.Source) & 0x0f
out[1] = b1
// 16-byte (IPv6)
packBytes(param.IPv6, out, 2)
out[18] = param.PrefixLength
out[19] = byte(param.Status)
return out
}
func (param *LanConfigParam_IPv6StaticAddress) Unpack(data []byte) error {
if len(data) < 20 {
return ErrUnpackedDataTooShortWith(len(data), 20)
}
param.SetSelector = data[0]
param.Enabled = isBit7Set(data[1])
param.Source = LanIPv6StaticAddressSource(data[1] & 0x0f)
param.IPv6 = net.IP(data[2:18])
param.PrefixLength = data[18]
param.Status = LanIPv6AddressStatus(data[19])
return nil
}
func (param *LanConfigParam_IPv6StaticAddress) Format() string {
return fmt.Sprintf("%d, Enabled: %v, Source: %d, IPv6: %s, PrefixLength: %d, Status: %s",
param.SetSelector, param.Enabled, param.Source, param.IPv6, param.PrefixLength, param.Status)
}
type LanConfigParam_IPv6DHCPv6StaticDUIDCount struct {
// The maximum number of 16-byte blocks that can be used for storing each DUID via
// the IPv6 DHCPv6 Static DUIDs parameter. 1-based. Returns 0 if IPv6 Static Address
// configuration is not supported.
Max uint8
}
func (param *LanConfigParam_IPv6DHCPv6StaticDUIDCount) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DHCPv6StaticDUIDCount, 0, 0
}
func (param *LanConfigParam_IPv6DHCPv6StaticDUIDCount) Pack() []byte {
out := make([]byte, 1)
out[0] = param.Max
return out
}
func (param *LanConfigParam_IPv6DHCPv6StaticDUIDCount) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Max = data[0]
return nil
}
func (param *LanConfigParam_IPv6DHCPv6StaticDUIDCount) Format() string {
return fmt.Sprintf("%d", param.Max)
}
type LanConfigParam_IPv6DHCPv6StaticDUID struct {
SetSelector uint8
BlockSelector uint8
DUID [16]byte
}
func (param *LanConfigParam_IPv6DHCPv6StaticDUID) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DHCPv6StaticDUID, param.SetSelector, param.BlockSelector
}
func (param *LanConfigParam_IPv6DHCPv6StaticDUID) Pack() []byte {
out := make([]byte, 18)
out[0] = param.SetSelector
out[1] = param.BlockSelector
copy(out[2:], param.DUID[:])
return out
}
func (param *LanConfigParam_IPv6DHCPv6StaticDUID) Unpack(data []byte) error {
if len(data) < 18 {
return ErrUnpackedDataTooShortWith(len(data), 18)
}
param.SetSelector = data[0]
param.BlockSelector = data[1]
copy(param.DUID[:], data[2:18])
return nil
}
func (param *LanConfigParam_IPv6DHCPv6StaticDUID) Format() string {
return fmt.Sprintf("%d, %d, %x", param.SetSelector, param.BlockSelector, param.DUID)
}
type LanConfigParam_IPv6DynamicAddress struct {
SetSelector uint8
Enabled bool
Source LanIPv6DynamicAddressSource
IPv6 net.IP
PrefixLength uint8
Status LanIPv6AddressStatus
}
func (param *LanConfigParam_IPv6DynamicAddress) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DynamicAddress, param.SetSelector, 0
}
func (param *LanConfigParam_IPv6DynamicAddress) Pack() []byte {
out := make([]byte, 20)
out[0] = param.SetSelector
var b1 uint8
b1 = setOrClearBit7(b1, param.Enabled)
b1 |= uint8(param.Source) & 0x0f
out[1] = b1
// 16-byte (IPv6)
packBytes(param.IPv6, out, 2)
out[18] = param.PrefixLength
out[19] = byte(param.Status)
return out
}
func (param *LanConfigParam_IPv6DynamicAddress) Unpack(data []byte) error {
if len(data) < 20 {
return ErrUnpackedDataTooShortWith(len(data), 20)
}
param.SetSelector = data[0]
param.Enabled = isBit7Set(data[1])
param.Source = LanIPv6DynamicAddressSource(data[1] & 0x0f)
param.IPv6 = net.IP(data[2:18])
param.PrefixLength = data[18]
param.Status = LanIPv6AddressStatus(data[19])
return nil
}
func (param *LanConfigParam_IPv6DynamicAddress) Format() string {
return fmt.Sprintf("%d, Enabled: %v, Source: %d, IPv6: %s, PrefixLength: %d, Status: %s",
param.SetSelector, param.Enabled, param.Source, param.IPv6, param.PrefixLength, param.Status)
}
type LanConfigParam_IPv6DHCPv6DynamicDUIDCount struct {
// The maximum number of 16-byte blocks that can be used for storing each DUID via
// the IPv6 DHCPv6 Static DUIDs parameter. 1-based. Returns 0 if IPv6 Static Address
// configuration is not supported.
Max uint8
}
func (param *LanConfigParam_IPv6DHCPv6DynamicDUIDCount) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DHCPv6DynamicDUIDCount, 0, 0
}
func (param *LanConfigParam_IPv6DHCPv6DynamicDUIDCount) Pack() []byte {
out := make([]byte, 1)
out[0] = param.Max
return out
}
func (param *LanConfigParam_IPv6DHCPv6DynamicDUIDCount) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Max = data[0]
return nil
}
func (param *LanConfigParam_IPv6DHCPv6DynamicDUIDCount) Format() string {
return fmt.Sprintf("%d", param.Max)
}
type LanConfigParam_IPv6DHCPv6DynamicDUID struct {
SetSelector uint8
BlockSelector uint8
DUID [16]byte
}
func (param *LanConfigParam_IPv6DHCPv6DynamicDUID) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DHCPv6DynamicDUID, param.SetSelector, param.BlockSelector
}
func (param *LanConfigParam_IPv6DHCPv6DynamicDUID) Pack() []byte {
out := make([]byte, 18)
out[0] = param.SetSelector
out[1] = param.BlockSelector
copy(out[2:], param.DUID[:])
return out
}
func (param *LanConfigParam_IPv6DHCPv6DynamicDUID) Unpack(data []byte) error {
if len(data) < 18 {
return ErrUnpackedDataTooShortWith(len(data), 18)
}
param.SetSelector = data[0]
param.BlockSelector = data[1]
copy(param.DUID[:], data[2:18])
return nil
}
func (param *LanConfigParam_IPv6DHCPv6DynamicDUID) Format() string {
return fmt.Sprintf("%d, %d, %x", param.SetSelector, param.BlockSelector, param.DUID)
}
type LanConfigParam_IPv6DHCPv6TimingConfigSupport struct {
Mode LanIPv6DHCPv6TimingConfigMode
}
func (param *LanConfigParam_IPv6DHCPv6TimingConfigSupport) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DHCPv6TimingConfigSupport, 0, 0
}
func (param *LanConfigParam_IPv6DHCPv6TimingConfigSupport) Pack() []byte {
out := make([]byte, 1)
out[0] = byte(param.Mode)
return out
}
func (param *LanConfigParam_IPv6DHCPv6TimingConfigSupport) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Mode = LanIPv6DHCPv6TimingConfigMode(data[0])
return nil
}
func (param *LanConfigParam_IPv6DHCPv6TimingConfigSupport) Format() string {
return fmt.Sprintf("%s (%d)", param.Mode.String(), param.Mode)
}
type LanConfigParam_IPv6DHCPv6TimingConfig struct {
SetSelector uint8
BlockSelector uint8
}
func (param *LanConfigParam_IPv6DHCPv6TimingConfig) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DHCPv6TimingConfig, param.SetSelector, param.BlockSelector
}
func (param *LanConfigParam_IPv6DHCPv6TimingConfig) Pack() []byte {
out := make([]byte, 2)
out[0] = param.SetSelector
out[1] = param.BlockSelector
return out
}
func (param *LanConfigParam_IPv6DHCPv6TimingConfig) Unpack(data []byte) error {
if len(data) < 2 {
return ErrUnpackedDataTooShortWith(len(data), 2)
}
param.SetSelector = data[0]
param.BlockSelector = data[1]
return nil
}
func (param *LanConfigParam_IPv6DHCPv6TimingConfig) Format() string {
return fmt.Sprintf("%d, %d", param.SetSelector, param.BlockSelector)
}
type LanConfigParam_IPv6RouterAddressConfigControl struct {
// enable dynamic router address configuration via router advertisement messages.
EnableDynamic bool
// enable static router address
EnableStatic bool
}
func (param *LanConfigParam_IPv6RouterAddressConfigControl) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6RouterAddressConfigControl, 0, 0
}
func (param *LanConfigParam_IPv6RouterAddressConfigControl) Pack() []byte {
out := make([]byte, 1)
var b uint8
b = setOrClearBit1(b, param.EnableDynamic)
b = setOrClearBit0(b, param.EnableStatic)
out[0] = b
return out
}
func (param *LanConfigParam_IPv6RouterAddressConfigControl) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.EnableDynamic = isBit1Set(data[0])
param.EnableStatic = isBit0Set(data[0])
return nil
}
func (param *LanConfigParam_IPv6RouterAddressConfigControl) Format() string {
return fmt.Sprintf("dynamic: %s, static: %s",
formatBool(param.EnableDynamic, "enabled", "disabled"),
formatBool(param.EnableStatic, "enabled", "disabled"),
)
}
type LanConfigParam_IPv6StaticRouter1IP struct {
IPv6 net.IP
}
func (param *LanConfigParam_IPv6StaticRouter1IP) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticRouter1IP, 0, 0
}
func (param *LanConfigParam_IPv6StaticRouter1IP) Pack() []byte {
out := make([]byte, 16)
copy(out, param.IPv6)
return out
}
func (param *LanConfigParam_IPv6StaticRouter1IP) Unpack(data []byte) error {
if len(data) < 16 {
return ErrUnpackedDataTooShortWith(len(data), 16)
}
param.IPv6 = data
return nil
}
func (param *LanConfigParam_IPv6StaticRouter1IP) Format() string {
return param.IPv6.String()
}
type LanConfigParam_IPv6StaticRouter1MAC struct {
MAC net.HardwareAddr
}
func (param *LanConfigParam_IPv6StaticRouter1MAC) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticRouter1MAC, 0, 0
}
func (param *LanConfigParam_IPv6StaticRouter1MAC) Pack() []byte {
out := make([]byte, 6)
copy(out, param.MAC)
return out
}
func (param *LanConfigParam_IPv6StaticRouter1MAC) Unpack(data []byte) error {
if len(data) < 6 {
return ErrUnpackedDataTooShortWith(len(data), 6)
}
param.MAC = data
return nil
}
func (param *LanConfigParam_IPv6StaticRouter1MAC) Format() string {
return param.MAC.String()
}
type LanConfigParam_IPv6StaticRouter1PrefixLength struct {
PrefixLength uint8
}
func (param *LanConfigParam_IPv6StaticRouter1PrefixLength) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticRouter1PrefixLength, 0, 0
}
func (param *LanConfigParam_IPv6StaticRouter1PrefixLength) Pack() []byte {
out := make([]byte, 1)
out[0] = param.PrefixLength
return out
}
func (param *LanConfigParam_IPv6StaticRouter1PrefixLength) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.PrefixLength = data[0]
return nil
}
func (param *LanConfigParam_IPv6StaticRouter1PrefixLength) Format() string {
return fmt.Sprintf("%d", param.PrefixLength)
}
type LanConfigParam_IPv6StaticRouter1PrefixValue struct {
PrefixValue [16]byte
}
func (param *LanConfigParam_IPv6StaticRouter1PrefixValue) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticRouter1PrefixValue, 0, 0
}
func (param *LanConfigParam_IPv6StaticRouter1PrefixValue) Pack() []byte {
out := make([]byte, 16)
copy(out[0:], param.PrefixValue[:])
return out
}
func (param *LanConfigParam_IPv6StaticRouter1PrefixValue) Unpack(data []byte) error {
if len(data) < 16 {
return ErrUnpackedDataTooShortWith(len(data), 16)
}
copy(param.PrefixValue[:], data[0:])
return nil
}
func (param *LanConfigParam_IPv6StaticRouter1PrefixValue) Format() string {
return fmt.Sprintf("%s", param.PrefixValue)
}
type LanConfigParam_IPv6StaticRouter2IP struct {
IPv6 net.IP
}
func (param *LanConfigParam_IPv6StaticRouter2IP) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticRouter2IP, 0, 0
}
func (param *LanConfigParam_IPv6StaticRouter2IP) Pack() []byte {
out := make([]byte, 16)
copy(out, param.IPv6)
return out
}
func (param *LanConfigParam_IPv6StaticRouter2IP) Unpack(data []byte) error {
if len(data) < 16 {
return ErrUnpackedDataTooShortWith(len(data), 16)
}
param.IPv6 = data
return nil
}
func (param *LanConfigParam_IPv6StaticRouter2IP) Format() string {
return param.IPv6.String()
}
type LanConfigParam_IPv6StaticRouter2MAC struct {
MAC net.HardwareAddr
}
func (param *LanConfigParam_IPv6StaticRouter2MAC) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticRouter2MAC, 0, 0
}
func (param *LanConfigParam_IPv6StaticRouter2MAC) Pack() []byte {
out := make([]byte, 6)
copy(out, param.MAC)
return out
}
func (param *LanConfigParam_IPv6StaticRouter2MAC) Unpack(data []byte) error {
if len(data) < 6 {
return ErrUnpackedDataTooShortWith(len(data), 6)
}
param.MAC = data
return nil
}
func (param *LanConfigParam_IPv6StaticRouter2MAC) Format() string {
return param.MAC.String()
}
type LanConfigParam_IPv6StaticRouter2PrefixLength struct {
PrefixLength uint8
}
func (param *LanConfigParam_IPv6StaticRouter2PrefixLength) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticRouter2PrefixLength, 0, 0
}
func (param *LanConfigParam_IPv6StaticRouter2PrefixLength) Pack() []byte {
out := make([]byte, 1)
out[0] = param.PrefixLength
return out
}
func (param *LanConfigParam_IPv6StaticRouter2PrefixLength) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.PrefixLength = data[0]
return nil
}
func (param *LanConfigParam_IPv6StaticRouter2PrefixLength) Format() string {
return fmt.Sprintf("%d", param.PrefixLength)
}
type LanConfigParam_IPv6StaticRouter2PrefixValue struct {
PrefixValue [16]byte
}
func (param *LanConfigParam_IPv6StaticRouter2PrefixValue) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6StaticRouter2PrefixValue, 0, 0
}
func (param *LanConfigParam_IPv6StaticRouter2PrefixValue) Pack() []byte {
out := make([]byte, 16)
copy(out[0:], param.PrefixValue[:])
return out
}
func (param *LanConfigParam_IPv6StaticRouter2PrefixValue) Unpack(data []byte) error {
if len(data) < 16 {
return ErrUnpackedDataTooShortWith(len(data), 16)
}
copy(param.PrefixValue[:], data[0:])
return nil
}
func (param *LanConfigParam_IPv6StaticRouter2PrefixValue) Format() string {
return fmt.Sprintf("%s", param.PrefixValue)
}
type LanConfigParam_IPv6DynamicRouterInfoSets struct {
// Number of dynamic Router Address information entries
Count uint8
}
func (param *LanConfigParam_IPv6DynamicRouterInfoSets) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DynamicRouterInfoCount, 0, 0
}
func (param *LanConfigParam_IPv6DynamicRouterInfoSets) Pack() []byte {
out := make([]byte, 1)
out[0] = param.Count
return out
}
func (param *LanConfigParam_IPv6DynamicRouterInfoSets) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Count = data[0]
return nil
}
func (param *LanConfigParam_IPv6DynamicRouterInfoSets) Format() string {
return fmt.Sprintf("%d", param.Count)
}
type LanConfigParam_IPv6DynamicRouterInfoIP struct {
SetSelector uint8
IPv6 net.IP
}
func (param *LanConfigParam_IPv6DynamicRouterInfoIP) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DynamicRouterInfoIP, param.SetSelector, 0
}
func (param *LanConfigParam_IPv6DynamicRouterInfoIP) Pack() []byte {
out := make([]byte, 17)
out[0] = param.SetSelector
copy(out[1:], param.IPv6)
return out
}
func (param *LanConfigParam_IPv6DynamicRouterInfoIP) Unpack(data []byte) error {
if len(data) < 17 {
return ErrUnpackedDataTooShortWith(len(data), 17)
}
param.SetSelector = data[0]
param.IPv6 = data[1:]
return nil
}
func (param *LanConfigParam_IPv6DynamicRouterInfoIP) Format() string {
return fmt.Sprintf("%d, %s", param.SetSelector, param.IPv6)
}
type LanConfigParam_IPv6DynamicRouterInfoMAC struct {
SetSelector uint8
MAC net.HardwareAddr
}
func (param *LanConfigParam_IPv6DynamicRouterInfoMAC) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DynamicRouterInfoMAC, param.SetSelector, 0
}
func (param *LanConfigParam_IPv6DynamicRouterInfoMAC) Pack() []byte {
out := make([]byte, 7)
out[0] = param.SetSelector
copy(out[1:], param.MAC)
return out
}
func (param *LanConfigParam_IPv6DynamicRouterInfoMAC) Unpack(data []byte) error {
if len(data) < 7 {
return ErrUnpackedDataTooShortWith(len(data), 7)
}
param.SetSelector = data[0]
param.MAC = data[1:]
return nil
}
func (param *LanConfigParam_IPv6DynamicRouterInfoMAC) Format() string {
return fmt.Sprintf("%d, %s", param.SetSelector, param.MAC)
}
type LanConfigParam_IPv6DynamicRouterInfoPrefixLength struct {
SetSelector uint8
PrefixLength uint8
}
func (param *LanConfigParam_IPv6DynamicRouterInfoPrefixLength) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DynamicRouterInfoPrefixLength, param.SetSelector, 0
}
func (param *LanConfigParam_IPv6DynamicRouterInfoPrefixLength) Pack() []byte {
out := make([]byte, 2)
out[0] = param.SetSelector
out[1] = param.PrefixLength
return out
}
func (param *LanConfigParam_IPv6DynamicRouterInfoPrefixLength) Unpack(data []byte) error {
if len(data) < 2 {
return ErrUnpackedDataTooShortWith(len(data), 2)
}
param.SetSelector = data[0]
param.PrefixLength = data[1]
return nil
}
func (param *LanConfigParam_IPv6DynamicRouterInfoPrefixLength) Format() string {
return fmt.Sprintf("%d, %d", param.SetSelector, param.PrefixLength)
}
type LanConfigParam_IPv6DynamicRouterInfoPrefixValue struct {
SetSelector uint8
PrefixValue [16]byte
}
func (param *LanConfigParam_IPv6DynamicRouterInfoPrefixValue) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DynamicRouterInfoPrefixValue, param.SetSelector, 0
}
func (param *LanConfigParam_IPv6DynamicRouterInfoPrefixValue) Pack() []byte {
out := make([]byte, 17)
out[0] = param.SetSelector
copy(out[1:], param.PrefixValue[:])
return out
}
func (param *LanConfigParam_IPv6DynamicRouterInfoPrefixValue) Unpack(data []byte) error {
if len(data) < 17 {
return ErrUnpackedDataTooShortWith(len(data), 17)
}
param.SetSelector = data[0]
copy(param.PrefixValue[:], data[1:])
return nil
}
func (param *LanConfigParam_IPv6DynamicRouterInfoPrefixValue) Format() string {
return fmt.Sprintf("%d, %s", param.SetSelector, param.PrefixValue)
}
type LanConfigParam_IPv6DynamicRouterReceivedHopLimit struct {
HopLimit uint8
}
func (param *LanConfigParam_IPv6DynamicRouterReceivedHopLimit) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6DynamicRouterReceivedHopLimit, 0, 0
}
func (param *LanConfigParam_IPv6DynamicRouterReceivedHopLimit) Pack() []byte {
out := make([]byte, 1)
out[0] = param.HopLimit
return out
}
func (param *LanConfigParam_IPv6DynamicRouterReceivedHopLimit) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.HopLimit = data[0]
return nil
}
func (param *LanConfigParam_IPv6DynamicRouterReceivedHopLimit) Format() string {
return fmt.Sprintf("%d", param.HopLimit)
}
type LanConfigParam_IPv6NDSLAACTimingConfigSupport struct {
Mode LanIPv6NDSLAACTimingConfigMode
}
func (param *LanConfigParam_IPv6NDSLAACTimingConfigSupport) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6NDSLAACTimingConfigSupport, 0, 0
}
func (param *LanConfigParam_IPv6NDSLAACTimingConfigSupport) Pack() []byte {
out := make([]byte, 1)
out[0] = byte(param.Mode)
return out
}
func (param *LanConfigParam_IPv6NDSLAACTimingConfigSupport) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Mode = LanIPv6NDSLAACTimingConfigMode(data[0])
return nil
}
func (param *LanConfigParam_IPv6NDSLAACTimingConfigSupport) Format() string {
return fmt.Sprintf("%s (%d)", param.Mode.String(), param.Mode)
}
type LanConfigParam_IPv6NDSLAACTimingConfig struct {
SetSelector uint8
BlockSelector uint8
}
func (param *LanConfigParam_IPv6NDSLAACTimingConfig) LanConfigParameter() (paramSelector LanConfigParamSelector, setSelector uint8, blockSelector uint8) {
return LanConfigParamSelector_IPv6NDSLAACTimingConfig, param.SetSelector, param.BlockSelector
}
func (param *LanConfigParam_IPv6NDSLAACTimingConfig) Pack() []byte {
out := make([]byte, 2)
out[0] = param.SetSelector
out[1] = param.BlockSelector
return out
}
func (param *LanConfigParam_IPv6NDSLAACTimingConfig) Unpack(data []byte) error {
if len(data) < 2 {
return ErrUnpackedDataTooShortWith(len(data), 2)
}
param.SetSelector = data[0]
param.BlockSelector = data[1]
return nil
}
func (param *LanConfigParam_IPv6NDSLAACTimingConfig) Format() string {
return fmt.Sprintf("%d, %d", param.SetSelector, param.BlockSelector)
}
golang-github-bougou-go-ipmi-0.7.2/types_netfn.go 0000664 0000000 0000000 00000002551 14741105271 0021776 0 ustar 00root root 0000000 0000000 package ipmi
// NetFn is Network Function
type NetFn uint8
// Network Function Codes, section 5.1 Table 5
// Even NetFn values are used for requests to the BMC,
// and odd NetFn values are returned in responses from the BMC.
//
// six-bit field identifying the function, so total 64 NetFn (32 NetFn pairs)
const (
NetFnChassisRequest NetFn = 0x00
NetFnChassisResponse NetFn = 0x01
NetFnBridgeRequest NetFn = 0x02
NetFnBridgeResponse NetFn = 0x03
NetFnSensorEventRequest NetFn = 0x04
NetFnSensorEventResponse NetFn = 0x05
NetFnAppRequest NetFn = 0x06
NetFnAppResponse NetFn = 0x07
NetFnFirmwareRequest NetFn = 0x08
NetFnFirmwareResponse NetFn = 0x09
NetFnStorageRequest NetFn = 0x0a
NetFnStorageResponse NetFn = 0x0b
NetFnTransportRequest NetFn = 0x0c
NetFnTransportResponse NetFn = 0x0d
// Reserved 0E - 2B
NetFnGroupExtensionRequest NetFn = 0x2c
NetFnGroupExtensionResponse NetFn = 0x2d
NetFnOEMGroupRequest NetFn = 0x2e
NetFnOEMGroupResponse NetFn = 0x2f
// 30h-3Fh controller specific
// Vendor specific (16 Network Functions [8 pairs]).
NetFnOEMSupermicroRequest NetFn = 0x30
)
// Group Extensions
const (
// Intel DCMI extensions (https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/dcmi-v1-5-rev-spec.pdf)
GroupExtensionDCMI uint8 = 0xDC
)
golang-github-bougou-go-ipmi-0.7.2/types_oem.go 0000664 0000000 0000000 00000006546 14741105271 0021454 0 ustar 00root root 0000000 0000000 package ipmi
// OEM represents Manufacturer ID, that is IANA Private Enterprise Number
type OEM uint32
// cSpell: disable
const (
OEM_UNKNOWN = 0
OEM_DEBUG = 0xFFFFFE /* Hoping IANA won't hit this soon */
OEM_RESERVED = 0x0FFFFF /* As per IPMI 2.0 specification */
OEM_IBM_2 = 2 /* 2 for [IBM] */
OEM_HP = 11
OEM_SUN = 42
OEM_NOKIA = 94
OEM_BULL = 107
OEM_HITACHI_116 = 116
OEM_NEC = 119
OEM_TOSHIBA = 186
OEM_ERICSSON = 193
OEM_INTEL = 343
OEM_TATUNG = 373
OEM_HITACHI_399 = 399
OEM_DELL = 674
OEM_HUAWEI = 2011
OEM_LMC = 2168
OEM_RADISYS = 4337
OEM_BROADCOM = 4413
OEM_IBM_4769 = 4769 /* 4769 for [IBM Corporation] */
OEM_MAGNUM = 5593
OEM_TYAN = 6653
OEM_QUANTA = 7244
OEM_VIKING = 9237
OEM_ADVANTECH = 10297
OEM_FUJITSU_SIEMENS = 10368
OEM_AVOCENT = 10418
OEM_PEPPERCON = 10437
OEM_SUPERMICRO = 10876
OEM_OSA = 11102
OEM_GOOGLE = 11129
OEM_PICMG = 12634
OEM_RARITAN = 13742
OEM_KONTRON = 15000
OEM_PPS = 16394
OEM_IBM_20301 = 20301 /* 20301 for [IBM eServer X] */
OEM_AMI = 20974
OEM_FOXCONN = 22238
OEM_ADLINK_24339 = 24339 /* 24339 for [ADLINK TECHNOLOGY INC.] */
OEM_H3C = 25506
OEM_NOKIA_SOLUTIONS_AND_NETWORKS = 28458
OEM_VITA = 33196
OEM_INSPUR = 37945
OEM_TENCENT = 41475
OEM_BYTEDANCE = 46045
OEM_SUPERMICRO_47488 = 47488
OEM_YADRO = 49769
)
func (oem OEM) String() string {
m := map[OEM]string{
2: "IBM",
11: "HP",
42: "Sun",
94: "Nokia",
107: "Bull",
116: "Hitachi",
119: "NEC",
186: "Toshiba",
193: "Ericsson",
343: "Intel",
373: "Tatung", // 大同
399: "Hitachi",
674: "Dell",
2011: "Huawei",
2168: "LMC",
4337: "Radisys",
4413: "Broadcom",
4769: "IBM",
5593: "Magnum", // 迈格纳技术集成公司
6653: "Tyan", // 泰安
7244: "Quanta",
9237: "Viking",
10297: "Advantech", // 研华科技
10368: "Fujitsu",
10418: "Avocent",
10437: "Peppercon",
10876: "Supermicro",
11102: "OSA",
11129: "Google",
12634: "PICMG",
13742: "Raritan", // 力登
15000: "Kontron", // 控创
16394: "PPS",
20301: "IBM",
20974: "AMI",
22238: "Foxconn",
24339: "ADLINK", // 凌华
25506: "H3C",
28458: "Nokia",
33196: "Vita", // 维塔
37945: "Inspur", // 浪潮
41475: "Tencent", // 腾讯
46045: "ByteDance", // 字节跳动
47488: "Supermicro",
49769: "Yadro",
}
if s, ok := m[oem]; ok {
return s
}
return "Unknown"
}
golang-github-bougou-go-ipmi-0.7.2/types_payload.go 0000664 0000000 0000000 00000006665 14741105271 0022327 0 ustar 00root root 0000000 0000000 package ipmi
// 13.27.3
// The Get Channel Payload Support command returns which standard payload type numbers and OEM payload
// type handles are available on a given channel of a BMC.
type PayloadType uint8
const (
// Standard Payload Types
// used to identify payloads that are specified by the IPMI specifications
PayloadTypeIPMI PayloadType = 0x00
PayloadTypeSOL PayloadType = 0x01
PayloadTypeOEM PayloadType = 0x02
// Session Setup Payload Types
// used to identify payloads that are for session setup messages specified by the IPMI specifications
PayloadTypeRmcpOpenSessionRequest PayloadType = 0x10
PayloadTypeRmcpOpenSessionResponse PayloadType = 0x11
PayloadTypeRAKPMessage1 PayloadType = 0x12
PayloadTypeRAKPMessage2 PayloadType = 0x13
PayloadTypeRAKPMessage3 PayloadType = 0x14
PayloadTypeRAKPMessage4 PayloadType = 0x15
// OEM Payload Type Handles
// used to identify payloads that are specified by a given OEM
PayloadTypeOEM0 PayloadType = 0x20
PayloadTypeOEM1 PayloadType = 0x21
PayloadTypeOEM2 PayloadType = 0x22
PayloadTypeOEM3 PayloadType = 0x23
PayloadTypeOEM4 PayloadType = 0x24
PayloadTypeOEM5 PayloadType = 0x25
PayloadTypeOEM6 PayloadType = 0x26
PayloadTypeOEM7 PayloadType = 0x27
)
func (pt PayloadType) String() string {
m := map[PayloadType]string{
0x00: "ipmi",
0x01: "sol",
0x02: "oem",
0x10: "rmcp-open-session-request",
0x11: "rmcp-open-session-response",
0x12: "rakp-message-1",
0x13: "rakp-message-2",
0x14: "rakp-message-3",
0x15: "rakp-message-4",
0x20: "oem0",
0x21: "oem1",
0x22: "oem2",
0x23: "oem3",
0x24: "oem4",
0x25: "oem5",
0x26: "oem6",
0x27: "oem7",
}
s, ok := m[pt]
if ok {
return s
}
return "reserved"
}
// 13.28
type AuthAlg uint8
const (
AuthAlgRAKP_None AuthAlg = 0x00 // Mandatory
AuthAlgRAKP_HMAC_SHA1 AuthAlg = 0x01 // Mandatory
AuthAlgRAKP_HMAC_MD5 AuthAlg = 0x02 // Optional
AuthAlgRAKP_HMAC_SHA256 AuthAlg = 0x03 // Optional
)
func (authAlg AuthAlg) String() string {
m := map[AuthAlg]string{
0x00: "none",
0x01: "hmac_sha1",
0x02: "hmac_md5",
0x03: "hmac_sha256",
}
s, ok := m[authAlg]
if ok {
return s
}
return ""
}
// 13.28.4
type IntegrityAlg uint8
const (
IntegrityAlg_None IntegrityAlg = 0x00 // Mandatory
IntegrityAlg_HMAC_SHA1_96 IntegrityAlg = 0x01 // Mandatory
IntegrityAlg_HMAC_MD5_128 IntegrityAlg = 0x02 // Optional
IntegrityAlg_MD5_128 IntegrityAlg = 0x03 // Optional
IntegrityAlg_HMAC_SHA256_128 IntegrityAlg = 0x04 // Optional
)
func (integrityAlg IntegrityAlg) String() string {
m := map[IntegrityAlg]string{
0x00: "none",
0x01: "hmac_sha1_96",
0x02: "hmac_md5_128",
0x03: "md5_128",
0x04: "hmac_sha256_128",
}
s, ok := m[integrityAlg]
if ok {
return s
}
return ""
}
// 13.28.5
// Confidentiality (Encryption) Algorithms
// AES is more secure than RC4
// RC4 is cryptographically broken and should not be used for secure applications.
type CryptAlg uint8
const (
CryptAlg_None CryptAlg = 0x00 // Mandatory
CryptAlg_AES_CBC_128 CryptAlg = 0x01 // Mandatory
CryptAlg_xRC4_128 CryptAlg = 0x02 // Optional
CryptAlg_xRC4_40 CryptAlg = 0x03 // Optional
Encryption_AES_CBS_128_BlockSize uint8 = 0x10
)
func (cryptAlg CryptAlg) String() string {
m := map[CryptAlg]string{
0x00: "none",
0x01: "aes_cbc_128",
0x02: "xrc4_128",
0x03: "xrc4_40",
}
s, ok := m[cryptAlg]
if ok {
return s
}
return ""
}
golang-github-bougou-go-ipmi-0.7.2/types_pef.go 0000664 0000000 0000000 00000040606 14741105271 0021441 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"fmt"
"strconv"
"strings"
"github.com/olekukonko/tablewriter"
)
// 17.7 Event Filter Table
type PEFEventFilter struct {
// Filter Configuration
//
// FilterState (enabled or disabled)
// [4:0] - reserved
//
// [7] - 1b = enable filter
// 0b = disable filter
FilterState bool
// [6:5] - 11b = reserved
// 10b = manufacturer pre-configured filter. The filter entry has been
// configured by the system integrator and should not be altered by software.
// Software is allowed to enable or disable the filter, however.
// 01b = reserved
// 00b = software configurable filter. The filter entry is available for
// configuration by system management software.
FilterType PEFEventFilterType
// 17.6 PEF Actions
// All actions are optional for an implementation, with the exception of Alert
// which is mandatory if alerting is supported for one or more channels.
// The BMC will return 0b for unsupported actions.
// Software can test for which actions are supported by writing 1's to the
// specified fields and reading back the result.
// (Note that reserved bits must be written with 0's)
ActionGroupControlOperation bool
ActionDiagnosticInterrupt bool
ActionOEM bool
ActionPowerCycle bool
ActionReset bool
ActionPowerOff bool
// Either Event filter Action should be enabled or Power action should be present as channel alert is enabled.
ActionAlert bool // Relates with AlertPolicyNumber
// Used to select an alerting policy set from the Alert Policy Table.
// The Alert Policy Table holds different policies that configure the order in which different alert destinations and alerting media are tried.
// [6:4] - group control selector (1-based). Selects entry from group control table. (see [ICMB)
GroupControlSelector uint8
// [3:0] - policy number. Value is "don't care" if (ActionAlert=false) Alert is not selected in the Event Filter Action.
AlertPolicyNumber uint8
EventSeverity PEFEventSeverity
GeneratorID GeneratorID
SensorType SensorType
SensorNumber SensorNumber
EventReadingType EventReadingType
EventData1EventOffsetMask uint16
EventData1ANDMask uint8
// Used to indicate whether each bit position's comparison is an exact comparison or not.
EventData1Compare1 uint8
EventData1Compare2 uint8
EventData2ANDMask uint8
EventData2Compare1 uint8
EventData2Compare2 uint8
EventData3ANDMask uint8
EventData3Compare1 uint8
EventData3Compare2 uint8
}
func (entry *PEFEventFilter) enabledActions() []string {
out := make([]string, 0)
if entry.ActionGroupControlOperation {
out = append(out, "Group Control Operation")
}
if entry.ActionDiagnosticInterrupt {
out = append(out, "DiagnosticInterrupt")
}
if entry.ActionOEM {
out = append(out, "OEM-defined")
}
if entry.ActionPowerCycle {
out = append(out, "PowerCycle")
}
if entry.ActionReset {
out = append(out, "Reset")
}
if entry.ActionPowerOff {
out = append(out, "PowerOff")
}
if entry.ActionAlert {
out = append(out, "Alert")
}
return out
}
func (entry *PEFEventFilter) Unpack(data []byte) error {
if len(data) < 20 {
return ErrUnpackedDataTooShortWith(len(data), 20)
}
var b byte
b = data[0]
entry.FilterState = isBit7Set(b)
entry.FilterType = PEFEventFilterType((b >> 5) & 0x03)
b = data[1]
entry.ActionGroupControlOperation = isBit6Set(b)
entry.ActionDiagnosticInterrupt = isBit5Set(b)
entry.ActionOEM = isBit4Set(b)
entry.ActionPowerCycle = isBit3Set(b)
entry.ActionReset = isBit2Set(b)
entry.ActionPowerOff = isBit1Set(b)
entry.ActionAlert = isBit0Set(b)
b = data[2]
entry.GroupControlSelector = (b >> 4) & 0x07
entry.AlertPolicyNumber = b & 0x0f
entry.EventSeverity = PEFEventSeverity(data[3])
generatorID, _, _ := unpackUint16L(data, 4)
entry.GeneratorID = GeneratorID(generatorID)
entry.SensorType = SensorType(data[6])
entry.SensorNumber = SensorNumber(data[7])
entry.EventReadingType = EventReadingType(data[8])
eventData1, _, _ := unpackUint16L(data, 9)
entry.EventData1EventOffsetMask = eventData1
entry.EventData1ANDMask = data[11]
entry.EventData1Compare1 = data[12]
entry.EventData1Compare2 = data[13]
entry.EventData2ANDMask = data[14]
entry.EventData2Compare1 = data[15]
entry.EventData2Compare2 = data[16]
entry.EventData3ANDMask = data[17]
entry.EventData3Compare1 = data[18]
entry.EventData3Compare2 = data[19]
return nil
}
func (entry *PEFEventFilter) Pack() []byte {
out := make([]byte, 20)
var b byte
b = uint8(entry.FilterType) << 5
b = setOrClearBit7(b, entry.FilterState)
out[0] = b
b = 0
b = setOrClearBit6(b, entry.ActionGroupControlOperation)
b = setOrClearBit5(b, entry.ActionDiagnosticInterrupt)
b = setOrClearBit4(b, entry.ActionOEM)
b = setOrClearBit3(b, entry.ActionPowerCycle)
b = setOrClearBit2(b, entry.ActionReset)
b = setOrClearBit1(b, entry.ActionPowerOff)
b = setOrClearBit0(b, entry.ActionAlert)
out[1] = b
b = uint8(entry.GroupControlSelector) << 4
b |= entry.AlertPolicyNumber & 0x0f
out[2] = b
out[3] = byte(entry.EventSeverity)
packUint16L(uint16(entry.GeneratorID), out, 4)
out[6] = byte(entry.SensorType)
out[7] = byte(entry.SensorNumber)
out[8] = byte(entry.EventReadingType)
packUint16L(entry.EventData1EventOffsetMask, out, 9)
out[11] = entry.EventData1ANDMask
out[12] = entry.EventData1Compare1
out[13] = entry.EventData1Compare2
out[14] = entry.EventData2ANDMask
out[15] = entry.EventData2Compare1
out[16] = entry.EventData2Compare2
out[17] = entry.EventData3ANDMask
out[18] = entry.EventData3Compare1
out[19] = entry.EventData3Compare2
return out
}
func (entry *PEFEventFilter) Format() string {
return fmt.Sprintf(`
FilterType: %v
FilterState: %v
ActionGroupControlOperation: %v
ActionDiagnosticInterrupt: %v
ActionOEM: %v
ActionPowerCycle: %v
ActionReset: %v
ActionPowerOff: %v
ActionAlert: %v
GroupControlSelector: %v
AlertPolicyNumber: %v
EventSeverity: %v
GeneratorID: %v
SensorType: %v
SensorNumber: %v
EventReadingType: %v
EventData1EventOffsetMask: %v
EventData1ANDMask: %v
EventData1Compare1: %v
EventData1Compare2: %v
EventData2ANDMask: %v
EventData2Compare1: %v
EventData2Compare2: %v
EventData3ANDMask: %v
EventData3Compare1: %v
EventData3Compare2: %v
`,
PEFEventFilterType(entry.FilterType),
entry.FilterState,
entry.ActionGroupControlOperation,
entry.ActionDiagnosticInterrupt,
entry.ActionOEM,
entry.ActionPowerCycle,
entry.ActionReset,
entry.ActionPowerOff,
entry.ActionAlert,
entry.GroupControlSelector,
entry.AlertPolicyNumber,
PEFEventSeverity(entry.EventSeverity),
GeneratorID(entry.GeneratorID),
SensorType(entry.SensorType),
SensorNumber(entry.SensorNumber),
EventReadingType(entry.EventReadingType),
entry.EventData1EventOffsetMask,
entry.EventData1ANDMask,
entry.EventData1Compare1,
entry.EventData1Compare2,
entry.EventData2ANDMask,
entry.EventData2Compare1,
entry.EventData2Compare2,
entry.EventData3ANDMask,
entry.EventData3Compare1,
entry.EventData3Compare2)
}
func FormatEventFilters(eventFilters []*PEFEventFilter) string {
var buf = new(bytes.Buffer)
table := tablewriter.NewWriter(buf)
var headers []string
// the first faked item was used to make sure headers are always generated
for i, f := range append([]*PEFEventFilter{{}}, eventFilters...) {
content := [][2]string{
{"Filter State", formatBool(f.FilterState, "enabled", "disabled")},
{"Filter Type", f.FilterType.String()},
{"Actions", strings.Join(f.enabledActions(), ",")},
{"Group Control Selector", fmt.Sprintf("%v", f.GroupControlSelector)},
{"Alert Policy Number", fmt.Sprintf("%v", f.AlertPolicyNumber)},
{"Event Severity", fmt.Sprintf("%v", f.EventSeverity)},
{"Generator ID", fmt.Sprintf("%v", f.GeneratorID)},
{"Sensor Type", fmt.Sprintf("%v", f.SensorType)},
{"Sensor Number", fmt.Sprintf("%#02x", f.SensorNumber)},
{"Event Reading Type", fmt.Sprintf("%v", f.EventReadingType)},
{"ED1 Event Offset Mask", fmt.Sprintf("%v", f.EventData1EventOffsetMask)},
// {"ED1 AND Mask", fmt.Sprintf("%v", f.EventData1ANDMask)},
// {"ED1 Compare 1", fmt.Sprintf("%v", f.EventData1Compare1)},
// {"ED1 Compare 2", fmt.Sprintf("%v", f.EventData1Compare2)},
// {"ED2 AND Mask", fmt.Sprintf("%v", f.EventData2ANDMask)},
// {"ED2 Compare 1", fmt.Sprintf("%v", f.EventData2Compare1)},
// {"ED2 Compare 2", fmt.Sprintf("%v", f.EventData2Compare2)},
// {"ED3 AND Mask", fmt.Sprintf("%v", f.EventData3ANDMask)},
// {"ED3 Compare 1", fmt.Sprintf("%v", f.EventData3Compare1)},
// {"ED3 Compare 2", fmt.Sprintf("%v", f.EventData3Compare2)},
}
if i == 0 {
headers = make([]string, len(content))
for j, c := range content {
headers[j] = c[0]
}
} else {
row := make([]string, len(content))
for j, c := range content {
row[j] = c[1]
}
table.Append(row)
}
}
table.SetHeader(headers)
table.SetFooter(headers)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_RIGHT)
table.Render()
return buf.String()
}
// PEFEventFilterType:
// - manufacturer pre-configured filter.
// The filter entry has been configured by the system integrator and
// should not be altered by software. Software is allowed to enable or
// disable the filter, however.
// - software configurable filter.
// The filter entry is available for configuration by system management software.
type PEFEventFilterType uint8
const (
PEFEventFilterType_Configurable PEFEventFilterType = 0x00
PEFEventFilterType_PreConfigured PEFEventFilterType = 0x10
)
func (filterType PEFEventFilterType) String() string {
m := map[PEFEventFilterType]string{
PEFEventFilterType_Configurable: "Configurable",
PEFEventFilterType_PreConfigured: "Pre-Configured",
}
s, ok := m[filterType]
if ok {
return s
}
return fmt.Sprintf("%#02x", filterType)
}
type PEFEventSeverity uint8
const (
PEFEventSeverityUnspecified PEFEventSeverity = 0x00
PEFEventSeverityMonitor PEFEventSeverity = 0x01
PEFEventSeverityInformation PEFEventSeverity = 0x02
PEFEventSeverityOK PEFEventSeverity = 0x04
PEFEventSeverityNonCritical PEFEventSeverity = 0x08 // aka Warning
PEFEventSeverityCritical PEFEventSeverity = 0x10
PEFEventSeverityNonRecoverable PEFEventSeverity = 0x20
)
func (severity PEFEventSeverity) String() string {
m := map[PEFEventSeverity]string{
PEFEventSeverityUnspecified: "Unspecified",
PEFEventSeverityMonitor: "Monitor",
PEFEventSeverityInformation: "Information",
PEFEventSeverityOK: "OK",
PEFEventSeverityNonCritical: "Non-Critical",
PEFEventSeverityCritical: "Critical",
PEFEventSeverityNonRecoverable: "Non-Recoverable",
}
if s, ok := m[severity]; ok {
return s
}
return ""
}
// 17.11 Alert Policy Table
type PEFAlertPolicy struct {
// [7:4] - policy number. 1 based. 0000b = reserved.
PolicyNumber uint8
// PolicyState (enabled or disabled)
//
// [3] - 0b = this entry is disabled. Skip to next entry in policy, if any.
// 1b = this entry is enabled.
PolicyState bool
// [2:0] - policy
PolicyAction PEFAlertPolicyAction
// [7:4] = ChannelNumber Number.
ChannelNumber uint8
// [3:0] = Destination selector.
Destination uint8
// [7] - Event-specific Alert String
// 1b = Alert String look-up is event specific. The following Alert String Set / Selector sub-
// field is interpreted as an Alert String Set Number that is used in conjunction with
// the Event Filter Number to lookup the Alert String from the PEF Configuration Parameters.
// 0b = Alert String is not event specific. The following Alert String Set / Selector sub-field
// is interpreted as an Alert String Selector that provides a direct pointer to the
// desired Alert String from the PEF Configuration Parameters.
IsEventSpecific bool
// [6:0] - Alert String Set / Selector.
// This value identifies one or more Alert Strings in the Alert String table.
// - When used as an Alert String Set Number (IsEventSpecific = true), it is used in conjunction with the Event Filter Number to uniquely identify an Alert String.
// - When used as an Alert String Selector (IsEventSpecific = false), it directly selects an Alert String from the PEF Configuration Parameters.
AlertStringKey uint8
}
func (entry *PEFAlertPolicy) Pack() []byte {
out := make([]byte, 3)
var b uint8
b = uint8(entry.PolicyAction) & 0x07
b = setOrClearBit3(b, entry.PolicyState)
b |= entry.PolicyNumber << 4
out[0] = b
b = entry.Destination & 0x0F
b |= entry.ChannelNumber << 4
out[1] = b
b = entry.AlertStringKey & 0x7F
b = setOrClearBit7(b, entry.IsEventSpecific)
out[2] = b
return out
}
func (entry *PEFAlertPolicy) Unpack(data []byte) error {
if len(data) < 3 {
return ErrUnpackedDataTooShortWith(len(data), 3)
}
entry.PolicyNumber = data[0] >> 4
entry.PolicyState = isBit3Set(data[0])
entry.PolicyAction = PEFAlertPolicyAction(data[0] & 0x07)
entry.ChannelNumber = data[1] >> 4
entry.Destination = data[1] & 0x0F
entry.IsEventSpecific = isBit7Set(data[2])
entry.AlertStringKey = data[2] & 0x7F
return nil
}
func (entry *PEFAlertPolicy) Format() string {
return fmt.Sprintf(`
PolicyNumber : %d
PolicyState : %v
PolicyAction : %v
Channel : %d
Destination : %d
IsEventSpecific : %v
AlertStringKey : %d`,
entry.PolicyNumber,
entry.PolicyState,
entry.PolicyAction,
entry.ChannelNumber,
entry.Destination,
entry.IsEventSpecific,
entry.AlertStringKey)
}
func FormatPEFAlertPolicyTable(alertPolicies []*PEFAlertPolicy) string {
headers := []string{
"Entry",
"PolicyNumber",
"PolicyState",
"PolicyAction",
"Channel",
"Destination",
"IsEventSpecific",
"AlertStringKey",
}
rows := make([][]string, len(alertPolicies))
for i, alertPolicy := range alertPolicies {
rows[i] = []string{
strconv.Itoa(i + 1),
fmt.Sprintf("%d", alertPolicy.PolicyNumber),
fmt.Sprintf("%v", alertPolicy.PolicyState),
alertPolicy.PolicyAction.ShortString(),
fmt.Sprintf("%d", alertPolicy.ChannelNumber),
fmt.Sprintf("%d", alertPolicy.Destination),
fmt.Sprintf("%v", alertPolicy.IsEventSpecific),
fmt.Sprintf("%d", alertPolicy.AlertStringKey),
}
}
return formatTable(headers, rows)
}
type PEFAlertPolicyAction uint8
const (
// always send alert to this destination.
PEFAlertPolicyAction_Always PEFAlertPolicyAction = 0
// if alert to previous destination was successful, do not send alert to this destination.
// Proceed to next entry in this policy set.
PEFAlertPolicyAction_ProceedNext PEFAlertPolicyAction = 1
// if alert to previous destination was successful, do not send alert to this destination.
// Do not process any more entries in this policy set.
PEFAlertPolicyAction_NoProceed PEFAlertPolicyAction = 2
// if alert to previous destination was successful, do not send alert to this destination.
// Proceed to next entry in this policy set that is to a different channel.
PEFAlertPolicyAction_ProceedNextDifferentChannel PEFAlertPolicyAction = 3
// if alert to previous destination was successful, do not send alert to this destination.
// Proceed to next entry in this policy set that is to a different destination type.
PEFAlertPolicyAction_ProceedNextDifferentDestination PEFAlertPolicyAction = 4
)
func (action PEFAlertPolicyAction) String() string {
m := map[PEFAlertPolicyAction]string{
PEFAlertPolicyAction_Always: "Always send alert to this destination",
PEFAlertPolicyAction_ProceedNext: "If previous successful, skip this and continue (if configured)",
PEFAlertPolicyAction_NoProceed: "If previous successful, stop alerting further",
PEFAlertPolicyAction_ProceedNextDifferentChannel: "If previous successful, switch to another channel (if configured)",
PEFAlertPolicyAction_ProceedNextDifferentDestination: "If previous successful, switch to another destination (if configured)",
}
if s, ok := m[action]; ok {
return s
}
return "Unknown"
}
func (action PEFAlertPolicyAction) ShortString() string {
m := map[PEFAlertPolicyAction]string{
PEFAlertPolicyAction_Always: "Match-always",
PEFAlertPolicyAction_ProceedNext: "Proceed-next",
PEFAlertPolicyAction_NoProceed: "No-proceed",
PEFAlertPolicyAction_ProceedNextDifferentChannel: "Different-channel",
PEFAlertPolicyAction_ProceedNextDifferentDestination: "Different-destination",
}
if s, ok := m[action]; ok {
return s
}
return "Unknown"
}
golang-github-bougou-go-ipmi-0.7.2/types_pef_params.go 0000664 0000000 0000000 00000067367 14741105271 0023021 0 ustar 00root root 0000000 0000000 package ipmi
import "fmt"
type PEFConfigParamSelector uint8
const (
PEFConfigParamSelector_SetInProgress PEFConfigParamSelector = 0x00
PEFConfigParamSelector_Control PEFConfigParamSelector = 0x01
PEFConfigParamSelector_ActionGlobalControl PEFConfigParamSelector = 0x02
PEFConfigParamSelector_StartupDelay PEFConfigParamSelector = 0x03
PEFConfigParamSelector_AlertStartDelay PEFConfigParamSelector = 0x04
PEFConfigParamSelector_EventFiltersCount PEFConfigParamSelector = 0x05
PEFConfigParamSelector_EventFilter PEFConfigParamSelector = 0x06
PEFConfigParamSelector_EventFilterData1 PEFConfigParamSelector = 0x07
PEFConfigParamSelector_AlertPoliciesCount PEFConfigParamSelector = 0x08
PEFConfigParamSelector_AlertPolicy PEFConfigParamSelector = 0x09
PEFConfigParamSelector_SystemGUID PEFConfigParamSelector = 0x0a
PEFConfigParamSelector_AlertStringsCount PEFConfigParamSelector = 0x0b
PEFConfigParamSelector_AlertStringKey PEFConfigParamSelector = 0x0c
PEFConfigParamSelector_AlertString PEFConfigParamSelector = 0x0d
PEFConfigParamSelector_GroupControlsCount PEFConfigParamSelector = 0x0e
PEFConfigParamSelector_GroupControl PEFConfigParamSelector = 0x0f
// 96:127
// OEM Parameters (optional. Non-volatile or volatile as specified by OEM)
// This range is available for special OEM configuration parameters.
// The OEM is identified according to the Manufacturer ID field returned by the Get Device ID command.
)
func (p PEFConfigParamSelector) String() string {
m := map[PEFConfigParamSelector]string{
PEFConfigParamSelector_SetInProgress: "Set In Progress",
PEFConfigParamSelector_Control: "Control",
PEFConfigParamSelector_ActionGlobalControl: "Action Global Control",
PEFConfigParamSelector_StartupDelay: "Startup Delay",
PEFConfigParamSelector_AlertStartDelay: "Alert Start Delay",
PEFConfigParamSelector_EventFiltersCount: "Event Filters Count",
PEFConfigParamSelector_EventFilter: "Event Filter",
PEFConfigParamSelector_EventFilterData1: "Event Filter Data1",
PEFConfigParamSelector_AlertPoliciesCount: "Alert Policies Count",
PEFConfigParamSelector_AlertPolicy: "Alert Policy",
PEFConfigParamSelector_SystemGUID: "System GUID",
PEFConfigParamSelector_AlertStringsCount: "Alert Strings Count",
PEFConfigParamSelector_AlertStringKey: "Alert String Key",
PEFConfigParamSelector_AlertString: "Alert String",
PEFConfigParamSelector_GroupControlsCount: "Group Controls Count",
PEFConfigParamSelector_GroupControl: "Group Control",
}
if s, ok := m[p]; ok {
return s
}
return fmt.Sprintf("Unknown (%#02x)", p)
}
type PEFConfigParameter interface {
PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8)
Parameter
}
var (
_ PEFConfigParameter = (*PEFConfigParam_SetInProgress)(nil)
_ PEFConfigParameter = (*PEFConfigParam_Control)(nil)
_ PEFConfigParameter = (*PEFConfigParam_ActionGlobalControl)(nil)
_ PEFConfigParameter = (*PEFConfigParam_StartupDelay)(nil)
_ PEFConfigParameter = (*PEFConfigParam_AlertStartupDelay)(nil)
_ PEFConfigParameter = (*PEFConfigParam_EventFiltersCount)(nil)
_ PEFConfigParameter = (*PEFConfigParam_EventFilter)(nil)
_ PEFConfigParameter = (*PEFConfigParam_AlertPoliciesCount)(nil)
_ PEFConfigParameter = (*PEFConfigParam_AlertPolicy)(nil)
_ PEFConfigParameter = (*PEFConfigParam_SystemGUID)(nil)
_ PEFConfigParameter = (*PEFConfigParam_AlertStringsCount)(nil)
_ PEFConfigParameter = (*PEFConfigParam_AlertStringKey)(nil)
_ PEFConfigParameter = (*PEFConfigParam_AlertString)(nil)
_ PEFConfigParameter = (*PEFConfigParam_GroupControlsCount)(nil)
_ PEFConfigParameter = (*PEFConfigParam_GroupControl)(nil)
)
func isNilPEFConfigParameter(param PEFConfigParameter) bool {
switch v := param.(type) {
case *PEFConfigParam_SetInProgress:
return v == nil
case *PEFConfigParam_Control:
return v == nil
case *PEFConfigParam_ActionGlobalControl:
return v == nil
case *PEFConfigParam_StartupDelay:
return v == nil
case *PEFConfigParam_AlertStartupDelay:
return v == nil
case *PEFConfigParam_EventFiltersCount:
return v == nil
case *PEFConfigParam_EventFilter:
return v == nil
case *PEFConfigParam_AlertPoliciesCount:
return v == nil
case *PEFConfigParam_AlertPolicy:
return v == nil
case *PEFConfigParam_SystemGUID:
return v == nil
case *PEFConfigParam_AlertStringsCount:
return v == nil
case *PEFConfigParam_AlertStringKey:
return v == nil
case *PEFConfigParam_AlertString:
return v == nil
case *PEFConfigParam_GroupControlsCount:
return v == nil
case *PEFConfigParam_GroupControl:
return v == nil
default:
return false
}
}
type PEFConfigParams struct {
SetInProgress *PEFConfigParam_SetInProgress
Control *PEFConfigParam_Control
ActionGlobalControl *PEFConfigParam_ActionGlobalControl
StartupDelay *PEFConfigParam_StartupDelay
AlertStartupDelay *PEFConfigParam_AlertStartupDelay
EventFiltersCount *PEFConfigParam_EventFiltersCount
EventFilters []*PEFConfigParam_EventFilter
EventFiltersData1 []*PEFConfigParam_EventFilterData1
AlertPoliciesCount *PEFConfigParam_AlertPoliciesCount
AlertPolicies []*PEFConfigParam_AlertPolicy
SystemGUID *PEFConfigParam_SystemGUID
AlertStringsCount *PEFConfigParam_AlertStringsCount
AlertStringKeys []*PEFConfigParam_AlertStringKey
AlertStrings []*PEFConfigParam_AlertString
GroupControlsCount *PEFConfigParam_GroupControlsCount
GroupControls []*PEFConfigParam_GroupControl
}
func (pefConfigParams *PEFConfigParams) Format() string {
var out string
format := func(param PEFConfigParameter) string {
if isNilPEFConfigParameter(param) {
return ""
}
paramSelector, _, _ := param.PEFConfigParameter()
content := param.Format()
if content[len(content)-1] != '\n' {
content += "\n"
}
return fmt.Sprintf("[%2d] %s : %s", paramSelector, paramSelector.String(), content)
}
if pefConfigParams.SetInProgress != nil {
out += format(pefConfigParams.SetInProgress)
}
if pefConfigParams.Control != nil {
out += format(pefConfigParams.Control)
}
if pefConfigParams.ActionGlobalControl != nil {
out += format(pefConfigParams.ActionGlobalControl)
}
if pefConfigParams.StartupDelay != nil {
out += format(pefConfigParams.StartupDelay)
}
if pefConfigParams.AlertStartupDelay != nil {
out += format(pefConfigParams.AlertStartupDelay)
}
if pefConfigParams.EventFiltersCount != nil {
out += format(pefConfigParams.EventFiltersCount)
}
if pefConfigParams.EventFilters != nil {
for i := range pefConfigParams.EventFilters {
out += format(pefConfigParams.EventFilters[i])
}
}
if pefConfigParams.EventFiltersData1 != nil {
for i := range pefConfigParams.EventFiltersData1 {
out += format(pefConfigParams.EventFiltersData1[i])
}
}
if pefConfigParams.AlertPoliciesCount != nil {
out += format(pefConfigParams.AlertPoliciesCount)
}
if pefConfigParams.AlertPolicies != nil {
for i := range pefConfigParams.AlertPolicies {
out += format(pefConfigParams.AlertPolicies[i])
}
}
if pefConfigParams.SystemGUID != nil {
out += format(pefConfigParams.SystemGUID)
}
if pefConfigParams.AlertStringsCount != nil {
out += format(pefConfigParams.AlertStringsCount)
}
if pefConfigParams.AlertStringKeys != nil {
for i := range pefConfigParams.AlertStringKeys {
out += format(pefConfigParams.AlertStringKeys[i])
}
}
if pefConfigParams.AlertStrings != nil {
for i := range pefConfigParams.AlertStrings {
out += format(pefConfigParams.AlertStrings[i])
}
}
if pefConfigParams.GroupControlsCount != nil {
out += format(pefConfigParams.GroupControlsCount)
}
if pefConfigParams.GroupControls != nil {
for i := range pefConfigParams.GroupControls {
out += format(pefConfigParams.GroupControls[i])
}
}
return out
}
type PEFConfigParam_SetInProgress struct {
Value SetInProgressState
}
func (param *PEFConfigParam_SetInProgress) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_SetInProgress, 0, 0
}
func (param *PEFConfigParam_SetInProgress) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Value = SetInProgressState(data[0])
return nil
}
func (param *PEFConfigParam_SetInProgress) Pack() []byte {
return []byte{byte(param.Value)}
}
func (param *PEFConfigParam_SetInProgress) Format() string {
return fmt.Sprintf("%v", param.Value)
}
type PEFConfigParam_Control struct {
EnablePEFAlertStartupDelay bool
EnablePEFStartupDelay bool
EnableEventMessage bool
EnablePEF bool
}
func (param *PEFConfigParam_Control) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_Control, 0, 0
}
func (param *PEFConfigParam_Control) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.EnablePEFAlertStartupDelay = isBit3Set(data[0])
param.EnablePEFStartupDelay = isBit2Set(data[0])
param.EnableEventMessage = isBit1Set(data[0])
param.EnablePEF = isBit0Set(data[0])
return nil
}
func (param *PEFConfigParam_Control) Pack() []byte {
b := uint8(0x00)
b = setOrClearBit3(b, param.EnablePEFAlertStartupDelay)
b = setOrClearBit2(b, param.EnablePEFStartupDelay)
b = setOrClearBit1(b, param.EnableEventMessage)
b = setOrClearBit0(b, param.EnablePEF)
return []byte{b}
}
func (param *PEFConfigParam_Control) Format() string {
return fmt.Sprintf(`
PEF startup delay : %s
Alert startup delay : %s
PEF event messages : %s
PEF : %s
`,
formatBool(param.EnablePEFAlertStartupDelay, "enabled", "disabled"),
formatBool(param.EnablePEFStartupDelay, "enabled", "disabled"),
formatBool(param.EnableEventMessage, "enabled", "disabled"),
formatBool(param.EnablePEF, "enabled", "disabled"),
)
}
type PEFConfigParam_ActionGlobalControl struct {
DiagnosticInterruptEnabled bool
OEMActionEnabled bool
PowerCycleActionEnabled bool
ResetActionEnabled bool
PowerDownActionEnabled bool
AlertActionEnabled bool
}
func (param *PEFConfigParam_ActionGlobalControl) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_ActionGlobalControl, 0, 0
}
func (param *PEFConfigParam_ActionGlobalControl) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.DiagnosticInterruptEnabled = isBit5Set(data[0])
param.OEMActionEnabled = isBit4Set(data[0])
param.PowerCycleActionEnabled = isBit3Set(data[0])
param.ResetActionEnabled = isBit2Set(data[0])
param.PowerDownActionEnabled = isBit1Set(data[0])
param.AlertActionEnabled = isBit0Set(data[0])
return nil
}
func (param *PEFConfigParam_ActionGlobalControl) Pack() []byte {
b := uint8(0x00)
b = setOrClearBit5(b, param.DiagnosticInterruptEnabled)
b = setOrClearBit4(b, param.OEMActionEnabled)
b = setOrClearBit3(b, param.PowerCycleActionEnabled)
b = setOrClearBit2(b, param.ResetActionEnabled)
b = setOrClearBit1(b, param.PowerDownActionEnabled)
b = setOrClearBit0(b, param.AlertActionEnabled)
return []byte{b}
}
func (param *PEFConfigParam_ActionGlobalControl) Format() string {
return fmt.Sprintf(`
Diagnostic-interrupt : %s
OEM-defined : %s
Power-cycle : %s
Reset : %s
Power-off : %s
Alert : %s
`,
formatBool(param.DiagnosticInterruptEnabled, "active", "inactive"),
formatBool(param.OEMActionEnabled, "active", "inactive"),
formatBool(param.PowerCycleActionEnabled, "active", "inactive"),
formatBool(param.ResetActionEnabled, "active", "inactive"),
formatBool(param.PowerDownActionEnabled, "active", "inactive"),
formatBool(param.AlertActionEnabled, "active", "inactive"),
)
}
type PEFConfigParam_StartupDelay struct {
DelaySec uint8
}
func (param *PEFConfigParam_StartupDelay) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_StartupDelay, 0, 0
}
func (param *PEFConfigParam_StartupDelay) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.DelaySec = data[0]
return nil
}
func (param *PEFConfigParam_StartupDelay) Pack() []byte {
return []byte{param.DelaySec}
}
func (param *PEFConfigParam_StartupDelay) Format() string {
return fmt.Sprintf("%v", param.DelaySec)
}
type PEFConfigParam_AlertStartupDelay struct {
DelaySec uint8
}
func (param *PEFConfigParam_AlertStartupDelay) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_AlertStartDelay, 0, 0
}
func (param *PEFConfigParam_AlertStartupDelay) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.DelaySec = data[0]
return nil
}
func (param *PEFConfigParam_AlertStartupDelay) Pack() []byte {
return []byte{param.DelaySec}
}
func (param *PEFConfigParam_AlertStartupDelay) Format() string {
return fmt.Sprintf("%v", param.DelaySec)
}
// Number of event filters supported. 1-based.
// This parameter does not need to be supported if Alerting is not supported.
// READ ONLY
type PEFConfigParam_EventFiltersCount struct {
Value uint8
}
func (param *PEFConfigParam_EventFiltersCount) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_EventFiltersCount, 0, 0
}
func (param *PEFConfigParam_EventFiltersCount) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Value = data[0]
return nil
}
func (param *PEFConfigParam_EventFiltersCount) Pack() []byte {
return []byte{param.Value}
}
func (param *PEFConfigParam_EventFiltersCount) Format() string {
return fmt.Sprintf("%d", param.Value)
}
type PEFConfigParam_EventFilter struct {
// Set Selector = filter number. 1-based. 00h = reserved.
SetSelector uint8
Filter *PEFEventFilter
}
func (param *PEFConfigParam_EventFilter) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_EventFilter, param.SetSelector, 0
}
func (param *PEFConfigParam_EventFilter) Unpack(data []byte) error {
if len(data) < 21 {
return ErrUnpackedDataTooShortWith(len(data), 21)
}
param.SetSelector = data[0]
eventFilter := &PEFEventFilter{}
if err := eventFilter.Unpack(data[1:21]); err != nil {
return fmt.Errorf("unpack entry failed, err: %w", err)
}
param.Filter = eventFilter
return nil
}
func (param *PEFConfigParam_EventFilter) Pack() []byte {
entryData := param.Filter.Pack()
out := make([]byte, len(entryData))
out[0] = param.SetSelector
packBytes(entryData, out, 1)
return out
}
func (param *PEFConfigParam_EventFilter) Format() string {
return fmt.Sprintf(`
Event Filter Number: %d
Event Filter:
%v
`, param.SetSelector, param.Filter.Format())
}
// This parameter provides an aliased access to the first byte of the event filter data.
// This is provided to simplify the act of enabling and disabling individual filters
// by avoiding the need to do a read-modify-write of the entire filter data.
type PEFConfigParam_EventFilterData1 struct {
// Set Selector = filter number
SetSelector uint8
// data byte 1 of event filter data
// [7] - 1b = enable filter
// 0b = disable filter
FilterEnabled bool
// [6:5] - 11b = reserved
// 10b = manufacturer pre-configured filter. The filter entry has been
// configured by the system integrator and should not be altered by software.
// Software is allowed to enable or disable the filter, however.
// 01b = reserved
// 00b = software configurable filter. The filter entry is available for
// configuration by system management software.
FilterType PEFEventFilterType
}
func (param *PEFConfigParam_EventFilterData1) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_EventFilterData1, param.SetSelector, 0
}
func (param *PEFConfigParam_EventFilterData1) Unpack(data []byte) error {
if len(data) < 2 {
return ErrUnpackedDataTooShortWith(len(data), 21)
}
param.SetSelector = data[0]
b := data[1]
param.FilterEnabled = isBit7Set(b)
param.FilterType = PEFEventFilterType((b >> 5) & 0x03)
return nil
}
func (param *PEFConfigParam_EventFilterData1) Pack() []byte {
out := make([]byte, 21)
out[0] = param.SetSelector
var b byte
b = uint8(param.FilterType) << 5
b = setOrClearBit7(b, param.FilterEnabled)
out[1] = b
return out
}
func (param *PEFConfigParam_EventFilterData1) Format() string {
return fmt.Sprintf(`FilterNumber: %d, FilterEnabled: %v, FilterType: %v`, param.SetSelector, param.FilterEnabled, param.FilterType)
}
// Number of alert policy entries supported. 1-based.
// This parameter does not need to be supported if Alerting is not supported.
// READ ONLY
type PEFConfigParam_AlertPoliciesCount struct {
Value uint8
}
func (param *PEFConfigParam_AlertPoliciesCount) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_AlertPoliciesCount, 0, 0
}
func (param *PEFConfigParam_AlertPoliciesCount) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Value = data[0]
return nil
}
func (param *PEFConfigParam_AlertPoliciesCount) Pack() []byte {
return []byte{param.Value}
}
func (param *PEFConfigParam_AlertPoliciesCount) Format() string {
return fmt.Sprintf("%d", param.Value)
}
type PEFConfigParam_AlertPolicy struct {
// Set Selector = entry number
// - [7] - reserved
// - [6:0] - alert policy entry number. 1-based.
SetSelector uint8
Policy *PEFAlertPolicy
}
func (param *PEFConfigParam_AlertPolicy) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_AlertPolicy, param.SetSelector, 0
}
func (param *PEFConfigParam_AlertPolicy) Unpack(data []byte) error {
if len(data) < 4 {
return ErrUnpackedDataTooShortWith(len(data), 4)
}
param.SetSelector = data[0]
b := &PEFAlertPolicy{}
if err := b.Unpack(data[1:]); err != nil {
return err
}
param.Policy = b
return nil
}
func (param *PEFConfigParam_AlertPolicy) Pack() []byte {
entryData := param.Policy.Pack()
out := make([]byte, 1+len(entryData))
out[0] = param.SetSelector
packBytes(entryData, out, 1)
return out
}
func (param *PEFConfigParam_AlertPolicy) Format() string {
return fmt.Sprintf(`
Entry Number %d : %v
`, param.SetSelector, param.Policy.Format())
}
type PEFConfigParam_SystemGUID struct {
// Used to fill in the GUID field in a PET Trap.
// [7:1] - reserved
// [0]
// 1b = BMC uses following value in PET Trap.
// 0b = BMC ignores following value and uses value returned from Get System GUID command instead.
UseGUID bool
GUID [16]byte
}
func (param *PEFConfigParam_SystemGUID) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_SystemGUID, 0, 0
}
func (param *PEFConfigParam_SystemGUID) Unpack(configData []byte) error {
if len(configData) < 17 {
return ErrUnpackedDataTooShortWith(len(configData), 17)
}
param.UseGUID = isBit0Set(configData[0])
param.GUID = array16(configData[1:17])
return nil
}
func (param *PEFConfigParam_SystemGUID) Pack() []byte {
out := make([]byte, 17)
out[0] = setOrClearBit0(0x00, param.UseGUID)
copy(out[1:], param.GUID[:])
return out
}
func (param *PEFConfigParam_SystemGUID) Format() string {
var guidStr string
guid, err := ParseGUID(param.GUID[:], GUIDModeSMBIOS)
if err != nil {
guidStr = fmt.Sprintf(" (%s)", err)
} else {
guidStr = guid.String()
}
return fmt.Sprintf(`
UseGUID : %v
GUID : %s
`, param.UseGUID, guidStr)
}
// Number of alert strings supported in addition to Alert String 0. 1-based.
// This parameter does not need to be supported if Alerting is not supported.
// READ ONLY
type PEFConfigParam_AlertStringsCount struct {
Value uint8
}
func (param *PEFConfigParam_AlertStringsCount) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_AlertStringsCount, 0, 0
}
func (param *PEFConfigParam_AlertStringsCount) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Value = data[0]
return nil
}
func (param *PEFConfigParam_AlertStringsCount) Pack() []byte {
return []byte{param.Value}
}
func (param *PEFConfigParam_AlertStringsCount) Format() string {
return fmt.Sprintf("%d", param.Value)
}
// Sets the keys used to look up Alert String data in PEF.
// This parameter does not need to be supported if Alerting is not supported.
//
// It's purpose is to get the AlertStringSelector from combination of the (Event) FilterNumber and AlertStringSet.
type PEFConfigParam_AlertStringKey struct {
// Set Selector = Alert string selector.
// - 0 = selects volatile string parameters
// - 01h-7Fh = non-volatile string selectors
SetSelector uint8
// [6:0] - Filter number. 1-based. 00h = unspecified.
FilterNumber uint8
// [6:0] - Set number for string. 1-based. 00h = unspecified.
AlertStringSet uint8
}
func (param *PEFConfigParam_AlertStringKey) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_AlertStringKey, param.SetSelector, 0
}
func (param *PEFConfigParam_AlertStringKey) Unpack(data []byte) error {
if len(data) < 3 {
return ErrUnpackedDataTooShortWith(len(data), 3)
}
param.SetSelector = data[0]
param.FilterNumber = data[1]
param.AlertStringSet = data[2]
return nil
}
func (param *PEFConfigParam_AlertStringKey) Pack() []byte {
return []byte{param.SetSelector, param.FilterNumber, param.AlertStringSet}
}
func (param *PEFConfigParam_AlertStringKey) Format() string {
return fmt.Sprintf(`Set Selector: %d, Event Filter Number: %d, Alert String Set: %d`,
param.SetSelector, param.FilterNumber, param.AlertStringSet)
}
type PEFConfigParam_AlertString struct {
// Set Selector = string selector.
// - 0 = selects volatile string
// - 01h-7Fh = non-volatile string selectors
SetSelector uint8
// Block Selector = string block number to set, 1 based. Blocks are 16 bytes.
BlockSelector uint8
// String data. Null terminated 8-bit ASCII string. 16-bytes max. per block.
StringData []byte
}
func (param *PEFConfigParam_AlertString) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_AlertString, param.SetSelector, param.BlockSelector
}
func (param *PEFConfigParam_AlertString) Unpack(data []byte) error {
if len(data) < 3 {
return ErrUnpackedDataTooShortWith(len(data), 3)
}
param.SetSelector = data[0]
param.BlockSelector = data[1]
param.StringData, _, _ = unpackBytes(data, 2, len(data)-2)
return nil
}
func (param *PEFConfigParam_AlertString) Pack() []byte {
out := make([]byte, 2+len(param.StringData))
out[0] = param.SetSelector
out[1] = param.BlockSelector
packBytes(param.StringData, out, 2)
return out
}
func (param *PEFConfigParam_AlertString) Format() string {
return fmt.Sprintf(`AlertStringSelector: %d, BlockSelector: %d, StringData: %s`, param.SetSelector, param.BlockSelector, string(param.StringData))
}
// READ ONLY
type PEFConfigParam_GroupControlsCount struct {
Value uint8
}
func (param *PEFConfigParam_GroupControlsCount) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_GroupControlsCount, 0, 0
}
func (param *PEFConfigParam_GroupControlsCount) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
param.Value = data[0]
return nil
}
func (param *PEFConfigParam_GroupControlsCount) Pack() []byte {
return []byte{param.Value}
}
func (param *PEFConfigParam_GroupControlsCount) Format() string {
return fmt.Sprintf("%d", param.Value)
}
type PEFConfigParam_GroupControl struct {
// Set Selector (Entry Selector) = group control table entry selector.
SetSelector uint8
ForceControlOperation bool
DelayedControl bool
ChannelNumber uint8
GroupID0 uint8
MemberID0 uint8
DisableMemberID0Check bool
GroupID1 uint8
MemberID1 uint8
DisableMemberID1Check bool
GroupID2 uint8
MemberID2 uint8
DisableMemberID2Check bool
GroupID3 uint8
MemberID3 uint8
DisableMemberID3Check bool
RetryCount uint8
Operation uint8
}
func (param *PEFConfigParam_GroupControl) PEFConfigParameter() (paramSelector PEFConfigParamSelector, setSelector uint8, blockSelector uint8) {
return PEFConfigParamSelector_GroupControl, param.SetSelector, 0
}
func (param *PEFConfigParam_GroupControl) Unpack(data []byte) error {
if len(data) < 11 {
return ErrUnpackedDataTooShortWith(len(data), 11)
}
param.SetSelector = data[0]
param.ForceControlOperation = isBit5Set(data[1])
param.DelayedControl = isBit4Set(data[1])
param.ChannelNumber = data[1] & 0x0F
param.GroupID0 = data[2]
param.MemberID0 = data[3] & 0x0F
param.DisableMemberID0Check = isBit4Set(data[3])
param.GroupID1 = data[4]
param.MemberID1 = data[5] & 0x0F
param.DisableMemberID1Check = isBit4Set(data[5])
param.GroupID2 = data[6]
param.MemberID2 = data[7] & 0x0F
param.DisableMemberID2Check = isBit4Set(data[7])
param.GroupID3 = data[8]
param.MemberID3 = data[9] & 0x0F
param.DisableMemberID3Check = isBit4Set(data[9])
// data 11: - Retries and Operation
// [7] - reserved
// [6:4] - number of times to retry sending the command to perform
// the group operation [For ICMB, the BMC broadcasts a
// Group Chassis Control command] (1-based)
param.RetryCount = (data[10] & 0x7F) >> 4
param.Operation = data[10] & 0x0F
return nil
}
func (param *PEFConfigParam_GroupControl) Pack() []byte {
var b uint8
out := make([]byte, 11)
out[0] = param.SetSelector
b = param.ChannelNumber & 0x0F
b = setOrClearBit5(b, param.ForceControlOperation)
b = setOrClearBit4(b, param.DelayedControl)
out[1] = b
out[2] = param.GroupID0
b = param.MemberID0 & 0x0F
b = setOrClearBit4(b, param.DisableMemberID0Check)
out[3] = b
out[4] = param.GroupID1
b = param.MemberID1 & 0x0F
b = setOrClearBit4(b, param.DisableMemberID1Check)
out[5] = b
out[6] = param.GroupID2
b = param.MemberID2 & 0x0F
b = setOrClearBit4(b, param.DisableMemberID2Check)
out[7] = b
out[8] = param.GroupID3
b = param.MemberID3 & 0x0F
b = setOrClearBit4(b, param.DisableMemberID3Check)
out[9] = b
b = param.RetryCount << 4
b |= param.Operation
out[10] = b
return out
}
func (param *PEFConfigParam_GroupControl) Format() string {
return fmt.Sprintf(`
EntrySelector: %d
ForceControlOperation: %v
DelayedControl: %v
ChannelNumber: %d
GroupID0: %d
MemberID0: %d
DisableMemberID0Check: %v
GroupID1: %d
MemberID1: %d
DisableMemberID1Check: %v
GroupID2: %d
MemberID2: %d
DisableMemberID2Check: %v
GroupID3: %d
MemberID3: %d
DisableMemberID3Check: %v
RetryCount: %d
Operation: %d
`,
param.SetSelector,
param.ForceControlOperation,
param.DelayedControl,
param.ChannelNumber,
param.GroupID0,
param.MemberID0,
param.DisableMemberID0Check,
param.GroupID1,
param.MemberID1,
param.DisableMemberID1Check,
param.GroupID2,
param.MemberID2,
param.DisableMemberID2Check,
param.GroupID3,
param.MemberID3,
param.DisableMemberID3Check,
param.RetryCount,
param.Operation)
}
golang-github-bougou-go-ipmi-0.7.2/types_rmcp.go 0000664 0000000 0000000 00000031757 14741105271 0021637 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
)
const (
RmcpVersion uint8 = 0x06
RMCP_TYPE_MASK = 0x80
RMCP_TYPE_NORM = 0x00
RMCP_TYPE_ACK = 0x01
)
// Rmcp holds the data that will be send over UDP
type Rmcp struct {
// Multi-byte fields in RMCP/ASF fields are specified as being transmitted in "Network Byte Order" - meaning most-significant byte first.
// RMCP and ASF-specified fields are therefore transferred **most-significant byte first**.
RmcpHeader *RmcpHeader
// Multi-byte fields in RMCP/ASF fields are specified as being transmitted in "Network Byte Order"
ASF *ASF
// The IPMI convention is to transfer multi-byte numeric fields least-significant Byte first. Therefore, unless otherwise specified:
// Data in the IPMI Session Header and IPMI Message fields are transmitted **least-significant byte first**.
Session15 *Session15
Session20 *Session20
}
func (r *Rmcp) Pack() []byte {
out := r.RmcpHeader.Pack()
if r.ASF != nil {
out = append(out, r.ASF.Pack()...)
}
if r.Session15 != nil {
out = append(out, r.Session15.Pack()...)
}
if r.Session20 != nil {
out = append(out, r.Session20.Pack()...)
}
return out
}
func (r *Rmcp) Unpack(msg []byte) error {
if len(msg) < 4 {
return ErrUnpackedDataTooShortWith(len(msg), 4)
}
rmcpHeader := &RmcpHeader{}
err := rmcpHeader.Unpack(msg[:4])
if err != nil {
return fmt.Errorf("unpack RmcpHeader failed, err: %w", err)
}
r.RmcpHeader = rmcpHeader
if len(msg) < 4+1 {
return fmt.Errorf("msg length too short, no session inside")
}
if r.RmcpHeader.MessageClass == MessageClassASF {
asf := &ASF{}
err := asf.Unpack(msg[4:])
if err != nil {
return fmt.Errorf("unpack ASF failed, err: %w", err)
}
r.ASF = asf
return nil
}
authTypeOrFormat := msg[4]
if authTypeOrFormat == byte(AuthTypeRMCPPlus) {
// IPMI 2.0
s20 := &Session20{}
err = s20.Unpack(msg[4:])
if err != nil {
return fmt.Errorf("unpack IPMI 2.0 Session failed, err: %w", err)
}
r.Session20 = s20
} else {
// IPMI 1.5
s15 := &Session15{}
err = s15.Unpack(msg[4:])
if err != nil {
return fmt.Errorf("unpack IPMI 1.5 Session failed, err: %w", err)
}
r.Session15 = s15
}
if r.Session15 != nil && r.Session20 != nil {
return fmt.Errorf("the IPMI session can not be both version 1.5 and 2.0")
}
return nil
}
// RmcpHeader represents RMCP Message Header
// 13.1.3
type RmcpHeader struct {
// 06h = RMCP Version 1.0
// IPMI-over-LAN uses version 1 of the RMCP protocol and packet format
Version uint8
// RMCP Messages with class=IPMI should be sent with an RMCP Sequence Number of FFh
// to indicate that an RMCP ACK message should not be generated by the message receiver.
SequenceNumber uint8
// This field identifies the format of the messages that follow this header.
// All messages of class ASF (6) conform to the formats defined in this
// specification and can be extended via an OEM IANA.
// Bit 7 RMCP ACK
// 0 - Normal RMCP message
// 1 - RMCP ACK message
ACKFlag bool
// Bit 6:5 Reserved
// Bit 4:0 Message Class
// 0-5 = Reserved
// 6 = ASF
// 7 = IPMI
// 8 = OEM defined
// all other = Reserved
MessageClass MessageClass // Can be IPMI Messages, ASF, OEM
}
func NewRmcpHeader() *RmcpHeader {
return &RmcpHeader{
Version: RmcpVersion,
SequenceNumber: 0xff,
MessageClass: MessageClassIPMI,
}
}
func NewRmcpHeaderASF() *RmcpHeader {
return &RmcpHeader{
Version: RmcpVersion,
SequenceNumber: 0xff,
MessageClass: MessageClassASF,
}
}
func (r *RmcpHeader) Pack() []byte {
msg := make([]byte, 4)
packUint8(r.Version, msg, 0)
// 1 byte reserved
packUint8(r.SequenceNumber, msg, 2)
var messageClass uint8 = 0x00
if r.ACKFlag {
messageClass |= 0x80
} else {
messageClass |= 0x00
}
messageClass |= uint8(r.MessageClass)
packUint8(messageClass, msg, 3)
return msg
}
func (r *RmcpHeader) Unpack(msg []byte) error {
if len(msg) < 4 {
return ErrUnpackedDataTooShortWith(len(msg), 4)
}
r.Version, _, _ = unpackUint8(msg, 0)
// 1 byte reserved
r.SequenceNumber, _, _ = unpackUint8(msg, 2)
var b uint8
b, _, _ = unpackUint8(msg, 3)
r.ACKFlag = isBit7Set(b)
messageClass := b & 0x7f // clear the ACK bit
r.MessageClass = MessageClass(messageClass)
return nil
}
type MessageType uint8
const (
MessageACKBit uint8 = 0x80
MessageNormalBit uint8 = 0x00
)
const (
MessageTypeUndefined MessageType = 0x00
MessageTypePing MessageType = 0x80
MessageTypeRMCPACK MessageType = (0x80 | 6)
MessageTypeASF MessageType = (0x00 | 6)
MessageTypeIPMI MessageType = (0x00 | 7)
MessageTypeOEM MessageType = (0x00 | 8)
)
// the ACK/Normal Bit and the Message Class combine to identify the type of
// message under RMCP
// see: Table 13-, Message Type Determination Under RMCP
func (r *RmcpHeader) MessageType() MessageType {
if r.ACKFlag {
switch r.MessageClass {
case MessageClassASF:
return MessageTypeRMCPACK
default:
return MessageTypeUndefined
}
}
switch r.MessageClass {
case MessageClassASF:
return MessageTypeASF
case MessageClassOEM:
return MessageTypeOEM
case MessageClassIPMI:
return MessageTypeIPMI
default:
return MessageTypeIPMI
}
}
type MessageClass uint8
const (
// 0-5 Reserved
MessageClassASF = 6
MessageClassIPMI = 7
MessageClassOEM = 8
// 9-15 Reserved
)
func (mc MessageClass) NormalACKFlag() bool {
i := uint8(mc) & uint8(1) << 7
return i == uint8(1)<<7
}
// 13.2.1 RMCP ACK Messages
type RmcpAckMessage struct {
// Copied from received message
Version uint8
// Copied from received message
SequenceNumber uint8
// [7] - Set to 1 to indicate ACK packet
// [6:0] - Copied from received message.
ACKFlag bool
MessageClass MessageClass // Can be IPMI Messages, ASF, OEM
}
type ASF struct {
IANA uint32 // 4542
MessageType uint8
// 0-FEh, generated by remote console. This is an RMCP version of a sequence number.
// Values 0-254 (0-FEh) are used for RMCP request/response messages.
// 255 indicates the message is unidirectional and not part of a request/response pair.
MessageTag uint8
DataLength uint8 // 00h
Data []byte
}
func (asf *ASF) Pack() []byte {
msg := make([]byte, 8+len(asf.Data))
packUint32(asf.IANA, msg, 0) // MSB, not LSB
packUint8(asf.MessageType, msg, 4)
packUint8(asf.MessageTag, msg, 5)
// 1 byte reserved
packUint8(asf.DataLength, msg, 7)
packBytes(asf.Data, msg, 8)
return msg
}
func (asf *ASF) Unpack(msg []byte) error {
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
asf.IANA, _, _ = unpackUint32L(msg, 0)
asf.MessageType, _, _ = unpackUint8(msg, 4)
asf.MessageTag, _, _ = unpackUint8(msg, 5)
// 1 byte reserved
asf.DataLength, _, _ = unpackUint8(msg, 7)
if len(msg) < 8+int(asf.DataLength) {
return ErrUnpackedDataTooShortWith(len(msg), 8+int(asf.DataLength))
}
asf.Data, _, _ = unpackBytes(msg, 8, int(asf.DataLength))
return nil
}
func (c *Client) BuildRmcpRequest(ctx context.Context, reqCmd Request) (*Rmcp, error) {
payloadType, rawPayload, err := c.buildRawPayload(ctx, reqCmd)
if err != nil {
return nil, fmt.Errorf("buildRawPayload failed, err: %w", err)
}
c.DebugBytes("rawPayload", rawPayload, 16)
// ASF
if _, ok := reqCmd.(*RmcpPingRequest); ok {
rmcp := &Rmcp{
RmcpHeader: NewRmcpHeaderASF(),
ASF: &ASF{
IANA: 4542,
MessageType: uint8(MessageTypePing),
MessageTag: 0,
DataLength: 0,
Data: rawPayload,
},
}
return rmcp, nil
}
// IPMI 2.0
if c.v20 {
session20, err := c.genSession20(payloadType, rawPayload)
if err != nil {
return nil, fmt.Errorf("genSession20 failed, err: %w", err)
}
rmcp := &Rmcp{
RmcpHeader: NewRmcpHeader(),
Session20: session20,
}
return rmcp, nil
}
// IPMI 1.5
session15, err := c.genSession15(rawPayload)
if err != nil {
return nil, fmt.Errorf("genSession15 failed, err: %w", err)
}
rmcp := &Rmcp{
RmcpHeader: NewRmcpHeader(),
Session15: session15,
}
return rmcp, nil
}
// ParseRmcpResponse parses msg bytes.
// The response param should be passed as a pointer of the struct which implements the Response interface.
func (c *Client) ParseRmcpResponse(ctx context.Context, msg []byte, response Response) error {
rmcp := &Rmcp{}
if err := rmcp.Unpack(msg); err != nil {
return fmt.Errorf("unpack rmcp failed, err: %w", err)
}
c.Debug("<<<<<< RMCP Response", rmcp)
if rmcp.ASF != nil {
if int(rmcp.ASF.DataLength) != len(rmcp.ASF.Data) {
return fmt.Errorf("asf Data Length not equal")
}
if err := response.Unpack(rmcp.ASF.Data); err != nil {
return fmt.Errorf("unpack asf response failed, err: %w", err)
}
return nil
}
if rmcp.Session15 != nil {
ipmiPayload := rmcp.Session15.Payload
ipmiRes := IPMIResponse{}
if err := ipmiRes.Unpack(ipmiPayload); err != nil {
return fmt.Errorf("unpack ipmiRes failed, err: %w", err)
}
c.Debug("<<<< IPMI Response", ipmiRes)
ccode := ipmiRes.CompletionCode
if ccode != 0x00 {
return &ResponseError{
completionCode: CompletionCode(ccode),
description: fmt.Sprintf("ipmiRes CompletionCode (%#02x) is not normal: %s", ccode, StrCC(response, ccode)),
}
}
// now ccode is 0x00, we can continue to deserialize response
if err := response.Unpack(ipmiRes.Data); err != nil {
return &ResponseError{
completionCode: 0x00,
description: fmt.Sprintf("unpack response failed, err: %s", err),
}
}
}
if rmcp.Session20 != nil {
sessionHdr := rmcp.Session20.SessionHeader20
switch sessionHdr.PayloadType {
case
PayloadTypeRmcpOpenSessionResponse,
PayloadTypeRAKPMessage2,
PayloadTypeRAKPMessage4:
// Session Setup Payload Types
if err := response.Unpack(rmcp.Session20.SessionPayload); err != nil {
return fmt.Errorf("unpack session setup response failed, err: %w", err)
}
return nil
case PayloadTypeIPMI:
// Standard Payload Types
ipmiPayload := rmcp.Session20.SessionPayload
if sessionHdr.PayloadEncrypted {
c.DebugBytes("decrypting", ipmiPayload, 16)
d, err := c.decryptPayload(rmcp.Session20.SessionPayload)
if err != nil {
return fmt.Errorf("decrypt session payload failed, err: %w", err)
}
ipmiPayload = d
c.DebugBytes("decrypted", ipmiPayload, 16)
}
ipmiRes := IPMIResponse{}
if err := ipmiRes.Unpack(ipmiPayload); err != nil {
return fmt.Errorf("unpack ipmiRes failed, err: %w", err)
}
c.Debug("<<<< IPMI Response", ipmiRes)
ccode := ipmiRes.CompletionCode
if ccode != 0x00 {
return &ResponseError{
completionCode: CompletionCode(ccode),
description: fmt.Sprintf("ipmiRes CompletionCode (%#02x) is not normal: %s", ccode, StrCC(response, ccode)),
}
}
// now ccode is 0x00, we can continue to deserialize response
if err := response.Unpack(ipmiRes.Data); err != nil {
return &ResponseError{
completionCode: 0x00,
description: fmt.Sprintf("unpack response failed, err: %s", err),
}
}
}
}
return nil
}
// 13.24 RMCP+ and RAKP Message Status Codes
type RmcpStatusCode uint8
const (
RmcpStatusCodeNoErrors RmcpStatusCode = 0x00
RmcpStatusCodeNoResToCreateSess RmcpStatusCode = 0x01
RmcpStatusCodeInvalidSessionID RmcpStatusCode = 0x02
RmcpStatusCodeInvalidPayloadType RmcpStatusCode = 0x03
RmcpStatusCodeInvalidAuthAlg RmcpStatusCode = 0x04
RmcpStatusCodeInvalidIntegrityAlg RmcpStatusCode = 0x05
RmcpStatusCodeNoMatchingAuthPayload RmcpStatusCode = 0x06
RmcpStatusCodeNoMatchingIntegrityPayload RmcpStatusCode = 0x07
RmcpStatusCodeInactiveSessionID RmcpStatusCode = 0x08
RmcpStatusCodeInvalidRole RmcpStatusCode = 0x09
RmcpStatusCodeUnauthorizedRoleOfPriLevel RmcpStatusCode = 0x0a
RmcpStatusCodeNoResToCreateSessAtRole RmcpStatusCode = 0x0b
RmcpStatusCodeInvalidNameLength RmcpStatusCode = 0x0c
RmcpStatusCodeUnauthorizedName RmcpStatusCode = 0x0d
RmcpStatusCodeUnauthorizedGUID RmcpStatusCode = 0x0e
RmcpStatusCodeInvalidIntegrityCheckValue RmcpStatusCode = 0x0f
RmcpStatusCodeInvalidConfidentAlg RmcpStatusCode = 0x10
RmcpStatusCodeNoCipherSuiteMatch RmcpStatusCode = 0x11
RmcpStatusCodeIllegalParameter RmcpStatusCode = 0x12
)
func (c RmcpStatusCode) String() string {
m := map[RmcpStatusCode]string{
0x00: "No errors",
0x01: "Insufficient resources to create a session",
0x02: "Invalid Session ID",
0x03: "Invalid payload type",
0x04: "Invalid authentication algorithm",
0x05: "Invalid integrity algorithm",
0x06: "No matching authentication payload",
0x07: "No matching integrity payload",
0x08: "Inactive Session ID",
0x09: "Invalid role",
0x0a: "Unauthorized role of privilege level requested",
0x0b: "Insufficient resources to create a session at the requested role",
0x0c: "Invalid name length",
0x0d: "Unauthorized name",
0x0e: "Unauthorized GUID",
0x0f: "Invalid integrity check value",
0x10: "Invalid confidentiality algorithm",
0x11: "No Cipher Suite match with proposed security algorithms",
0x12: "Illegal or unrecognized parameter",
// 0x13 - 0xff: Reserved for future definition by this specification.
}
s, ok := m[c]
if ok {
return s
}
return "Unknown"
}
golang-github-bougou-go-ipmi-0.7.2/types_sdr.go 0000664 0000000 0000000 00000065464 14741105271 0021470 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"context"
"fmt"
"github.com/olekukonko/tablewriter"
)
const SDRRecordHeaderSize int = 5
// 43. Sensor Data Record Formats
// SDRRecordType is a number representing the type of the record.
type SDRRecordType uint8
const (
SDRRecordTypeFullSensor SDRRecordType = 0x01
SDRRecordTypeCompactSensor SDRRecordType = 0x02
SDRRecordTypeEventOnly SDRRecordType = 0x03
SDRRecordTypeEntityAssociation SDRRecordType = 0x08
SDRRecordTypeDeviceRelativeEntityAssociation SDRRecordType = 0x09
SDRRecordTypeGenericLocator SDRRecordType = 0x10
SDRRecordTypeFRUDeviceLocator SDRRecordType = 0x11
SDRRecordTypeManagementControllerDeviceLocator SDRRecordType = 0x12
SDRRecordTypeManagementControllerConfirmation SDRRecordType = 0x13
SDRRecordTypeBMCMessageChannelInfo SDRRecordType = 0x14
SDRRecordTypeOEM SDRRecordType = 0xc0
)
func (sdrRecordType SDRRecordType) String() string {
// 43.6 SDR Type 0Ah:0Fh - Reserved Records
// This range and all other unspecified SDR Type values are reserved.
var sdrRecordTypeMap = map[SDRRecordType]string{
0x01: "Full",
0x02: "Compact",
0x03: "Event",
0x08: "Entity Assoc",
0x09: "Device Entity Assoc",
0x10: "Generic Device Loc",
0x11: "FRU Device Loc",
0x12: "MC Device Loc", // MC: Management Controller
0x13: "MC Confirmation",
0x14: "BMC Msg Channel Info",
0xc0: "OEM",
}
s, ok := sdrRecordTypeMap[sdrRecordType]
if !ok {
return "Reserved"
}
return s
}
type SDRHeader struct {
RecordID uint16
SDRVersion uint8 // The version number of the SDR specification.
RecordType SDRRecordType // A number representing the type of the record. E.g. 01h = 8-bit Sensor with Thresholds.
RecordLength uint8 // Number of bytes of data following the Record Length field.
}
// 43. Sensor Data Record Formats
type SDR struct {
// NextRecordID should be filled by ParseSDR.
NextRecordID uint16
RecordHeader *SDRHeader
Full *SDRFull
Compact *SDRCompact
EventOnly *SDREventOnly
EntityAssociation *SDREntityAssociation
DeviceRelative *SDRDeviceRelative
GenericDeviceLocator *SDRGenericDeviceLocator
FRUDeviceLocator *SDRFRUDeviceLocator
MgmtControllerDeviceLocator *SDRMgmtControllerDeviceLocator
MgmtControllerConfirmation *SDRMgmtControllerConfirmation
BMCChannelInfo *SDRBMCChannelInfo
OEM *SDROEM
Reserved *SDRReserved
}
func (sdr *SDR) String() string {
recordStr := fmt.Sprintf(`RecordID: : %#02x
RecordType: : %s
SDR Version: : %#02x
Record Length: : %d
`,
sdr.RecordHeader.RecordID,
sdr.RecordHeader.RecordType,
sdr.RecordHeader.SDRVersion,
sdr.RecordHeader.RecordLength,
)
recordType := sdr.RecordHeader.RecordType
switch recordType {
case SDRRecordTypeFullSensor:
return recordStr + sdr.Full.String()
case SDRRecordTypeCompactSensor:
return recordStr + sdr.Compact.String()
case SDRRecordTypeEventOnly:
return recordStr + sdr.EventOnly.String()
case SDRRecordTypeEntityAssociation:
return recordStr
case SDRRecordTypeDeviceRelativeEntityAssociation:
return recordStr
case SDRRecordTypeGenericLocator:
return recordStr
case SDRRecordTypeFRUDeviceLocator:
return recordStr
case SDRRecordTypeManagementControllerDeviceLocator:
return recordStr
case SDRRecordTypeManagementControllerConfirmation:
return recordStr
case SDRRecordTypeOEM:
return recordStr
default:
return recordStr
}
}
func (sdr *SDR) SensorNumber() SensorNumber {
recordType := sdr.RecordHeader.RecordType
switch recordType {
case SDRRecordTypeFullSensor:
return sdr.Full.SensorNumber
case SDRRecordTypeCompactSensor:
return sdr.Compact.SensorNumber
case SDRRecordTypeEventOnly:
return sdr.EventOnly.SensorNumber
}
return SensorNumberReserved
}
func (sdr *SDR) SensorName() string {
recordType := sdr.RecordHeader.RecordType
switch recordType {
case SDRRecordTypeFullSensor:
return string(sdr.Full.IDStringBytes)
case SDRRecordTypeCompactSensor:
return string(sdr.Compact.IDStringBytes)
case SDRRecordTypeEventOnly:
return string(sdr.EventOnly.IDStringBytes)
}
return ""
}
// Determine if sensor has an analog reading
func (sdr *SDR) HasAnalogReading() bool {
// Only Full sensors can return analog values, Compact sensors can't return analog values.
// But not all Full sensors return analog values.
if sdr.RecordHeader.RecordType != SDRRecordTypeFullSensor {
return false
}
if sdr.Full == nil {
return false
}
return sdr.Full.HasAnalogReading()
}
// ParseSDR parses raw SDR record data to SDR struct.
// This function is normally used after getting GetSDRResponse or GetDeviceSDRResponse to
// interpret the raw SDR record data in the response.
func ParseSDR(data []byte, nextRecordID uint16) (*SDR, error) {
sdrHeader := &SDRHeader{}
if len(data) < SDRRecordHeaderSize {
return nil, ErrNotEnoughDataWith("sdr record header size", len(data), SDRRecordHeaderSize)
}
sdrHeader.RecordID, _, _ = unpackUint16L(data, 0)
sdrHeader.SDRVersion, _, _ = unpackUint8(data, 2)
recordType, _, _ := unpackUint8(data, 3)
sdrHeader.RecordType = SDRRecordType(recordType)
sdrHeader.RecordLength, _, _ = unpackUint8(data, 4)
sdr := &SDR{
RecordHeader: sdrHeader,
NextRecordID: nextRecordID,
}
switch sdrHeader.RecordType {
case SDRRecordTypeFullSensor:
if err := parseSDRFullSensor(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDRFullSensor failed, err: %w", err)
}
case SDRRecordTypeCompactSensor:
if err := parseSDRCompactSensor(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDRCompactSensor failed, err: %w", err)
}
case SDRRecordTypeEventOnly:
if err := parseSDREventOnly(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDREventOnly failed, err: %w", err)
}
case SDRRecordTypeEntityAssociation:
if err := parseSDREntityAssociation(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDREntityAssociation failed, err: %w", err)
}
case SDRRecordTypeDeviceRelativeEntityAssociation:
if err := parseSDRDeviceRelativeEntityAssociation(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDRDeviceRelativeEntityAssociation failed, err: %w", err)
}
case SDRRecordTypeGenericLocator:
if err := parseSDRGenericLocator(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDRGenericLocator failed, err: %w", err)
}
case SDRRecordTypeFRUDeviceLocator:
if err := parseSDRFRUDeviceLocator(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDRFRUDeviceLocator failed, err: %w", err)
}
case SDRRecordTypeManagementControllerDeviceLocator:
if err := parseSDRManagementControllerDeviceLocator(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDRManagementControllerDeviceLocator failed, err: %w", err)
}
case SDRRecordTypeManagementControllerConfirmation:
if err := parseSDRManagementControllerConfirmation(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDRManagementControllerConfirmation failed, err: %w", err)
}
case SDRRecordTypeBMCMessageChannelInfo:
if err := parseSDRBMCMessageChannelInfo(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDRBMCMessageChannelInfo failed, err: %w", err)
}
case SDRRecordTypeOEM:
if err := parseSDROEM(data, sdr); err != nil {
return nil, fmt.Errorf("parseSDROEM failed, err: %w", err)
}
}
return sdr, nil
}
// Format SDRs of FRU record type
func FormatSDRs_FRU(records []*SDR) string {
var buf = new(bytes.Buffer)
table := tablewriter.NewWriter(buf)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_RIGHT)
headers := []string{
"RecordID",
"RecordType",
"DeviceAccessAddr",
"FRUDeviceID",
"IsLogicFRU",
"AccessLUN",
"PrivateBusID",
"ChannelNumber",
"DeviceType",
"Modifier",
"FRUEntityID",
"FRUEntityInstance",
"TypeLength",
"DeviceName",
}
table.SetHeader(headers)
table.SetFooter(headers)
for _, sdr := range records {
if sdr == nil || sdr.RecordHeader == nil {
continue
}
recordID := sdr.RecordHeader.RecordID
recordType := sdr.RecordHeader.RecordType
switch recordType {
case SDRRecordTypeFRUDeviceLocator:
sdrFRU := sdr.FRUDeviceLocator
table.Append([]string{
fmt.Sprintf("%#02x", recordID),
fmt.Sprintf("%s (%#02x)", recordType.String(), uint8(recordType)),
fmt.Sprintf("%#02x", sdrFRU.DeviceAccessAddress),
fmt.Sprintf("%#02x", sdrFRU.FRUDeviceID_SlaveAddress),
fmt.Sprintf("%v", sdrFRU.IsLogicalFRUDevice),
fmt.Sprintf("%#02x", sdrFRU.AccessLUN),
fmt.Sprintf("%#02x", sdrFRU.PrivateBusID),
fmt.Sprintf("%#02x", sdrFRU.ChannelNumber),
fmt.Sprintf("%s (%#02x)", sdrFRU.DeviceType.String(), uint8(sdrFRU.DeviceType)),
fmt.Sprintf("%#02x", sdrFRU.DeviceTypeModifier),
fmt.Sprintf("%#02x", sdrFRU.FRUEntityID),
fmt.Sprintf("%#02x", sdrFRU.FRUEntityInstance),
sdrFRU.DeviceIDTypeLength.String(),
string(sdrFRU.DeviceIDBytes),
})
default:
}
}
table.Render()
return buf.String()
}
// FormatSDRs returns a table formatted string for print.
func FormatSDRs(records []*SDR) string {
var buf = new(bytes.Buffer)
table := tablewriter.NewWriter(buf)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_RIGHT)
headers := []string{
"RecordID",
"RecordType",
"GeneratorID",
"SensorNumber",
"SensorName",
"Entity",
"SensorType",
"EventReadingType",
"SensorValue",
"SensorUnit",
"SensorStatus",
}
table.SetHeader(headers)
table.SetFooter(headers)
for _, sdr := range records {
if sdr == nil || sdr.RecordHeader == nil {
continue
}
recordID := sdr.RecordHeader.RecordID
recordType := sdr.RecordHeader.RecordType
var generatorID GeneratorID
var sensorUnit SensorUnit
var entityID EntityID
var entityInstance EntityInstance
var sensorType SensorType
var eventReadingType EventReadingType
var sensorValue float64
var sensorStatus string
switch recordType {
case SDRRecordTypeFullSensor:
generatorID = sdr.Full.GeneratorID
sensorUnit = sdr.Full.SensorUnit
entityID = sdr.Full.SensorEntityID
entityInstance = sdr.Full.SensorEntityInstance
sensorType = sdr.Full.SensorType
eventReadingType = sdr.Full.SensorEventReadingType
sensorValue = sdr.Full.SensorValue
sensorStatus = sdr.Full.SensorStatus
case SDRRecordTypeCompactSensor:
generatorID = sdr.Compact.GeneratorID
sensorUnit = sdr.Compact.SensorUnit
entityID = sdr.Compact.SensorEntityID
entityInstance = sdr.Compact.SensorEntityInstance
sensorType = sdr.Compact.SensorType
eventReadingType = sdr.Compact.SensorEventReadingType
sensorValue = sdr.Compact.SensorValue
sensorStatus = sdr.Compact.SensorStatus
default:
}
table.Append([]string{
fmt.Sprintf("%#02x", recordID),
fmt.Sprintf("%s (%#02x)", recordType.String(), uint8(recordType)),
fmt.Sprintf("%#04x", generatorID),
fmt.Sprintf("%#02x", sdr.SensorNumber()),
sdr.SensorName(),
canonicalEntityString(entityID, entityInstance),
sensorType.String(),
eventReadingType.String(),
fmt.Sprintf("%#.2f", sensorValue),
sensorUnit.String(),
sensorStatus,
})
}
table.Render()
return buf.String()
}
// Mask_Threshold holds masks for a specific threshold type.
type Mask_Threshold struct {
StatusReturned bool // Indicates whether this threshold comparison status is returned via the Get Sensor Reading command.
Settable bool
Readable bool
High_Assert bool
Low_Assert bool
High_Deassert bool
Low_Deassert bool
}
// Mask_Thresholds holds masks for all threshold types.
type Mask_Thresholds struct {
LNR Mask_Threshold
LCR Mask_Threshold
LNC Mask_Threshold
UNR Mask_Threshold
UCR Mask_Threshold
UNC Mask_Threshold
}
func (mask *Mask_Thresholds) IsThresholdReadable(thresholdType SensorThresholdType) bool {
switch thresholdType {
case SensorThresholdType_LCR:
return mask.LCR.Readable
case SensorThresholdType_LNR:
return mask.LNR.Readable
case SensorThresholdType_LNC:
return mask.LNC.Readable
case SensorThresholdType_UCR:
return mask.UCR.Readable
case SensorThresholdType_UNC:
return mask.UNC.Readable
case SensorThresholdType_UNR:
return mask.UNR.Readable
}
return false
}
type Mask_DiscreteEvent struct {
State_0 bool
State_1 bool
State_2 bool
State_3 bool
State_4 bool
State_5 bool
State_6 bool
State_7 bool
State_8 bool
State_9 bool
State_10 bool
State_11 bool
State_12 bool
State_13 bool
State_14 bool
}
func (mask Mask_DiscreteEvent) TrueEvents() []uint8 {
events := []uint8{}
if mask.State_0 {
events = append(events, 0)
}
if mask.State_1 {
events = append(events, 1)
}
if mask.State_2 {
events = append(events, 2)
}
if mask.State_3 {
events = append(events, 3)
}
if mask.State_4 {
events = append(events, 4)
}
if mask.State_5 {
events = append(events, 5)
}
if mask.State_6 {
events = append(events, 6)
}
if mask.State_7 {
events = append(events, 7)
}
if mask.State_8 {
events = append(events, 8)
}
if mask.State_9 {
events = append(events, 9)
}
if mask.State_10 {
events = append(events, 10)
}
if mask.State_11 {
events = append(events, 11)
}
if mask.State_12 {
events = append(events, 12)
}
if mask.State_13 {
events = append(events, 13)
}
if mask.State_14 {
events = append(events, 14)
}
return events
}
type Mask_Discrete struct {
// Assertion Event Mask for non-threshold based sensors, true means assertion event can be generated for this state
Assert Mask_DiscreteEvent
// Deassertion Event Mask for non-threshold based sensors, true means deassertion event can be generated for this state
Deassert Mask_DiscreteEvent
// Reading Mask for non-threshold based sensors, true means discrete state can be returned by this sensor
Reading Mask_DiscreteEvent
}
// For non-threshold-based sensors, Mask holds:
// - Assertion Event Mask
// - Deassertion Event Mask
// - Discrete Reading Mask
//
// For threshold-based sensors, Mask holds:
// - Lower Threshold Reading Mask
// - Upper Threshold Reading Mask
// - Settable Threshold Mask, Readable Threshold Mask
//
// Used in Full and Compact SDR
type Mask struct {
Threshold Mask_Thresholds
Discrete Mask_Discrete
}
// ParseAssertLower fill:
// - Assertion Event Mask
// - Lower Threshold Reading Mask
// - Threshold Assertion Event Mask
func (mask *Mask) ParseAssertLower(b uint16) {
lsb := uint8(b & 0x00ff) // Least Significant Byte
msb := uint8(b >> 8) // Most Significant Byte
// Assertion Event Mask
mask.Discrete.Assert.State_14 = isBit6Set(lsb)
mask.Discrete.Assert.State_13 = isBit5Set(lsb)
mask.Discrete.Assert.State_12 = isBit4Set(lsb)
mask.Discrete.Assert.State_11 = isBit3Set(lsb)
mask.Discrete.Assert.State_10 = isBit2Set(lsb)
mask.Discrete.Assert.State_9 = isBit1Set(lsb)
mask.Discrete.Assert.State_8 = isBit0Set(lsb)
mask.Discrete.Assert.State_7 = isBit7Set(msb)
mask.Discrete.Assert.State_6 = isBit6Set(msb)
mask.Discrete.Assert.State_5 = isBit5Set(msb)
mask.Discrete.Assert.State_4 = isBit4Set(msb)
mask.Discrete.Assert.State_3 = isBit3Set(msb)
mask.Discrete.Assert.State_2 = isBit2Set(msb)
mask.Discrete.Assert.State_1 = isBit1Set(msb)
mask.Discrete.Assert.State_0 = isBit0Set(msb)
// Lower Threshold Reading Mask
// Indicates which lower threshold comparison status is returned via the Get Sensor Reading command
mask.Threshold.LNR.StatusReturned = isBit6Set(lsb)
mask.Threshold.LCR.StatusReturned = isBit5Set(lsb)
mask.Threshold.LNC.StatusReturned = isBit4Set(lsb)
// Threshold Assertion Event Mask
mask.Threshold.UNR.High_Assert = isBit3Set(lsb)
mask.Threshold.UNR.Low_Assert = isBit2Set(lsb)
mask.Threshold.UCR.High_Assert = isBit1Set(lsb)
mask.Threshold.UCR.Low_Assert = isBit0Set(lsb)
mask.Threshold.UNC.High_Assert = isBit7Set(msb)
mask.Threshold.UNC.Low_Assert = isBit6Set(msb)
mask.Threshold.LNR.High_Assert = isBit5Set(msb)
mask.Threshold.LNR.Low_Assert = isBit4Set(msb)
mask.Threshold.LCR.High_Assert = isBit3Set(msb)
mask.Threshold.LCR.Low_Assert = isBit2Set(msb)
mask.Threshold.LNC.High_Assert = isBit1Set(msb)
mask.Threshold.LNC.Low_Assert = isBit0Set(msb)
}
func (mask *Mask) ParseDeassertUpper(b uint16) {
lsb := uint8(b & 0x00ff) // Least Significant Byte
msb := uint8(b >> 8) // Most Significant Byte
// Deassertion Event Mask
mask.Discrete.Deassert.State_14 = isBit6Set(lsb)
mask.Discrete.Deassert.State_13 = isBit5Set(lsb)
mask.Discrete.Deassert.State_12 = isBit4Set(lsb)
mask.Discrete.Deassert.State_11 = isBit3Set(lsb)
mask.Discrete.Deassert.State_10 = isBit2Set(lsb)
mask.Discrete.Deassert.State_9 = isBit1Set(lsb)
mask.Discrete.Deassert.State_8 = isBit0Set(lsb)
mask.Discrete.Deassert.State_7 = isBit7Set(msb)
mask.Discrete.Deassert.State_6 = isBit6Set(msb)
mask.Discrete.Deassert.State_5 = isBit5Set(msb)
mask.Discrete.Deassert.State_4 = isBit4Set(msb)
mask.Discrete.Deassert.State_3 = isBit3Set(msb)
mask.Discrete.Deassert.State_2 = isBit2Set(msb)
mask.Discrete.Deassert.State_1 = isBit1Set(msb)
mask.Discrete.Deassert.State_0 = isBit0Set(msb)
// Upper Threshold Reading Mask
// Indicates which upper threshold comparison status is returned via the Get Sensor Reading command.
mask.Threshold.UNR.StatusReturned = isBit6Set(lsb)
mask.Threshold.UCR.StatusReturned = isBit5Set(lsb)
mask.Threshold.UNC.StatusReturned = isBit4Set(lsb)
// Threshold Deassertion Event Mask
mask.Threshold.UNR.High_Deassert = isBit3Set(lsb)
mask.Threshold.UNR.Low_Deassert = isBit2Set(lsb)
mask.Threshold.UCR.High_Deassert = isBit1Set(lsb)
mask.Threshold.UCR.Low_Deassert = isBit0Set(lsb)
mask.Threshold.UNC.High_Deassert = isBit7Set(msb)
mask.Threshold.UNC.Low_Deassert = isBit6Set(msb)
mask.Threshold.LNR.High_Deassert = isBit5Set(msb)
mask.Threshold.LNR.Low_Deassert = isBit4Set(msb)
mask.Threshold.LCR.High_Deassert = isBit3Set(msb)
mask.Threshold.LCR.Low_Deassert = isBit2Set(msb)
mask.Threshold.LNC.High_Deassert = isBit1Set(msb)
mask.Threshold.LNC.Low_Deassert = isBit0Set(msb)
}
func (mask *Mask) ParseReading(b uint16) {
lsb := uint8(b & 0x0000ffff) // Least Significant Byte
msb := uint8(b >> 8) // Most Significant Byte
// Reading Mask (for non-threshold based sensors)
// Indicates what discrete readings can be returned by this sensor.
mask.Discrete.Reading.State_14 = isBit6Set(lsb)
mask.Discrete.Reading.State_13 = isBit5Set(lsb)
mask.Discrete.Reading.State_12 = isBit4Set(lsb)
mask.Discrete.Reading.State_11 = isBit3Set(lsb)
mask.Discrete.Reading.State_10 = isBit2Set(lsb)
mask.Discrete.Reading.State_9 = isBit1Set(lsb)
mask.Discrete.Reading.State_8 = isBit0Set(lsb)
mask.Discrete.Reading.State_7 = isBit7Set(msb)
mask.Discrete.Reading.State_6 = isBit6Set(msb)
mask.Discrete.Reading.State_5 = isBit5Set(msb)
mask.Discrete.Reading.State_4 = isBit4Set(msb)
mask.Discrete.Reading.State_3 = isBit3Set(msb)
mask.Discrete.Reading.State_2 = isBit2Set(msb)
mask.Discrete.Reading.State_1 = isBit1Set(msb)
mask.Discrete.Reading.State_0 = isBit0Set(msb)
// Settable Threshold Mask (for threshold-based sensors)
// Indicates which thresholds are settable via the Set Sensor Thresholds.
mask.Threshold.UNR.Settable = isBit5Set(lsb)
mask.Threshold.UCR.Settable = isBit4Set(lsb)
mask.Threshold.UNC.Settable = isBit3Set(lsb)
mask.Threshold.LNR.Settable = isBit2Set(lsb)
mask.Threshold.LCR.Settable = isBit1Set(lsb)
mask.Threshold.LNC.Settable = isBit0Set(lsb)
// Readable Threshold Mask (for threshold-based sensors)
// Indicates which thresholds are readable via the Get Sensor Thresholds command.
mask.Threshold.UNR.Readable = isBit5Set(msb)
mask.Threshold.UCR.Readable = isBit4Set(msb)
mask.Threshold.UNC.Readable = isBit3Set(msb)
mask.Threshold.LNR.Readable = isBit2Set(msb)
mask.Threshold.LCR.Readable = isBit1Set(msb)
mask.Threshold.LNC.Readable = isBit0Set(msb)
}
// StatusReturnedThresholds returns all supported thresholds comparison status
// via the Get Sensor Reading command.
func (mask *Mask) StatusReturnedThresholds() SensorThresholdTypes {
out := make([]SensorThresholdType, 0)
if mask.Threshold.UNC.StatusReturned {
out = append(out, SensorThresholdType_UNC)
}
if mask.Threshold.UCR.StatusReturned {
out = append(out, SensorThresholdType_UCR)
}
if mask.Threshold.UNR.StatusReturned {
out = append(out, SensorThresholdType_UNR)
}
if mask.Threshold.LNC.StatusReturned {
out = append(out, SensorThresholdType_LNC)
}
if mask.Threshold.LCR.StatusReturned {
out = append(out, SensorThresholdType_LCR)
}
if mask.Threshold.LNR.StatusReturned {
out = append(out, SensorThresholdType_LNR)
}
return out
}
// ReadableThresholds returns all readable thresholds for the sensor.
func (mask *Mask) ReadableThresholds() SensorThresholdTypes {
out := make([]SensorThresholdType, 0)
if mask.Threshold.UNC.Readable {
out = append(out, SensorThresholdType_UNC)
}
if mask.Threshold.UCR.Readable {
out = append(out, SensorThresholdType_UCR)
}
if mask.Threshold.UNR.Readable {
out = append(out, SensorThresholdType_UNR)
}
if mask.Threshold.LNC.Readable {
out = append(out, SensorThresholdType_LNC)
}
if mask.Threshold.LCR.Readable {
out = append(out, SensorThresholdType_LCR)
}
if mask.Threshold.LNR.Readable {
out = append(out, SensorThresholdType_LNR)
}
return out
}
func (mask *Mask) SettableThresholds() SensorThresholdTypes {
out := make([]SensorThresholdType, 0)
if mask.Threshold.UNC.Settable {
out = append(out, SensorThresholdType_UNC)
}
if mask.Threshold.UCR.Settable {
out = append(out, SensorThresholdType_UCR)
}
if mask.Threshold.UNR.Settable {
out = append(out, SensorThresholdType_UNR)
}
if mask.Threshold.LNC.Settable {
out = append(out, SensorThresholdType_LNC)
}
if mask.Threshold.LCR.Settable {
out = append(out, SensorThresholdType_LCR)
}
if mask.Threshold.LNR.Settable {
out = append(out, SensorThresholdType_LNR)
}
return out
}
func (mask *Mask) SupportedThresholdEvents() SensorEvents {
out := make([]SensorEvent, 0)
// Assertion Events
if mask.Threshold.UNC.High_Assert {
out = append(out, SensorEvent_UNC_High_Assert)
}
if mask.Threshold.UNC.Low_Assert {
out = append(out, SensorEvent_UNC_Low_Assert)
}
if mask.Threshold.UCR.High_Assert {
out = append(out, SensorEvent_UCR_High_Assert)
}
if mask.Threshold.UCR.Low_Assert {
out = append(out, SensorEvent_UCR_Low_Assert)
}
if mask.Threshold.UNR.High_Assert {
out = append(out, SensorEvent_UNR_High_Assert)
}
if mask.Threshold.UNR.Low_Assert {
out = append(out, SensorEvent_UNR_Low_Assert)
}
if mask.Threshold.LNC.High_Assert {
out = append(out, SensorEvent_LNC_High_Assert)
}
if mask.Threshold.LNC.Low_Assert {
out = append(out, SensorEvent_LNC_Low_Assert)
}
if mask.Threshold.LCR.High_Assert {
out = append(out, SensorEvent_LCR_High_Assert)
}
if mask.Threshold.LCR.Low_Assert {
out = append(out, SensorEvent_LCR_Low_Assert)
}
if mask.Threshold.LNR.High_Assert {
out = append(out, SensorEvent_LNR_High_Assert)
}
if mask.Threshold.LNR.Low_Assert {
out = append(out, SensorEvent_LNR_Low_Assert)
}
// Deassertion Events
if mask.Threshold.UNC.High_Deassert {
out = append(out, SensorEvent_UNC_High_Deassert)
}
if mask.Threshold.UNC.Low_Deassert {
out = append(out, SensorEvent_UNC_Low_Deassert)
}
if mask.Threshold.UCR.High_Deassert {
out = append(out, SensorEvent_UCR_High_Deassert)
}
if mask.Threshold.UCR.Low_Deassert {
out = append(out, SensorEvent_UCR_Low_Deassert)
}
if mask.Threshold.UNR.High_Deassert {
out = append(out, SensorEvent_UNR_High_Deassert)
}
if mask.Threshold.UNR.Low_Deassert {
out = append(out, SensorEvent_UNR_Low_Deassert)
}
if mask.Threshold.LNC.High_Deassert {
out = append(out, SensorEvent_LNC_High_Deassert)
}
if mask.Threshold.LNC.Low_Deassert {
out = append(out, SensorEvent_LNC_Low_Deassert)
}
if mask.Threshold.LCR.High_Deassert {
out = append(out, SensorEvent_LCR_High_Deassert)
}
if mask.Threshold.LCR.Low_Deassert {
out = append(out, SensorEvent_LCR_Low_Deassert)
}
if mask.Threshold.LNR.High_Deassert {
out = append(out, SensorEvent_LNR_High_Deassert)
}
if mask.Threshold.LNR.Low_Deassert {
out = append(out, SensorEvent_LNR_Low_Deassert)
}
return out
}
// SensorCapabilities represent the capabilities of the sensor.
// SDRs of Full/Compact record type has this field.
type SensorCapabilities struct {
// [7] - 1b = ignore sensor if Entity is not present or disabled. 0b = don't ignore sensor
IgnoreSensorIfNoEntity bool
// Sensor Auto Re-arm Support
// Indicates whether the sensor requires manual rearming, or automatically rearms
// itself when the event clears. 'manual' implies that the get sensor event status and
// rearm sensor events commands are supported
// [6] - 0b = no (manual), 1b = yes (auto)
AutoRearm bool
HysteresisAccess SensorHysteresisAccess
ThresholdAccess SensorThresholdAccess
EventMessageControl SensorEventMessageControl
}
// SDRs of Full/Compact record type has this field.
type SensorInitialization struct {
// 1b = Sensor is settable (Support the Set Sensor Reading And Event Status command)
// 0b = Sensor is not settable
//
// using this bit to report settable sensors is optional.
// I.e. it is ok to report a settable sensor as 'not settable' in the
// SDR if it is desired to not report this capability to s/w
Settable bool
// 1b = enable scanning
//
// this bit=1 implies that the sensor
// accepts the 'enable/disable scanning' bit in the Set
// Sensor Event Enable command.
InitScanning bool
// 1b = enable events (per Sensor Event Message Control
// Support bits in Sensor Capabilities field, and per
// the Event Mask fields, below).
InitEvents bool
// 1b = initialize sensor thresholds (per settable threshold mask below).
InitThresholds bool
// 1b = initialize sensor hysteresis (per Sensor Hysteresis
// Support bits in the Sensor Capabilities field, below).
InitHysteresis bool
// 1b = initialize Sensor Type and Event / Reading Type code
InitSensorType bool
// Sensor Default (power up) State
//
// Reports how this sensor comes up on device power up and hardware/cold reset.
// The Initialization Agent does not use this bit. This bit solely reports to software
// how the sensor comes prior to being initialized by the Initialization Agent.
// 0b = event generation disabled, 1b = event generation enabled
EventGenerationEnabled bool
// 0b = sensor scanning disabled, 1b = sensor scanning enabled
SensorScanningEnabled bool
}
// enhanceSDR will fill extra data for SDR
func (c *Client) enhanceSDR(ctx context.Context, sdr *SDR) error {
if sdr == nil {
return nil
}
if sdr.RecordHeader.RecordType != SDRRecordTypeFullSensor &&
sdr.RecordHeader.RecordType != SDRRecordTypeCompactSensor {
return nil
}
sensor, err := c.sdrToSensor(ctx, sdr)
if err != nil {
return fmt.Errorf("sdrToSensor failed, err: %w", err)
}
switch sdr.RecordHeader.RecordType {
case SDRRecordTypeFullSensor:
sdr.Full.SensorValue = sensor.Value
sdr.Full.SensorStatus = sensor.Status()
case SDRRecordTypeCompactSensor:
sdr.Compact.SensorValue = sensor.Value
sdr.Compact.SensorStatus = sensor.Status()
}
return nil
}
golang-github-bougou-go-ipmi-0.7.2/types_sdr_compact.go 0000664 0000000 0000000 00000021241 14741105271 0023157 0 ustar 00root root 0000000 0000000 package ipmi
import (
"fmt"
"strings"
)
// 43.2 SDR Type 02h, Compact Sensor Record
//
// The Compact sensor record saves space, but has limitations in the sensors it can describe.
type SDRCompact struct {
//
// Record KEY
//
GeneratorID GeneratorID
SensorNumber SensorNumber
//
// RECORD BODY
//
SensorEntityID EntityID
SensorEntityInstance EntityInstance
// 0b = treat entity as a physical entity per Entity ID table
// 1b = treat entity as a logical container entity. For example, if this bit is set,
// and the Entity ID is "Processor", the container entity would be considered
// to represent a logical "Processor Group" rather than a physical processor.
// This bit is typically used in conjunction with an Entity Association record.
SensorEntityIsLogical bool
SensorInitialization SensorInitialization
SensorCapabilities SensorCapabilities
SensorType SensorType
SensorEventReadingType EventReadingType
Mask Mask
SensorUnit SensorUnit
// SensorValue is not stored in SDR intrinsically, this field is set by `enhanceSDR`
// It is fetched by IPMI command GetSensorReading and aligned/converted to SensorUnit based.
SensorValue float64
// SensorStatus is not stored in SDR intrinsically, this field is set by `enhanceSDR`
SensorStatus string
// Sensor Direction. Indicates whether the sensor is monitoring an input or
// output relative to the given Entity. E.g. if the sensor is monitoring a
// current, this can be used to specify whether it is an input voltage or an
// output voltage.
// 00b = unspecified / not applicable
// 01b = input
// 10b = output
// 11b = reserved
SensorDirection uint8
EntityInstanceSharing uint8
// Positive hysteresis is defined as the unsigned number of counts that are
// subtracted from the raw threshold values to create the "re-arm" point for all
// positive-going thresholds on the sensor. 0 indicates that there is no hysteresis on
// positive-going thresholds for this sensor. Hysteresis values are given as raw
// counts. That is, to find the degree of hysteresis in units, the value must be
// converted using the "y=Mx+B" formula.
//
// compact SDR can have pos/neg hysteresis, but they cannot be analog!
PositiveHysteresisRaw uint8
// Negative hysteresis is defined as the unsigned number of counts that are added
// to the raw threshold value to create the "re-arm" point for all negative-going
// thresholds on the sensor. 0 indicates that there is no hysteresis on negative-going
// thresholds for this sensor.
//
// compact SDR can have pos/neg hysteresis, but they cannot be analog!
NegativeHysteresisRaw uint8
IDStringTypeLength TypeLength // Sensor ID String Type/Length Code
IDStringBytes []byte // Sensor ID String bytes.
}
func (compact *SDRCompact) String() string {
return fmt.Sprintf(`Sensor ID : %s (%#02x)
Generator : %d
Entity ID : %d.%d (%s)
Sensor Type (%s) : %s (%#02x)
Sensor Reading : %.3f %s
Sensor Status : %s
Sensor Initialization :
Settable : %v
Scanning : %v
Events : %v
Hysteresis : %v
Sensor Type : %v
Default State:
Event Generation : %s
Scanning : %s
Sensor Capabilities :
Auto Re-arm : %s
Hysteresis Support : %s
Threshold Access : %s
Ev Message Control : %s
Mask :
Readable Thresholds : %s
Settable Thresholds : %s
Threshold Read Mask : %s
Assertions Enabled : %s
Deassertions Enabled: %s
Positive Hysteresis : %#02x
Negative Hysteresis : %#02x`,
string(compact.IDStringBytes), compact.SensorNumber,
compact.GeneratorID,
uint8(compact.SensorEntityID), uint8(compact.SensorEntityInstance), compact.SensorEntityID.String(),
compact.SensorEventReadingType.SensorClass(), compact.SensorType.String(), uint8(compact.SensorType),
compact.SensorValue, compact.SensorUnit,
compact.SensorStatus,
compact.SensorInitialization.Settable,
compact.SensorInitialization.InitScanning,
compact.SensorInitialization.InitEvents,
compact.SensorInitialization.InitHysteresis,
compact.SensorInitialization.InitSensorType,
formatBool(compact.SensorInitialization.EventGenerationEnabled, "enabled", "disabled"),
formatBool(compact.SensorInitialization.SensorScanningEnabled, "enabled", "disabled"),
formatBool(compact.SensorCapabilities.AutoRearm, "yes(auto)", "no(manual)"),
compact.SensorCapabilities.HysteresisAccess.String(),
compact.SensorCapabilities.ThresholdAccess,
compact.SensorCapabilities.EventMessageControl,
strings.Join(compact.Mask.ReadableThresholds().Strings(), " "),
strings.Join(compact.Mask.SettableThresholds().Strings(), " "),
strings.Join(compact.Mask.StatusReturnedThresholds().Strings(), " "),
strings.Join(compact.Mask.SupportedThresholdEvents().FilterAssert().Strings(), " "),
strings.Join(compact.Mask.SupportedThresholdEvents().FilterDeassert().Strings(), " "),
compact.PositiveHysteresisRaw,
compact.NegativeHysteresisRaw,
)
// Assertions Enabled : Critical Interrupt
// [PCI PERR]
// [PCI SERR]
// [Bus Correctable error]
// [Bus Uncorrectable error]
// [Bus Fatal Error]
// Deassertions Enabled : Critical Interrupt
// [PCI PERR]
// [PCI SERR]
// [Bus Correctable error]
// [Bus Uncorrectable error]
// [Bus Fatal Error]
// OEM : 0
}
func (record *SDRCompact) PositiveHysteresis() (raw uint8, valid bool) {
raw = record.PositiveHysteresisRaw
if raw == 0x00 || raw == 0xff {
valid = false
} else {
valid = true
}
return
}
func (record *SDRCompact) NegativeHysteresis() (raw uint8, valid bool) {
raw = record.NegativeHysteresisRaw
if raw == 0x00 || raw == 0xff {
valid = false
} else {
valid = true
}
return
}
func parseSDRCompactSensor(data []byte, sdr *SDR) error {
const SDRCompactSensorMinSize int = 32 // plus the ID String Bytes (optional 16 bytes maximum)
minSize := SDRCompactSensorMinSize
if len(data) < minSize {
return ErrNotEnoughDataWith("sdr (compact sensor) min size", len(data), minSize)
}
s := &SDRCompact{}
sdr.Compact = s
generatorID, _, _ := unpackUint16L(data, 5)
s.GeneratorID = GeneratorID(generatorID)
sensorNumber, _, _ := unpackUint8(data, 7)
s.SensorNumber = SensorNumber(sensorNumber)
b8, _, _ := unpackUint8(data, 8)
s.SensorEntityID = EntityID(b8)
b9, _, _ := unpackUint8(data, 9)
s.SensorEntityInstance = EntityInstance(b9 & 0x7f)
s.SensorEntityIsLogical = isBit7Set(b9)
b10, _, _ := unpackUint8(data, 10)
s.SensorInitialization = SensorInitialization{
Settable: isBit7Set(b10),
InitScanning: isBit6Set(b10),
InitEvents: isBit5Set(b10),
InitThresholds: isBit4Set(b10),
InitHysteresis: isBit3Set(b10),
InitSensorType: isBit2Set(b10),
EventGenerationEnabled: isBit1Set(b10),
SensorScanningEnabled: isBit0Set(b10),
}
b11, _, _ := unpackUint8(data, 11)
s.SensorCapabilities = SensorCapabilities{
IgnoreSensorIfNoEntity: isBit7Set(b11),
AutoRearm: isBit6Set(b11),
HysteresisAccess: SensorHysteresisAccess((b11 & 0x3f) >> 4),
ThresholdAccess: SensorThresholdAccess((b11 & 0x0f) >> 2),
EventMessageControl: SensorEventMessageControl(b11 & 0x03),
}
sensorType, _, _ := unpackUint8(data, 12)
s.SensorType = SensorType(sensorType)
eventReadingType, _, _ := unpackUint8(data, 13)
s.SensorEventReadingType = EventReadingType(eventReadingType)
mask := Mask{}
b14, _, _ := unpackUint16(data, 14)
b16, _, _ := unpackUint16(data, 16)
b18, _, _ := unpackUint16(data, 18)
mask.ParseAssertLower(b14)
mask.ParseDeassertUpper(b16)
mask.ParseReading(b18)
s.Mask = mask
b20, _, _ := unpackUint8(data, 20)
b21, _, _ := unpackUint8(data, 21)
b22, _, _ := unpackUint8(data, 22)
s.SensorUnit = SensorUnit{
AnalogDataFormat: SensorAnalogUnitFormat((b20 & 0xc0) >> 6),
RateUnit: SensorRateUnit((b20 & 0x38) >> 4),
ModifierRelation: SensorModifierRelation((b20 & 0x06) >> 2),
Percentage: isBit0Set(b20),
BaseUnit: SensorUnitType(b21),
ModifierUnit: SensorUnitType(b22),
}
s.PositiveHysteresisRaw, _, _ = unpackUint8(data, 25)
s.NegativeHysteresisRaw, _, _ = unpackUint8(data, 26)
typeLength, _, _ := unpackUint8(data, 31)
s.IDStringTypeLength = TypeLength(typeLength)
idStrLen := int(s.IDStringTypeLength.Length())
if len(data) < minSize+idStrLen {
return ErrNotEnoughDataWith("sdr (compact sensor)", len(data), minSize+idStrLen)
}
s.IDStringBytes, _, _ = unpackBytes(data, minSize, idStrLen)
return nil
}
golang-github-bougou-go-ipmi-0.7.2/types_sdr_full.go 0000664 0000000 0000000 00000042477 14741105271 0022511 0 ustar 00root root 0000000 0000000 package ipmi
import (
"fmt"
"strings"
)
// 43.1 SDRFull Type 01h, Full Sensor Record
//
// The Full Sensor Record can be used to describe any type of sensor.
type SDRFull struct {
//
// Record KEY
//
// The Record 'Key' Fields are a set of fields that together are unique amongst instances of a given record type.
// The Record Key bytes shall be contiguous and follow the Record Header.
// The number of bytes that make up the Record Key field may vary according to record type.
GeneratorID GeneratorID
SensorNumber SensorNumber
//
// RECORD BODY
//
// Indicates the physical entity that the sensor is monitoring or is otherwise
// associated with the sensor.
SensorEntityID EntityID
SensorEntityInstance EntityInstance
// For example, if this bit is set, and the Entity ID is "Processor",
// the container entity would be considered to represent a logical "Processor Group" rather than a physical processor.
//
// This bit is typically used in conjunction with an Entity Association full.
//
// 0b = treat entity as a physical entity per Entity ID table
// 1b = treat entity as a logical container entity.
SensorEntityIsLogical bool
SensorInitialization SensorInitialization
SensorCapabilities SensorCapabilities
SensorType SensorType
SensorEventReadingType EventReadingType
Mask Mask
SensorUnit SensorUnit
// Note, SensorValue is not stored in SDR intrinsically, this field is set by `enhanceSDR`
// It is fetched by IPMI command GetSensorReading and aligned/converted to SensorUnit based.
SensorValue float64
// Note, SensorStatus is not stored in SDR intrinsically, this field is set by `enhanceSDR`
SensorStatus string
EntityInstanceSharing uint8
// see: 36.3 Sensor Reading Conversion Formula
// y = L[(Mx + (B * 10^B_Exp) ) * 10^R_Exp ] units
// LinearizationFunc is the Linearization func. (L of the Sensor Reading Conversion Formula)
//
// [6:0] - enum (linear, ln, log10, log2, e, exp10, exp2, 1/x, sqr(x), cube(x), sqrt(x),
// cube-1 (x) )
// - 70h = non-linear.
// 71h-7Fh = non-linear, OEM defined.
LinearizationFunc LinearizationFunc
ReadingFactors
// Sensor Direction. Indicates whether the sensor is monitoring an input or
// output relative to the given Entity. E.g. if the sensor is monitoring a
// current, this can be used to specify whether it is an input voltage or an
// output voltage.
// 00b = unspecified / not applicable
// 01b = input
// 10b = output
// 11b = reserved
SensorDirection uint8
// Analog Flags
NominalReadingSpecified bool
NormalMaxSpecified bool
NormalMinSpecified bool
// 额定值, 标称值
// Given as a raw value. Must be converted to units-based value using the y=Mx+B
// formula. 1's or 2's complement signed or unsigned per flag bits in Sensor Units 1
//
// Only meaningful when NominalReadingSpecified is true
NominalReadingRaw uint8
// 最大正常值
// Only meaningful when NormalMaxSpecified is true
NormalMaxRaw uint8
// 最小正常值
// Only meaningful when NormalMinSpecified is true
NormalMinRaw uint8
// Given as a raw value. Must be converted to units-based value based using the
// y=Mx+B formula. Signed or unsigned per "signed" bit in sensor flags. Normally
// "FFh" for an 8-bit unsigned sensor, but can be a lesser value if the sensor has a
// restricted range. If max. reading cannot be pre-specified this value should be set
// to max value, based on data format, (e.g. FFh for an unsigned sensor, 7Fh for 2"s
// complement, etc.)
SensorMaxReadingRaw uint8
// Given as a raw value. Must be converted to units-based value using the "y=Mx+B"
// formula. Signed or unsigned per "signed" bit in sensor flags. If min. reading
// cannot be pre-specified this value should be set to min value, based on data
// format, (e.g. 00h for an unsigned sensor, 80h for 2"s complement, etc.)
SensorMinReadingRaw uint8
// Given as raw value.
UNR_Raw uint8
UCR_Raw uint8
UNC_Raw uint8
LNR_Raw uint8
LCR_Raw uint8
LNC_Raw uint8
// Positive hysteresis is defined as the unsigned number of counts that are
// subtracted from the raw threshold values to create the "re-arm" point for all
// positive-going thresholds on the sensor. 0 indicates that there is no hysteresis on
// positive-going thresholds for this sensor. Hysteresis values are given as raw
// counts. That is, to find the degree of hysteresis in units, the value must be
// converted using the "y=Mx+B" formula.
//
// 正向迟滞量
PositiveHysteresisRaw uint8
// Negative hysteresis is defined as the unsigned number of counts that are added
// to the raw threshold value to create the "re-arm" point for all negative-going
// thresholds on the sensor. 0 indicates that there is no hysteresis on negative-going
// thresholds for this sensor.
//
// 负向迟滞量
NegativeHysteresisRaw uint8
IDStringTypeLength TypeLength
IDStringBytes []byte
}
// ConvertReading converts raw sensor reading or raw sensor threshold value to real value in the desired units for the sensor.
func (full *SDRFull) ConvertReading(raw uint8) float64 {
if full.HasAnalogReading() {
return ConvertReading(raw, full.SensorUnit.AnalogDataFormat, full.ReadingFactors, full.LinearizationFunc)
}
return float64(raw)
}
// ConvertSensorHysteresis converts raw sensor hysteresis value to real value in the desired units for the sensor.
func (full *SDRFull) ConvertSensorHysteresis(raw uint8) float64 {
if full.HasAnalogReading() {
return ConvertSensorHysteresis(raw, full.SensorUnit.AnalogDataFormat, full.ReadingFactors, full.LinearizationFunc)
}
return float64(raw)
}
// ConvertSensorTolerance converts raw sensor tolerance value to real value in the desired units for the sensor.
func (full *SDRFull) ConvertSensorTolerance(raw uint8) float64 {
if full.HasAnalogReading() {
return ConvertSensorTolerance(raw, full.SensorUnit.AnalogDataFormat, full.ReadingFactors, full.LinearizationFunc)
}
return float64(raw)
}
func (full *SDRFull) ReadingStr(raw uint8, valid bool) string {
if !valid {
return "unspecified"
}
if !full.SensorUnit.IsAnalog() {
return fmt.Sprintf("%#02x", raw)
}
value := full.ConvertReading(raw)
return fmt.Sprintf("%#02x/%.3f", raw, value)
}
func (full *SDRFull) ReadingMaxStr() string {
maxRaw := full.SensorMaxReadingRaw
analogFormat := full.SensorUnit.AnalogDataFormat
if (analogFormat == SensorAnalogUnitFormat_Unsigned && maxRaw == 0xff) ||
(analogFormat == SensorAnalogUnitFormat_1sComplement && maxRaw == 0x00) ||
(analogFormat == SensorAnalogUnitFormat_2sComplement && maxRaw == 0x7f) ||
(full.SensorUnit.IsAnalog() && full.ConvertReading(maxRaw) == 0.0) {
return "unspecified"
}
return full.ReadingStr(maxRaw, true)
}
func (full *SDRFull) ReadingMinStr() string {
minRaw := full.SensorMinReadingRaw
analogFormat := full.SensorUnit.AnalogDataFormat
if (analogFormat == SensorAnalogUnitFormat_Unsigned && minRaw == 0x00) ||
(analogFormat == SensorAnalogUnitFormat_1sComplement && minRaw == 0xff) ||
(analogFormat == SensorAnalogUnitFormat_2sComplement && minRaw == 0x80) ||
(full.SensorUnit.IsAnalog() && full.ConvertReading(minRaw) == 0.0) {
return "unspecified"
}
return full.ReadingStr(minRaw, true)
}
// ThresholdValueStr formats a threshold value for specified threshold type.
// If the threshold is not readable, return "not readable".
func (full *SDRFull) ThresholdValueStr(thresholdType SensorThresholdType) string {
thresholdAttr := full.SensorThreshold(thresholdType)
return full.ReadingStr(thresholdAttr.Raw, thresholdAttr.Mask.Readable)
}
func (full *SDRFull) HysteresisStr(raw uint8) string {
if !full.SensorUnit.IsAnalog() {
if raw == 0x00 || raw == 0xff {
return "unspecified"
}
return fmt.Sprintf("%#02x", raw)
}
// analog sensor
value := full.ConvertSensorHysteresis(raw)
if raw == 0x00 || raw == 0xff || value == 0.0 {
return "unspecified"
}
return fmt.Sprintf("%#02x/%.3f", raw, value)
}
// SensorThreshold return SensorThreshold for a specified threshold type.
func (full *SDRFull) SensorThreshold(thresholdType SensorThresholdType) SensorThreshold {
switch thresholdType {
case SensorThresholdType_LNR:
return SensorThreshold{
Type: thresholdType,
Mask: full.Mask.Threshold.LNR,
Raw: full.LNR_Raw,
}
case SensorThresholdType_LCR:
return SensorThreshold{
Type: thresholdType,
Mask: full.Mask.Threshold.LCR,
Raw: full.LCR_Raw,
}
case SensorThresholdType_LNC:
return SensorThreshold{
Type: thresholdType,
Mask: full.Mask.Threshold.LNC,
Raw: full.LNC_Raw,
}
case SensorThresholdType_UNC:
return SensorThreshold{
Type: thresholdType,
Mask: full.Mask.Threshold.UNC,
Raw: full.UNC_Raw,
}
case SensorThresholdType_UCR:
return SensorThreshold{
Type: thresholdType,
Mask: full.Mask.Threshold.UCR,
Raw: full.UCR_Raw,
}
case SensorThresholdType_UNR:
return SensorThreshold{
Type: thresholdType,
Mask: full.Mask.Threshold.UNR,
Raw: full.UNR_Raw,
}
}
return SensorThreshold{
Type: thresholdType,
}
}
func (full *SDRFull) String() string {
// For pure SDR record, there's no reading for a sensor, unless you use
// GetSensorReading command to fetch it.
return fmt.Sprintf(`Sensor ID : %s (%#02x)
Generator : %#02x
Entity ID : %d.%d (%s)
Sensor Type (%s) : %s (%#02x)
Sensor Reading : %.4f (+/- %d) %s
Sensor Status : %s
Sensor Initialization :
Settable : %v
Scanning : %v
Events : %v
Hysteresis : %v
Sensor Type : %v
Default State:
Event Generation : %s
Scanning : %s
Sensor Capabilities :
Auto Re-arm : %s
Hysteresis Support : %s
Threshold Access : %s
Ev Message Control : %s
Mask :
Readable Thresholds : %s
Settable Thresholds : %s
Threshold Read Mask : %s
Assertions Enabled : %s
Deassertions Enabled: %s
Nominal Reading : %s
Normal Minimum : %s
Normal Maximum : %s
Lower Non-Recoverable : %s
Lower Critical : %s
Lower Non-Critical : %s
Upper Non-Critical : %s
Upper Critical : %s
Upper Non-Recoverable : %s
Positive Hysteresis : %s
Negative Hysteresis : %s
Minimum sensor range : %s
Maximum sensor range : %s
SensorDirection : %d
LinearizationFunc : %s
Reading Factors : %s`,
string(full.IDStringBytes), full.SensorNumber,
full.GeneratorID,
uint8(full.SensorEntityID), uint8(full.SensorEntityInstance), full.SensorEntityID.String(),
full.SensorEventReadingType.SensorClass(), full.SensorType.String(), uint8(full.SensorType),
full.SensorValue, full.ReadingFactors.Tolerance, full.SensorUnit,
full.SensorStatus,
full.SensorInitialization.Settable,
full.SensorInitialization.InitScanning,
full.SensorInitialization.InitEvents,
full.SensorInitialization.InitHysteresis,
full.SensorInitialization.InitSensorType,
formatBool(full.SensorInitialization.EventGenerationEnabled, "enabled", "disabled"),
formatBool(full.SensorInitialization.SensorScanningEnabled, "enabled", "disabled"),
formatBool(full.SensorCapabilities.AutoRearm, "yes(auto)", "no(manual)"),
full.SensorCapabilities.HysteresisAccess.String(),
full.SensorCapabilities.ThresholdAccess,
full.SensorCapabilities.EventMessageControl,
strings.Join(full.Mask.ReadableThresholds().Strings(), " "),
strings.Join(full.Mask.SettableThresholds().Strings(), " "),
strings.Join(full.Mask.StatusReturnedThresholds().Strings(), " "),
strings.Join(full.Mask.SupportedThresholdEvents().FilterAssert().Strings(), " "),
strings.Join(full.Mask.SupportedThresholdEvents().FilterDeassert().Strings(), " "),
full.ReadingStr(full.NominalReadingRaw, full.NominalReadingSpecified),
full.ReadingStr(full.NormalMinRaw, full.NormalMinSpecified),
full.ReadingStr(full.NormalMaxRaw, full.NormalMaxSpecified),
full.ThresholdValueStr(SensorThresholdType_LNR),
full.ThresholdValueStr(SensorThresholdType_LCR),
full.ThresholdValueStr(SensorThresholdType_LNC),
full.ThresholdValueStr(SensorThresholdType_UNC),
full.ThresholdValueStr(SensorThresholdType_UCR),
full.ThresholdValueStr(SensorThresholdType_UNR),
full.HysteresisStr(full.PositiveHysteresisRaw),
full.HysteresisStr(full.NegativeHysteresisRaw),
full.ReadingMinStr(),
full.ReadingMaxStr(),
full.SensorDirection,
full.LinearizationFunc,
full.ReadingFactors,
)
}
func parseSDRFullSensor(data []byte, sdr *SDR) error {
const SDRFullSensorMinSize int = 48 // plus the ID String Bytes (optional 16 bytes maximum)
minSize := SDRFullSensorMinSize
if len(data) < minSize {
return ErrNotEnoughDataWith("sdr (full sensor) min size", len(data), minSize)
}
s := &SDRFull{}
sdr.Full = s
generatorID, _, _ := unpackUint16L(data, 5)
s.GeneratorID = GeneratorID(generatorID)
sensorNumber, _, _ := unpackUint8(data, 7)
s.SensorNumber = SensorNumber(sensorNumber)
b8, _, _ := unpackUint8(data, 8)
s.SensorEntityID = EntityID(b8)
b9, _, _ := unpackUint8(data, 9)
s.SensorEntityInstance = EntityInstance(b9 & 0x7f)
s.SensorEntityIsLogical = isBit7Set(b9)
b10, _, _ := unpackUint8(data, 10)
s.SensorInitialization = SensorInitialization{
Settable: isBit7Set(b10),
InitScanning: isBit6Set(b10),
InitEvents: isBit5Set(b10),
InitThresholds: isBit4Set(b10),
InitHysteresis: isBit3Set(b10),
InitSensorType: isBit2Set(b10),
EventGenerationEnabled: isBit1Set(b10),
SensorScanningEnabled: isBit0Set(b10),
}
b11, _, _ := unpackUint8(data, 11)
s.SensorCapabilities = SensorCapabilities{
IgnoreSensorIfNoEntity: isBit7Set(b11),
AutoRearm: isBit6Set(b11),
HysteresisAccess: SensorHysteresisAccess((b11 & 0x3f) >> 4),
ThresholdAccess: SensorThresholdAccess((b11 & 0x0f) >> 2),
EventMessageControl: SensorEventMessageControl(b11 & 0x03),
}
sensorType, _, _ := unpackUint8(data, 12)
s.SensorType = SensorType(sensorType)
eventReadingType, _, _ := unpackUint8(data, 13)
s.SensorEventReadingType = EventReadingType(eventReadingType)
mask := Mask{}
b14, _, _ := unpackUint16(data, 14)
b16, _, _ := unpackUint16(data, 16)
b18, _, _ := unpackUint16(data, 18)
mask.ParseAssertLower(b14)
mask.ParseDeassertUpper(b16)
mask.ParseReading(b18)
s.Mask = mask
b20, _, _ := unpackUint8(data, 20)
b21, _, _ := unpackUint8(data, 21)
b22, _, _ := unpackUint8(data, 22)
s.SensorUnit = SensorUnit{
AnalogDataFormat: SensorAnalogUnitFormat((b20 & 0xc0) >> 6),
RateUnit: SensorRateUnit((b20 & 0x38) >> 4),
ModifierRelation: SensorModifierRelation((b20 & 0x06) >> 2),
Percentage: isBit0Set(b20),
BaseUnit: SensorUnitType(b21),
ModifierUnit: SensorUnitType(b22),
}
b23, _, _ := unpackUint8(data, 23)
s.LinearizationFunc = LinearizationFunc(b23)
b24, _, _ := unpackUint8(data, 24)
b25, _, _ := unpackUint8(data, 25)
m := uint16(b25&0xc0)<<2 | uint16(b24)
s.M = int16(twosComplement(uint32(m), 10))
s.Tolerance = b25 & 0x3f
b26, _, _ := unpackUint8(data, 26)
b27, _, _ := unpackUint8(data, 27)
b28, _, _ := unpackUint8(data, 28)
b := uint16(b27&0xc0)<<2 | uint16(b26)
s.B = int16(twosComplement(uint32(b), 10))
s.Accuracy = uint16(b28&0xf0)<<2 | uint16(b27&0x3f)
s.Accuracy_Exp = (b28 & 0x0c) >> 2
s.SensorDirection = b28 & 0x03
b29, _, _ := unpackUint8(data, 29)
rExp := uint8((b29 & 0xf0) >> 4)
s.R_Exp = int8(twosComplement(uint32(rExp), 4))
bExp := uint8(b29 & 0x0f)
s.B_Exp = int8(twosComplement(uint32(bExp), 4))
b30, _, _ := unpackUint8(data, 30)
s.NormalMinSpecified = isBit2Set(b30)
s.NormalMaxSpecified = isBit1Set(b30)
s.NominalReadingSpecified = isBit0Set(b30)
s.NominalReadingRaw, _, _ = unpackUint8(data, 31)
s.NormalMaxRaw, _, _ = unpackUint8(data, 32)
s.NormalMinRaw, _, _ = unpackUint8(data, 33)
s.SensorMaxReadingRaw, _, _ = unpackUint8(data, 34)
s.SensorMinReadingRaw, _, _ = unpackUint8(data, 35)
s.UNR_Raw, _, _ = unpackUint8(data, 36)
s.UCR_Raw, _, _ = unpackUint8(data, 37)
s.UNC_Raw, _, _ = unpackUint8(data, 38)
s.LNR_Raw, _, _ = unpackUint8(data, 39)
s.LCR_Raw, _, _ = unpackUint8(data, 40)
s.LNC_Raw, _, _ = unpackUint8(data, 41)
s.PositiveHysteresisRaw, _, _ = unpackUint8(data, 42)
s.NegativeHysteresisRaw, _, _ = unpackUint8(data, 43)
typeLength, _, _ := unpackUint8(data, 47)
s.IDStringTypeLength = TypeLength(typeLength)
idStrLen := int(s.IDStringTypeLength.Length())
if len(data) < minSize+idStrLen {
return ErrNotEnoughDataWith("sdr (full sensor)", len(data), minSize+idStrLen)
}
s.IDStringBytes, _, _ = unpackBytes(data, minSize, idStrLen)
return nil
}
func (full *SDRFull) HasAnalogReading() bool {
// Todo, logic is not clear.
/*
* Per the IPMI Specification:
* Only Full Threshold sensors are identified as providing
* analog readings.
*
* But... HP didn't interpret this as meaning that "Only Threshold
* Sensors" can provide analog readings. So, HP packed analog
* readings into some of their non-Threshold Sensor. There is
* nothing that explicitly prohibits this in the spec, so if
* an Analog reading is available in a Non-Threshold sensor and
* there are units specified for identifying the reading then
* we do an analog conversion even though the sensor is
* non-Threshold. To be safe, we provide this extension for
* HP.
*
*/
if full.SensorEventReadingType.IsThreshold() {
// for threshold sensors
return true
}
if full.SensorUnit.IsAnalog() {
return true
}
// for non-threshold sensors, but the analog data format indicates analog.
// this rarely exists, except HP.
// Todo
return false
}
golang-github-bougou-go-ipmi-0.7.2/types_sdr_others.go 0000664 0000000 0000000 00000066062 14741105271 0023047 0 ustar 00root root 0000000 0000000 package ipmi
import "fmt"
// 43.3 SDR Type 03h, Event-Only Record
type SDREventOnly struct {
//
// Record KEY
//
GeneratorID GeneratorID
SensorNumber SensorNumber // Unique number identifying the sensor behind a given slave address and LUN. Code FFh reserved.
//
// RECORD BODY
//
SensorEntityID EntityID
SensorEntityInstance EntityInstance
// 0b = treat entity as a physical entity per Entity ID table
// 1b = treat entity as a logical container entity. For example, if this bit is set,
// and the Entity ID is "Processor", the container entity would be considered
// to represent a logical "Processor Group" rather than a physical processor.
// This bit is typically used in conjunction with an Entity Association record.
SensorEntityIsLogical bool
SensorType SensorType
SensorEventReadingType EventReadingType
SensorDirection uint8
IDStringInstanceModifierType uint8
// Share count (number of sensors sharing this record). Sensor numbers sharing this
// record are sequential starting with the sensor number specified by the Sensor
// Number field for this record. E.g. if the starting sensor number was 10, and the share
// count was 3, then sensors 10, 11, and 12 would share this record.
ShareCount uint8
EntityInstanceSharing bool
// Multiple Discrete sensors can share the same sensor data record. The ID String Instance
// Modifier and Modifier Offset are used to modify the Sensor ID String as follows:
// Suppose sensor ID is "Temp " for "Temperature Sensor", share count = 3, ID string
// instance modifier = numeric, instance modifier offset = 5 - then the sensors could be
// identified as:
// Temp 5, Temp 6, Temp 7
// If the modifier = alpha, and offset = 26, then the sensors could be identified as:
// Temp AA, Temp AB, Temp AC
// (alpha characters are considered to be base 26 for ASCII)
IDStringInstanceModifierOffset uint8
IDStringTypeLength TypeLength
IDStringBytes []byte
}
func (eventOnly *SDREventOnly) String() string {
return fmt.Sprintf(`Sensor ID : %s (%#02x)
Generator : %d
Entity ID : %d.%d (%s)
Sensor Type (%s) : %s (%#02x)`,
string(eventOnly.IDStringBytes), eventOnly.SensorNumber,
eventOnly.GeneratorID,
uint8(eventOnly.SensorEntityID), uint8(eventOnly.SensorEntityInstance), eventOnly.SensorEntityID.String(),
eventOnly.SensorEventReadingType.SensorClass(), eventOnly.SensorType.String(), uint8(eventOnly.SensorType),
)
}
func parseSDREventOnly(data []byte, sdr *SDR) error {
const SDREventOnlyMinSize int = 17
minSize := SDREventOnlyMinSize
if len(data) < minSize {
return ErrNotEnoughDataWith("sdr (event-only sensor) min size", len(data), minSize)
}
s := &SDREventOnly{}
sdr.EventOnly = s
generatorID, _, _ := unpackUint16L(data, 5)
s.GeneratorID = GeneratorID(generatorID)
sensorNumber, _, _ := unpackUint8(data, 7)
s.SensorNumber = SensorNumber(sensorNumber)
b8, _, _ := unpackUint8(data, 8)
s.SensorEntityID = EntityID(b8)
b9, _, _ := unpackUint8(data, 9)
s.SensorEntityInstance = EntityInstance(b9 & 0x7f)
s.SensorEntityIsLogical = isBit7Set(b9)
sensorType, _, _ := unpackUint8(data, 10)
s.SensorType = SensorType(sensorType)
eventReadingType, _, _ := unpackUint8(data, 11)
s.SensorEventReadingType = EventReadingType(eventReadingType)
typeLength, _, _ := unpackUint8(data, 16)
s.IDStringTypeLength = TypeLength(typeLength)
idStrLen := int(s.IDStringTypeLength.Length())
if len(data) < minSize+idStrLen {
return ErrNotEnoughDataWith("sdr (event-only sensor)", len(data), minSize+idStrLen)
}
s.IDStringBytes, _, _ = unpackBytes(data, minSize, idStrLen)
return nil
}
// 43.4 SDR Type 08h - Entity Association Record
type SDREntityAssociation struct {
//
// Record KEY
//
ContainerEntityID uint8
ContainerEntityInstance uint8
// [7] - 0b = contained entities specified as list
// 1b = contained entities specified as range
ContainedEntitiesAsRange bool
// [6] - Record Link
// 0b = no linked Entity Association records
// 1b = linked Entity Association records exist
LinkedEntityAssociationExist bool
// [5] - 0b = Container entity and contained entities can be assumed absent
// if presence sensor for container entity cannot be accessed.
// This value is also used if the entity does not have a presence sensor.
// 1b = Presence sensor should always be accessible. Software should consider
// it an error if the presence sensor associated with the container entity
// is not accessible. If a presence sensor is accessible, then the
// presence sensor can still report that the container entity is absent.
PresenceSensorAlwaysAccessible bool
ContainedEntity1ID uint8
ContainedEntity1Instance uint8
//
// RECORD BODY
//
ContainedEntity2ID uint8
ContainedEntity2Instance uint8
ContainedEntity3ID uint8
ContainedEntity3Instance uint8
ContainedEntity4ID uint8
ContainedEntity4Instance uint8
}
func parseSDREntityAssociation(data []byte, sdr *SDR) error {
const SDREntityAssociationSize int = 16
if len(data) < SDREntityAssociationSize {
return ErrNotEnoughDataWith("sdr (entity association)", len(data), SDREntityAssociationSize)
}
s := &SDREntityAssociation{}
sdr.EntityAssociation = s
s.ContainerEntityID, _, _ = unpackUint8(data, 5)
s.ContainerEntityInstance, _, _ = unpackUint8(data, 6)
flag, _, _ := unpackUint8(data, 7)
s.ContainedEntitiesAsRange = isBit7Set(flag)
s.LinkedEntityAssociationExist = isBit6Set(flag)
s.PresenceSensorAlwaysAccessible = isBit5Set(flag)
s.ContainedEntity1ID, _, _ = unpackUint8(data, 8)
s.ContainedEntity1Instance, _, _ = unpackUint8(data, 9)
s.ContainedEntity2ID, _, _ = unpackUint8(data, 10)
s.ContainedEntity2Instance, _, _ = unpackUint8(data, 11)
s.ContainedEntity3ID, _, _ = unpackUint8(data, 12)
s.ContainedEntity3Instance, _, _ = unpackUint8(data, 13)
s.ContainedEntity4ID, _, _ = unpackUint8(data, 14)
s.ContainedEntity4Instance, _, _ = unpackUint8(data, 15)
return nil
}
// 43.5 SDR Type 09h - Device-relative Entity Association Record
type SDRDeviceRelative struct {
//
// Record KEY
//
ContainerEntityID uint8
ContainerEntityInstance uint8
ContainerEntityDeviceAddress uint8
ContainerEntityDeviceChannel uint8
// [7] - 0b = contained entities specified as list
// 1b = contained entities specified as range
ContainedEntitiesAsRange bool
// [6] - Record Link
// 0b = no linked Entity Association records
// 1b = linked Entity Association records exist
LinkedEntityAssociationExist bool
// [5] - 0b = Container entity and contained entities can be assumed absent
// if presence sensor for container entity cannot be accessed.
// This value is also used if the entity does not have a presence sensor.
// 1b = Presence sensor should always be accessible. Software should consider
// it an error if the presence sensor associated with the container entity
// is not accessible. If a presence sensor is accessible, then the
// presence sensor can still report that the container entity is absent.
PresenceSensorAlwaysAccessible bool
ContainedEntity1DeviceAddress uint8
ContainedEntity1DeviceChannel uint8
ContainedEntity1ID uint8
ContainedEntity1Instance uint8
//
// RECORD BODY
//
ContainedEntity2DeviceAddress uint8
ContainedEntity2DeviceChannel uint8
ContainedEntity2ID uint8
ContainedEntity2Instance uint8
ContainedEntity3DeviceAddress uint8
ContainedEntity3DeviceChannel uint8
ContainedEntity3ID uint8
ContainedEntity3Instance uint8
ContainedEntity4DeviceAddress uint8
ContainedEntity4DeviceChannel uint8
ContainedEntity4ID uint8
ContainedEntity4Instance uint8
}
func parseSDRDeviceRelativeEntityAssociation(data []byte, sdr *SDR) error {
const SDRDeviceRelativeEntityAssociationSize = 32
if len(data) < SDRDeviceRelativeEntityAssociationSize {
return ErrNotEnoughDataWith("sdr (device-relative entity association)", len(data), SDRDeviceRelativeEntityAssociationSize)
}
s := &SDRDeviceRelative{}
sdr.DeviceRelative = s
s.ContainerEntityID, _, _ = unpackUint8(data, 5)
s.ContainerEntityInstance, _, _ = unpackUint8(data, 6)
s.ContainerEntityDeviceAddress, _, _ = unpackUint8(data, 7)
s.ContainerEntityDeviceChannel, _, _ = unpackUint8(data, 8)
flag, _, _ := unpackUint8(data, 9)
s.ContainedEntitiesAsRange = isBit7Set(flag)
s.LinkedEntityAssociationExist = isBit6Set(flag)
s.PresenceSensorAlwaysAccessible = isBit5Set(flag)
s.ContainedEntity1DeviceAddress, _, _ = unpackUint8(data, 10)
s.ContainedEntity1DeviceChannel, _, _ = unpackUint8(data, 11)
s.ContainedEntity1ID, _, _ = unpackUint8(data, 12)
s.ContainedEntity1Instance, _, _ = unpackUint8(data, 13)
s.ContainedEntity2DeviceAddress, _, _ = unpackUint8(data, 14)
s.ContainedEntity2DeviceChannel, _, _ = unpackUint8(data, 15)
s.ContainedEntity2ID, _, _ = unpackUint8(data, 16)
s.ContainedEntity2Instance, _, _ = unpackUint8(data, 17)
s.ContainedEntity3DeviceAddress, _, _ = unpackUint8(data, 18)
s.ContainedEntity3DeviceChannel, _, _ = unpackUint8(data, 19)
s.ContainedEntity3ID, _, _ = unpackUint8(data, 20)
s.ContainedEntity3Instance, _, _ = unpackUint8(data, 21)
s.ContainedEntity4DeviceAddress, _, _ = unpackUint8(data, 22)
s.ContainedEntity4DeviceChannel, _, _ = unpackUint8(data, 23)
s.ContainedEntity4ID, _, _ = unpackUint8(data, 24)
s.ContainedEntity4Instance, _, _ = unpackUint8(data, 25)
unpackBytes(data, 26, 6) // last 6 bytes reserved
return nil
}
// 43.7 SDR Type 10h - Generic Device Locator Record
// This record is used to store the location and type information for devices
// on the IPMB or management controller private busses that are neither
// IPMI FRU devices nor IPMI management controllers.
//
// These devices can either be common non-intelligent I2C devices, special management ASICs, or proprietary controllers.
//
// IPMI FRU Devices and Management Controllers are located via the FRU Device Locator
// and Management Controller Device Locator records described in following sections.
type SDRGenericDeviceLocator struct {
//
// Record KEY
//
DeviceAccessAddress uint8 // Slave address of management controller used to access device. 0000000b if device is directly on IPMB
DeviceSlaveAddress uint8
ChannelNumber uint8 // Channel number for management controller used to access device
AccessLUN uint8 // LUN for Master Write-Read command. 00b if device is non-intelligent device directly on IPMB.
PrivateBusID uint8 // Private bus ID if bus = Private. 000b if device directly on IPMB
//
// RECORD BODY
//
AddressSpan uint8
DeviceType uint8
DeviceTypeModifier uint8
EntityID uint8
EntityInstance uint8
DeviceIDTypeLength TypeLength
DeviceIDString []byte // Short ID string for the device
}
func parseSDRGenericLocator(data []byte, sdr *SDR) error {
const SDRGenericLocatorMinSize = 16 // plus the ID String Bytes (optional 16 bytes maximum)
minSize := SDRGenericLocatorMinSize
if len(data) < minSize {
return ErrNotEnoughDataWith("sdr (generic-locator) min size", len(data), minSize)
}
s := &SDRGenericDeviceLocator{}
sdr.GenericDeviceLocator = s
s.DeviceAccessAddress, _, _ = unpackUint8(data, 5)
b, _, _ := unpackUint8(data, 6)
s.DeviceSlaveAddress = b
c, _, _ := unpackUint8(data, 7)
s.ChannelNumber = ((b & 0x01) << 4) | (c >> 5)
s.AccessLUN = (c & 0x1f) >> 3
s.PrivateBusID = (c & 0x07)
s.AddressSpan, _, _ = unpackUint8(data, 8)
s.DeviceType, _, _ = unpackUint8(data, 10)
s.DeviceTypeModifier, _, _ = unpackUint8(data, 11)
s.EntityID, _, _ = unpackUint8(data, 12)
s.EntityInstance, _, _ = unpackUint8(data, 13)
typeLength, _, _ := unpackUint8(data, 15)
s.DeviceIDTypeLength = TypeLength(typeLength)
idStrLen := int(s.DeviceIDTypeLength.Length())
if len(data) < minSize+idStrLen {
return ErrNotEnoughDataWith("sdr (generic-locator)", len(data), minSize+idStrLen)
}
s.DeviceIDString, _, _ = unpackBytes(data, minSize, idStrLen)
return nil
}
// 43.8 SDR Type 11h - FRU Device Locator Record
// 38. Accessing FRU Devices
type SDRFRUDeviceLocator struct {
//
// Record KEY
//
// [7:1] - Slave address of controller used to access device. 0000000b if device is directly on IPMB.
// This field indicates whether the device is on a private bus or not.
DeviceAccessAddress uint8
// FRU Device ID / Device Slave Address
//
// For Logical FRU DEVICE (accessed via FRU commands to mgmt. controller):
// [7:0] - Number identifying FRU device within given IPM Controller. FFh = reserved.
// The primary FRU device for a management controller is always device #0 at
// LUN 00b. The primary FRU device is not reported via this FRU Device Locator
// record - its presence is identified via the Device Capabilities field in the
// Management Controller Device Locator record.
//
// For non-intelligent FRU device:
// [7:1] - 7-bit I2C Slave Address
// This is relative to the bus the device is on.
// For devices on the IPMB, this is the slave address of the device on the IPMB.
// For devices on a private bus, this is the slave address of the device on the private bus.
// [0] - reserved
FRUDeviceID_SlaveAddress uint8
// [7] - logical/physical FRU device
// 0b = device is not a logical FRU Device (a physical device, that is a non-intelligent device)
// 1b = device is logical FRU Device (accessed via FRU commands to mgmt. controller)
IsLogicalFRUDevice bool
// [4:3] - LUN for Read/Write FRU Data Command or Master Write-Read command.
AccessLUN uint8
// [2:0] - Private bus ID if bus = Private.
// 000b if device directly on IPMB, or device is a logical FRU Device.
//
// three bits, total eight bus ids, 000 ~ 111, (0 ~ 7)
PrivateBusID uint8
// [7:4] - Channel number for management controller used to access device.
// 000b if device directly on the primary IPMB, or if controller is on the primary IPMB.
// Msbit for channel number is kept in next byte.
// (For IPMI v1.5. This byte position was reserved for IPMI v1.0.)
//
// [3:0] - reserved
ChannelNumber uint8
//
// RECORD BODY
//
DeviceType DeviceType
DeviceTypeModifier uint8
FRUEntityID uint8
FRUEntityInstance uint8
DeviceIDTypeLength TypeLength
DeviceIDBytes []byte // Short ID string for the FRU Device
}
// Table 38-1, FRU Device Locator Field Usage
func (sdrFRU *SDRFRUDeviceLocator) Location() FRULocation {
if sdrFRU.IsLogicalFRUDevice {
return FRULocation_MgmtController
}
if sdrFRU.DeviceAccessAddress == 0x00 {
return FRULocation_IPMB
}
return FRULocation_PrivateBus
}
func parseSDRFRUDeviceLocator(data []byte, sdr *SDR) error {
const SDRFRUDeviceLocatorMinSize = 16 // plus the ID String Bytes (optional 16 bytes maximum)
minSize := SDRFRUDeviceLocatorMinSize
if len(data) < minSize {
return ErrNotEnoughDataWith("sdr (fru device) min size", len(data), minSize)
}
s := &SDRFRUDeviceLocator{}
sdr.FRUDeviceLocator = s
b5, _, _ := unpackUint8(data, 5)
s.DeviceAccessAddress = b5
b7, _, _ := unpackUint8(data, 6)
// Todo
s.FRUDeviceID_SlaveAddress = b7
b8, _, _ := unpackUint8(data, 7)
s.IsLogicalFRUDevice = isBit7Set(b8)
s.AccessLUN = (b8 & 0x1f) >> 3
s.PrivateBusID = b8 & 0x07
b9, _, _ := unpackUint8(data, 8)
s.ChannelNumber = b9 >> 4
deviceType, _, _ := unpackUint8(data, 10)
s.DeviceType = DeviceType(deviceType)
s.DeviceTypeModifier, _, _ = unpackUint8(data, 11)
s.FRUEntityID, _, _ = unpackUint8(data, 12)
s.FRUEntityInstance, _, _ = unpackUint8(data, 13)
// index 14 Reserved for OEM use.
typeLength, _, _ := unpackUint8(data, 15)
s.DeviceIDTypeLength = TypeLength(typeLength)
var idStrLen int
if s.DeviceIDTypeLength.TypeCode() == 0x00 {
// unspecified type
idStrLen = len(data) - minSize
} else {
idStrLen = int(s.DeviceIDTypeLength.Length())
}
if len(data) < minSize+idStrLen {
return ErrNotEnoughDataWith("sdr (fru device)", len(data), minSize+idStrLen)
}
s.DeviceIDBytes, _, _ = unpackBytes(data, minSize, idStrLen)
return nil
}
// 43.9 SDR Type 12h - Management Controller Device Locator Record
type SDRMgmtControllerDeviceLocator struct {
//
// Record KEY
//
DeviceSlaveAddress uint8 // 7-bit I2C Slave Address[1] of device on channel
ChannelNumber uint8
//
// RECORD BODY
//
ACPISystemPowerStateNotificationRequired bool
ACPIDevicePowerStateNotificationRequired bool
ControllerLogsInitializationAgentErrors bool
LogInitializationAgentErrors bool
DeviceCap_ChassisDevice bool // device functions as chassis device
DeviceCap_Bridge bool // Controller responds to Bridge NetFn command
DeviceCap_IPMBEventGenerator bool // device generates event messages on IPMB
DeviceCap_IPMBEventReceiver bool // device accepts event messages from IPMB
DeviceCap_FRUInventoryDevice bool // accepts FRU commands to FRU Device #0 at LUN 00b
DeviceCap_SELDevice bool // provides interface to SEL
DeviceCap_SDRRepoDevice bool // For BMC, indicates BMC provides interface to 1b = SDR Repository. For other controller, indicates controller accepts Device SDR commands
DeviceCap_SensorDevice bool // device accepts sensor commands
EntityID uint8
EntityInstance uint8
DeviceIDTypeLength TypeLength
DeviceIDBytes []byte
}
func parseSDRManagementControllerDeviceLocator(data []byte, sdr *SDR) error {
const SDRManagementControllerDeviceLocatorMinSize = 16 // plus the ID String Bytes (optional 16 bytes maximum)
minSize := SDRManagementControllerDeviceLocatorMinSize
if len(data) < minSize {
return ErrNotEnoughDataWith("sdr (mgmt controller device locator) min size", len(data), minSize)
}
s := &SDRMgmtControllerDeviceLocator{}
sdr.MgmtControllerDeviceLocator = s
b6, _, _ := unpackUint8(data, 5)
s.DeviceSlaveAddress = b6
b7, _, _ := unpackUint8(data, 6)
s.ChannelNumber = b7
b8, _, _ := unpackUint8(data, 7)
s.ACPISystemPowerStateNotificationRequired = isBit7Set(b8)
s.ACPIDevicePowerStateNotificationRequired = isBit6Set(b8)
s.ControllerLogsInitializationAgentErrors = isBit3Set(b8)
s.LogInitializationAgentErrors = isBit2Set(b8)
b9, _, _ := unpackUint8(data, 8)
s.DeviceCap_ChassisDevice = isBit7Set(b9)
s.DeviceCap_Bridge = isBit6Set(b9)
s.DeviceCap_IPMBEventGenerator = isBit5Set(b9)
s.DeviceCap_IPMBEventReceiver = isBit4Set(b9)
s.DeviceCap_FRUInventoryDevice = isBit3Set(b9)
s.DeviceCap_SELDevice = isBit2Set(b9)
s.DeviceCap_SDRRepoDevice = isBit1Set(b9)
s.DeviceCap_SensorDevice = isBit0Set(b9)
s.EntityID, _, _ = unpackUint8(data, 12)
s.EntityInstance, _, _ = unpackUint8(data, 13)
typeLength, _, _ := unpackUint8(data, 15)
s.DeviceIDTypeLength = TypeLength(typeLength)
idStrLen := int(s.DeviceIDTypeLength.Length())
if len(data) < minSize+idStrLen {
return ErrNotEnoughDataWith("sdr (mgmt controller device locator)", len(data), minSize+idStrLen)
}
s.DeviceIDBytes, _, _ = unpackBytes(data, minSize, idStrLen)
return nil
}
// 43.10 SDR Type 13h - Management Controller Confirmation Record
type SDRMgmtControllerConfirmation struct {
//
// Record KEY
//
DeviceSlaveAddress uint8 // 7-bit I2C Slave Address[1] of device on IPMB.
DeviceID uint8
ChannelNumber uint8
DeviceRevision uint8
//
// RECORD BODY
//
FirmwareMajorRevision uint8 // [6:0] - Major Firmware Revision, binary encoded.
FirmwareMinorRevision uint8 // Minor Firmware Revision. BCD encoded.
// IPMI Version from Get Device ID command. Holds IPMI Command Specification
// Version. BCD encoded. 00h = reserved. Bits 7:4 hold the Least Significant digit of the
// revision, while bits 3:0 hold the Most Significant bits. E.g. a value of 01h indicates
// revision 1.0
MajorIPMIVersion uint8
MinorIPMIVersion uint8
ManufacturerID uint32 // 3 bytes only
ProductID uint16
DeviceGUID []byte // 16 bytes
}
func parseSDRManagementControllerConfirmation(data []byte, sdr *SDR) error {
const SDRManagementControllerConfirmationSize = 32
minSize := SDRManagementControllerConfirmationSize
if len(data) < minSize {
return ErrNotEnoughDataWith("sdr (mgmt controller confirmation) min size", len(data), minSize)
}
s := &SDRMgmtControllerConfirmation{}
sdr.MgmtControllerConfirmation = s
b6, _, _ := unpackUint8(data, 5)
s.DeviceSlaveAddress = b6
s.DeviceID, _, _ = unpackUint8(data, 6)
b8, _, _ := unpackUint8(data, 7)
s.ChannelNumber = b8 >> 4
s.DeviceRevision = b8 & 0x0f
b9, _, _ := unpackUint8(data, 8)
s.FirmwareMajorRevision = b9 & 0x7f
s.FirmwareMinorRevision, _, _ = unpackUint8(data, 9)
ipmiVersionBCD, _, _ := unpackUint8(data, 10)
s.MajorIPMIVersion = ipmiVersionBCD & 0x0f
s.MinorIPMIVersion = ipmiVersionBCD >> 4
s.ManufacturerID, _, _ = unpackUint24L(data, 11)
s.ProductID, _, _ = unpackUint16L(data, 14)
s.DeviceGUID, _, _ = unpackBytes(data, 16, 16)
return nil
}
// 43.11 SDR Type 14h - BMC Message Channel Info Record
type SDRBMCChannelInfo struct {
//
// NO Record KEY
//
//
// RECORD BODY
//
Channel0 ChannelInfo
Channel1 ChannelInfo
Channel2 ChannelInfo
Channel3 ChannelInfo
Channel4 ChannelInfo
Channel5 ChannelInfo
Channel6 ChannelInfo
Channel7 ChannelInfo
MessagingInterruptType uint8
EventMessageBufferInterruptType uint8
}
type ChannelInfo struct {
TransmitSupported bool // false means receive message queue access only
MessageReceiveLUN uint8
ChannelProtocol uint8
}
func parseChannelInfo(b uint8) ChannelInfo {
return ChannelInfo{
TransmitSupported: isBit7Set(b),
MessageReceiveLUN: (b & 0x7f) >> 4,
ChannelProtocol: b & 0x0f,
}
}
func parseSDRBMCMessageChannelInfo(data []byte, sdr *SDR) error {
const SDRBMCMessageChannelInfoSize = 16
minSize := SDRBMCMessageChannelInfoSize
if len(data) < minSize {
return ErrNotEnoughDataWith("sdr (bmc message channel info) min size", len(data), minSize)
}
s := &SDRBMCChannelInfo{}
sdr.BMCChannelInfo = s
s.Channel0 = parseChannelInfo(data[5])
s.Channel1 = parseChannelInfo(data[6])
s.Channel2 = parseChannelInfo(data[7])
s.Channel3 = parseChannelInfo(data[8])
s.Channel4 = parseChannelInfo(data[9])
s.Channel5 = parseChannelInfo(data[10])
s.Channel6 = parseChannelInfo(data[11])
s.Channel7 = parseChannelInfo(data[12])
s.MessagingInterruptType, _, _ = unpackUint8(data, 13)
s.EventMessageBufferInterruptType, _, _ = unpackUint8(data, 14)
return nil
}
// 43.12 SDR Type C0h - OEM Record
type SDROEM struct {
//
// NO Record KEY
//
//
// RECORD BODY
//
ManufacturerID uint32 // 3 bytes only
OEMData []byte
}
func parseSDROEM(data []byte, sdr *SDR) error {
const SDROEMMinSize = 8
const SDROEMMaxSize = 64 // OEM defined records are limited to a maximum of 64 bytes, including the header
if len(data) < SDROEMMinSize {
return ErrNotEnoughDataWith("sdr (oem) min size", len(data), SDROEMMinSize)
}
s := &SDROEM{}
sdr.OEM = s
s.ManufacturerID, _, _ = unpackUint24L(data, 5)
s.OEMData, _, _ = unpackBytesMost(data, 8, SDROEMMaxSize-8)
return nil
}
// 43.6 SDR Type 0Ah:0Fh - Reserved Records
type SDRReserved struct {
}
// 43.15 Type/Length Byte Format
//
// 7:6 00 = Unicode
// 00b define a Unicode string in the IPMI specification,
// whereas they specify a binary field in the Platform Management FRU specification.
// 01 = BCD plus (see below)
// 10 = 6-bit ASCII, packed
// 11 = 8-bit ASCII + Latin 1.
// At least two bytes of data must be present when this type is used.
// Therefore, the length (number of data bytes) will be >1 if data is present,
// 0 if data is not present. A length of 1 is reserved.
// 5 reserved.
// the bit 5 is reserved in the IPMI specification type/length byte,
// where it is part of the length field in the Platform Management FRU specification
// 4:0 length of following data, in characters.
// 00000b indicates 'none following'.
// 11111b = reserved.
type TypeLength uint8
func (tl TypeLength) String() string {
return fmt.Sprintf("Byte: (%#02x) / Type: (%s) / Length: %d / Size: %d", uint8(tl), tl.Type(), tl.Length(), tl.Size())
}
func (tl TypeLength) Type() string {
typecode := tl.TypeCode()
var s string
switch typecode {
case 0:
s = "Binary"
case 1:
s = "BCD plus"
case 2:
s = "6-bit ASCII"
case 3:
s = "8-bit ASCII"
}
return s
}
func (tl TypeLength) TypeCode() uint8 {
return (uint8(tl) & 0xc0) >> 6 // the highest 2 bits
}
// Length returns the length of bytes occupied that packed the chars.
// But it is not the length of chars.
// For BCD plus type, one byte packs two chars.
func (tl TypeLength) Length() uint8 {
return uint8(tl) & 0x3f // the lowest 6 bits
}
// Size returns the length of chars.
func (tl TypeLength) Size() uint8 {
typecode := tl.TypeCode()
l := tl.Length()
var size uint8
switch typecode {
case 0: /* 00b: binary data */
size = l
case 1: /* 01b: BCD plus (binary-coded decimal) */
// one byte packs two chars
/* hex dump or BCD -> 2x length */
size = l * 2
case 2: /* 10b: 6-bit ASCII packed */
// three bytes packs four chars
/* 4 chars per group of 1-3 bytes, round up to 4 bytes boundary */
size = (l/3 + 1) * 4
case 3: /* 11b: 8-bit ASCII + Latin 1 */
/* no length adjustment */
size = l
}
return size
}
// Chars decodes the raw bytes to ASCII chars according to the encoding type code of TypeLength
func (tl TypeLength) Chars(raw []byte) (chars []byte, err error) {
if len(raw) != int(tl.Length()) {
err = fmt.Errorf("passed raw not equal to length")
return
}
size := int(tl.Size())
chars = make([]byte, size)
switch tl.TypeCode() {
case 0: // 00b - Binary
for i := 0; i < size; i++ {
chars[i] = raw[i]
}
case 1: // 01b - BCD Plus
var bcdPlusChars = [16]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '-', '.', ':', ',', '_'}
for i := 0; i < size; i++ {
var charIndex uint8
if i%2 == 0 {
charIndex = raw[i/2] >> 0 & 0x0f
} else {
charIndex = raw[i/2] >> 4
}
chars[i] = bcdPlusChars[charIndex]
}
case 2: // 10b - 6-bit ASCII
// 6-bit ASCII definition
var ascii6bit = [64]byte{
' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
}
var leftover byte
var s []byte
for i := 0; i < len(raw); i++ {
// every 3 bytes pack 4 chars, so we can calculate
// character positions in a byte based on the remainder of division by 3.
switch i % 3 {
case 0:
idx := raw[i] & 0x3f // 6 right bits are an index of one char
leftover = (raw[i] & 0xc0) >> 6 // 2 left bits are leftovers
s = append(s, ascii6bit[idx])
case 1:
idx := leftover | (raw[i]&0x0f)<<2 // index of one char is 2-bit leftover as prefix plus 4 right bits
leftover = (raw[i] & 0xf0) >> 4 // 4 left bits are leftovers
s = append(s, ascii6bit[idx])
case 2:
idx := (raw[i]&0x03)<<4 | leftover // index of one char is 2 right bits plus 4-bit leftover as suffix
leftover = 0 // cleanup leftover calculation
s = append(s, ascii6bit[idx])
idx = (raw[i] & 0xfc) >> 2 // 6 left bits are an index of one char
s = append(s, ascii6bit[idx])
}
}
chars = s
case 3: // 11b - 8-bit ASCII
for i := 0; i < size; i++ {
chars[i] = raw[i]
}
}
return
}
golang-github-bougou-go-ipmi-0.7.2/types_sdr_others_test.go 0000664 0000000 0000000 00000006012 14741105271 0024073 0 ustar 00root root 0000000 0000000 package ipmi
import (
"reflect"
"testing"
)
func TestTypeLength_Chars(t *testing.T) {
t.Parallel()
type args struct {
raw []byte
}
tests := []struct {
name string
tl TypeLength
args args
wantChars []byte
wantErr bool
}{
{
name: "empty tl & raw",
tl: 0x00,
args: args{raw: []byte{}},
wantChars: []byte{},
wantErr: false,
},
{
name: "different length for tl & raw",
tl: 0xc0,
args: args{raw: []byte{57, 84}},
wantChars: nil,
wantErr: true,
},
{
name: "valid 8-bit ASCII",
tl: 0xcd,
args: args{raw: []byte{89, 49, 85, 85, 66, 51, 79, 71, 88, 89, 48, 75, 70}},
// cSpell: disable
wantChars: []byte("Y1UUB3OGXY0KF"),
// cSpell: enable
wantErr: false,
},
{
name: "untrimmed 8-bit ASCII",
tl: 0xc8,
args: args{raw: []byte{83, 97, 109, 115, 117, 110, 103, 0}},
wantChars: []byte{83, 97, 109, 115, 117, 110, 103, 0}, // "Samsung\0"
wantErr: false,
},
{
// Every 3 bytes contains 4 chars.
// 'Y' in 6-bit ASCII is 111001
// Three 'Y's are 01111001 10011110 00000011
name: "3-symbol word (empty 4th char) 6-bit ASCII",
tl: 0x83,
args: args{raw: []byte{121, 158, 3}},
wantChars: []byte("YYY "),
wantErr: false,
},
{
// Four 'Y's are 01111001 10011110 11100111
name: "4-symbol word (full 3 bytes) 6-bit ASCII",
tl: 0x83,
args: args{raw: []byte{121, 158, 231}},
wantChars: []byte("YYYY"),
wantErr: false,
},
{
// Five 'Y's are 01111001 10011110 11100111 00111001
name: "5-symbol word (not a multiple of 3 bytes) 6-bit ASCII",
tl: 0x84,
args: args{raw: []byte{121, 158, 231, 57}},
wantChars: []byte("YYYYY"),
wantErr: false,
},
{
// Six 'Y's are 01111001 10011110 11100111 01111001 00001110
name: "6-symbol word (not a multiple of 3 bytes) 6-bit ASCII",
tl: 0x85,
args: args{raw: []byte{121, 158, 231, 121, 14}},
wantChars: []byte("YYYYYY"),
wantErr: false,
},
{
// Seven 'Y's are 01111001 10011110 11100111 01111001 10011110 00000011
name: "7-symbol word (empty 8th char) 6-bit ASCII",
tl: 0x86,
args: args{raw: []byte{121, 158, 231, 121, 158, 3}},
wantChars: []byte("YYYYYYY "),
wantErr: false,
},
{
name: "valid 6-bit ASCII",
tl: 0x8a,
args: args{raw: []byte{57, 100, 143, 34, 69, 89, 82, 13, 73, 16}},
wantChars: []byte{89, 48, 86, 67, 66, 52, 52, 54, 50, 85, 48, 50, 48}, // Y0VCB4462U020
wantErr: false,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
gotChars, err := tt.tl.Chars(tt.args.raw)
if (err != nil) != tt.wantErr {
t.Errorf("TypeLength.Chars() error = %v, wantErr %v", err, tt.wantErr)
}
if !reflect.DeepEqual(gotChars, tt.wantChars) {
t.Errorf("TypeLength.Chars() = %#v (%s), want %#v (%s)", gotChars, string(gotChars), tt.wantChars, string(tt.wantChars))
}
})
}
}
golang-github-bougou-go-ipmi-0.7.2/types_sel.go 0000664 0000000 0000000 00000017764 14741105271 0021463 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"fmt"
"time"
"github.com/olekukonko/tablewriter"
)
// 32. SEL Record Formats
type SEL struct {
// SEL Record IDs 0000h and FFFFh are reserved for functional use and are not legal ID values.
// Record IDs are handles. They are not required to be sequential or consecutive.
// Applications should not assume that SEL Record IDs will follow any particular numeric ordering.
RecordID uint16
RecordType SELRecordType
Standard *SELStandard
OEMTimestamped *SELOEMTimestamped
OEMNonTimestamped *SELOEMNonTimestamped
}
func (sel *SEL) Pack() []byte {
msg := make([]byte, 16)
packUint16L(sel.RecordID, msg, 0)
packUint8(uint8(sel.RecordType), msg, 2)
switch sel.RecordType.Range() {
case SELRecordTypeRangeStandard:
if sel.Standard != nil {
msg = append(msg[0:3], sel.Standard.Pack()...)
}
case SELRecordTypeRangeTimestampedOEM:
if sel.OEMTimestamped != nil {
msg = append(msg[0:3], sel.OEMTimestamped.Pack()...)
}
case SELRecordTypeRangeNonTimestampedOEM:
if sel.OEMNonTimestamped != nil {
msg = append(msg[0:3], sel.OEMNonTimestamped.Pack()...)
}
}
return msg
}
func ParseSEL(msg []byte) (*SEL, error) {
if len(msg) != 16 {
return nil, fmt.Errorf("SEL Record msg should be 16 bytes in length")
}
recordID, _, _ := unpackUint16L(msg, 0)
recordType, _, _ := unpackUint8(msg, 2)
sel := &SEL{
RecordID: recordID,
RecordType: SELRecordType(recordType),
}
recordTypeRange := sel.RecordType.Range()
switch recordTypeRange {
case SELRecordTypeRangeStandard:
if err := parseSELDefault(msg, sel); err != nil {
return nil, fmt.Errorf("parseSELDefault failed, err: %w", err)
}
case SELRecordTypeRangeTimestampedOEM:
if err := parseSELOEMTimestamped(msg, sel); err != nil {
return nil, fmt.Errorf("parseSELOEMTimestamped failed, err: %w", err)
}
case SELRecordTypeRangeNonTimestampedOEM:
if err := parseSELOEMNonTimestamped(msg, sel); err != nil {
return nil, fmt.Errorf("parseSELOEMNonTimestamped failed, err: %w", err)
}
}
return sel, nil
}
// 32.2 OEM SEL Record - Type C0h-DFh
type SELOEMTimestamped struct {
Timestamp time.Time // Time when event was logged. uint32 LS byte first.
ManufacturerID uint32 // only 3 bytes
OEMDefined [6]byte
}
func (oemTimestamped *SELOEMTimestamped) Pack() []byte {
var msg = make([]byte, 13)
packUint32L(uint32(oemTimestamped.Timestamp.Unix()), msg, 0)
packUint24L(oemTimestamped.ManufacturerID, msg, 4)
packBytes(oemTimestamped.OEMDefined[:], msg, 7)
return msg
}
type SELOEMNonTimestamped struct {
OEM [13]byte
}
func (oemNonTimestamped *SELOEMNonTimestamped) Pack() []byte {
return oemNonTimestamped.OEM[:]
}
// 32.1 SEL Standard Event Records
type SELStandard struct {
Timestamp time.Time // Time when event was logged. uint32 LS byte first.
GeneratorID GeneratorID // RqSA & LUN if event was generated from IPMB. Software ID if event was generated from system software.
EvMRev uint8 // Event Message Revision (format version)
SensorType SensorType // Sensor Type Code for sensor that generated the event
SensorNumber SensorNumber // Number of sensor that generated the event
EventDir EventDir // Event Direction. [7] -0b = Assertion event. 1b = Deassertion event.
EventReadingType EventReadingType // Type of trigger for the event. [6:0] - Event Type Code
// 29.7 Event Data Field Formats
//
// The sensor class determines the corresponding Event Data format.
// The sensor class can be extracted from EventReadingType.
EventData EventData
}
func (standard *SELStandard) Pack() []byte {
var msg = make([]byte, 13)
packUint32L(uint32(standard.Timestamp.Unix()), msg, 0)
packUint16L(uint16(standard.GeneratorID), msg, 4)
packUint8(standard.EvMRev, msg, 6)
packUint8(uint8(standard.SensorType), msg, 7)
packUint8(uint8(standard.SensorNumber), msg, 8)
var eventType = uint8(standard.EventReadingType)
if standard.EventDir {
eventType = eventType | 0x80
}
packUint8(eventType, msg, 9)
packUint8(standard.EventData.EventData1, msg, 10)
packUint8(standard.EventData.EventData2, msg, 11)
packUint8(standard.EventData.EventData3, msg, 12)
return msg
}
// EventString return string description of the event.
func (sel *SELStandard) EventString() string {
return sel.EventReadingType.EventString(sel.SensorType, sel.EventData)
}
func (sel *SELStandard) EventSeverity() EventSeverity {
return sel.EventReadingType.EventSeverity(sel.SensorType, sel.EventData, sel.EventDir)
}
func parseSELDefault(msg []byte, sel *SEL) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
var s = &SELStandard{}
sel.Standard = s
ts, _, _ := unpackUint32L(msg, 3)
s.Timestamp = parseTimestamp(ts)
gid, _, _ := unpackUint16L(msg, 7)
s.GeneratorID = GeneratorID(gid)
s.EvMRev, _, _ = unpackUint8(msg, 9)
sensorType, _, _ := unpackUint8(msg, 10)
s.SensorType = SensorType(sensorType)
sensorNumber, _, _ := unpackUint8(msg, 11)
s.SensorNumber = SensorNumber(sensorNumber)
b, _, _ := unpackUint8(msg, 12)
s.EventDir = EventDir(isBit7Set(b))
s.EventReadingType = EventReadingType(b & 0x7f) // clear bit 7
s.EventData.EventData1, _, _ = unpackUint8(msg, 13)
s.EventData.EventData2, _, _ = unpackUint8(msg, 14)
s.EventData.EventData3, _, _ = unpackUint8(msg, 15)
return nil
}
func parseSELOEMTimestamped(msg []byte, sel *SEL) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
var s = &SELOEMTimestamped{}
sel.OEMTimestamped = s
ts, _, _ := unpackUint32L(msg, 3)
s.Timestamp = parseTimestamp(ts)
id, _, _ := unpackUint24L(msg, 7)
s.ManufacturerID = id
s.OEMDefined = [6]byte{}
b, _, _ := unpackBytes(msg, 10, 6)
for i := 0; i < 6; i++ {
s.OEMDefined[i] = b[i]
}
return nil
}
func parseSELOEMNonTimestamped(msg []byte, sel *SEL) error {
if len(msg) < 16 {
return ErrUnpackedDataTooShortWith(len(msg), 16)
}
var s = &SELOEMNonTimestamped{}
sel.OEMNonTimestamped = s
s.OEM = [13]byte{}
b, _, _ := unpackBytes(msg, 3, 13)
for i := 0; i < 6; i++ {
s.OEM[i] = b[i]
}
return nil
}
// FormatSELs print sel records in table format.
// The second sdrMap is optional. If the sdrMap is not nil,
// it will also print sensor number, entity id and instance, and asserted discrete states.
// The sdrMap can be fetched by GetSDRsMap method.
func FormatSELs(records []*SEL, sdrMap SDRMapBySensorNumber) string {
var elistMode bool // extend list
if sdrMap != nil {
elistMode = true
}
var buf = new(bytes.Buffer)
table := tablewriter.NewWriter(buf)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_RIGHT)
headers := []string{
"ID",
"RecordType",
"EvmRev",
"Timestamp",
"GID",
"SensorNumber",
"SensorTypeCode",
"SensorType",
"EventReadingType",
"EventReadingType",
"EventDescription",
"EventDir",
"EventSeverity",
"EventData",
}
if elistMode {
headers = append(headers, "SensorName")
}
table.SetHeader(headers)
table.SetFooter(headers)
for _, sel := range records {
recordTypeRange := sel.RecordType.Range()
switch recordTypeRange {
case SELRecordTypeRangeStandard:
s := sel.Standard
rowContent := []string{
fmt.Sprintf("%#04x", sel.RecordID),
sel.RecordType.String(),
fmt.Sprintf("%#02x", s.EvMRev),
fmt.Sprintf("%v", s.Timestamp),
fmt.Sprintf("%#04x", s.GeneratorID),
fmt.Sprintf("%#02x", s.SensorNumber),
fmt.Sprintf("%#02x", uint8(s.SensorType)),
s.SensorType.String(),
fmt.Sprintf("%#02x", uint8(s.EventReadingType)),
s.EventReadingType.String(),
s.EventString(),
s.EventDir.String(),
string(s.EventSeverity()),
s.EventData.String(),
}
if elistMode {
var sensorName string
sdr, ok := sdrMap[s.GeneratorID][s.SensorNumber]
if !ok {
sensorName = fmt.Sprintf("N/A %#04x, %#02x", s.GeneratorID, s.SensorNumber)
} else {
sensorName = sdr.SensorName()
}
rowContent = append(rowContent, sensorName)
}
table.Append(rowContent)
case SELRecordTypeRangeTimestampedOEM:
case SELRecordTypeRangeNonTimestampedOEM:
}
}
table.Render()
return buf.String()
}
golang-github-bougou-go-ipmi-0.7.2/types_sensor.go 0000664 0000000 0000000 00000116362 14741105271 0022203 0 ustar 00root root 0000000 0000000 package ipmi
import (
"bytes"
"fmt"
"math"
"strings"
"github.com/olekukonko/tablewriter"
)
// 42.1
// Sensors are classified according to the type of readings they provide and/or the type of events they generate.
//
// Three sensor classes: threshold, discrete, oem
// (oem is a special case of discrete)
//
// A sensor can return either an analog or discrete readings. Sensor events can be discrete or threshold-based.
// Valid sensorclass string values are:
// "N/A", "threshold", "discrete", "oem"
type SensorClass string
const (
SensorClassNotApplicable SensorClass = "N/A" // 不适用的
SensorClassThreshold SensorClass = "threshold"
// 离散 multiple states possible
// Discrete sensors can contain up to 15 possible states.
// It is possible for a discrete sensor to have more than one state active at a time
SensorClassDiscrete SensorClass = "discrete"
// A digital sensor is not really a unique class, but a term commonly used to refer to
// special case of a discrete sensor that only has two possible states
// SensorClassDigitalDiscrete SensorClass = "digital-discrete"
// Special case of discrete where the meaning of the states (offsets) are OEM defined.
SensorClassOEM SensorClass = "oem"
)
// 41.1 Sensor Type Code
// 42.2 Sensor Type Codes and Data
type SensorType uint8
func (c SensorType) String() string {
s, ok := sensorTypeMap[c]
if ok {
return s
}
return "unknown"
}
const (
SensorTypeReserved SensorType = 0x00
SensorTypeTemperature SensorType = 0x01 // 温度传感器
SensorTypeVoltage SensorType = 0x02 // 电压传感器
SensorTypeCurrent SensorType = 0x03 // 电流传感器
SensorTypeFan SensorType = 0x04 // 风扇传感器
SensorTypePhysicalSecurity SensorType = 0x05 // Chassis Intrusion
SensorTypePlatformSecurity SensorType = 0x06
SensorTypeProcessor SensorType = 0x07
SensorTypePowerSupply SensorType = 0x08
SensorTypePowerUnit SensorType = 0x09
SensorTypeCollingDevice SensorType = 0x0a
SensorTypeOtherUnitsbased SensorType = 0x0b
SensorTypeMemory SensorType = 0x0c
SensorTypeDriveSlot SensorType = 0x0d
SensorTypePostMemoryResize SensorType = 0x0e
SensorTypeSystemFirmwareProgress SensorType = 0x0f
SensorTypeEventLoggingDisabled SensorType = 0x10
SensorTypeWatchdog1 SensorType = 0x11
SensorTypeSystemEvent SensorType = 0x12
SensorTypeCriticalInterrupt SensorType = 0x13
SensorTypeButtonSwitch SensorType = 0x14
SensorTypeModuleBoard SensorType = 0x15
SensorTypeMicrocontrollerCoprocessor SensorType = 0x16
SensorTypeAddinCard SensorType = 0x17
SensorTypeChassis SensorType = 0x18
SensorTypeChipSet SensorType = 0x19
SensorTypeOtherFRU SensorType = 0x1a
SensorTypeCableInterconnect SensorType = 0x1b
SensorTypeTerminator SensorType = 0x1c
SensorTypeSystemBootRestartInitiated SensorType = 0x1d
SensorTypeBootError SensorType = 0x1e
SensorTypeBaseOSBootInstallationStatus SensorType = 0x1f
SensorTypeOSStopShutdown SensorType = 0x20
SensorTypeSlotConnector SensorType = 0x21
SensorTypeSystemACPIPowerState SensorType = 0x22
SensorTypeWatchdog2 SensorType = 0x23
SensorTypePlatformAlert SensorType = 0x24
SensorTypeEntityPresence SensorType = 0x25
SensorTypeMonitorASIC SensorType = 0x26
SensorTypeLAN SensorType = 0x27
SensorTypeManagementSubsystemHealth SensorType = 0x28
SensorTypeBattery SensorType = 0x29
SensorTypeSessionAudit SensorType = 0x2a
SensorTypeVersionChange SensorType = 0x2b
SensorTypeFRUState SensorType = 0x2c
// Reserved: 0x2D - 0xBF
// OEM Reserved: 0xC0 - 0xFF
)
var sensorTypeMap = map[SensorType]string{
0x00: "Reserved",
0x01: "Temperature",
0x02: "Voltage",
0x03: "Current",
0x04: "Fan",
0x05: "Physical Security",
0x06: "Platform Security",
0x07: "Processor",
0x08: "Power Supply",
0x09: "Power Unit",
0x0a: "Cooling Device",
0x0b: "Other",
0x0c: "Memory",
0x0d: "Drive Slot / Bay",
0x0e: "POST Memory Resize",
0x0f: "System Firmwares",
0x10: "Event Logging Disabled",
0x11: "Watchdog1",
0x12: "System Event",
0x13: "Critical Interrupt",
0x14: "Button",
0x15: "Module / Board",
0x16: "Microcontroller",
0x17: "Add-in Card",
0x18: "Chassis",
0x19: "Chip Set",
0x1a: "Other FRU",
0x1b: "Cable / Interconnect",
0x1c: "Terminator",
0x1d: "System Boot Initiated",
0x1e: "Boot Error",
0x1f: "OS Boot",
0x20: "OS Critical Stop",
0x21: "Slot / Connector",
0x22: "System ACPI Power State",
0x23: "Watchdog2",
0x24: "Platform Alert",
0x25: "Entity Presence",
0x26: "Monitor ASIC",
0x27: "LAN",
0x28: "Management Subsys Health",
0x29: "Battery",
0x2a: "Session Audit",
0x2b: "Version Change",
0x2c: "FRU State",
}
func SensorTypeFromNameOrNumber(sensorTypeNameOrNumber string) (SensorType, error) {
sensorTypeNumber, err := parseStringToInt64(sensorTypeNameOrNumber)
if err == nil {
// arg is number
_, exists := sensorTypeMap[SensorType(sensorTypeNumber)]
if exists {
return SensorType(sensorTypeNumber), nil
}
return SensorTypeReserved, fmt.Errorf("unknown sensor type number: %s", sensorTypeNameOrNumber)
}
for number, name := range sensorTypeMap {
if name == sensorTypeNameOrNumber {
return SensorType(number), nil
}
}
return SensorTypeReserved, fmt.Errorf("unknown sensor type name: %s", sensorTypeNameOrNumber)
}
// 43.17 Sensor Unit Type Codes
type SensorUnitType uint8
const (
SensorUnitType_Unspecified SensorUnitType = 0 // unspecified
SensorUnitType_DegreesC SensorUnitType = 1 // degrees C, Celsius, 摄氏度 ℃
SensorUnitType_DegreesF SensorUnitType = 2 // degrees F, Fahrenheit, 华氏度
SensorUnitType_DegreesK SensorUnitType = 3 // degrees K, Kelvins, 开尔文
SensorUnitType_Volts SensorUnitType = 4 // Volts, 伏特(电压单位)
SensorUnitType_Amps SensorUnitType = 5 // Amps, 安培数
SensorUnitType_Watts SensorUnitType = 6 // Watts, 瓦特(功率单位)
SensorUnitType_Joules SensorUnitType = 7 // Joules, 焦耳
SensorUnitType_Coulombs SensorUnitType = 8 // Coulombs, 库伦
SensorUnitType_VA SensorUnitType = 9 // VA, 伏安
SensorUnitType_Nits SensorUnitType = 10 // Nits, 尼特(光度单位)
SensorUnitType_Lumen SensorUnitType = 11 // lumen, 流明(光通量单位)
SensorUnitType_Lux SensorUnitType = 12 // lux, 勒克斯(照明单位)
SensorUnitType_Candela SensorUnitType = 13 // Candela, 坎, 坎德拉(发光强度单位)
SensorUnitType_KPa SensorUnitType = 14 // kPa kilopascal, 千帕, 千帕斯卡
SensorUnitType_PSI SensorUnitType = 15 // PSI
SensorUnitType_Newton SensorUnitType = 16 // Newton, 牛顿(力的单位)
SensorUnitType_CFM SensorUnitType = 17 // CFM, 风量, cubic feet per minute (cu ft/min)
SensorUnitType_RPM SensorUnitType = 18 // RPM, 每分钟转数, Revolutions per minute, is the number of turns in one minute
SensorUnitType_Hz SensorUnitType = 19 // Hz, 赫兹
SensorUnitType_MicroSecond SensorUnitType = 20 // microsecond, 微秒
SensorUnitType_MilliSecond SensorUnitType = 21 // millisecond, 毫秒
SensorUnitType_Second SensorUnitType = 22 // second, 秒
SensorUnitType_Minute SensorUnitType = 23 // minute, 分
SensorUnitType_Hour SensorUnitType = 24 // hour, 时
SensorUnitType_Day SensorUnitType = 25 // day, 日
SensorUnitType_Week SensorUnitType = 26 // week, 周
SensorUnitType_Mil SensorUnitType = 27 // mil, 毫升;密耳(千分之一寸)
SensorUnitType_Inches SensorUnitType = 28 // inches, 英寸(inch的复数)
SensorUnitType_Fleet SensorUnitType = 29 // feet
SensorUnitType_CuIn SensorUnitType = 30 // cu in, 立方英寸(cubic inch)
SensorUnitType_CuFleet SensorUnitType = 31 // cu feet
SensorUnitType_MM SensorUnitType = 32 // mm, 毫米(millimeter)
SensorUnitType_CM SensorUnitType = 33 // cm, 厘米(centimeter)
SensorUnitType_M SensorUnitType = 34 // m, 米
SensorUnitType_CuCM SensorUnitType = 35 // cu cm
SensorUnitType_Cum SensorUnitType = 36 // cum
SensorUnitType_Liters SensorUnitType = 37 // liters, 公升(容量单位)
SensorUnitType_FluidOunce SensorUnitType = 38 // fluid ounce, 液盎司(液体容量单位, 等于 fluidounce)
SensorUnitType_Radians SensorUnitType = 39 // radians, 弧度(radian的复数)
SensorUnitType_vSteradians SensorUnitType = 40 // steradians, 球面度, 立体弧度(立体角国际单位制, 等于 sterad)
SensorUnitType_Revolutions SensorUnitType = 41 // revolutions, 转数(revolution的复数形式)
SensorUnitType_Cycles SensorUnitType = 42 // cycles, 周期, 圈
SensorUnitType_Gravities SensorUnitType = 43 // gravities, 重力
SensorUnitType_Ounce SensorUnitType = 44 // ounce, 盎司
SensorUnitType_Pound SensorUnitType = 45 // pound, 英镑
SensorUnitType_FootPound SensorUnitType = 46 // ft-lb, 英尺-磅(foot pound)
SensorUnitType_OzIn SensorUnitType = 47 // oz-in, 扭力;盎司英寸
SensorUnitType_Gauss SensorUnitType = 48 // gauss, 高斯(磁感应或磁场的单位)
SensorUnitType_Gilberts SensorUnitType = 49 // gilberts, 吉伯(磁通量的单位)
SensorUnitType_Henry SensorUnitType = 50 // henry, 亨利(电感单位)
SensorUnitType_MilliHenry SensorUnitType = 51 // millihenry, 毫亨(利)(电感单位)
SensorUnitType_Farad SensorUnitType = 52 // farad, 法拉(电容单位)
SensorUnitType_MicroFarad SensorUnitType = 53 // microfarad, 微法拉(电容量的实用单位)
SensorUnitType_Ohms SensorUnitType = 54 // ohms, 欧姆(Ohm) :电阻的量度单位, 欧姆值越大, 电阻越大
SensorUnitType_Siemens SensorUnitType = 55 // siemens, 西门子, 电导单位
SensorUnitType_Mole SensorUnitType = 56 // mole, 摩尔 [化学] 克分子(等于mole)
SensorUnitType_Becquerel SensorUnitType = 57 // becquerel, 贝可(放射性活度单位)
SensorUnitType_PPM SensorUnitType = 58 // PPM (parts/million), 百万分率, 百万分之…(parts per million)
SensorUnitType_Reserved SensorUnitType = 59 // reserved
SensorUnitType_Decibels SensorUnitType = 60 // Decibels, 分贝(声音强度单位, decibel的复数)
SensorUnitType_DbA SensorUnitType = 61 // DbA, dBA is often used to specify the loudness of the fan used to cool the microprocessor and associated components. Typical dBA ratings are in the neighborhood of 25 dBA, representing 25 A-weighted decibels above the threshold of hearing. This is approximately the loudness of a person whispering in a quiet room.
SensorUnitType_DbC SensorUnitType = 62 // DbC
SensorUnitType_Gray SensorUnitType = 63 // gray, 核吸收剂量(Gy)
SensorUnitType_Sievert SensorUnitType = 64 // sievert, 希沃特(辐射效果单位, 简称希)
SensorUnitType_ColorTempDegK SensorUnitType = 65 // color temp deg K, 色温
SensorUnitType_Bit SensorUnitType = 66 // bit, 比特(二进位制信息单位)
SensorUnitType_Kilobit SensorUnitType = 67 // kilobit, 千比特
SensorUnitType_Megabit SensorUnitType = 68 // megabit, 兆比特
SensorUnitType_Gigabit SensorUnitType = 69 // gigabit, 吉比特
SensorUnitType_Byte SensorUnitType = 70 // byte, 字节
SensorUnitType_Kilobyte SensorUnitType = 71 // kilobyte, 千字节
SensorUnitType_Megabyte SensorUnitType = 72 // megabyte, 兆字节
SensorUnitType_Gigabyte SensorUnitType = 73 // gigabyte, 吉字节
SensorUnitType_Word SensorUnitType = 74 // word (data), 字
SensorUnitType_DWord SensorUnitType = 75 // dword, 双字
SensorUnitType_QWord SensorUnitType = 76 // qword, 四字
SensorUnitType_Line SensorUnitType = 77 // line (re. mem. line)
SensorUnitType_Hit SensorUnitType = 78 // hit, 命中
SensorUnitType_Miss SensorUnitType = 79 // miss, 未击中, 未命中
SensorUnitType_Retry SensorUnitType = 80 // retry, 重试(次数)
SensorUnitType_Reset SensorUnitType = 81 // reset, 重置(次数)
SensorUnitType_Overrun SensorUnitType = 82 // overrun) / overflow 满载, 溢出(次数)
SensorUnitType_Underrun SensorUnitType = 83 // underrun 欠载
SensorUnitType_Collision SensorUnitType = 84 // collision, 冲突
SensorUnitType_Packet SensorUnitType = 85 // packets, 包, 数据包
SensorUnitType_Message SensorUnitType = 86 // messages, 消息
SensorUnitType_Characters SensorUnitType = 87 // characters, 字符
SensorUnitType_Error SensorUnitType = 88 // error, 错误
SensorUnitType_CorrectableError SensorUnitType = 89 // correctable error 可校正错误
SensorUnitType_UncorrectableError SensorUnitType = 90 // uncorrectable error 不可校正错误
SensorUnitType_FatalError SensorUnitType = 91 // fatal error, 致命错误, 不可恢复的错误
SensorUnitType_Grams SensorUnitType = 92 // grams, 克(gram的复数形式)
)
func (u SensorUnitType) String() string {
s, ok := sensorUnitMap[u]
if ok {
return s
}
return ""
}
var sensorUnitMap = map[SensorUnitType]string{
0: "unspecified",
1: "degrees C",
2: "degrees F",
3: "degrees K",
4: "Volts",
5: "Amps",
6: "Watts",
7: "Joules",
8: "Coulombs",
9: "VA",
10: "Nits",
11: "lumen",
12: "lux",
13: "Candela",
14: "kPa",
15: "PSI",
16: "Newton",
17: "CFM",
18: "RPM",
19: "Hz",
20: "microsecond",
21: "millisecond",
22: "second",
23: "minute",
24: "hour",
25: "day",
26: "week",
27: "mil",
28: "inches",
29: "feet",
30: "cu in",
31: "cu feet",
32: "mm",
33: "cm",
34: "m",
35: "cu cm",
36: "cu m",
37: "liters",
38: "fluid ounce",
39: "radians",
40: "steradians",
41: "revolutions",
42: "cycles",
43: "gravities",
44: "ounce",
45: "pound",
46: "ft-lb",
47: "oz-in",
48: "gauss",
49: "gilberts",
50: "henry",
51: "millihenry",
52: "farad",
53: "microfarad",
54: "ohms",
55: "siemens",
56: "mole",
57: "becquerel",
58: "PPM",
59: "reserved",
60: "Decibels",
61: "DbA",
62: "DbC",
63: "gray",
64: "sievert",
65: "color temp deg K",
66: "bit",
67: "kilobit",
68: "megabit",
69: "gigabit",
70: "byte",
71: "kilobyte",
72: "megabyte",
73: "gigabyte",
74: "word",
75: "dword",
76: "qword",
77: "line",
78: "hit",
79: "miss",
80: "retry",
81: "reset",
82: "overflow",
83: "underrun",
84: "collision",
85: "packets",
86: "messages",
87: "characters",
88: "error",
89: "correctable error",
90: "uncorrectable error",
91: "fatal error",
92: "grams",
}
// SensorThresholdType are enums for types of threshold
type SensorThresholdType string
const (
SensorThresholdType_LNC SensorThresholdType = "LowerNonCritical"
SensorThresholdType_LCR SensorThresholdType = "LowerCritical"
SensorThresholdType_LNR SensorThresholdType = "LowerNonRecoverable"
SensorThresholdType_UNC SensorThresholdType = "UpperNonCritical"
SensorThresholdType_UCR SensorThresholdType = "UpperCritical"
SensorThresholdType_UNR SensorThresholdType = "UpperNonRecoverable"
)
func (sensorThresholdType SensorThresholdType) Abbr() string {
m := map[SensorThresholdType]string{
SensorThresholdType_LNC: "lnc",
SensorThresholdType_LCR: "lcr",
SensorThresholdType_LNR: "lnr",
SensorThresholdType_UNC: "unc",
SensorThresholdType_UCR: "ucr",
SensorThresholdType_UNR: "unr",
}
s, ok := m[sensorThresholdType]
if ok {
return s
}
return ""
}
type SensorThresholdTypes []SensorThresholdType
func (types SensorThresholdTypes) Strings() []string {
out := []string{}
for _, v := range types {
out = append(out, v.Abbr())
}
return out
}
// SensorThresholdStatus are enums for threshold status of sensor.
//
// ....UNR status (NonRecoverable)
// -----------------UNR threshold
// ....UCR status (Critical)
// -----------------UCR threshold
// ....UNC status (NonCritical)
// -----------------UNC threshold
// ....OK status (OK)
// -----------------LNC threshold
// ....LNC status (NonCritical)
// -----------------LCR threshold
// ....LCR status (Critical)
// -----------------LNR threshold
// ....LNR status (NonRecoverable)
type SensorThresholdStatus string
const (
SensorThresholdStatus_OK = "ok"
SensorThresholdStatus_LNC = "lnc"
SensorThresholdStatus_LCR = "lcr"
SensorThresholdStatus_LNR = "lnr"
SensorThresholdStatus_UNC = "unc"
SensorThresholdStatus_UCR = "ucr"
SensorThresholdStatus_UNR = "unr"
)
type SensorStatus string
const (
// SensorStatusOK means okay (the sensor is present and operating correctly)
SensorStatusOK = "OK"
// SensorStatusNoSensor means no sensor (corresponding reading will say disabled or Not Readable)
SensorStatusNoSensor = "N/A"
// SensorStatusNonCritical means non-critical error (lower or upper)
SensorStatusNonCritical = "NC"
// SensorStatusCritical means critical error (lower or upper)
SensorStatusCritical = "CR"
// SensorStatusNonRecoverable means non-recoverable error (lower or upper)
SensorStatusNonRecoverable = "NR"
)
// SensorThreshold holds all values and attributes of a specified threshold type.
type SensorThreshold struct {
// type of threshold
Type SensorThresholdType
Mask Mask_Threshold
// threshold raw reading value before conversion
Raw uint8
}
// LinearizationFunc is linearization function used in "Sensor Reading Conversion Formula"
// 线性化函数
type LinearizationFunc uint8
const (
LinearizationFunc_Linear LinearizationFunc = 0x00
LinearizationFunc_LN LinearizationFunc = 0x01
LinearizationFunc_LOG10 LinearizationFunc = 0x02
LinearizationFunc_LOG2 LinearizationFunc = 0x03
LinearizationFunc_E LinearizationFunc = 0x04
LinearizationFunc_EXP10 LinearizationFunc = 0x05
LinearizationFunc_EXP2 LinearizationFunc = 0x06
LinearizationFunc_1X LinearizationFunc = 0x07
LinearizationFunc_SQR LinearizationFunc = 0x08
LinearizationFunc_CUBE LinearizationFunc = 0x09
LinearizationFunc_SQRT LinearizationFunc = 0x0a
LinearizationFunc_CBRT LinearizationFunc = 0x0b
// 70h = non-linear.
// 71h-7Fh = non-linear OEM
LinearizationFunc_NonLinear LinearizationFunc = 0x70
)
func (l LinearizationFunc) IsNonLinear() bool {
if uint8(l) >= 0x70 && uint8(l) <= 0x7f {
return true
}
return false
}
func (l LinearizationFunc) String() string {
m := map[LinearizationFunc]string{
0x00: "linear",
0x01: "ln",
0x02: "log10",
0x03: "log2",
0x04: "e",
0x05: "exp10",
0x06: "exp2",
0x07: "1/x",
0x08: "sqr(x)", // 平方 sqr(3) = 9
0x09: "cube(x)", // 立方 cube(3) = 27
0x0a: "sqrt(x)", // 平方根 sqrt(9) = 3
0x0b: "cbrt(x)", // 立方根 cbrt(27) = 3
}
s, ok := m[l]
if ok {
return fmt.Sprintf("%s(%d)", s, uint8(l))
}
return fmt.Sprintf("(%d)", uint8(l))
}
// Apply applies linearization func (itself) to the input value and returns the result.
func (l LinearizationFunc) Apply(x float64) float64 {
switch l {
case LinearizationFunc_LN:
return math.Log(float64(x))
case LinearizationFunc_LOG10:
return math.Log10(float64(x))
case LinearizationFunc_LOG2:
return math.Log2(float64(x))
case LinearizationFunc_E:
return math.Pow(math.E, float64(x))
case LinearizationFunc_EXP10:
return math.Pow10(int(x))
case LinearizationFunc_EXP2:
return math.Exp2(float64(x))
case LinearizationFunc_1X:
return math.Pow(float64(x), -1)
case LinearizationFunc_SQR:
return math.Pow(float64(x), 2.0)
case LinearizationFunc_CUBE:
return math.Pow(float64(x), 3.0)
case LinearizationFunc_SQRT:
return math.Sqrt(float64(x))
case LinearizationFunc_CBRT:
return math.Cbrt(float64(x))
case LinearizationFunc_Linear:
// `linear means y=f(x)=x`, nothing to do
default:
// other values mean sensor is non-linear, also no linearization function is applied. (see 36.2 third paragraph)
}
return x
}
type SensorUnit struct {
AnalogDataFormat SensorAnalogUnitFormat
RateUnit SensorRateUnit
ModifierRelation SensorModifierRelation
Percentage bool // Percentage 0b = no, 1b = yes
BaseUnit SensorUnitType
ModifierUnit SensorUnitType
}
func (unit SensorUnit) String() string {
if !unit.IsAnalog() {
return "discrete"
}
// return unit.BaseUnit.String()
var percentageStr string
if unit.Percentage {
percentageStr = "% "
}
switch unit.ModifierRelation {
case SensorModifierRelation_Div:
return fmt.Sprintf("%s%s/%s", percentageStr, unit.BaseUnit, unit.ModifierUnit)
case SensorModifierRelation_Mul:
return fmt.Sprintf("%s%s*%s", percentageStr, unit.BaseUnit, unit.ModifierUnit)
// SensorModifierRelation_None:
default:
if unit.BaseUnit == SensorUnitType_Unspecified && unit.Percentage {
return "percent"
}
return fmt.Sprintf("%s%s", percentageStr, unit.BaseUnit)
}
}
func (unit SensorUnit) IsAnalog() bool {
return unit.AnalogDataFormat != SensorAnalogUnitFormat_NotAnalog
}
type SensorAnalogUnitFormat uint8
const (
SensorAnalogUnitFormat_Unsigned SensorAnalogUnitFormat = 0 // unsigned
SensorAnalogUnitFormat_1sComplement SensorAnalogUnitFormat = 1 // 1's complement (signed)
SensorAnalogUnitFormat_2sComplement SensorAnalogUnitFormat = 2 // 2's complement (signed)
SensorAnalogUnitFormat_NotAnalog SensorAnalogUnitFormat = 3 // does not return analog (numeric) reading
)
func (format SensorAnalogUnitFormat) String() string {
m := map[SensorAnalogUnitFormat]string{
0: "unsigned",
1: "1s comp",
2: "2s comp",
3: "not analog",
}
s, ok := m[format]
if ok {
return s
}
return "unknown"
}
type SensorRateUnit uint8
const (
SensorRateUnit_None SensorRateUnit = 0
SensorRateUnit_PerMicroSec SensorRateUnit = 1
SensorRateUnit_PerMilliSec SensorRateUnit = 2
SensorRateUnit_PerSec SensorRateUnit = 3
SensorRateUnit_PerMin SensorRateUnit = 4
SensorRateUnit_PerHour SensorRateUnit = 5
SensorRateUnit_PerDay SensorRateUnit = 6
SensorRateUnit_Reserved SensorRateUnit = 7
)
func (unit SensorRateUnit) String() string {
m := map[SensorRateUnit]string{
0: "none",
1: "per µS",
2: "per ms",
3: "per s",
4: "per minute",
5: "per hour",
6: "per day",
7: "reserved",
}
s, ok := m[unit]
if ok {
return s
}
return ""
}
type SensorModifierRelation uint8
const (
SensorModifierRelation_None SensorModifierRelation = 0
SensorModifierRelation_Div SensorModifierRelation = 1 // Basic Unit / Modifier Unit
SensorModifierRelation_Mul SensorModifierRelation = 2 // Basic Unit * Modifier Unit
)
func (unit SensorModifierRelation) String() string {
m := map[SensorModifierRelation]string{
0: "none",
1: "div",
2: "mul",
3: "reserved",
}
s, ok := m[unit]
if ok {
return s
}
return ""
}
// SensorEventMessageControl indicates whether this sensor generates Event Messages,
// and if so, what type of Event Message control is offered.
type SensorEventMessageControl uint8
const (
// per threshold/discrete-state event enable/disable control (implies
// that entire sensor and global disable are also supported)
SensorEventMessageControl_PerThresholdState SensorEventMessageControl = 0
// entire sensor only (implies that global disable is also supported)
SensorEventMessageControl_EntireSensorOnly SensorEventMessageControl = 1
// global disable only
SensorEventMessageControl_GlobalDisableOnly SensorEventMessageControl = 2
// no events from sensor
SensorEventMessageControl_NoEvents SensorEventMessageControl = 3
)
func (a SensorEventMessageControl) String() string {
switch a {
case 0:
return "Per-threshold"
case 1:
return "Entire Sensor Only"
case 2:
return "Global Disable Only"
case 3:
return "No Events From Sensor"
default:
return ""
}
}
// SensorThresholdAccess represents the access mode for the threshold value of the sensor.
type SensorThresholdAccess uint8
const (
// no thresholds.
SensorThresholdAccess_No SensorThresholdAccess = 0
// thresholds are readable, per Reading Mask
SensorThresholdAccess_Readable SensorThresholdAccess = 1
// thresholds are readable and settable, per Reading Mask and Settable Threshold Mask, respectively.
SensorThresholdAccess_ReadableSettable SensorThresholdAccess = 2
// Fixed, unreadable, thresholds.
// Which thresholds are supported is reflected by the Reading Mask.
// The threshold value fields report the values that are hard-coded in the sensor.
SensorThresholdAccess_Fixed SensorThresholdAccess = 3
)
func (a SensorThresholdAccess) String() string {
switch a {
case 0:
return "No"
case 1:
return "Readable"
case 2:
return "ReadableSettable"
case 3:
return "FixedUnreadable"
default:
return ""
}
}
// SensorHysteresisAccess represents the access mode for the hysteresis value of the sensor.
type SensorHysteresisAccess uint8
const (
// No hysteresis, or hysteresis built-in but not specified
SensorHysteresisAccess_No SensorHysteresisAccess = 0
// hysteresis is readable.
SensorHysteresisAccess_Readable SensorHysteresisAccess = 1
// hysteresis is readable and settable.
SensorHysteresisAccess_ReadableSettable SensorHysteresisAccess = 2
// Fixed, unreadable, hysteresis. Hysteresis fields values implemented in the sensor.
SensorHysteresisAccess_Fixed SensorHysteresisAccess = 3
)
func (a SensorHysteresisAccess) String() string {
switch a {
case 0:
return "No"
case 1:
return "Readable"
case 2:
return "ReadableSettable"
case 3:
return "FixedUnreadable"
default:
return ""
}
}
// ReadingFactors is used in "Sensor Reading Conversion Formula"
// Only Full SDR defines reading factors.
// see: 36.3 Sensor Reading Conversion Formula
type ReadingFactors struct {
M int16 // 10 bits used
// in +/- ½ raw counts
Tolerance uint8 // 6 bits used
B int16 // 10 bits used
// Unsigned, 10-bit Basic Sensor Accuracy in 1/100 percent scaled up by unsigned Accuracy exponent.
Accuracy uint16 // 10 bits, unsigned
Accuracy_Exp uint8 // 2 bits, unsigned
// [7:4] - R (result) exponent 4 bits, 2's complement, signed
// [3:0] - B exponent 4 bits, 2's complement, signed
R_Exp int8 // 4 bits, signed, also called K2
B_Exp int8 // 4 bits, signed, also called K1
}
func (f ReadingFactors) String() string {
return fmt.Sprintf("M: (%d), T: (%d), B: (%d), A: (%d), A_Exp: (%d), R_Exp: (%d), B_Exp: (%d)",
f.M, f.Tolerance, f.B, f.Accuracy, f.Accuracy_Exp, f.R_Exp, f.B_Exp)
}
// The raw analog data is unpacked as an unsigned integer.
// But whether it is a positive number (>0) or negative number (<0) is determined
// by the "analog data format" field (SensorUnit.AnalogDataFormat)
func AnalogValue(raw uint8, format SensorAnalogUnitFormat) int32 {
switch format {
case SensorAnalogUnitFormat_NotAnalog:
return int32(raw)
case SensorAnalogUnitFormat_Unsigned:
return int32(raw)
case SensorAnalogUnitFormat_1sComplement:
return int32(onesComplement(uint32(raw), 8))
case SensorAnalogUnitFormat_2sComplement:
return int32(twosComplement(uint32(raw), 8))
}
return int32(raw)
}
// ConvertReading converts raw sensor reading or raw sensor threshold value to real value in the desired units for the sensor.
//
// see: 36.3 Sensor Reading Conversion Formula
//
// INPUT: raw (unsigned)
// -- APPLY: analogDataFormat
// --> GOT: analog (signed)
// -- APPLY: factors/linearization
// --> GOT: converted (float64)
func ConvertReading(raw uint8, analogDataFormat SensorAnalogUnitFormat, factors ReadingFactors, linearizationFunc LinearizationFunc) float64 {
// y = L[(Mx + (B * 10^B_Exp) ) * 10^R_Exp ] units
analog := AnalogValue(raw, analogDataFormat)
x := float64(analog)
M := float64(factors.M)
B := float64(factors.B)
Bexp := math.Pow(10, float64(factors.B_Exp))
Rexp := math.Pow(10, float64(factors.R_Exp))
y := (M*x + B*Bexp) * Rexp
return linearizationFunc.Apply(y)
}
// ConvertSensorHysteresis converts raw sensor hysteresis value to real value in the desired units for the sensor.
//
// see: 36.3 Sensor Reading Conversion Formula
func ConvertSensorHysteresis(raw uint8, analogDataFormat SensorAnalogUnitFormat, factors ReadingFactors, linearizationFunc LinearizationFunc) float64 {
// y = L[(Mx + (B * 10^B_Exp) ) * 10^R_Exp ] units
analog := AnalogValue(raw, analogDataFormat)
x := float64(analog)
M := float64(factors.M)
B := float64(factors.B)
Bexp := math.Pow(10, float64(factors.B_Exp))
Rexp := math.Pow(10, float64(factors.R_Exp))
y := (M*x + B*Bexp) * Rexp
return linearizationFunc.Apply(y)
}
// ConvertSensorTolerance converts raw sensor tolerance value to real value in the desired units for the sensor.
//
// see: 36.4.1 Tolerance
func ConvertSensorTolerance(raw uint8, analogDataFormat SensorAnalogUnitFormat, factors ReadingFactors, linearizationFunc LinearizationFunc) float64 {
// y = L[Mx/2 * 10^R_Exp ] units.
analog := AnalogValue(raw, analogDataFormat)
x := float64(analog)
M := float64(factors.M)
Rexp := math.Pow(10, float64(factors.R_Exp))
y := (M * x / 2) * Rexp
return linearizationFunc.Apply(y)
}
// Sensor holds all attribute of a sensor.
type Sensor struct {
Number uint8
Name string
SDRRecordType SDRRecordType
HasAnalogReading bool
SensorType SensorType
EventReadingType EventReadingType
SensorUnit SensorUnit
SensorInitialization SensorInitialization
SensorCapabilities SensorCapabilities
EntityID EntityID
EntityInstance EntityInstance
scanningDisabled bool // update by GetSensorReading
readingAvailable bool // update by GetSensorReading
// Raw reading value before conversion
Raw uint8
// reading value after conversion
Value float64
Threshold struct {
Mask Mask_Thresholds
// Threshold Status, updated by GetSensorReadingResponse.ThresholdStatus()
ThresholdStatus SensorThresholdStatus
// Only Full SDR
LinearizationFunc LinearizationFunc
ReadingFactors
LNC_Raw uint8
LCR_Raw uint8
LNR_Raw uint8
UNC_Raw uint8
UCR_Raw uint8
UNR_Raw uint8
LNC float64
LCR float64
LNR float64
UNC float64
UCR float64
UNR float64
PositiveHysteresisRaw uint8
NegativeHysteresisRaw uint8
PositiveHysteresis float64
NegativeHysteresis float64
}
Discrete struct {
Mask Mask_Discrete
ActiveStates Mask_DiscreteEvent
// filled by GetSensorReadingResponse
optionalData1 uint8
optionalData2 uint8
}
OccurredEvents []SensorEvent
}
func (s *Sensor) String() string {
sensorReadingRawStr := fmt.Sprintf("%d", s.Raw)
sensorReadingValueStr := fmt.Sprintf("%.3f %s", s.Value, s.SensorUnit)
if s.scanningDisabled {
sensorReadingRawStr = "Unable to read sensor: Device Not Present"
sensorReadingValueStr = "Unable to read sensor: Device Not Present"
}
return fmt.Sprintf("Sensor ID : %s (%#02x)\n", s.Name, s.Number) +
fmt.Sprintf(" Entity ID : %d.%d (%s)\n", uint8(s.EntityID), uint8(s.EntityInstance), s.EntityID) +
fmt.Sprintf(" Sensor Type : %s (%#02x) (%s)\n", s.SensorType.String(), uint8(s.SensorType), string(s.EventReadingType.SensorClass())) +
fmt.Sprintf(" Sensor Number : %#02x\n", s.Number) +
fmt.Sprintf(" Sensor Name : %s\n", s.Name) +
fmt.Sprintf(" Sensor Reading (raw) : %s\n", sensorReadingRawStr) +
fmt.Sprintf(" Sensor Value : %s\n", sensorReadingValueStr) +
fmt.Sprintf(" Sensor Status : %s\n", s.Status()) +
fmt.Sprintf(" Sensor Human String : %s\n", s.HumanStr())
}
// FormatSensors return a string of table printed for sensors
func FormatSensors(extended bool, sensors ...*Sensor) string {
var buf = new(bytes.Buffer)
table := tablewriter.NewWriter(buf)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_RIGHT)
headers := []string{
"SDRType",
"SensorNumber",
"SensorName",
"SensorType",
"Reading",
"Unit",
"Status",
"LNR",
"LCR",
"LNC",
"UNC",
"UCR",
"UNR",
}
if extended {
headers = append(headers, []string{
"EntityID",
"EventReadingType",
"AnalogDataFormat",
"ReadV",
"ScanD",
"ReadU",
"HasAR",
"DiscreteEvents",
"HumanStr",
}...)
}
table.SetHeader(headers)
table.SetFooter(headers)
for _, sensor := range sensors {
rowContent := []string{
sensor.SDRRecordType.String(),
fmt.Sprintf("%#02x", sensor.Number),
sensor.Name,
fmt.Sprintf("%s (%#02x)", sensor.SensorType.String(), uint8(sensor.SensorType)),
sensor.ReadingStr(),
sensor.SensorUnit.String(),
sensor.Status(),
sensor.ThresholdStr(SensorThresholdType_LNR),
sensor.ThresholdStr(SensorThresholdType_LCR),
sensor.ThresholdStr(SensorThresholdType_LNC),
sensor.ThresholdStr(SensorThresholdType_UNC),
sensor.ThresholdStr(SensorThresholdType_UCR),
sensor.ThresholdStr(SensorThresholdType_UNR),
}
if extended {
rowContent = append(rowContent, []string{
fmt.Sprintf("%s (%#02x)", sensor.EntityID, uint8(sensor.EntityID)),
fmt.Sprintf("%s (%#02x)", sensor.EventReadingType.String(), uint8(sensor.EventReadingType)),
sensor.SensorUnit.AnalogDataFormat.String(),
fmt.Sprintf("%v", sensor.IsReadingValid()),
fmt.Sprintf("%v", sensor.scanningDisabled),
fmt.Sprintf("%v", !sensor.readingAvailable),
fmt.Sprintf("%v", sensor.HasAnalogReading),
}...)
if sensor.IsThreshold() {
rowContent = append(rowContent, "N/A")
} else {
rowContent = append(rowContent, fmt.Sprintf("%v", sensor.DiscreteActiveEvents()))
}
rowContent = append(rowContent, sensor.HumanStr())
}
table.Append(rowContent)
}
table.Render()
return buf.String()
}
// IsThreshold returns whether the sensor is threshold sensor class or not.
func (sensor *Sensor) IsThreshold() bool {
return sensor.EventReadingType.IsThreshold()
}
func (sensor *Sensor) IsReadingValid() bool {
return sensor.readingAvailable
}
func (sensor *Sensor) IsThresholdAndReadingValid() bool {
return sensor.IsThreshold() && sensor.IsReadingValid()
}
func (sensor *Sensor) IsThresholdReadable(thresholdType SensorThresholdType) bool {
if !sensor.IsThreshold() {
return false
}
mask := sensor.Threshold.Mask
return mask.IsThresholdReadable(thresholdType)
}
// ConvertReading converts raw discrete-sensor reading or raw threshold-sensor value to real value in the desired units for the sensor.
//
// This function can also be applied on raw threshold setting (UNR,UCR,NNC,LNC,LCR,LNR) values.
func (sensor *Sensor) ConvertReading(raw uint8) float64 {
if sensor.HasAnalogReading {
return ConvertReading(raw, sensor.SensorUnit.AnalogDataFormat, sensor.Threshold.ReadingFactors, sensor.Threshold.LinearizationFunc)
}
return float64(raw)
}
func (sensor *Sensor) ConvertSensorHysteresis(raw uint8) float64 {
if sensor.HasAnalogReading {
return ConvertSensorHysteresis(raw, sensor.SensorUnit.AnalogDataFormat, sensor.Threshold.ReadingFactors, sensor.Threshold.LinearizationFunc)
}
return float64(raw)
}
func (sensor *Sensor) ConvertSensorTolerance(raw uint8) float64 {
if sensor.HasAnalogReading {
return ConvertSensorTolerance(raw, sensor.SensorUnit.AnalogDataFormat, sensor.Threshold.ReadingFactors, sensor.Threshold.LinearizationFunc)
}
return float64(raw)
}
// SensorThreshold return SensorThreshold for a specified threshold type.
func (sensor *Sensor) SensorThreshold(thresholdType SensorThresholdType) SensorThreshold {
switch thresholdType {
case SensorThresholdType_LNR:
return SensorThreshold{
Type: thresholdType,
Mask: sensor.Threshold.Mask.LNR,
Raw: sensor.Threshold.LNR_Raw,
}
case SensorThresholdType_LCR:
return SensorThreshold{
Type: thresholdType,
Mask: sensor.Threshold.Mask.LCR,
Raw: sensor.Threshold.LCR_Raw,
}
case SensorThresholdType_LNC:
return SensorThreshold{
Type: thresholdType,
Mask: sensor.Threshold.Mask.LNC,
Raw: sensor.Threshold.LNC_Raw,
}
case SensorThresholdType_UNC:
return SensorThreshold{
Type: thresholdType,
Mask: sensor.Threshold.Mask.UNC,
Raw: sensor.Threshold.UNC_Raw,
}
case SensorThresholdType_UCR:
return SensorThreshold{
Type: thresholdType,
Mask: sensor.Threshold.Mask.UCR,
Raw: sensor.Threshold.UCR_Raw,
}
case SensorThresholdType_UNR:
return SensorThreshold{
Type: thresholdType,
Mask: sensor.Threshold.Mask.UNR,
Raw: sensor.Threshold.UNR_Raw,
}
}
return SensorThreshold{
Type: thresholdType,
}
}
func (sensor *Sensor) Status() string {
if sensor.scanningDisabled {
return "N/A"
}
if !sensor.IsReadingValid() {
return "N/A"
}
if sensor.IsThreshold() {
return string(sensor.Threshold.ThresholdStatus)
}
return fmt.Sprintf("0x%02x%02x", sensor.Discrete.optionalData1, sensor.Discrete.optionalData2)
}
func (sensor *Sensor) HumanStr() string {
if sensor.scanningDisabled {
return "N/A"
}
if !sensor.IsReadingValid() {
return "N/A"
}
if sensor.IsThreshold() {
return fmt.Sprintf("%.3f %s", sensor.Value, sensor.SensorUnit)
}
return strings.Join(sensor.DiscreteActiveEventsString(), ", ")
}
func (sensor *Sensor) ReadingStr() string {
if sensor.scanningDisabled {
return "N/A"
}
if !sensor.IsReadingValid() {
return "N/A"
}
if sensor.IsThreshold() {
return fmt.Sprintf("%.3f", sensor.Value)
}
return fmt.Sprintf("%d", sensor.Raw)
}
func (sensor *Sensor) ThresholdStr(thresholdType SensorThresholdType) string {
if !sensor.IsThresholdReadable(thresholdType) {
return "N/A"
}
var value float64
switch thresholdType {
case SensorThresholdType_LCR:
value = sensor.Threshold.LCR
case SensorThresholdType_LNR:
value = sensor.Threshold.LNR
case SensorThresholdType_LNC:
value = sensor.Threshold.LNC
case SensorThresholdType_UCR:
value = sensor.Threshold.UCR
case SensorThresholdType_UNC:
value = sensor.Threshold.UNC
case SensorThresholdType_UNR:
value = sensor.Threshold.UNR
}
return fmt.Sprintf("%.3f", value)
}
func (sensor *Sensor) HysteresisStr(raw uint8) string {
switch sensor.SDRRecordType {
case SDRRecordTypeFullSensor:
if !sensor.SensorUnit.IsAnalog() {
if raw == 0x00 || raw == 0xff {
return "unspecified"
}
return fmt.Sprintf("%#02x", raw)
}
// analog sensor
value := sensor.ConvertSensorHysteresis(raw)
if raw == 0x00 || raw == 0xff || value == 0.0 {
return "unspecified"
}
return fmt.Sprintf("%#02x/%.3f", raw, value)
case SDRRecordTypeCompactSensor:
if raw == 0x00 || raw == 0xff {
return "unspecified"
}
return fmt.Sprintf("%#02x", raw)
}
return ""
}
func (sensor *Sensor) DiscreteActiveEvents() []uint8 {
if sensor.IsThreshold() {
return []uint8{}
}
return sensor.Discrete.ActiveStates.TrueEvents()
}
func (sensor *Sensor) DiscreteActiveEventsString() []string {
result := make([]string, 0)
for _, eventOffset := range sensor.DiscreteActiveEvents() {
result = append(result, sensor.EventString(eventOffset))
}
return result
}
func (sensor *Sensor) EventString(eventOffset uint8) string {
event := sensor.EventReadingType.EventForOffset(sensor.SensorType, eventOffset)
if event != nil {
return event.EventName
}
return ""
}
golang-github-bougou-go-ipmi-0.7.2/types_sensor_event.go 0000664 0000000 0000000 00000040574 14741105271 0023405 0 ustar 00root root 0000000 0000000 package ipmi
import "fmt"
type SensorEvent struct {
SensorClass SensorClass
ThresholdType SensorThresholdType
Assert bool // true -> assertion events; false -> deassertion events
High bool // true -> going high; false -> going low
State uint8 // state 0-14 (total 15 possible states)
}
func (e SensorEvent) String() string {
switch e.SensorClass {
case SensorClassThreshold:
out := e.ThresholdType.Abbr()
if e.High {
out += "+"
} else {
out += "-"
}
return out
case SensorClassDiscrete:
return fmt.Sprintf("state%d", e.State)
}
return ""
}
type SensorEvents []SensorEvent
func (events SensorEvents) Strings() []string {
out := make([]string, 0)
return out
}
func (events SensorEvents) FilterAssert() SensorEvents {
out := make([]SensorEvent, 0)
for _, event := range events {
if event.Assert {
out = append(out, event)
}
}
return out
}
func (events SensorEvents) FilterDeassert() SensorEvents {
out := make([]SensorEvent, 0)
for _, event := range events {
if !event.Assert {
out = append(out, event)
}
}
return out
}
func (events SensorEvents) FilterThreshold() SensorEvents {
out := make([]SensorEvent, 0)
for _, event := range events {
if event.SensorClass == SensorClassThreshold {
out = append(out, event)
}
}
return out
}
func (events SensorEvents) FilterDiscrete() SensorEvents {
out := make([]SensorEvent, 0)
for _, event := range events {
if event.SensorClass == SensorClassDiscrete {
out = append(out, event)
}
}
return out
}
// SensorEventFlag holds a struct with fields indicating the specified sensor event is set or not.
// SensorEventFlag was embedded in Sensor related commands.
type SensorEventFlag struct {
SensorEvent_UNC_High_Assert bool
SensorEvent_UNC_Low_Assert bool
SensorEvent_LNR_High_Assert bool
SensorEvent_LNR_Low_Assert bool
SensorEvent_LCR_High_Assert bool
SensorEvent_LCR_Low_Assert bool
SensorEvent_LNC_High_Assert bool
SensorEvent_LNC_Low_Assert bool
SensorEvent_State_7_Assert bool
SensorEvent_State_6_Assert bool
SensorEvent_State_5_Assert bool
SensorEvent_State_4_Assert bool
SensorEvent_State_3_Assert bool
SensorEvent_State_2_Assert bool
SensorEvent_State_1_Assert bool
SensorEvent_State_0_Assert bool
SensorEvent_UNR_High_Assert bool
SensorEvent_UNR_Low_Assert bool
SensorEvent_UCR_High_Assert bool
SensorEvent_UCR_Low_Assert bool
SensorEvent_State_14_Assert bool
SensorEvent_State_13_Assert bool
SensorEvent_State_12_Assert bool
SensorEvent_State_11_Assert bool
SensorEvent_State_10_Assert bool
SensorEvent_State_9_Assert bool
SensorEvent_State_8_Assert bool
SensorEvent_UNC_High_Deassert bool
SensorEvent_UNC_Low_Deassert bool
SensorEvent_LNR_High_Deassert bool
SensorEvent_LNR_Low_Deassert bool
SensorEvent_LCR_High_Deassert bool
SensorEvent_LCR_Low_Deassert bool
SensorEvent_LNC_High_Deassert bool
SensorEvent_LNC_Low_Deassert bool
SensorEvent_State_7_Deassert bool
SensorEvent_State_6_Deassert bool
SensorEvent_State_5_Deassert bool
SensorEvent_State_4_Deassert bool
SensorEvent_State_3_Deassert bool
SensorEvent_State_2_Deassert bool
SensorEvent_State_1_Deassert bool
SensorEvent_State_0_Deassert bool
SensorEvent_UNR_High_Deassert bool
SensorEvent_UNR_Low_Deassert bool
SensorEvent_UCR_High_Deassert bool
SensorEvent_UCR_Low_Deassert bool
SensorEvent_State_14_Deassert bool
SensorEvent_State_13_Deassert bool
SensorEvent_State_12_Deassert bool
SensorEvent_State_11_Deassert bool
SensorEvent_State_10_Deassert bool
SensorEvent_State_9_Deassert bool
SensorEvent_State_8_Deassert bool
}
// TrueEvents returns a slice of SensorEvent those are set to true in the SensorEventFlag.
func (flag *SensorEventFlag) TrueEvents() []SensorEvent {
out := make([]SensorEvent, 0)
if flag.SensorEvent_UNC_High_Assert {
out = append(out, SensorEvent_UNC_High_Assert)
}
if flag.SensorEvent_UNC_Low_Assert {
out = append(out, SensorEvent_UNC_Low_Deassert)
}
if flag.SensorEvent_LNR_High_Assert {
out = append(out, SensorEvent_LNR_High_Assert)
}
if flag.SensorEvent_LNR_Low_Assert {
out = append(out, SensorEvent_LNR_Low_Assert)
}
if flag.SensorEvent_LCR_High_Assert {
out = append(out, SensorEvent_LCR_High_Assert)
}
if flag.SensorEvent_LCR_Low_Assert {
out = append(out, SensorEvent_LCR_Low_Assert)
}
if flag.SensorEvent_LNC_High_Assert {
out = append(out, SensorEvent_LNC_High_Assert)
}
if flag.SensorEvent_LNC_Low_Assert {
out = append(out, SensorEvent_LNC_Low_Assert)
}
if flag.SensorEvent_State_7_Assert {
out = append(out, SensorEvent_State_7_Assert)
}
if flag.SensorEvent_State_6_Assert {
out = append(out, SensorEvent_State_6_Assert)
}
if flag.SensorEvent_State_5_Assert {
out = append(out, SensorEvent_State_5_Assert)
}
if flag.SensorEvent_State_4_Assert {
out = append(out, SensorEvent_State_4_Assert)
}
if flag.SensorEvent_State_3_Assert {
out = append(out, SensorEvent_State_3_Assert)
}
if flag.SensorEvent_State_2_Assert {
out = append(out, SensorEvent_State_2_Assert)
}
if flag.SensorEvent_State_1_Assert {
out = append(out, SensorEvent_State_1_Assert)
}
if flag.SensorEvent_State_0_Assert {
out = append(out, SensorEvent_State_0_Assert)
}
if flag.SensorEvent_UNR_High_Assert {
out = append(out, SensorEvent_UNR_High_Assert)
}
if flag.SensorEvent_UNR_Low_Assert {
out = append(out, SensorEvent_UNR_Low_Assert)
}
if flag.SensorEvent_UCR_High_Assert {
out = append(out, SensorEvent_UCR_High_Assert)
}
if flag.SensorEvent_UCR_Low_Assert {
out = append(out, SensorEvent_UCR_Low_Assert)
}
if flag.SensorEvent_State_14_Assert {
out = append(out, SensorEvent_State_14_Assert)
}
if flag.SensorEvent_State_13_Assert {
out = append(out, SensorEvent_State_13_Assert)
}
if flag.SensorEvent_State_12_Assert {
out = append(out, SensorEvent_State_12_Assert)
}
if flag.SensorEvent_State_11_Assert {
out = append(out, SensorEvent_State_11_Assert)
}
if flag.SensorEvent_State_10_Assert {
out = append(out, SensorEvent_State_10_Assert)
}
if flag.SensorEvent_State_9_Assert {
out = append(out, SensorEvent_State_9_Assert)
}
if flag.SensorEvent_State_8_Assert {
out = append(out, SensorEvent_State_8_Assert)
}
if flag.SensorEvent_UNC_High_Deassert {
out = append(out, SensorEvent_UNC_High_Deassert)
}
if flag.SensorEvent_UNC_Low_Deassert {
out = append(out, SensorEvent_UNC_Low_Deassert)
}
if flag.SensorEvent_LNR_High_Deassert {
out = append(out, SensorEvent_LNR_High_Deassert)
}
if flag.SensorEvent_LNR_Low_Deassert {
out = append(out, SensorEvent_LNR_Low_Deassert)
}
if flag.SensorEvent_LCR_High_Deassert {
out = append(out, SensorEvent_LCR_High_Deassert)
}
if flag.SensorEvent_LCR_Low_Deassert {
out = append(out, SensorEvent_LCR_Low_Deassert)
}
if flag.SensorEvent_LNC_High_Deassert {
out = append(out, SensorEvent_LNC_High_Deassert)
}
if flag.SensorEvent_LNC_Low_Deassert {
out = append(out, SensorEvent_LNC_Low_Deassert)
}
if flag.SensorEvent_State_7_Deassert {
out = append(out, SensorEvent_State_7_Deassert)
}
if flag.SensorEvent_State_6_Deassert {
out = append(out, SensorEvent_State_6_Deassert)
}
if flag.SensorEvent_State_5_Deassert {
out = append(out, SensorEvent_State_5_Deassert)
}
if flag.SensorEvent_State_4_Deassert {
out = append(out, SensorEvent_State_4_Deassert)
}
if flag.SensorEvent_State_3_Deassert {
out = append(out, SensorEvent_State_3_Deassert)
}
if flag.SensorEvent_State_2_Deassert {
out = append(out, SensorEvent_State_2_Deassert)
}
if flag.SensorEvent_State_1_Deassert {
out = append(out, SensorEvent_State_1_Deassert)
}
if flag.SensorEvent_State_0_Deassert {
out = append(out, SensorEvent_State_0_Deassert)
}
if flag.SensorEvent_UNR_High_Deassert {
out = append(out, SensorEvent_UNR_High_Deassert)
}
if flag.SensorEvent_UNR_Low_Deassert {
out = append(out, SensorEvent_UNR_Low_Deassert)
}
if flag.SensorEvent_UCR_High_Deassert {
out = append(out, SensorEvent_UCR_High_Deassert)
}
if flag.SensorEvent_UCR_Low_Deassert {
out = append(out, SensorEvent_UCR_Low_Deassert)
}
if flag.SensorEvent_State_14_Deassert {
out = append(out, SensorEvent_State_14_Deassert)
}
if flag.SensorEvent_State_13_Deassert {
out = append(out, SensorEvent_State_13_Deassert)
}
if flag.SensorEvent_State_12_Deassert {
out = append(out, SensorEvent_State_12_Deassert)
}
if flag.SensorEvent_State_11_Deassert {
out = append(out, SensorEvent_State_11_Deassert)
}
if flag.SensorEvent_State_10_Deassert {
out = append(out, SensorEvent_State_10_Deassert)
}
if flag.SensorEvent_State_9_Deassert {
out = append(out, SensorEvent_State_9_Deassert)
}
if flag.SensorEvent_State_8_Deassert {
out = append(out, SensorEvent_State_8_Deassert)
}
return out
}
var (
SensorEvent_UNC_High_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UNC,
Assert: true,
High: true,
}
SensorEvent_UNC_Low_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UNC,
Assert: true,
High: false,
}
SensorEvent_LNR_High_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LNR,
Assert: true,
High: true,
}
SensorEvent_LNR_Low_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LNR,
Assert: true,
High: false,
}
SensorEvent_LCR_High_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LCR,
Assert: true,
High: true,
}
SensorEvent_LCR_Low_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LCR,
Assert: true,
High: false,
}
SensorEvent_LNC_High_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LNC,
Assert: true,
High: true,
}
SensorEvent_LNC_Low_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LNC,
Assert: true,
High: false,
}
SensorEvent_UNR_High_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UNR,
Assert: true,
High: true,
}
SensorEvent_UNR_Low_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UNR,
Assert: true,
High: false,
}
SensorEvent_UCR_High_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UCR,
Assert: true,
High: true,
}
SensorEvent_UCR_Low_Assert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UCR,
Assert: true,
High: false,
}
SensorEvent_State_14_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 14,
}
SensorEvent_State_13_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 13,
}
SensorEvent_State_12_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 12,
}
SensorEvent_State_11_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 11,
}
SensorEvent_State_10_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 10,
}
SensorEvent_State_9_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 9,
}
SensorEvent_State_8_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 8,
}
SensorEvent_State_7_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 7,
}
SensorEvent_State_6_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 6,
}
SensorEvent_State_5_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 5,
}
SensorEvent_State_4_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 4,
}
SensorEvent_State_3_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 3,
}
SensorEvent_State_2_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 2,
}
SensorEvent_State_1_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 1,
}
SensorEvent_State_0_Assert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: true,
State: 0,
}
SensorEvent_UNC_High_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UNC,
Assert: false,
High: true,
}
// Deassert Events
SensorEvent_UNC_Low_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UNC,
Assert: false,
High: true,
}
SensorEvent_LNR_High_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LNR,
Assert: false,
High: true,
}
SensorEvent_LNR_Low_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LNR,
Assert: false,
High: false,
}
SensorEvent_LCR_High_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LCR,
Assert: false,
High: true,
}
SensorEvent_LCR_Low_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LCR,
Assert: false,
High: false,
}
SensorEvent_LNC_High_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LNC,
Assert: false,
High: true,
}
SensorEvent_LNC_Low_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_LNC,
Assert: false,
High: false,
}
SensorEvent_UNR_High_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UNR,
Assert: false,
High: true,
}
SensorEvent_UNR_Low_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UNR,
Assert: false,
High: false,
}
SensorEvent_UCR_High_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UCR,
Assert: false,
High: true,
}
SensorEvent_UCR_Low_Deassert = SensorEvent{
SensorClass: SensorClassThreshold,
ThresholdType: SensorThresholdType_UCR,
Assert: false,
High: false,
}
SensorEvent_State_14_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 14,
}
SensorEvent_State_13_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 13,
}
SensorEvent_State_12_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 12,
}
SensorEvent_State_11_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 11,
}
SensorEvent_State_10_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 10,
}
SensorEvent_State_9_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 9,
}
SensorEvent_State_8_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 8,
}
SensorEvent_State_7_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 7,
}
SensorEvent_State_6_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 6,
}
SensorEvent_State_5_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 5,
}
SensorEvent_State_4_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 4,
}
SensorEvent_State_3_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 3,
}
SensorEvent_State_2_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 2,
}
SensorEvent_State_1_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 1,
}
SensorEvent_State_0_Deassert = SensorEvent{
SensorClass: SensorClassDiscrete,
Assert: false,
State: 0,
}
)
golang-github-bougou-go-ipmi-0.7.2/types_sensor_test.go 0000664 0000000 0000000 00000002325 14741105271 0023233 0 ustar 00root root 0000000 0000000 package ipmi
import (
"fmt"
"testing"
)
func Test_ConvertReading(t *testing.T) {
tests := []struct {
raw uint8
analogDataFormat SensorAnalogUnitFormat
factors ReadingFactors
linearizationFunc LinearizationFunc
}{
{
raw: 0,
analogDataFormat: SensorAnalogUnitFormat_Unsigned,
factors: ReadingFactors{},
linearizationFunc: LinearizationFunc_Linear,
},
{
raw: 0,
analogDataFormat: SensorAnalogUnitFormat_NotAnalog,
factors: ReadingFactors{},
linearizationFunc: LinearizationFunc_Linear,
},
{
raw: 0,
analogDataFormat: SensorAnalogUnitFormat_1sComplement,
factors: ReadingFactors{
M: 1,
Tolerance: 0,
B: 0,
Accuracy: 0,
Accuracy_Exp: 0,
B_Exp: 0,
},
linearizationFunc: LinearizationFunc_Linear,
},
{
raw: 0,
analogDataFormat: SensorAnalogUnitFormat_2sComplement,
factors: ReadingFactors{},
linearizationFunc: LinearizationFunc_Linear,
},
}
for _, tt := range tests {
v := ConvertReading(tt.raw, tt.analogDataFormat, tt.factors, tt.linearizationFunc)
fmt.Println(v)
// Todo
}
}
golang-github-bougou-go-ipmi-0.7.2/types_session.go 0000664 0000000 0000000 00000047536 14741105271 0022363 0 ustar 00root root 0000000 0000000 package ipmi
import (
"crypto/md5"
"encoding/binary"
"fmt"
)
type (
AuthType uint8
)
const (
AuthTypeNone AuthType = 0x00
AuthTypeMD2 AuthType = 0x01
AuthTypeMD5 AuthType = 0x02
AuthTypePassword AuthType = 0x04
AuthTypeOEM AuthType = 0x05
AuthTypeRMCPPlus AuthType = 0x06
)
const (
SessionHeader20SizeMax int = 18
SessionHeader20SizeMin int = 12
SessionHeader15SizeMax int = 26
SessionHeader15SizeMin int = 10
)
// SessionHeader15 for IPMI 1.5
// see 22.12, Table 13.
//
// Whether the session header fields are present in a packet is based on
// whether the channel is specified as supporting multiple sessions or not.
// In addition, which session fields are present is based on the authentication type.
// Single-session connections and session-less channels do not include session header fields.
//
// Session header fields are present on all packets where the channel and
// connection mode is specified as supporting multiple sessions, even if
// the particular implementation only supports one session.
//
// Note that the command tables do not show the session header fields except for the
// Get Channel Authentication Capabilities, Get Session Challenge, and Activate Session commands.
// However, they are still required for all commands on a multi-session connection.
type SessionHeader15 struct {
// For IPMI 1.5, it's value is 00h, 01h, 02h, 04h, 05h
AuthType AuthType
// For IPMI v2.0 RMCP+ there are separate sequence numbers tracked for authenticated and unauthenticated packets.
// 0000_0000h is used for packets that are sent outside of a session.
Sequence uint32
SessionID uint32
// The Authentication Code field in the session header may or may not be present based on the Authentication Type. The authentication code field is absent whenever the Authentication Type is NONE. Whether the authentication code field is present or not when the Authentication Type = OEM is dependent on the OEM identified in the Get Channel Authentication Capabilities command.
//
// 16 bytes, not present when Authentication Type set to none
AuthCode []byte // IPMI 1.5
// Payload length in bytes. 1-based.
// IPMI 1.5 should be uint8
// You should construct SessionHeader after the payload is created, thus you can fill the length here.
PayloadLength uint8
}
func (h *SessionHeader15) Pack() []byte {
var msg = make([]byte, 10+len(h.AuthCode))
packUint8(uint8(h.AuthType), msg, 0)
packUint32L(h.Sequence, msg, 1)
packUint32L(h.SessionID, msg, 5)
if h.AuthType != AuthTypeNone {
packBytes(h.AuthCode, msg, 9)
}
packUint8(h.PayloadLength, msg, 9+len(h.AuthCode))
return msg
}
func (h *SessionHeader15) Unpack(msg []byte) error {
if len(msg) < SessionHeader15SizeMin {
return ErrUnpackedDataTooShortWith(len(msg), SessionHeader15SizeMin)
}
b, _, _ := unpackUint8(msg, 0)
h.AuthType = AuthType(b)
h.Sequence, _, _ = unpackUint32L(msg, 1)
h.SessionID, _, _ = unpackUint32L(msg, 5)
var payloadLengthIndex = 9
if h.AuthType != AuthTypeNone {
if len(msg) < SessionHeader15SizeMax {
return ErrUnpackedDataTooShortWith(len(msg), SessionHeader15SizeMax)
}
h.AuthCode, _, _ = unpackBytes(msg, 9, 16)
payloadLengthIndex = 25
}
h.PayloadLength, _, _ = unpackUint8(msg, payloadLengthIndex)
return nil
}
type Session15 struct {
SessionHeader15 *SessionHeader15
Payload []byte
// legacy PAD not needed for IPMI v2.0
LegacyPAD byte
}
func (s *Session15) Pack() []byte {
out := s.SessionHeader15.Pack()
out = append(out, s.Payload...)
return out
}
func (s *Session15) Unpack(msg []byte) error {
sessionHeader := &SessionHeader15{}
err := sessionHeader.Unpack(msg)
if err != nil {
return fmt.Errorf("unpack SessionHeader15 failed, err: %w", err)
}
s.SessionHeader15 = sessionHeader
sessionHeaderSize := len(sessionHeader.Pack())
sessionPayloadSize := int(sessionHeader.PayloadLength)
if len(msg) < sessionHeaderSize+sessionPayloadSize {
return ErrUnpackedDataTooShortWith(len(msg), sessionHeaderSize+sessionPayloadSize)
}
s.Payload, _, _ = unpackBytes(msg, sessionHeaderSize, sessionPayloadSize)
return nil
}
// SessionHeader20 for IPMI 2.0
type SessionHeader20 struct {
// For IPMI 2.0, it's value is always 06h
AuthType AuthType
PayloadEncrypted bool
PayloadAuthenticated bool
PayloadType PayloadType
// The complete identification of an OEM Payload is given by the combination of a three-byte IANA ID for the OEM, a reserved byte, plus a twobyte OEM Payload ID that is assigned and defined by the given OEM
OEMIANA uint32
OEMPayloadID uint16
// Should be set to bmcSessionID (generated by bmc, cached by remote console)
SessionID uint32
// For IPMI v2.0 RMCP+ there are separate sequence numbers tracked for authenticated and unauthenticated packets.
// 0000_0000h is used for packets that are sent outside of a session.
Sequence uint32
// Payload length in bytes. 1-based.
// You should construct SessionHeader after the payload is created, thus you can fill the length here.
// IPMI 2.0 should be uint16
PayloadLength uint16
}
func (h *SessionHeader20) Pack() []byte {
// the longest length of SessionHeader20 is 18
msg := make([]byte, 18)
packUint8(uint8(h.AuthType), msg, 0)
var encryptedMask uint8 = 0x00
if h.PayloadEncrypted {
encryptedMask = 0x80
}
var authenticatedMask uint8 = 0x00
if h.PayloadAuthenticated {
authenticatedMask = 0x40
}
packUint8(encryptedMask|authenticatedMask|uint8(h.PayloadType), msg, 1)
var sessionIDIndex int
var msgEndIndex int
if h.PayloadType == PayloadTypeOEM {
packUint32L(h.OEMIANA, msg, 2)
packUint16L(h.OEMPayloadID, msg, 6)
sessionIDIndex = 8
msgEndIndex = 18
} else {
sessionIDIndex = 2
msgEndIndex = 12
}
packUint32L(h.SessionID, msg, sessionIDIndex)
packUint32L(h.Sequence, msg, sessionIDIndex+4)
packUint16L(h.PayloadLength, msg, sessionIDIndex+8)
return msg[:msgEndIndex]
}
func (h *SessionHeader20) Unpack(msg []byte) error {
if len(msg) < SessionHeader20SizeMin {
return ErrUnpackedDataTooShortWith(len(msg), SessionHeader20SizeMin)
}
authType, _, _ := unpackUint8(msg, 0)
h.AuthType = AuthType(authType)
payloadType, _, _ := unpackUint8(msg, 1)
h.PayloadEncrypted = isBit7Set(payloadType)
h.PayloadAuthenticated = isBit6Set(payloadType)
h.PayloadType = PayloadType(payloadType & 0x3f)
var sessionIDIndex int
if h.PayloadType == PayloadTypeOEM {
if len(msg) < SessionHeader20SizeMax {
return ErrUnpackedDataTooShortWith(len(msg), SessionHeader20SizeMax)
}
h.OEMIANA, _, _ = unpackUint32L(msg, 2)
h.OEMPayloadID, _, _ = unpackUint16L(msg, 6)
sessionIDIndex = 8
} else {
sessionIDIndex = 2
}
h.SessionID, _, _ = unpackUint32L(msg, sessionIDIndex)
h.Sequence, _, _ = unpackUint32L(msg, sessionIDIndex+4)
h.PayloadLength, _, _ = unpackUint16L(msg, sessionIDIndex+8)
return nil
}
type Session20 struct {
SessionHeader20 *SessionHeader20
// for encrypted packets, it should contain Confidentiality Header, Encrypted Payload, and Confidentiality Trailer.
SessionPayload []byte
// For IPMI v2.0 RMCP+ packets, the IPMI Session Trailer is absent whenever the Session ID is 0000_0000h, or whenever bit 6 in the payload type field indicates the packet is unauthenticated.
SessionTrailer *SessionTrailer
}
func (s *Session20) Pack() []byte {
out := s.SessionHeader20.Pack()
out = append(out, s.SessionPayload...)
if s.SessionTrailer != nil {
out = append(out, s.SessionTrailer.Pack()...)
}
return out
}
func (s *Session20) Unpack(msg []byte) error {
sessionHeader := &SessionHeader20{}
if err := sessionHeader.Unpack(msg); err != nil {
return fmt.Errorf("unpack SessionHeader failed, err: %w", err)
}
s.SessionHeader20 = sessionHeader
var sessionHeaderSize int
if sessionHeader.PayloadType == PayloadTypeOEM {
sessionHeaderSize = SessionHeader20SizeMax
} else {
sessionHeaderSize = SessionHeader20SizeMin
}
payloadLength := int(s.SessionHeader20.PayloadLength)
if len(msg) < sessionHeaderSize+payloadLength {
return ErrUnpackedDataTooShortWith(len(msg), sessionHeaderSize+payloadLength)
}
s.SessionPayload, _, _ = unpackBytes(msg, sessionHeaderSize, payloadLength)
s.SessionTrailer = nil
sessionTrailerIndex := sessionHeaderSize + payloadLength
if s.SessionHeader20.PayloadAuthenticated && s.SessionHeader20.SessionID != 0 {
padSize := genSessionTrailerPadLength(sessionHeader.Pack(), s.SessionPayload)
sessionTrailer := &SessionTrailer{}
_, err := sessionTrailer.Unpack(msg, sessionTrailerIndex, padSize)
if err != nil {
return fmt.Errorf("unpack SessionTrailer failed, err: %w", err)
}
s.SessionTrailer = sessionTrailer
}
return nil
}
// For IPMI v2.0 RMCP+ packets, the IPMI Session Trailer is absent whenever the Session ID is 0000_0000h, or whenever bit 6 in the payload type field indicates the packet is unauthenticated
type SessionTrailer struct {
// IPMI 2.0 and ASF only
// Added as needed to cause the number of bytes in the data range covered by the AuthCode (Integrity Data) field to be a multiple of 4 bytes (DWORD). If present, each Integrity Pad byte is set to FFh.
IntegrityPAD []byte
// indicates how many pad bytes were added so that the amount of non-pad data can be determined.
PadLength uint8
// Reserved in IPMI v2.0. Set to 07h for RMCP+ packets defined in this specification.
NextHeader uint8
// For IPMI v2.0 (RMCP+) if this field is present, then it is calculated according to the Integrity Algorithm that was negotiated during the session open process. See Table 13-, Integrity Algorithm Numbers.
// This field is absent when the packet is unauthenticated.
AuthCode []byte // Integrity Data
}
func (s *SessionTrailer) Pack() []byte {
msg := make([]byte, len(s.IntegrityPAD)+2+len(s.AuthCode))
packBytes(s.IntegrityPAD, msg, 0)
packUint8(s.PadLength, msg, len(s.IntegrityPAD))
packUint8(s.NextHeader, msg, len(s.IntegrityPAD)+1)
packBytes(s.AuthCode, msg, len(s.IntegrityPAD)+2)
return msg
}
func (s *SessionTrailer) Unpack(msg []byte, off int, padSize int) (int, error) {
var err error
s.IntegrityPAD, off, _ = unpackBytes(msg, off, padSize)
s.PadLength, off, _ = unpackUint8(msg, off)
s.NextHeader, off, _ = unpackUint8(msg, off)
s.AuthCode, off, _ = unpackBytesMost(msg, off, 16)
return off, err
}
type SessionState uint8
const (
SessionStatePreSession SessionState = 0x00
SessionStateOpenSessionSent SessionState = 0x01
SessionStateOpenSessionReceived SessionState = 0x02
SessionStateRakp1Sent SessionState = 0x03
SessionStateRakp2Received SessionState = 0x04
SessionStateRakp3Sent SessionState = 0x05
SessionStateActive SessionState = 0x06
SessionStateCloseSent SessionState = 0x07
)
func (c *Client) genSession15(rawPayload []byte) (*Session15, error) {
c.lock()
defer c.unlock()
sessionHeader := &SessionHeader15{
AuthType: AuthTypeNone,
Sequence: 0,
SessionID: 0,
AuthCode: nil, // AuthCode would be filled afterward
PayloadLength: uint8(len(rawPayload)),
}
if c.session.v15.preSession || c.session.v15.active {
sessionHeader.AuthType = c.session.authType
sessionHeader.SessionID = c.session.v15.sessionID
}
if c.session.v15.active {
c.session.v15.inSeq += 1
sessionHeader.Sequence = c.session.v15.inSeq
}
if sessionHeader.AuthType != AuthTypeNone {
authCode := c.genAuthCodeForMultiSession(rawPayload)
sessionHeader.AuthCode = authCode
}
return &Session15{
SessionHeader15: sessionHeader,
Payload: rawPayload,
}, nil
}
func (c *Client) genSession20(payloadType PayloadType, rawPayload []byte) (*Session20, error) {
c.lock()
defer c.unlock()
//
// Session Header
//
sessionHeader := &SessionHeader20{
AuthType: AuthTypeRMCPPlus, // Auth Type / Format is always 0x06 for IPMI v2
PayloadType: payloadType,
PayloadAuthenticated: false,
PayloadEncrypted: false,
SessionID: 0,
Sequence: 0,
PayloadLength: 0, // PayloadLength would be updated later after encryption if necessary.
}
if c.session.v20.state == SessionStateActive {
sessionHeader.PayloadAuthenticated = true
sessionHeader.PayloadEncrypted = true
sessionHeader.SessionID = c.session.v20.bmcSessionID // use bmc session id
c.session.v20.sequence += 1
sessionHeader.Sequence = c.session.v20.sequence
}
//
// Session Payload
//
sessionPayload := rawPayload
if c.session.v20.state == SessionStateActive && sessionHeader.PayloadEncrypted {
e, err := c.encryptPayload(rawPayload, nil)
if err != nil {
return nil, fmt.Errorf("encrypt payload failed, err: %w", err)
}
sessionPayload = e
}
// now we can fill PayloadLength field of the SessionHeader
sessionHeader.PayloadLength = uint16(len(sessionPayload))
c.DebugBytes("sessionPayload(final)", sessionPayload, 16)
sessionHeaderBytes := sessionHeader.Pack()
c.DebugBytes("sessionHeader", sessionHeaderBytes, 16)
//
// Session Trailer
//
var sessionTrailer *SessionTrailer = nil
var err error
// For IPMI v2.0 RMCP+ packets, the IPMI Session Trailer is absent
// whenever the Session ID is 0000_0000h, or the packet is unauthenticated
if sessionHeader.PayloadAuthenticated && sessionHeader.SessionID != 0 {
sessionTrailer, err = c.genSessionTrailer(sessionHeaderBytes, sessionPayload)
if err != nil {
return nil, fmt.Errorf("genSessionTrailer failed, err: %w", err)
}
}
return &Session20{
SessionHeader20: sessionHeader,
SessionPayload: sessionPayload,
SessionTrailer: sessionTrailer,
}, nil
}
func genSessionTrailerPadLength(sessionHeader []byte, sessionPayload []byte) int {
// (12) sessionHeader length
// sessionPayload length
// (1) pad length field
// (1) next header field
length := len(sessionHeader) + len(sessionPayload) + 1 + 1
var padSize int = 0
if length%4 != 0 {
padSize = 4 - int(length%4)
}
return padSize
}
// genSessionTrailer will create the SessionTrailer.
//
// see 13.28.4 Integrity Algorithms
// Unless otherwise specified, the integrity algorithm is applied to the packet
// data starting with the AuthType/Format field up to and including the field
// that immediately precedes the AuthCode field itself.
func (c *Client) genSessionTrailer(sessionHeader []byte, sessionPayload []byte) (*SessionTrailer, error) {
padSize := genSessionTrailerPadLength(sessionHeader, sessionPayload)
var pad = make([]byte, padSize)
for i := 0; i < padSize; i++ {
pad[i] = 0xff
}
sessionTrailer := &SessionTrailer{
IntegrityPAD: pad,
PadLength: uint8(padSize),
NextHeader: 0x07, /* Hardcoded per the spec, table 13-8 */
AuthCode: nil,
}
var input []byte = sessionHeader
input = append(input, sessionPayload...)
input = append(input, sessionTrailer.IntegrityPAD...)
input = append(input, sessionTrailer.PadLength)
input = append(input, sessionTrailer.NextHeader)
c.DebugBytes("auth code input", input, 16)
authCode, err := c.genIntegrityAuthCode(input)
if err != nil {
return nil, fmt.Errorf("generate integrity authcode failed, err: %w", err)
}
c.DebugBytes("generated auth code", authCode, 16)
sessionTrailer.AuthCode = authCode
return sessionTrailer, nil
}
// the input data only represents the serialized ipmi msg request bytes.
// the output bytes contains the
// - Confidentiality Header (clear text)
// - Encrypted Payload.
// - the cipher text of both rawPayload
// - padded Confidentiality Trailer.
func (c *Client) encryptPayload(rawPayload []byte, iv []byte) ([]byte, error) {
switch c.session.v20.cryptAlg {
case CryptAlg_None:
return rawPayload, nil
case CryptAlg_AES_CBC_128:
// The input to the AES encryption algorithm has to be a multiple of the block size (16 bytes).
// The extra byte we are adding is the pad length byte.
var paddedData = rawPayload
var padLength uint8
if mod := (len(rawPayload) + 1) % int(Encryption_AES_CBS_128_BlockSize); mod > 0 {
padLength = Encryption_AES_CBS_128_BlockSize - uint8(mod)
} else {
padLength = 0
}
for i := uint8(0); i < padLength; i++ {
paddedData = append(paddedData, i+1)
}
paddedData = append(paddedData, padLength) // now, the length of data SHOULD be multiple of 16
c.DebugBytes("padded data (before encrypt)", paddedData, 16)
// see 13.29 Table 13-, AES-CBC Encrypted Payload Fields
if len(iv) == 0 {
iv = randomBytes(16) // Initialization Vector
}
c.DebugBytes("random iv", iv, 16)
// see 13.29.2 Encryption with AES
// AES-128 uses a 128-bit Cipher Key. The Cipher Key is the first 128-bits of key K2
cipherKey := c.session.v20.k2[0:16]
c.DebugBytes("cipher key (k2)", cipherKey, 16)
encryptedPayload, err := encryptAES(paddedData, cipherKey, iv)
if err != nil {
return nil, fmt.Errorf("encrypt payload with AES_CBC_128 failed, err: %w", err)
}
c.DebugBytes("encrypted data", encryptedPayload, 16)
var out []byte
// write Confidentiality Header
out = append(out, iv...)
// write Encrypted Payload
out = append(out, encryptedPayload...)
c.DebugBytes("encrypted session payload", out, 16)
return out, nil
case CryptAlg_xRC4_40, CryptAlg_xRC4_128:
var out []byte
// see 13.30 Table 13-, xRC4-Encrypted Payload Fields
var confidentialityHeader []byte
var offset = make([]byte, 4)
if c.session.v20.accumulatedPayloadSize == 0 {
// means this is the first sent packet
for i := 0; i < 4; i++ {
offset[i] = 0
}
c.session.v20.rc4EncryptIV = array16(randomBytes(16))
confidentialityHeader = append(offset, c.session.v20.rc4EncryptIV[:]...)
} else {
binary.BigEndian.PutUint32(offset, c.session.v20.accumulatedPayloadSize)
confidentialityHeader = offset
}
c.session.v20.accumulatedPayloadSize += uint32(len(rawPayload))
iv := c.session.v20.rc4EncryptIV[:]
out = append(out, confidentialityHeader...)
input := append(c.session.v20.k2, iv...)
keyRC := md5.New().Sum(input)
var cipherKey []byte
switch c.session.v20.cryptAlg {
case CryptAlg_xRC4_40:
// For xRC4 using a 40-bit key, only the most significant forty bits of Krc are used
cipherKey = keyRC[:5]
case CryptAlg_xRC4_128:
// For xRC4 using a 128-bit key, all bits of Krc are used for initialization
cipherKey = keyRC[:16]
}
encryptedPayload, err := encryptRC4(rawPayload, cipherKey, iv)
if err != nil {
return nil, fmt.Errorf("encrypt payload with xRC4_40 or xRC4_128 failed, err: %w", err)
}
// write Encrypted Payload
out = append(out, encryptedPayload...)
// xRC4 does not use a confidentiality trailer.
return out, nil
default:
return nil, fmt.Errorf("not supported encryption algorithm %x", c.session.v20.cryptAlg)
}
}
// the input data is the encrypted session payload.
// the output bytes is the decrypted IPMI Message bytes with padding removed.
func (c *Client) decryptPayload(data []byte) ([]byte, error) {
switch c.session.v20.cryptAlg {
case CryptAlg_None:
return data, nil
case CryptAlg_AES_CBC_128:
iv := data[0:16] // the first 16 byte is the initialization vector
cipherText := data[16:]
cipherKey := c.session.v20.k2[0:16]
d, err := decryptAES(cipherText, cipherKey, iv)
if err != nil {
return nil, fmt.Errorf("decrypt payload with AES_CBC_128 failed, err: %w", err)
}
padLength := d[len(d)-1]
dEnd := len(d) - int(padLength) - 1
return d[0:dEnd], nil
case CryptAlg_xRC4_40, CryptAlg_xRC4_128:
// the first received packet
if data[0] == 0x0 && data[1] == 0x0 && data[2] == 0x0 && data[3] == 0x0 {
c.session.v20.rc4DecryptIV = array16(data[4:20])
}
iv := c.session.v20.rc4DecryptIV[:]
input := append(c.session.v20.k2, iv...)
keyRC := md5.New().Sum(input)
var cipherKey []byte
switch c.session.v20.cryptAlg {
case CryptAlg_xRC4_40:
// For xRC4 using a 40-bit key, only the most significant forty bits of Krc are used
cipherKey = keyRC[:5]
case CryptAlg_xRC4_128:
// For xRC4 using a 128-bit key, all bits of Krc are used for initialization
cipherKey = keyRC[:16]
}
payloadData := data[20:]
b, err := decryptRC4(payloadData, cipherKey, iv)
if err != nil {
return nil, fmt.Errorf("decrypt payload with xRC4_128 failed, err: %w", err)
}
return b, nil
default:
return nil, fmt.Errorf("not supported encryption algorithm %0x", c.session.v20.cryptAlg)
}
}
golang-github-bougou-go-ipmi-0.7.2/types_sol_config_params.go 0000664 0000000 0000000 00000026341 14741105271 0024354 0 ustar 00root root 0000000 0000000 package ipmi
import "fmt"
type SOLConfigParamSelector uint8
const (
SOLConfigParamSelector_SetInProgress SOLConfigParamSelector = 0x00
SOLConfigParamSelector_SOLEnable SOLConfigParamSelector = 0x01
SOLConfigParamSelector_SOLAuthentication SOLConfigParamSelector = 0x02
SOLConfigParamSelector_Character SOLConfigParamSelector = 0x03
SOLConfigParamSelector_SOLRetry SOLConfigParamSelector = 0x04
SOLConfigParamSelector_NonVolatileBitRate SOLConfigParamSelector = 0x05
SOLConfigParamSelector_VolatileBitRate SOLConfigParamSelector = 0x06
SOLConfigParamSelector_PayloadChannel SOLConfigParamSelector = 0x07
SOLConfigParamSelector_PayloadPort SOLConfigParamSelector = 0x08
)
func (p SOLConfigParamSelector) String() string {
m := map[SOLConfigParamSelector]string{
SOLConfigParamSelector_SetInProgress: "Set In Progress",
SOLConfigParamSelector_SOLEnable: "SOL Enable",
SOLConfigParamSelector_SOLAuthentication: "SOL Authentication",
SOLConfigParamSelector_Character: "Character",
SOLConfigParamSelector_SOLRetry: "SOL Retry",
SOLConfigParamSelector_NonVolatileBitRate: "Non-Volatile Bit Rate",
SOLConfigParamSelector_VolatileBitRate: "Volatile Bit Rate",
SOLConfigParamSelector_PayloadChannel: "Payload Channel",
SOLConfigParamSelector_PayloadPort: "Payload Port",
}
s, ok := m[p]
if ok {
return s
}
return "Unknown"
}
type SOLConfigParameter interface {
SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8)
Parameter
}
var (
_ SOLConfigParameter = (*SOLConfigParam_SetInProgress)(nil)
_ SOLConfigParameter = (*SOLConfigParam_SOLEnable)(nil)
_ SOLConfigParameter = (*SOLConfigParam_SOLAuthentication)(nil)
_ SOLConfigParameter = (*SOLConfigParam_Character)(nil)
_ SOLConfigParameter = (*SOLConfigParam_SOLRetry)(nil)
_ SOLConfigParameter = (*SOLConfigParam_NonVolatileBitRate)(nil)
_ SOLConfigParameter = (*SOLConfigParam_VolatileBitRate)(nil)
_ SOLConfigParameter = (*SOLConfigParam_PayloadChannel)(nil)
_ SOLConfigParameter = (*SOLConfigParam_PayloadPort)(nil)
)
func isNilSOLConfigParameter(param SOLConfigParameter) bool {
switch v := param.(type) {
case *SOLConfigParam_SetInProgress:
return v == nil
case *SOLConfigParam_SOLEnable:
return v == nil
case *SOLConfigParam_SOLAuthentication:
return v == nil
case *SOLConfigParam_Character:
return v == nil
case *SOLConfigParam_SOLRetry:
return v == nil
case *SOLConfigParam_NonVolatileBitRate:
return v == nil
case *SOLConfigParam_VolatileBitRate:
return v == nil
case *SOLConfigParam_PayloadChannel:
return v == nil
case *SOLConfigParam_PayloadPort:
return v == nil
default:
return false
}
}
type SOLConfigParams struct {
SetInProgress *SOLConfigParam_SetInProgress
SOLEnable *SOLConfigParam_SOLEnable
SOLAuthentication *SOLConfigParam_SOLAuthentication
Character *SOLConfigParam_Character
SOLRetry *SOLConfigParam_SOLRetry
NonVolatileBitRate *SOLConfigParam_NonVolatileBitRate
VolatileBitRate *SOLConfigParam_VolatileBitRate
PayloadChannel *SOLConfigParam_PayloadChannel
PayloadPort *SOLConfigParam_PayloadPort
}
func (p *SOLConfigParams) Format() string {
format := func(param SOLConfigParameter) string {
if isNilSOLConfigParameter(param) {
return ""
}
paramSelector, _, _ := param.SOLConfigParameter()
content := param.Format()
if content[len(content)-1] != '\n' {
content += "\n"
}
return fmt.Sprintf("[%2d] %-22s : %s", paramSelector, paramSelector.String(), content)
}
out := ""
out += format(p.SetInProgress)
out += format(p.SOLEnable)
out += format(p.SOLAuthentication)
out += format(p.Character)
out += format(p.SOLRetry)
out += format(p.NonVolatileBitRate)
out += format(p.VolatileBitRate)
out += format(p.PayloadChannel)
out += format(p.PayloadPort)
return out
}
type SOLConfigParam_SetInProgress struct {
Value SetInProgressState
}
func (p *SOLConfigParam_SetInProgress) SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8) {
return SOLConfigParamSelector_SetInProgress, 0x00, 0x00
}
func (p *SOLConfigParam_SetInProgress) Unpack(paramData []byte) error {
if len(paramData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
p.Value = SetInProgressState(paramData[0])
return nil
}
func (p *SOLConfigParam_SetInProgress) Pack() []byte {
return []byte{byte(p.Value)}
}
func (p *SOLConfigParam_SetInProgress) Format() string {
return p.Value.String()
}
type SOLConfigParam_SOLEnable struct {
EnableSOLPayload bool
}
func (p *SOLConfigParam_SOLEnable) SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8) {
return SOLConfigParamSelector_SOLEnable, 0x00, 0x00
}
func (p *SOLConfigParam_SOLEnable) Unpack(paramData []byte) error {
if len(paramData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
p.EnableSOLPayload = isBit0Set(paramData[0])
return nil
}
func (p *SOLConfigParam_SOLEnable) Pack() []byte {
var b uint8 = 0x00
b = setOrClearBit0(b, p.EnableSOLPayload)
return []byte{b}
}
func (p *SOLConfigParam_SOLEnable) Format() string {
return fmt.Sprintf("%v", p.EnableSOLPayload)
}
type SOLConfigParam_SOLAuthentication struct {
ForceEncryption bool
ForceAuthentication bool
PrivilegeLevel uint8
}
func (p *SOLConfigParam_SOLAuthentication) SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8) {
return SOLConfigParamSelector_SOLAuthentication, 0x00, 0x00
}
func (p *SOLConfigParam_SOLAuthentication) Unpack(paramData []byte) error {
if len(paramData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
b := paramData[0]
p.ForceEncryption = isBit7Set(b)
p.ForceAuthentication = isBit6Set(b)
p.PrivilegeLevel = b & 0x0f
return nil
}
func (p *SOLConfigParam_SOLAuthentication) Pack() []byte {
var b uint8 = 0x00
if p.ForceEncryption {
b = setBit7(b)
}
if p.ForceAuthentication {
b = setBit6(b)
}
b |= p.PrivilegeLevel
return []byte{b}
}
func (p *SOLConfigParam_SOLAuthentication) Format() string {
return fmt.Sprintf(`
Force Encryption : %v
Force Authentication : %v
Privilege Level : %#02x
`, p.ForceEncryption, p.ForceAuthentication, p.PrivilegeLevel)
}
type SOLConfigParam_Character struct {
AccumulateInterval5Millis uint8
SendThreshold uint8
}
func (p *SOLConfigParam_Character) SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8) {
return SOLConfigParamSelector_Character, 0x00, 0x00
}
func (p *SOLConfigParam_Character) Unpack(paramData []byte) error {
if len(paramData) != 2 {
return fmt.Errorf("the parameter data length must be 2 byte")
}
p.AccumulateInterval5Millis = paramData[0]
p.SendThreshold = paramData[1]
return nil
}
func (p *SOLConfigParam_Character) Pack() []byte {
return []byte{p.AccumulateInterval5Millis, p.SendThreshold}
}
func (p *SOLConfigParam_Character) Format() string {
return fmt.Sprintf(`
Accumulate Interval (ms) : %d
Send Threshold : %d
`, p.AccumulateInterval5Millis*5, p.SendThreshold)
}
type SOLConfigParam_SOLRetry struct {
// 1-based. 0 = no retries after packet is transmitted. Packet will be
// dropped if no ACK/NACK received by time retries expire.
RetryCount uint8
// 1-based. Retry Interval in 10 ms increments. Sets the time that
// the BMC will wait before the first retry and the time between retries when sending
// SOL packets to the remote console.
// 00h: Retries sent back-to-back
RetryInterval10Millis uint8
}
func (p *SOLConfigParam_SOLRetry) SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8) {
return SOLConfigParamSelector_SOLRetry, 0x00, 0x00
}
func (p *SOLConfigParam_SOLRetry) Unpack(paramData []byte) error {
if len(paramData) != 2 {
return fmt.Errorf("the parameter data length must be 2 byte")
}
p.RetryCount = paramData[0]
p.RetryInterval10Millis = paramData[1]
return nil
}
func (p *SOLConfigParam_SOLRetry) Pack() []byte {
return []byte{p.RetryCount, p.RetryInterval10Millis}
}
func (p *SOLConfigParam_SOLRetry) Format() string {
return fmt.Sprintf(`
Retry Count : %d
Retry Interval (ms) : %d
`, p.RetryCount, p.RetryInterval10Millis*10)
}
type SOLConfigParam_NonVolatileBitRate struct {
BitRate uint8
}
func (p *SOLConfigParam_NonVolatileBitRate) SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8) {
return SOLConfigParamSelector_NonVolatileBitRate, 0x00, 0x00
}
func (p *SOLConfigParam_NonVolatileBitRate) Unpack(paramData []byte) error {
if len(paramData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
p.BitRate = paramData[0]
return nil
}
func (p *SOLConfigParam_NonVolatileBitRate) Pack() []byte {
return []byte{p.BitRate}
}
func (p *SOLConfigParam_NonVolatileBitRate) Format() string {
return fmt.Sprintf("%.1f kbps (%d)", bitRateKBPS(p.BitRate), p.BitRate)
}
func bitRateKBPS(bitRate uint8) float64 {
m := map[uint8]float64{
0x06: 9.6,
0x07: 19.2,
0x08: 38.4,
0x09: 57.6,
0x0a: 115.2,
}
s, ok := m[bitRate]
if ok {
return s
}
return 0
}
type SOLConfigParam_VolatileBitRate struct {
BitRate uint8
}
func (p *SOLConfigParam_VolatileBitRate) SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8) {
return SOLConfigParamSelector_VolatileBitRate, 0x00, 0x00
}
func (p *SOLConfigParam_VolatileBitRate) Unpack(paramData []byte) error {
if len(paramData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
p.BitRate = paramData[0]
return nil
}
func (p *SOLConfigParam_VolatileBitRate) Pack() []byte {
return []byte{p.BitRate}
}
func (p *SOLConfigParam_VolatileBitRate) Format() string {
return fmt.Sprintf("%.1f kbps (%d)", bitRateKBPS(p.BitRate), p.BitRate)
}
type SOLConfigParam_PayloadChannel struct {
ChannelNumber uint8
}
func (p *SOLConfigParam_PayloadChannel) SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8) {
return SOLConfigParamSelector_PayloadChannel, 0x00, 0x00
}
func (p *SOLConfigParam_PayloadChannel) Unpack(paramData []byte) error {
if len(paramData) != 1 {
return fmt.Errorf("the parameter data length must be 1 byte")
}
p.ChannelNumber = paramData[0]
return nil
}
func (p *SOLConfigParam_PayloadChannel) Pack() []byte {
return []byte{p.ChannelNumber}
}
func (p *SOLConfigParam_PayloadChannel) Format() string {
return fmt.Sprintf("%d", p.ChannelNumber)
}
type SOLConfigParam_PayloadPort struct {
Port uint16
}
func (p *SOLConfigParam_PayloadPort) SOLConfigParameter() (paramSelector SOLConfigParamSelector, setSelector uint8, blockSelector uint8) {
return SOLConfigParamSelector_PayloadPort, 0x00, 0x00
}
func (p *SOLConfigParam_PayloadPort) Unpack(paramData []byte) error {
if len(paramData) != 2 {
return fmt.Errorf("the parameter data length must be 2 byte")
}
p.Port, _, _ = unpackUint16L(paramData, 0)
return nil
}
func (p *SOLConfigParam_PayloadPort) Pack() []byte {
out := make([]byte, 2)
packUint16L(p.Port, out, 0)
return out
}
func (p *SOLConfigParam_PayloadPort) Format() string {
return fmt.Sprintf("%d", p.Port)
}
golang-github-bougou-go-ipmi-0.7.2/types_system_info_params.go 0000664 0000000 0000000 00000031550 14741105271 0024567 0 ustar 00root root 0000000 0000000 package ipmi
import (
"fmt"
)
type SystemInfoParamSelector uint8
const (
SystemInfoParamSelector_SetInProgress SystemInfoParamSelector = 0
SystemInfoParamSelector_SystemFirmwareVersion SystemInfoParamSelector = 1
SystemInfoParamSelector_SystemName SystemInfoParamSelector = 2
SystemInfoParamSelector_PrimaryOSName SystemInfoParamSelector = 3
SystemInfoParamSelector_OSName SystemInfoParamSelector = 4
SystemInfoParamSelector_OSVersion SystemInfoParamSelector = 5
SystemInfoParamSelector_BMCURL SystemInfoParamSelector = 6
SystemInfoParamSelector_ManagementURL SystemInfoParamSelector = 7
)
func (paramSelector SystemInfoParamSelector) String() string {
m := map[SystemInfoParamSelector]string{
SystemInfoParamSelector_SetInProgress: "Set In Progress",
SystemInfoParamSelector_SystemFirmwareVersion: "System Firmware Version",
SystemInfoParamSelector_SystemName: "System Name",
SystemInfoParamSelector_PrimaryOSName: "Primary OS Name",
SystemInfoParamSelector_OSName: "OS Name",
SystemInfoParamSelector_OSVersion: "OS Version",
SystemInfoParamSelector_BMCURL: "BMC URL",
SystemInfoParamSelector_ManagementURL: "Management URL",
}
s, ok := m[paramSelector]
if ok {
return s
}
return "Unknown"
}
type SystemInfoParameter interface {
SystemInfoParameter() (paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8)
Parameter
}
var (
_ SystemInfoParameter = (*SystemInfoParam_SetInProgress)(nil)
_ SystemInfoParameter = (*SystemInfoParam_SystemFirmwareVersion)(nil)
_ SystemInfoParameter = (*SystemInfoParam_SystemName)(nil)
_ SystemInfoParameter = (*SystemInfoParam_PrimaryOSName)(nil)
_ SystemInfoParameter = (*SystemInfoParam_OSName)(nil)
_ SystemInfoParameter = (*SystemInfoParam_OSVersion)(nil)
_ SystemInfoParameter = (*SystemInfoParam_BMCURL)(nil)
_ SystemInfoParameter = (*SystemInfoParam_ManagementURL)(nil)
)
func isNilSystemInfoParamete(param SystemInfoParameter) bool {
switch v := param.(type) {
case *SystemInfoParam_SetInProgress:
return v == nil
case *SystemInfoParam_SystemFirmwareVersion:
return v == nil
case *SystemInfoParam_SystemName:
return v == nil
case *SystemInfoParam_PrimaryOSName:
return v == nil
case *SystemInfoParam_OSName:
return v == nil
case *SystemInfoParam_OSVersion:
return v == nil
case *SystemInfoParam_BMCURL:
return v == nil
case *SystemInfoParam_ManagementURL:
return v == nil
default:
return false
}
}
type SystemInfoParams struct {
SetInProgress *SystemInfoParam_SetInProgress
SystemFirmwareVersions []*SystemInfoParam_SystemFirmwareVersion
SystemNames []*SystemInfoParam_SystemName
PrimaryOSNames []*SystemInfoParam_PrimaryOSName
OSNames []*SystemInfoParam_OSName
OSVersions []*SystemInfoParam_OSVersion
BMCURLs []*SystemInfoParam_BMCURL
ManagementURLs []*SystemInfoParam_ManagementURL
}
type SystemInfo struct {
SetInProgress SetInProgressState
SystemFirmwareVersion string
SystemName string
PrimaryOSName string
OSName string
OSVersion string
BMCURL string
ManagementURL string
}
func (systemInfoParams *SystemInfoParams) ToSystemInfo() *SystemInfo {
systemInfo := &SystemInfo{
SetInProgress: systemInfoParams.SetInProgress.Value,
}
systemInfo.SystemFirmwareVersion, _, _, _ = getSystemInfoStringMeta(convertToInterfaceSlice(systemInfoParams.SystemFirmwareVersions))
systemInfo.SystemName, _, _, _ = getSystemInfoStringMeta(convertToInterfaceSlice(systemInfoParams.SystemNames))
systemInfo.PrimaryOSName, _, _, _ = getSystemInfoStringMeta(convertToInterfaceSlice(systemInfoParams.PrimaryOSNames))
systemInfo.OSName, _, _, _ = getSystemInfoStringMeta(convertToInterfaceSlice(systemInfoParams.OSNames))
systemInfo.OSVersion, _, _, _ = getSystemInfoStringMeta(convertToInterfaceSlice(systemInfoParams.OSVersions))
systemInfo.BMCURL, _, _, _ = getSystemInfoStringMeta(convertToInterfaceSlice(systemInfoParams.BMCURLs))
systemInfo.ManagementURL, _, _, _ = getSystemInfoStringMeta(convertToInterfaceSlice(systemInfoParams.ManagementURLs))
return systemInfo
}
func (systemInfoParams *SystemInfoParams) Format() string {
format := func(param SystemInfoParameter) string {
if isNilSystemInfoParamete(param) {
return ""
}
paramSelector, _, _ := param.SystemInfoParameter()
content := param.Format()
if content[len(content)-1] != '\n' {
content += "\n"
}
return fmt.Sprintf("[%02d] %-24s : %s", paramSelector, paramSelector.String(), content)
}
formatArray := func(params []interface{}) string {
if len(params) == 0 {
return ""
}
out := ""
for _, param := range params {
v, ok := param.(SystemInfoParameter)
if ok {
out += format(v)
}
}
s, stringDataRaw, stringDataType, stringDataLength := getSystemInfoStringMeta(params)
out += fmt.Sprintf(`
String Data Type : %d
String Data Length : %d
String Data Raw : %v
String Data : %s
`, stringDataType, stringDataLength, stringDataRaw, s,
)
return out
}
out := ""
out += format(systemInfoParams.SetInProgress)
out += formatArray(convertToInterfaceSlice(systemInfoParams.SystemFirmwareVersions))
out += formatArray(convertToInterfaceSlice(systemInfoParams.SystemNames))
out += formatArray(convertToInterfaceSlice(systemInfoParams.PrimaryOSNames))
out += formatArray(convertToInterfaceSlice(systemInfoParams.OSNames))
out += formatArray(convertToInterfaceSlice(systemInfoParams.OSVersions))
out += formatArray(convertToInterfaceSlice(systemInfoParams.BMCURLs))
out += formatArray(convertToInterfaceSlice(systemInfoParams.ManagementURLs))
return out
}
func (systemInfo *SystemInfo) Format() string {
return fmt.Sprintf(`
Set In Progress : %s
System Firmware Version : %s
System Name : %s
Primary OS Name : %s
OS Name : %s
OS Version : %s
BVM URL : %s
Management URL : %s
`,
systemInfo.SetInProgress,
systemInfo.SystemFirmwareVersion,
systemInfo.SystemName,
systemInfo.PrimaryOSName,
systemInfo.OSName,
systemInfo.OSVersion,
systemInfo.BMCURL,
systemInfo.ManagementURL,
)
}
type SystemInfoParam_SetInProgress struct {
Value SetInProgressState
}
func (p *SystemInfoParam_SetInProgress) SystemInfoParameter() (paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8) {
return SystemInfoParamSelector_SetInProgress, 0, 0
}
func (p *SystemInfoParam_SetInProgress) Pack() []byte {
return []byte{uint8(p.Value)}
}
func (p *SystemInfoParam_SetInProgress) Unpack(data []byte) error {
if len(data) < 1 {
return ErrUnpackedDataTooShortWith(len(data), 1)
}
p.Value = SetInProgressState(data[0])
return nil
}
func (p *SystemInfoParam_SetInProgress) Format() string {
return p.Value.String()
}
type SystemInfoParam_SystemFirmwareVersion struct {
SetSelector uint8
BlockData [16]byte
}
func (p *SystemInfoParam_SystemFirmwareVersion) SystemInfoParameter() (paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8) {
return SystemInfoParamSelector_SystemFirmwareVersion, 0, 0
}
func (p *SystemInfoParam_SystemFirmwareVersion) Pack() []byte {
out := make([]byte, 1+len(p.BlockData))
packUint8(p.SetSelector, out, 0)
packBytes(p.BlockData[:], out, 1)
return out
}
func (p *SystemInfoParam_SystemFirmwareVersion) Unpack(data []byte) error {
if len(data) < 1+len(p.BlockData) {
return ErrUnpackedDataTooShortWith(len(data), 1+len(p.BlockData))
}
p.SetSelector = data[0]
copy(p.BlockData[:], data[1:])
return nil
}
func (p *SystemInfoParam_SystemFirmwareVersion) Format() string {
return fmt.Sprintf(`
Set Selector : %d
Block Data : %02x
`, p.SetSelector, p.BlockData)
}
type SystemInfoParam_SystemName struct {
SetSelector uint8
BlockData [16]byte
}
func (p *SystemInfoParam_SystemName) SystemInfoParameter() (paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8) {
return SystemInfoParamSelector_SystemName, 0, 0
}
func (p *SystemInfoParam_SystemName) Pack() []byte {
out := make([]byte, 1+len(p.BlockData))
packUint8(p.SetSelector, out, 0)
packBytes(p.BlockData[:], out, 1)
return out
}
func (p *SystemInfoParam_SystemName) Unpack(data []byte) error {
if len(data) < 1+len(p.BlockData) {
return ErrUnpackedDataTooShortWith(len(data), 1+len(p.BlockData))
}
p.SetSelector = data[0]
copy(p.BlockData[:], data[1:])
return nil
}
func (p *SystemInfoParam_SystemName) Format() string {
return fmt.Sprintf(`
Set Selector : %d
Block Data : %02x
`, p.SetSelector, p.BlockData)
}
type SystemInfoParam_PrimaryOSName struct {
SetSelector uint8
BlockData [16]byte
}
func (p *SystemInfoParam_PrimaryOSName) SystemInfoParameter() (paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8) {
return SystemInfoParamSelector_PrimaryOSName, 0, 0
}
func (p *SystemInfoParam_PrimaryOSName) Pack() []byte {
out := make([]byte, 1+len(p.BlockData))
packUint8(p.SetSelector, out, 0)
packBytes(p.BlockData[:], out, 1)
return out
}
func (p *SystemInfoParam_PrimaryOSName) Unpack(data []byte) error {
if len(data) < 1+len(p.BlockData) {
return ErrUnpackedDataTooShortWith(len(data), 1+len(p.BlockData))
}
p.SetSelector = data[0]
copy(p.BlockData[:], data[1:])
return nil
}
func (p *SystemInfoParam_PrimaryOSName) Format() string {
return fmt.Sprintf(`
Set Selector : %d
Block Data : %02x
`, p.SetSelector, p.BlockData)
}
type SystemInfoParam_OSName struct {
SetSelector uint8
BlockData [16]byte
}
func (p *SystemInfoParam_OSName) SystemInfoParameter() (paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8) {
return SystemInfoParamSelector_OSName, 0, 0
}
func (p *SystemInfoParam_OSName) Pack() []byte {
out := make([]byte, 1+len(p.BlockData))
packUint8(p.SetSelector, out, 0)
packBytes(p.BlockData[:], out, 1)
return out
}
func (p *SystemInfoParam_OSName) Unpack(data []byte) error {
if len(data) < 1+len(p.BlockData) {
return ErrUnpackedDataTooShortWith(len(data), 1+len(p.BlockData))
}
p.SetSelector = data[0]
copy(p.BlockData[:], data[1:])
return nil
}
func (p *SystemInfoParam_OSName) Format() string {
return fmt.Sprintf(`
Set Selector : %d
Block Data : %02x
`, p.SetSelector, p.BlockData)
}
type SystemInfoParam_OSVersion struct {
SetSelector uint8
BlockData [16]byte
}
func (p *SystemInfoParam_OSVersion) SystemInfoParameter() (paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8) {
return SystemInfoParamSelector_OSVersion, 0, 0
}
func (p *SystemInfoParam_OSVersion) Pack() []byte {
out := make([]byte, 1+len(p.BlockData))
packUint8(p.SetSelector, out, 0)
packBytes(p.BlockData[:], out, 1)
return out
}
func (p *SystemInfoParam_OSVersion) Unpack(data []byte) error {
if len(data) < 1+len(p.BlockData) {
return ErrUnpackedDataTooShortWith(len(data), 1+len(p.BlockData))
}
p.SetSelector = data[0]
copy(p.BlockData[:], data[1:])
return nil
}
func (p *SystemInfoParam_OSVersion) Format() string {
return fmt.Sprintf(`
Set Selector : %d
Block Data : %02x
`, p.SetSelector, p.BlockData)
}
type SystemInfoParam_BMCURL struct {
SetSelector uint8
BlockData [16]byte
}
func (p *SystemInfoParam_BMCURL) SystemInfoParameter() (paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8) {
return SystemInfoParamSelector_BMCURL, 0, 0
}
func (p *SystemInfoParam_BMCURL) Pack() []byte {
out := make([]byte, 1+len(p.BlockData))
packUint8(p.SetSelector, out, 0)
packBytes(p.BlockData[:], out, 1)
return out
}
func (p *SystemInfoParam_BMCURL) Unpack(data []byte) error {
if len(data) < 1+len(p.BlockData) {
return ErrUnpackedDataTooShortWith(len(data), 1+len(p.BlockData))
}
p.SetSelector = data[0]
copy(p.BlockData[:], data[1:])
return nil
}
func (p *SystemInfoParam_BMCURL) Format() string {
return fmt.Sprintf(`
Set Selector : %d
Block Data : %02x
`, p.SetSelector, p.BlockData)
}
type SystemInfoParam_ManagementURL struct {
SetSelector uint8
BlockData [16]byte
}
func (p *SystemInfoParam_ManagementURL) SystemInfoParameter() (paramSelector SystemInfoParamSelector, setSelector uint8, blockSelector uint8) {
return SystemInfoParamSelector_ManagementURL, 0, 0
}
func (p *SystemInfoParam_ManagementURL) Pack() []byte {
out := make([]byte, 1+len(p.BlockData))
packUint8(p.SetSelector, out, 0)
packBytes(p.BlockData[:], out, 1)
return out
}
func (p *SystemInfoParam_ManagementURL) Unpack(data []byte) error {
if len(data) < 1+len(p.BlockData) {
return ErrUnpackedDataTooShortWith(len(data), 1+len(p.BlockData))
}
p.SetSelector = data[0]
copy(p.BlockData[:], data[1:])
return nil
}
func (p *SystemInfoParam_ManagementURL) Format() string {
return fmt.Sprintf(`
Set Selector : %d
Block Data : %02x
`, p.SetSelector, p.BlockData)
}
golang-github-bougou-go-ipmi-0.7.2/udpclient.go 0000664 0000000 0000000 00000007601 14741105271 0021430 0 ustar 00root root 0000000 0000000 package ipmi
import (
"context"
"fmt"
"io"
"net"
"strconv"
"sync"
"time"
"golang.org/x/net/proxy"
)
// UDPClient exposes some common methods for communicating with UDP target addr.
type UDPClient struct {
// Target Host
Host string
// Target Port
Port int
proxy proxy.Dialer
timeout time.Duration
bufferSize int
conn net.Conn
// lock is used to protect udp Exchange method to prevent another
// send/receive operation from occurring while one is in progress.
lock sync.Mutex
}
func NewUDPClient(host string, port int) *UDPClient {
udpClient := &UDPClient{
Host: host,
Port: port,
}
return udpClient
}
func (c *UDPClient) initConn() error {
if c.conn != nil {
return nil
}
if c.proxy != nil {
conn, err := c.proxy.Dial("udp", fmt.Sprintf("%s:%d", c.Host, c.Port))
if err != nil {
return fmt.Errorf("udp proxy dial failed, err: %w", err)
}
c.conn = conn
return nil
}
remoteAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", c.Host, c.Port))
if err != nil {
return fmt.Errorf("resolve addr failed, err: %w", err)
}
conn, err := net.DialUDP("udp", nil, remoteAddr)
if err != nil {
return fmt.Errorf("udp dial failed, err: %w", err)
}
c.conn = conn
return nil
}
func (c *UDPClient) SetProxy(proxy proxy.Dialer) *UDPClient {
c.proxy = proxy
return c
}
func (c *UDPClient) SetTimeout(timeout time.Duration) *UDPClient {
c.timeout = timeout
return c
}
func (c *UDPClient) SetBufferSize(bufferSize int) *UDPClient {
c.bufferSize = bufferSize
return c
}
// RemoteIP returns the parsed ip address of the target.
func (c *UDPClient) RemoteIP() string {
if net.ParseIP(c.Host) == nil {
addrs, err := net.LookupHost(c.Host)
if err == nil && len(addrs) > 0 {
return addrs[0]
}
}
return c.Host
}
func (c *UDPClient) LocalIPPort() (string, int) {
conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", c.Host, c.Port))
if err != nil {
return "", 0
}
defer conn.Close()
host, port, _ := net.SplitHostPort(conn.LocalAddr().String())
p, _ := strconv.Atoi(port)
return host, p
}
func (c *UDPClient) Close() error {
if c.conn == nil {
return nil
}
if err := c.conn.Close(); err != nil {
return fmt.Errorf("close udp conn failed, err: %w", err)
}
c.conn = nil
return nil
}
// Exchange performs a synchronous UDP query.
// It sends the request, and waits for a reply.
// Exchange does not retry a failed query.
// The sent content is read from reader.
func (c *UDPClient) Exchange(ctx context.Context, reader io.Reader) ([]byte, error) {
if err := c.initConn(); err != nil {
return nil, fmt.Errorf("init udp connection failed, err: %w", err)
}
c.lock.Lock()
defer c.lock.Unlock()
recvBuffer := make([]byte, c.bufferSize)
doneChan := make(chan error, 1)
// recvChan stores the integer number which indicates how many bytes
recvChan := make(chan int, 1)
go func() {
// It is possible that this action blocks, although this
// should only occur in very resource-intensive situations:
// - when you've filled up the socket buffer and the OS
// can't dequeue the queue fast enough.
_, err := io.Copy(c.conn, reader)
if err != nil {
doneChan <- fmt.Errorf("write to conn failed, err: %w", err)
return
}
// Set a deadline for the Read operation so that we don't
// wait forever for a server that might not respond on
// a reasonable amount of time.
deadline := time.Now().Add(c.timeout)
err = c.conn.SetReadDeadline(deadline)
if err != nil {
doneChan <- fmt.Errorf("set conn read deadline failed, err: %w", err)
return
}
nRead, err := c.conn.Read(recvBuffer)
if err != nil {
doneChan <- fmt.Errorf("read from conn failed, err: %w", err)
return
}
doneChan <- nil
recvChan <- nRead
}()
select {
case <-ctx.Done():
return nil, fmt.Errorf("canceled from caller")
case err := <-doneChan:
if err != nil {
return nil, err
}
recvCount := <-recvChan
return recvBuffer[:recvCount], nil
}
}
golang-github-bougou-go-ipmi-0.7.2/utils/ 0000775 0000000 0000000 00000000000 14741105271 0020246 5 ustar 00root root 0000000 0000000 golang-github-bougou-go-ipmi-0.7.2/utils/md2/ 0000775 0000000 0000000 00000000000 14741105271 0020730 5 ustar 00root root 0000000 0000000 golang-github-bougou-go-ipmi-0.7.2/utils/md2/md2.go 0000664 0000000 0000000 00000010233 14741105271 0021740 0 ustar 00root root 0000000 0000000 // Copyright 2012-2013 Huan Truong. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// copied from: https://github.com/htruong/go-md2/blob/master/md2.go
// Package md2 implements the MD2 hash algorithm as defined in RFC 1319.
package md2
import (
"hash"
)
func init() {
}
// The size of an MD2 checksum in bytes.
const Size = 16
// The blocksize of MD2 in bytes.
const BlockSize = 16
const _Chunk = 16
var PI_SUBST = []uint8{
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
31, 26, 219, 153, 141, 51, 159, 17, 131, 20,
}
// digest represents the partial evaluation of a checksum.
type digest struct {
digest [Size]byte // the digest, Size
state [48]byte // state, 48 ints
x [_Chunk]byte // temp storage buffer, 16 bytes, _Chunk
nx uint8 // how many bytes are there in the buffer
}
func (d *digest) Reset() {
for i := range d.digest {
d.digest[i] = 0
}
for i := range d.state {
d.state[i] = 0
}
for i := range d.x {
d.x[i] = 0
}
d.nx = 0
}
// New returns a new hash.Hash computing the MD2 checksum.
func New() hash.Hash {
d := new(digest)
d.Reset()
return d
}
func (d *digest) Size() int { return Size }
func (d *digest) BlockSize() int { return BlockSize }
// Write is the interface for IO Writer
func (d *digest) Write(p []byte) (nn int, err error) {
nn = len(p)
//d.len += uint64(nn)
// If we have something left in the buffer
if d.nx > 0 {
n := uint8(len(p))
var i uint8
// try to copy the rest n bytes free of the buffer into the buffer
// then hash the buffer
if (n + d.nx) > _Chunk {
n = _Chunk - d.nx
}
for i = 0; i < n; i++ {
// copy n bytes to the buffer
d.x[d.nx+i] = p[i]
}
d.nx += n
// if we have exactly 1 block in the buffer then hash that block
if d.nx == _Chunk {
block(d, d.x[0:_Chunk])
d.nx = 0
}
p = p[n:]
}
imax := len(p) / _Chunk
// For the rest, try hashing by the blocksize
for i := 0; i < imax; i++ {
block(d, p[:_Chunk])
p = p[_Chunk:]
}
// Then stuff the rest that doesn't add up to a block to the buffer
if len(p) > 0 {
d.nx = uint8(copy(d.x[:], p))
}
return
}
func (d0 *digest) Sum(in []byte) []byte {
// Make a copy of d0 so that caller can keep writing and summing.
d := *d0
// Padding.
var tmp [_Chunk]byte
len := uint8(d.nx)
for i := range tmp {
tmp[i] = _Chunk - len
}
d.Write(tmp[0 : _Chunk-len])
// At this state we should have nothing left in buffer
if d.nx != 0 {
panic("d.nx != 0")
}
d.Write(d.digest[0:16])
// At this state we should have nothing left in buffer
if d.nx != 0 {
panic("d.nx != 0")
}
return append(in, d.state[0:16]...)
}
func block(dig *digest, p []byte) {
var t, i, j uint8
t = 0
for i = 0; i < 16; i++ {
dig.state[i+16] = p[i]
dig.state[i+32] = byte(p[i] ^ dig.state[i])
}
for i = 0; i < 18; i++ {
for j = 0; j < 48; j++ {
dig.state[j] = byte(dig.state[j] ^ PI_SUBST[t])
t = dig.state[j]
}
t = byte(t + i)
}
t = dig.digest[15]
for i = 0; i < 16; i++ {
dig.digest[i] = byte(dig.digest[i] ^ PI_SUBST[p[i]^t])
t = dig.digest[i]
}
}