162306a36Sopenharmony_ci/****************************************************************************** 262306a36Sopenharmony_ci * Intel Management Engine Interface (Intel MEI) Linux driver 362306a36Sopenharmony_ci * Intel MEI Interface Header 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license. When using or 662306a36Sopenharmony_ci * redistributing this file, you may do so under either license. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * GPL LICENSE SUMMARY 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Copyright(c) 2012 Intel Corporation. All rights reserved. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 1362306a36Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as 1462306a36Sopenharmony_ci * published by the Free Software Foundation. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 1762306a36Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 1862306a36Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1962306a36Sopenharmony_ci * General Public License for more details. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * You should have received a copy of the GNU General Public License 2262306a36Sopenharmony_ci * along with this program; if not, write to the Free Software 2362306a36Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, 2462306a36Sopenharmony_ci * USA 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * The full GNU General Public License is included in this distribution 2762306a36Sopenharmony_ci * in the file called LICENSE.GPL. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Contact Information: 3062306a36Sopenharmony_ci * Intel Corporation. 3162306a36Sopenharmony_ci * linux-mei@linux.intel.com 3262306a36Sopenharmony_ci * http://www.intel.com 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * BSD LICENSE 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. 3762306a36Sopenharmony_ci * All rights reserved. 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 4062306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 4162306a36Sopenharmony_ci * are met: 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * * Redistributions of source code must retain the above copyright 4462306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 4562306a36Sopenharmony_ci * * Redistributions in binary form must reproduce the above copyright 4662306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 4762306a36Sopenharmony_ci * the documentation and/or other materials provided with the 4862306a36Sopenharmony_ci * distribution. 4962306a36Sopenharmony_ci * * Neither the name Intel Corporation nor the names of its 5062306a36Sopenharmony_ci * contributors may be used to endorse or promote products derived 5162306a36Sopenharmony_ci * from this software without specific prior written permission. 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 5462306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 5562306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 5662306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 5762306a36Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 5862306a36Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 5962306a36Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 6062306a36Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 6162306a36Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 6262306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 6362306a36Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci *****************************************************************************/ 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#include <stdio.h> 6862306a36Sopenharmony_ci#include <stdlib.h> 6962306a36Sopenharmony_ci#include <string.h> 7062306a36Sopenharmony_ci#include <fcntl.h> 7162306a36Sopenharmony_ci#include <sys/ioctl.h> 7262306a36Sopenharmony_ci#include <unistd.h> 7362306a36Sopenharmony_ci#include <errno.h> 7462306a36Sopenharmony_ci#include <stdint.h> 7562306a36Sopenharmony_ci#include <stdbool.h> 7662306a36Sopenharmony_ci#include <bits/wordsize.h> 7762306a36Sopenharmony_ci#include <linux/mei.h> 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/***************************************************************************** 8062306a36Sopenharmony_ci * Intel Management Engine Interface 8162306a36Sopenharmony_ci *****************************************************************************/ 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#define mei_msg(_me, fmt, ARGS...) do { \ 8462306a36Sopenharmony_ci if (_me->verbose) \ 8562306a36Sopenharmony_ci fprintf(stderr, fmt, ##ARGS); \ 8662306a36Sopenharmony_ci} while (0) 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define mei_err(_me, fmt, ARGS...) do { \ 8962306a36Sopenharmony_ci fprintf(stderr, "Error: " fmt, ##ARGS); \ 9062306a36Sopenharmony_ci} while (0) 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistruct mei { 9362306a36Sopenharmony_ci uuid_le guid; 9462306a36Sopenharmony_ci bool initialized; 9562306a36Sopenharmony_ci bool verbose; 9662306a36Sopenharmony_ci unsigned int buf_size; 9762306a36Sopenharmony_ci unsigned char prot_ver; 9862306a36Sopenharmony_ci int fd; 9962306a36Sopenharmony_ci}; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic void mei_deinit(struct mei *cl) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci if (cl->fd != -1) 10462306a36Sopenharmony_ci close(cl->fd); 10562306a36Sopenharmony_ci cl->fd = -1; 10662306a36Sopenharmony_ci cl->buf_size = 0; 10762306a36Sopenharmony_ci cl->prot_ver = 0; 10862306a36Sopenharmony_ci cl->initialized = false; 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic bool mei_init(struct mei *me, const uuid_le *guid, 11262306a36Sopenharmony_ci unsigned char req_protocol_version, bool verbose) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci int result; 11562306a36Sopenharmony_ci struct mei_client *cl; 11662306a36Sopenharmony_ci struct mei_connect_client_data data; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci me->verbose = verbose; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci me->fd = open("/dev/mei0", O_RDWR); 12162306a36Sopenharmony_ci if (me->fd == -1) { 12262306a36Sopenharmony_ci mei_err(me, "Cannot establish a handle to the Intel MEI driver\n"); 12362306a36Sopenharmony_ci goto err; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci memcpy(&me->guid, guid, sizeof(*guid)); 12662306a36Sopenharmony_ci memset(&data, 0, sizeof(data)); 12762306a36Sopenharmony_ci me->initialized = true; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci memcpy(&data.in_client_uuid, &me->guid, sizeof(me->guid)); 13062306a36Sopenharmony_ci result = ioctl(me->fd, IOCTL_MEI_CONNECT_CLIENT, &data); 13162306a36Sopenharmony_ci if (result) { 13262306a36Sopenharmony_ci mei_err(me, "IOCTL_MEI_CONNECT_CLIENT receive message. err=%d\n", result); 13362306a36Sopenharmony_ci goto err; 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci cl = &data.out_client_properties; 13662306a36Sopenharmony_ci mei_msg(me, "max_message_length %d\n", cl->max_msg_length); 13762306a36Sopenharmony_ci mei_msg(me, "protocol_version %d\n", cl->protocol_version); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if ((req_protocol_version > 0) && 14062306a36Sopenharmony_ci (cl->protocol_version != req_protocol_version)) { 14162306a36Sopenharmony_ci mei_err(me, "Intel MEI protocol version not supported\n"); 14262306a36Sopenharmony_ci goto err; 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci me->buf_size = cl->max_msg_length; 14662306a36Sopenharmony_ci me->prot_ver = cl->protocol_version; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci return true; 14962306a36Sopenharmony_cierr: 15062306a36Sopenharmony_ci mei_deinit(me); 15162306a36Sopenharmony_ci return false; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer, 15562306a36Sopenharmony_ci ssize_t len, unsigned long timeout) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci struct timeval tv; 15862306a36Sopenharmony_ci fd_set set; 15962306a36Sopenharmony_ci ssize_t rc; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci tv.tv_sec = timeout / 1000; 16262306a36Sopenharmony_ci tv.tv_usec = (timeout % 1000) * 1000000; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci mei_msg(me, "call read length = %zd\n", len); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci FD_ZERO(&set); 16762306a36Sopenharmony_ci FD_SET(me->fd, &set); 16862306a36Sopenharmony_ci rc = select(me->fd + 1, &set, NULL, NULL, &tv); 16962306a36Sopenharmony_ci if (rc > 0 && FD_ISSET(me->fd, &set)) { 17062306a36Sopenharmony_ci mei_msg(me, "have reply\n"); 17162306a36Sopenharmony_ci } else if (rc == 0) { 17262306a36Sopenharmony_ci rc = -1; 17362306a36Sopenharmony_ci mei_err(me, "read failed on timeout\n"); 17462306a36Sopenharmony_ci goto out; 17562306a36Sopenharmony_ci } else { /* rc < 0 */ 17662306a36Sopenharmony_ci rc = errno; 17762306a36Sopenharmony_ci mei_err(me, "read failed on select with status %zd %s\n", 17862306a36Sopenharmony_ci rc, strerror(errno)); 17962306a36Sopenharmony_ci goto out; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci rc = read(me->fd, buffer, len); 18362306a36Sopenharmony_ci if (rc < 0) { 18462306a36Sopenharmony_ci mei_err(me, "read failed with status %zd %s\n", 18562306a36Sopenharmony_ci rc, strerror(errno)); 18662306a36Sopenharmony_ci goto out; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci mei_msg(me, "read succeeded with result %zd\n", rc); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ciout: 19262306a36Sopenharmony_ci if (rc < 0) 19362306a36Sopenharmony_ci mei_deinit(me); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci return rc; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer, 19962306a36Sopenharmony_ci ssize_t len, unsigned long timeout) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci ssize_t written; 20262306a36Sopenharmony_ci ssize_t rc; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci mei_msg(me, "call write length = %zd\n", len); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci written = write(me->fd, buffer, len); 20762306a36Sopenharmony_ci if (written < 0) { 20862306a36Sopenharmony_ci rc = -errno; 20962306a36Sopenharmony_ci mei_err(me, "write failed with status %zd %s\n", 21062306a36Sopenharmony_ci written, strerror(errno)); 21162306a36Sopenharmony_ci goto out; 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci mei_msg(me, "write success\n"); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci rc = written; 21662306a36Sopenharmony_ciout: 21762306a36Sopenharmony_ci if (rc < 0) 21862306a36Sopenharmony_ci mei_deinit(me); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci return rc; 22162306a36Sopenharmony_ci} 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci/*************************************************************************** 22462306a36Sopenharmony_ci * Intel Advanced Management Technology ME Client 22562306a36Sopenharmony_ci ***************************************************************************/ 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci#define AMT_MAJOR_VERSION 1 22862306a36Sopenharmony_ci#define AMT_MINOR_VERSION 1 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci#define AMT_STATUS_SUCCESS 0x0 23162306a36Sopenharmony_ci#define AMT_STATUS_INTERNAL_ERROR 0x1 23262306a36Sopenharmony_ci#define AMT_STATUS_NOT_READY 0x2 23362306a36Sopenharmony_ci#define AMT_STATUS_INVALID_AMT_MODE 0x3 23462306a36Sopenharmony_ci#define AMT_STATUS_INVALID_MESSAGE_LENGTH 0x4 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci#define AMT_STATUS_HOST_IF_EMPTY_RESPONSE 0x4000 23762306a36Sopenharmony_ci#define AMT_STATUS_SDK_RESOURCES 0x1004 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci#define AMT_BIOS_VERSION_LEN 65 24162306a36Sopenharmony_ci#define AMT_VERSIONS_NUMBER 50 24262306a36Sopenharmony_ci#define AMT_UNICODE_STRING_LEN 20 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistruct amt_unicode_string { 24562306a36Sopenharmony_ci uint16_t length; 24662306a36Sopenharmony_ci char string[AMT_UNICODE_STRING_LEN]; 24762306a36Sopenharmony_ci} __attribute__((packed)); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistruct amt_version_type { 25062306a36Sopenharmony_ci struct amt_unicode_string description; 25162306a36Sopenharmony_ci struct amt_unicode_string version; 25262306a36Sopenharmony_ci} __attribute__((packed)); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistruct amt_version { 25562306a36Sopenharmony_ci uint8_t major; 25662306a36Sopenharmony_ci uint8_t minor; 25762306a36Sopenharmony_ci} __attribute__((packed)); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistruct amt_code_versions { 26062306a36Sopenharmony_ci uint8_t bios[AMT_BIOS_VERSION_LEN]; 26162306a36Sopenharmony_ci uint32_t count; 26262306a36Sopenharmony_ci struct amt_version_type versions[AMT_VERSIONS_NUMBER]; 26362306a36Sopenharmony_ci} __attribute__((packed)); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci/*************************************************************************** 26662306a36Sopenharmony_ci * Intel Advanced Management Technology Host Interface 26762306a36Sopenharmony_ci ***************************************************************************/ 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistruct amt_host_if_msg_header { 27062306a36Sopenharmony_ci struct amt_version version; 27162306a36Sopenharmony_ci uint16_t _reserved; 27262306a36Sopenharmony_ci uint32_t command; 27362306a36Sopenharmony_ci uint32_t length; 27462306a36Sopenharmony_ci} __attribute__((packed)); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistruct amt_host_if_resp_header { 27762306a36Sopenharmony_ci struct amt_host_if_msg_header header; 27862306a36Sopenharmony_ci uint32_t status; 27962306a36Sopenharmony_ci unsigned char data[]; 28062306a36Sopenharmony_ci} __attribute__((packed)); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ciconst uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, \ 28362306a36Sopenharmony_ci 0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci#define AMT_HOST_IF_CODE_VERSIONS_REQUEST 0x0400001A 28662306a36Sopenharmony_ci#define AMT_HOST_IF_CODE_VERSIONS_RESPONSE 0x0480001A 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ciconst struct amt_host_if_msg_header CODE_VERSION_REQ = { 28962306a36Sopenharmony_ci .version = {AMT_MAJOR_VERSION, AMT_MINOR_VERSION}, 29062306a36Sopenharmony_ci ._reserved = 0, 29162306a36Sopenharmony_ci .command = AMT_HOST_IF_CODE_VERSIONS_REQUEST, 29262306a36Sopenharmony_ci .length = 0 29362306a36Sopenharmony_ci}; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_cistruct amt_host_if { 29762306a36Sopenharmony_ci struct mei mei_cl; 29862306a36Sopenharmony_ci unsigned long send_timeout; 29962306a36Sopenharmony_ci bool initialized; 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic bool amt_host_if_init(struct amt_host_if *acmd, 30462306a36Sopenharmony_ci unsigned long send_timeout, bool verbose) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci acmd->send_timeout = (send_timeout) ? send_timeout : 20000; 30762306a36Sopenharmony_ci acmd->initialized = mei_init(&acmd->mei_cl, &MEI_IAMTHIF, 0, verbose); 30862306a36Sopenharmony_ci return acmd->initialized; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic void amt_host_if_deinit(struct amt_host_if *acmd) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci mei_deinit(&acmd->mei_cl); 31462306a36Sopenharmony_ci acmd->initialized = false; 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic uint32_t amt_verify_code_versions(const struct amt_host_if_resp_header *resp) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci uint32_t status = AMT_STATUS_SUCCESS; 32062306a36Sopenharmony_ci struct amt_code_versions *code_ver; 32162306a36Sopenharmony_ci size_t code_ver_len; 32262306a36Sopenharmony_ci uint32_t ver_type_cnt; 32362306a36Sopenharmony_ci uint32_t len; 32462306a36Sopenharmony_ci uint32_t i; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci code_ver = (struct amt_code_versions *)resp->data; 32762306a36Sopenharmony_ci /* length - sizeof(status) */ 32862306a36Sopenharmony_ci code_ver_len = resp->header.length - sizeof(uint32_t); 32962306a36Sopenharmony_ci ver_type_cnt = code_ver_len - 33062306a36Sopenharmony_ci sizeof(code_ver->bios) - 33162306a36Sopenharmony_ci sizeof(code_ver->count); 33262306a36Sopenharmony_ci if (code_ver->count != ver_type_cnt / sizeof(struct amt_version_type)) { 33362306a36Sopenharmony_ci status = AMT_STATUS_INTERNAL_ERROR; 33462306a36Sopenharmony_ci goto out; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci for (i = 0; i < code_ver->count; i++) { 33862306a36Sopenharmony_ci len = code_ver->versions[i].description.length; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (len > AMT_UNICODE_STRING_LEN) { 34162306a36Sopenharmony_ci status = AMT_STATUS_INTERNAL_ERROR; 34262306a36Sopenharmony_ci goto out; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci len = code_ver->versions[i].version.length; 34662306a36Sopenharmony_ci if (code_ver->versions[i].version.string[len] != '\0' || 34762306a36Sopenharmony_ci len != strlen(code_ver->versions[i].version.string)) { 34862306a36Sopenharmony_ci status = AMT_STATUS_INTERNAL_ERROR; 34962306a36Sopenharmony_ci goto out; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ciout: 35362306a36Sopenharmony_ci return status; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic uint32_t amt_verify_response_header(uint32_t command, 35762306a36Sopenharmony_ci const struct amt_host_if_msg_header *resp_hdr, 35862306a36Sopenharmony_ci uint32_t response_size) 35962306a36Sopenharmony_ci{ 36062306a36Sopenharmony_ci if (response_size < sizeof(struct amt_host_if_resp_header)) { 36162306a36Sopenharmony_ci return AMT_STATUS_INTERNAL_ERROR; 36262306a36Sopenharmony_ci } else if (response_size != (resp_hdr->length + 36362306a36Sopenharmony_ci sizeof(struct amt_host_if_msg_header))) { 36462306a36Sopenharmony_ci return AMT_STATUS_INTERNAL_ERROR; 36562306a36Sopenharmony_ci } else if (resp_hdr->command != command) { 36662306a36Sopenharmony_ci return AMT_STATUS_INTERNAL_ERROR; 36762306a36Sopenharmony_ci } else if (resp_hdr->_reserved != 0) { 36862306a36Sopenharmony_ci return AMT_STATUS_INTERNAL_ERROR; 36962306a36Sopenharmony_ci } else if (resp_hdr->version.major != AMT_MAJOR_VERSION || 37062306a36Sopenharmony_ci resp_hdr->version.minor < AMT_MINOR_VERSION) { 37162306a36Sopenharmony_ci return AMT_STATUS_INTERNAL_ERROR; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci return AMT_STATUS_SUCCESS; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic uint32_t amt_host_if_call(struct amt_host_if *acmd, 37762306a36Sopenharmony_ci const unsigned char *command, ssize_t command_sz, 37862306a36Sopenharmony_ci uint8_t **read_buf, uint32_t rcmd, 37962306a36Sopenharmony_ci unsigned int expected_sz) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci uint32_t in_buf_sz; 38262306a36Sopenharmony_ci ssize_t out_buf_sz; 38362306a36Sopenharmony_ci ssize_t written; 38462306a36Sopenharmony_ci uint32_t status; 38562306a36Sopenharmony_ci struct amt_host_if_resp_header *msg_hdr; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci in_buf_sz = acmd->mei_cl.buf_size; 38862306a36Sopenharmony_ci *read_buf = (uint8_t *)malloc(sizeof(uint8_t) * in_buf_sz); 38962306a36Sopenharmony_ci if (*read_buf == NULL) 39062306a36Sopenharmony_ci return AMT_STATUS_SDK_RESOURCES; 39162306a36Sopenharmony_ci memset(*read_buf, 0, in_buf_sz); 39262306a36Sopenharmony_ci msg_hdr = (struct amt_host_if_resp_header *)*read_buf; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci written = mei_send_msg(&acmd->mei_cl, 39562306a36Sopenharmony_ci command, command_sz, acmd->send_timeout); 39662306a36Sopenharmony_ci if (written != command_sz) 39762306a36Sopenharmony_ci return AMT_STATUS_INTERNAL_ERROR; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci out_buf_sz = mei_recv_msg(&acmd->mei_cl, *read_buf, in_buf_sz, 2000); 40062306a36Sopenharmony_ci if (out_buf_sz <= 0) 40162306a36Sopenharmony_ci return AMT_STATUS_HOST_IF_EMPTY_RESPONSE; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci status = msg_hdr->status; 40462306a36Sopenharmony_ci if (status != AMT_STATUS_SUCCESS) 40562306a36Sopenharmony_ci return status; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci status = amt_verify_response_header(rcmd, 40862306a36Sopenharmony_ci &msg_hdr->header, out_buf_sz); 40962306a36Sopenharmony_ci if (status != AMT_STATUS_SUCCESS) 41062306a36Sopenharmony_ci return status; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci if (expected_sz && expected_sz != out_buf_sz) 41362306a36Sopenharmony_ci return AMT_STATUS_INTERNAL_ERROR; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci return AMT_STATUS_SUCCESS; 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic uint32_t amt_get_code_versions(struct amt_host_if *cmd, 42062306a36Sopenharmony_ci struct amt_code_versions *versions) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci struct amt_host_if_resp_header *response = NULL; 42362306a36Sopenharmony_ci uint32_t status; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci status = amt_host_if_call(cmd, 42662306a36Sopenharmony_ci (const unsigned char *)&CODE_VERSION_REQ, 42762306a36Sopenharmony_ci sizeof(CODE_VERSION_REQ), 42862306a36Sopenharmony_ci (uint8_t **)&response, 42962306a36Sopenharmony_ci AMT_HOST_IF_CODE_VERSIONS_RESPONSE, 0); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (status != AMT_STATUS_SUCCESS) 43262306a36Sopenharmony_ci goto out; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci status = amt_verify_code_versions(response); 43562306a36Sopenharmony_ci if (status != AMT_STATUS_SUCCESS) 43662306a36Sopenharmony_ci goto out; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci memcpy(versions, response->data, sizeof(struct amt_code_versions)); 43962306a36Sopenharmony_ciout: 44062306a36Sopenharmony_ci if (response != NULL) 44162306a36Sopenharmony_ci free(response); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci return status; 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci/************************** end of amt_host_if_command ***********************/ 44762306a36Sopenharmony_ciint main(int argc, char **argv) 44862306a36Sopenharmony_ci{ 44962306a36Sopenharmony_ci struct amt_code_versions ver; 45062306a36Sopenharmony_ci struct amt_host_if acmd; 45162306a36Sopenharmony_ci unsigned int i; 45262306a36Sopenharmony_ci uint32_t status; 45362306a36Sopenharmony_ci int ret; 45462306a36Sopenharmony_ci bool verbose; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci verbose = (argc > 1 && strcmp(argv[1], "-v") == 0); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci if (!amt_host_if_init(&acmd, 5000, verbose)) { 45962306a36Sopenharmony_ci ret = 1; 46062306a36Sopenharmony_ci goto out; 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci status = amt_get_code_versions(&acmd, &ver); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci amt_host_if_deinit(&acmd); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci switch (status) { 46862306a36Sopenharmony_ci case AMT_STATUS_HOST_IF_EMPTY_RESPONSE: 46962306a36Sopenharmony_ci printf("Intel AMT: DISABLED\n"); 47062306a36Sopenharmony_ci ret = 0; 47162306a36Sopenharmony_ci break; 47262306a36Sopenharmony_ci case AMT_STATUS_SUCCESS: 47362306a36Sopenharmony_ci printf("Intel AMT: ENABLED\n"); 47462306a36Sopenharmony_ci for (i = 0; i < ver.count; i++) { 47562306a36Sopenharmony_ci printf("%s:\t%s\n", ver.versions[i].description.string, 47662306a36Sopenharmony_ci ver.versions[i].version.string); 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci ret = 0; 47962306a36Sopenharmony_ci break; 48062306a36Sopenharmony_ci default: 48162306a36Sopenharmony_ci printf("An error has occurred\n"); 48262306a36Sopenharmony_ci ret = 1; 48362306a36Sopenharmony_ci break; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ciout: 48762306a36Sopenharmony_ci return ret; 48862306a36Sopenharmony_ci} 489