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