1 #include <stdio.h> 2 #include <string.h> 3 #include <stdint.h> 4 #include <malloc.h> 5 #include "sensorhandler.h" 6 7 extern uint8_t find_sensor(uint8_t); 8 9 10 struct sensorRES_t { 11 uint8_t sensor_number; 12 uint8_t operation; 13 uint8_t sensor_reading; 14 uint8_t assert_state7_0; 15 uint8_t assert_state14_8; 16 uint8_t deassert_state7_0; 17 uint8_t deassert_state14_8; 18 uint8_t event_data1; 19 uint8_t event_data2; 20 uint8_t event_data3; 21 } __attribute__ ((packed)); 22 23 #define ISBITSET(x,y) (((x)>>(y))&0x01) 24 #define ASSERTINDEX 0 25 #define DEASSERTINDEX 1 26 27 // Sensor Type, Offset, function handler, Dbus Method, Assert value, Deassert value 28 struct lookup_t { 29 uint8_t sensor_type; 30 uint8_t offset; 31 int (*func)(const sensorRES_t *, const lookup_t *, const char *); 32 char member[16]; 33 char assertion[64]; 34 char deassertion[64]; 35 }; 36 37 extern int updateDbusInterface(uint8_t , const char *, const char *); 38 39 int set_sensor_dbus_state_simple(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { 40 41 return set_sensor_dbus_state_s(pRec->sensor_number, 42 pTable->member, 43 value); 44 } 45 46 struct event_data_t { 47 uint8_t data; 48 char text[64]; 49 }; 50 51 event_data_t g_fwprogress02h[] = { 52 {0x00, "Unspecified"}, 53 {0x01, "Memory Init"}, 54 {0x02, "HD Init"}, 55 {0x03, "Secondary Proc Init"}, 56 {0x04, "User Authentication"}, 57 {0x05, "User init system setup"}, 58 {0x06, "USB configuration"}, 59 {0x07, "PCI configuration"}, 60 {0x08, "Option ROM Init"}, 61 {0x09, "Video Init"}, 62 {0x0A, "Cache Init"}, 63 {0x0B, "SM Bus init"}, 64 {0x0C, "Keyboard Init"}, 65 {0x0D, "Embedded ctrl init"}, 66 {0x0E, "Docking station attachment"}, 67 {0x0F, "Enable docking station"}, 68 {0x10, "Docking station ejection"}, 69 {0x11, "Disabling docking station"}, 70 {0x12, "Calling OS Wakeup"}, 71 {0x13, "Starting OS"}, 72 {0x14, "Baseboard Init"}, 73 {0x15, ""}, 74 {0x16, "Floppy Init"}, 75 {0x17, "Keyboard Test"}, 76 {0x18, "Pointing Device Test"}, 77 {0x19, "Primary Proc Init"}, 78 {0xFF, "Unknown"} 79 }; 80 81 event_data_t g_fwprogress00h[] = { 82 {0x00, "Unspecified."}, 83 {0x01, "No system memory detected"}, 84 {0x02, "No usable system memory"}, 85 {0x03, "Unrecoverable hard-disk/ATAPI/IDE"}, 86 {0x04, "Unrecoverable system-board"}, 87 {0x05, "Unrecoverable diskette"}, 88 {0x06, "Unrecoverable hard-disk controller"}, 89 {0x07, "Unrecoverable PS/2 or USB keyboard"}, 90 {0x08, "Removable boot media not found"}, 91 {0x09, "Unrecoverable video controller"}, 92 {0x0A, "No video device detected"}, 93 {0x0B, "Firmware ROM corruption detected"}, 94 {0x0C, "CPU voltage mismatch"}, 95 {0x0D, "CPU speed matching"}, 96 {0xFF, "unknown"}, 97 }; 98 99 100 char *event_data_lookup(event_data_t *p, uint8_t b) { 101 102 while(p->data != 0xFF) { 103 if (p->data == b) { 104 break; 105 } 106 p++; 107 } 108 109 return p->text; 110 } 111 112 113 114 // The fw progress sensor contains some additional information that needs to be processed 115 // prior to calling the dbus code. 116 int set_sensor_dbus_state_fwprogress(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { 117 118 char valuestring[128]; 119 char* p = valuestring; 120 121 switch (pTable->offset) { 122 123 case 0x00 : snprintf(p, sizeof(valuestring), "POST Error, %s", event_data_lookup(g_fwprogress00h, pRec->event_data2)); 124 break; 125 case 0x01 : /* Using g_fwprogress02h for 0x01 because thats what the ipmi spec says to do */ 126 snprintf(p, sizeof(valuestring), "FW Hang, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2)); 127 break; 128 case 0x02 : snprintf(p, sizeof(valuestring), "FW Progress, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2)); 129 break; 130 default : snprintf(p, sizeof(valuestring), "Internal warning, fw_progres offset unknown (0x%02x)", pTable->offset); 131 break; 132 } 133 134 return set_sensor_dbus_state_s(pRec->sensor_number, 135 pTable->member, 136 p); 137 } 138 139 // Handling this special OEM sensor by coping what is in byte 4. I also think that is odd 140 // considering byte 3 is for sensor reading. This seems like a misuse of the IPMI spec 141 int set_sensor_dbus_state_osbootcount(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { 142 return set_sensor_dbus_state_y(pRec->sensor_number, 143 "setValue", 144 pRec->assert_state7_0); 145 } 146 147 int set_sensor_dbus_state_system_event(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { 148 char valuestring[128]; 149 char* p = valuestring; 150 151 switch (pTable->offset) { 152 153 case 0x00 : snprintf(p, sizeof(valuestring), "System Reconfigured"); 154 break; 155 case 0x01 : snprintf(p, sizeof(valuestring), "OEM Boot Event"); 156 break; 157 case 0x02 : snprintf(p, sizeof(valuestring), "Undetermine System Hardware Failure"); 158 break; 159 case 0x03 : snprintf(p, sizeof(valuestring), "System Failure see error log for more details (0x%02x)", pRec->event_data2); 160 break; 161 case 0x04 : snprintf(p, sizeof(valuestring), "System Failure see PEF error log for more details (0x%02x)", pRec->event_data2); 162 break; 163 default : snprintf(p, sizeof(valuestring), "Internal warning, system_event offset unknown (0x%02x)", pTable->offset); 164 break; 165 } 166 167 return set_sensor_dbus_state_s(pRec->sensor_number, 168 pTable->member, 169 p); 170 } 171 172 173 // This table lists only senors we care about telling dbus about. 174 // Offset definition cab be found in section 42.2 of the IPMI 2.0 175 // spec. Add more if/when there are more items of interest. 176 lookup_t g_ipmidbuslookup[] = { 177 178 {0xe9, 0x00, set_sensor_dbus_state_simple, "setValue", "Disabled", ""}, // OCC Inactive 0 179 {0xe9, 0x01, set_sensor_dbus_state_simple, "setValue", "Enabled", ""}, // OCC Active 1 180 {0x07, 0x07, set_sensor_dbus_state_simple, "setPresent", "True", "False"}, 181 {0x07, 0x08, set_sensor_dbus_state_simple, "setFault", "True", "False"}, 182 {0x0C, 0x06, set_sensor_dbus_state_simple, "setPresent", "True", "False"}, 183 {0x0C, 0x04, set_sensor_dbus_state_simple, "setFault", "True", "False"}, 184 {0x0F, 0x02, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, 185 {0x0F, 0x01, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, 186 {0x0F, 0x00, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, 187 {0xC7, 0x01, set_sensor_dbus_state_simple, "setFault", "True", "False"}, 188 {0xc3, 0x00, set_sensor_dbus_state_osbootcount, "setValue", "" ,""}, 189 {0x1F, 0x00, set_sensor_dbus_state_simple, "setValue", "Boot completed (00)", ""}, 190 {0x1F, 0x01, set_sensor_dbus_state_simple, "setValue", "Boot completed (01)", ""}, 191 {0x1F, 0x02, set_sensor_dbus_state_simple, "setValue", "PXE boot completed", ""}, 192 {0x1F, 0x03, set_sensor_dbus_state_simple, "setValue", "Diagnostic boot completed", ""}, 193 {0x1F, 0x04, set_sensor_dbus_state_simple, "setValue", "CD-ROM boot completed", ""}, 194 {0x1F, 0x05, set_sensor_dbus_state_simple, "setValue", "ROM boot completed", ""}, 195 {0x1F, 0x06, set_sensor_dbus_state_simple, "setValue", "Boot completed (06)", ""}, 196 {0x12, 0x00, set_sensor_dbus_state_system_event, "setValue", "", ""}, 197 {0x12, 0x01, set_sensor_dbus_state_system_event, "setValue", "", ""}, 198 {0x12, 0x02, set_sensor_dbus_state_system_event, "setValue", "", ""}, 199 {0x12, 0x03, set_sensor_dbus_state_system_event, "setValue", "", ""}, 200 {0x12, 0x04, set_sensor_dbus_state_system_event, "setValue", "", ""}, 201 {0xD8, 0x00, set_sensor_dbus_state_simple, "setValue", "Disabled", ""}, 202 {0xFF, 0xFF, NULL, "", "", ""} 203 }; 204 205 206 void reportSensorEventAssert(sensorRES_t *pRec, int index) { 207 lookup_t *pTable = &g_ipmidbuslookup[index]; 208 (*pTable->func)(pRec, pTable, pTable->assertion); 209 } 210 void reportSensorEventDeassert(sensorRES_t *pRec, int index) { 211 lookup_t *pTable = &g_ipmidbuslookup[index]; 212 (*pTable->func)(pRec, pTable, pTable->deassertion); 213 } 214 215 216 int findindex(const uint8_t sensor_type, int offset, int *index) { 217 218 int i=0, rc=0; 219 lookup_t *pTable = g_ipmidbuslookup; 220 221 do { 222 if ( ((pTable+i)->sensor_type == sensor_type) && 223 ((pTable+i)->offset == offset) ) { 224 rc = 1; 225 *index = i; 226 break; 227 } 228 i++; 229 } while ((pTable+i)->sensor_type != 0xFF); 230 231 return rc; 232 } 233 234 void debug_print_ok_to_dont_care(uint8_t stype, int offset) 235 { 236 printf("LOOKATME: Sensor should not be reported: Type 0x%02x, Offset 0x%02x\n", 237 stype, offset); 238 } 239 240 bool shouldReport(uint8_t sensorType, int offset, int *index) { 241 242 bool rc = false; 243 244 if (findindex(sensorType, offset, index)) { rc = true; } 245 246 if (rc==false) { debug_print_ok_to_dont_care(sensorType, offset); } 247 248 return rc; 249 } 250 251 252 int updateSensorRecordFromSSRAESC(const void *record) { 253 254 sensorRES_t *pRec = (sensorRES_t *) record; 255 uint8_t stype; 256 int index, i=0; 257 258 stype = find_sensor(pRec->sensor_number); 259 260 // 0xC3 types use the assertion7_0 for the value to be set 261 // so skip the reseach and call the correct event reporting 262 // function 263 if (stype == 0xC3) { 264 265 shouldReport(stype, 0x00, &index); 266 reportSensorEventAssert(pRec, index); 267 268 } else { 269 // Scroll through each bit position . Determine 270 // if any bit is either asserted or Deasserted. 271 for(i=0;i<8;i++) { 272 273 if ((ISBITSET(pRec->assert_state7_0,i)) && 274 (shouldReport(stype, i, &index))) 275 { 276 reportSensorEventAssert(pRec, index); 277 } 278 if ((ISBITSET(pRec->assert_state14_8,i)) && 279 (shouldReport(stype, i+8, &index))) 280 { 281 reportSensorEventAssert(pRec, index); 282 } 283 if ((ISBITSET(pRec->deassert_state7_0,i)) && 284 (shouldReport(stype, i, &index))) 285 { 286 reportSensorEventDeassert(pRec, index); 287 } 288 if ((ISBITSET(pRec->deassert_state14_8,i)) && 289 (shouldReport(stype, i+8, &index))) 290 { 291 reportSensorEventDeassert(pRec, index); 292 } 293 } 294 295 } 296 297 298 return 0; 299 } 300