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
HECILinux(const GUID guid,bool verbose)85 HECILinux::HECILinux(const GUID guid, bool verbose) :
86 HECI(guid, verbose),
87 _fd(-1),
88 m_haveHeciVersion(false)
89 {
90 }
91
~HECILinux()92 HECILinux::~HECILinux()
93 {
94 if (_fd != -1) {
95 close(_fd);
96 }
97 }
98
GetHeciVersion(HECI_VERSION & version) const99 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
Init(unsigned char reqProtocolVersion)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
Deinit()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
ReceiveMessage(unsigned char * buffer,int len,unsigned long timeout)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
SendMessage(const unsigned char * buffer,int len,unsigned long timeout)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