xref: /onnv-gate/usr/src/cmd/lms/heci/HECIUnix.cpp (revision 9203:3ebffd0a1b10)
1*9203SMark.Logan@Sun.COM /*******************************************************************************
2*9203SMark.Logan@Sun.COM  * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
3*9203SMark.Logan@Sun.COM  *
4*9203SMark.Logan@Sun.COM  * Redistribution and use in source and binary forms, with or without
5*9203SMark.Logan@Sun.COM  * modification, are permitted provided that the following conditions are met:
6*9203SMark.Logan@Sun.COM  *
7*9203SMark.Logan@Sun.COM  *  - Redistributions of source code must retain the above copyright notice,
8*9203SMark.Logan@Sun.COM  *    this list of conditions and the following disclaimer.
9*9203SMark.Logan@Sun.COM  *
10*9203SMark.Logan@Sun.COM  *  - Redistributions in binary form must reproduce the above copyright notice,
11*9203SMark.Logan@Sun.COM  *    this list of conditions and the following disclaimer in the documentation
12*9203SMark.Logan@Sun.COM  *    and/or other materials provided with the distribution.
13*9203SMark.Logan@Sun.COM  *
14*9203SMark.Logan@Sun.COM  *  - Neither the name of Intel Corp. nor the names of its
15*9203SMark.Logan@Sun.COM  *    contributors may be used to endorse or promote products derived from this
16*9203SMark.Logan@Sun.COM  *    software without specific prior written permission.
17*9203SMark.Logan@Sun.COM  *
18*9203SMark.Logan@Sun.COM  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
19*9203SMark.Logan@Sun.COM  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*9203SMark.Logan@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*9203SMark.Logan@Sun.COM  * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
22*9203SMark.Logan@Sun.COM  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*9203SMark.Logan@Sun.COM  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*9203SMark.Logan@Sun.COM  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*9203SMark.Logan@Sun.COM  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*9203SMark.Logan@Sun.COM  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*9203SMark.Logan@Sun.COM  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*9203SMark.Logan@Sun.COM  * POSSIBILITY OF SUCH DAMAGE.
29*9203SMark.Logan@Sun.COM  *******************************************************************************/
30*9203SMark.Logan@Sun.COM 
31*9203SMark.Logan@Sun.COM #ifdef HAVE_CONFIG_H
32*9203SMark.Logan@Sun.COM #include "config.h"
33*9203SMark.Logan@Sun.COM #endif
34*9203SMark.Logan@Sun.COM #include <cstdio>
35*9203SMark.Logan@Sun.COM #include <cstring>
36*9203SMark.Logan@Sun.COM #include <cstdlib>
37*9203SMark.Logan@Sun.COM #include <cerrno>
38*9203SMark.Logan@Sun.COM #include <fcntl.h>
39*9203SMark.Logan@Sun.COM #include <sys/ioctl.h>
40*9203SMark.Logan@Sun.COM #include <unistd.h>
41*9203SMark.Logan@Sun.COM #include <stdint.h>
42*9203SMark.Logan@Sun.COM #include <aio.h>
43*9203SMark.Logan@Sun.COM 
44*9203SMark.Logan@Sun.COM #ifdef __sun
45*9203SMark.Logan@Sun.COM #include <stdio.h>
46*9203SMark.Logan@Sun.COM #include <stdlib.h>
47*9203SMark.Logan@Sun.COM #endif	// __sun
48*9203SMark.Logan@Sun.COM 
49*9203SMark.Logan@Sun.COM #include "HECIUnix.h"
50*9203SMark.Logan@Sun.COM 
51*9203SMark.Logan@Sun.COM #pragma pack(1)
52*9203SMark.Logan@Sun.COM 
53*9203SMark.Logan@Sun.COM typedef struct heci_ioctl_data
54*9203SMark.Logan@Sun.COM {
55*9203SMark.Logan@Sun.COM 	uint32_t size;
56*9203SMark.Logan@Sun.COM 	char *data;
57*9203SMark.Logan@Sun.COM #ifndef  _LP64
58*9203SMark.Logan@Sun.COM 	/*
59*9203SMark.Logan@Sun.COM 	 * If lms is compiled in 32-bit, padding is needed to
60*9203SMark.Logan@Sun.COM 	 * talk to the driver which is 64-bit only.
61*9203SMark.Logan@Sun.COM 	 */
62*9203SMark.Logan@Sun.COM 	char *pad;
63*9203SMark.Logan@Sun.COM #endif
64*9203SMark.Logan@Sun.COM } heci_ioctl_data_t;
65*9203SMark.Logan@Sun.COM 
66*9203SMark.Logan@Sun.COM /* IOCTL commands */
67*9203SMark.Logan@Sun.COM #undef HECI_IOCTL
68*9203SMark.Logan@Sun.COM #undef IOCTL_HECI_GET_VERSION
69*9203SMark.Logan@Sun.COM #undef IOCTL_HECI_CONNECT_CLIENT
70*9203SMark.Logan@Sun.COM #undef IOCTL_HECI_WD
71*9203SMark.Logan@Sun.COM #define HECI_IOCTL_TYPE 0x48
72*9203SMark.Logan@Sun.COM #define IOCTL_HECI_GET_VERSION \
73*9203SMark.Logan@Sun.COM     _IOWR(HECI_IOCTL_TYPE, 0x0, heci_ioctl_data_t)
74*9203SMark.Logan@Sun.COM #define IOCTL_HECI_CONNECT_CLIENT \
75*9203SMark.Logan@Sun.COM     _IOWR(HECI_IOCTL_TYPE, 0x01, heci_ioctl_data_t)
76*9203SMark.Logan@Sun.COM #define IOCTL_HECI_WD \
77*9203SMark.Logan@Sun.COM     _IOWR(HECI_IOCTL_TYPE, 0x02, heci_ioctl_data_t)
78*9203SMark.Logan@Sun.COM #define IAMT_HECI_GET_RECEIVED_MESSAGE_DATA \
79*9203SMark.Logan@Sun.COM     _IOW(HECI_IOCTL_TYPE, 0x03, heci_ioctl_data_t)
80*9203SMark.Logan@Sun.COM 
81*9203SMark.Logan@Sun.COM #pragma pack(0)
82*9203SMark.Logan@Sun.COM 
83*9203SMark.Logan@Sun.COM /***************************** public functions *****************************/
84*9203SMark.Logan@Sun.COM 
HECILinux(const GUID guid,bool verbose)85*9203SMark.Logan@Sun.COM HECILinux::HECILinux(const GUID guid, bool verbose) :
86*9203SMark.Logan@Sun.COM HECI(guid, verbose),
87*9203SMark.Logan@Sun.COM _fd(-1),
88*9203SMark.Logan@Sun.COM m_haveHeciVersion(false)
89*9203SMark.Logan@Sun.COM {
90*9203SMark.Logan@Sun.COM }
91*9203SMark.Logan@Sun.COM 
~HECILinux()92*9203SMark.Logan@Sun.COM HECILinux::~HECILinux()
93*9203SMark.Logan@Sun.COM {
94*9203SMark.Logan@Sun.COM 	if (_fd != -1) {
95*9203SMark.Logan@Sun.COM 		close(_fd);
96*9203SMark.Logan@Sun.COM 	}
97*9203SMark.Logan@Sun.COM }
98*9203SMark.Logan@Sun.COM 
GetHeciVersion(HECI_VERSION & version) const99*9203SMark.Logan@Sun.COM bool HECILinux::GetHeciVersion(HECI_VERSION &version) const
100*9203SMark.Logan@Sun.COM {
101*9203SMark.Logan@Sun.COM 	if (m_haveHeciVersion) {
102*9203SMark.Logan@Sun.COM 		memcpy(&version, &m_heciVersion, sizeof(HECI_VERSION));
103*9203SMark.Logan@Sun.COM 		return true;
104*9203SMark.Logan@Sun.COM 	}
105*9203SMark.Logan@Sun.COM 	return false;
106*9203SMark.Logan@Sun.COM }
107*9203SMark.Logan@Sun.COM 
Init(unsigned char reqProtocolVersion)108*9203SMark.Logan@Sun.COM bool HECILinux::Init(unsigned char reqProtocolVersion)
109*9203SMark.Logan@Sun.COM {
110*9203SMark.Logan@Sun.COM 	int result;
111*9203SMark.Logan@Sun.COM 	HECI_CLIENT *heci_client;
112*9203SMark.Logan@Sun.COM 	bool return_result = true;
113*9203SMark.Logan@Sun.COM 	heci_ioctl_data_t version_response;
114*9203SMark.Logan@Sun.COM 	heci_ioctl_data_t client_connect;
115*9203SMark.Logan@Sun.COM 
116*9203SMark.Logan@Sun.COM 	m_haveHeciVersion = false;
117*9203SMark.Logan@Sun.COM 	if (_initialized) {
118*9203SMark.Logan@Sun.COM 		Deinit();
119*9203SMark.Logan@Sun.COM 	}
120*9203SMark.Logan@Sun.COM 
121*9203SMark.Logan@Sun.COM 	_fd = open("/dev/heci", O_RDWR);
122*9203SMark.Logan@Sun.COM 
123*9203SMark.Logan@Sun.COM 	if (_fd == -1 ) {
124*9203SMark.Logan@Sun.COM 		if (_verbose) {
125*9203SMark.Logan@Sun.COM 			fprintf(stderr, "Error: Cannot establish a handle to the HECI driver\n");
126*9203SMark.Logan@Sun.COM 		}
127*9203SMark.Logan@Sun.COM 		return false;
128*9203SMark.Logan@Sun.COM 	}
129*9203SMark.Logan@Sun.COM 	_initialized = true;
130*9203SMark.Logan@Sun.COM 	version_response.size = sizeof(HECI_VERSION);
131*9203SMark.Logan@Sun.COM 	version_response.data = (char *)malloc(version_response.size);
132*9203SMark.Logan@Sun.COM 	if (!version_response.data) {
133*9203SMark.Logan@Sun.COM 		if (_verbose) {
134*9203SMark.Logan@Sun.COM 			fprintf(stderr, "malloc failure.\n");
135*9203SMark.Logan@Sun.COM 		}
136*9203SMark.Logan@Sun.COM 		return_result = false;
137*9203SMark.Logan@Sun.COM 		Deinit();
138*9203SMark.Logan@Sun.COM 		goto heci_free;
139*9203SMark.Logan@Sun.COM 	}
140*9203SMark.Logan@Sun.COM 
141*9203SMark.Logan@Sun.COM 	result = ioctl(_fd, IOCTL_HECI_GET_VERSION, &version_response);
142*9203SMark.Logan@Sun.COM 	if (result) {
143*9203SMark.Logan@Sun.COM 		if (_verbose) {
144*9203SMark.Logan@Sun.COM 			fprintf(stderr, "error in IOCTL_HECI_GET_VERSION recieve message. err=%d\n", result);
145*9203SMark.Logan@Sun.COM 		}
146*9203SMark.Logan@Sun.COM 		return_result = false;
147*9203SMark.Logan@Sun.COM 		Deinit();
148*9203SMark.Logan@Sun.COM 		goto heci_free;
149*9203SMark.Logan@Sun.COM 	}
150*9203SMark.Logan@Sun.COM 	memcpy(&m_heciVersion, version_response.data, sizeof(HECI_VERSION));
151*9203SMark.Logan@Sun.COM 	m_haveHeciVersion = true;
152*9203SMark.Logan@Sun.COM 	if (_verbose) {
153*9203SMark.Logan@Sun.COM 		fprintf(stdout, "Connected to HECI driver, version: %d.%d.%d.%d\n",
154*9203SMark.Logan@Sun.COM 			m_heciVersion.major, m_heciVersion.minor, m_heciVersion.hotfix, m_heciVersion.build);
155*9203SMark.Logan@Sun.COM 		fprintf(stdout, "Size of guid = %lu\n", (unsigned long)sizeof(_guid));
156*9203SMark.Logan@Sun.COM 	}
157*9203SMark.Logan@Sun.COM 	client_connect.size = sizeof(_guid);
158*9203SMark.Logan@Sun.COM 	client_connect.data = (char *)malloc(client_connect.size);
159*9203SMark.Logan@Sun.COM 	if (!client_connect.data) {
160*9203SMark.Logan@Sun.COM 		if (_verbose) {
161*9203SMark.Logan@Sun.COM 			fprintf(stderr, "malloc failure.\n");
162*9203SMark.Logan@Sun.COM 		}
163*9203SMark.Logan@Sun.COM 		return_result = false;
164*9203SMark.Logan@Sun.COM 		Deinit();
165*9203SMark.Logan@Sun.COM 		goto heci_free;
166*9203SMark.Logan@Sun.COM 	}
167*9203SMark.Logan@Sun.COM 	memcpy(client_connect.data, &_guid, sizeof(_guid));
168*9203SMark.Logan@Sun.COM 	result = ioctl(_fd, IOCTL_HECI_CONNECT_CLIENT, &client_connect);
169*9203SMark.Logan@Sun.COM 	if (result) {
170*9203SMark.Logan@Sun.COM 		if (_verbose) {
171*9203SMark.Logan@Sun.COM 			fprintf(stderr, "error in IOCTL_HECI_CONNECT_CLIENT recieve message. err=%d\n", result);
172*9203SMark.Logan@Sun.COM 		}
173*9203SMark.Logan@Sun.COM 		return_result = false;
174*9203SMark.Logan@Sun.COM 		Deinit();
175*9203SMark.Logan@Sun.COM 		goto heci_free;
176*9203SMark.Logan@Sun.COM 	}
177*9203SMark.Logan@Sun.COM 	heci_client = (HECI_CLIENT *) client_connect.data;
178*9203SMark.Logan@Sun.COM 	if (_verbose) {
179*9203SMark.Logan@Sun.COM 		fprintf(stdout, "max_message_length %d \n", (heci_client->MaxMessageLength));
180*9203SMark.Logan@Sun.COM 		fprintf(stdout, "protocol_version %d \n", (heci_client->ProtocolVersion));
181*9203SMark.Logan@Sun.COM 	}
182*9203SMark.Logan@Sun.COM 
183*9203SMark.Logan@Sun.COM 	if ((reqProtocolVersion > 0) && (heci_client->ProtocolVersion != reqProtocolVersion)) {
184*9203SMark.Logan@Sun.COM 		if (_verbose) {
185*9203SMark.Logan@Sun.COM 			fprintf(stderr, "Error: MEI protocol version not supported\n");
186*9203SMark.Logan@Sun.COM 		}
187*9203SMark.Logan@Sun.COM 		return_result = false;
188*9203SMark.Logan@Sun.COM 		Deinit();
189*9203SMark.Logan@Sun.COM 		goto heci_free;
190*9203SMark.Logan@Sun.COM 	}
191*9203SMark.Logan@Sun.COM 
192*9203SMark.Logan@Sun.COM 	_protocolVersion = heci_client->ProtocolVersion;
193*9203SMark.Logan@Sun.COM 	_bufSize = heci_client->MaxMessageLength;
194*9203SMark.Logan@Sun.COM 
195*9203SMark.Logan@Sun.COM heci_free:
196*9203SMark.Logan@Sun.COM 	if (NULL != version_response.data) {
197*9203SMark.Logan@Sun.COM 		free(version_response.data);
198*9203SMark.Logan@Sun.COM 	}
199*9203SMark.Logan@Sun.COM 	if (NULL != client_connect.data) {
200*9203SMark.Logan@Sun.COM 		free(client_connect.data);
201*9203SMark.Logan@Sun.COM 	}
202*9203SMark.Logan@Sun.COM 	return return_result;
203*9203SMark.Logan@Sun.COM }
204*9203SMark.Logan@Sun.COM 
Deinit()205*9203SMark.Logan@Sun.COM void HECILinux::Deinit()
206*9203SMark.Logan@Sun.COM {
207*9203SMark.Logan@Sun.COM 	if (_fd != -1) {
208*9203SMark.Logan@Sun.COM 		close(_fd);
209*9203SMark.Logan@Sun.COM 		_fd = -1;
210*9203SMark.Logan@Sun.COM 	}
211*9203SMark.Logan@Sun.COM 
212*9203SMark.Logan@Sun.COM 	_bufSize = 0;
213*9203SMark.Logan@Sun.COM 	_protocolVersion = 0;
214*9203SMark.Logan@Sun.COM 	_initialized = false;
215*9203SMark.Logan@Sun.COM }
216*9203SMark.Logan@Sun.COM 
ReceiveMessage(unsigned char * buffer,int len,unsigned long timeout)217*9203SMark.Logan@Sun.COM int HECILinux::ReceiveMessage(unsigned char *buffer, int len, unsigned long timeout)
218*9203SMark.Logan@Sun.COM {
219*9203SMark.Logan@Sun.COM 	int rv = 0;
220*9203SMark.Logan@Sun.COM 	int error = 0;
221*9203SMark.Logan@Sun.COM 
222*9203SMark.Logan@Sun.COM 	if (_verbose) {
223*9203SMark.Logan@Sun.COM 		fprintf(stdout, "call read length = %d\n", len);
224*9203SMark.Logan@Sun.COM 	}
225*9203SMark.Logan@Sun.COM 	rv = read(_fd, (void*)buffer, len);
226*9203SMark.Logan@Sun.COM 	if (rv < 0) {
227*9203SMark.Logan@Sun.COM 		error = errno;
228*9203SMark.Logan@Sun.COM 		if (_verbose) {
229*9203SMark.Logan@Sun.COM 			fprintf(stderr, "read failed with status %d %d\n", rv, error);
230*9203SMark.Logan@Sun.COM 		}
231*9203SMark.Logan@Sun.COM 		Deinit();
232*9203SMark.Logan@Sun.COM 	} else {
233*9203SMark.Logan@Sun.COM 		if (_verbose) {
234*9203SMark.Logan@Sun.COM 			fprintf(stderr, "read succeded with result %d\n", rv);
235*9203SMark.Logan@Sun.COM 		}
236*9203SMark.Logan@Sun.COM 	}
237*9203SMark.Logan@Sun.COM 	return rv;
238*9203SMark.Logan@Sun.COM }
239*9203SMark.Logan@Sun.COM 
SendMessage(const unsigned char * buffer,int len,unsigned long timeout)240*9203SMark.Logan@Sun.COM int HECILinux::SendMessage(const unsigned char *buffer, int len, unsigned long timeout)
241*9203SMark.Logan@Sun.COM {
242*9203SMark.Logan@Sun.COM 	int rv = 0;
243*9203SMark.Logan@Sun.COM 	int return_length =0;
244*9203SMark.Logan@Sun.COM 	int error = 0;
245*9203SMark.Logan@Sun.COM 	fd_set set;
246*9203SMark.Logan@Sun.COM 	struct timeval tv;
247*9203SMark.Logan@Sun.COM 
248*9203SMark.Logan@Sun.COM 	tv.tv_sec =  timeout / 1000;
249*9203SMark.Logan@Sun.COM 	tv.tv_usec =(timeout % 1000) * 1000000;
250*9203SMark.Logan@Sun.COM 
251*9203SMark.Logan@Sun.COM 	if (_verbose) {
252*9203SMark.Logan@Sun.COM 		fprintf(stdout, "call write length = %d\n", len);
253*9203SMark.Logan@Sun.COM 	}
254*9203SMark.Logan@Sun.COM 	rv = write(_fd, (void *)buffer, len);
255*9203SMark.Logan@Sun.COM 	if (rv < 0) {
256*9203SMark.Logan@Sun.COM 		error = errno;
257*9203SMark.Logan@Sun.COM 		if (_verbose) {
258*9203SMark.Logan@Sun.COM 			fprintf(stderr,"write failed with status %d %d\n", rv, error);
259*9203SMark.Logan@Sun.COM 		}
260*9203SMark.Logan@Sun.COM 		goto out;
261*9203SMark.Logan@Sun.COM 	}
262*9203SMark.Logan@Sun.COM 
263*9203SMark.Logan@Sun.COM 	return_length = rv;
264*9203SMark.Logan@Sun.COM 
265*9203SMark.Logan@Sun.COM 	FD_ZERO(&set);
266*9203SMark.Logan@Sun.COM 	FD_SET(_fd, &set);
267*9203SMark.Logan@Sun.COM 	rv = select(_fd+1 ,&set, NULL, NULL, &tv);
268*9203SMark.Logan@Sun.COM 	if (rv > 0 && FD_ISSET(_fd, &set)) {
269*9203SMark.Logan@Sun.COM 		if (_verbose) {
270*9203SMark.Logan@Sun.COM 			fprintf(stderr, "write success\n");
271*9203SMark.Logan@Sun.COM 		}
272*9203SMark.Logan@Sun.COM 	}
273*9203SMark.Logan@Sun.COM 	else if (rv == 0) {
274*9203SMark.Logan@Sun.COM 		if (_verbose) {
275*9203SMark.Logan@Sun.COM 			fprintf(stderr, "write failed on timeout with status\n");
276*9203SMark.Logan@Sun.COM 		}
277*9203SMark.Logan@Sun.COM 		goto out;
278*9203SMark.Logan@Sun.COM 	}
279*9203SMark.Logan@Sun.COM 	else { //rv<0
280*9203SMark.Logan@Sun.COM 		if (_verbose) {
281*9203SMark.Logan@Sun.COM 			fprintf(stderr, "write failed on select with status %d\n", rv);
282*9203SMark.Logan@Sun.COM 		}
283*9203SMark.Logan@Sun.COM 		goto out;
284*9203SMark.Logan@Sun.COM 	}
285*9203SMark.Logan@Sun.COM 
286*9203SMark.Logan@Sun.COM 	rv = return_length;
287*9203SMark.Logan@Sun.COM 
288*9203SMark.Logan@Sun.COM out:
289*9203SMark.Logan@Sun.COM 	if (rv < 0) {
290*9203SMark.Logan@Sun.COM 		Deinit();
291*9203SMark.Logan@Sun.COM 	}
292*9203SMark.Logan@Sun.COM 
293*9203SMark.Logan@Sun.COM 	return rv;
294*9203SMark.Logan@Sun.COM }
295*9203SMark.Logan@Sun.COM 
296