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_type_for_sensor_number(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), "Undetermined 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 	// Turbo Allowed
181 	{0xda, 0x00, set_sensor_dbus_state_simple, "setValue", "True", "False"},
182 	// Power Supply Derating
183 	{0xb4, 0x00, set_sensor_dbus_state_simple, "setValue", "", ""},
184 	// Power Cap
185 	{0xC2, 0x00, set_sensor_dbus_state_simple, "setValue", "", ""},
186 	{0x07, 0x07, set_sensor_dbus_state_simple, "setPresent", "True", "False"},
187 	{0x07, 0x08, set_sensor_dbus_state_simple, "setFault",   "True", "False"},
188 	{0x0C, 0x06, set_sensor_dbus_state_simple, "setPresent", "True", "False"},
189 	{0x0C, 0x04, set_sensor_dbus_state_simple, "setFault",   "True", "False"},
190 	{0x0F, 0x02, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"},
191 	{0x0F, 0x01, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"},
192 	{0x0F, 0x00, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"},
193 	{0xC7, 0x01, set_sensor_dbus_state_simple, "setFault", "True", "False"},
194 	{0xc3, 0x00, set_sensor_dbus_state_osbootcount, "setValue", "" ,""},
195 	{0x1F, 0x00, set_sensor_dbus_state_simple, "setValue", "Boot completed (00)", ""},
196 	{0x1F, 0x01, set_sensor_dbus_state_simple, "setValue", "Boot completed (01)", ""},
197 	{0x1F, 0x02, set_sensor_dbus_state_simple, "setValue", "PXE boot completed", ""},
198 	{0x1F, 0x03, set_sensor_dbus_state_simple, "setValue", "Diagnostic boot completed", ""},
199 	{0x1F, 0x04, set_sensor_dbus_state_simple, "setValue", "CD-ROM boot completed", ""},
200 	{0x1F, 0x05, set_sensor_dbus_state_simple, "setValue", "ROM boot completed", ""},
201 	{0x1F, 0x06, set_sensor_dbus_state_simple, "setValue", "Boot completed (06)", ""},
202 	{0x12, 0x00, set_sensor_dbus_state_system_event, "setValue", "", ""},
203 	{0x12, 0x01, set_sensor_dbus_state_system_event, "setValue", "", ""},
204 	{0x12, 0x02, set_sensor_dbus_state_system_event, "setValue", "", ""},
205 	{0x12, 0x03, set_sensor_dbus_state_system_event, "setValue", "", ""},
206 	{0x12, 0x04, set_sensor_dbus_state_system_event, "setValue", "", ""},
207 	{0xCA, 0x00, set_sensor_dbus_state_simple,       "setValue", "Disabled", ""},
208 	{0xCA, 0x01, set_sensor_dbus_state_simple,       "setValue", "Enabled", ""},
209 	{0xFF, 0xFF, NULL, "", "", ""}
210 };
211 
212 
213 void reportSensorEventAssert(sensorRES_t *pRec, int index) {
214 	lookup_t *pTable = &g_ipmidbuslookup[index];
215 	(*pTable->func)(pRec, pTable, pTable->assertion);
216 }
217 void reportSensorEventDeassert(sensorRES_t *pRec, int index) {
218 	lookup_t *pTable = &g_ipmidbuslookup[index];
219 	(*pTable->func)(pRec, pTable, pTable->deassertion);
220 }
221 
222 
223 int findindex(const uint8_t sensor_type, int offset, int *index) {
224 
225 	int i=0, rc=0;
226 	lookup_t *pTable = g_ipmidbuslookup;
227 
228 	do {
229 		if ( ((pTable+i)->sensor_type == sensor_type) &&
230 			 ((pTable+i)->offset  == offset) ) {
231 			rc = 1;
232 			*index = i;
233 			break;
234 		}
235 		i++;
236 	} while ((pTable+i)->sensor_type  != 0xFF);
237 
238 	return rc;
239 }
240 
241 void debug_print_ok_to_dont_care(uint8_t stype, int offset)
242 {
243 	printf("LOOKATME: Sensor should not be reported:  Type 0x%02x, Offset 0x%02x\n",
244 		stype, offset);
245 }
246 
247 bool shouldReport(uint8_t sensorType, int offset, int *index) {
248 
249 	bool rc = false;
250 
251 	if (findindex(sensorType, offset, index)) { rc = true;	}
252 
253 	if (rc==false) { debug_print_ok_to_dont_care(sensorType, offset); }
254 
255 	return rc;
256 }
257 
258 
259 int updateSensorRecordFromSSRAESC(const void *record) {
260 
261 	sensorRES_t *pRec = (sensorRES_t *) record;
262 	uint8_t stype;
263 	int index, i=0;
264 
265 	stype = find_type_for_sensor_number(pRec->sensor_number);
266 
267 	// 0xC3 types use the assertion7_0 for the value to be set
268 	// so skip the reseach and call the correct event reporting
269 	// function
270 	if (stype == 0xC3) {
271 
272 		shouldReport(stype, 0x00, &index);
273 		reportSensorEventAssert(pRec, index);
274 
275 	} else {
276 		// Scroll through each bit position .  Determine
277 		// if any bit is either asserted or Deasserted.
278 		for(i=0;i<8;i++) {
279 
280 			if ((ISBITSET(pRec->assert_state7_0,i))  &&
281 				(shouldReport(stype, i, &index)))
282 			{
283 				reportSensorEventAssert(pRec, index);
284 			}
285 			if ((ISBITSET(pRec->assert_state14_8,i))  &&
286 				(shouldReport(stype, i+8, &index)))
287 			{
288 				reportSensorEventAssert(pRec, index);
289 			}
290 			if ((ISBITSET(pRec->deassert_state7_0,i))  &&
291 				(shouldReport(stype, i, &index)))
292 			{
293 				reportSensorEventDeassert(pRec, index);
294 			}
295 			if ((ISBITSET(pRec->deassert_state14_8,i))  &&
296 				(shouldReport(stype, i+8, &index)))
297 			{
298 				reportSensorEventDeassert(pRec, index);
299 			}
300 		}
301 
302 	}
303 
304 
305 	return 0;
306 }
307