13f7c5e40SJason M. Bills /*
23f7c5e40SJason M. Bills // Copyright (c) 2017 2018 Intel Corporation
33f7c5e40SJason M. Bills //
43f7c5e40SJason M. Bills // Licensed under the Apache License, Version 2.0 (the "License");
53f7c5e40SJason M. Bills // you may not use this file except in compliance with the License.
63f7c5e40SJason M. Bills // You may obtain a copy of the License at
73f7c5e40SJason M. Bills //
83f7c5e40SJason M. Bills //      http://www.apache.org/licenses/LICENSE-2.0
93f7c5e40SJason M. Bills //
103f7c5e40SJason M. Bills // Unless required by applicable law or agreed to in writing, software
113f7c5e40SJason M. Bills // distributed under the License is distributed on an "AS IS" BASIS,
123f7c5e40SJason M. Bills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f7c5e40SJason M. Bills // See the License for the specific language governing permissions and
143f7c5e40SJason M. Bills // limitations under the License.
153f7c5e40SJason M. Bills */
163f7c5e40SJason M. Bills 
173f7c5e40SJason M. Bills #pragma once
18*e035c588SVernon Mauery #include <ipmid/api-types.hpp>
19*e035c588SVernon Mauery #include <ipmid/api.hpp>
203f7c5e40SJason M. Bills 
21fcd2d3a9SJames Feist #include <cstdint>
22fcd2d3a9SJames Feist 
233f7c5e40SJason M. Bills static constexpr uint8_t ipmiSdrVersion = 0x51;
243f7c5e40SJason M. Bills 
25c04e2e70SJason M. Bills namespace intel_oem::ipmi::sel
26c04e2e70SJason M. Bills {
27c04e2e70SJason M. Bills static constexpr uint8_t selOperationSupport = 0x02;
28c04e2e70SJason M. Bills static constexpr uint8_t systemEvent = 0x02;
29c04e2e70SJason M. Bills static constexpr size_t systemEventSize = 3;
30c04e2e70SJason M. Bills static constexpr uint8_t oemTsEventFirst = 0xC0;
31c04e2e70SJason M. Bills static constexpr uint8_t oemTsEventLast = 0xDF;
32c04e2e70SJason M. Bills static constexpr size_t oemTsEventSize = 9;
33c04e2e70SJason M. Bills static constexpr uint8_t oemEventFirst = 0xE0;
34c04e2e70SJason M. Bills static constexpr uint8_t oemEventLast = 0xFF;
35c04e2e70SJason M. Bills static constexpr size_t oemEventSize = 13;
36c04e2e70SJason M. Bills static constexpr uint8_t eventMsgRev = 0x04;
37c04e2e70SJason M. Bills } // namespace intel_oem::ipmi::sel
38c04e2e70SJason M. Bills 
39*e035c588SVernon Mauery //////////////////////////////////////////////////////////////////////////////
40*e035c588SVernon Mauery //
41*e035c588SVernon Mauery // blurbs from ipmi-host/sensorhandler.hpp
42*e035c588SVernon Mauery //
43*e035c588SVernon Mauery //////////////////////////////////////////////////////////////////////////////
44*e035c588SVernon Mauery static constexpr int FULL_RECORD_ID_STR_MAX_LENGTH = 16;
45*e035c588SVernon Mauery namespace get_sdr
46*e035c588SVernon Mauery {
47*e035c588SVernon Mauery // Record header
48*e035c588SVernon Mauery struct SensorDataRecordHeader
49*e035c588SVernon Mauery {
50*e035c588SVernon Mauery     uint8_t record_id_lsb;
51*e035c588SVernon Mauery     uint8_t record_id_msb;
52*e035c588SVernon Mauery     uint8_t sdr_version;
53*e035c588SVernon Mauery     uint8_t record_type;
54*e035c588SVernon Mauery     uint8_t record_length; // Length not counting the header
55*e035c588SVernon Mauery } __attribute__((packed));
56*e035c588SVernon Mauery 
57*e035c588SVernon Mauery namespace header
58*e035c588SVernon Mauery {
59*e035c588SVernon Mauery 
set_record_id(int id,SensorDataRecordHeader * hdr)60*e035c588SVernon Mauery inline void set_record_id(int id, SensorDataRecordHeader* hdr)
61*e035c588SVernon Mauery {
62*e035c588SVernon Mauery     hdr->record_id_lsb = (id & 0xFF);
63*e035c588SVernon Mauery     hdr->record_id_msb = (id >> 8) & 0xFF;
64*e035c588SVernon Mauery };
65*e035c588SVernon Mauery 
66*e035c588SVernon Mauery } // namespace header
67*e035c588SVernon Mauery 
68*e035c588SVernon Mauery /** @struct SensorDataFruRecordKey
69*e035c588SVernon Mauery  *
70*e035c588SVernon Mauery  *  FRU Device Locator Record(key) - SDR Type 11
71*e035c588SVernon Mauery  */
72*e035c588SVernon Mauery struct SensorDataFruRecordKey
73*e035c588SVernon Mauery {
74*e035c588SVernon Mauery     uint8_t deviceAddress;
75*e035c588SVernon Mauery     uint8_t fruID;
76*e035c588SVernon Mauery     uint8_t accessLun;
77*e035c588SVernon Mauery     uint8_t channelNumber;
78*e035c588SVernon Mauery } __attribute__((packed));
79*e035c588SVernon Mauery 
80*e035c588SVernon Mauery static constexpr int FRU_RECORD_DEVICE_ID_MAX_LENGTH = 16;
81*e035c588SVernon Mauery 
82*e035c588SVernon Mauery /** @struct SensorDataFruRecordBody
83*e035c588SVernon Mauery  *
84*e035c588SVernon Mauery  *  FRU Device Locator Record(body) - SDR Type 11
85*e035c588SVernon Mauery  */
86*e035c588SVernon Mauery struct SensorDataFruRecordBody
87*e035c588SVernon Mauery {
88*e035c588SVernon Mauery     uint8_t reserved;
89*e035c588SVernon Mauery     uint8_t deviceType;
90*e035c588SVernon Mauery     uint8_t deviceTypeModifier;
91*e035c588SVernon Mauery     uint8_t entityID;
92*e035c588SVernon Mauery     uint8_t entityInstance;
93*e035c588SVernon Mauery     uint8_t oem;
94*e035c588SVernon Mauery     uint8_t deviceIDLen;
95*e035c588SVernon Mauery     char deviceID[FRU_RECORD_DEVICE_ID_MAX_LENGTH];
96*e035c588SVernon Mauery } __attribute__((packed));
97*e035c588SVernon Mauery 
98*e035c588SVernon Mauery /** @struct SensorDataFruRecord
99*e035c588SVernon Mauery  *
100*e035c588SVernon Mauery  *  FRU Device Locator Record - SDR Type 11
101*e035c588SVernon Mauery  */
102*e035c588SVernon Mauery struct SensorDataFruRecord
103*e035c588SVernon Mauery {
104*e035c588SVernon Mauery     SensorDataRecordHeader header;
105*e035c588SVernon Mauery     SensorDataFruRecordKey key;
106*e035c588SVernon Mauery     SensorDataFruRecordBody body;
107*e035c588SVernon Mauery } __attribute__((packed));
108*e035c588SVernon Mauery 
109*e035c588SVernon Mauery enum SensorDataRecordType
110*e035c588SVernon Mauery {
111*e035c588SVernon Mauery     SENSOR_DATA_FULL_RECORD = 0x1,
112*e035c588SVernon Mauery     SENSOR_DATA_EVENT_RECORD = 0x3,
113*e035c588SVernon Mauery     SENSOR_DATA_FRU_RECORD = 0x11,
114*e035c588SVernon Mauery     SENSOR_DATA_ENTITY_RECORD = 0x8,
115*e035c588SVernon Mauery };
116*e035c588SVernon Mauery 
117*e035c588SVernon Mauery // Record key
118*e035c588SVernon Mauery struct SensorDataRecordKey
119*e035c588SVernon Mauery {
120*e035c588SVernon Mauery     uint8_t owner_id;
121*e035c588SVernon Mauery     uint8_t owner_lun;
122*e035c588SVernon Mauery     uint8_t sensor_number;
123*e035c588SVernon Mauery } __attribute__((packed));
124*e035c588SVernon Mauery 
125*e035c588SVernon Mauery struct SensorDataFullRecordBody
126*e035c588SVernon Mauery {
127*e035c588SVernon Mauery     uint8_t entity_id;
128*e035c588SVernon Mauery     uint8_t entity_instance;
129*e035c588SVernon Mauery     uint8_t sensor_initialization;
130*e035c588SVernon Mauery     uint8_t sensor_capabilities; // no macro support
131*e035c588SVernon Mauery     uint8_t sensor_type;
132*e035c588SVernon Mauery     uint8_t event_reading_type;
133*e035c588SVernon Mauery     uint8_t supported_assertions[2];          // no macro support
134*e035c588SVernon Mauery     uint8_t supported_deassertions[2];        // no macro support
135*e035c588SVernon Mauery     uint8_t discrete_reading_setting_mask[2]; // no macro support
136*e035c588SVernon Mauery     uint8_t sensor_units_1;
137*e035c588SVernon Mauery     uint8_t sensor_units_2_base;
138*e035c588SVernon Mauery     uint8_t sensor_units_3_modifier;
139*e035c588SVernon Mauery     uint8_t linearization;
140*e035c588SVernon Mauery     uint8_t m_lsb;
141*e035c588SVernon Mauery     uint8_t m_msb_and_tolerance;
142*e035c588SVernon Mauery     uint8_t b_lsb;
143*e035c588SVernon Mauery     uint8_t b_msb_and_accuracy_lsb;
144*e035c588SVernon Mauery     uint8_t accuracy_and_sensor_direction;
145*e035c588SVernon Mauery     uint8_t r_b_exponents;
146*e035c588SVernon Mauery     uint8_t analog_characteristic_flags; // no macro support
147*e035c588SVernon Mauery     uint8_t nominal_reading;
148*e035c588SVernon Mauery     uint8_t normal_max;
149*e035c588SVernon Mauery     uint8_t normal_min;
150*e035c588SVernon Mauery     uint8_t sensor_max;
151*e035c588SVernon Mauery     uint8_t sensor_min;
152*e035c588SVernon Mauery     uint8_t upper_nonrecoverable_threshold;
153*e035c588SVernon Mauery     uint8_t upper_critical_threshold;
154*e035c588SVernon Mauery     uint8_t upper_noncritical_threshold;
155*e035c588SVernon Mauery     uint8_t lower_nonrecoverable_threshold;
156*e035c588SVernon Mauery     uint8_t lower_critical_threshold;
157*e035c588SVernon Mauery     uint8_t lower_noncritical_threshold;
158*e035c588SVernon Mauery     uint8_t positive_threshold_hysteresis;
159*e035c588SVernon Mauery     uint8_t negative_threshold_hysteresis;
160*e035c588SVernon Mauery     uint16_t reserved;
161*e035c588SVernon Mauery     uint8_t oem_reserved;
162*e035c588SVernon Mauery     uint8_t id_string_info;
163*e035c588SVernon Mauery     char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
164*e035c588SVernon Mauery } __attribute__((packed));
165*e035c588SVernon Mauery 
166*e035c588SVernon Mauery struct SensorDataFullRecord
167*e035c588SVernon Mauery {
168*e035c588SVernon Mauery     SensorDataRecordHeader header;
169*e035c588SVernon Mauery     SensorDataRecordKey key;
170*e035c588SVernon Mauery     SensorDataFullRecordBody body;
171*e035c588SVernon Mauery } __attribute__((packed));
172*e035c588SVernon Mauery 
173*e035c588SVernon Mauery namespace body
174*e035c588SVernon Mauery {
set_id_strlen(uint8_t len,SensorDataFullRecordBody * body)175*e035c588SVernon Mauery inline void set_id_strlen(uint8_t len, SensorDataFullRecordBody* body)
176*e035c588SVernon Mauery {
177*e035c588SVernon Mauery     body->id_string_info &= ~(0x1f);
178*e035c588SVernon Mauery     body->id_string_info |= len & 0x1f;
179*e035c588SVernon Mauery };
set_id_type(uint8_t type,SensorDataFullRecordBody * body)180*e035c588SVernon Mauery inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body)
181*e035c588SVernon Mauery {
182*e035c588SVernon Mauery     body->id_string_info &= ~(3 << 6);
183*e035c588SVernon Mauery     body->id_string_info |= (type & 0x3) << 6;
184*e035c588SVernon Mauery };
185*e035c588SVernon Mauery } // namespace body
186*e035c588SVernon Mauery } // namespace get_sdr
187*e035c588SVernon Mauery //////////////////////////////////////////////////////////////////////////////
188*e035c588SVernon Mauery //
189*e035c588SVernon Mauery // <end> blurbs from ipmi-host/sensorhandler.hpp
190*e035c588SVernon Mauery //
191*e035c588SVernon Mauery //////////////////////////////////////////////////////////////////////////////
192*e035c588SVernon Mauery 
193*e035c588SVernon Mauery //////////////////////////////////////////////////////////////////////////////
194*e035c588SVernon Mauery //
195*e035c588SVernon Mauery // blurbs from ipmi-host/selutility.hpp
196*e035c588SVernon Mauery //
197*e035c588SVernon Mauery //////////////////////////////////////////////////////////////////////////////
198*e035c588SVernon Mauery namespace ipmi::sel
199*e035c588SVernon Mauery {
200*e035c588SVernon Mauery static constexpr auto firstEntry = 0x0000;
201*e035c588SVernon Mauery static constexpr auto lastEntry = 0xFFFF;
202*e035c588SVernon Mauery static constexpr auto entireRecord = 0xFF;
203*e035c588SVernon Mauery static constexpr auto selVersion = 0x51;
204*e035c588SVernon Mauery static constexpr auto invalidTimeStamp = 0xFFFFFFFF;
205*e035c588SVernon Mauery static constexpr auto getEraseStatus = 0x00;
206*e035c588SVernon Mauery static constexpr auto eraseComplete = 0x01;
207*e035c588SVernon Mauery static constexpr auto initiateErase = 0xAA;
208*e035c588SVernon Mauery 
209*e035c588SVernon Mauery } // namespace ipmi::sel
210*e035c588SVernon Mauery //////////////////////////////////////////////////////////////////////////////
211*e035c588SVernon Mauery //
212*e035c588SVernon Mauery // <end> blurbs from ipmi-host/selutility.hpp
213*e035c588SVernon Mauery //
214*e035c588SVernon Mauery //////////////////////////////////////////////////////////////////////////////
215*e035c588SVernon Mauery 
2163f7c5e40SJason M. Bills #pragma pack(push, 1)
2173f7c5e40SJason M. Bills struct GetSDRReq
2183f7c5e40SJason M. Bills {
2193f7c5e40SJason M. Bills     uint16_t reservationID;
2203f7c5e40SJason M. Bills     uint16_t recordID;
2213f7c5e40SJason M. Bills     uint8_t offset;
2223f7c5e40SJason M. Bills     uint8_t bytesToRead;
2233f7c5e40SJason M. Bills };
2243f7c5e40SJason M. Bills #pragma pack(pop)
2253f7c5e40SJason M. Bills 
2263f7c5e40SJason M. Bills enum class SdrRepositoryInfoOps : uint8_t
2273f7c5e40SJason M. Bills {
2283f7c5e40SJason M. Bills     allocCommandSupported = 0x1,
2293f7c5e40SJason M. Bills     reserveSDRRepositoryCommandSupported = 0x2,
2303f7c5e40SJason M. Bills     partialAddSDRSupported = 0x4,
2313f7c5e40SJason M. Bills     deleteSDRSupported = 0x8,
2323f7c5e40SJason M. Bills     reserved = 0x10,
2333f7c5e40SJason M. Bills     modalLSB = 0x20,
2343f7c5e40SJason M. Bills     modalMSB = 0x40,
2353f7c5e40SJason M. Bills     overflow = 0x80
2363f7c5e40SJason M. Bills };
2373f7c5e40SJason M. Bills 
238e2d1aee3SJason M. Bills enum class GetFRUAreaAccessType : uint8_t
239e2d1aee3SJason M. Bills {
240e2d1aee3SJason M. Bills     byte = 0x0,
241e2d1aee3SJason M. Bills     words = 0x1
242e2d1aee3SJason M. Bills };
243e2d1aee3SJason M. Bills 
2443f7c5e40SJason M. Bills enum class SensorUnits : uint8_t
2453f7c5e40SJason M. Bills {
2463f7c5e40SJason M. Bills     unspecified = 0x0,
2473f7c5e40SJason M. Bills     degreesC = 0x1,
2483f7c5e40SJason M. Bills     volts = 0x4,
2493f7c5e40SJason M. Bills     amps = 0x5,
2503f7c5e40SJason M. Bills     watts = 0x6,
2513f7c5e40SJason M. Bills     rpm = 0x12,
2523f7c5e40SJason M. Bills };
2533f7c5e40SJason M. Bills 
254e2d1aee3SJason M. Bills #pragma pack(push, 1)
25574c50c64SJames Feist struct Type12Record
25674c50c64SJames Feist {
25774c50c64SJames Feist     get_sdr::SensorDataRecordHeader header;
25880d4d5f9SMatt Simmering     uint8_t targetAddress;
25974c50c64SJames Feist     uint8_t channelNumber;
26074c50c64SJames Feist     uint8_t powerStateNotification;
26174c50c64SJames Feist     uint8_t deviceCapabilities;
262f4d5e05eSJohnathan Mantey     // define reserved bytes explicitly. The uint24_t is silently expanded to
263f4d5e05eSJohnathan Mantey     // uint32_t, which ruins the byte alignment required by this structure.
264f4d5e05eSJohnathan Mantey     uint8_t reserved[3];
26574c50c64SJames Feist     uint8_t entityID;
26674c50c64SJames Feist     uint8_t entityInstance;
26774c50c64SJames Feist     uint8_t oem;
26874c50c64SJames Feist     uint8_t typeLengthCode;
26974c50c64SJames Feist     char name[16];
270f4d5e05eSJohnathan Mantey 
Type12RecordType12Record271f4d5e05eSJohnathan Mantey     Type12Record(uint16_t recordID, uint8_t address, uint8_t chNumber,
272f4d5e05eSJohnathan Mantey                  uint8_t pwrStateNotification, uint8_t capabilities,
273f4d5e05eSJohnathan Mantey                  uint8_t eid, uint8_t entityInst, uint8_t mfrDefined,
274f4d5e05eSJohnathan Mantey                  const std::string& sensorname) :
27580d4d5f9SMatt Simmering         targetAddress(address),
276f4d5e05eSJohnathan Mantey         channelNumber(chNumber), powerStateNotification(pwrStateNotification),
277f4d5e05eSJohnathan Mantey         deviceCapabilities(capabilities), reserved{}, entityID(eid),
278f4d5e05eSJohnathan Mantey         entityInstance(entityInst), oem(mfrDefined)
279f4d5e05eSJohnathan Mantey     {
280f4d5e05eSJohnathan Mantey         get_sdr::header::set_record_id(recordID, &header);
281f4d5e05eSJohnathan Mantey         header.sdr_version = ipmiSdrVersion;
282f4d5e05eSJohnathan Mantey         header.record_type = 0x12;
283f4d5e05eSJohnathan Mantey         size_t nameLen = std::min(sensorname.size(), sizeof(name));
284f4d5e05eSJohnathan Mantey         header.record_length = sizeof(Type12Record) -
285f4d5e05eSJohnathan Mantey                                sizeof(get_sdr::SensorDataRecordHeader) -
286f4d5e05eSJohnathan Mantey                                sizeof(name) + nameLen;
287f4d5e05eSJohnathan Mantey         typeLengthCode = 0xc0 | nameLen;
288f4d5e05eSJohnathan Mantey         std::copy(sensorname.begin(), sensorname.begin() + nameLen, name);
289f4d5e05eSJohnathan Mantey     }
29074c50c64SJames Feist };
29174c50c64SJames Feist #pragma pack(pop)
29274c50c64SJames Feist 
293fee5e4c7SYong Li #pragma pack(push, 1)
294fee5e4c7SYong Li struct NMDiscoveryRecord
295fee5e4c7SYong Li {
296fee5e4c7SYong Li     get_sdr::SensorDataRecordHeader header;
297fee5e4c7SYong Li     uint8_t oemID0;
298fee5e4c7SYong Li     uint8_t oemID1;
299fee5e4c7SYong Li     uint8_t oemID2;
300fee5e4c7SYong Li     uint8_t subType;
301fee5e4c7SYong Li     uint8_t version;
30280d4d5f9SMatt Simmering     uint8_t targetAddress;
303fee5e4c7SYong Li     uint8_t channelNumber;
304fee5e4c7SYong Li     uint8_t healthEventSensor;
305fee5e4c7SYong Li     uint8_t exceptionEventSensor;
306fee5e4c7SYong Li     uint8_t operationalCapSensor;
307fee5e4c7SYong Li     uint8_t thresholdExceededSensor;
308fee5e4c7SYong Li };
309fee5e4c7SYong Li #pragma pack(pop)
310fee5e4c7SYong Li 
3113f7c5e40SJason M. Bills namespace ipmi
3123f7c5e40SJason M. Bills {
3133f7c5e40SJason M. Bills namespace storage
3143f7c5e40SJason M. Bills {
31574c50c64SJames Feist 
316fee5e4c7SYong Li constexpr const size_t nmDiscoverySDRCount = 1;
31774c50c64SJames Feist constexpr const size_t type12Count = 2;
318dcff1506SVernon Mauery ipmi::Cc getFruSdrs(ipmi::Context::ptr& ctx, size_t index,
3192569025eSJames Feist                     get_sdr::SensorDataFruRecord& resp);
3203f7c5e40SJason M. Bills 
321dcff1506SVernon Mauery ipmi::Cc getFruSdrCount(ipmi::Context::ptr& ctx, size_t& count);
32274c50c64SJames Feist 
32374c50c64SJames Feist std::vector<uint8_t> getType12SDRs(uint16_t index, uint16_t recordId);
324fee5e4c7SYong Li std::vector<uint8_t> getNMDiscoverySDR(uint16_t index, uint16_t recordId);
3253f7c5e40SJason M. Bills } // namespace storage
3263f7c5e40SJason M. Bills } // namespace ipmi
327