1 /* 2 // Copyright (c) 2017 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 17 #pragma once 18 #include <ipmid/api-types.hpp> 19 #include <ipmid/api.hpp> 20 21 #include <cstdint> 22 23 static constexpr uint8_t ipmiSdrVersion = 0x51; 24 25 namespace intel_oem::ipmi::sel 26 { 27 static constexpr uint8_t selOperationSupport = 0x02; 28 static constexpr uint8_t systemEvent = 0x02; 29 static constexpr size_t systemEventSize = 3; 30 static constexpr uint8_t oemTsEventFirst = 0xC0; 31 static constexpr uint8_t oemTsEventLast = 0xDF; 32 static constexpr size_t oemTsEventSize = 9; 33 static constexpr uint8_t oemEventFirst = 0xE0; 34 static constexpr uint8_t oemEventLast = 0xFF; 35 static constexpr size_t oemEventSize = 13; 36 static constexpr uint8_t eventMsgRev = 0x04; 37 } // namespace intel_oem::ipmi::sel 38 39 ////////////////////////////////////////////////////////////////////////////// 40 // 41 // blurbs from ipmi-host/sensorhandler.hpp 42 // 43 ////////////////////////////////////////////////////////////////////////////// 44 static constexpr int FULL_RECORD_ID_STR_MAX_LENGTH = 16; 45 namespace get_sdr 46 { 47 // Record header 48 struct SensorDataRecordHeader 49 { 50 uint8_t record_id_lsb; 51 uint8_t record_id_msb; 52 uint8_t sdr_version; 53 uint8_t record_type; 54 uint8_t record_length; // Length not counting the header 55 } __attribute__((packed)); 56 57 namespace header 58 { 59 60 inline void set_record_id(int id, SensorDataRecordHeader* hdr) 61 { 62 hdr->record_id_lsb = (id & 0xFF); 63 hdr->record_id_msb = (id >> 8) & 0xFF; 64 }; 65 66 } // namespace header 67 68 /** @struct SensorDataFruRecordKey 69 * 70 * FRU Device Locator Record(key) - SDR Type 11 71 */ 72 struct SensorDataFruRecordKey 73 { 74 uint8_t deviceAddress; 75 uint8_t fruID; 76 uint8_t accessLun; 77 uint8_t channelNumber; 78 } __attribute__((packed)); 79 80 static constexpr int FRU_RECORD_DEVICE_ID_MAX_LENGTH = 16; 81 82 /** @struct SensorDataFruRecordBody 83 * 84 * FRU Device Locator Record(body) - SDR Type 11 85 */ 86 struct SensorDataFruRecordBody 87 { 88 uint8_t reserved; 89 uint8_t deviceType; 90 uint8_t deviceTypeModifier; 91 uint8_t entityID; 92 uint8_t entityInstance; 93 uint8_t oem; 94 uint8_t deviceIDLen; 95 char deviceID[FRU_RECORD_DEVICE_ID_MAX_LENGTH]; 96 } __attribute__((packed)); 97 98 /** @struct SensorDataFruRecord 99 * 100 * FRU Device Locator Record - SDR Type 11 101 */ 102 struct SensorDataFruRecord 103 { 104 SensorDataRecordHeader header; 105 SensorDataFruRecordKey key; 106 SensorDataFruRecordBody body; 107 } __attribute__((packed)); 108 109 enum SensorDataRecordType 110 { 111 SENSOR_DATA_FULL_RECORD = 0x1, 112 SENSOR_DATA_EVENT_RECORD = 0x3, 113 SENSOR_DATA_FRU_RECORD = 0x11, 114 SENSOR_DATA_ENTITY_RECORD = 0x8, 115 }; 116 117 // Record key 118 struct SensorDataRecordKey 119 { 120 uint8_t owner_id; 121 uint8_t owner_lun; 122 uint8_t sensor_number; 123 } __attribute__((packed)); 124 125 struct SensorDataFullRecordBody 126 { 127 uint8_t entity_id; 128 uint8_t entity_instance; 129 uint8_t sensor_initialization; 130 uint8_t sensor_capabilities; // no macro support 131 uint8_t sensor_type; 132 uint8_t event_reading_type; 133 uint8_t supported_assertions[2]; // no macro support 134 uint8_t supported_deassertions[2]; // no macro support 135 uint8_t discrete_reading_setting_mask[2]; // no macro support 136 uint8_t sensor_units_1; 137 uint8_t sensor_units_2_base; 138 uint8_t sensor_units_3_modifier; 139 uint8_t linearization; 140 uint8_t m_lsb; 141 uint8_t m_msb_and_tolerance; 142 uint8_t b_lsb; 143 uint8_t b_msb_and_accuracy_lsb; 144 uint8_t accuracy_and_sensor_direction; 145 uint8_t r_b_exponents; 146 uint8_t analog_characteristic_flags; // no macro support 147 uint8_t nominal_reading; 148 uint8_t normal_max; 149 uint8_t normal_min; 150 uint8_t sensor_max; 151 uint8_t sensor_min; 152 uint8_t upper_nonrecoverable_threshold; 153 uint8_t upper_critical_threshold; 154 uint8_t upper_noncritical_threshold; 155 uint8_t lower_nonrecoverable_threshold; 156 uint8_t lower_critical_threshold; 157 uint8_t lower_noncritical_threshold; 158 uint8_t positive_threshold_hysteresis; 159 uint8_t negative_threshold_hysteresis; 160 uint16_t reserved; 161 uint8_t oem_reserved; 162 uint8_t id_string_info; 163 char id_string[FULL_RECORD_ID_STR_MAX_LENGTH]; 164 } __attribute__((packed)); 165 166 struct SensorDataFullRecord 167 { 168 SensorDataRecordHeader header; 169 SensorDataRecordKey key; 170 SensorDataFullRecordBody body; 171 } __attribute__((packed)); 172 173 namespace body 174 { 175 inline void set_id_strlen(uint8_t len, SensorDataFullRecordBody* body) 176 { 177 body->id_string_info &= ~(0x1f); 178 body->id_string_info |= len & 0x1f; 179 }; 180 inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body) 181 { 182 body->id_string_info &= ~(3 << 6); 183 body->id_string_info |= (type & 0x3) << 6; 184 }; 185 } // namespace body 186 } // namespace get_sdr 187 ////////////////////////////////////////////////////////////////////////////// 188 // 189 // <end> blurbs from ipmi-host/sensorhandler.hpp 190 // 191 ////////////////////////////////////////////////////////////////////////////// 192 193 ////////////////////////////////////////////////////////////////////////////// 194 // 195 // blurbs from ipmi-host/selutility.hpp 196 // 197 ////////////////////////////////////////////////////////////////////////////// 198 namespace ipmi::sel 199 { 200 static constexpr auto firstEntry = 0x0000; 201 static constexpr auto lastEntry = 0xFFFF; 202 static constexpr auto entireRecord = 0xFF; 203 static constexpr auto selVersion = 0x51; 204 static constexpr auto invalidTimeStamp = 0xFFFFFFFF; 205 static constexpr auto getEraseStatus = 0x00; 206 static constexpr auto eraseComplete = 0x01; 207 static constexpr auto initiateErase = 0xAA; 208 209 } // namespace ipmi::sel 210 ////////////////////////////////////////////////////////////////////////////// 211 // 212 // <end> blurbs from ipmi-host/selutility.hpp 213 // 214 ////////////////////////////////////////////////////////////////////////////// 215 216 #pragma pack(push, 1) 217 struct GetSDRReq 218 { 219 uint16_t reservationID; 220 uint16_t recordID; 221 uint8_t offset; 222 uint8_t bytesToRead; 223 }; 224 #pragma pack(pop) 225 226 enum class SdrRepositoryInfoOps : uint8_t 227 { 228 allocCommandSupported = 0x1, 229 reserveSDRRepositoryCommandSupported = 0x2, 230 partialAddSDRSupported = 0x4, 231 deleteSDRSupported = 0x8, 232 reserved = 0x10, 233 modalLSB = 0x20, 234 modalMSB = 0x40, 235 overflow = 0x80 236 }; 237 238 enum class GetFRUAreaAccessType : uint8_t 239 { 240 byte = 0x0, 241 words = 0x1 242 }; 243 244 enum class SensorUnits : uint8_t 245 { 246 unspecified = 0x0, 247 degreesC = 0x1, 248 volts = 0x4, 249 amps = 0x5, 250 watts = 0x6, 251 rpm = 0x12, 252 }; 253 254 #pragma pack(push, 1) 255 struct FRUHeader 256 { 257 uint8_t commonHeaderFormat; 258 uint8_t internalOffset; 259 uint8_t chassisOffset; 260 uint8_t boardOffset; 261 uint8_t productOffset; 262 uint8_t multiRecordOffset; 263 uint8_t pad; 264 uint8_t checksum; 265 }; 266 #pragma pack(pop) 267 268 #pragma pack(push, 1) 269 struct Type12Record 270 { 271 get_sdr::SensorDataRecordHeader header; 272 uint8_t targetAddress; 273 uint8_t channelNumber; 274 uint8_t powerStateNotification; 275 uint8_t deviceCapabilities; 276 // define reserved bytes explicitly. The uint24_t is silently expanded to 277 // uint32_t, which ruins the byte alignment required by this structure. 278 uint8_t reserved[3]; 279 uint8_t entityID; 280 uint8_t entityInstance; 281 uint8_t oem; 282 uint8_t typeLengthCode; 283 char name[16]; 284 285 Type12Record(uint16_t recordID, uint8_t address, uint8_t chNumber, 286 uint8_t pwrStateNotification, uint8_t capabilities, 287 uint8_t eid, uint8_t entityInst, uint8_t mfrDefined, 288 const std::string& sensorname) : 289 targetAddress(address), 290 channelNumber(chNumber), powerStateNotification(pwrStateNotification), 291 deviceCapabilities(capabilities), reserved{}, entityID(eid), 292 entityInstance(entityInst), oem(mfrDefined) 293 { 294 get_sdr::header::set_record_id(recordID, &header); 295 header.sdr_version = ipmiSdrVersion; 296 header.record_type = 0x12; 297 size_t nameLen = std::min(sensorname.size(), sizeof(name)); 298 header.record_length = sizeof(Type12Record) - 299 sizeof(get_sdr::SensorDataRecordHeader) - 300 sizeof(name) + nameLen; 301 typeLengthCode = 0xc0 | nameLen; 302 std::copy(sensorname.begin(), sensorname.begin() + nameLen, name); 303 } 304 }; 305 #pragma pack(pop) 306 307 #pragma pack(push, 1) 308 struct NMDiscoveryRecord 309 { 310 get_sdr::SensorDataRecordHeader header; 311 uint8_t oemID0; 312 uint8_t oemID1; 313 uint8_t oemID2; 314 uint8_t subType; 315 uint8_t version; 316 uint8_t targetAddress; 317 uint8_t channelNumber; 318 uint8_t healthEventSensor; 319 uint8_t exceptionEventSensor; 320 uint8_t operationalCapSensor; 321 uint8_t thresholdExceededSensor; 322 }; 323 #pragma pack(pop) 324 325 namespace ipmi 326 { 327 namespace storage 328 { 329 330 constexpr const size_t nmDiscoverySDRCount = 1; 331 constexpr const size_t type12Count = 2; 332 ipmi::Cc getFruSdrs(ipmi::Context::ptr& ctx, size_t index, 333 get_sdr::SensorDataFruRecord& resp); 334 335 ipmi::Cc getFruSdrCount(ipmi::Context::ptr& ctx, size_t& count); 336 337 std::vector<uint8_t> getType12SDRs(uint16_t index, uint16_t recordId); 338 std::vector<uint8_t> getNMDiscoverySDR(uint16_t index, uint16_t recordId); 339 } // namespace storage 340 } // namespace ipmi 341