xref: /openbmc/ipmitool/lib/ipmi_sel.c (revision 2d79e69f)
1c18ec02fSPetter Reinholdtsen /* -*-mode: C; indent-tabs-mode: t; -*-
2c18ec02fSPetter Reinholdtsen  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
3c18ec02fSPetter Reinholdtsen  *
4c18ec02fSPetter Reinholdtsen  * Redistribution and use in source and binary forms, with or without
5c18ec02fSPetter Reinholdtsen  * modification, are permitted provided that the following conditions
6c18ec02fSPetter Reinholdtsen  * are met:
7c18ec02fSPetter Reinholdtsen  *
8c18ec02fSPetter Reinholdtsen  * Redistribution of source code must retain the above copyright
9c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer.
10c18ec02fSPetter Reinholdtsen  *
11c18ec02fSPetter Reinholdtsen  * Redistribution in binary form must reproduce the above copyright
12c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer in the
13c18ec02fSPetter Reinholdtsen  * documentation and/or other materials provided with the distribution.
14c18ec02fSPetter Reinholdtsen  *
15c18ec02fSPetter Reinholdtsen  * Neither the name of Sun Microsystems, Inc. or the names of
16c18ec02fSPetter Reinholdtsen  * contributors may be used to endorse or promote products derived
17c18ec02fSPetter Reinholdtsen  * from this software without specific prior written permission.
18c18ec02fSPetter Reinholdtsen  *
19c18ec02fSPetter Reinholdtsen  * This software is provided "AS IS," without a warranty of any kind.
20c18ec02fSPetter Reinholdtsen  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21c18ec02fSPetter Reinholdtsen  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22c18ec02fSPetter Reinholdtsen  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23c18ec02fSPetter Reinholdtsen  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24c18ec02fSPetter Reinholdtsen  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25c18ec02fSPetter Reinholdtsen  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
26c18ec02fSPetter Reinholdtsen  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27c18ec02fSPetter Reinholdtsen  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28c18ec02fSPetter Reinholdtsen  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29c18ec02fSPetter Reinholdtsen  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30c18ec02fSPetter Reinholdtsen  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31c18ec02fSPetter Reinholdtsen  */
32c18ec02fSPetter Reinholdtsen 
33c18ec02fSPetter Reinholdtsen #include <string.h>
34c18ec02fSPetter Reinholdtsen #include <math.h>
35c18ec02fSPetter Reinholdtsen #define __USE_XOPEN /* glibc2 needs this for strptime */
36c18ec02fSPetter Reinholdtsen #include <time.h>
37c18ec02fSPetter Reinholdtsen #include <ctype.h>
38c18ec02fSPetter Reinholdtsen #include <errno.h>
39c18ec02fSPetter Reinholdtsen 
40c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
41c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
42c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
43c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_mc.h>
44c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
45c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sel.h>
46c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sdr.h>
47c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_fru.h>
48c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sensor.h>
49c18ec02fSPetter Reinholdtsen 
50c18ec02fSPetter Reinholdtsen extern int verbose;
51c18ec02fSPetter Reinholdtsen static int sel_extended = 0;
52c18ec02fSPetter Reinholdtsen static int sel_oem_nrecs = 0;
53c18ec02fSPetter Reinholdtsen 
54c18ec02fSPetter Reinholdtsen static IPMI_OEM sel_iana = IPMI_OEM_UNKNOWN;
55c18ec02fSPetter Reinholdtsen 
56c18ec02fSPetter Reinholdtsen struct ipmi_sel_oem_msg_rec {
57c18ec02fSPetter Reinholdtsen 	int	value[14];
58c18ec02fSPetter Reinholdtsen 	char	*string[14];
59c18ec02fSPetter Reinholdtsen 	char	*text;
60c18ec02fSPetter Reinholdtsen } *sel_oem_msg;
61c18ec02fSPetter Reinholdtsen 
62c18ec02fSPetter Reinholdtsen #define SEL_BYTE(n) (n-3) /* So we can refer to byte positions in log entries (byte 3 is at index 0, etc) */
63c18ec02fSPetter Reinholdtsen 
64c18ec02fSPetter Reinholdtsen // Definiation for the Decoding the SEL OEM Bytes for DELL Platfoms
65c18ec02fSPetter Reinholdtsen #define BIT(x)	 (1 << x)	/* Select the Bit */
66c18ec02fSPetter Reinholdtsen #define	SIZE_OF_DESC	128	/* Max Size of the description String to be displyed for the Each sel entry */
67c18ec02fSPetter Reinholdtsen #define	MAX_CARDNO_STR	32	/* Max Size of Card number string */
68c18ec02fSPetter Reinholdtsen #define	MAX_DIMM_STR	32	/* Max Size of DIMM string */
69c18ec02fSPetter Reinholdtsen #define	MAX_CARD_STR	32	/* Max Size of Card string */
70c18ec02fSPetter Reinholdtsen /*
71c18ec02fSPetter Reinholdtsen  * Reads values found in message translation file.  XX is a wildcard, R means reserved.
72c18ec02fSPetter Reinholdtsen  * Returns -1 for XX, -2 for R, -3 for non-hex (string), or positive integer from a hex value.
73c18ec02fSPetter Reinholdtsen  */
ipmi_sel_oem_readval(char * str)74c18ec02fSPetter Reinholdtsen static int ipmi_sel_oem_readval(char *str)
75c18ec02fSPetter Reinholdtsen {
76c18ec02fSPetter Reinholdtsen 	int ret;
77c18ec02fSPetter Reinholdtsen 	if (!strcmp(str, "XX")) {
78c18ec02fSPetter Reinholdtsen 		return -1;
79c18ec02fSPetter Reinholdtsen 	}
80c18ec02fSPetter Reinholdtsen 	if (!strcmp(str, "R")) {
81c18ec02fSPetter Reinholdtsen 		return -2;
82c18ec02fSPetter Reinholdtsen 	}
83c18ec02fSPetter Reinholdtsen 	if (sscanf(str, "0x%x", &ret) != 1) {
84c18ec02fSPetter Reinholdtsen 		return -3;
85c18ec02fSPetter Reinholdtsen 	}
86c18ec02fSPetter Reinholdtsen 	return ret;
87c18ec02fSPetter Reinholdtsen }
88c18ec02fSPetter Reinholdtsen 
89c18ec02fSPetter Reinholdtsen /*
90c18ec02fSPetter Reinholdtsen  * This is where the magic happens.  SEL_BYTE is a bit ugly, but it allows
91c18ec02fSPetter Reinholdtsen  * reference to byte positions instead of array indexes which (hopefully)
92c18ec02fSPetter Reinholdtsen  * helps make the code easier to read.
93c18ec02fSPetter Reinholdtsen  */
9482a0caa3SZdenek Styblik static int
ipmi_sel_oem_match(uint8_t * evt,const struct ipmi_sel_oem_msg_rec * rec)95*88891f69SZdenek Styblik ipmi_sel_oem_match(uint8_t *evt, const struct ipmi_sel_oem_msg_rec *rec)
96c18ec02fSPetter Reinholdtsen {
97*88891f69SZdenek Styblik 	if (evt[2] == rec->value[SEL_BYTE(3)]
98*88891f69SZdenek Styblik 		&& ((rec->value[SEL_BYTE(4)] < 0)
99*88891f69SZdenek Styblik 			|| (evt[3] == rec->value[SEL_BYTE(4)]))
100*88891f69SZdenek Styblik 		&& ((rec->value[SEL_BYTE(5)] < 0)
101*88891f69SZdenek Styblik 			|| (evt[4] == rec->value[SEL_BYTE(5)]))
102*88891f69SZdenek Styblik 		&& ((rec->value[SEL_BYTE(6)] < 0)
103*88891f69SZdenek Styblik 			|| (evt[5] == rec->value[SEL_BYTE(6)]))
104*88891f69SZdenek Styblik 		&& ((rec->value[SEL_BYTE(7)] < 0)
105*88891f69SZdenek Styblik 			|| (evt[6] == rec->value[SEL_BYTE(7)]))
106*88891f69SZdenek Styblik 		&& ((rec->value[SEL_BYTE(11)] < 0)
107*88891f69SZdenek Styblik 			|| (evt[10] == rec->value[SEL_BYTE(11)]))
108*88891f69SZdenek Styblik 		&& ((rec->value[SEL_BYTE(12)] < 0)
109*88891f69SZdenek Styblik 			|| (evt[11] == rec->value[SEL_BYTE(12)]))) {
110c18ec02fSPetter Reinholdtsen 		return 1;
111c18ec02fSPetter Reinholdtsen 	} else {
112c18ec02fSPetter Reinholdtsen 		return 0;
113c18ec02fSPetter Reinholdtsen 	}
114c18ec02fSPetter Reinholdtsen }
115c18ec02fSPetter Reinholdtsen 
ipmi_sel_oem_init(const char * filename)116c18ec02fSPetter Reinholdtsen int ipmi_sel_oem_init(const char * filename)
117c18ec02fSPetter Reinholdtsen {
118c18ec02fSPetter Reinholdtsen 	FILE * fp;
119c18ec02fSPetter Reinholdtsen 	int i, j, k, n, byte;
120c18ec02fSPetter Reinholdtsen 	char buf[15][150];
121c18ec02fSPetter Reinholdtsen 
122c18ec02fSPetter Reinholdtsen 	if (filename == NULL) {
123c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "No SEL OEM filename provided");
124c18ec02fSPetter Reinholdtsen 		return -1;
125c18ec02fSPetter Reinholdtsen 	}
126c18ec02fSPetter Reinholdtsen 
127c18ec02fSPetter Reinholdtsen 	fp = ipmi_open_file_read(filename);
128c18ec02fSPetter Reinholdtsen 	if (fp == NULL) {
129c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Could not open %s file", filename);
130c18ec02fSPetter Reinholdtsen 		return -1;
131c18ec02fSPetter Reinholdtsen 	}
132c18ec02fSPetter Reinholdtsen 
133c18ec02fSPetter Reinholdtsen 	/* count number of records (lines) in input file */
134c18ec02fSPetter Reinholdtsen 	sel_oem_nrecs = 0;
135c18ec02fSPetter Reinholdtsen 	while (fscanf(fp, "%*[^\n]\n") == 0) {
136c18ec02fSPetter Reinholdtsen 		sel_oem_nrecs++;
137c18ec02fSPetter Reinholdtsen 	}
138c18ec02fSPetter Reinholdtsen 
139c18ec02fSPetter Reinholdtsen 	printf("nrecs=%d\n", sel_oem_nrecs);
140c18ec02fSPetter Reinholdtsen 
141c18ec02fSPetter Reinholdtsen 	rewind(fp);
142c18ec02fSPetter Reinholdtsen 	sel_oem_msg = (struct ipmi_sel_oem_msg_rec *)calloc(sel_oem_nrecs,
143c18ec02fSPetter Reinholdtsen 				 sizeof(struct ipmi_sel_oem_msg_rec));
144c18ec02fSPetter Reinholdtsen 
145c18ec02fSPetter Reinholdtsen 	for (i=0; i < sel_oem_nrecs; i++) {
146c18ec02fSPetter Reinholdtsen 		n=fscanf(fp, "\"%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"%[^\"]\",\""
147c18ec02fSPetter Reinholdtsen 			       "%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"%[^\"]\",\""
148c18ec02fSPetter Reinholdtsen 			       "%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"%[^\"]\",\""
149c18ec02fSPetter Reinholdtsen 			       "%[^\"]\",\"%[^\"]\",\"%[^\"]\"\n",
150c18ec02fSPetter Reinholdtsen 			 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
151c18ec02fSPetter Reinholdtsen 			 buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
152c18ec02fSPetter Reinholdtsen 			 buf[12], buf[13], buf[14]);
153c18ec02fSPetter Reinholdtsen 
154c18ec02fSPetter Reinholdtsen 		if (n != 15) {
155c18ec02fSPetter Reinholdtsen 			lprintf (LOG_ERR, "Encountered problems reading line %d of %s",
156c18ec02fSPetter Reinholdtsen 				 i+1, filename);
157c18ec02fSPetter Reinholdtsen 			fclose(fp);
158c18ec02fSPetter Reinholdtsen 			fp = NULL;
159c18ec02fSPetter Reinholdtsen 			sel_oem_nrecs = 0;
160c18ec02fSPetter Reinholdtsen 			/* free all the memory allocated so far */
161c18ec02fSPetter Reinholdtsen 			for (j=0; j<i ; j++) {
162c18ec02fSPetter Reinholdtsen 				for (k=3; k<17; k++) {
163c18ec02fSPetter Reinholdtsen 					if (sel_oem_msg[j].value[SEL_BYTE(k)] == -3) {
164c18ec02fSPetter Reinholdtsen 						free(sel_oem_msg[j].string[SEL_BYTE(k)]);
165c18ec02fSPetter Reinholdtsen 						sel_oem_msg[j].string[SEL_BYTE(k)] = NULL;
166c18ec02fSPetter Reinholdtsen 					}
167c18ec02fSPetter Reinholdtsen 				}
168c18ec02fSPetter Reinholdtsen 			}
169c18ec02fSPetter Reinholdtsen 			free(sel_oem_msg);
170c18ec02fSPetter Reinholdtsen 			sel_oem_msg = NULL;
171c18ec02fSPetter Reinholdtsen 			return -1;
172c18ec02fSPetter Reinholdtsen 		}
173c18ec02fSPetter Reinholdtsen 
174c18ec02fSPetter Reinholdtsen 		for (byte = 3; byte < 17; byte++) {
175c18ec02fSPetter Reinholdtsen 			if ((sel_oem_msg[i].value[SEL_BYTE(byte)] =
176c18ec02fSPetter Reinholdtsen 			     ipmi_sel_oem_readval(buf[SEL_BYTE(byte)])) == -3) {
177c18ec02fSPetter Reinholdtsen 				sel_oem_msg[i].string[SEL_BYTE(byte)] =
178c18ec02fSPetter Reinholdtsen 					(char *)malloc(strlen(buf[SEL_BYTE(byte)]) + 1);
179c18ec02fSPetter Reinholdtsen 				strcpy(sel_oem_msg[i].string[SEL_BYTE(byte)],
180c18ec02fSPetter Reinholdtsen 				       buf[SEL_BYTE(byte)]);
181c18ec02fSPetter Reinholdtsen 			}
182c18ec02fSPetter Reinholdtsen 		}
183c18ec02fSPetter Reinholdtsen 		sel_oem_msg[i].text = (char *)malloc(strlen(buf[SEL_BYTE(17)]) + 1);
184c18ec02fSPetter Reinholdtsen 		strcpy(sel_oem_msg[i].text, buf[SEL_BYTE(17)]);
185c18ec02fSPetter Reinholdtsen 	}
186c18ec02fSPetter Reinholdtsen 
187c18ec02fSPetter Reinholdtsen 	fclose(fp);
188c18ec02fSPetter Reinholdtsen 	fp = NULL;
189c18ec02fSPetter Reinholdtsen 	return 0;
190c18ec02fSPetter Reinholdtsen }
191c18ec02fSPetter Reinholdtsen 
ipmi_sel_oem_message(struct sel_event_record * evt,int verbose)192c18ec02fSPetter Reinholdtsen static void ipmi_sel_oem_message(struct sel_event_record * evt, int verbose)
193c18ec02fSPetter Reinholdtsen {
194c18ec02fSPetter Reinholdtsen 	/*
195c18ec02fSPetter Reinholdtsen 	 * Note: although we have a verbose argument, currently the output
196c18ec02fSPetter Reinholdtsen 	 * isn't affected by it.
197c18ec02fSPetter Reinholdtsen 	 */
198c18ec02fSPetter Reinholdtsen 	int i, j;
199c18ec02fSPetter Reinholdtsen 
200c18ec02fSPetter Reinholdtsen 	for (i=0; i < sel_oem_nrecs; i++) {
201*88891f69SZdenek Styblik 		if (ipmi_sel_oem_match((uint8_t *)evt, &sel_oem_msg[i])) {
202c18ec02fSPetter Reinholdtsen 			printf (csv_output ? ",\"%s\"" : " | %s", sel_oem_msg[i].text);
203c18ec02fSPetter Reinholdtsen 			for (j=4; j<17; j++) {
204c18ec02fSPetter Reinholdtsen 				if (sel_oem_msg[i].value[SEL_BYTE(j)] == -3) {
205c18ec02fSPetter Reinholdtsen 					printf (csv_output ? ",%s=0x%x" : " %s = 0x%x",
206c18ec02fSPetter Reinholdtsen 						sel_oem_msg[i].string[SEL_BYTE(j)],
207c18ec02fSPetter Reinholdtsen 						((uint8_t *)evt)[SEL_BYTE(j)]);
208c18ec02fSPetter Reinholdtsen 				}
209c18ec02fSPetter Reinholdtsen 			}
210c18ec02fSPetter Reinholdtsen 		}
211c18ec02fSPetter Reinholdtsen 	}
212c18ec02fSPetter Reinholdtsen }
213c18ec02fSPetter Reinholdtsen 
214c18ec02fSPetter Reinholdtsen static const struct valstr event_dir_vals[] = {
215c18ec02fSPetter Reinholdtsen 	{ 0, "Assertion Event" },
216c18ec02fSPetter Reinholdtsen 	{ 1, "Deassertion Event" },
217c18ec02fSPetter Reinholdtsen 	{ 0, NULL },
218c18ec02fSPetter Reinholdtsen };
219c18ec02fSPetter Reinholdtsen 
220c18ec02fSPetter Reinholdtsen static const char *
ipmi_get_event_type(uint8_t code)221c18ec02fSPetter Reinholdtsen ipmi_get_event_type(uint8_t code)
222c18ec02fSPetter Reinholdtsen {
223c18ec02fSPetter Reinholdtsen         if (code == 0)
224c18ec02fSPetter Reinholdtsen                 return "Unspecified";
225c18ec02fSPetter Reinholdtsen         if (code == 1)
226c18ec02fSPetter Reinholdtsen                 return "Threshold";
227c18ec02fSPetter Reinholdtsen         if (code >= 0x02 && code <= 0x0b)
228c18ec02fSPetter Reinholdtsen                 return "Generic Discrete";
229c18ec02fSPetter Reinholdtsen         if (code == 0x6f)
230c18ec02fSPetter Reinholdtsen                 return "Sensor-specific Discrete";
231c18ec02fSPetter Reinholdtsen         if (code >= 0x70 && code <= 0x7f)
232c18ec02fSPetter Reinholdtsen                 return "OEM";
233c18ec02fSPetter Reinholdtsen         return "Reserved";
234c18ec02fSPetter Reinholdtsen }
235c18ec02fSPetter Reinholdtsen 
236c18ec02fSPetter Reinholdtsen static char *
ipmi_sel_timestamp(uint32_t stamp)237c18ec02fSPetter Reinholdtsen ipmi_sel_timestamp(uint32_t stamp)
238c18ec02fSPetter Reinholdtsen {
239c18ec02fSPetter Reinholdtsen 	static char tbuf[40];
240c18ec02fSPetter Reinholdtsen 	time_t s = (time_t)stamp;
241c18ec02fSPetter Reinholdtsen 	memset(tbuf, 0, 40);
242c18ec02fSPetter Reinholdtsen 	strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", gmtime(&s));
243c18ec02fSPetter Reinholdtsen 	return tbuf;
244c18ec02fSPetter Reinholdtsen }
245c18ec02fSPetter Reinholdtsen 
246c18ec02fSPetter Reinholdtsen static char *
ipmi_sel_timestamp_date(uint32_t stamp)247c18ec02fSPetter Reinholdtsen ipmi_sel_timestamp_date(uint32_t stamp)
248c18ec02fSPetter Reinholdtsen {
249c18ec02fSPetter Reinholdtsen 	static char tbuf[11];
250c18ec02fSPetter Reinholdtsen 	time_t s = (time_t)stamp;
251c18ec02fSPetter Reinholdtsen 	strftime(tbuf, sizeof(tbuf), "%m/%d/%Y", gmtime(&s));
252c18ec02fSPetter Reinholdtsen 	return tbuf;
253c18ec02fSPetter Reinholdtsen }
254c18ec02fSPetter Reinholdtsen 
255c18ec02fSPetter Reinholdtsen static char *
ipmi_sel_timestamp_time(uint32_t stamp)256c18ec02fSPetter Reinholdtsen ipmi_sel_timestamp_time(uint32_t stamp)
257c18ec02fSPetter Reinholdtsen {
258c18ec02fSPetter Reinholdtsen 	static char tbuf[9];
259c18ec02fSPetter Reinholdtsen 	time_t s = (time_t)stamp;
260c18ec02fSPetter Reinholdtsen 	strftime(tbuf, sizeof(tbuf), "%H:%M:%S", gmtime(&s));
261c18ec02fSPetter Reinholdtsen 	return tbuf;
262c18ec02fSPetter Reinholdtsen }
263c18ec02fSPetter Reinholdtsen 
264c18ec02fSPetter Reinholdtsen static char *
hex2ascii(uint8_t * hexChars,uint8_t numBytes)265c18ec02fSPetter Reinholdtsen hex2ascii (uint8_t * hexChars, uint8_t numBytes)
266c18ec02fSPetter Reinholdtsen {
267c18ec02fSPetter Reinholdtsen 	int count;
268c18ec02fSPetter Reinholdtsen 	static char hexString[SEL_OEM_NOTS_DATA_LEN+1];       /*Max Size*/
269c18ec02fSPetter Reinholdtsen 
270c18ec02fSPetter Reinholdtsen 	if(numBytes > SEL_OEM_NOTS_DATA_LEN)
271c18ec02fSPetter Reinholdtsen 		numBytes = SEL_OEM_NOTS_DATA_LEN;
272c18ec02fSPetter Reinholdtsen 
273c18ec02fSPetter Reinholdtsen 	for(count=0;count < numBytes;count++)
274c18ec02fSPetter Reinholdtsen 	{
275c18ec02fSPetter Reinholdtsen 		if((hexChars[count]<0x40)||(hexChars[count]>0x7e))
276c18ec02fSPetter Reinholdtsen 			hexString[count]='.';
277c18ec02fSPetter Reinholdtsen     		else
278c18ec02fSPetter Reinholdtsen 			hexString[count]=hexChars[count];
279c18ec02fSPetter Reinholdtsen 	}
280c18ec02fSPetter Reinholdtsen 	hexString[numBytes]='\0';
281c18ec02fSPetter Reinholdtsen 	return hexString;
282c18ec02fSPetter Reinholdtsen }
283c18ec02fSPetter Reinholdtsen 
284c18ec02fSPetter Reinholdtsen IPMI_OEM
ipmi_get_oem(struct ipmi_intf * intf)285c18ec02fSPetter Reinholdtsen ipmi_get_oem(struct ipmi_intf * intf)
286c18ec02fSPetter Reinholdtsen {
287c18ec02fSPetter Reinholdtsen 	/* Execute a Get Device ID command to determine the OEM */
288c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
289c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
290c18ec02fSPetter Reinholdtsen 	struct ipm_devid_rsp *devid;
291c18ec02fSPetter Reinholdtsen 
292c18ec02fSPetter Reinholdtsen 	if (intf->fd == 0) {
293c18ec02fSPetter Reinholdtsen 		if( sel_iana != IPMI_OEM_UNKNOWN ){
294c18ec02fSPetter Reinholdtsen 			return sel_iana;
295c18ec02fSPetter Reinholdtsen 		}
296c18ec02fSPetter Reinholdtsen 		return IPMI_OEM_UNKNOWN;
297c18ec02fSPetter Reinholdtsen 	}
298c18ec02fSPetter Reinholdtsen 
299c18ec02fSPetter Reinholdtsen 	/*
300c18ec02fSPetter Reinholdtsen 	 * Return the cached manufacturer id if the device is open and
301c18ec02fSPetter Reinholdtsen 	 * we got an identified OEM owner.   Otherwise just attempt to read
302c18ec02fSPetter Reinholdtsen 	 * it.
303c18ec02fSPetter Reinholdtsen 	 */
304c18ec02fSPetter Reinholdtsen 	if (intf->opened && intf->manufacturer_id != IPMI_OEM_UNKNOWN) {
305c18ec02fSPetter Reinholdtsen 		return intf->manufacturer_id;
306c18ec02fSPetter Reinholdtsen 	}
307c18ec02fSPetter Reinholdtsen 
308c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
309c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
310c18ec02fSPetter Reinholdtsen 	req.msg.cmd   = BMC_GET_DEVICE_ID;
311c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 0;
312c18ec02fSPetter Reinholdtsen 
313c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
314c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
315c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Device ID command failed");
316c18ec02fSPetter Reinholdtsen 		return IPMI_OEM_UNKNOWN;
317c18ec02fSPetter Reinholdtsen 	}
318c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
319c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Device ID command failed: %#x %s",
320c18ec02fSPetter Reinholdtsen 			rsp->ccode, val2str(rsp->ccode, completion_code_vals));
321c18ec02fSPetter Reinholdtsen 		return IPMI_OEM_UNKNOWN;
322c18ec02fSPetter Reinholdtsen 	}
323c18ec02fSPetter Reinholdtsen 
324c18ec02fSPetter Reinholdtsen 	devid = (struct ipm_devid_rsp *) rsp->data;
325c18ec02fSPetter Reinholdtsen 
326c18ec02fSPetter Reinholdtsen 	lprintf(LOG_DEBUG,"Iana: %u",
327c18ec02fSPetter Reinholdtsen            IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id));
328c18ec02fSPetter Reinholdtsen 
329c18ec02fSPetter Reinholdtsen 	return  IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id);
330c18ec02fSPetter Reinholdtsen }
331c18ec02fSPetter Reinholdtsen 
332c18ec02fSPetter Reinholdtsen static int
ipmi_sel_add_entry(struct ipmi_intf * intf,struct sel_event_record * rec)333c18ec02fSPetter Reinholdtsen ipmi_sel_add_entry(struct ipmi_intf * intf, struct sel_event_record * rec)
334c18ec02fSPetter Reinholdtsen {
335c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
336c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
337c18ec02fSPetter Reinholdtsen 
338c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
339c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
340c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_CMD_ADD_SEL_ENTRY;
341c18ec02fSPetter Reinholdtsen 	req.msg.data = (unsigned char *)rec;
342c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 16;
343c18ec02fSPetter Reinholdtsen 
344c18ec02fSPetter Reinholdtsen 	ipmi_sel_print_std_entry(intf, rec);
345c18ec02fSPetter Reinholdtsen 
346c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
347c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
348c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Add SEL Entry failed");
349c18ec02fSPetter Reinholdtsen 		return -1;
350c18ec02fSPetter Reinholdtsen 	}
351c18ec02fSPetter Reinholdtsen 	else if (rsp->ccode > 0) {
352c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Add SEL Entry failed: %s",
353c18ec02fSPetter Reinholdtsen 			val2str(rsp->ccode, completion_code_vals));
354c18ec02fSPetter Reinholdtsen 		return -1;
355c18ec02fSPetter Reinholdtsen 	}
356c18ec02fSPetter Reinholdtsen 
357c18ec02fSPetter Reinholdtsen 	return 0;
358c18ec02fSPetter Reinholdtsen }
359c18ec02fSPetter Reinholdtsen 
360c18ec02fSPetter Reinholdtsen 
361c18ec02fSPetter Reinholdtsen static int
ipmi_sel_add_entries_fromfile(struct ipmi_intf * intf,const char * filename)362c18ec02fSPetter Reinholdtsen ipmi_sel_add_entries_fromfile(struct ipmi_intf * intf, const char * filename)
363c18ec02fSPetter Reinholdtsen {
364c18ec02fSPetter Reinholdtsen 	FILE * fp;
365c18ec02fSPetter Reinholdtsen 	char buf[1024];
366c18ec02fSPetter Reinholdtsen 	char * ptr, * tok;
367c18ec02fSPetter Reinholdtsen 	int i, j;
368c18ec02fSPetter Reinholdtsen 	int rc = 0;
369c18ec02fSPetter Reinholdtsen 	uint8_t rqdata[8];
370c18ec02fSPetter Reinholdtsen 	struct sel_event_record sel_event;
371c18ec02fSPetter Reinholdtsen 
372c18ec02fSPetter Reinholdtsen 	if (filename == NULL)
373c18ec02fSPetter Reinholdtsen 		return -1;
374c18ec02fSPetter Reinholdtsen 
375c18ec02fSPetter Reinholdtsen 	fp = ipmi_open_file_read(filename);
376c18ec02fSPetter Reinholdtsen 	if (fp == NULL)
377c18ec02fSPetter Reinholdtsen 		return -1;
378c18ec02fSPetter Reinholdtsen 
379c18ec02fSPetter Reinholdtsen 	while (feof(fp) == 0) {
380c18ec02fSPetter Reinholdtsen 		if (fgets(buf, 1024, fp) == NULL)
381c18ec02fSPetter Reinholdtsen 			continue;
382c18ec02fSPetter Reinholdtsen 
383c18ec02fSPetter Reinholdtsen 		/* clip off optional comment tail indicated by # */
384c18ec02fSPetter Reinholdtsen 		ptr = strchr(buf, '#');
385c18ec02fSPetter Reinholdtsen 		if (ptr)
386c18ec02fSPetter Reinholdtsen 			*ptr = '\0';
387c18ec02fSPetter Reinholdtsen 		else
388c18ec02fSPetter Reinholdtsen 			ptr = buf + strlen(buf);
389c18ec02fSPetter Reinholdtsen 
390c18ec02fSPetter Reinholdtsen 		/* clip off trailing and leading whitespace */
391c18ec02fSPetter Reinholdtsen 		ptr--;
392c18ec02fSPetter Reinholdtsen 		while (isspace((int)*ptr) && ptr >= buf)
393c18ec02fSPetter Reinholdtsen 			*ptr-- = '\0';
394c18ec02fSPetter Reinholdtsen 		ptr = buf;
395c18ec02fSPetter Reinholdtsen 		while (isspace((int)*ptr))
396c18ec02fSPetter Reinholdtsen 			ptr++;
397c18ec02fSPetter Reinholdtsen 		if (strlen(ptr) == 0)
398c18ec02fSPetter Reinholdtsen 			continue;
399c18ec02fSPetter Reinholdtsen 
400c18ec02fSPetter Reinholdtsen 		/* parse the event, 7 bytes with optional comment */
401c18ec02fSPetter Reinholdtsen 		/* 0x00 0x00 0x00 0x00 0x00 0x00 0x00 # event */
402c18ec02fSPetter Reinholdtsen 		i = 0;
403c18ec02fSPetter Reinholdtsen 		tok = strtok(ptr, " ");
404c18ec02fSPetter Reinholdtsen 		while (tok) {
405c18ec02fSPetter Reinholdtsen 			if (i == 7)
406c18ec02fSPetter Reinholdtsen 				break;
407c18ec02fSPetter Reinholdtsen 			j = i++;
408c18ec02fSPetter Reinholdtsen 			if (str2uchar(tok, &rqdata[j]) != 0) {
409c18ec02fSPetter Reinholdtsen 				break;
410c18ec02fSPetter Reinholdtsen 			}
411c18ec02fSPetter Reinholdtsen 			tok = strtok(NULL, " ");
412c18ec02fSPetter Reinholdtsen 		}
413c18ec02fSPetter Reinholdtsen 		if (i < 7) {
414c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid Event: %s",
415c18ec02fSPetter Reinholdtsen 			       buf2str(rqdata, sizeof(rqdata)));
416c18ec02fSPetter Reinholdtsen 			continue;
417c18ec02fSPetter Reinholdtsen 		}
418c18ec02fSPetter Reinholdtsen 
419c18ec02fSPetter Reinholdtsen 		memset(&sel_event, 0, sizeof(struct sel_event_record));
420c18ec02fSPetter Reinholdtsen 		sel_event.record_id = 0x0000;
421c18ec02fSPetter Reinholdtsen 		sel_event.record_type = 0x02;
422c18ec02fSPetter Reinholdtsen 		sel_event.sel_type.standard_type.gen_id = 0x00;
423c18ec02fSPetter Reinholdtsen 		sel_event.sel_type.standard_type.evm_rev = rqdata[0];
424c18ec02fSPetter Reinholdtsen 		sel_event.sel_type.standard_type.sensor_type = rqdata[1];
425c18ec02fSPetter Reinholdtsen 		sel_event.sel_type.standard_type.sensor_num = rqdata[2];
426c18ec02fSPetter Reinholdtsen 		sel_event.sel_type.standard_type.event_type = rqdata[3] & 0x7f;
427c18ec02fSPetter Reinholdtsen 		sel_event.sel_type.standard_type.event_dir = (rqdata[3] & 0x80) >> 7;
428c18ec02fSPetter Reinholdtsen 		sel_event.sel_type.standard_type.event_data[0] = rqdata[4];
429c18ec02fSPetter Reinholdtsen 		sel_event.sel_type.standard_type.event_data[1] = rqdata[5];
430c18ec02fSPetter Reinholdtsen 		sel_event.sel_type.standard_type.event_data[2] = rqdata[6];
431c18ec02fSPetter Reinholdtsen 
432c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_add_entry(intf, &sel_event);
433c18ec02fSPetter Reinholdtsen 		if (rc < 0)
434c18ec02fSPetter Reinholdtsen 			break;
435c18ec02fSPetter Reinholdtsen 	}
436c18ec02fSPetter Reinholdtsen 
437c18ec02fSPetter Reinholdtsen 	fclose(fp);
438c18ec02fSPetter Reinholdtsen 	return rc;
439c18ec02fSPetter Reinholdtsen }
440c18ec02fSPetter Reinholdtsen 
441c18ec02fSPetter Reinholdtsen static struct ipmi_event_sensor_types oem_kontron_event_reading_types[] __attribute__((unused)) = {
442c18ec02fSPetter Reinholdtsen    { 0x70 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "OEM Firmware Info 1", "Code Assert" },
443c18ec02fSPetter Reinholdtsen    { 0x71 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "OEM Firmware Info 2", "Code Assert" },
444c18ec02fSPetter Reinholdtsen };
445c18ec02fSPetter Reinholdtsen 
446c18ec02fSPetter Reinholdtsen char *
get_kontron_evt_desc(struct ipmi_intf * intf,struct sel_event_record * rec)447c18ec02fSPetter Reinholdtsen get_kontron_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
448c18ec02fSPetter Reinholdtsen {
449c18ec02fSPetter Reinholdtsen 	char * description = NULL;
450c18ec02fSPetter Reinholdtsen 	/*
451c18ec02fSPetter Reinholdtsen 	 * Kontron OEM events are described in the product's user manual,  but are limited in favor of
452c18ec02fSPetter Reinholdtsen     * sensor specific
453c18ec02fSPetter Reinholdtsen 	 */
454c18ec02fSPetter Reinholdtsen 
455c18ec02fSPetter Reinholdtsen 	/* Only standard records are defined so far */
456c18ec02fSPetter Reinholdtsen 	if( rec->record_type < 0xC0 ){
457c18ec02fSPetter Reinholdtsen 		struct ipmi_event_sensor_types *st=NULL;
458c18ec02fSPetter Reinholdtsen 		for ( st=oem_kontron_event_reading_types ; st->type != NULL; st++){
459c18ec02fSPetter Reinholdtsen 			if (st->code == rec->sel_type.standard_type.event_type ){
460c18ec02fSPetter Reinholdtsen 				size_t len =strlen(st->desc);
461c18ec02fSPetter Reinholdtsen 				description = (char*)malloc( len + 1 );
462c18ec02fSPetter Reinholdtsen 				memcpy(description, st->desc , len);
463c18ec02fSPetter Reinholdtsen 				description[len] = 0;;
464c18ec02fSPetter Reinholdtsen 				return description;
465c18ec02fSPetter Reinholdtsen 			}
466c18ec02fSPetter Reinholdtsen 		}
467c18ec02fSPetter Reinholdtsen 	}
468c18ec02fSPetter Reinholdtsen 
469c18ec02fSPetter Reinholdtsen 	return NULL;
470c18ec02fSPetter Reinholdtsen }
471c18ec02fSPetter Reinholdtsen 
472c18ec02fSPetter Reinholdtsen char *
get_newisys_evt_desc(struct ipmi_intf * intf,struct sel_event_record * rec)473c18ec02fSPetter Reinholdtsen get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
474c18ec02fSPetter Reinholdtsen {
475c18ec02fSPetter Reinholdtsen 	/*
476c18ec02fSPetter Reinholdtsen 	 * Newisys OEM event descriptions can be retrieved through an
477c18ec02fSPetter Reinholdtsen 	 * OEM IPMI command.
478c18ec02fSPetter Reinholdtsen 	 */
479c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
480c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
481c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[6];
482c18ec02fSPetter Reinholdtsen 	char * description = NULL;
483c18ec02fSPetter Reinholdtsen 
484c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
485c18ec02fSPetter Reinholdtsen 	req.msg.netfn = 0x2E;
486c18ec02fSPetter Reinholdtsen 	req.msg.cmd   = 0x01;
487c18ec02fSPetter Reinholdtsen 	req.msg.data_len = sizeof(msg_data);
488c18ec02fSPetter Reinholdtsen 
489c18ec02fSPetter Reinholdtsen 	msg_data[0] = 0x15;	/* IANA LSB */
490c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0x24; /* IANA     */
491c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x00; /* IANA MSB */
492c18ec02fSPetter Reinholdtsen 	msg_data[3] = 0x01; /* Subcommand */
493c18ec02fSPetter Reinholdtsen 	msg_data[4] = rec->record_id & 0x00FF;        /* SEL Record ID LSB */
494c18ec02fSPetter Reinholdtsen 	msg_data[5] = (rec->record_id & 0xFF00) >> 8; /* SEL Record ID MSB */
495c18ec02fSPetter Reinholdtsen 
496c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
497c18ec02fSPetter Reinholdtsen 
498c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
499c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
500c18ec02fSPetter Reinholdtsen 		if (verbose)
501c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error issuing OEM command");
502c18ec02fSPetter Reinholdtsen 		return NULL;
503c18ec02fSPetter Reinholdtsen 	}
504c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
505c18ec02fSPetter Reinholdtsen 		if (verbose)
506c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "OEM command returned error code: %s",
507c18ec02fSPetter Reinholdtsen 					val2str(rsp->ccode, completion_code_vals));
508c18ec02fSPetter Reinholdtsen 		return NULL;
509c18ec02fSPetter Reinholdtsen 	}
510c18ec02fSPetter Reinholdtsen 
511c18ec02fSPetter Reinholdtsen 	/* Verify our response before we use it */
512c18ec02fSPetter Reinholdtsen 	if (rsp->data_len < 5)
513c18ec02fSPetter Reinholdtsen 	{
514c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Newisys OEM response too short");
515c18ec02fSPetter Reinholdtsen 		return NULL;
516c18ec02fSPetter Reinholdtsen 	}
517c18ec02fSPetter Reinholdtsen 	else if (rsp->data_len != (4 + rsp->data[3]))
518c18ec02fSPetter Reinholdtsen 	{
519c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Newisys OEM response has unexpected length");
520c18ec02fSPetter Reinholdtsen 		return NULL;
521c18ec02fSPetter Reinholdtsen 	}
522c18ec02fSPetter Reinholdtsen 	else if (IPM_DEV_MANUFACTURER_ID(rsp->data) != IPMI_OEM_NEWISYS)
523c18ec02fSPetter Reinholdtsen 	{
524c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Newisys OEM response has unexpected length");
525c18ec02fSPetter Reinholdtsen 		return NULL;
526c18ec02fSPetter Reinholdtsen 	}
527c18ec02fSPetter Reinholdtsen 
528c18ec02fSPetter Reinholdtsen 	description = (char*)malloc(rsp->data[3] + 1);
529c18ec02fSPetter Reinholdtsen 	memcpy(description, rsp->data + 4, rsp->data[3]);
530c18ec02fSPetter Reinholdtsen 	description[rsp->data[3]] = 0;;
531c18ec02fSPetter Reinholdtsen 
532c18ec02fSPetter Reinholdtsen 	return description;
533c18ec02fSPetter Reinholdtsen }
534c18ec02fSPetter Reinholdtsen 
535c18ec02fSPetter Reinholdtsen char *
get_supermicro_evt_desc(struct ipmi_intf * intf,struct sel_event_record * rec)536c18ec02fSPetter Reinholdtsen get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec)
537c18ec02fSPetter Reinholdtsen {
538c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
539c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
540c18ec02fSPetter Reinholdtsen 	char *desc = NULL;
541c18ec02fSPetter Reinholdtsen 	int chipset_type = 1;
542c18ec02fSPetter Reinholdtsen 	int data1;
543c18ec02fSPetter Reinholdtsen 	int data2;
544c18ec02fSPetter Reinholdtsen 	int data3;
545c18ec02fSPetter Reinholdtsen 	int sensor_type;
546c18ec02fSPetter Reinholdtsen 	uint8_t i = 0;
547c18ec02fSPetter Reinholdtsen 	uint16_t oem_id = 0;
548c18ec02fSPetter Reinholdtsen 	/* Get the OEM event Bytes of the SEL Records byte 13, 14, 15 to
549c18ec02fSPetter Reinholdtsen 	 * data1,data2,data3
550c18ec02fSPetter Reinholdtsen 	 */
551c18ec02fSPetter Reinholdtsen 	data1 = rec->sel_type.standard_type.event_data[0];
552c18ec02fSPetter Reinholdtsen 	data2 = rec->sel_type.standard_type.event_data[1];
553c18ec02fSPetter Reinholdtsen 	data3 = rec->sel_type.standard_type.event_data[2];
554c18ec02fSPetter Reinholdtsen 	/* Check for the Standard Event type == 0x6F */
555c18ec02fSPetter Reinholdtsen 	if (rec->sel_type.standard_type.event_type != 0x6F) {
556c18ec02fSPetter Reinholdtsen 		return NULL;
557c18ec02fSPetter Reinholdtsen 	}
558c18ec02fSPetter Reinholdtsen 	/* Allocate mem for te Description string */
559aabd9eb1SZdenek Styblik 	desc = malloc(sizeof(char) * SIZE_OF_DESC);
560c18ec02fSPetter Reinholdtsen 	if (desc == NULL) {
561c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "ipmitool: malloc failure");
562c18ec02fSPetter Reinholdtsen 		return NULL;
563c18ec02fSPetter Reinholdtsen 	}
564aabd9eb1SZdenek Styblik 	memset(desc, '\0', SIZE_OF_DESC);
565c18ec02fSPetter Reinholdtsen 	sensor_type = rec->sel_type.standard_type.sensor_type;
566c18ec02fSPetter Reinholdtsen 	switch (sensor_type) {
567c18ec02fSPetter Reinholdtsen 		case SENSOR_TYPE_MEMORY:
568c18ec02fSPetter Reinholdtsen 			memset(&req, 0, sizeof (req));
569c18ec02fSPetter Reinholdtsen 			req.msg.netfn = IPMI_NETFN_APP;
570c18ec02fSPetter Reinholdtsen 			req.msg.lun = 0;
571c18ec02fSPetter Reinholdtsen 			req.msg.cmd = BMC_GET_DEVICE_ID;
572c18ec02fSPetter Reinholdtsen 			req.msg.data = NULL;
573c18ec02fSPetter Reinholdtsen 			req.msg.data_len = 0;
574c18ec02fSPetter Reinholdtsen 
575c18ec02fSPetter Reinholdtsen 			rsp = intf->sendrecv(intf, &req);
576c18ec02fSPetter Reinholdtsen 			if (rsp == NULL) {
577c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, " Error getting system info");
578c18ec02fSPetter Reinholdtsen 				if (desc != NULL) {
579c18ec02fSPetter Reinholdtsen 					free(desc);
580c18ec02fSPetter Reinholdtsen 					desc = NULL;
581c18ec02fSPetter Reinholdtsen 				}
582c18ec02fSPetter Reinholdtsen 				return NULL;
583c18ec02fSPetter Reinholdtsen 			} else if (rsp->ccode > 0) {
584c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, " Error getting system info: %s",
585c18ec02fSPetter Reinholdtsen 						val2str(rsp->ccode, completion_code_vals));
586c18ec02fSPetter Reinholdtsen 				if (desc != NULL) {
587c18ec02fSPetter Reinholdtsen 					free(desc);
588c18ec02fSPetter Reinholdtsen 					desc = NULL;
589c18ec02fSPetter Reinholdtsen 				}
590c18ec02fSPetter Reinholdtsen 				return NULL;
591c18ec02fSPetter Reinholdtsen 			}
592c18ec02fSPetter Reinholdtsen 			/* check the chipset type */
593c18ec02fSPetter Reinholdtsen 			oem_id = ipmi_get_oem_id(intf);
594c18ec02fSPetter Reinholdtsen 			if (oem_id == 0) {
595e37e3ab7SZdenek Styblik 				if (desc != NULL) {
596e37e3ab7SZdenek Styblik 					free(desc);
597e37e3ab7SZdenek Styblik 					desc = NULL;
598e37e3ab7SZdenek Styblik 				}
599c18ec02fSPetter Reinholdtsen 				return NULL;
600c18ec02fSPetter Reinholdtsen 			}
601b6ec5072SZdenek Styblik 			for (i = 0; supermicro_X8[i] != 0xFFFF; i++) {
602c18ec02fSPetter Reinholdtsen 				if (oem_id == supermicro_X8[i]) {
603c18ec02fSPetter Reinholdtsen 					chipset_type = 0;
604c18ec02fSPetter Reinholdtsen 					break;
605c18ec02fSPetter Reinholdtsen 				}
606c18ec02fSPetter Reinholdtsen 			}
607b6ec5072SZdenek Styblik 			for (i = 0; supermicro_x9[i] != 0xFFFF; i++) {
608c18ec02fSPetter Reinholdtsen 				if (oem_id == supermicro_x9[i]) {
609c18ec02fSPetter Reinholdtsen 					chipset_type = 2;
610c18ec02fSPetter Reinholdtsen 					break;
611c18ec02fSPetter Reinholdtsen 				}
612c18ec02fSPetter Reinholdtsen 			}
613c18ec02fSPetter Reinholdtsen 			if (chipset_type == 0) {
614c18ec02fSPetter Reinholdtsen 				snprintf(desc, SIZE_OF_DESC, "@DIMM%2X(CPU%x)",
615c18ec02fSPetter Reinholdtsen 						data2,
616c18ec02fSPetter Reinholdtsen 						(data3 & 0x03) + 1);
617c18ec02fSPetter Reinholdtsen 			} else if (chipset_type == 1) {
618c18ec02fSPetter Reinholdtsen 				snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)",
619c18ec02fSPetter Reinholdtsen 						(data2 >> 4) + 0x40 + (data3 & 0x3) * 4,
620c18ec02fSPetter Reinholdtsen 						(data2 & 0xf) + 0x27, (data3 & 0x03) + 1);
621c18ec02fSPetter Reinholdtsen 			} else if (chipset_type == 2) {
622c18ec02fSPetter Reinholdtsen 				snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)",
623c18ec02fSPetter Reinholdtsen 						(data2 >> 4) + 0x40 + (data3 & 0x3) * 3,
624c18ec02fSPetter Reinholdtsen 						(data2 & 0xf) + 0x27, (data3 & 0x03) + 1);
625c18ec02fSPetter Reinholdtsen 			} else {
626aabd9eb1SZdenek Styblik 				/* No description. */
627aabd9eb1SZdenek Styblik 				desc[0] = '\0';
628c18ec02fSPetter Reinholdtsen 			}
629c18ec02fSPetter Reinholdtsen 			break;
630c18ec02fSPetter Reinholdtsen 		case SENSOR_TYPE_SUPERMICRO_OEM:
631c18ec02fSPetter Reinholdtsen 			if (data1 == 0x80 && data3 == 0xFF) {
632c18ec02fSPetter Reinholdtsen 				if (data2 == 0x0) {
633c18ec02fSPetter Reinholdtsen 					snprintf(desc, SIZE_OF_DESC, "BMC unexpected reset");
634c18ec02fSPetter Reinholdtsen 				} else if (data2 == 0x1) {
635c18ec02fSPetter Reinholdtsen 					snprintf(desc, SIZE_OF_DESC, "BMC cold reset");
636c18ec02fSPetter Reinholdtsen 				} else if (data2 == 0x2) {
637c18ec02fSPetter Reinholdtsen 					snprintf(desc, SIZE_OF_DESC, "BMC warm reset");
638c18ec02fSPetter Reinholdtsen 				}
639c18ec02fSPetter Reinholdtsen 			}
640c18ec02fSPetter Reinholdtsen 			break;
641c18ec02fSPetter Reinholdtsen 	}
642c18ec02fSPetter Reinholdtsen 	return desc;
643c18ec02fSPetter Reinholdtsen }
644c18ec02fSPetter Reinholdtsen 
645c18ec02fSPetter Reinholdtsen /*
646c18ec02fSPetter Reinholdtsen  * Function 	: Decoding the SEL OEM Bytes for the DELL Platforms.
647c18ec02fSPetter Reinholdtsen  * Description  : The below fucntion will decode the SEL Events OEM Bytes for the Dell specific	Sensors only.
648c18ec02fSPetter Reinholdtsen  * The below function will append the additional information Strings/description to the normal sel desc.
649c18ec02fSPetter Reinholdtsen  * With this the SEL will display additional information sent via OEM Bytes of the SEL Record.
650c18ec02fSPetter Reinholdtsen  * NOTE		: Specific to DELL Platforms only.
651c18ec02fSPetter Reinholdtsen  * Returns	: 	Pointer to the char string.
652c18ec02fSPetter Reinholdtsen  */
get_dell_evt_desc(struct ipmi_intf * intf,struct sel_event_record * rec)653c18ec02fSPetter Reinholdtsen char * get_dell_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
654c18ec02fSPetter Reinholdtsen {
655c18ec02fSPetter Reinholdtsen 	int data1, data2, data3;
656c18ec02fSPetter Reinholdtsen 	int sensor_type;
657c18ec02fSPetter Reinholdtsen 	char *desc = NULL;
658c18ec02fSPetter Reinholdtsen 
659c18ec02fSPetter Reinholdtsen 	unsigned char count;
660c18ec02fSPetter Reinholdtsen 	unsigned char node;
661c18ec02fSPetter Reinholdtsen 	unsigned char dimmNum;
662c18ec02fSPetter Reinholdtsen 	unsigned char dimmsPerNode;
663c18ec02fSPetter Reinholdtsen 	char          dimmStr[MAX_DIMM_STR];
664c18ec02fSPetter Reinholdtsen 	char          tmpdesc[SIZE_OF_DESC];
665c18ec02fSPetter Reinholdtsen 	char*         str;
666c18ec02fSPetter Reinholdtsen 	unsigned char incr = 0;
667c18ec02fSPetter Reinholdtsen 	unsigned char i=0,j = 0;
668c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
669c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
670c18ec02fSPetter Reinholdtsen 	char tmpData;
671c18ec02fSPetter Reinholdtsen 	int version;
672c18ec02fSPetter Reinholdtsen 	/* Get the OEM event Bytes of the SEL Records byte 13, 14, 15 to Data1,data2,data3 */
673c18ec02fSPetter Reinholdtsen 	data1 = rec->sel_type.standard_type.event_data[0];
674c18ec02fSPetter Reinholdtsen 	data2 = rec->sel_type.standard_type.event_data[1];
675c18ec02fSPetter Reinholdtsen 	data3 = rec->sel_type.standard_type.event_data[2];
676c18ec02fSPetter Reinholdtsen 	/* Check for the Standard Event type == 0x6F */
677c18ec02fSPetter Reinholdtsen 	if (0x6F == rec->sel_type.standard_type.event_type)
678c18ec02fSPetter Reinholdtsen 		{
679c18ec02fSPetter Reinholdtsen 		sensor_type = rec->sel_type.standard_type.sensor_type;
680c18ec02fSPetter Reinholdtsen 		/* Allocate mem for te Description string */
681c18ec02fSPetter Reinholdtsen 		desc = (char*)malloc(SIZE_OF_DESC);
682c18ec02fSPetter Reinholdtsen 		if(NULL == desc)
683c18ec02fSPetter Reinholdtsen 			return NULL;
684c18ec02fSPetter Reinholdtsen 		memset(desc,0,SIZE_OF_DESC);
685c18ec02fSPetter Reinholdtsen 		memset(tmpdesc,0,SIZE_OF_DESC);
686c18ec02fSPetter Reinholdtsen 		switch (sensor_type) {
687c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_PROCESSOR:	/* Processor/CPU related OEM Sel Byte Decoding for DELL Platforms only */
688c18ec02fSPetter Reinholdtsen 				if((OEM_CODE_IN_BYTE2 == (data1 & DATA_BYTE2_SPECIFIED_MASK)))
689c18ec02fSPetter Reinholdtsen 				{
690c18ec02fSPetter Reinholdtsen 					if(0x00 == (data1 & MASK_LOWER_NIBBLE))
691c18ec02fSPetter Reinholdtsen 						snprintf(desc,SIZE_OF_DESC,"CPU Internal Err | ");
692c18ec02fSPetter Reinholdtsen 					if(0x06 == (data1 & MASK_LOWER_NIBBLE))
693c18ec02fSPetter Reinholdtsen 					{
694c18ec02fSPetter Reinholdtsen 						snprintf(desc,SIZE_OF_DESC,"CPU Protocol Err | ");
695c18ec02fSPetter Reinholdtsen 
696c18ec02fSPetter Reinholdtsen 					}
697c18ec02fSPetter Reinholdtsen 
698c18ec02fSPetter Reinholdtsen 					/* change bit location to a number */
699c18ec02fSPetter Reinholdtsen 					for (count= 0; count < 8; count++)
700c18ec02fSPetter Reinholdtsen 					{
701c18ec02fSPetter Reinholdtsen 					  if (BIT(count)& data2)
702c18ec02fSPetter Reinholdtsen 					  {
703c18ec02fSPetter Reinholdtsen 					    count++;
704c18ec02fSPetter Reinholdtsen 						/* 0x0A - CPU sensor number */
705c18ec02fSPetter Reinholdtsen 						if((0x06 == (data1 & MASK_LOWER_NIBBLE)) && (0x0A == rec->sel_type.standard_type.sensor_num))
706c18ec02fSPetter Reinholdtsen 						    snprintf(desc,SIZE_OF_DESC,"FSB %d ",count);			// Which CPU Has generated the FSB
707c18ec02fSPetter Reinholdtsen 						else
708c18ec02fSPetter Reinholdtsen 						    snprintf(desc,SIZE_OF_DESC,"CPU %d | APIC ID %d ",count,data3);	/* Specific CPU related info */
709c18ec02fSPetter Reinholdtsen 					    break;
710c18ec02fSPetter Reinholdtsen 					  }
711c18ec02fSPetter Reinholdtsen 					}
712c18ec02fSPetter Reinholdtsen 				}
713c18ec02fSPetter Reinholdtsen 			break;
714c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_MEMORY:	/* Memory or DIMM related OEM Sel Byte Decoding for DELL Platforms only */
715c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_EVT_LOG:	/* Events Logging for Memory or DIMM related OEM Sel Byte Decoding for DELL Platforms only */
716c18ec02fSPetter Reinholdtsen 
717c18ec02fSPetter Reinholdtsen 				/* Get the current version of the IPMI Spec Based on that Decoding of memory info is done.*/
718c18ec02fSPetter Reinholdtsen 				memset(&req, 0, sizeof (req));
719c18ec02fSPetter Reinholdtsen 				req.msg.netfn = IPMI_NETFN_APP;
720c18ec02fSPetter Reinholdtsen 				req.msg.lun = 0;
721c18ec02fSPetter Reinholdtsen 				req.msg.cmd = BMC_GET_DEVICE_ID;
722c18ec02fSPetter Reinholdtsen 				req.msg.data = NULL;
723c18ec02fSPetter Reinholdtsen 				req.msg.data_len = 0;
724c18ec02fSPetter Reinholdtsen 
725c18ec02fSPetter Reinholdtsen 				rsp = intf->sendrecv(intf, &req);
726c18ec02fSPetter Reinholdtsen 				if (NULL == rsp)
727c18ec02fSPetter Reinholdtsen 				{
728c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, " Error getting system info");
729c18ec02fSPetter Reinholdtsen 					if (desc != NULL) {
730c18ec02fSPetter Reinholdtsen 						free(desc);
731c18ec02fSPetter Reinholdtsen 						desc = NULL;
732c18ec02fSPetter Reinholdtsen 					}
733c18ec02fSPetter Reinholdtsen 					return NULL;
734c18ec02fSPetter Reinholdtsen 				}
735c18ec02fSPetter Reinholdtsen 				else if (rsp->ccode > 0)
736c18ec02fSPetter Reinholdtsen 				{
737c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, " Error getting system info: %s",
738c18ec02fSPetter Reinholdtsen 						val2str(rsp->ccode, completion_code_vals));
739c18ec02fSPetter Reinholdtsen 					if (desc != NULL) {
740c18ec02fSPetter Reinholdtsen 						free(desc);
741c18ec02fSPetter Reinholdtsen 						desc = NULL;
742c18ec02fSPetter Reinholdtsen 					}
743c18ec02fSPetter Reinholdtsen 					return NULL;
744c18ec02fSPetter Reinholdtsen 				}
745c18ec02fSPetter Reinholdtsen 				version = rsp->data[4];
746c18ec02fSPetter Reinholdtsen 				/* Memory DIMMS */
747c18ec02fSPetter Reinholdtsen 				if( (data1 &  OEM_CODE_IN_BYTE2) || (data1 & OEM_CODE_IN_BYTE3 ) )
748c18ec02fSPetter Reinholdtsen 				{
749c18ec02fSPetter Reinholdtsen 					/* Memory Redundancy related oem bytes docoding .. */
750c18ec02fSPetter Reinholdtsen 					if( (SENSOR_TYPE_MEMORY == sensor_type) && (0x0B == rec->sel_type.standard_type.event_type) )
751c18ec02fSPetter Reinholdtsen 					{
752c18ec02fSPetter Reinholdtsen 						if(0x00 == (data1 & MASK_LOWER_NIBBLE))
753c18ec02fSPetter Reinholdtsen 						{
754c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC," Redundancy Regained | ");
755c18ec02fSPetter Reinholdtsen 						}
756c18ec02fSPetter Reinholdtsen 						else if(0x01 == (data1 & MASK_LOWER_NIBBLE))
757c18ec02fSPetter Reinholdtsen 						{
758c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"Redundancy Lost | ");
759c18ec02fSPetter Reinholdtsen 						}
760c18ec02fSPetter Reinholdtsen 					} /* Correctable and uncorrectable ECC Error Decoding */
761c18ec02fSPetter Reinholdtsen 					else if(SENSOR_TYPE_MEMORY == sensor_type)
762c18ec02fSPetter Reinholdtsen 					{
763c18ec02fSPetter Reinholdtsen 						if(0x00 == (data1 & MASK_LOWER_NIBBLE))
764c18ec02fSPetter Reinholdtsen 						{
765c18ec02fSPetter Reinholdtsen 							/* 0x1C - Memory Sensor Number */
766c18ec02fSPetter Reinholdtsen 							if(0x1C == rec->sel_type.standard_type.sensor_num)
767c18ec02fSPetter Reinholdtsen 							{
768c18ec02fSPetter Reinholdtsen 								/*Add the complete information about the Memory Configs.*/
769c18ec02fSPetter Reinholdtsen 								if((data1 &  OEM_CODE_IN_BYTE2) && (data1 & OEM_CODE_IN_BYTE3 ))
770c18ec02fSPetter Reinholdtsen 								{
771c18ec02fSPetter Reinholdtsen 									count = 0;
772c18ec02fSPetter Reinholdtsen 									snprintf(desc,SIZE_OF_DESC,"CRC Error on:");
773c18ec02fSPetter Reinholdtsen 									for(i=0;i<4;i++)
774c18ec02fSPetter Reinholdtsen 									{
775c18ec02fSPetter Reinholdtsen 										if((BIT(i))&(data2))
776c18ec02fSPetter Reinholdtsen 										{
777c18ec02fSPetter Reinholdtsen 											if(count)
778c18ec02fSPetter Reinholdtsen 											{
779c18ec02fSPetter Reinholdtsen 						                        str = desc+strlen(desc);
780c18ec02fSPetter Reinholdtsen 												*str++ = ',';
781c18ec02fSPetter Reinholdtsen 												str = '\0';
782c18ec02fSPetter Reinholdtsen 						              					count = 0;
783c18ec02fSPetter Reinholdtsen 											}
784c18ec02fSPetter Reinholdtsen 											switch(i) /* Which type of memory config is present.. */
785c18ec02fSPetter Reinholdtsen 											{
786c18ec02fSPetter Reinholdtsen 												case 0: snprintf(tmpdesc,SIZE_OF_DESC,"South Bound Memory");
787c18ec02fSPetter Reinholdtsen 														strcat(desc,tmpdesc);
788c18ec02fSPetter Reinholdtsen 														count++;
789c18ec02fSPetter Reinholdtsen 														break;
790c18ec02fSPetter Reinholdtsen 												case 1:	snprintf(tmpdesc,SIZE_OF_DESC,"South Bound Config");
791c18ec02fSPetter Reinholdtsen 														strcat(desc,tmpdesc);
792c18ec02fSPetter Reinholdtsen 														count++;
793c18ec02fSPetter Reinholdtsen 														break;
794c18ec02fSPetter Reinholdtsen 												case 2: snprintf(tmpdesc,SIZE_OF_DESC,"North Bound memory");
795c18ec02fSPetter Reinholdtsen 														strcat(desc,tmpdesc);
796c18ec02fSPetter Reinholdtsen 														count++;
797c18ec02fSPetter Reinholdtsen 														break;
798c18ec02fSPetter Reinholdtsen 												case 3:	snprintf(tmpdesc,SIZE_OF_DESC,"North Bound memory-corr");
799c18ec02fSPetter Reinholdtsen 														strcat(desc,tmpdesc);
800c18ec02fSPetter Reinholdtsen 														count++;
801c18ec02fSPetter Reinholdtsen 														break;
802c18ec02fSPetter Reinholdtsen 												default:
803c18ec02fSPetter Reinholdtsen 														break;
804c18ec02fSPetter Reinholdtsen 											}
805c18ec02fSPetter Reinholdtsen 										}
806c18ec02fSPetter Reinholdtsen 									}
807c18ec02fSPetter Reinholdtsen 									if(data3>=0x00 && data3<0xFF)
808c18ec02fSPetter Reinholdtsen 									{
809c18ec02fSPetter Reinholdtsen 										snprintf(tmpdesc,SIZE_OF_DESC,"|Failing_Channel:%d",data3);
810c18ec02fSPetter Reinholdtsen 										strcat(desc,tmpdesc);
811c18ec02fSPetter Reinholdtsen 									}
812c18ec02fSPetter Reinholdtsen 								}
813c18ec02fSPetter Reinholdtsen 								break;
814c18ec02fSPetter Reinholdtsen 							}
815c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"Correctable ECC | ");
816c18ec02fSPetter Reinholdtsen 						}
817c18ec02fSPetter Reinholdtsen 						else if(0x01 == (data1 & MASK_LOWER_NIBBLE))
818c18ec02fSPetter Reinholdtsen 						{
819c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"UnCorrectable ECC | ");
820c18ec02fSPetter Reinholdtsen 						}
821c18ec02fSPetter Reinholdtsen 					} /* Corr Memory log disabled */
822c18ec02fSPetter Reinholdtsen 					else if(SENSOR_TYPE_EVT_LOG == sensor_type)
823c18ec02fSPetter Reinholdtsen 					{
824c18ec02fSPetter Reinholdtsen 						if(0x00 == (data1 & MASK_LOWER_NIBBLE))
825c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"Corr Memory Log Disabled | ");
826c18ec02fSPetter Reinholdtsen 					}
827c18ec02fSPetter Reinholdtsen 				}
828c18ec02fSPetter Reinholdtsen 				else
829c18ec02fSPetter Reinholdtsen 				{
830c18ec02fSPetter Reinholdtsen 					if(SENSOR_TYPE_SYS_EVENT == sensor_type)
831c18ec02fSPetter Reinholdtsen 					{
832c18ec02fSPetter Reinholdtsen 						if(0x02 == (data1 & MASK_LOWER_NIBBLE))
833c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"Unknown System Hardware Failure ");
834c18ec02fSPetter Reinholdtsen 					}
835c18ec02fSPetter Reinholdtsen 					if(SENSOR_TYPE_EVT_LOG == sensor_type)
836c18ec02fSPetter Reinholdtsen 					{
837c18ec02fSPetter Reinholdtsen 						if(0x03 == (data1 & MASK_LOWER_NIBBLE))
838c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"All Even Logging Dissabled");
839c18ec02fSPetter Reinholdtsen 					}
840c18ec02fSPetter Reinholdtsen 				}
841c18ec02fSPetter Reinholdtsen 				/*
842c18ec02fSPetter Reinholdtsen  				 * Based on the above error, we need to find whcih memory slot or
843c18ec02fSPetter Reinholdtsen  				 * Card has got the Errors/Sel Generated.
844c18ec02fSPetter Reinholdtsen  				 */
845c18ec02fSPetter Reinholdtsen 				if(data1 & OEM_CODE_IN_BYTE2 )
846c18ec02fSPetter Reinholdtsen 				{
847c18ec02fSPetter Reinholdtsen 					/* Find the Card Type */
848c18ec02fSPetter Reinholdtsen 					if((0x0F != (data2 >> 4)) && ((data2 >> 4) < 0x08))
849c18ec02fSPetter Reinholdtsen 					{
850c18ec02fSPetter Reinholdtsen 						tmpData = 	('A'+ (data2 >> 4));
851c18ec02fSPetter Reinholdtsen 						if( (SENSOR_TYPE_MEMORY == sensor_type) && (0x0B == rec->sel_type.standard_type.event_type) )
852c18ec02fSPetter Reinholdtsen 						{
853c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc, SIZE_OF_DESC, "Bad Card %c", tmpData);
854c18ec02fSPetter Reinholdtsen 						}
855c18ec02fSPetter Reinholdtsen 						else
856c18ec02fSPetter Reinholdtsen 						{
857c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc, SIZE_OF_DESC, "Card %c", tmpData);
858c18ec02fSPetter Reinholdtsen 						}
859c18ec02fSPetter Reinholdtsen 						strcat(desc, tmpdesc);
860c18ec02fSPetter Reinholdtsen 					} /* Find the Bank Number of the DIMM */
861c18ec02fSPetter Reinholdtsen 					if (0x0F != (data2 & MASK_LOWER_NIBBLE))
862c18ec02fSPetter Reinholdtsen 					{
863c18ec02fSPetter Reinholdtsen 						if(0x51  == version)
864c18ec02fSPetter Reinholdtsen 						{
865c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc, SIZE_OF_DESC, "Bank %d", ((data2 & 0x0F)+1));
866c18ec02fSPetter Reinholdtsen 							strcat(desc, tmpdesc);
867c18ec02fSPetter Reinholdtsen 						}
868c18ec02fSPetter Reinholdtsen 						else
869c18ec02fSPetter Reinholdtsen 						{
870c18ec02fSPetter Reinholdtsen 							incr = (data2 & 0x0f) << 3;
871c18ec02fSPetter Reinholdtsen 						}
872c18ec02fSPetter Reinholdtsen 					}
873c18ec02fSPetter Reinholdtsen 
874c18ec02fSPetter Reinholdtsen 				}
875c18ec02fSPetter Reinholdtsen 				/* Find the DIMM Number of the Memory which has Generated the Fault or Sel */
876c18ec02fSPetter Reinholdtsen 				if(data1 & OEM_CODE_IN_BYTE3 )
877c18ec02fSPetter Reinholdtsen 				{
878c18ec02fSPetter Reinholdtsen 					// Based on the IPMI Spec Need Identify the DIMM Details.
879c18ec02fSPetter Reinholdtsen 					// For the SPEC 1.5 Only the DIMM Number is Valid.
880c18ec02fSPetter Reinholdtsen 					if(0x51  == version)
881c18ec02fSPetter Reinholdtsen 					{
882c18ec02fSPetter Reinholdtsen 						snprintf(tmpdesc, SIZE_OF_DESC, "DIMM %c", ('A'+ data3));
883c18ec02fSPetter Reinholdtsen 						strcat(desc, tmpdesc);
884c18ec02fSPetter Reinholdtsen 					}
885c18ec02fSPetter Reinholdtsen 					/* For the SPEC 2.0 Decode the DIMM Number as it supports more.*/
886c18ec02fSPetter Reinholdtsen 					else if( ((data2 >> 4) > 0x07) && (0x0F != (data2 >> 4) ))
887c18ec02fSPetter Reinholdtsen 					{
888c18ec02fSPetter Reinholdtsen 						strcpy(dimmStr, " DIMM");
889c18ec02fSPetter Reinholdtsen 						str = desc+strlen(desc);
890c18ec02fSPetter Reinholdtsen 						dimmsPerNode = 4;
891c18ec02fSPetter Reinholdtsen 						if(0x09 == (data2 >> 4)) dimmsPerNode = 6;
892c18ec02fSPetter Reinholdtsen 						else if(0x0A == (data2 >> 4)) dimmsPerNode = 8;
893c18ec02fSPetter Reinholdtsen 						else if(0x0B == (data2 >> 4)) dimmsPerNode = 9;
894c18ec02fSPetter Reinholdtsen 						else if(0x0C == (data2 >> 4)) dimmsPerNode = 12;
895c18ec02fSPetter Reinholdtsen 						else if(0x0D == (data2 >> 4)) dimmsPerNode = 24;
896c18ec02fSPetter Reinholdtsen 						else if(0x0E == (data2 >> 4)) dimmsPerNode = 3;
897c18ec02fSPetter Reinholdtsen 						count = 0;
898c18ec02fSPetter Reinholdtsen 				        	for (i = 0; i < 8; i++)
899c18ec02fSPetter Reinholdtsen 				        	{
900c18ec02fSPetter Reinholdtsen 				        		if (BIT(i) & data3)
901c18ec02fSPetter Reinholdtsen 				          		{
902c18ec02fSPetter Reinholdtsen 								if(count)
903c18ec02fSPetter Reinholdtsen 								{
904c18ec02fSPetter Reinholdtsen 									strcat(str,",");
905c18ec02fSPetter Reinholdtsen 									count = 0x00;
906c18ec02fSPetter Reinholdtsen 								}
907c18ec02fSPetter Reinholdtsen 				            		node = (incr + i)/dimmsPerNode;
908c18ec02fSPetter Reinholdtsen 					            	dimmNum = ((incr + i)%dimmsPerNode)+1;
909c18ec02fSPetter Reinholdtsen 					            	dimmStr[5] = node + 'A';
910c18ec02fSPetter Reinholdtsen 					            	sprintf(tmpdesc,"%d",dimmNum);
911c18ec02fSPetter Reinholdtsen 					            	for(j = 0; j < strlen(tmpdesc);j++)
912c18ec02fSPetter Reinholdtsen 								dimmStr[6+j] = tmpdesc[j];
913c18ec02fSPetter Reinholdtsen 							dimmStr[6+j] = '\0';
914c18ec02fSPetter Reinholdtsen 							strcat(str,dimmStr); // final DIMM Details.
915c18ec02fSPetter Reinholdtsen 		 			               	count++;
916c18ec02fSPetter Reinholdtsen 					          	}
917c18ec02fSPetter Reinholdtsen 					        }
918c18ec02fSPetter Reinholdtsen 					}
919c18ec02fSPetter Reinholdtsen 					else
920c18ec02fSPetter Reinholdtsen 					{
921c18ec02fSPetter Reinholdtsen 					        strcpy(dimmStr, " DIMM");
922c18ec02fSPetter Reinholdtsen 						str = desc+strlen(desc);
923c18ec02fSPetter Reinholdtsen 					        count = 0;
924c18ec02fSPetter Reinholdtsen 					        for (i = 0; i < 8; i++)
925c18ec02fSPetter Reinholdtsen 					        {
926c18ec02fSPetter Reinholdtsen 				        		if (BIT(i) & data3)
927c18ec02fSPetter Reinholdtsen 				   			{
928c18ec02fSPetter Reinholdtsen 						            // check if more than one DIMM, if so add a comma to the string.
929c18ec02fSPetter Reinholdtsen 						        	sprintf(tmpdesc,"%d",(i + incr + 1));
930c18ec02fSPetter Reinholdtsen 								if(count)
931c18ec02fSPetter Reinholdtsen 								{
932c18ec02fSPetter Reinholdtsen 									strcat(str,",");
933c18ec02fSPetter Reinholdtsen 									count = 0x00;
934c18ec02fSPetter Reinholdtsen 								}
935c18ec02fSPetter Reinholdtsen 								for(j = 0; j < strlen(tmpdesc);j++)
936c18ec02fSPetter Reinholdtsen 									dimmStr[5+j] = tmpdesc[j];
937c18ec02fSPetter Reinholdtsen 								dimmStr[5+j] = '\0';
938c18ec02fSPetter Reinholdtsen 							        strcat(str, dimmStr);
939c18ec02fSPetter Reinholdtsen 							        count++;
940c18ec02fSPetter Reinholdtsen 				          		}
941c18ec02fSPetter Reinholdtsen 				        	}
942c18ec02fSPetter Reinholdtsen 			        	}
943c18ec02fSPetter Reinholdtsen 				}
944c18ec02fSPetter Reinholdtsen 			break;
945c18ec02fSPetter Reinholdtsen 			/* Sensor In system charectorization Error Decoding.
946c18ec02fSPetter Reinholdtsen 				Sensor type  0x20*/
947c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_TXT_CMD_ERROR:
948c18ec02fSPetter Reinholdtsen 				if((0x00 == (data1 & MASK_LOWER_NIBBLE))&&((data1 & OEM_CODE_IN_BYTE2) && (data1 & OEM_CODE_IN_BYTE3)))
949c18ec02fSPetter Reinholdtsen 				{
950c18ec02fSPetter Reinholdtsen 					switch(data3)
951c18ec02fSPetter Reinholdtsen 					{
952c18ec02fSPetter Reinholdtsen 						case 0x01:
953c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"BIOS TXT Error");
954c18ec02fSPetter Reinholdtsen 							break;
955c18ec02fSPetter Reinholdtsen 						case 0x02:
956c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"Processor/FIT TXT");
957c18ec02fSPetter Reinholdtsen 							break;
958c18ec02fSPetter Reinholdtsen 						case 0x03:
959c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"BIOS ACM TXT Error");
960c18ec02fSPetter Reinholdtsen 							break;
961c18ec02fSPetter Reinholdtsen 						case 0x04:
962c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"SINIT ACM TXT Error");
963c18ec02fSPetter Reinholdtsen 							break;
964c18ec02fSPetter Reinholdtsen 						case 0xff:
965c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC,"Unrecognized TT Error12");
966c18ec02fSPetter Reinholdtsen 							break;
967c18ec02fSPetter Reinholdtsen 						default:
968c18ec02fSPetter Reinholdtsen 							break;
969c18ec02fSPetter Reinholdtsen 					}
970c18ec02fSPetter Reinholdtsen 				}
971c18ec02fSPetter Reinholdtsen 			break;
972c18ec02fSPetter Reinholdtsen 			/* OS Watch Dog Timer Sel Events */
973c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_WTDOG:
974c18ec02fSPetter Reinholdtsen 
975c18ec02fSPetter Reinholdtsen 				if(SENSOR_TYPE_OEM_SEC_EVENT == data1)
976c18ec02fSPetter Reinholdtsen 				{
977c18ec02fSPetter Reinholdtsen 					if(0x04 == data2)
978c18ec02fSPetter Reinholdtsen 					{
979c18ec02fSPetter Reinholdtsen 						snprintf(desc,SIZE_OF_DESC,"Hard Reset|Interrupt type None,SMS/OS Timer used at expiration");
980c18ec02fSPetter Reinholdtsen 					}
981c18ec02fSPetter Reinholdtsen 				}
982c18ec02fSPetter Reinholdtsen 
983c18ec02fSPetter Reinholdtsen 			break;
984c18ec02fSPetter Reinholdtsen 						/* This Event is for BMC to Othe Hardware or CPU . */
985c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_VER_CHANGE:
986c18ec02fSPetter Reinholdtsen 				if((0x02 == (data1 & MASK_LOWER_NIBBLE))&&((data1 & OEM_CODE_IN_BYTE2) && (data1 & OEM_CODE_IN_BYTE3)))
987c18ec02fSPetter Reinholdtsen 				{
988c18ec02fSPetter Reinholdtsen 					if(0x02 == data2)
989c18ec02fSPetter Reinholdtsen 					{
990c18ec02fSPetter Reinholdtsen 						if(0x00 == data3)
991c18ec02fSPetter Reinholdtsen 						{
992c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "between BMC/iDRAC Firmware and other hardware");
993c18ec02fSPetter Reinholdtsen 						}
994c18ec02fSPetter Reinholdtsen 						else if(0x01 == data3)
995c18ec02fSPetter Reinholdtsen 						{
996c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "between BMC/iDRAC Firmware and CPU");
997c18ec02fSPetter Reinholdtsen 						}
998c18ec02fSPetter Reinholdtsen 					}
999c18ec02fSPetter Reinholdtsen 				}
1000c18ec02fSPetter Reinholdtsen 			break;
1001c18ec02fSPetter Reinholdtsen 			/* Flex or Mac tuning OEM Decoding for the DELL. */
1002c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_OEM_SEC_EVENT:
1003c18ec02fSPetter Reinholdtsen 				/* 0x25 - Virtual MAC sensory number - Dell OEM */
1004c18ec02fSPetter Reinholdtsen 				if(0x25 == rec->sel_type.standard_type.sensor_num)
1005c18ec02fSPetter Reinholdtsen 				{
1006c18ec02fSPetter Reinholdtsen 					if(0x01 == (data1 & MASK_LOWER_NIBBLE))
1007c18ec02fSPetter Reinholdtsen 					{
1008c18ec02fSPetter Reinholdtsen 						snprintf(desc, SIZE_OF_DESC, "Failed to program Virtual Mac Address");
1009c18ec02fSPetter Reinholdtsen 						if((data1 & OEM_CODE_IN_BYTE2)&&(data1 & OEM_CODE_IN_BYTE3))
1010c18ec02fSPetter Reinholdtsen 						{
1011c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc, SIZE_OF_DESC, " at bus:%.2x device:%.2x function:%x",
1012c18ec02fSPetter Reinholdtsen 							data3 &0x7F, (data2 >> 3) & 0x1F,
1013c18ec02fSPetter Reinholdtsen 							data2 & 0x07);
1014c18ec02fSPetter Reinholdtsen                             strcat(desc,tmpdesc);
1015c18ec02fSPetter Reinholdtsen 						}
1016c18ec02fSPetter Reinholdtsen 					}
1017c18ec02fSPetter Reinholdtsen 					else if(0x02 == (data1 & MASK_LOWER_NIBBLE))
1018c18ec02fSPetter Reinholdtsen 					{
1019c18ec02fSPetter Reinholdtsen 						snprintf(desc, SIZE_OF_DESC, "Device option ROM failed to support link tuning or flex address");
1020c18ec02fSPetter Reinholdtsen 					}
1021c18ec02fSPetter Reinholdtsen 					else if(0x03 == (data1 & MASK_LOWER_NIBBLE))
1022c18ec02fSPetter Reinholdtsen 					{
1023c18ec02fSPetter Reinholdtsen 						snprintf(desc, SIZE_OF_DESC, "Failed to get link tuning or flex address data from BMC/iDRAC");
1024c18ec02fSPetter Reinholdtsen 					}
1025c18ec02fSPetter Reinholdtsen 				}
1026c18ec02fSPetter Reinholdtsen 			break;
1027c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_CRIT_INTR:
1028c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_OEM_NFATAL_ERROR:	/* Non - Fatal PCIe Express Error Decoding */
1029c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_OEM_FATAL_ERROR:	/* Fatal IO Error Decoding */
1030c18ec02fSPetter Reinholdtsen 				/* 0x29 - QPI Linx Error Sensor Dell OEM */
1031c18ec02fSPetter Reinholdtsen 				if(0x29 == rec->sel_type.standard_type.sensor_num)
1032c18ec02fSPetter Reinholdtsen 				{
1033c18ec02fSPetter Reinholdtsen 					if((0x02 == (data1 & MASK_LOWER_NIBBLE))&&((data1 & OEM_CODE_IN_BYTE2) && (data1 & OEM_CODE_IN_BYTE3)))
1034c18ec02fSPetter Reinholdtsen 					{
1035c18ec02fSPetter Reinholdtsen 						snprintf(tmpdesc, SIZE_OF_DESC, "Partner-(LinkId:%d,AgentId:%d)|",(data2 & 0xC0),(data2 & 0x30));
1036c18ec02fSPetter Reinholdtsen 						strcat(desc,tmpdesc);
1037c18ec02fSPetter Reinholdtsen 						snprintf(tmpdesc, SIZE_OF_DESC, "ReportingAgent(LinkId:%d,AgentId:%d)|",(data2 & 0x0C),(data2 & 0x03));
1038c18ec02fSPetter Reinholdtsen 						strcat(desc,tmpdesc);
1039c18ec02fSPetter Reinholdtsen 						if(0x00 == (data3 & 0xFC))
1040c18ec02fSPetter Reinholdtsen 						{
1041c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc, SIZE_OF_DESC, "LinkWidthDegraded|");
1042c18ec02fSPetter Reinholdtsen 							strcat(desc,tmpdesc);
1043c18ec02fSPetter Reinholdtsen 						}
1044c18ec02fSPetter Reinholdtsen 						if(BIT(1)& data3)
1045c18ec02fSPetter Reinholdtsen 						{
1046c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc,SIZE_OF_DESC,"PA_Type:IOH|");
1047c18ec02fSPetter Reinholdtsen 						}
1048c18ec02fSPetter Reinholdtsen 						else
1049c18ec02fSPetter Reinholdtsen 						{
1050c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc,SIZE_OF_DESC,"PA-Type:CPU|");
1051c18ec02fSPetter Reinholdtsen 						}
1052c18ec02fSPetter Reinholdtsen 						strcat(desc,tmpdesc);
1053c18ec02fSPetter Reinholdtsen 						if(BIT(0)& data3)
1054c18ec02fSPetter Reinholdtsen 						{
1055c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc,SIZE_OF_DESC,"RA-Type:IOH");
1056c18ec02fSPetter Reinholdtsen 						}
1057c18ec02fSPetter Reinholdtsen 						else
1058c18ec02fSPetter Reinholdtsen 						{
1059c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc,SIZE_OF_DESC,"RA-Type:CPU");
1060c18ec02fSPetter Reinholdtsen 						}
1061c18ec02fSPetter Reinholdtsen 						strcat(desc,tmpdesc);
1062c18ec02fSPetter Reinholdtsen 					}
1063c18ec02fSPetter Reinholdtsen 				}
1064c18ec02fSPetter Reinholdtsen 				else
1065c18ec02fSPetter Reinholdtsen 				{
1066c18ec02fSPetter Reinholdtsen 
1067c18ec02fSPetter Reinholdtsen 					if(0x02 == (data1 & MASK_LOWER_NIBBLE))
1068c18ec02fSPetter Reinholdtsen 					{
1069c18ec02fSPetter Reinholdtsen 						sprintf(desc,"%s","IO channel Check NMI");
1070c18ec02fSPetter Reinholdtsen                     }
1071c18ec02fSPetter Reinholdtsen 					else
1072c18ec02fSPetter Reinholdtsen 					{
1073c18ec02fSPetter Reinholdtsen 						if(0x00 == (data1 & MASK_LOWER_NIBBLE))
1074c18ec02fSPetter Reinholdtsen 						{
1075c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "%s","PCIe Error |");
1076c18ec02fSPetter Reinholdtsen 						}
1077c18ec02fSPetter Reinholdtsen 						else if(0x01 == (data1 & MASK_LOWER_NIBBLE))
1078c18ec02fSPetter Reinholdtsen 						{
1079c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "%s","I/O Error |");
1080c18ec02fSPetter Reinholdtsen 						}
1081c18ec02fSPetter Reinholdtsen 						else if(0x04 == (data1 & MASK_LOWER_NIBBLE))
1082c18ec02fSPetter Reinholdtsen 						{
1083c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "%s","PCI PERR |");
1084c18ec02fSPetter Reinholdtsen 						}
1085c18ec02fSPetter Reinholdtsen 						else if(0x05 == (data1 & MASK_LOWER_NIBBLE))
1086c18ec02fSPetter Reinholdtsen 						{
1087c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "%s","PCI SERR |");
1088c18ec02fSPetter Reinholdtsen 						}
1089c18ec02fSPetter Reinholdtsen 						else
1090c18ec02fSPetter Reinholdtsen 						{
1091c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "%s"," ");
1092c18ec02fSPetter Reinholdtsen 						}
1093c18ec02fSPetter Reinholdtsen 						if (data3 & 0x80)
1094c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc, SIZE_OF_DESC, "Slot %d", data3 & 0x7F);
1095c18ec02fSPetter Reinholdtsen 						else
1096c18ec02fSPetter Reinholdtsen 							snprintf(tmpdesc, SIZE_OF_DESC, "PCI bus:%.2x device:%.2x function:%x",
1097c18ec02fSPetter Reinholdtsen 							data3 &0x7F, (data2 >> 3) & 0x1F,
1098c18ec02fSPetter Reinholdtsen 							data2 & 0x07);
1099c18ec02fSPetter Reinholdtsen 
1100c18ec02fSPetter Reinholdtsen 						strcat(desc,tmpdesc);
1101c18ec02fSPetter Reinholdtsen 					}
1102c18ec02fSPetter Reinholdtsen 				}
1103c18ec02fSPetter Reinholdtsen 			break;
1104c18ec02fSPetter Reinholdtsen 			/* POST Fatal Errors generated from the  Server with much more info*/
1105c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_FRM_PROG:
1106c18ec02fSPetter Reinholdtsen 				if((0x0F == (data1 & MASK_LOWER_NIBBLE))&&(data1 & OEM_CODE_IN_BYTE2))
1107c18ec02fSPetter Reinholdtsen 				{
1108c18ec02fSPetter Reinholdtsen 					switch(data2)
1109c18ec02fSPetter Reinholdtsen 					{
1110c18ec02fSPetter Reinholdtsen 						case 0x80:
1111c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "No memory is detected.");break;
1112c18ec02fSPetter Reinholdtsen 						case 0x81:
1113c18ec02fSPetter Reinholdtsen 							snprintf(desc,SIZE_OF_DESC, "Memory is detected but is not configurable.");break;
1114c18ec02fSPetter Reinholdtsen 						case 0x82:
1115c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "Memory is configured but not usable.");break;
1116c18ec02fSPetter Reinholdtsen 						case 0x83:
1117c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "System BIOS shadow failed.");break;
1118c18ec02fSPetter Reinholdtsen 						case 0x84:
1119c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "CMOS failed.");break;
1120c18ec02fSPetter Reinholdtsen 						case 0x85:
1121c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "DMA controller failed.");break;
1122c18ec02fSPetter Reinholdtsen 						case 0x86:
1123c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "Interrupt controller failed.");break;
1124c18ec02fSPetter Reinholdtsen 						case 0x87:
1125c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "Timer refresh failed.");break;
1126c18ec02fSPetter Reinholdtsen 						case 0x88:
1127c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "Programmable interval timer error.");break;
1128c18ec02fSPetter Reinholdtsen 						case 0x89:
1129c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "Parity error.");break;
1130c18ec02fSPetter Reinholdtsen 						case 0x8A:
1131c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "SIO failed.");break;
1132c18ec02fSPetter Reinholdtsen 						case 0x8B:
1133c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "Keyboard controller failed.");break;
1134c18ec02fSPetter Reinholdtsen 						case 0x8C:
1135c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "System management interrupt initialization failed.");break;
1136c18ec02fSPetter Reinholdtsen 						case 0x8D:
1137c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "TXT-SX Error.");break;
1138c18ec02fSPetter Reinholdtsen 						case 0xC0:
1139c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "Shutdown test failed.");break;
1140c18ec02fSPetter Reinholdtsen 						case 0xC1:
1141c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "BIOS POST memory test failed.");break;
1142c18ec02fSPetter Reinholdtsen 						case 0xC2:
1143c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "RAC configuration failed.");break;
1144c18ec02fSPetter Reinholdtsen 						case 0xC3:
1145c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "CPU configuration failed.");break;
1146c18ec02fSPetter Reinholdtsen 						case 0xC4:
1147c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "Incorrect memory configuration.");break;
1148c18ec02fSPetter Reinholdtsen 						case 0xFE:
1149c18ec02fSPetter Reinholdtsen 							snprintf(desc, SIZE_OF_DESC, "General failure after video.");
1150c18ec02fSPetter Reinholdtsen 							break;
1151c18ec02fSPetter Reinholdtsen 					}
1152c18ec02fSPetter Reinholdtsen 				}
1153c18ec02fSPetter Reinholdtsen 			break;
1154c18ec02fSPetter Reinholdtsen 
1155c18ec02fSPetter Reinholdtsen 			default:
1156c18ec02fSPetter Reinholdtsen 			break;
1157c18ec02fSPetter Reinholdtsen 		}
1158c18ec02fSPetter Reinholdtsen 	}
1159c18ec02fSPetter Reinholdtsen 	else
1160c18ec02fSPetter Reinholdtsen 	{
1161c18ec02fSPetter Reinholdtsen 		sensor_type = rec->sel_type.standard_type.event_type;
1162c18ec02fSPetter Reinholdtsen 	}
1163c18ec02fSPetter Reinholdtsen 	return desc;
1164c18ec02fSPetter Reinholdtsen }
1165c18ec02fSPetter Reinholdtsen 
1166c18ec02fSPetter Reinholdtsen char *
ipmi_get_oem_desc(struct ipmi_intf * intf,struct sel_event_record * rec)1167c18ec02fSPetter Reinholdtsen ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
1168c18ec02fSPetter Reinholdtsen {
1169c18ec02fSPetter Reinholdtsen 	char * desc = NULL;
1170c18ec02fSPetter Reinholdtsen 
1171c18ec02fSPetter Reinholdtsen 	switch (ipmi_get_oem(intf))
1172c18ec02fSPetter Reinholdtsen 	{
1173c18ec02fSPetter Reinholdtsen 	case IPMI_OEM_NEWISYS:
1174c18ec02fSPetter Reinholdtsen 		desc = get_newisys_evt_desc(intf, rec);
1175c18ec02fSPetter Reinholdtsen 		break;
1176c18ec02fSPetter Reinholdtsen 	case IPMI_OEM_KONTRON:
1177c18ec02fSPetter Reinholdtsen 		desc =  get_kontron_evt_desc(intf, rec);
1178c18ec02fSPetter Reinholdtsen 		break;
1179c18ec02fSPetter Reinholdtsen 	case IPMI_OEM_DELL: // Dell Decoding of the OEM Bytes from SEL Record.
1180c18ec02fSPetter Reinholdtsen 		desc = get_dell_evt_desc(intf, rec);
1181c18ec02fSPetter Reinholdtsen 		break;
1182c18ec02fSPetter Reinholdtsen 	case IPMI_OEM_SUPERMICRO:
1183c18ec02fSPetter Reinholdtsen 	case IPMI_OEM_SUPERMICRO_47488:
1184c18ec02fSPetter Reinholdtsen 		desc = get_supermicro_evt_desc(intf, rec);
1185c18ec02fSPetter Reinholdtsen 		break;
1186c18ec02fSPetter Reinholdtsen 	case IPMI_OEM_UNKNOWN:
1187c18ec02fSPetter Reinholdtsen 	default:
1188c18ec02fSPetter Reinholdtsen 		break;
1189c18ec02fSPetter Reinholdtsen 	}
1190c18ec02fSPetter Reinholdtsen 
1191c18ec02fSPetter Reinholdtsen 	return desc;
1192c18ec02fSPetter Reinholdtsen }
1193c18ec02fSPetter Reinholdtsen 
1194c18ec02fSPetter Reinholdtsen 
1195c18ec02fSPetter Reinholdtsen void
ipmi_get_event_desc(struct ipmi_intf * intf,struct sel_event_record * rec,char ** desc)1196c18ec02fSPetter Reinholdtsen ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char ** desc)
1197c18ec02fSPetter Reinholdtsen {
1198c18ec02fSPetter Reinholdtsen 	uint8_t code, offset;
1199c18ec02fSPetter Reinholdtsen 	struct ipmi_event_sensor_types *evt = NULL;
1200c18ec02fSPetter Reinholdtsen 	char *sfx = NULL;	/* This will be assigned if the Platform is DELL,
1201c18ec02fSPetter Reinholdtsen 				 additional info is appended to the current Description */
1202c18ec02fSPetter Reinholdtsen 
1203c18ec02fSPetter Reinholdtsen 	if (desc == NULL)
1204c18ec02fSPetter Reinholdtsen 		return;
1205c18ec02fSPetter Reinholdtsen 	*desc = NULL;
1206c18ec02fSPetter Reinholdtsen 
1207c18ec02fSPetter Reinholdtsen 	if ((rec->sel_type.standard_type.event_type >= 0x70) && (rec->sel_type.standard_type.event_type < 0x7F)) {
1208c18ec02fSPetter Reinholdtsen 		*desc = ipmi_get_oem_desc(intf, rec);
1209c18ec02fSPetter Reinholdtsen 		return;
1210c18ec02fSPetter Reinholdtsen 	} else if (rec->sel_type.standard_type.event_type == 0x6f) {
1211c18ec02fSPetter Reinholdtsen 		if( rec->sel_type.standard_type.sensor_type >= 0xC0 &&  rec->sel_type.standard_type.sensor_type < 0xF0) {
1212c18ec02fSPetter Reinholdtsen 			IPMI_OEM iana = ipmi_get_oem(intf);
1213c18ec02fSPetter Reinholdtsen 
1214c18ec02fSPetter Reinholdtsen 			switch(iana){
1215c18ec02fSPetter Reinholdtsen 				case IPMI_OEM_KONTRON:
1216c18ec02fSPetter Reinholdtsen 					lprintf(LOG_DEBUG, "oem sensor type %x %d using oem type supplied description",
1217c18ec02fSPetter Reinholdtsen 		                       rec->sel_type.standard_type.sensor_type , iana);
1218c18ec02fSPetter Reinholdtsen 
1219c18ec02fSPetter Reinholdtsen 					evt = oem_kontron_event_types;
1220c18ec02fSPetter Reinholdtsen 					code = rec->sel_type.standard_type.sensor_type;
1221c18ec02fSPetter Reinholdtsen 				 break;
1222c18ec02fSPetter Reinholdtsen 				case IPMI_OEM_DELL:		/* OEM Bytes Decoding for DELLi */
1223c18ec02fSPetter Reinholdtsen 					evt = sensor_specific_types;
1224c18ec02fSPetter Reinholdtsen 					code = rec->sel_type.standard_type.sensor_type;
1225c18ec02fSPetter Reinholdtsen 				 	if ( (OEM_CODE_IN_BYTE2 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK)) ||
1226c18ec02fSPetter Reinholdtsen 					     (OEM_CODE_IN_BYTE3 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE3_SPECIFIED_MASK)) )
1227c18ec02fSPetter Reinholdtsen 				 	{
1228c18ec02fSPetter Reinholdtsen 				 		if(rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK)
1229c18ec02fSPetter Reinholdtsen 						 	evt->data = rec->sel_type.standard_type.event_data[1];
1230c18ec02fSPetter Reinholdtsen 
1231c18ec02fSPetter Reinholdtsen 						 sfx = ipmi_get_oem_desc(intf, rec);
1232c18ec02fSPetter Reinholdtsen 				 	}
1233c18ec02fSPetter Reinholdtsen 				 break;
1234c18ec02fSPetter Reinholdtsen 				case IPMI_OEM_SUPERMICRO:
1235c18ec02fSPetter Reinholdtsen 				case IPMI_OEM_SUPERMICRO_47488:
1236c18ec02fSPetter Reinholdtsen 					evt = sensor_specific_types;
1237c18ec02fSPetter Reinholdtsen 					code = rec->sel_type.standard_type.sensor_type;
1238c18ec02fSPetter Reinholdtsen 					sfx = ipmi_get_oem_desc(intf, rec);
1239c18ec02fSPetter Reinholdtsen 					break;
1240c18ec02fSPetter Reinholdtsen 				 /* add your oem sensor assignation here */
124139fb1af2SZdenek Styblik 				default:
124239fb1af2SZdenek Styblik 					break;
1243c18ec02fSPetter Reinholdtsen 			}
1244c18ec02fSPetter Reinholdtsen 			if( evt == NULL ){
1245c18ec02fSPetter Reinholdtsen 				lprintf(LOG_DEBUG, "oem sensor type %x  using standard type supplied description",
1246c18ec02fSPetter Reinholdtsen 		                          rec->sel_type.standard_type.sensor_type );
1247c18ec02fSPetter Reinholdtsen 			}
1248c18ec02fSPetter Reinholdtsen 		} else {
1249c18ec02fSPetter Reinholdtsen 			switch (ipmi_get_oem(intf)) {
1250c18ec02fSPetter Reinholdtsen 				case IPMI_OEM_SUPERMICRO:
1251c18ec02fSPetter Reinholdtsen 				case IPMI_OEM_SUPERMICRO_47488:
1252c18ec02fSPetter Reinholdtsen 					evt = sensor_specific_types;
1253c18ec02fSPetter Reinholdtsen 					code = rec->sel_type.standard_type.sensor_type;
1254c18ec02fSPetter Reinholdtsen 					sfx = ipmi_get_oem_desc(intf, rec);
1255c18ec02fSPetter Reinholdtsen 				 break;
125639fb1af2SZdenek Styblik 				default:
125739fb1af2SZdenek Styblik 				 break;
1258c18ec02fSPetter Reinholdtsen 			}
1259c18ec02fSPetter Reinholdtsen 		}
1260c18ec02fSPetter Reinholdtsen 		if( evt == NULL ){
1261c18ec02fSPetter Reinholdtsen 			evt = sensor_specific_types;
1262c18ec02fSPetter Reinholdtsen 			code = rec->sel_type.standard_type.sensor_type;
1263c18ec02fSPetter Reinholdtsen 		}
1264c18ec02fSPetter Reinholdtsen 		/*
1265c18ec02fSPetter Reinholdtsen  		 * Check for the OEM DELL Interface based on the Dell Specific Vendor Code.
1266c18ec02fSPetter Reinholdtsen  		 * If its Dell Platform, do the OEM Byte decode from the SEL Records.
1267c18ec02fSPetter Reinholdtsen  		 * Additional information should be written by the ipmi_get_oem_desc()
1268c18ec02fSPetter Reinholdtsen  		 */
1269c18ec02fSPetter Reinholdtsen 		if(ipmi_get_oem(intf) == IPMI_OEM_DELL) {
1270c18ec02fSPetter Reinholdtsen 			code = rec->sel_type.standard_type.sensor_type;
1271c18ec02fSPetter Reinholdtsen 			if ( (OEM_CODE_IN_BYTE2 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK)) ||
1272c18ec02fSPetter Reinholdtsen 			     (OEM_CODE_IN_BYTE3 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE3_SPECIFIED_MASK)) )
1273c18ec02fSPetter Reinholdtsen 			{
1274c18ec02fSPetter Reinholdtsen 				if(rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK)
1275c18ec02fSPetter Reinholdtsen 					evt->data = rec->sel_type.standard_type.event_data[1];
1276c18ec02fSPetter Reinholdtsen 					 sfx = ipmi_get_oem_desc(intf, rec);
1277c18ec02fSPetter Reinholdtsen 
1278c18ec02fSPetter Reinholdtsen 			}
1279c18ec02fSPetter Reinholdtsen 			else if(SENSOR_TYPE_OEM_SEC_EVENT == rec->sel_type.standard_type.event_data[0])
1280c18ec02fSPetter Reinholdtsen 			{
1281c18ec02fSPetter Reinholdtsen 				/* 0x23 : Sensor Number.*/
1282c18ec02fSPetter Reinholdtsen 				if(0x23 == rec->sel_type.standard_type.sensor_num)
1283c18ec02fSPetter Reinholdtsen 				{
1284c18ec02fSPetter Reinholdtsen 					evt->data = rec->sel_type.standard_type.event_data[1];
1285c18ec02fSPetter Reinholdtsen 					sfx = ipmi_get_oem_desc(intf, rec);
1286c18ec02fSPetter Reinholdtsen 				}
1287c18ec02fSPetter Reinholdtsen 			}
1288c18ec02fSPetter Reinholdtsen 		}
1289c18ec02fSPetter Reinholdtsen 	} else {
1290c18ec02fSPetter Reinholdtsen 		evt = generic_event_types;
1291c18ec02fSPetter Reinholdtsen 		code = rec->sel_type.standard_type.event_type;
1292c18ec02fSPetter Reinholdtsen 	}
1293c18ec02fSPetter Reinholdtsen 
1294c18ec02fSPetter Reinholdtsen 	offset = rec->sel_type.standard_type.event_data[0] & 0xf;
1295c18ec02fSPetter Reinholdtsen 
1296c18ec02fSPetter Reinholdtsen 	while (evt->type) {
1297c18ec02fSPetter Reinholdtsen 		if ((evt->code == code && evt->offset == offset && evt->desc != NULL) &&
1298c18ec02fSPetter Reinholdtsen 			((evt->data == ALL_OFFSETS_SPECIFIED) ||
1299c18ec02fSPetter Reinholdtsen 			 ((rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK) &&
1300c18ec02fSPetter Reinholdtsen 			  (evt->data == rec->sel_type.standard_type.event_data[1]))))
1301c18ec02fSPetter Reinholdtsen 		{
1302c18ec02fSPetter Reinholdtsen 			/* Increase the Malloc size to current_size + Dellspecific description size */
1303c18ec02fSPetter Reinholdtsen 			*desc = (char *)malloc(strlen(evt->desc) + 48 + SIZE_OF_DESC);
1304c18ec02fSPetter Reinholdtsen 			if (NULL == *desc) {
1305c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "ipmitool: malloc failure");
1306c18ec02fSPetter Reinholdtsen 				return;
1307c18ec02fSPetter Reinholdtsen 			}
1308c18ec02fSPetter Reinholdtsen 			memset(*desc, 0, strlen(evt->desc)+ 48 + SIZE_OF_DESC);
1309c18ec02fSPetter Reinholdtsen 			/*
1310c18ec02fSPetter Reinholdtsen  			 * Additional info is present for the DELL Platforms.
1311c18ec02fSPetter Reinholdtsen  			 * Append the same to the evt->desc string.
1312c18ec02fSPetter Reinholdtsen  			 */
1313c18ec02fSPetter Reinholdtsen 			if (sfx) {
1314c18ec02fSPetter Reinholdtsen 				sprintf(*desc, "%s (%s)", evt->desc, sfx);
1315c18ec02fSPetter Reinholdtsen 				free(sfx);
1316c18ec02fSPetter Reinholdtsen 				sfx = NULL;
1317c18ec02fSPetter Reinholdtsen 			} else {
1318c18ec02fSPetter Reinholdtsen 				sprintf(*desc, "%s", evt->desc);
1319c18ec02fSPetter Reinholdtsen 			}
1320c18ec02fSPetter Reinholdtsen 			return;
1321c18ec02fSPetter Reinholdtsen 		}
1322c18ec02fSPetter Reinholdtsen 		evt++;
1323c18ec02fSPetter Reinholdtsen 	}
1324c18ec02fSPetter Reinholdtsen 	/* The Above while Condition was not met beacouse the below sensor type were Newly defined OEM
1325c18ec02fSPetter Reinholdtsen 	   Secondary Events. 0xC1, 0xC2, 0xC3. */
1326c18ec02fSPetter Reinholdtsen     if((sfx) && (0x6F == rec->sel_type.standard_type.event_type))
1327c18ec02fSPetter Reinholdtsen 	{
1328c18ec02fSPetter Reinholdtsen 	    uint8_t flag = 0x00;
1329c18ec02fSPetter Reinholdtsen 	    switch(code)
1330c18ec02fSPetter Reinholdtsen 		{
1331c18ec02fSPetter Reinholdtsen             case SENSOR_TYPE_FRM_PROG:
1332c18ec02fSPetter Reinholdtsen                  if(0x0F == offset)
1333c18ec02fSPetter Reinholdtsen                      flag = 0x01;
1334c18ec02fSPetter Reinholdtsen                  break;
1335c18ec02fSPetter Reinholdtsen 			case SENSOR_TYPE_OEM_SEC_EVENT:
1336c18ec02fSPetter Reinholdtsen 			     if((0x01 == offset) || (0x02 == offset) || (0x03 == offset))
1337c18ec02fSPetter Reinholdtsen                      flag = 0x01;
1338c18ec02fSPetter Reinholdtsen                  break;
1339c18ec02fSPetter Reinholdtsen             case SENSOR_TYPE_OEM_NFATAL_ERROR:
1340c18ec02fSPetter Reinholdtsen                  if((0x00 == offset) || (0x02 == offset))
1341c18ec02fSPetter Reinholdtsen                      flag = 0x01;
1342c18ec02fSPetter Reinholdtsen                  break;
1343c18ec02fSPetter Reinholdtsen             case SENSOR_TYPE_OEM_FATAL_ERROR:
1344c18ec02fSPetter Reinholdtsen                  if(0x01 == offset)
1345c18ec02fSPetter Reinholdtsen                      flag = 0x01;
1346c18ec02fSPetter Reinholdtsen                  break;
1347c18ec02fSPetter Reinholdtsen             case SENSOR_TYPE_SUPERMICRO_OEM:
1348c18ec02fSPetter Reinholdtsen                  flag = 0x02;
1349c18ec02fSPetter Reinholdtsen                  break;
1350c18ec02fSPetter Reinholdtsen             default:
1351c18ec02fSPetter Reinholdtsen                  break;
1352c18ec02fSPetter Reinholdtsen 		}
1353c18ec02fSPetter Reinholdtsen 		if(flag)
1354c18ec02fSPetter Reinholdtsen 		{
1355c18ec02fSPetter Reinholdtsen 		    *desc = (char *)malloc( 48 + SIZE_OF_DESC);
1356c18ec02fSPetter Reinholdtsen 		    if (NULL == *desc)
1357c18ec02fSPetter Reinholdtsen 			{
1358c18ec02fSPetter Reinholdtsen 		        lprintf(LOG_ERR, "ipmitool: malloc failure");
1359c18ec02fSPetter Reinholdtsen 			    return;
1360c18ec02fSPetter Reinholdtsen 		    }
1361c18ec02fSPetter Reinholdtsen 		memset(*desc, 0, 48 + SIZE_OF_DESC);
1362c18ec02fSPetter Reinholdtsen 		if (flag == 0x02) {
1363c18ec02fSPetter Reinholdtsen 			sprintf(*desc, "%s", sfx);
1364c18ec02fSPetter Reinholdtsen 			return;
1365c18ec02fSPetter Reinholdtsen 		}
1366c18ec02fSPetter Reinholdtsen 		sprintf(*desc, "(%s)",sfx);
1367c18ec02fSPetter Reinholdtsen      	}
1368c18ec02fSPetter Reinholdtsen 		free(sfx);
1369c18ec02fSPetter Reinholdtsen 		sfx = NULL;
1370c18ec02fSPetter Reinholdtsen 	}
1371c18ec02fSPetter Reinholdtsen }
1372c18ec02fSPetter Reinholdtsen 
1373c18ec02fSPetter Reinholdtsen 
1374c18ec02fSPetter Reinholdtsen const char *
ipmi_sel_get_oem_sensor_type(IPMI_OEM iana,uint8_t code)1375c18ec02fSPetter Reinholdtsen ipmi_sel_get_oem_sensor_type(IPMI_OEM iana, uint8_t code)
1376c18ec02fSPetter Reinholdtsen {
1377c18ec02fSPetter Reinholdtsen 	struct ipmi_event_sensor_types *st = NULL;
1378c18ec02fSPetter Reinholdtsen 
1379c18ec02fSPetter Reinholdtsen 	switch(iana){
1380c18ec02fSPetter Reinholdtsen 		case IPMI_OEM_KONTRON:
1381c18ec02fSPetter Reinholdtsen 			st = oem_kontron_event_types;
1382c18ec02fSPetter Reinholdtsen 		break;
1383c18ec02fSPetter Reinholdtsen 		/* add you oem sensor type lookup assignement here */
1384c18ec02fSPetter Reinholdtsen 		default:
1385c18ec02fSPetter Reinholdtsen 			lprintf(LOG_DEBUG, "ipmitool: missing OEM sensor type for %ul",iana);
1386c18ec02fSPetter Reinholdtsen 		break;
1387c18ec02fSPetter Reinholdtsen 	}
1388c18ec02fSPetter Reinholdtsen 
1389c18ec02fSPetter Reinholdtsen 	if( st != NULL )
1390c18ec02fSPetter Reinholdtsen 		for (; st->type != NULL; st++)
1391c18ec02fSPetter Reinholdtsen 			if (st->code == code)
1392c18ec02fSPetter Reinholdtsen 				return st->type;
1393c18ec02fSPetter Reinholdtsen 
1394c18ec02fSPetter Reinholdtsen 	return ipmi_sel_get_sensor_type(code);
1395c18ec02fSPetter Reinholdtsen }
1396c18ec02fSPetter Reinholdtsen 
1397c18ec02fSPetter Reinholdtsen const char *
ipmi_sel_get_oem_sensor_type_offset(IPMI_OEM iana,uint8_t code,uint8_t offset)1398c18ec02fSPetter Reinholdtsen ipmi_sel_get_oem_sensor_type_offset(IPMI_OEM iana, uint8_t code, uint8_t offset)
1399c18ec02fSPetter Reinholdtsen {
1400c18ec02fSPetter Reinholdtsen 	struct ipmi_event_sensor_types *st = NULL;
1401c18ec02fSPetter Reinholdtsen 
1402c18ec02fSPetter Reinholdtsen 	switch(iana){
1403c18ec02fSPetter Reinholdtsen 		case IPMI_OEM_KONTRON:
1404c18ec02fSPetter Reinholdtsen 			st = oem_kontron_event_types;
1405c18ec02fSPetter Reinholdtsen 		break;
1406c18ec02fSPetter Reinholdtsen 		/* add you oem sensor type lookup assignement here */
1407c18ec02fSPetter Reinholdtsen 		default:
1408c18ec02fSPetter Reinholdtsen 			lprintf(LOG_DEBUG,
1409c18ec02fSPetter Reinholdtsen                       "ipmitool: missing OEM sensor type offset for %ul",iana);
1410c18ec02fSPetter Reinholdtsen 		break;
1411c18ec02fSPetter Reinholdtsen 	}
1412c18ec02fSPetter Reinholdtsen 
1413c18ec02fSPetter Reinholdtsen 	if( st != NULL )
1414c18ec02fSPetter Reinholdtsen 		for (; st->type != NULL; st++)
1415c18ec02fSPetter Reinholdtsen 		{
1416c18ec02fSPetter Reinholdtsen 			if (st->code == code && st->offset == (offset&0xf))
1417c18ec02fSPetter Reinholdtsen 				return st->type;
1418c18ec02fSPetter Reinholdtsen 		}
1419c18ec02fSPetter Reinholdtsen 
1420c18ec02fSPetter Reinholdtsen 	return ipmi_sel_get_oem_sensor_type(iana,code);
1421c18ec02fSPetter Reinholdtsen }
1422c18ec02fSPetter Reinholdtsen 
1423c18ec02fSPetter Reinholdtsen const char *
ipmi_sel_get_sensor_type(uint8_t code)1424c18ec02fSPetter Reinholdtsen ipmi_sel_get_sensor_type(uint8_t code)
1425c18ec02fSPetter Reinholdtsen {
1426c18ec02fSPetter Reinholdtsen 	struct ipmi_event_sensor_types *st;
1427c18ec02fSPetter Reinholdtsen 	for (st = sensor_specific_types; st->type != NULL; st++)
1428c18ec02fSPetter Reinholdtsen 		if (st->code == code)
1429c18ec02fSPetter Reinholdtsen 			return st->type;
1430c18ec02fSPetter Reinholdtsen 	return "Unknown";
1431c18ec02fSPetter Reinholdtsen }
1432c18ec02fSPetter Reinholdtsen 
1433c18ec02fSPetter Reinholdtsen const char *
ipmi_sel_get_sensor_type_offset(uint8_t code,uint8_t offset)1434c18ec02fSPetter Reinholdtsen ipmi_sel_get_sensor_type_offset(uint8_t code, uint8_t offset)
1435c18ec02fSPetter Reinholdtsen {
1436c18ec02fSPetter Reinholdtsen 	struct ipmi_event_sensor_types *st;
1437c18ec02fSPetter Reinholdtsen 	for (st = sensor_specific_types; st->type != NULL; st++)
1438c18ec02fSPetter Reinholdtsen 		if (st->code == code && st->offset == (offset&0xf))
1439c18ec02fSPetter Reinholdtsen 			return st->type;
1440c18ec02fSPetter Reinholdtsen 
1441c18ec02fSPetter Reinholdtsen 	return ipmi_sel_get_sensor_type(code);
1442c18ec02fSPetter Reinholdtsen }
1443c18ec02fSPetter Reinholdtsen 
1444c18ec02fSPetter Reinholdtsen static int
ipmi_sel_get_info(struct ipmi_intf * intf)1445c18ec02fSPetter Reinholdtsen ipmi_sel_get_info(struct ipmi_intf * intf)
1446c18ec02fSPetter Reinholdtsen {
1447c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1448c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1449c18ec02fSPetter Reinholdtsen 	uint16_t e, version;
1450c18ec02fSPetter Reinholdtsen 	uint32_t f;
1451c18ec02fSPetter Reinholdtsen 	int pctfull = 0;
1452c18ec02fSPetter Reinholdtsen 	uint32_t fs    = 0xffffffff;
1453c18ec02fSPetter Reinholdtsen 	uint32_t zeros = 0;
1454c18ec02fSPetter Reinholdtsen 
1455c18ec02fSPetter Reinholdtsen 
1456c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1457c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
1458c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_CMD_GET_SEL_INFO;
1459c18ec02fSPetter Reinholdtsen 
1460c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1461c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
1462c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get SEL Info command failed");
1463c18ec02fSPetter Reinholdtsen 		return -1;
1464c18ec02fSPetter Reinholdtsen 	}
1465c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
1466c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get SEL Info command failed: %s",
1467c18ec02fSPetter Reinholdtsen 		       val2str(rsp->ccode, completion_code_vals));
1468c18ec02fSPetter Reinholdtsen 		return -1;
1469c18ec02fSPetter Reinholdtsen 	}
1470c18ec02fSPetter Reinholdtsen 	if (verbose > 2)
1471c18ec02fSPetter Reinholdtsen 		printbuf(rsp->data, rsp->data_len, "sel_info");
1472c18ec02fSPetter Reinholdtsen 
1473c18ec02fSPetter Reinholdtsen 	printf("SEL Information\n");
1474c18ec02fSPetter Reinholdtsen         version = rsp->data[0];
1475c18ec02fSPetter Reinholdtsen 	printf("Version          : %d.%d (%s)\n",
1476c18ec02fSPetter Reinholdtsen 	       version & 0xf, (version>>4) & 0xf,
1477c18ec02fSPetter Reinholdtsen 	       (version == 0x51 || version == 0x02) ? "v1.5, v2 compliant" : "Unknown");
1478c18ec02fSPetter Reinholdtsen 
1479c18ec02fSPetter Reinholdtsen 	/* save the entry count and free space to determine percent full */
1480c18ec02fSPetter Reinholdtsen 	e = buf2short(rsp->data + 1);
1481c18ec02fSPetter Reinholdtsen 	f = buf2short(rsp->data + 3);
1482c18ec02fSPetter Reinholdtsen 	printf("Entries          : %d\n", e);
1483c18ec02fSPetter Reinholdtsen 	printf("Free Space       : %d bytes %s\n", f ,(f==65535 ? "or more" : "" ));
1484c18ec02fSPetter Reinholdtsen 
1485c18ec02fSPetter Reinholdtsen 	if (e) {
1486c18ec02fSPetter Reinholdtsen 		e *= 16; /* each entry takes 16 bytes */
1487c18ec02fSPetter Reinholdtsen 		f += e;	/* this is supposed to give the total size ... */
1488c18ec02fSPetter Reinholdtsen 		pctfull = (int)(100 * ( (double)e / (double)f ));
1489c18ec02fSPetter Reinholdtsen 	}
1490c18ec02fSPetter Reinholdtsen 
1491c18ec02fSPetter Reinholdtsen 	if( f >= 65535 ) {
1492c18ec02fSPetter Reinholdtsen 		printf("Percent Used     : %s\n", "unknown" );
1493c18ec02fSPetter Reinholdtsen 	}
1494c18ec02fSPetter Reinholdtsen 	else {
1495c18ec02fSPetter Reinholdtsen 		printf("Percent Used     : %d%%\n", pctfull);
1496c18ec02fSPetter Reinholdtsen 	}
1497c18ec02fSPetter Reinholdtsen 
1498c18ec02fSPetter Reinholdtsen 
1499c18ec02fSPetter Reinholdtsen 	if ((!memcmp(rsp->data + 5, &fs,    4)) ||
1500c18ec02fSPetter Reinholdtsen 		(!memcmp(rsp->data + 5, &zeros, 4)))
1501c18ec02fSPetter Reinholdtsen 		printf("Last Add Time    : Not Available\n");
1502c18ec02fSPetter Reinholdtsen 	else
1503c18ec02fSPetter Reinholdtsen 		printf("Last Add Time    : %s\n",
1504c18ec02fSPetter Reinholdtsen 			   ipmi_sel_timestamp(buf2long(rsp->data + 5)));
1505c18ec02fSPetter Reinholdtsen 
1506c18ec02fSPetter Reinholdtsen 	if ((!memcmp(rsp->data + 9, &fs,    4)) ||
1507c18ec02fSPetter Reinholdtsen 		(!memcmp(rsp->data + 9, &zeros, 4)))
1508c18ec02fSPetter Reinholdtsen 		printf("Last Del Time    : Not Available\n");
1509c18ec02fSPetter Reinholdtsen 	else
1510c18ec02fSPetter Reinholdtsen 		printf("Last Del Time    : %s\n",
1511c18ec02fSPetter Reinholdtsen 			   ipmi_sel_timestamp(buf2long(rsp->data + 9)));
1512c18ec02fSPetter Reinholdtsen 
1513c18ec02fSPetter Reinholdtsen 
1514c18ec02fSPetter Reinholdtsen 	printf("Overflow         : %s\n",
1515c18ec02fSPetter Reinholdtsen 	       rsp->data[13] & 0x80 ? "true" : "false");
1516c18ec02fSPetter Reinholdtsen 	printf("Supported Cmds   : ");
1517c18ec02fSPetter Reinholdtsen         if (rsp->data[13] & 0x0f)
1518c18ec02fSPetter Reinholdtsen         {
1519c18ec02fSPetter Reinholdtsen 	        if (rsp->data[13] & 0x08)
1520c18ec02fSPetter Reinholdtsen                         printf("'Delete' ");
1521c18ec02fSPetter Reinholdtsen 	        if (rsp->data[13] & 0x04)
1522c18ec02fSPetter Reinholdtsen                         printf("'Partial Add' ");
1523c18ec02fSPetter Reinholdtsen 	        if (rsp->data[13] & 0x02)
1524c18ec02fSPetter Reinholdtsen                         printf("'Reserve' ");
1525c18ec02fSPetter Reinholdtsen 	        if (rsp->data[13] & 0x01)
1526c18ec02fSPetter Reinholdtsen                         printf("'Get Alloc Info' ");
1527c18ec02fSPetter Reinholdtsen         }
1528c18ec02fSPetter Reinholdtsen         else
1529c18ec02fSPetter Reinholdtsen                 printf("None");
1530c18ec02fSPetter Reinholdtsen         printf("\n");
1531c18ec02fSPetter Reinholdtsen 
1532c18ec02fSPetter Reinholdtsen 	/* get sel allocation info if supported */
1533c18ec02fSPetter Reinholdtsen 	if (rsp->data[13] & 1) {
1534c18ec02fSPetter Reinholdtsen 		memset(&req, 0, sizeof(req));
1535c18ec02fSPetter Reinholdtsen 		req.msg.netfn = IPMI_NETFN_STORAGE;
1536c18ec02fSPetter Reinholdtsen 		req.msg.cmd = IPMI_CMD_GET_SEL_ALLOC_INFO;
1537c18ec02fSPetter Reinholdtsen 
1538c18ec02fSPetter Reinholdtsen 		rsp = intf->sendrecv(intf, &req);
1539c18ec02fSPetter Reinholdtsen 		if (rsp == NULL) {
1540c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
1541c18ec02fSPetter Reinholdtsen 				"Get SEL Allocation Info command failed");
1542c18ec02fSPetter Reinholdtsen 			return -1;
1543c18ec02fSPetter Reinholdtsen 		}
1544c18ec02fSPetter Reinholdtsen 		if (rsp->ccode > 0) {
1545c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
1546c18ec02fSPetter Reinholdtsen 				"Get SEL Allocation Info command failed: %s",
1547c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
1548c18ec02fSPetter Reinholdtsen 			return -1;
1549c18ec02fSPetter Reinholdtsen 		}
1550c18ec02fSPetter Reinholdtsen 
1551c18ec02fSPetter Reinholdtsen 		printf("# of Alloc Units : %d\n", buf2short(rsp->data));
1552c18ec02fSPetter Reinholdtsen 		printf("Alloc Unit Size  : %d\n", buf2short(rsp->data + 2));
1553c18ec02fSPetter Reinholdtsen 		printf("# Free Units     : %d\n", buf2short(rsp->data + 4));
1554c18ec02fSPetter Reinholdtsen 		printf("Largest Free Blk : %d\n", buf2short(rsp->data + 6));
1555c18ec02fSPetter Reinholdtsen 		printf("Max Record Size  : %d\n", rsp->data[8]);
1556c18ec02fSPetter Reinholdtsen 	}
1557c18ec02fSPetter Reinholdtsen 	return 0;
1558c18ec02fSPetter Reinholdtsen }
1559c18ec02fSPetter Reinholdtsen 
1560c18ec02fSPetter Reinholdtsen uint16_t
ipmi_sel_get_std_entry(struct ipmi_intf * intf,uint16_t id,struct sel_event_record * evt)1561c18ec02fSPetter Reinholdtsen ipmi_sel_get_std_entry(struct ipmi_intf * intf, uint16_t id,
1562c18ec02fSPetter Reinholdtsen 		       struct sel_event_record * evt)
1563c18ec02fSPetter Reinholdtsen {
1564c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1565c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1566c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[6];
1567c18ec02fSPetter Reinholdtsen 	uint16_t next;
1568c18ec02fSPetter Reinholdtsen 	int data_count;
1569c18ec02fSPetter Reinholdtsen 
1570c18ec02fSPetter Reinholdtsen 	memset(msg_data, 0, 6);
1571c18ec02fSPetter Reinholdtsen 	msg_data[0] = 0x00;	/* no reserve id, not partial get */
1572c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0x00;
1573c18ec02fSPetter Reinholdtsen 	msg_data[2] = id & 0xff;
1574c18ec02fSPetter Reinholdtsen 	msg_data[3] = (id >> 8) & 0xff;
1575c18ec02fSPetter Reinholdtsen 	msg_data[4] = 0x00;	/* offset */
1576c18ec02fSPetter Reinholdtsen 	msg_data[5] = 0xff;	/* length */
1577c18ec02fSPetter Reinholdtsen 
1578c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1579c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
1580c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_CMD_GET_SEL_ENTRY;
1581c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
1582c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 6;
1583c18ec02fSPetter Reinholdtsen 
1584c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1585c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
1586c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get SEL Entry %x command failed", id);
1587c18ec02fSPetter Reinholdtsen 		return 0;
1588c18ec02fSPetter Reinholdtsen 	}
1589c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
1590c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get SEL Entry %x command failed: %s",
1591c18ec02fSPetter Reinholdtsen 			id, val2str(rsp->ccode, completion_code_vals));
1592c18ec02fSPetter Reinholdtsen 		return 0;
1593c18ec02fSPetter Reinholdtsen 	}
1594c18ec02fSPetter Reinholdtsen 
1595c18ec02fSPetter Reinholdtsen 	/* save next entry id */
1596c18ec02fSPetter Reinholdtsen 	next = (rsp->data[1] << 8) | rsp->data[0];
1597c18ec02fSPetter Reinholdtsen 
1598c18ec02fSPetter Reinholdtsen 	lprintf(LOG_DEBUG, "SEL Entry: %s", buf2str(rsp->data+2, rsp->data_len-2));
1599c18ec02fSPetter Reinholdtsen 	memset(evt, 0, sizeof(*evt));
1600c18ec02fSPetter Reinholdtsen 
1601c18ec02fSPetter Reinholdtsen 	/*Clear SEL Structure*/
1602c18ec02fSPetter Reinholdtsen 	evt->record_id = 0;
1603c18ec02fSPetter Reinholdtsen 	evt->record_type = 0;
1604c18ec02fSPetter Reinholdtsen 	if (evt->record_type < 0xc0)
1605c18ec02fSPetter Reinholdtsen 	{
1606c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.timestamp = 0;
1607c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.gen_id = 0;
1608c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.evm_rev = 0;
1609c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.sensor_type = 0;
1610c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.sensor_num = 0;
1611c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.event_type = 0;
1612c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.event_dir = 0;
1613c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.event_data[0] = 0;
1614c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.event_data[1] = 0;
1615c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.event_data[2] = 0;
1616c18ec02fSPetter Reinholdtsen 	}
1617c18ec02fSPetter Reinholdtsen 	else if (evt->record_type < 0xe0)
1618c18ec02fSPetter Reinholdtsen 	{
1619c18ec02fSPetter Reinholdtsen 		evt->sel_type.oem_ts_type.timestamp = 0;
1620c18ec02fSPetter Reinholdtsen 		evt->sel_type.oem_ts_type.manf_id[0] = 0;
1621c18ec02fSPetter Reinholdtsen 		evt->sel_type.oem_ts_type.manf_id[1] = 0;
1622c18ec02fSPetter Reinholdtsen 		evt->sel_type.oem_ts_type.manf_id[2] = 0;
1623c18ec02fSPetter Reinholdtsen 		for(data_count=0; data_count < SEL_OEM_TS_DATA_LEN ; data_count++)
1624c18ec02fSPetter Reinholdtsen 			evt->sel_type.oem_ts_type.oem_defined[data_count] = 0;
1625c18ec02fSPetter Reinholdtsen 	}
1626c18ec02fSPetter Reinholdtsen 	else
1627c18ec02fSPetter Reinholdtsen 	{
1628c18ec02fSPetter Reinholdtsen 		for(data_count=0; data_count < SEL_OEM_NOTS_DATA_LEN ; data_count++)
1629c18ec02fSPetter Reinholdtsen 			evt->sel_type.oem_nots_type.oem_defined[data_count] = 0;
1630c18ec02fSPetter Reinholdtsen 	}
1631c18ec02fSPetter Reinholdtsen 
1632c18ec02fSPetter Reinholdtsen 	/* save response into SEL event structure */
1633c18ec02fSPetter Reinholdtsen 	evt->record_id = (rsp->data[3] << 8) | rsp->data[2];
1634c18ec02fSPetter Reinholdtsen 	evt->record_type = rsp->data[4];
1635c18ec02fSPetter Reinholdtsen 	if (evt->record_type < 0xc0)
1636c18ec02fSPetter Reinholdtsen 	{
1637c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.timestamp = (rsp->data[8] << 24) |	(rsp->data[7] << 16) |
1638c18ec02fSPetter Reinholdtsen     			(rsp->data[6] << 8) | rsp->data[5];
1639c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.gen_id = (rsp->data[10] << 8) | rsp->data[9];
1640c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.evm_rev = rsp->data[11];
1641c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.sensor_type = rsp->data[12];
1642c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.sensor_num = rsp->data[13];
1643c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.event_type = rsp->data[14] & 0x7f;
1644c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.event_dir = (rsp->data[14] & 0x80) >> 7;
1645c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.event_data[0] = rsp->data[15];
1646c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.event_data[1] = rsp->data[16];
1647c18ec02fSPetter Reinholdtsen     		evt->sel_type.standard_type.event_data[2] = rsp->data[17];
1648c18ec02fSPetter Reinholdtsen   	}
1649c18ec02fSPetter Reinholdtsen   	else if (evt->record_type < 0xe0)
1650c18ec02fSPetter Reinholdtsen   	{
1651c18ec02fSPetter Reinholdtsen     		evt->sel_type.oem_ts_type.timestamp= (rsp->data[8] << 24) |	(rsp->data[7] << 16) |
1652c18ec02fSPetter Reinholdtsen     			(rsp->data[6] << 8) | rsp->data[5];
1653c18ec02fSPetter Reinholdtsen 		evt->sel_type.oem_ts_type.manf_id[0]= rsp->data[11];
1654c18ec02fSPetter Reinholdtsen 		evt->sel_type.oem_ts_type.manf_id[1]= rsp->data[10];
1655c18ec02fSPetter Reinholdtsen 		evt->sel_type.oem_ts_type.manf_id[2]= rsp->data[9];
1656c18ec02fSPetter Reinholdtsen   		for(data_count=0; data_count < SEL_OEM_TS_DATA_LEN ; data_count++)
1657c18ec02fSPetter Reinholdtsen       			evt->sel_type.oem_ts_type.oem_defined[data_count] = rsp->data[(data_count+12)];
1658c18ec02fSPetter Reinholdtsen   	}
1659c18ec02fSPetter Reinholdtsen   	else
1660c18ec02fSPetter Reinholdtsen   	{
1661c18ec02fSPetter Reinholdtsen   		for(data_count=0; data_count < SEL_OEM_NOTS_DATA_LEN ; data_count++)
1662c18ec02fSPetter Reinholdtsen       			evt->sel_type.oem_nots_type.oem_defined[data_count] = rsp->data[(data_count+5)];
1663c18ec02fSPetter Reinholdtsen 	}
1664c18ec02fSPetter Reinholdtsen 	return next;
1665c18ec02fSPetter Reinholdtsen }
1666c18ec02fSPetter Reinholdtsen 
1667c18ec02fSPetter Reinholdtsen static void
ipmi_sel_print_event_file(struct ipmi_intf * intf,struct sel_event_record * evt,FILE * fp)1668c18ec02fSPetter Reinholdtsen ipmi_sel_print_event_file(struct ipmi_intf * intf, struct sel_event_record * evt, FILE * fp)
1669c18ec02fSPetter Reinholdtsen {
1670c18ec02fSPetter Reinholdtsen 	char * description;
1671c18ec02fSPetter Reinholdtsen 
1672c18ec02fSPetter Reinholdtsen 	if (fp == NULL)
1673c18ec02fSPetter Reinholdtsen 		return;
1674c18ec02fSPetter Reinholdtsen 
1675c18ec02fSPetter Reinholdtsen 	ipmi_get_event_desc(intf, evt, &description);
1676c18ec02fSPetter Reinholdtsen 
1677c18ec02fSPetter Reinholdtsen 	fprintf(fp, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x # %s #0x%02x %s\n",
1678c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.evm_rev,
1679c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.sensor_type,
1680c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.sensor_num,
1681c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.event_type | (evt->sel_type.standard_type.event_dir << 7),
1682c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.event_data[0],
1683c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.event_data[1],
1684c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.event_data[2],
1685c18ec02fSPetter Reinholdtsen       (
1686c18ec02fSPetter Reinholdtsen 			(evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0)
1687c18ec02fSPetter Reinholdtsen 			?
1688c18ec02fSPetter Reinholdtsen    		ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])
1689c18ec02fSPetter Reinholdtsen 			:
1690c18ec02fSPetter Reinholdtsen 			ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])
1691c18ec02fSPetter Reinholdtsen       ),
1692c18ec02fSPetter Reinholdtsen 		evt->sel_type.standard_type.sensor_num,
1693c18ec02fSPetter Reinholdtsen 		(description != NULL) ? description : "Unknown");
1694c18ec02fSPetter Reinholdtsen 
1695c18ec02fSPetter Reinholdtsen 	if (description != NULL) {
1696c18ec02fSPetter Reinholdtsen 		free(description);
1697c18ec02fSPetter Reinholdtsen 		description = NULL;
1698c18ec02fSPetter Reinholdtsen 	}
1699c18ec02fSPetter Reinholdtsen }
1700c18ec02fSPetter Reinholdtsen 
1701c18ec02fSPetter Reinholdtsen void
ipmi_sel_print_extended_entry(struct ipmi_intf * intf,struct sel_event_record * evt)1702c18ec02fSPetter Reinholdtsen ipmi_sel_print_extended_entry(struct ipmi_intf * intf, struct sel_event_record * evt)
1703c18ec02fSPetter Reinholdtsen {
1704c18ec02fSPetter Reinholdtsen 	sel_extended++;
1705c18ec02fSPetter Reinholdtsen 	ipmi_sel_print_std_entry(intf, evt);
1706c18ec02fSPetter Reinholdtsen 	sel_extended--;
1707c18ec02fSPetter Reinholdtsen }
1708c18ec02fSPetter Reinholdtsen 
1709c18ec02fSPetter Reinholdtsen void
ipmi_sel_print_std_entry(struct ipmi_intf * intf,struct sel_event_record * evt)1710c18ec02fSPetter Reinholdtsen ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt)
1711c18ec02fSPetter Reinholdtsen {
1712c18ec02fSPetter Reinholdtsen 	char * description;
1713c18ec02fSPetter Reinholdtsen 	struct sdr_record_list * sdr = NULL;
1714c18ec02fSPetter Reinholdtsen 	int data_count;
1715c18ec02fSPetter Reinholdtsen 
1716c18ec02fSPetter Reinholdtsen 	if (sel_extended && (evt->record_type < 0xc0))
1717c18ec02fSPetter Reinholdtsen 		sdr = ipmi_sdr_find_sdr_bynumtype(intf, evt->sel_type.standard_type.gen_id, evt->sel_type.standard_type.sensor_num, evt->sel_type.standard_type.sensor_type);
1718c18ec02fSPetter Reinholdtsen 
1719c18ec02fSPetter Reinholdtsen 
1720c18ec02fSPetter Reinholdtsen 	if (!evt)
1721c18ec02fSPetter Reinholdtsen 		return;
1722c18ec02fSPetter Reinholdtsen 
1723c18ec02fSPetter Reinholdtsen 	if (csv_output)
1724c18ec02fSPetter Reinholdtsen 		printf("%x,", evt->record_id);
1725c18ec02fSPetter Reinholdtsen 	else
1726c18ec02fSPetter Reinholdtsen 		printf("%4x | ", evt->record_id);
1727c18ec02fSPetter Reinholdtsen 
1728c18ec02fSPetter Reinholdtsen 	if (evt->record_type == 0xf0)
1729c18ec02fSPetter Reinholdtsen 	{
1730c18ec02fSPetter Reinholdtsen 		if (csv_output)
1731c18ec02fSPetter Reinholdtsen 			printf(",,");
1732c18ec02fSPetter Reinholdtsen 
1733c18ec02fSPetter Reinholdtsen 		printf ("Linux kernel panic: %.11s\n", (char *) evt + 5);
1734c18ec02fSPetter Reinholdtsen 		return;
1735c18ec02fSPetter Reinholdtsen 	}
1736c18ec02fSPetter Reinholdtsen 
1737c18ec02fSPetter Reinholdtsen 	if (evt->record_type < 0xe0)
1738c18ec02fSPetter Reinholdtsen 	{
1739c18ec02fSPetter Reinholdtsen 		if ((evt->sel_type.standard_type.timestamp < 0x20000000)||(evt->sel_type.oem_ts_type.timestamp <  0x20000000)){
1740c18ec02fSPetter Reinholdtsen 			printf(" Pre-Init ");
1741c18ec02fSPetter Reinholdtsen 
1742c18ec02fSPetter Reinholdtsen 			if (csv_output)
1743c18ec02fSPetter Reinholdtsen 				printf(",");
1744c18ec02fSPetter Reinholdtsen 			else
1745c18ec02fSPetter Reinholdtsen 				printf(" |");
1746c18ec02fSPetter Reinholdtsen 
1747c18ec02fSPetter Reinholdtsen 			printf("%010d", evt->sel_type.standard_type.timestamp );
1748c18ec02fSPetter Reinholdtsen 			if (csv_output)
1749c18ec02fSPetter Reinholdtsen 				printf(",");
1750c18ec02fSPetter Reinholdtsen 			else
1751c18ec02fSPetter Reinholdtsen 				printf("| ");
1752c18ec02fSPetter Reinholdtsen 		}
1753c18ec02fSPetter Reinholdtsen 		else {
1754c18ec02fSPetter Reinholdtsen 			if (evt->record_type < 0xc0)
1755c18ec02fSPetter Reinholdtsen 				printf("%s", ipmi_sel_timestamp_date(evt->sel_type.standard_type.timestamp));
1756c18ec02fSPetter Reinholdtsen 			else
1757c18ec02fSPetter Reinholdtsen         			printf("%s", ipmi_sel_timestamp_date(evt->sel_type.oem_ts_type.timestamp));
1758c18ec02fSPetter Reinholdtsen 			if (csv_output)
1759c18ec02fSPetter Reinholdtsen 				printf(",");
1760c18ec02fSPetter Reinholdtsen 			else
1761c18ec02fSPetter Reinholdtsen 				printf(" | ");
1762c18ec02fSPetter Reinholdtsen 
1763c18ec02fSPetter Reinholdtsen 			if (evt->record_type < 0xc0)
1764c18ec02fSPetter Reinholdtsen 				printf("%s", ipmi_sel_timestamp_time(evt->sel_type.standard_type.timestamp));
1765c18ec02fSPetter Reinholdtsen 			else
1766c18ec02fSPetter Reinholdtsen         			printf("%s", ipmi_sel_timestamp_time(evt->sel_type.oem_ts_type.timestamp));
1767c18ec02fSPetter Reinholdtsen 
1768c18ec02fSPetter Reinholdtsen 			if (csv_output)
1769c18ec02fSPetter Reinholdtsen 				printf(",");
1770c18ec02fSPetter Reinholdtsen 			else
1771c18ec02fSPetter Reinholdtsen 				printf(" | ");
1772c18ec02fSPetter Reinholdtsen 		}
1773c18ec02fSPetter Reinholdtsen 
1774c18ec02fSPetter Reinholdtsen 	}
1775c18ec02fSPetter Reinholdtsen 	else
1776c18ec02fSPetter Reinholdtsen 	{
1777c18ec02fSPetter Reinholdtsen 		if (csv_output)
1778c18ec02fSPetter Reinholdtsen 			printf(",,");
1779c18ec02fSPetter Reinholdtsen 	}
1780c18ec02fSPetter Reinholdtsen 
1781c18ec02fSPetter Reinholdtsen 	if (evt->record_type >= 0xc0)
1782c18ec02fSPetter Reinholdtsen 	{
1783c18ec02fSPetter Reinholdtsen 		printf ("OEM record %02x", evt->record_type);
1784c18ec02fSPetter Reinholdtsen 		if (csv_output)
1785c18ec02fSPetter Reinholdtsen 			printf(",");
1786c18ec02fSPetter Reinholdtsen 		else
1787c18ec02fSPetter Reinholdtsen 			printf(" | ");
1788c18ec02fSPetter Reinholdtsen 
17898f783736SZdenek Styblik 		if(evt->record_type <= 0xdf)
1790c18ec02fSPetter Reinholdtsen 		{
1791c18ec02fSPetter Reinholdtsen 			printf ("%02x%02x%02x", evt->sel_type.oem_ts_type.manf_id[0], evt->sel_type.oem_ts_type.manf_id[1], evt->sel_type.oem_ts_type.manf_id[2]);
1792c18ec02fSPetter Reinholdtsen 			if (csv_output)
1793c18ec02fSPetter Reinholdtsen 				printf(",");
1794c18ec02fSPetter Reinholdtsen 			else
1795c18ec02fSPetter Reinholdtsen 				printf(" | ");
1796c18ec02fSPetter Reinholdtsen 			for(data_count=0;data_count < SEL_OEM_TS_DATA_LEN;data_count++)
1797c18ec02fSPetter Reinholdtsen 				printf("%02x", evt->sel_type.oem_ts_type.oem_defined[data_count]);
1798c18ec02fSPetter Reinholdtsen 		}
1799c18ec02fSPetter Reinholdtsen 		else
1800c18ec02fSPetter Reinholdtsen 		{
1801c18ec02fSPetter Reinholdtsen 			for(data_count=0;data_count < SEL_OEM_NOTS_DATA_LEN;data_count++)
1802c18ec02fSPetter Reinholdtsen 				printf("%02x", evt->sel_type.oem_nots_type.oem_defined[data_count]);
1803c18ec02fSPetter Reinholdtsen 		}
1804c18ec02fSPetter Reinholdtsen 		ipmi_sel_oem_message(evt, 0);
1805c18ec02fSPetter Reinholdtsen 		printf ("\n");
1806c18ec02fSPetter Reinholdtsen 		return;
1807c18ec02fSPetter Reinholdtsen 	}
1808c18ec02fSPetter Reinholdtsen 
1809c18ec02fSPetter Reinholdtsen 	/* lookup SDR entry based on sensor number and type */
1810c18ec02fSPetter Reinholdtsen 	if (sdr != NULL) {
1811c18ec02fSPetter Reinholdtsen 		printf("%s ",
1812c18ec02fSPetter Reinholdtsen 	   (
1813c18ec02fSPetter Reinholdtsen 			(evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0)
1814c18ec02fSPetter Reinholdtsen 			?
1815c18ec02fSPetter Reinholdtsen    		ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])
1816c18ec02fSPetter Reinholdtsen 			:
1817c18ec02fSPetter Reinholdtsen 			ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])
1818c18ec02fSPetter Reinholdtsen 			)
1819c18ec02fSPetter Reinholdtsen 		);
1820c18ec02fSPetter Reinholdtsen 		switch (sdr->type) {
1821c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_FULL_SENSOR:
1822c18ec02fSPetter Reinholdtsen 			printf("%s", sdr->record.full->id_string);
1823c18ec02fSPetter Reinholdtsen 			break;
1824c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_COMPACT_SENSOR:
1825c18ec02fSPetter Reinholdtsen 			printf("%s", sdr->record.compact->id_string);
1826c18ec02fSPetter Reinholdtsen 			break;
1827c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
1828c18ec02fSPetter Reinholdtsen 			printf("%s", sdr->record.eventonly->id_string);
1829c18ec02fSPetter Reinholdtsen 			break;
1830c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR:
1831c18ec02fSPetter Reinholdtsen 			printf("%s", sdr->record.fruloc->id_string);
1832c18ec02fSPetter Reinholdtsen 			break;
1833c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
1834c18ec02fSPetter Reinholdtsen 			printf("%s", sdr->record.mcloc->id_string);
1835c18ec02fSPetter Reinholdtsen 			break;
1836c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR:
1837c18ec02fSPetter Reinholdtsen 			printf("%s", sdr->record.genloc->id_string);
1838c18ec02fSPetter Reinholdtsen 			break;
1839c18ec02fSPetter Reinholdtsen 		default:
1840c18ec02fSPetter Reinholdtsen 			printf("#%02x", evt->sel_type.standard_type.sensor_num);
1841c18ec02fSPetter Reinholdtsen 			break;
1842c18ec02fSPetter Reinholdtsen 		}
1843c18ec02fSPetter Reinholdtsen 	} else {
1844c18ec02fSPetter Reinholdtsen 		printf("%s",(
1845c18ec02fSPetter Reinholdtsen 			(evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0)
1846c18ec02fSPetter Reinholdtsen 			?
1847c18ec02fSPetter Reinholdtsen    		ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])
1848c18ec02fSPetter Reinholdtsen 			:
1849c18ec02fSPetter Reinholdtsen 			ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])
1850c18ec02fSPetter Reinholdtsen 		));
1851c18ec02fSPetter Reinholdtsen 		if (evt->sel_type.standard_type.sensor_num != 0)
1852c18ec02fSPetter Reinholdtsen 			printf(" #0x%02x", evt->sel_type.standard_type.sensor_num);
1853c18ec02fSPetter Reinholdtsen 	}
1854c18ec02fSPetter Reinholdtsen 
1855c18ec02fSPetter Reinholdtsen 	if (csv_output)
1856c18ec02fSPetter Reinholdtsen 		printf(",");
1857c18ec02fSPetter Reinholdtsen 	else
1858c18ec02fSPetter Reinholdtsen 		printf(" | ");
1859c18ec02fSPetter Reinholdtsen 
1860c18ec02fSPetter Reinholdtsen 	ipmi_get_event_desc(intf, evt, &description);
1861c18ec02fSPetter Reinholdtsen 	if (description) {
1862c18ec02fSPetter Reinholdtsen 		printf("%s", description);
1863c18ec02fSPetter Reinholdtsen 		free(description);
1864c18ec02fSPetter Reinholdtsen 		description = NULL;
1865c18ec02fSPetter Reinholdtsen 	}
1866c18ec02fSPetter Reinholdtsen 
1867c18ec02fSPetter Reinholdtsen 	if (csv_output) {
1868c18ec02fSPetter Reinholdtsen 		printf(",");
1869c18ec02fSPetter Reinholdtsen 	} else {
1870c18ec02fSPetter Reinholdtsen 		printf(" | ");
1871c18ec02fSPetter Reinholdtsen 	}
1872c18ec02fSPetter Reinholdtsen 
1873c18ec02fSPetter Reinholdtsen 	if (evt->sel_type.standard_type.event_dir) {
1874c18ec02fSPetter Reinholdtsen 		printf("Deasserted");
1875c18ec02fSPetter Reinholdtsen 	} else {
1876c18ec02fSPetter Reinholdtsen 		printf("Asserted");
1877c18ec02fSPetter Reinholdtsen 	}
1878c18ec02fSPetter Reinholdtsen 
1879c18ec02fSPetter Reinholdtsen 	if (sdr != NULL && evt->sel_type.standard_type.event_type == 1) {
1880c18ec02fSPetter Reinholdtsen 		/*
1881c18ec02fSPetter Reinholdtsen 		 * Threshold Event
1882c18ec02fSPetter Reinholdtsen 		 */
1883c18ec02fSPetter Reinholdtsen 		float trigger_reading = 0.0;
1884c18ec02fSPetter Reinholdtsen 		float threshold_reading = 0.0;
1885c18ec02fSPetter Reinholdtsen 		uint8_t threshold_reading_provided = 0;
1886c18ec02fSPetter Reinholdtsen 
1887c18ec02fSPetter Reinholdtsen 		/* trigger reading in event data byte 2 */
1888c18ec02fSPetter Reinholdtsen 		if (((evt->sel_type.standard_type.event_data[0] >> 6) & 3) == 1) {
1889c18ec02fSPetter Reinholdtsen 			trigger_reading = sdr_convert_sensor_reading(
1890c18ec02fSPetter Reinholdtsen 				sdr->record.full, evt->sel_type.standard_type.event_data[1]);
1891c18ec02fSPetter Reinholdtsen 		}
1892c18ec02fSPetter Reinholdtsen 
1893c18ec02fSPetter Reinholdtsen 		/* trigger threshold in event data byte 3 */
1894c18ec02fSPetter Reinholdtsen 		if (((evt->sel_type.standard_type.event_data[0] >> 4) & 3) == 1) {
1895c18ec02fSPetter Reinholdtsen 			threshold_reading = sdr_convert_sensor_reading(
1896c18ec02fSPetter Reinholdtsen 				sdr->record.full, evt->sel_type.standard_type.event_data[2]);
1897c18ec02fSPetter Reinholdtsen 			threshold_reading_provided = 1;
1898c18ec02fSPetter Reinholdtsen 		}
1899c18ec02fSPetter Reinholdtsen 
1900c18ec02fSPetter Reinholdtsen 		if (csv_output)
1901c18ec02fSPetter Reinholdtsen 			printf(",");
1902c18ec02fSPetter Reinholdtsen 		else
1903c18ec02fSPetter Reinholdtsen 			printf(" | ");
1904c18ec02fSPetter Reinholdtsen 
1905c18ec02fSPetter Reinholdtsen 		printf("Reading %.*f",
1906c18ec02fSPetter Reinholdtsen 				(trigger_reading==(int)trigger_reading) ? 0 : 2,
1907c18ec02fSPetter Reinholdtsen 				trigger_reading);
1908c18ec02fSPetter Reinholdtsen 		if (threshold_reading_provided) {
1909c18ec02fSPetter Reinholdtsen 			printf(" %s Threshold %.*f %s",
1910c18ec02fSPetter Reinholdtsen 					((evt->sel_type.standard_type.event_data[0] & 0xf) % 2) ? ">" : "<",
1911c18ec02fSPetter Reinholdtsen 					(threshold_reading==(int)threshold_reading) ? 0 : 2,
1912c18ec02fSPetter Reinholdtsen 					threshold_reading,
1913c18ec02fSPetter Reinholdtsen 					ipmi_sdr_get_unit_string(sdr->record.common->unit.pct,
1914c18ec02fSPetter Reinholdtsen 						sdr->record.common->unit.modifier,
1915c18ec02fSPetter Reinholdtsen 						sdr->record.common->unit.type.base,
1916c18ec02fSPetter Reinholdtsen 						sdr->record.common->unit.type.modifier));
1917c18ec02fSPetter Reinholdtsen 		}
1918c18ec02fSPetter Reinholdtsen 	}
1919c18ec02fSPetter Reinholdtsen 	else if (evt->sel_type.standard_type.event_type == 0x6f) {
1920c18ec02fSPetter Reinholdtsen 		int print_sensor = 1;
1921c18ec02fSPetter Reinholdtsen 		switch (ipmi_get_oem(intf)) {
1922c18ec02fSPetter Reinholdtsen 			case IPMI_OEM_SUPERMICRO:
1923c18ec02fSPetter Reinholdtsen 			case IPMI_OEM_SUPERMICRO_47488:
1924c18ec02fSPetter Reinholdtsen 				print_sensor = 0;
1925c18ec02fSPetter Reinholdtsen 			 break;
192639fb1af2SZdenek Styblik 			default:
192739fb1af2SZdenek Styblik 			 break;
1928c18ec02fSPetter Reinholdtsen 		}
1929c18ec02fSPetter Reinholdtsen 		/*
1930c18ec02fSPetter Reinholdtsen 		 * Sensor-Specific Discrete
1931c18ec02fSPetter Reinholdtsen 		 */
1932c18ec02fSPetter Reinholdtsen 		if (print_sensor && evt->sel_type.standard_type.sensor_type == 0xC && /*TODO*/
1933c18ec02fSPetter Reinholdtsen 		    evt->sel_type.standard_type.sensor_num == 0 &&
1934c18ec02fSPetter Reinholdtsen 		    (evt->sel_type.standard_type.event_data[0] & 0x30) == 0x20) {
1935c18ec02fSPetter Reinholdtsen 			/* break down memory ECC reporting if we can */
1936c18ec02fSPetter Reinholdtsen 			if (csv_output)
1937c18ec02fSPetter Reinholdtsen 				printf(",");
1938c18ec02fSPetter Reinholdtsen 			else
1939c18ec02fSPetter Reinholdtsen 				printf(" | ");
1940c18ec02fSPetter Reinholdtsen 
1941c18ec02fSPetter Reinholdtsen 			printf("CPU %d DIMM %d",
1942c18ec02fSPetter Reinholdtsen 			       evt->sel_type.standard_type.event_data[2] & 0x0f,
1943c18ec02fSPetter Reinholdtsen 			       (evt->sel_type.standard_type.event_data[2] & 0xf0) >> 4);
1944c18ec02fSPetter Reinholdtsen 		}
1945c18ec02fSPetter Reinholdtsen 	}
1946c18ec02fSPetter Reinholdtsen 
1947c18ec02fSPetter Reinholdtsen 	printf("\n");
1948c18ec02fSPetter Reinholdtsen }
1949c18ec02fSPetter Reinholdtsen 
1950c18ec02fSPetter Reinholdtsen void
ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf,struct sel_event_record * evt)1951c18ec02fSPetter Reinholdtsen ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf, struct sel_event_record * evt)
1952c18ec02fSPetter Reinholdtsen {
1953c18ec02fSPetter Reinholdtsen   char * description;
1954c18ec02fSPetter Reinholdtsen   int data_count;
1955c18ec02fSPetter Reinholdtsen 
1956c18ec02fSPetter Reinholdtsen 	if (!evt)
1957c18ec02fSPetter Reinholdtsen 		return;
1958c18ec02fSPetter Reinholdtsen 
1959c18ec02fSPetter Reinholdtsen 	printf("SEL Record ID          : %04x\n", evt->record_id);
1960c18ec02fSPetter Reinholdtsen 
1961c18ec02fSPetter Reinholdtsen 	if (evt->record_type == 0xf0)
1962c18ec02fSPetter Reinholdtsen 	{
1963c18ec02fSPetter Reinholdtsen 		printf (" Record Type           : Linux kernel panic (OEM record %02x)\n", evt->record_type);
1964c18ec02fSPetter Reinholdtsen 		printf (" Panic string          : %.11s\n\n", (char *) evt + 5);
1965c18ec02fSPetter Reinholdtsen 		return;
1966c18ec02fSPetter Reinholdtsen 	}
1967c18ec02fSPetter Reinholdtsen 
1968c18ec02fSPetter Reinholdtsen 	printf(" Record Type           : %02x", evt->record_type);
1969c18ec02fSPetter Reinholdtsen 	if (evt->record_type >= 0xc0)
1970c18ec02fSPetter Reinholdtsen 	{
1971c18ec02fSPetter Reinholdtsen 		if (evt->record_type < 0xe0)
1972c18ec02fSPetter Reinholdtsen 			printf("  (OEM timestamped)");
1973c18ec02fSPetter Reinholdtsen 		else
1974c18ec02fSPetter Reinholdtsen 			printf("  (OEM non-timestamped)");
1975c18ec02fSPetter Reinholdtsen 	}
1976c18ec02fSPetter Reinholdtsen 	printf("\n");
1977c18ec02fSPetter Reinholdtsen 
1978c18ec02fSPetter Reinholdtsen 	if (evt->record_type < 0xe0)
1979c18ec02fSPetter Reinholdtsen 	{
1980c18ec02fSPetter Reinholdtsen 		printf(" Timestamp             : ");
1981c18ec02fSPetter Reinholdtsen 		if (evt->record_type < 0xc0)
1982c18ec02fSPetter Reinholdtsen 			printf("%s %s", ipmi_sel_timestamp_date(evt->sel_type.standard_type.timestamp),
1983c18ec02fSPetter Reinholdtsen 				ipmi_sel_timestamp_time(evt->sel_type.standard_type.timestamp));
1984c18ec02fSPetter Reinholdtsen 		else
1985c18ec02fSPetter Reinholdtsen 			printf("%s %s", ipmi_sel_timestamp_date(evt->sel_type.oem_ts_type.timestamp),
1986c18ec02fSPetter Reinholdtsen 				ipmi_sel_timestamp_time(evt->sel_type.oem_ts_type.timestamp));
1987c18ec02fSPetter Reinholdtsen 		printf("\n");
1988c18ec02fSPetter Reinholdtsen 	}
1989c18ec02fSPetter Reinholdtsen 
1990c18ec02fSPetter Reinholdtsen 	if (evt->record_type >= 0xc0)
1991c18ec02fSPetter Reinholdtsen 	{
19928f783736SZdenek Styblik 		if(evt->record_type <= 0xdf)
1993c18ec02fSPetter Reinholdtsen 		{
1994c18ec02fSPetter Reinholdtsen 			printf (" Manufactacturer ID    : %02x%02x%02x\n", evt->sel_type.oem_ts_type.manf_id[0],
1995c18ec02fSPetter Reinholdtsen 			evt->sel_type.oem_ts_type.manf_id[1], evt->sel_type.oem_ts_type.manf_id[2]);
1996c18ec02fSPetter Reinholdtsen 			printf (" OEM Defined           : ");
1997c18ec02fSPetter Reinholdtsen 			for(data_count=0;data_count < SEL_OEM_TS_DATA_LEN;data_count++)
1998c18ec02fSPetter Reinholdtsen 				printf("%02x", evt->sel_type.oem_ts_type.oem_defined[data_count]);
1999c18ec02fSPetter Reinholdtsen 			printf(" [%s]\n\n",hex2ascii (evt->sel_type.oem_ts_type.oem_defined, SEL_OEM_TS_DATA_LEN));
2000c18ec02fSPetter Reinholdtsen 		}
2001c18ec02fSPetter Reinholdtsen 		else
2002c18ec02fSPetter Reinholdtsen 		{
2003c18ec02fSPetter Reinholdtsen 			printf (" OEM Defined           : ");
2004c18ec02fSPetter Reinholdtsen 			for(data_count=0;data_count < SEL_OEM_NOTS_DATA_LEN;data_count++)
2005c18ec02fSPetter Reinholdtsen 				printf("%02x", evt->sel_type.oem_nots_type.oem_defined[data_count]);
2006c18ec02fSPetter Reinholdtsen 			printf(" [%s]\n\n",hex2ascii (evt->sel_type.oem_nots_type.oem_defined, SEL_OEM_NOTS_DATA_LEN));
2007c18ec02fSPetter Reinholdtsen 			ipmi_sel_oem_message(evt, 1);
2008c18ec02fSPetter Reinholdtsen 		}
2009c18ec02fSPetter Reinholdtsen 		return;
2010c18ec02fSPetter Reinholdtsen 	}
2011c18ec02fSPetter Reinholdtsen 
2012c18ec02fSPetter Reinholdtsen 	printf(" Generator ID          : %04x\n",
2013c18ec02fSPetter Reinholdtsen 	       evt->sel_type.standard_type.gen_id);
2014c18ec02fSPetter Reinholdtsen 	printf(" EvM Revision          : %02x\n",
2015c18ec02fSPetter Reinholdtsen 	       evt->sel_type.standard_type.evm_rev);
2016c18ec02fSPetter Reinholdtsen 	printf(" Sensor Type           : %s\n",
2017c18ec02fSPetter Reinholdtsen    (
2018c18ec02fSPetter Reinholdtsen 			(evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0)
2019c18ec02fSPetter Reinholdtsen 			?
2020c18ec02fSPetter Reinholdtsen    		ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])
2021c18ec02fSPetter Reinholdtsen 			:
2022c18ec02fSPetter Reinholdtsen 			ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])
2023c18ec02fSPetter Reinholdtsen 			)
2024c18ec02fSPetter Reinholdtsen 	);
2025c18ec02fSPetter Reinholdtsen 	printf(" Sensor Number         : %02x\n",
2026c18ec02fSPetter Reinholdtsen 	       evt->sel_type.standard_type.sensor_num);
2027c18ec02fSPetter Reinholdtsen 	printf(" Event Type            : %s\n",
2028c18ec02fSPetter Reinholdtsen 	       ipmi_get_event_type(evt->sel_type.standard_type.event_type));
2029c18ec02fSPetter Reinholdtsen 	printf(" Event Direction       : %s\n",
2030c18ec02fSPetter Reinholdtsen 	       val2str(evt->sel_type.standard_type.event_dir, event_dir_vals));
2031c18ec02fSPetter Reinholdtsen 	printf(" Event Data            : %02x%02x%02x\n",
2032c18ec02fSPetter Reinholdtsen 	       evt->sel_type.standard_type.event_data[0], evt->sel_type.standard_type.event_data[1], evt->sel_type.standard_type.event_data[2]);
2033c18ec02fSPetter Reinholdtsen         ipmi_get_event_desc(intf, evt, &description);
2034c18ec02fSPetter Reinholdtsen 	printf(" Description           : %s\n",
2035c18ec02fSPetter Reinholdtsen                description ? description : "");
2036c18ec02fSPetter Reinholdtsen         free(description);
2037c18ec02fSPetter Reinholdtsen 				description = NULL;
2038c18ec02fSPetter Reinholdtsen 
2039c18ec02fSPetter Reinholdtsen 	printf("\n");
2040c18ec02fSPetter Reinholdtsen }
2041c18ec02fSPetter Reinholdtsen 
2042c18ec02fSPetter Reinholdtsen 
2043c18ec02fSPetter Reinholdtsen void
ipmi_sel_print_extended_entry_verbose(struct ipmi_intf * intf,struct sel_event_record * evt)2044c18ec02fSPetter Reinholdtsen ipmi_sel_print_extended_entry_verbose(struct ipmi_intf * intf, struct sel_event_record * evt)
2045c18ec02fSPetter Reinholdtsen {
2046c18ec02fSPetter Reinholdtsen 	struct sdr_record_list * sdr;
2047c18ec02fSPetter Reinholdtsen 	char * description;
2048c18ec02fSPetter Reinholdtsen 
2049c18ec02fSPetter Reinholdtsen 	if (!evt)
2050c18ec02fSPetter Reinholdtsen 		return;
2051c18ec02fSPetter Reinholdtsen 
2052c18ec02fSPetter Reinholdtsen 	sdr = ipmi_sdr_find_sdr_bynumtype(intf,
2053c18ec02fSPetter Reinholdtsen 					  evt->sel_type.standard_type.gen_id,
2054c18ec02fSPetter Reinholdtsen 					  evt->sel_type.standard_type.sensor_num,
2055c18ec02fSPetter Reinholdtsen 					  evt->sel_type.standard_type.sensor_type);
2056c18ec02fSPetter Reinholdtsen 	if (sdr == NULL)
2057c18ec02fSPetter Reinholdtsen 	{
2058c18ec02fSPetter Reinholdtsen 	    ipmi_sel_print_std_entry_verbose(intf, evt);
2059c18ec02fSPetter Reinholdtsen 		return;
2060c18ec02fSPetter Reinholdtsen 	}
2061c18ec02fSPetter Reinholdtsen 
2062c18ec02fSPetter Reinholdtsen 	printf("SEL Record ID          : %04x\n", evt->record_id);
2063c18ec02fSPetter Reinholdtsen 
2064c18ec02fSPetter Reinholdtsen 	if (evt->record_type == 0xf0)
2065c18ec02fSPetter Reinholdtsen 	{
2066c18ec02fSPetter Reinholdtsen 		printf (" Record Type           : "
2067c18ec02fSPetter Reinholdtsen 			"Linux kernel panic (OEM record %02x)\n",
2068c18ec02fSPetter Reinholdtsen 			evt->record_type);
2069c18ec02fSPetter Reinholdtsen 		printf (" Panic string          : %.11s\n\n",
2070c18ec02fSPetter Reinholdtsen 			(char *) evt + 5);
2071c18ec02fSPetter Reinholdtsen 		return;
2072c18ec02fSPetter Reinholdtsen 	}
2073c18ec02fSPetter Reinholdtsen 
2074c18ec02fSPetter Reinholdtsen 	printf(" Record Type           : %02x\n", evt->record_type);
2075c18ec02fSPetter Reinholdtsen 	if (evt->record_type < 0xe0)
2076c18ec02fSPetter Reinholdtsen 	{
2077c18ec02fSPetter Reinholdtsen 		printf(" Timestamp             : ");
2078c18ec02fSPetter Reinholdtsen 		printf("%s %s\n", ipmi_sel_timestamp_date(evt->sel_type.standard_type.timestamp),
2079c18ec02fSPetter Reinholdtsen 		ipmi_sel_timestamp_time(evt->sel_type.standard_type.timestamp));
2080c18ec02fSPetter Reinholdtsen 	}
2081c18ec02fSPetter Reinholdtsen 
2082c18ec02fSPetter Reinholdtsen 
2083c18ec02fSPetter Reinholdtsen 	printf(" Generator ID          : %04x\n",
2084c18ec02fSPetter Reinholdtsen 	       evt->sel_type.standard_type.gen_id);
2085c18ec02fSPetter Reinholdtsen 	printf(" EvM Revision          : %02x\n",
2086c18ec02fSPetter Reinholdtsen 	       evt->sel_type.standard_type.evm_rev);
2087c18ec02fSPetter Reinholdtsen 	printf(" Sensor Type           : %s\n",
2088c18ec02fSPetter Reinholdtsen 	       ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]));
2089c18ec02fSPetter Reinholdtsen 	printf(" Sensor Number         : %02x\n",
2090c18ec02fSPetter Reinholdtsen 	       evt->sel_type.standard_type.sensor_num);
2091c18ec02fSPetter Reinholdtsen 	printf(" Event Type            : %s\n",
2092c18ec02fSPetter Reinholdtsen 	       ipmi_get_event_type(evt->sel_type.standard_type.event_type));
2093c18ec02fSPetter Reinholdtsen 	printf(" Event Direction       : %s\n",
2094c18ec02fSPetter Reinholdtsen 	       val2str(evt->sel_type.standard_type.event_dir, event_dir_vals));
2095c18ec02fSPetter Reinholdtsen 	printf(" Event Data (RAW)      : %02x%02x%02x\n",
2096c18ec02fSPetter Reinholdtsen 	       evt->sel_type.standard_type.event_data[0], evt->sel_type.standard_type.event_data[1], evt->sel_type.standard_type.event_data[2]);
2097c18ec02fSPetter Reinholdtsen 
2098c18ec02fSPetter Reinholdtsen 	/* break down event data field
2099c18ec02fSPetter Reinholdtsen 	 * as per IPMI Spec 2.0 Table 29-6 */
2100c18ec02fSPetter Reinholdtsen 	if (evt->sel_type.standard_type.event_type == 1 && sdr->type == SDR_RECORD_TYPE_FULL_SENSOR) {
2101c18ec02fSPetter Reinholdtsen 		/* Threshold */
2102c18ec02fSPetter Reinholdtsen 		switch ((evt->sel_type.standard_type.event_data[0] >> 6) & 3) {  /* EV1[7:6] */
2103c18ec02fSPetter Reinholdtsen 		case 0:
2104c18ec02fSPetter Reinholdtsen 			/* unspecified byte 2 */
2105c18ec02fSPetter Reinholdtsen 			break;
2106c18ec02fSPetter Reinholdtsen 		case 1:
2107c18ec02fSPetter Reinholdtsen 			/* trigger reading in byte 2 */
2108c18ec02fSPetter Reinholdtsen 			printf(" Trigger Reading       : %.3f",
2109c18ec02fSPetter Reinholdtsen 			       sdr_convert_sensor_reading(sdr->record.full,
2110c18ec02fSPetter Reinholdtsen 							  evt->sel_type.standard_type.event_data[1]));
2111c18ec02fSPetter Reinholdtsen 			/* determine units with possible modifiers */
2112c18ec02fSPetter Reinholdtsen 			printf ("%s\n", ipmi_sdr_get_unit_string(sdr->record.common->unit.pct,
2113c18ec02fSPetter Reinholdtsen 								 sdr->record.common->unit.modifier,
2114c18ec02fSPetter Reinholdtsen 								 sdr->record.common->unit.type.base,
2115c18ec02fSPetter Reinholdtsen 								 sdr->record.common->unit.type.modifier));
2116c18ec02fSPetter Reinholdtsen 			break;
2117c18ec02fSPetter Reinholdtsen 		case 2:
2118c18ec02fSPetter Reinholdtsen 			/* oem code in byte 2 */
2119c18ec02fSPetter Reinholdtsen 			printf(" OEM Data              : %02x\n",
2120c18ec02fSPetter Reinholdtsen 			       evt->sel_type.standard_type.event_data[1]);
2121c18ec02fSPetter Reinholdtsen 			break;
2122c18ec02fSPetter Reinholdtsen 		case 3:
2123c18ec02fSPetter Reinholdtsen 			/* sensor-specific extension code in byte 2 */
2124c18ec02fSPetter Reinholdtsen 			printf(" Sensor Extension Code : %02x\n",
2125c18ec02fSPetter Reinholdtsen 			       evt->sel_type.standard_type.event_data[1]);
2126c18ec02fSPetter Reinholdtsen 			break;
2127c18ec02fSPetter Reinholdtsen 		}
2128c18ec02fSPetter Reinholdtsen 		switch ((evt->sel_type.standard_type.event_data[0] >> 4) & 3) {   /* EV1[5:4] */
2129c18ec02fSPetter Reinholdtsen 		case 0:
2130c18ec02fSPetter Reinholdtsen 			/* unspecified byte 3 */
2131c18ec02fSPetter Reinholdtsen 			break;
2132c18ec02fSPetter Reinholdtsen 		case 1:
2133c18ec02fSPetter Reinholdtsen 			/* trigger threshold value in byte 3 */
2134c18ec02fSPetter Reinholdtsen 			printf(" Trigger Threshold     : %.3f",
2135c18ec02fSPetter Reinholdtsen 			       sdr_convert_sensor_reading(sdr->record.full,
2136c18ec02fSPetter Reinholdtsen 							  evt->sel_type.standard_type.event_data[2]));
2137c18ec02fSPetter Reinholdtsen 			/* determine units with possible modifiers */
2138c18ec02fSPetter Reinholdtsen 			printf ("%s\n", ipmi_sdr_get_unit_string(sdr->record.common->unit.pct,
2139c18ec02fSPetter Reinholdtsen 								 sdr->record.common->unit.modifier,
2140c18ec02fSPetter Reinholdtsen 								 sdr->record.common->unit.type.base,
2141c18ec02fSPetter Reinholdtsen 								 sdr->record.common->unit.type.modifier));
2142c18ec02fSPetter Reinholdtsen 			break;
2143c18ec02fSPetter Reinholdtsen 		case 2:
2144c18ec02fSPetter Reinholdtsen 			/* OEM code in byte 3 */
2145c18ec02fSPetter Reinholdtsen 			printf(" OEM Data              : %02x\n",
2146c18ec02fSPetter Reinholdtsen 			       evt->sel_type.standard_type.event_data[2]);
2147c18ec02fSPetter Reinholdtsen 			break;
2148c18ec02fSPetter Reinholdtsen 		case 3:
2149c18ec02fSPetter Reinholdtsen 			/* sensor-specific extension code in byte 3 */
2150c18ec02fSPetter Reinholdtsen 			printf(" Sensor Extension Code : %02x\n",
2151c18ec02fSPetter Reinholdtsen 			       evt->sel_type.standard_type.event_data[2]);
2152c18ec02fSPetter Reinholdtsen 			break;
2153c18ec02fSPetter Reinholdtsen 		}
2154c18ec02fSPetter Reinholdtsen 	} else if (evt->sel_type.standard_type.event_type >= 0x2 && evt->sel_type.standard_type.event_type <= 0xc) {
2155c18ec02fSPetter Reinholdtsen 		/* Generic Discrete */
2156c18ec02fSPetter Reinholdtsen 	} else if (evt->sel_type.standard_type.event_type == 0x6f) {
2157c18ec02fSPetter Reinholdtsen 
2158c18ec02fSPetter Reinholdtsen 		/* Sensor-Specific Discrete */
2159c18ec02fSPetter Reinholdtsen 		if (evt->sel_type.standard_type.sensor_type == 0xC &&
2160c18ec02fSPetter Reinholdtsen 		    evt->sel_type.standard_type.sensor_num  == 0 &&			 /**** THIS LOOK TO BE OEM ****/
2161c18ec02fSPetter Reinholdtsen 		    (evt->sel_type.standard_type.event_data[0] & 0x30) == 0x20)
2162c18ec02fSPetter Reinholdtsen 		{
2163c18ec02fSPetter Reinholdtsen 			/* break down memory ECC reporting if we can */
2164c18ec02fSPetter Reinholdtsen 			printf(" Event Data            : CPU %d DIMM %d\n",
2165c18ec02fSPetter Reinholdtsen 			       evt->sel_type.standard_type.event_data[2] & 0x0f,
2166c18ec02fSPetter Reinholdtsen 			       (evt->sel_type.standard_type.event_data[2] & 0xf0) >> 4);
2167c18ec02fSPetter Reinholdtsen 		}
2168c18ec02fSPetter Reinholdtsen 		else if(
2169c18ec02fSPetter Reinholdtsen 				evt->sel_type.standard_type.sensor_type == 0x2b &&   /* Version change */
2170c18ec02fSPetter Reinholdtsen 				evt->sel_type.standard_type.event_data[0] == 0xC1	 /* Data in Data 2 */
2171c18ec02fSPetter Reinholdtsen 			   )
2172c18ec02fSPetter Reinholdtsen 
2173c18ec02fSPetter Reinholdtsen 		{
2174c18ec02fSPetter Reinholdtsen 			//evt->sel_type.standard_type.event_data[1]
2175c18ec02fSPetter Reinholdtsen 		}
2176c18ec02fSPetter Reinholdtsen 		else
2177c18ec02fSPetter Reinholdtsen 		{
2178c18ec02fSPetter Reinholdtsen 			/* FIXME : Add sensor specific discrete types */
2179c18ec02fSPetter Reinholdtsen 			printf(" Event Interpretation  : Missing\n");
2180c18ec02fSPetter Reinholdtsen 		}
2181c18ec02fSPetter Reinholdtsen 	} else if (evt->sel_type.standard_type.event_type >= 0x70 && evt->sel_type.standard_type.event_type <= 0x7f) {
2182c18ec02fSPetter Reinholdtsen 		/* OEM */
2183c18ec02fSPetter Reinholdtsen 	} else {
2184c18ec02fSPetter Reinholdtsen 		printf(" Event Data            : %02x%02x%02x\n",
2185c18ec02fSPetter Reinholdtsen 		       evt->sel_type.standard_type.event_data[0], evt->sel_type.standard_type.event_data[1], evt->sel_type.standard_type.event_data[2]);
2186c18ec02fSPetter Reinholdtsen 	}
2187c18ec02fSPetter Reinholdtsen 
2188c18ec02fSPetter Reinholdtsen         ipmi_get_event_desc(intf, evt, &description);
2189c18ec02fSPetter Reinholdtsen 	printf(" Description           : %s\n",
2190c18ec02fSPetter Reinholdtsen                description ? description : "");
2191c18ec02fSPetter Reinholdtsen         free(description);
2192c18ec02fSPetter Reinholdtsen 				description = NULL;
2193c18ec02fSPetter Reinholdtsen 
2194c18ec02fSPetter Reinholdtsen 	printf("\n");
2195c18ec02fSPetter Reinholdtsen }
2196c18ec02fSPetter Reinholdtsen 
2197c18ec02fSPetter Reinholdtsen static int
__ipmi_sel_savelist_entries(struct ipmi_intf * intf,int count,const char * savefile,int binary)2198c18ec02fSPetter Reinholdtsen __ipmi_sel_savelist_entries(struct ipmi_intf * intf, int count, const char * savefile,
2199c18ec02fSPetter Reinholdtsen 							int binary)
2200c18ec02fSPetter Reinholdtsen {
2201c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
2202c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
2203c18ec02fSPetter Reinholdtsen 	uint16_t next_id = 0, curr_id = 0;
2204c18ec02fSPetter Reinholdtsen 	struct sel_event_record evt;
2205c18ec02fSPetter Reinholdtsen 	int n=0;
2206c18ec02fSPetter Reinholdtsen 	FILE * fp = NULL;
2207c18ec02fSPetter Reinholdtsen 
2208c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
2209c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
2210c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_CMD_GET_SEL_INFO;
2211c18ec02fSPetter Reinholdtsen 
2212c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
2213c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
2214c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get SEL Info command failed");
2215c18ec02fSPetter Reinholdtsen 		return -1;
2216c18ec02fSPetter Reinholdtsen 	}
2217c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
2218c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get SEL Info command failed: %s",
2219c18ec02fSPetter Reinholdtsen 		       val2str(rsp->ccode, completion_code_vals));
2220c18ec02fSPetter Reinholdtsen 		return -1;
2221c18ec02fSPetter Reinholdtsen 	}
2222c18ec02fSPetter Reinholdtsen 	if (verbose > 2)
2223c18ec02fSPetter Reinholdtsen 		printbuf(rsp->data, rsp->data_len, "sel_info");
2224c18ec02fSPetter Reinholdtsen 
2225c18ec02fSPetter Reinholdtsen 	if (rsp->data[1] == 0 && rsp->data[2] == 0) {
2226c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "SEL has no entries");
2227c18ec02fSPetter Reinholdtsen 		return 0;
2228c18ec02fSPetter Reinholdtsen 	}
2229c18ec02fSPetter Reinholdtsen 
2230c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
2231c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
2232c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_CMD_RESERVE_SEL;
2233c18ec02fSPetter Reinholdtsen 
2234c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
2235c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
2236c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Reserve SEL command failed");
2237c18ec02fSPetter Reinholdtsen 		return -1;
2238c18ec02fSPetter Reinholdtsen 	}
2239c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
2240c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Reserve SEL command failed: %s",
2241c18ec02fSPetter Reinholdtsen 		       val2str(rsp->ccode, completion_code_vals));
2242c18ec02fSPetter Reinholdtsen 		return -1;
2243c18ec02fSPetter Reinholdtsen 	}
2244c18ec02fSPetter Reinholdtsen 
2245c18ec02fSPetter Reinholdtsen 	if (count < 0) {
2246c18ec02fSPetter Reinholdtsen 		/** Show only the most recent 'count' records. */
2247c18ec02fSPetter Reinholdtsen 		int delta;
2248c18ec02fSPetter Reinholdtsen 		uint16_t entries;
2249c18ec02fSPetter Reinholdtsen 
2250c18ec02fSPetter Reinholdtsen 		req.msg.cmd = IPMI_CMD_GET_SEL_INFO;
2251c18ec02fSPetter Reinholdtsen 		rsp = intf->sendrecv(intf, &req);
2252c18ec02fSPetter Reinholdtsen 		if (rsp == NULL) {
2253c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Get SEL Info command failed");
2254c18ec02fSPetter Reinholdtsen 			return -1;
2255c18ec02fSPetter Reinholdtsen 		}
2256c18ec02fSPetter Reinholdtsen 		if (rsp->ccode > 0) {
2257c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Get SEL Info command failed: %s",
2258c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
2259c18ec02fSPetter Reinholdtsen 			return -1;
2260c18ec02fSPetter Reinholdtsen 		}
2261c18ec02fSPetter Reinholdtsen 		entries = buf2short(rsp->data + 1);
2262c18ec02fSPetter Reinholdtsen 		if (-count > entries)
2263c18ec02fSPetter Reinholdtsen 			count = -entries;
2264c18ec02fSPetter Reinholdtsen 
2265c18ec02fSPetter Reinholdtsen 		/* Get first record. */
2266c18ec02fSPetter Reinholdtsen 		next_id = ipmi_sel_get_std_entry(intf, 0, &evt);
2267c18ec02fSPetter Reinholdtsen 
2268c18ec02fSPetter Reinholdtsen 		delta = next_id - evt.record_id;
2269c18ec02fSPetter Reinholdtsen 
2270c18ec02fSPetter Reinholdtsen 		/* Get last record. */
2271c18ec02fSPetter Reinholdtsen 		next_id = ipmi_sel_get_std_entry(intf, 0xffff, &evt);
2272c18ec02fSPetter Reinholdtsen 
2273c18ec02fSPetter Reinholdtsen 		next_id = evt.record_id + count * delta + delta;
2274c18ec02fSPetter Reinholdtsen 	}
2275c18ec02fSPetter Reinholdtsen 
2276c18ec02fSPetter Reinholdtsen 	if (savefile != NULL) {
2277c18ec02fSPetter Reinholdtsen 		fp = ipmi_open_file_write(savefile);
2278c18ec02fSPetter Reinholdtsen 	}
2279c18ec02fSPetter Reinholdtsen 
2280c18ec02fSPetter Reinholdtsen 	while (next_id != 0xffff) {
2281c18ec02fSPetter Reinholdtsen 		curr_id = next_id;
2282c18ec02fSPetter Reinholdtsen 		lprintf(LOG_DEBUG, "SEL Next ID: %04x", curr_id);
2283c18ec02fSPetter Reinholdtsen 
2284c18ec02fSPetter Reinholdtsen 		next_id = ipmi_sel_get_std_entry(intf, curr_id, &evt);
2285c18ec02fSPetter Reinholdtsen 		if (next_id == 0) {
2286c18ec02fSPetter Reinholdtsen 			/*
2287c18ec02fSPetter Reinholdtsen 			 * usually next_id of zero means end but
2288c18ec02fSPetter Reinholdtsen 			 * retry because some hardware has quirks
2289c18ec02fSPetter Reinholdtsen 			 * and will return 0 randomly.
2290c18ec02fSPetter Reinholdtsen 			 */
2291c18ec02fSPetter Reinholdtsen 			next_id = ipmi_sel_get_std_entry(intf, curr_id, &evt);
2292c18ec02fSPetter Reinholdtsen 			if (next_id == 0)
2293c18ec02fSPetter Reinholdtsen 				break;
2294c18ec02fSPetter Reinholdtsen 		}
2295c18ec02fSPetter Reinholdtsen 
2296c18ec02fSPetter Reinholdtsen 		if (verbose)
2297c18ec02fSPetter Reinholdtsen 			ipmi_sel_print_std_entry_verbose(intf, &evt);
2298c18ec02fSPetter Reinholdtsen 		else
2299c18ec02fSPetter Reinholdtsen 			ipmi_sel_print_std_entry(intf, &evt);
2300c18ec02fSPetter Reinholdtsen 
2301c18ec02fSPetter Reinholdtsen 		if (fp != NULL) {
2302c18ec02fSPetter Reinholdtsen 			if (binary)
2303c18ec02fSPetter Reinholdtsen 				fwrite(&evt, 1, 16, fp);
2304c18ec02fSPetter Reinholdtsen 			else
2305c18ec02fSPetter Reinholdtsen 				ipmi_sel_print_event_file(intf, &evt, fp);
2306c18ec02fSPetter Reinholdtsen 		}
2307c18ec02fSPetter Reinholdtsen 
2308c18ec02fSPetter Reinholdtsen 		if (++n == count) {
2309c18ec02fSPetter Reinholdtsen 			break;
2310c18ec02fSPetter Reinholdtsen 		}
2311c18ec02fSPetter Reinholdtsen 	}
2312c18ec02fSPetter Reinholdtsen 
2313c18ec02fSPetter Reinholdtsen 	if (fp != NULL)
2314c18ec02fSPetter Reinholdtsen 		fclose(fp);
2315c18ec02fSPetter Reinholdtsen 
2316c18ec02fSPetter Reinholdtsen 	return 0;
2317c18ec02fSPetter Reinholdtsen }
2318c18ec02fSPetter Reinholdtsen 
2319c18ec02fSPetter Reinholdtsen static int
ipmi_sel_list_entries(struct ipmi_intf * intf,int count)2320c18ec02fSPetter Reinholdtsen ipmi_sel_list_entries(struct ipmi_intf * intf, int count)
2321c18ec02fSPetter Reinholdtsen {
2322c18ec02fSPetter Reinholdtsen 	return __ipmi_sel_savelist_entries(intf, count, NULL, 0);
2323c18ec02fSPetter Reinholdtsen }
2324c18ec02fSPetter Reinholdtsen 
2325c18ec02fSPetter Reinholdtsen static int
ipmi_sel_save_entries(struct ipmi_intf * intf,int count,const char * savefile)2326c18ec02fSPetter Reinholdtsen ipmi_sel_save_entries(struct ipmi_intf * intf, int count, const char * savefile)
2327c18ec02fSPetter Reinholdtsen {
2328c18ec02fSPetter Reinholdtsen 	return __ipmi_sel_savelist_entries(intf, count, savefile, 0);
2329c18ec02fSPetter Reinholdtsen }
2330c18ec02fSPetter Reinholdtsen 
2331c18ec02fSPetter Reinholdtsen /*
2332c18ec02fSPetter Reinholdtsen  * ipmi_sel_interpret
2333c18ec02fSPetter Reinholdtsen  *
2334c18ec02fSPetter Reinholdtsen  * return 0 on success,
2335c18ec02fSPetter Reinholdtsen  *        -1 on error
2336c18ec02fSPetter Reinholdtsen  */
2337c18ec02fSPetter Reinholdtsen static int
ipmi_sel_interpret(struct ipmi_intf * intf,unsigned long iana,const char * readfile,const char * format)2338c18ec02fSPetter Reinholdtsen ipmi_sel_interpret(struct ipmi_intf *intf, unsigned long iana,
2339c18ec02fSPetter Reinholdtsen 		const char *readfile, const char *format)
2340c18ec02fSPetter Reinholdtsen {
2341c18ec02fSPetter Reinholdtsen 	FILE *fp = 0;
2342c18ec02fSPetter Reinholdtsen 	struct sel_event_record evt;
2343c18ec02fSPetter Reinholdtsen 	char *buffer = NULL;
2344c18ec02fSPetter Reinholdtsen 	char *cursor = NULL;
2345c18ec02fSPetter Reinholdtsen 	int status = 0;
2346c18ec02fSPetter Reinholdtsen 	/* since the interface is not used, iana is taken from
2347c18ec02fSPetter Reinholdtsen 	 * the command line
2348c18ec02fSPetter Reinholdtsen 	 */
2349c18ec02fSPetter Reinholdtsen 	sel_iana = iana;
2350c18ec02fSPetter Reinholdtsen 	if (strncmp("pps", format, 3) == 0) {
2351c18ec02fSPetter Reinholdtsen 		/* Parser for the following format */
2352c18ec02fSPetter Reinholdtsen 		/* 0x001F: Event: at Mar 27 06:41:10 2007;from:(0x9a,0,7);
2353c18ec02fSPetter Reinholdtsen 		 * sensor:(0xc3,119); event:0x6f(asserted): 0xA3 0x00 0x88
2354c18ec02fSPetter Reinholdtsen 		 * commonly found in PPS shelf managers
2355c18ec02fSPetter Reinholdtsen 		 * Supports a tweak for hotswap events that are already interpreted.
2356c18ec02fSPetter Reinholdtsen 		 */
2357c18ec02fSPetter Reinholdtsen 		fp = ipmi_open_file(readfile, 0);
2358c18ec02fSPetter Reinholdtsen 		if (fp == NULL) {
2359c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Failed to open file '%s' for reading.",
2360c18ec02fSPetter Reinholdtsen 					readfile);
2361c18ec02fSPetter Reinholdtsen 			return (-1);
2362c18ec02fSPetter Reinholdtsen 		}
2363c18ec02fSPetter Reinholdtsen 		buffer = (char *)malloc((size_t)256);
2364c18ec02fSPetter Reinholdtsen 		if (buffer == NULL) {
2365c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "ipmitool: malloc failure");
2366c18ec02fSPetter Reinholdtsen 			fclose(fp);
2367c18ec02fSPetter Reinholdtsen 			return (-1);
2368c18ec02fSPetter Reinholdtsen 		}
2369c18ec02fSPetter Reinholdtsen 		do {
2370c18ec02fSPetter Reinholdtsen 			/* Only allow complete lines to be parsed,
2371c18ec02fSPetter Reinholdtsen 			 * hardcoded maximum line length
2372c18ec02fSPetter Reinholdtsen 			 */
2373c18ec02fSPetter Reinholdtsen 			if (fgets(buffer, 256, fp) == NULL) {
2374c18ec02fSPetter Reinholdtsen 				status = (-1);
2375c18ec02fSPetter Reinholdtsen 				break;
2376c18ec02fSPetter Reinholdtsen 			}
2377c18ec02fSPetter Reinholdtsen 			if (strlen(buffer) > 255) {
2378c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "ipmitool: invalid entry found in file.");
2379c18ec02fSPetter Reinholdtsen 				continue;
2380c18ec02fSPetter Reinholdtsen 			}
2381c18ec02fSPetter Reinholdtsen 			cursor = buffer;
2382c18ec02fSPetter Reinholdtsen 			/* assume normal "System" event */
2383c18ec02fSPetter Reinholdtsen 			evt.record_type = 2;
2384c18ec02fSPetter Reinholdtsen 			errno = 0;
2385c18ec02fSPetter Reinholdtsen 			evt.record_id = strtol((const char *)cursor, (char **)NULL, 16);
2386c18ec02fSPetter Reinholdtsen 			if (errno != 0) {
2387c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Invalid record ID.");
2388c18ec02fSPetter Reinholdtsen 				status = (-1);
2389c18ec02fSPetter Reinholdtsen 				break;
2390c18ec02fSPetter Reinholdtsen 			}
2391c18ec02fSPetter Reinholdtsen 			evt.sel_type.standard_type.evm_rev = 4;
2392c18ec02fSPetter Reinholdtsen 
2393c18ec02fSPetter Reinholdtsen 			/* FIXME: convert*/
2394c18ec02fSPetter Reinholdtsen 			evt.sel_type.standard_type.timestamp;
2395c18ec02fSPetter Reinholdtsen 
2396c18ec02fSPetter Reinholdtsen 			/* skip timestamp */
2397c18ec02fSPetter Reinholdtsen 			cursor = index((const char *)cursor, ';');
2398c18ec02fSPetter Reinholdtsen 			cursor++;
2399c18ec02fSPetter Reinholdtsen 
2400c18ec02fSPetter Reinholdtsen 			/* FIXME: parse originator */
2401c18ec02fSPetter Reinholdtsen 			evt.sel_type.standard_type.gen_id = 0x0020;
2402c18ec02fSPetter Reinholdtsen 
2403c18ec02fSPetter Reinholdtsen 			/* skip  originator info */
2404c18ec02fSPetter Reinholdtsen 			cursor = index((const char *)cursor, ';');
2405c18ec02fSPetter Reinholdtsen 			cursor++;
2406c18ec02fSPetter Reinholdtsen 
2407c18ec02fSPetter Reinholdtsen 			/* Get sensor type */
2408c18ec02fSPetter Reinholdtsen 			cursor = index((const char *)cursor, '(');
2409c18ec02fSPetter Reinholdtsen 			cursor++;
2410c18ec02fSPetter Reinholdtsen 
2411c18ec02fSPetter Reinholdtsen 			errno = 0;
2412c18ec02fSPetter Reinholdtsen 			evt.sel_type.standard_type.sensor_type =
2413c18ec02fSPetter Reinholdtsen 				strtol((const char *)cursor, (char **)NULL, 16);
2414c18ec02fSPetter Reinholdtsen 			if (errno != 0) {
2415c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Invalid Sensor Type.");
2416c18ec02fSPetter Reinholdtsen 				status = (-1);
2417c18ec02fSPetter Reinholdtsen 				break;
2418c18ec02fSPetter Reinholdtsen 			}
2419c18ec02fSPetter Reinholdtsen 			cursor = index((const char *)cursor, ',');
2420c18ec02fSPetter Reinholdtsen 			cursor++;
2421c18ec02fSPetter Reinholdtsen 
2422c18ec02fSPetter Reinholdtsen 			errno = 0;
2423c18ec02fSPetter Reinholdtsen 			evt.sel_type.standard_type.sensor_num =
2424c18ec02fSPetter Reinholdtsen 				strtol((const char *)cursor, (char **)NULL, 10);
2425c18ec02fSPetter Reinholdtsen 			if (errno != 0) {
2426c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Invalid Sensor Number.");
2427c18ec02fSPetter Reinholdtsen 				status = (-1);
2428c18ec02fSPetter Reinholdtsen 				break;
2429c18ec02fSPetter Reinholdtsen 			}
2430c18ec02fSPetter Reinholdtsen 
2431c18ec02fSPetter Reinholdtsen 			/* skip  to event type  info */
2432c18ec02fSPetter Reinholdtsen 			cursor = index((const char *)cursor, ':');
2433c18ec02fSPetter Reinholdtsen 			cursor++;
2434c18ec02fSPetter Reinholdtsen 
2435c18ec02fSPetter Reinholdtsen 			errno = 0;
2436c18ec02fSPetter Reinholdtsen 			evt.sel_type.standard_type.event_type=
2437c18ec02fSPetter Reinholdtsen 				strtol((const char *)cursor, (char **)NULL, 16);
2438c18ec02fSPetter Reinholdtsen 			if (errno != 0) {
2439c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Invalid Event Type.");
2440c18ec02fSPetter Reinholdtsen 				status = (-1);
2441c18ec02fSPetter Reinholdtsen 				break;
2442c18ec02fSPetter Reinholdtsen 			}
2443c18ec02fSPetter Reinholdtsen 
2444c18ec02fSPetter Reinholdtsen 			/* skip  to event dir  info */
2445c18ec02fSPetter Reinholdtsen 			cursor = index((const char *)cursor, '(');
2446c18ec02fSPetter Reinholdtsen 			cursor++;
2447c18ec02fSPetter Reinholdtsen 			if (*cursor == 'a') {
2448c18ec02fSPetter Reinholdtsen 				evt.sel_type.standard_type.event_dir = 0;
2449c18ec02fSPetter Reinholdtsen 			} else {
2450c18ec02fSPetter Reinholdtsen 				evt.sel_type.standard_type.event_dir = 1;
2451c18ec02fSPetter Reinholdtsen 			}
2452c18ec02fSPetter Reinholdtsen 			/* skip  to data info */
2453c18ec02fSPetter Reinholdtsen 			cursor = index((const char *)cursor, ' ');
2454c18ec02fSPetter Reinholdtsen 			cursor++;
2455c18ec02fSPetter Reinholdtsen 
2456c18ec02fSPetter Reinholdtsen 			if (evt.sel_type.standard_type.sensor_type == 0xF0) {
2457c18ec02fSPetter Reinholdtsen 				/* got to FRU id */
2458c18ec02fSPetter Reinholdtsen 				while (!isdigit(*cursor)) {
2459c18ec02fSPetter Reinholdtsen 					cursor++;
2460c18ec02fSPetter Reinholdtsen 				}
2461c18ec02fSPetter Reinholdtsen 				/* store FRUid */
2462c18ec02fSPetter Reinholdtsen 				errno = 0;
2463c18ec02fSPetter Reinholdtsen 				evt.sel_type.standard_type.event_data[2] =
2464c18ec02fSPetter Reinholdtsen 					strtol(cursor, (char **)NULL, 10);
2465c18ec02fSPetter Reinholdtsen 				if (errno != 0) {
2466c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "Invalid Event Data#2.");
2467c18ec02fSPetter Reinholdtsen 					status = (-1);
2468c18ec02fSPetter Reinholdtsen 					break;
2469c18ec02fSPetter Reinholdtsen 				}
2470c18ec02fSPetter Reinholdtsen 
2471c18ec02fSPetter Reinholdtsen 				/* Get to previous state */
2472c18ec02fSPetter Reinholdtsen 				cursor = index((const char *)cursor, 'M');
2473c18ec02fSPetter Reinholdtsen 				cursor++;
2474c18ec02fSPetter Reinholdtsen 
2475c18ec02fSPetter Reinholdtsen 				/* Set previous state */
2476c18ec02fSPetter Reinholdtsen 				errno = 0;
2477c18ec02fSPetter Reinholdtsen 				evt.sel_type.standard_type.event_data[1] =
2478c18ec02fSPetter Reinholdtsen 					strtol(cursor, (char **)NULL, 10);
2479c18ec02fSPetter Reinholdtsen 				if (errno != 0) {
2480c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "Invalid Event Data#1.");
2481c18ec02fSPetter Reinholdtsen 					status = (-1);
2482c18ec02fSPetter Reinholdtsen 					break;
2483c18ec02fSPetter Reinholdtsen 				}
2484c18ec02fSPetter Reinholdtsen 
2485c18ec02fSPetter Reinholdtsen 				/* Get to current state */
2486c18ec02fSPetter Reinholdtsen 				cursor = index((const char *)cursor, 'M');
2487c18ec02fSPetter Reinholdtsen 				cursor++;
2488c18ec02fSPetter Reinholdtsen 
2489c18ec02fSPetter Reinholdtsen 				/* Set current state */
2490c18ec02fSPetter Reinholdtsen 				errno = 0;
2491c18ec02fSPetter Reinholdtsen 				evt.sel_type.standard_type.event_data[0] =
2492c18ec02fSPetter Reinholdtsen 					0xA0 | strtol(cursor, (char **)NULL, 10);
2493c18ec02fSPetter Reinholdtsen 				if (errno != 0) {
2494c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "Invalid Event Data#0.");
2495c18ec02fSPetter Reinholdtsen 					status = (-1);
2496c18ec02fSPetter Reinholdtsen 					break;
2497c18ec02fSPetter Reinholdtsen 				}
2498c18ec02fSPetter Reinholdtsen 
2499c18ec02fSPetter Reinholdtsen 				/* skip  to cause */
2500c18ec02fSPetter Reinholdtsen 				cursor = index((const char *)cursor, '=');
2501c18ec02fSPetter Reinholdtsen 				cursor++;
2502c18ec02fSPetter Reinholdtsen 				errno = 0;
2503c18ec02fSPetter Reinholdtsen 				evt.sel_type.standard_type.event_data[1] |=
2504c18ec02fSPetter Reinholdtsen 					(strtol(cursor, (char **)NULL, 16)) << 4;
2505c18ec02fSPetter Reinholdtsen 				if (errno != 0) {
2506c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "Invalid Event Data#1.");
2507c18ec02fSPetter Reinholdtsen 					status = (-1);
2508c18ec02fSPetter Reinholdtsen 					break;
2509c18ec02fSPetter Reinholdtsen 				}
2510c18ec02fSPetter Reinholdtsen 			} else if (*cursor == '0') {
2511c18ec02fSPetter Reinholdtsen 				errno = 0;
2512c18ec02fSPetter Reinholdtsen 				evt.sel_type.standard_type.event_data[0] =
2513c18ec02fSPetter Reinholdtsen 					strtol((const char *)cursor, (char **)NULL, 16);
2514c18ec02fSPetter Reinholdtsen 				if (errno != 0) {
2515c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "Invalid Event Data#0.");
2516c18ec02fSPetter Reinholdtsen 					status = (-1);
2517c18ec02fSPetter Reinholdtsen 					break;
2518c18ec02fSPetter Reinholdtsen 				}
2519c18ec02fSPetter Reinholdtsen 				cursor = index((const char *)cursor, ' ');
2520c18ec02fSPetter Reinholdtsen 				cursor++;
2521c18ec02fSPetter Reinholdtsen 
2522c18ec02fSPetter Reinholdtsen 				errno = 0;
2523c18ec02fSPetter Reinholdtsen 				evt.sel_type.standard_type.event_data[1] =
2524c18ec02fSPetter Reinholdtsen 					strtol((const char *)cursor, (char **)NULL, 16);
2525c18ec02fSPetter Reinholdtsen 				if (errno != 0) {
2526c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "Invalid Event Data#1.");
2527c18ec02fSPetter Reinholdtsen 					status = (-1);
2528c18ec02fSPetter Reinholdtsen 					break;
2529c18ec02fSPetter Reinholdtsen 				}
2530c18ec02fSPetter Reinholdtsen 
2531c18ec02fSPetter Reinholdtsen 				cursor = index((const char *)cursor, ' ');
2532c18ec02fSPetter Reinholdtsen 				cursor++;
2533c18ec02fSPetter Reinholdtsen 
2534c18ec02fSPetter Reinholdtsen 				errno = 0;
2535c18ec02fSPetter Reinholdtsen 				evt.sel_type.standard_type.event_data[2] =
2536c18ec02fSPetter Reinholdtsen 					strtol((const char *)cursor, (char **)NULL, 16);
2537c18ec02fSPetter Reinholdtsen 				if (errno != 0) {
2538c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "Invalid Event Data#2.");
2539c18ec02fSPetter Reinholdtsen 					status = (-1);
2540c18ec02fSPetter Reinholdtsen 					break;
2541c18ec02fSPetter Reinholdtsen 				}
2542c18ec02fSPetter Reinholdtsen 			} else {
2543c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "ipmitool: can't guess format.");
2544c18ec02fSPetter Reinholdtsen 			}
2545c18ec02fSPetter Reinholdtsen 			/* parse the PPS line into a sel_event_record */
2546c18ec02fSPetter Reinholdtsen 			if (verbose) {
2547c18ec02fSPetter Reinholdtsen 				ipmi_sel_print_std_entry_verbose(intf, &evt);
2548c18ec02fSPetter Reinholdtsen 			} else {
2549c18ec02fSPetter Reinholdtsen 				ipmi_sel_print_std_entry(intf, &evt);
2550c18ec02fSPetter Reinholdtsen 			}
2551c18ec02fSPetter Reinholdtsen 			cursor = NULL;
2552c18ec02fSPetter Reinholdtsen 		} while (status == 0); /* until file is completely read */
2553c18ec02fSPetter Reinholdtsen 		cursor = NULL;
2554c18ec02fSPetter Reinholdtsen 		free(buffer);
2555c18ec02fSPetter Reinholdtsen 		buffer = NULL;
2556c18ec02fSPetter Reinholdtsen 		fclose(fp);
2557c18ec02fSPetter Reinholdtsen 	} else {
2558c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Given format '%s' is unknown.", format);
2559c18ec02fSPetter Reinholdtsen 		status = (-1);
2560c18ec02fSPetter Reinholdtsen 	}
2561c18ec02fSPetter Reinholdtsen 	return status;
2562c18ec02fSPetter Reinholdtsen }
2563c18ec02fSPetter Reinholdtsen 
2564c18ec02fSPetter Reinholdtsen 
2565c18ec02fSPetter Reinholdtsen static int
ipmi_sel_writeraw(struct ipmi_intf * intf,const char * savefile)2566c18ec02fSPetter Reinholdtsen ipmi_sel_writeraw(struct ipmi_intf * intf, const char * savefile)
2567c18ec02fSPetter Reinholdtsen {
2568c18ec02fSPetter Reinholdtsen     return __ipmi_sel_savelist_entries(intf, 0, savefile, 1);
2569c18ec02fSPetter Reinholdtsen }
2570c18ec02fSPetter Reinholdtsen 
2571c18ec02fSPetter Reinholdtsen 
2572c18ec02fSPetter Reinholdtsen static int
ipmi_sel_readraw(struct ipmi_intf * intf,const char * inputfile)2573c18ec02fSPetter Reinholdtsen ipmi_sel_readraw(struct ipmi_intf * intf, const char * inputfile)
2574c18ec02fSPetter Reinholdtsen {
2575c18ec02fSPetter Reinholdtsen 	struct sel_event_record evt;
2576c18ec02fSPetter Reinholdtsen 	int ret = 0;
2577c18ec02fSPetter Reinholdtsen 	FILE* fp = 0;
2578c18ec02fSPetter Reinholdtsen 
2579c18ec02fSPetter Reinholdtsen 	fp = ipmi_open_file(inputfile, 0);
2580c18ec02fSPetter Reinholdtsen 	if (fp)
2581c18ec02fSPetter Reinholdtsen 	{
2582c18ec02fSPetter Reinholdtsen 		size_t bytesRead;
2583c18ec02fSPetter Reinholdtsen 
2584c18ec02fSPetter Reinholdtsen 		do {
2585c18ec02fSPetter Reinholdtsen 			if ((bytesRead = fread(&evt, 1, 16, fp)) == 16)
2586c18ec02fSPetter Reinholdtsen 			{
2587c18ec02fSPetter Reinholdtsen 				if (verbose)
2588c18ec02fSPetter Reinholdtsen 					ipmi_sel_print_std_entry_verbose(intf, &evt);
2589c18ec02fSPetter Reinholdtsen 				else
2590c18ec02fSPetter Reinholdtsen 					ipmi_sel_print_std_entry(intf, &evt);
2591c18ec02fSPetter Reinholdtsen 			}
2592c18ec02fSPetter Reinholdtsen 			else
2593c18ec02fSPetter Reinholdtsen 			{
2594c18ec02fSPetter Reinholdtsen 				if (bytesRead != 0)
2595c18ec02fSPetter Reinholdtsen 				{
2596c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "ipmitool: incomplete record found in file.");
2597c18ec02fSPetter Reinholdtsen 					ret = -1;
2598c18ec02fSPetter Reinholdtsen 				}
2599c18ec02fSPetter Reinholdtsen 
2600c18ec02fSPetter Reinholdtsen 				break;
2601c18ec02fSPetter Reinholdtsen 			}
2602c18ec02fSPetter Reinholdtsen 
2603c18ec02fSPetter Reinholdtsen 		} while (1);
2604c18ec02fSPetter Reinholdtsen 		fclose(fp);
2605c18ec02fSPetter Reinholdtsen 	}
2606c18ec02fSPetter Reinholdtsen 	else
2607c18ec02fSPetter Reinholdtsen 	{
2608c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "ipmitool: could not open input file.");
2609c18ec02fSPetter Reinholdtsen 		ret = -1;
2610c18ec02fSPetter Reinholdtsen 	}
2611c18ec02fSPetter Reinholdtsen 	return ret;
2612c18ec02fSPetter Reinholdtsen }
2613c18ec02fSPetter Reinholdtsen 
2614c18ec02fSPetter Reinholdtsen 
2615c18ec02fSPetter Reinholdtsen 
2616c18ec02fSPetter Reinholdtsen static uint16_t
ipmi_sel_reserve(struct ipmi_intf * intf)2617c18ec02fSPetter Reinholdtsen ipmi_sel_reserve(struct ipmi_intf * intf)
2618c18ec02fSPetter Reinholdtsen {
2619c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
2620c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
2621c18ec02fSPetter Reinholdtsen 
2622c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
2623c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
2624c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_CMD_RESERVE_SEL;
2625c18ec02fSPetter Reinholdtsen 
2626c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
2627c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
2628c18ec02fSPetter Reinholdtsen 		lprintf(LOG_WARN, "Unable to reserve SEL");
2629c18ec02fSPetter Reinholdtsen 		return 0;
2630c18ec02fSPetter Reinholdtsen 	}
2631c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
2632c18ec02fSPetter Reinholdtsen 		printf("Unable to reserve SEL: %s",
2633c18ec02fSPetter Reinholdtsen 		       val2str(rsp->ccode, completion_code_vals));
2634c18ec02fSPetter Reinholdtsen 		return 0;
2635c18ec02fSPetter Reinholdtsen 	}
2636c18ec02fSPetter Reinholdtsen 
2637c18ec02fSPetter Reinholdtsen 	return (rsp->data[0] | (rsp->data[1] << 8));
2638c18ec02fSPetter Reinholdtsen }
2639c18ec02fSPetter Reinholdtsen 
2640c18ec02fSPetter Reinholdtsen 
2641c18ec02fSPetter Reinholdtsen 
2642c18ec02fSPetter Reinholdtsen /*
2643c18ec02fSPetter Reinholdtsen  * ipmi_sel_get_time
2644c18ec02fSPetter Reinholdtsen  *
2645c18ec02fSPetter Reinholdtsen  * return 0 on success,
2646c18ec02fSPetter Reinholdtsen  *        -1 on error
2647c18ec02fSPetter Reinholdtsen  */
2648c18ec02fSPetter Reinholdtsen static int
ipmi_sel_get_time(struct ipmi_intf * intf)2649c18ec02fSPetter Reinholdtsen ipmi_sel_get_time(struct ipmi_intf * intf)
2650c18ec02fSPetter Reinholdtsen {
2651c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
2652c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
2653c18ec02fSPetter Reinholdtsen 	static char tbuf[40];
2654c18ec02fSPetter Reinholdtsen 	uint32_t timei;
2655c18ec02fSPetter Reinholdtsen 	time_t time;
2656c18ec02fSPetter Reinholdtsen 
2657c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
2658c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
2659c18ec02fSPetter Reinholdtsen 	req.msg.cmd   = IPMI_GET_SEL_TIME;
2660c18ec02fSPetter Reinholdtsen 
2661c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
2662c18ec02fSPetter Reinholdtsen 
2663c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
2664c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get SEL Time command failed");
2665c18ec02fSPetter Reinholdtsen 		return -1;
2666c18ec02fSPetter Reinholdtsen 	}
2667c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
2668c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get SEL Time command failed: %s",
2669c18ec02fSPetter Reinholdtsen 			val2str(rsp->ccode, completion_code_vals));
2670c18ec02fSPetter Reinholdtsen 		return -1;
2671c18ec02fSPetter Reinholdtsen 	}
2672c18ec02fSPetter Reinholdtsen 	if (rsp->data_len != 4) {
2673c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get SEL Time command failed: "
2674c18ec02fSPetter Reinholdtsen 			"Invalid data length %d", rsp->data_len);
2675c18ec02fSPetter Reinholdtsen 		return -1;
2676c18ec02fSPetter Reinholdtsen 	}
2677c18ec02fSPetter Reinholdtsen 
2678c18ec02fSPetter Reinholdtsen 	memcpy(&timei, rsp->data, 4);
2679c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN
2680c18ec02fSPetter Reinholdtsen 	time = (time_t)(BSWAP_32(timei));
2681c18ec02fSPetter Reinholdtsen #else
2682c18ec02fSPetter Reinholdtsen 	time = (time_t)timei;
2683c18ec02fSPetter Reinholdtsen #endif
2684c18ec02fSPetter Reinholdtsen 
2685c18ec02fSPetter Reinholdtsen 	strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", gmtime(&time));
2686c18ec02fSPetter Reinholdtsen 	printf("%s\n", tbuf);
2687c18ec02fSPetter Reinholdtsen 
2688c18ec02fSPetter Reinholdtsen 	return 0;
2689c18ec02fSPetter Reinholdtsen }
2690c18ec02fSPetter Reinholdtsen 
2691c18ec02fSPetter Reinholdtsen 
2692c18ec02fSPetter Reinholdtsen 
2693c18ec02fSPetter Reinholdtsen /*
2694c18ec02fSPetter Reinholdtsen  * ipmi_sel_set_time
2695c18ec02fSPetter Reinholdtsen  *
2696c18ec02fSPetter Reinholdtsen  * return 0 on success,
2697c18ec02fSPetter Reinholdtsen  *        -1 on error
2698c18ec02fSPetter Reinholdtsen  */
2699c18ec02fSPetter Reinholdtsen static int
ipmi_sel_set_time(struct ipmi_intf * intf,const char * time_string)2700c18ec02fSPetter Reinholdtsen ipmi_sel_set_time(struct ipmi_intf * intf, const char * time_string)
2701c18ec02fSPetter Reinholdtsen {
2702c18ec02fSPetter Reinholdtsen 	struct ipmi_rs     * rsp;
2703c18ec02fSPetter Reinholdtsen 	struct ipmi_rq       req;
2704c18ec02fSPetter Reinholdtsen 	struct tm            tm = {0};
2705c18ec02fSPetter Reinholdtsen 	time_t               t;
2706c18ec02fSPetter Reinholdtsen 	uint32_t	     timei;
2707c18ec02fSPetter Reinholdtsen 	const char *         time_format = "%m/%d/%Y %H:%M:%S";
2708c18ec02fSPetter Reinholdtsen 
2709c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
2710c18ec02fSPetter Reinholdtsen 	req.msg.netfn    = IPMI_NETFN_STORAGE;
2711c18ec02fSPetter Reinholdtsen 	req.msg.cmd      = IPMI_SET_SEL_TIME;
2712c18ec02fSPetter Reinholdtsen 
2713c18ec02fSPetter Reinholdtsen 	/* See if user requested set to current client system time */
2714c18ec02fSPetter Reinholdtsen 	if (strncasecmp(time_string, "now", 3) == 0) {
2715c18ec02fSPetter Reinholdtsen 		t = time(NULL);
2716c18ec02fSPetter Reinholdtsen 	}
2717c18ec02fSPetter Reinholdtsen 	else {
2718c18ec02fSPetter Reinholdtsen 		/* Now how do we get our time_t from our ascii version? */
2719c18ec02fSPetter Reinholdtsen 		if (strptime(time_string, time_format, &tm) == 0) {
2720c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Specified time could not be parsed");
2721c18ec02fSPetter Reinholdtsen 			return -1;
2722c18ec02fSPetter Reinholdtsen 		}
2723c18ec02fSPetter Reinholdtsen 		tm.tm_isdst = (-1); /* look up DST information */
2724c18ec02fSPetter Reinholdtsen 		t = mktime(&tm);
2725c18ec02fSPetter Reinholdtsen 		if (t < 0) {
2726c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Specified time could not be parsed");
2727c18ec02fSPetter Reinholdtsen 			return -1;
2728c18ec02fSPetter Reinholdtsen 		}
2729c18ec02fSPetter Reinholdtsen 	}
2730c18ec02fSPetter Reinholdtsen 
2731c18ec02fSPetter Reinholdtsen 	{
2732c18ec02fSPetter Reinholdtsen 		//modify UTC time to local time expressed in number of seconds from 1/1/70 0:0:0 1970 GMT
2733c18ec02fSPetter Reinholdtsen 		struct tm * tm_tmp = {0};
2734c18ec02fSPetter Reinholdtsen 		int gt_year,gt_yday,gt_hour,lt_year,lt_yday,lt_hour;
2735c18ec02fSPetter Reinholdtsen 		int delta_hour;
2736c18ec02fSPetter Reinholdtsen 		tm_tmp=gmtime(&t);
2737c18ec02fSPetter Reinholdtsen 		gt_year=tm_tmp->tm_year;
2738c18ec02fSPetter Reinholdtsen 		gt_yday=tm_tmp->tm_yday;
2739c18ec02fSPetter Reinholdtsen 		gt_hour=tm_tmp->tm_hour;
2740c18ec02fSPetter Reinholdtsen 		memset(&*tm_tmp, 0, sizeof(struct tm));
2741c18ec02fSPetter Reinholdtsen 		tm_tmp=localtime(&t);
2742c18ec02fSPetter Reinholdtsen 		lt_year=tm_tmp->tm_year;
2743c18ec02fSPetter Reinholdtsen 		lt_yday=tm_tmp->tm_yday;
2744c18ec02fSPetter Reinholdtsen 		lt_hour=tm_tmp->tm_hour;
2745c18ec02fSPetter Reinholdtsen 		delta_hour=lt_hour - gt_hour;
2746c18ec02fSPetter Reinholdtsen 		if ( (lt_year > gt_year) || ((lt_year == gt_year) && (lt_yday > gt_yday)) )
2747c18ec02fSPetter Reinholdtsen 			delta_hour += 24;
2748c18ec02fSPetter Reinholdtsen 		if ( (lt_year < gt_year) || ((lt_year == gt_year) && (lt_yday < gt_yday)) )
2749c18ec02fSPetter Reinholdtsen 			delta_hour -= 24;
2750c18ec02fSPetter Reinholdtsen 
2751c18ec02fSPetter Reinholdtsen 		t += (delta_hour * 60 * 60);
2752c18ec02fSPetter Reinholdtsen 	}
2753c18ec02fSPetter Reinholdtsen 
2754c18ec02fSPetter Reinholdtsen 	timei = (uint32_t)t;
2755c18ec02fSPetter Reinholdtsen 	req.msg.data = (uint8_t *)&timei;
2756c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 4;
2757c18ec02fSPetter Reinholdtsen 
2758c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN
2759c18ec02fSPetter Reinholdtsen 	timei = BSWAP_32(timei);
2760c18ec02fSPetter Reinholdtsen #endif
2761c18ec02fSPetter Reinholdtsen 
2762c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
2763c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
2764c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Set SEL Time command failed");
2765c18ec02fSPetter Reinholdtsen 		return -1;
2766c18ec02fSPetter Reinholdtsen 	}
2767c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
2768c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Set SEL Time command failed: %s",
2769c18ec02fSPetter Reinholdtsen 			val2str(rsp->ccode, completion_code_vals));
2770c18ec02fSPetter Reinholdtsen 		return -1;
2771c18ec02fSPetter Reinholdtsen 	}
2772c18ec02fSPetter Reinholdtsen 
2773c18ec02fSPetter Reinholdtsen 	ipmi_sel_get_time(intf);
2774c18ec02fSPetter Reinholdtsen 
2775c18ec02fSPetter Reinholdtsen 	return 0;
2776c18ec02fSPetter Reinholdtsen }
2777c18ec02fSPetter Reinholdtsen 
2778c18ec02fSPetter Reinholdtsen 
2779c18ec02fSPetter Reinholdtsen 
2780c18ec02fSPetter Reinholdtsen static int
ipmi_sel_clear(struct ipmi_intf * intf)2781c18ec02fSPetter Reinholdtsen ipmi_sel_clear(struct ipmi_intf * intf)
2782c18ec02fSPetter Reinholdtsen {
2783c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
2784c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
2785c18ec02fSPetter Reinholdtsen 	uint16_t reserve_id;
2786c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[6];
2787c18ec02fSPetter Reinholdtsen 
2788c18ec02fSPetter Reinholdtsen 	reserve_id = ipmi_sel_reserve(intf);
2789c18ec02fSPetter Reinholdtsen 	if (reserve_id == 0)
2790c18ec02fSPetter Reinholdtsen 		return -1;
2791c18ec02fSPetter Reinholdtsen 
2792c18ec02fSPetter Reinholdtsen 	memset(msg_data, 0, 6);
2793c18ec02fSPetter Reinholdtsen 	msg_data[0] = reserve_id & 0xff;
2794c18ec02fSPetter Reinholdtsen 	msg_data[1] = reserve_id >> 8;
2795c18ec02fSPetter Reinholdtsen 	msg_data[2] = 'C';
2796c18ec02fSPetter Reinholdtsen 	msg_data[3] = 'L';
2797c18ec02fSPetter Reinholdtsen 	msg_data[4] = 'R';
2798c18ec02fSPetter Reinholdtsen 	msg_data[5] = 0xaa;
2799c18ec02fSPetter Reinholdtsen 
2800c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
2801c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
2802c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_CMD_CLEAR_SEL;
2803c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
2804c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 6;
2805c18ec02fSPetter Reinholdtsen 
2806c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
2807c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
2808c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Unable to clear SEL");
2809c18ec02fSPetter Reinholdtsen 		return -1;
2810c18ec02fSPetter Reinholdtsen 	}
2811c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
2812c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Unable to clear SEL: %s",
2813c18ec02fSPetter Reinholdtsen 			val2str(rsp->ccode, completion_code_vals));
2814c18ec02fSPetter Reinholdtsen 		return -1;
2815c18ec02fSPetter Reinholdtsen 	}
2816c18ec02fSPetter Reinholdtsen 
2817c18ec02fSPetter Reinholdtsen 	printf("Clearing SEL.  Please allow a few seconds to erase.\n");
2818c18ec02fSPetter Reinholdtsen 	return 0;
2819c18ec02fSPetter Reinholdtsen }
2820c18ec02fSPetter Reinholdtsen 
2821c18ec02fSPetter Reinholdtsen static int
ipmi_sel_delete(struct ipmi_intf * intf,int argc,char ** argv)2822c18ec02fSPetter Reinholdtsen ipmi_sel_delete(struct ipmi_intf * intf, int argc, char ** argv)
2823c18ec02fSPetter Reinholdtsen {
2824c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
2825c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
2826c18ec02fSPetter Reinholdtsen 	uint16_t id;
2827c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[4];
2828c18ec02fSPetter Reinholdtsen 	int rc = 0;
2829c18ec02fSPetter Reinholdtsen 
2830c18ec02fSPetter Reinholdtsen 	if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
2831c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "usage: delete <id>...<id>\n");
2832c18ec02fSPetter Reinholdtsen 		return -1;
2833c18ec02fSPetter Reinholdtsen 	}
2834c18ec02fSPetter Reinholdtsen 
2835c18ec02fSPetter Reinholdtsen 	id = ipmi_sel_reserve(intf);
2836c18ec02fSPetter Reinholdtsen 	if (id == 0)
2837c18ec02fSPetter Reinholdtsen 		return -1;
2838c18ec02fSPetter Reinholdtsen 
2839c18ec02fSPetter Reinholdtsen 	memset(msg_data, 0, 4);
2840c18ec02fSPetter Reinholdtsen 	msg_data[0] = id & 0xff;
2841c18ec02fSPetter Reinholdtsen 	msg_data[1] = id >> 8;
2842c18ec02fSPetter Reinholdtsen 
2843c18ec02fSPetter Reinholdtsen 	for (; argc != 0; argc--)
2844c18ec02fSPetter Reinholdtsen 	{
2845c18ec02fSPetter Reinholdtsen 		if (str2ushort(argv[argc-1], &id) != 0) {
2846c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Given SEL ID '%s' is invalid.",
2847c18ec02fSPetter Reinholdtsen 					argv[argc-1]);
2848c18ec02fSPetter Reinholdtsen 			rc = (-1);
2849c18ec02fSPetter Reinholdtsen 			continue;
2850c18ec02fSPetter Reinholdtsen 		}
2851c18ec02fSPetter Reinholdtsen 		msg_data[2] = id & 0xff;
2852c18ec02fSPetter Reinholdtsen 		msg_data[3] = id >> 8;
2853c18ec02fSPetter Reinholdtsen 
2854c18ec02fSPetter Reinholdtsen 		memset(&req, 0, sizeof(req));
2855c18ec02fSPetter Reinholdtsen 		req.msg.netfn = IPMI_NETFN_STORAGE;
2856c18ec02fSPetter Reinholdtsen 		req.msg.cmd = IPMI_CMD_DELETE_SEL_ENTRY;
2857c18ec02fSPetter Reinholdtsen 		req.msg.data = msg_data;
2858c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 4;
2859c18ec02fSPetter Reinholdtsen 
2860c18ec02fSPetter Reinholdtsen 		rsp = intf->sendrecv(intf, &req);
2861c18ec02fSPetter Reinholdtsen 		if (rsp == NULL) {
2862c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Unable to delete entry %d", id);
2863c18ec02fSPetter Reinholdtsen 			rc = -1;
2864c18ec02fSPetter Reinholdtsen 		}
2865c18ec02fSPetter Reinholdtsen 		else if (rsp->ccode > 0) {
2866c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Unable to delete entry %d: %s", id,
2867c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
2868c18ec02fSPetter Reinholdtsen 			rc = -1;
2869c18ec02fSPetter Reinholdtsen 		}
2870c18ec02fSPetter Reinholdtsen 		else {
2871c18ec02fSPetter Reinholdtsen 			printf("Deleted entry %d\n", id);
2872c18ec02fSPetter Reinholdtsen 		}
2873c18ec02fSPetter Reinholdtsen 	}
2874c18ec02fSPetter Reinholdtsen 
2875c18ec02fSPetter Reinholdtsen 	return rc;
2876c18ec02fSPetter Reinholdtsen }
2877c18ec02fSPetter Reinholdtsen 
2878c18ec02fSPetter Reinholdtsen static int
ipmi_sel_show_entry(struct ipmi_intf * intf,int argc,char ** argv)2879c18ec02fSPetter Reinholdtsen ipmi_sel_show_entry(struct ipmi_intf * intf, int argc, char ** argv)
2880c18ec02fSPetter Reinholdtsen {
2881c18ec02fSPetter Reinholdtsen 	struct entity_id entity;
2882c56458daSZdenek Styblik 	struct sdr_record_list *entry;
2883c56458daSZdenek Styblik 	struct sdr_record_list *list;
2884c56458daSZdenek Styblik 	struct sdr_record_list *sdr;
2885c56458daSZdenek Styblik 	struct sel_event_record evt;
2886c56458daSZdenek Styblik 	int i;
2887c56458daSZdenek Styblik 	int oldv;
2888c18ec02fSPetter Reinholdtsen 	int rc = 0;
2889c56458daSZdenek Styblik 	uint16_t id;
2890c18ec02fSPetter Reinholdtsen 
2891c18ec02fSPetter Reinholdtsen 	if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
2892c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "usage: sel get <id>...<id>");
2893c56458daSZdenek Styblik 		return (-1);
2894c18ec02fSPetter Reinholdtsen 	}
2895c18ec02fSPetter Reinholdtsen 
2896c18ec02fSPetter Reinholdtsen 	if (ipmi_sel_reserve(intf) == 0) {
2897c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Unable to reserve SEL");
2898c56458daSZdenek Styblik 		return (-1);
2899c18ec02fSPetter Reinholdtsen 	}
2900c18ec02fSPetter Reinholdtsen 
2901c18ec02fSPetter Reinholdtsen 	for (i = 0; i < argc; i++) {
2902c18ec02fSPetter Reinholdtsen 		if (str2ushort(argv[i], &id) != 0) {
2903c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Given SEL ID '%s' is invalid.",
2904c18ec02fSPetter Reinholdtsen 					argv[i]);
2905c18ec02fSPetter Reinholdtsen 			rc = (-1);
2906c18ec02fSPetter Reinholdtsen 			continue;
2907c18ec02fSPetter Reinholdtsen 		}
2908c18ec02fSPetter Reinholdtsen 
2909c18ec02fSPetter Reinholdtsen 		lprintf(LOG_DEBUG, "Looking up SEL entry 0x%x", id);
2910c18ec02fSPetter Reinholdtsen 
2911c18ec02fSPetter Reinholdtsen 		/* lookup SEL entry based on ID */
2912250eb15fSZdenek Styblik 		if (!ipmi_sel_get_std_entry(intf, id, &evt)) {
2913250eb15fSZdenek Styblik 			lprintf(LOG_DEBUG, "SEL Entry 0x%x not found.", id);
2914250eb15fSZdenek Styblik 			rc = (-1);
2915250eb15fSZdenek Styblik 			continue;
2916250eb15fSZdenek Styblik 		}
2917c56458daSZdenek Styblik 		if (evt.sel_type.standard_type.sensor_num == 0
2918c56458daSZdenek Styblik 				&& evt.sel_type.standard_type.sensor_type == 0
2919c56458daSZdenek Styblik 				&& evt.record_type == 0) {
2920c18ec02fSPetter Reinholdtsen 			lprintf(LOG_WARN, "SEL Entry 0x%x not found", id);
2921c56458daSZdenek Styblik 			rc = (-1);
2922c18ec02fSPetter Reinholdtsen 			continue;
2923c18ec02fSPetter Reinholdtsen 		}
2924c18ec02fSPetter Reinholdtsen 
2925c18ec02fSPetter Reinholdtsen 		/* lookup SDR entry based on sensor number and type */
2926c18ec02fSPetter Reinholdtsen 		ipmi_sel_print_extended_entry_verbose(intf, &evt);
2927c18ec02fSPetter Reinholdtsen 
2928c56458daSZdenek Styblik 		sdr = ipmi_sdr_find_sdr_bynumtype(intf,
2929c56458daSZdenek Styblik 				evt.sel_type.standard_type.gen_id,
2930c56458daSZdenek Styblik 				evt.sel_type.standard_type.sensor_num,
2931c56458daSZdenek Styblik 				evt.sel_type.standard_type.sensor_type);
2932c18ec02fSPetter Reinholdtsen 		if (sdr == NULL) {
2933c18ec02fSPetter Reinholdtsen 			continue;
2934c18ec02fSPetter Reinholdtsen 		}
2935c18ec02fSPetter Reinholdtsen 
2936c18ec02fSPetter Reinholdtsen 		/* print SDR entry */
2937c18ec02fSPetter Reinholdtsen 		oldv = verbose;
293848117f5dSZdenek Styblik 		verbose = verbose ? verbose : 1;
2939c18ec02fSPetter Reinholdtsen 		switch (sdr->type) {
2940c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_FULL_SENSOR:
2941c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_COMPACT_SENSOR:
2942c18ec02fSPetter Reinholdtsen 			ipmi_sensor_print_fc(intf, sdr->record.common,
2943c18ec02fSPetter Reinholdtsen 					     sdr->type);
2944c18ec02fSPetter Reinholdtsen 			entity.id = sdr->record.common->entity.id;
2945c18ec02fSPetter Reinholdtsen 			entity.instance = sdr->record.common->entity.instance;
2946c18ec02fSPetter Reinholdtsen 			break;
2947c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
2948c18ec02fSPetter Reinholdtsen 			ipmi_sdr_print_sensor_eventonly(intf, sdr->record.eventonly);
2949c18ec02fSPetter Reinholdtsen 			entity.id = sdr->record.eventonly->entity.id;
2950c18ec02fSPetter Reinholdtsen 			entity.instance = sdr->record.eventonly->entity.instance;
2951c18ec02fSPetter Reinholdtsen 			break;
2952c18ec02fSPetter Reinholdtsen 		default:
2953c18ec02fSPetter Reinholdtsen 			verbose = oldv;
2954c18ec02fSPetter Reinholdtsen 			continue;
2955c18ec02fSPetter Reinholdtsen 		}
2956c18ec02fSPetter Reinholdtsen 		verbose = oldv;
2957c18ec02fSPetter Reinholdtsen 
2958c18ec02fSPetter Reinholdtsen 		/* lookup SDR entry based on entity id */
2959c18ec02fSPetter Reinholdtsen 		list = ipmi_sdr_find_sdr_byentity(intf, &entity);
2960c18ec02fSPetter Reinholdtsen 		for (entry=list; entry; entry=entry->next) {
2961c18ec02fSPetter Reinholdtsen 			/* print FRU devices we find for this entity */
2962c18ec02fSPetter Reinholdtsen 			if (entry->type == SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR)
2963c18ec02fSPetter Reinholdtsen 				ipmi_fru_print(intf, entry->record.fruloc);
2964c18ec02fSPetter Reinholdtsen 		}
2965c18ec02fSPetter Reinholdtsen 
2966c56458daSZdenek Styblik 		if ((argc > 1) && (i < (argc - 1))) {
2967c18ec02fSPetter Reinholdtsen 			printf("----------------------\n\n");
2968c18ec02fSPetter Reinholdtsen 		}
2969c56458daSZdenek Styblik 	}
2970c18ec02fSPetter Reinholdtsen 
2971c18ec02fSPetter Reinholdtsen 	return rc;
2972c18ec02fSPetter Reinholdtsen }
2973c18ec02fSPetter Reinholdtsen 
ipmi_sel_main(struct ipmi_intf * intf,int argc,char ** argv)2974c18ec02fSPetter Reinholdtsen int ipmi_sel_main(struct ipmi_intf * intf, int argc, char ** argv)
2975c18ec02fSPetter Reinholdtsen {
2976c18ec02fSPetter Reinholdtsen 	int rc = 0;
2977c18ec02fSPetter Reinholdtsen 
2978c18ec02fSPetter Reinholdtsen 	if (argc == 0)
2979c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_get_info(intf);
2980c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "help", 4) == 0)
2981c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "SEL Commands:  "
2982c18ec02fSPetter Reinholdtsen 				"info clear delete list elist get add time save readraw writeraw interpret");
2983c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "interpret", 9) == 0) {
2984c18ec02fSPetter Reinholdtsen 		uint32_t iana = 0;
2985c18ec02fSPetter Reinholdtsen 		if (argc < 4) {
2986c18ec02fSPetter Reinholdtsen 			lprintf(LOG_NOTICE, "usage: sel interpret iana filename format(pps)");
2987c18ec02fSPetter Reinholdtsen 			return 0;
2988c18ec02fSPetter Reinholdtsen 		}
2989c18ec02fSPetter Reinholdtsen 		if (str2uint(argv[1], &iana) != 0) {
2990c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Given IANA '%s' is invalid.",
2991c18ec02fSPetter Reinholdtsen 					argv[1]);
2992c18ec02fSPetter Reinholdtsen 			return (-1);
2993c18ec02fSPetter Reinholdtsen 		}
2994c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_interpret(intf, iana, argv[2], argv[3]);
2995c18ec02fSPetter Reinholdtsen 	}
2996c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "info", 4) == 0)
2997c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_get_info(intf);
2998c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "save", 4) == 0) {
2999c18ec02fSPetter Reinholdtsen 		if (argc < 2) {
3000c18ec02fSPetter Reinholdtsen 			lprintf(LOG_NOTICE, "usage: sel save <filename>");
3001c18ec02fSPetter Reinholdtsen 			return 0;
3002c18ec02fSPetter Reinholdtsen 		}
3003c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_save_entries(intf, 0, argv[1]);
3004c18ec02fSPetter Reinholdtsen 	}
3005c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "add", 3) == 0) {
3006c18ec02fSPetter Reinholdtsen 		if (argc < 2) {
3007c18ec02fSPetter Reinholdtsen 			lprintf(LOG_NOTICE, "usage: sel add <filename>");
3008c18ec02fSPetter Reinholdtsen 			return 0;
3009c18ec02fSPetter Reinholdtsen 		}
3010c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_add_entries_fromfile(intf, argv[1]);
3011c18ec02fSPetter Reinholdtsen 	}
3012c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "writeraw", 8) == 0) {
3013c18ec02fSPetter Reinholdtsen 		if (argc < 2) {
3014c18ec02fSPetter Reinholdtsen 			lprintf(LOG_NOTICE, "usage: sel writeraw <filename>");
3015c18ec02fSPetter Reinholdtsen 			return 0;
3016c18ec02fSPetter Reinholdtsen 		}
3017c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_writeraw(intf, argv[1]);
3018c18ec02fSPetter Reinholdtsen 	}
3019c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "readraw", 7) == 0) {
3020c18ec02fSPetter Reinholdtsen 		if (argc < 2) {
3021c18ec02fSPetter Reinholdtsen 			lprintf(LOG_NOTICE, "usage: sel readraw <filename>");
3022c18ec02fSPetter Reinholdtsen 			return 0;
3023c18ec02fSPetter Reinholdtsen 		}
3024c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_readraw(intf, argv[1]);
3025c18ec02fSPetter Reinholdtsen 	}
3026c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "ereadraw", 8) == 0) {
3027c18ec02fSPetter Reinholdtsen 		if (argc < 2) {
3028c18ec02fSPetter Reinholdtsen 			lprintf(LOG_NOTICE, "usage: sel ereadraw <filename>");
3029c18ec02fSPetter Reinholdtsen 			return 0;
3030c18ec02fSPetter Reinholdtsen 		}
3031c18ec02fSPetter Reinholdtsen 		sel_extended = 1;
3032c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_readraw(intf, argv[1]);
3033c18ec02fSPetter Reinholdtsen 	}
3034c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "list", 4) == 0 ||
3035c18ec02fSPetter Reinholdtsen 		 strncmp(argv[0], "elist", 5) == 0) {
3036c18ec02fSPetter Reinholdtsen 		/*
3037c18ec02fSPetter Reinholdtsen 		 * Usage:
3038c18ec02fSPetter Reinholdtsen 		 *	list           - show all SEL entries
3039c18ec02fSPetter Reinholdtsen 		 *  list first <n> - show the first (oldest) <n> SEL entries
3040c18ec02fSPetter Reinholdtsen 		 *  list last <n>  - show the last (newsest) <n> SEL entries
3041c18ec02fSPetter Reinholdtsen 		 */
3042c18ec02fSPetter Reinholdtsen 		int count = 0;
3043c18ec02fSPetter Reinholdtsen 		int sign = 1;
3044c18ec02fSPetter Reinholdtsen 		char *countstr = NULL;
3045c18ec02fSPetter Reinholdtsen 
3046c18ec02fSPetter Reinholdtsen 		if (strncmp(argv[0], "elist", 5) == 0)
3047c18ec02fSPetter Reinholdtsen 			sel_extended = 1;
3048c18ec02fSPetter Reinholdtsen 		else
3049c18ec02fSPetter Reinholdtsen 			sel_extended = 0;
3050c18ec02fSPetter Reinholdtsen 
3051c18ec02fSPetter Reinholdtsen 		if (argc == 2) {
3052c18ec02fSPetter Reinholdtsen 			countstr = argv[1];
3053c18ec02fSPetter Reinholdtsen 		}
3054c18ec02fSPetter Reinholdtsen 		else if (argc == 3) {
3055c18ec02fSPetter Reinholdtsen 			countstr = argv[2];
3056c18ec02fSPetter Reinholdtsen 
3057c18ec02fSPetter Reinholdtsen 			if (strncmp(argv[1], "last", 4) == 0) {
3058c18ec02fSPetter Reinholdtsen 				sign = -1;
3059c18ec02fSPetter Reinholdtsen 			}
3060c18ec02fSPetter Reinholdtsen 			else if (strncmp(argv[1], "first", 5) != 0) {
3061c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Unknown sel list option");
3062c18ec02fSPetter Reinholdtsen 				return -1;
3063c18ec02fSPetter Reinholdtsen 			}
3064c18ec02fSPetter Reinholdtsen 		}
3065c18ec02fSPetter Reinholdtsen 
3066c18ec02fSPetter Reinholdtsen 		if (countstr) {
3067c18ec02fSPetter Reinholdtsen 			if (str2int(countstr, &count) != 0) {
3068c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Numeric argument required; got '%s'",
3069c18ec02fSPetter Reinholdtsen 					countstr);
3070c18ec02fSPetter Reinholdtsen 				return -1;
3071c18ec02fSPetter Reinholdtsen 			}
3072c18ec02fSPetter Reinholdtsen 		}
3073c18ec02fSPetter Reinholdtsen 		count *= sign;
3074c18ec02fSPetter Reinholdtsen 
3075c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_list_entries(intf,count);
3076c18ec02fSPetter Reinholdtsen 	}
3077c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "clear", 5) == 0)
3078c18ec02fSPetter Reinholdtsen 		rc = ipmi_sel_clear(intf);
3079c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "delete", 6) == 0) {
3080c18ec02fSPetter Reinholdtsen 		if (argc < 2)
3081c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "usage: sel delete <id>...<id>");
3082c18ec02fSPetter Reinholdtsen 		else
3083c18ec02fSPetter Reinholdtsen 			rc = ipmi_sel_delete(intf, argc-1, &argv[1]);
3084c18ec02fSPetter Reinholdtsen 	}
3085c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "get", 3) == 0) {
3086c18ec02fSPetter Reinholdtsen 		if (argc < 2)
3087c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "usage: sel get <entry>");
3088c18ec02fSPetter Reinholdtsen 		else
3089c18ec02fSPetter Reinholdtsen 			rc = ipmi_sel_show_entry(intf, argc-1, &argv[1]);
3090c18ec02fSPetter Reinholdtsen 	}
3091c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "time", 4) == 0) {
3092c18ec02fSPetter Reinholdtsen 		if (argc < 2)
3093c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "sel time commands: get set");
3094c18ec02fSPetter Reinholdtsen 		else if (strncmp(argv[1], "get", 3) == 0)
3095c18ec02fSPetter Reinholdtsen 			ipmi_sel_get_time(intf);
3096c18ec02fSPetter Reinholdtsen 		else if (strncmp(argv[1], "set", 3) == 0) {
3097c18ec02fSPetter Reinholdtsen 			if (argc < 3)
3098c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "usage: sel time set \"mm/dd/yyyy hh:mm:ss\"");
3099c18ec02fSPetter Reinholdtsen 			else
3100c18ec02fSPetter Reinholdtsen 				rc = ipmi_sel_set_time(intf, argv[2]);
3101c18ec02fSPetter Reinholdtsen 		} else {
3102c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "sel time commands: get set");
3103c18ec02fSPetter Reinholdtsen 		}
3104c18ec02fSPetter Reinholdtsen 	}
3105c18ec02fSPetter Reinholdtsen 	else {
3106c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid SEL command: %s", argv[0]);
3107c18ec02fSPetter Reinholdtsen 		rc = -1;
3108c18ec02fSPetter Reinholdtsen 	}
3109c18ec02fSPetter Reinholdtsen 
3110c18ec02fSPetter Reinholdtsen 	return rc;
3111c18ec02fSPetter Reinholdtsen }
3112