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