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