summaryrefslogtreecommitdiffstats
path: root/ipmisensor.cpp
blob: bb5dd96585e4492e5e5ed8f539ed39066c9e9c48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <malloc.h>
#include "sensorhandler.h"

extern uint8_t find_type_for_sensor_number(uint8_t);


struct sensorRES_t {
	uint8_t sensor_number;
	uint8_t operation;
	uint8_t sensor_reading;
	uint8_t assert_state7_0;
	uint8_t assert_state14_8;
	uint8_t deassert_state7_0;
	uint8_t deassert_state14_8;
	uint8_t event_data1;
	uint8_t event_data2;
	uint8_t event_data3;
} __attribute__ ((packed));

#define ISBITSET(x,y) (((x)>>(y))&0x01)
#define ASSERTINDEX 0
#define DEASSERTINDEX 1

// Sensor Type,  Offset, function handler, Dbus Method, Assert value, Deassert value
struct lookup_t {
	uint8_t sensor_type;
	uint8_t offset;
	int (*func)(const sensorRES_t *, const lookup_t *, const char *);
	char    member[16];
	char    assertion[64];
	char    deassertion[64];
};

extern int updateDbusInterface(uint8_t , const char *, const char *);

int set_sensor_dbus_state_simple(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) {

	return set_sensor_dbus_state_s(pRec->sensor_number,
                                   pTable->member,
                                   value);
}

struct event_data_t {
	uint8_t data;
	char    text[64];
};

event_data_t g_fwprogress02h[] = {
	{0x00, "Unspecified"},
	{0x01, "Memory Init"},
	{0x02, "HD Init"},
	{0x03, "Secondary Proc Init"},
	{0x04, "User Authentication"},
	{0x05, "User init system setup"},
	{0x06, "USB configuration"},
	{0x07, "PCI configuration"},
	{0x08, "Option ROM Init"},
	{0x09, "Video Init"},
	{0x0A, "Cache Init"},
	{0x0B, "SM Bus init"},
	{0x0C, "Keyboard Init"},
	{0x0D, "Embedded ctrl init"},
	{0x0E, "Docking station attachment"},
	{0x0F, "Enable docking station"},
	{0x10, "Docking station ejection"},
	{0x11, "Disabling docking station"},
	{0x12, "Calling OS Wakeup"},
	{0x13, "Starting OS"},
	{0x14, "Baseboard Init"},
	{0x15, ""},
	{0x16, "Floppy Init"},
	{0x17, "Keyboard Test"},
	{0x18, "Pointing Device Test"},
	{0x19, "Primary Proc Init"},
	{0xFF, "Unknown"}
};

event_data_t g_fwprogress00h[] = {
	{0x00, "Unspecified."},
	{0x01, "No system memory detected"},
	{0x02, "No usable system memory"},
	{0x03, "Unrecoverable hard-disk/ATAPI/IDE"},
	{0x04, "Unrecoverable system-board"},
	{0x05, "Unrecoverable diskette"},
	{0x06, "Unrecoverable hard-disk controller"},
	{0x07, "Unrecoverable PS/2 or USB keyboard"},
	{0x08, "Removable boot media not found"},
	{0x09, "Unrecoverable video controller"},
	{0x0A, "No video device detected"},
	{0x0B, "Firmware ROM corruption detected"},
	{0x0C, "CPU voltage mismatch"},
	{0x0D, "CPU speed matching"},
	{0xFF, "unknown"},
};


char *event_data_lookup(event_data_t *p, uint8_t b) {

	while(p->data != 0xFF) {
		if (p->data == b) {
			break;
		}
		p++;
	}

	return p->text;
}



//  The fw progress sensor contains some additional information that needs to be processed
//  prior to calling the dbus code.
int set_sensor_dbus_state_fwprogress(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) {

	char valuestring[128];
	char* p = valuestring;

	switch (pTable->offset) {

		case 0x00 : snprintf(p, sizeof(valuestring), "POST Error, %s", event_data_lookup(g_fwprogress00h, pRec->event_data2));
					break;
		case 0x01 : /* Using g_fwprogress02h for 0x01 because that's what the ipmi spec says to do */
					snprintf(p, sizeof(valuestring), "FW Hang, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2));
					break;
		case 0x02 : snprintf(p, sizeof(valuestring), "FW Progress, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2));
					break;
		default : snprintf(p, sizeof(valuestring), "Internal warning, fw_progres offset unknown (0x%02x)", pTable->offset);
					break;
	}

	return set_sensor_dbus_state_s(pRec->sensor_number,
                                   pTable->member,
                                   p);
}

// Handling this special OEM sensor by coping what is in byte 4.  I also think that is odd
// considering byte 3 is for sensor reading.  This seems like a misuse of the IPMI spec
int set_sensor_dbus_state_osbootcount(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) {
	return set_sensor_dbus_state_y(pRec->sensor_number,
                                   "setValue",
                                   pRec->assert_state7_0);
}

int set_sensor_dbus_state_system_event(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) {
	char valuestring[128];
	char* p = valuestring;

	switch (pTable->offset) {

		case 0x00 : snprintf(p, sizeof(valuestring), "System Reconfigured");
					break;
		case 0x01 : snprintf(p, sizeof(valuestring), "OEM Boot Event");
					break;
		case 0x02 : snprintf(p, sizeof(valuestring), "Undetermined System Hardware Failure");
					break;
		case 0x03 : snprintf(p, sizeof(valuestring), "System Failure see error log for more details (0x%02x)", pRec->event_data2);
					break;
		case 0x04 : snprintf(p, sizeof(valuestring), "System Failure see PEF error log for more details (0x%02x)", pRec->event_data2);
					break;
		default : snprintf(p, sizeof(valuestring), "Internal warning, system_event offset unknown (0x%02x)", pTable->offset);
					break;
	}

	return set_sensor_dbus_state_s(pRec->sensor_number,
                                   pTable->member,
                                   p);
}


//  This table lists only senors we care about telling dbus about.
//  Offset definition cab be found in section 42.2 of the IPMI 2.0
//  spec.  Add more if/when there are more items of interest.
lookup_t g_ipmidbuslookup[] = {

	{0xe9, 0x00, set_sensor_dbus_state_simple, "setValue", "Disabled", ""}, // OCC Inactive 0
	{0xe9, 0x01, set_sensor_dbus_state_simple, "setValue", "Enabled", ""},   // OCC Active 1
	// Turbo Allowed
	{0xda, 0x00, set_sensor_dbus_state_simple, "setValue", "True", "False"},
	// Power Supply Derating
	{0xb4, 0x00, set_sensor_dbus_state_simple, "setValue", "", ""},
	// Power Cap
	{0xC2, 0x00, set_sensor_dbus_state_simple, "setValue", "", ""},
	{0x07, 0x07, set_sensor_dbus_state_simple, "setPresent", "True", "False"},
	{0x07, 0x08, set_sensor_dbus_state_simple, "setFault",   "True", "False"},
	{0x0C, 0x06, set_sensor_dbus_state_simple, "setPresent", "True", "False"},
	{0x0C, 0x04, set_sensor_dbus_state_simple, "setFault",   "True", "False"},
	{0x0F, 0x02, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"},
	{0x0F, 0x01, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"},
	{0x0F, 0x00, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"},
	{0xC7, 0x01, set_sensor_dbus_state_simple, "setFault", "True", "False"},
	{0xc3, 0x00, set_sensor_dbus_state_osbootcount, "setValue", "" ,""},
	{0x1F, 0x00, set_sensor_dbus_state_simple, "setValue", "Boot completed (00)", ""},
	{0x1F, 0x01, set_sensor_dbus_state_simple, "setValue", "Boot completed (01)", ""},
	{0x1F, 0x02, set_sensor_dbus_state_simple, "setValue", "PXE boot completed", ""},
	{0x1F, 0x03, set_sensor_dbus_state_simple, "setValue", "Diagnostic boot completed", ""},
	{0x1F, 0x04, set_sensor_dbus_state_simple, "setValue", "CD-ROM boot completed", ""},
	{0x1F, 0x05, set_sensor_dbus_state_simple, "setValue", "ROM boot completed", ""},
	{0x1F, 0x06, set_sensor_dbus_state_simple, "setValue", "Boot completed (06)", ""},
	{0x12, 0x00, set_sensor_dbus_state_system_event, "setValue", "", ""},
	{0x12, 0x01, set_sensor_dbus_state_system_event, "setValue", "", ""},
	{0x12, 0x02, set_sensor_dbus_state_system_event, "setValue", "", ""},
	{0x12, 0x03, set_sensor_dbus_state_system_event, "setValue", "", ""},
	{0x12, 0x04, set_sensor_dbus_state_system_event, "setValue", "", ""},
	{0xCA, 0x00, set_sensor_dbus_state_simple,       "setValue", "Disabled", ""},
	{0xCA, 0x01, set_sensor_dbus_state_simple,       "setValue", "Enabled", ""},
	{0xFF, 0xFF, NULL, "", "", ""}
};


void reportSensorEventAssert(sensorRES_t *pRec, int index) {
	lookup_t *pTable = &g_ipmidbuslookup[index];
	(*pTable->func)(pRec, pTable, pTable->assertion);
}
void reportSensorEventDeassert(sensorRES_t *pRec, int index) {
	lookup_t *pTable = &g_ipmidbuslookup[index];
	(*pTable->func)(pRec, pTable, pTable->deassertion);
}


int findindex(const uint8_t sensor_type, int offset, int *index) {

	int i=0, rc=0;
	lookup_t *pTable = g_ipmidbuslookup;

	do {
		if ( ((pTable+i)->sensor_type == sensor_type) &&
			 ((pTable+i)->offset  == offset) ) {
			rc = 1;
			*index = i;
			break;
		}
		i++;
	} while ((pTable+i)->sensor_type  != 0xFF);

	return rc;
}

bool shouldReport(uint8_t sensorType, int offset, int *index) {

	bool rc = false;

	if (findindex(sensorType, offset, index)) { rc = true;	}
    if (rc == false) {
#ifdef __IPMI_DEBUG__
        log<level::DEBUG>("LOOKATME: Sensor should not be reported",
                        entry("SENSORTYPE=0x%02x", sensorType),
                        entry("OFFSET=0x%02x", offset));
#endif
        }

	return rc;
}


int updateSensorRecordFromSSRAESC(const void *record) {

	sensorRES_t *pRec = (sensorRES_t *) record;
	uint8_t stype;
	int index, i=0;

	stype = find_type_for_sensor_number(pRec->sensor_number);

	// 0xC3 types use the assertion7_0 for the value to be set
	// so skip the reseach and call the correct event reporting
	// function
	if (stype == 0xC3) {

		shouldReport(stype, 0x00, &index);
		reportSensorEventAssert(pRec, index);

	} else {
		// Scroll through each bit position .  Determine
		// if any bit is either asserted or Deasserted.
		for(i=0;i<8;i++) {

			if ((ISBITSET(pRec->assert_state7_0,i))  &&
				(shouldReport(stype, i, &index)))
			{
				reportSensorEventAssert(pRec, index);
			}
			if ((ISBITSET(pRec->assert_state14_8,i))  &&
				(shouldReport(stype, i+8, &index)))
			{
				reportSensorEventAssert(pRec, index);
			}
			if ((ISBITSET(pRec->deassert_state7_0,i))  &&
				(shouldReport(stype, i, &index)))
			{
				reportSensorEventDeassert(pRec, index);
			}
			if ((ISBITSET(pRec->deassert_state14_8,i))  &&
				(shouldReport(stype, i+8, &index)))
			{
				reportSensorEventDeassert(pRec, index);
			}
		}

	}


	return 0;
}
OpenPOWER on IntegriCloud