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