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 	// 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 	{0xD8, 0x00, set_sensor_dbus_state_simple,       "setValue", "Disabled", ""},
208 	{0xFF, 0xFF, NULL, "", "", ""}
209 };
210 
211 
212 void reportSensorEventAssert(sensorRES_t *pRec, int index) {
213 	lookup_t *pTable = &g_ipmidbuslookup[index];
214 	(*pTable->func)(pRec, pTable, pTable->assertion);
215 }
216 void reportSensorEventDeassert(sensorRES_t *pRec, int index) {
217 	lookup_t *pTable = &g_ipmidbuslookup[index];
218 	(*pTable->func)(pRec, pTable, pTable->deassertion);
219 }
220 
221 
222 int findindex(const uint8_t sensor_type, int offset, int *index) {
223 
224 	int i=0, rc=0;
225 	lookup_t *pTable = g_ipmidbuslookup;
226 
227 	do {
228 		if ( ((pTable+i)->sensor_type == sensor_type) &&
229 			 ((pTable+i)->offset  == offset) ) {
230 			rc = 1;
231 			*index = i;
232 			break;
233 		}
234 		i++;
235 	} while ((pTable+i)->sensor_type  != 0xFF);
236 
237 	return rc;
238 }
239 
240 void debug_print_ok_to_dont_care(uint8_t stype, int offset)
241 {
242 	printf("LOOKATME: Sensor should not be reported:  Type 0x%02x, Offset 0x%02x\n",
243 		stype, offset);
244 }
245 
246 bool shouldReport(uint8_t sensorType, int offset, int *index) {
247 
248 	bool rc = false;
249 
250 	if (findindex(sensorType, offset, index)) { rc = true;	}
251 
252 	if (rc==false) { debug_print_ok_to_dont_care(sensorType, offset); }
253 
254 	return rc;
255 }
256 
257 
258 int updateSensorRecordFromSSRAESC(const void *record) {
259 
260 	sensorRES_t *pRec = (sensorRES_t *) record;
261 	uint8_t stype;
262 	int index, i=0;
263 
264 	stype = find_sensor(pRec->sensor_number);
265 
266 	// 0xC3 types use the assertion7_0 for the value to be set
267 	// so skip the reseach and call the correct event reporting
268 	// function
269 	if (stype == 0xC3) {
270 
271 		shouldReport(stype, 0x00, &index);
272 		reportSensorEventAssert(pRec, index);
273 
274 	} else {
275 		// Scroll through each bit position .  Determine
276 		// if any bit is either asserted or Deasserted.
277 		for(i=0;i<8;i++) {
278 
279 			if ((ISBITSET(pRec->assert_state7_0,i))  &&
280 				(shouldReport(stype, i, &index)))
281 			{
282 				reportSensorEventAssert(pRec, index);
283 			}
284 			if ((ISBITSET(pRec->assert_state14_8,i))  &&
285 				(shouldReport(stype, i+8, &index)))
286 			{
287 				reportSensorEventAssert(pRec, index);
288 			}
289 			if ((ISBITSET(pRec->deassert_state7_0,i))  &&
290 				(shouldReport(stype, i, &index)))
291 			{
292 				reportSensorEventDeassert(pRec, index);
293 			}
294 			if ((ISBITSET(pRec->deassert_state14_8,i))  &&
295 				(shouldReport(stype, i+8, &index)))
296 			{
297 				reportSensorEventDeassert(pRec, index);
298 			}
299 		}
300 
301 	}
302 
303 
304 	return 0;
305 }
306