> 
> Move misc-devices/mei examples to samples/mei and remove it from
> Documentation Makefile. Delete misc-devices/Makefile.
> 
> Create a new Makefile to build samples/mei. It can be built from top level
> directory or from mei directory:
> 
> Run make -C samples/mei or cd samples/mei; make
> 
> Acked-by: Jonathan Corbet <cor...@lwn.net>
> Signed-off-by: Shuah Khan <shua...@osg.samsung.com>


Acked-by: Tomas Winkler <tomas.wink...@intel.com> 


> ---
>  Documentation/Makefile                           |   2 +-
>  Documentation/misc-devices/Makefile              |   1 -
>  Documentation/misc-devices/mei/.gitignore        |   1 -
>  Documentation/misc-devices/mei/Makefile          |   5 -
>  Documentation/misc-devices/mei/TODO              |   2 -
>  Documentation/misc-devices/mei/mei-amt-version.c | 479 --------------------
> ---
>  MAINTAINERS                                      |   1 +
>  samples/mei/.gitignore                           |   1 +
>  samples/mei/Makefile                             |   9 +
>  samples/mei/TODO                                 |   2 +
>  samples/mei/mei-amt-version.c                    | 479
> +++++++++++++++++++++++
>  11 files changed, 493 insertions(+), 489 deletions(-)  delete mode 100644
> Documentation/misc-devices/Makefile
>  delete mode 100644 Documentation/misc-devices/mei/.gitignore
>  delete mode 100644 Documentation/misc-devices/mei/Makefile
>  delete mode 100644 Documentation/misc-devices/mei/TODO
>  delete mode 100644 Documentation/misc-devices/mei/mei-amt-version.c
>  create mode 100644 samples/mei/.gitignore  create mode 100644
> samples/mei/Makefile  create mode 100644 samples/mei/TODO  create
> mode 100644 samples/mei/mei-amt-version.c
> 
> diff --git a/Documentation/Makefile b/Documentation/Makefile index
> 80b5bdc..3c2a207 100644
> --- a/Documentation/Makefile
> +++ b/Documentation/Makefile
> @@ -1,2 +1,2 @@
>  subdir-y := accounting auxdisplay blackfin \
> -     laptops misc-devices pcmcia timers watchdog
> +     laptops pcmcia timers watchdog
> diff --git a/Documentation/misc-devices/Makefile b/Documentation/misc-
> devices/Makefile
> deleted file mode 100644
> index e2b7aa4..0000000
> --- a/Documentation/misc-devices/Makefile
> +++ /dev/null
> @@ -1 +0,0 @@
> -subdir-y := mei
> diff --git a/Documentation/misc-devices/mei/.gitignore
> b/Documentation/misc-devices/mei/.gitignore
> deleted file mode 100644
> index f356b81..0000000
> --- a/Documentation/misc-devices/mei/.gitignore
> +++ /dev/null
> @@ -1 +0,0 @@
> -mei-amt-version
> diff --git a/Documentation/misc-devices/mei/Makefile
> b/Documentation/misc-devices/mei/Makefile
> deleted file mode 100644
> index d758047..0000000
> --- a/Documentation/misc-devices/mei/Makefile
> +++ /dev/null
> @@ -1,5 +0,0 @@
> -# List of programs to build
> -hostprogs-y := mei-amt-version
> -HOSTCFLAGS_mei-amt-version.o += -I$(objtree)/usr/include -# Tell kbuild
> to always build the programs -always := $(hostprogs-y) diff --git
> a/Documentation/misc-devices/mei/TODO b/Documentation/misc-
> devices/mei/TODO
> deleted file mode 100644
> index 6b3625d..0000000
> --- a/Documentation/misc-devices/mei/TODO
> +++ /dev/null
> @@ -1,2 +0,0 @@
> -TODO:
> -     - Cleanup and split the timer function
> diff --git a/Documentation/misc-devices/mei/mei-amt-version.c
> b/Documentation/misc-devices/mei/mei-amt-version.c
> deleted file mode 100644
> index 57d0d87..0000000
> --- a/Documentation/misc-devices/mei/mei-amt-version.c
> +++ /dev/null
> @@ -1,479 +0,0 @@
> -
> /**********************************************************
> ********************
> - * Intel Management Engine Interface (Intel MEI) Linux driver
> - * Intel MEI Interface Header
> - *
> - * This file is provided under a dual BSD/GPLv2 license.  When using or
> - * redistributing this file, you may do so under either license.
> - *
> - * GPL LICENSE SUMMARY
> - *
> - * Copyright(c) 2012 Intel Corporation. All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of version 2 of the GNU General Public License as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> GNU
> - * General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
> - * USA
> - *
> - * The full GNU General Public License is included in this distribution
> - * in the file called LICENSE.GPL.
> - *
> - * Contact Information:
> - *   Intel Corporation.
> - *   linux-...@linux.intel.com
> - *   http://www.intel.com
> - *
> - * BSD LICENSE
> - *
> - * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
> - * All rights reserved.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - *
> - *  * Redistributions of source code must retain the above copyright
> - *    notice, this list of conditions and the following disclaimer.
> - *  * Redistributions in binary form must reproduce the above copyright
> - *    notice, this list of conditions and the following disclaimer in
> - *    the documentation and/or other materials provided with the
> - *    distribution.
> - *  * Neither the name Intel Corporation nor the names of its
> - *    contributors may be used to endorse or promote products derived
> - *    from this software without specific prior written permission.
> - *
> - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> AND ON ANY
> - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> - *
> -
> **********************************************************
> *******************/
> -
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <fcntl.h>
> -#include <sys/ioctl.h>
> -#include <unistd.h>
> -#include <errno.h>
> -#include <stdint.h>
> -#include <stdbool.h>
> -#include <bits/wordsize.h>
> -#include <linux/mei.h>
> -
> -
> /**********************************************************
> *******************
> - * Intel Management Engine Interface
> -
> **********************************************************
> *******************/
> -
> -#define mei_msg(_me, fmt, ARGS...) do {         \
> -     if (_me->verbose)                       \
> -             fprintf(stderr, fmt, ##ARGS);   \
> -} while (0)
> -
> -#define mei_err(_me, fmt, ARGS...) do {         \
> -     fprintf(stderr, "Error: " fmt, ##ARGS); \
> -} while (0)
> -
> -struct mei {
> -     uuid_le guid;
> -     bool initialized;
> -     bool verbose;
> -     unsigned int buf_size;
> -     unsigned char prot_ver;
> -     int fd;
> -};
> -
> -static void mei_deinit(struct mei *cl)
> -{
> -     if (cl->fd != -1)
> -             close(cl->fd);
> -     cl->fd = -1;
> -     cl->buf_size = 0;
> -     cl->prot_ver = 0;
> -     cl->initialized = false;
> -}
> -
> -static bool mei_init(struct mei *me, const uuid_le *guid,
> -             unsigned char req_protocol_version, bool verbose)
> -{
> -     int result;
> -     struct mei_client *cl;
> -     struct mei_connect_client_data data;
> -
> -     me->verbose = verbose;
> -
> -     me->fd = open("/dev/mei", O_RDWR);
> -     if (me->fd == -1) {
> -             mei_err(me, "Cannot establish a handle to the Intel MEI
> driver\n");
> -             goto err;
> -     }
> -     memcpy(&me->guid, guid, sizeof(*guid));
> -     memset(&data, 0, sizeof(data));
> -     me->initialized = true;
> -
> -     memcpy(&data.in_client_uuid, &me->guid, sizeof(me->guid));
> -     result = ioctl(me->fd, IOCTL_MEI_CONNECT_CLIENT, &data);
> -     if (result) {
> -             mei_err(me, "IOCTL_MEI_CONNECT_CLIENT receive
> message. err=%d\n", result);
> -             goto err;
> -     }
> -     cl = &data.out_client_properties;
> -     mei_msg(me, "max_message_length %d\n", cl->max_msg_length);
> -     mei_msg(me, "protocol_version %d\n", cl->protocol_version);
> -
> -     if ((req_protocol_version > 0) &&
> -          (cl->protocol_version != req_protocol_version)) {
> -             mei_err(me, "Intel MEI protocol version not supported\n");
> -             goto err;
> -     }
> -
> -     me->buf_size = cl->max_msg_length;
> -     me->prot_ver = cl->protocol_version;
> -
> -     return true;
> -err:
> -     mei_deinit(me);
> -     return false;
> -}
> -
> -static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer,
> -                     ssize_t len, unsigned long timeout)
> -{
> -     ssize_t rc;
> -
> -     mei_msg(me, "call read length = %zd\n", len);
> -
> -     rc = read(me->fd, buffer, len);
> -     if (rc < 0) {
> -             mei_err(me, "read failed with status %zd %s\n",
> -                             rc, strerror(errno));
> -             mei_deinit(me);
> -     } else {
> -             mei_msg(me, "read succeeded with result %zd\n", rc);
> -     }
> -     return rc;
> -}
> -
> -static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer,
> -                     ssize_t len, unsigned long timeout)
> -{
> -     struct timeval tv;
> -     ssize_t written;
> -     ssize_t rc;
> -     fd_set set;
> -
> -     tv.tv_sec = timeout / 1000;
> -     tv.tv_usec = (timeout % 1000) * 1000000;
> -
> -     mei_msg(me, "call write length = %zd\n", len);
> -
> -     written = write(me->fd, buffer, len);
> -     if (written < 0) {
> -             rc = -errno;
> -             mei_err(me, "write failed with status %zd %s\n",
> -                     written, strerror(errno));
> -             goto out;
> -     }
> -
> -     FD_ZERO(&set);
> -     FD_SET(me->fd, &set);
> -     rc = select(me->fd + 1 , &set, NULL, NULL, &tv);
> -     if (rc > 0 && FD_ISSET(me->fd, &set)) {
> -             mei_msg(me, "write success\n");
> -     } else if (rc == 0) {
> -             mei_err(me, "write failed on timeout with status\n");
> -             goto out;
> -     } else { /* rc < 0 */
> -             mei_err(me, "write failed on select with status %zd\n", rc);
> -             goto out;
> -     }
> -
> -     rc = written;
> -out:
> -     if (rc < 0)
> -             mei_deinit(me);
> -
> -     return rc;
> -}
> -
> -
> /**********************************************************
> *****************
> - * Intel Advanced Management Technology ME Client
> -
> **********************************************************
> *****************/
> -
> -#define AMT_MAJOR_VERSION 1
> -#define AMT_MINOR_VERSION 1
> -
> -#define AMT_STATUS_SUCCESS                0x0
> -#define AMT_STATUS_INTERNAL_ERROR         0x1
> -#define AMT_STATUS_NOT_READY              0x2
> -#define AMT_STATUS_INVALID_AMT_MODE       0x3
> -#define AMT_STATUS_INVALID_MESSAGE_LENGTH 0x4
> -
> -#define AMT_STATUS_HOST_IF_EMPTY_RESPONSE  0x4000
> -#define AMT_STATUS_SDK_RESOURCES      0x1004
> -
> -
> -#define AMT_BIOS_VERSION_LEN   65
> -#define AMT_VERSIONS_NUMBER    50
> -#define AMT_UNICODE_STRING_LEN 20
> -
> -struct amt_unicode_string {
> -     uint16_t length;
> -     char string[AMT_UNICODE_STRING_LEN];
> -} __attribute__((packed));
> -
> -struct amt_version_type {
> -     struct amt_unicode_string description;
> -     struct amt_unicode_string version;
> -} __attribute__((packed));
> -
> -struct amt_version {
> -     uint8_t major;
> -     uint8_t minor;
> -} __attribute__((packed));
> -
> -struct amt_code_versions {
> -     uint8_t bios[AMT_BIOS_VERSION_LEN];
> -     uint32_t count;
> -     struct amt_version_type versions[AMT_VERSIONS_NUMBER];
> -} __attribute__((packed));
> -
> -
> /**********************************************************
> *****************
> - * Intel Advanced Management Technology Host Interface
> -
> **********************************************************
> *****************/
> -
> -struct amt_host_if_msg_header {
> -     struct amt_version version;
> -     uint16_t _reserved;
> -     uint32_t command;
> -     uint32_t length;
> -} __attribute__((packed));
> -
> -struct amt_host_if_resp_header {
> -     struct amt_host_if_msg_header header;
> -     uint32_t status;
> -     unsigned char data[0];
> -} __attribute__((packed));
> -
> -const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,  \
> -                             0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c);
> -
> -#define AMT_HOST_IF_CODE_VERSIONS_REQUEST  0x0400001A -#define
> AMT_HOST_IF_CODE_VERSIONS_RESPONSE 0x0480001A
> -
> -const struct amt_host_if_msg_header CODE_VERSION_REQ = {
> -     .version = {AMT_MAJOR_VERSION, AMT_MINOR_VERSION},
> -     ._reserved = 0,
> -     .command = AMT_HOST_IF_CODE_VERSIONS_REQUEST,
> -     .length = 0
> -};
> -
> -
> -struct amt_host_if {
> -     struct mei mei_cl;
> -     unsigned long send_timeout;
> -     bool initialized;
> -};
> -
> -
> -static bool amt_host_if_init(struct amt_host_if *acmd,
> -                   unsigned long send_timeout, bool verbose)
> -{
> -     acmd->send_timeout = (send_timeout) ? send_timeout : 20000;
> -     acmd->initialized = mei_init(&acmd->mei_cl, &MEI_IAMTHIF, 0,
> verbose);
> -     return acmd->initialized;
> -}
> -
> -static void amt_host_if_deinit(struct amt_host_if *acmd) -{
> -     mei_deinit(&acmd->mei_cl);
> -     acmd->initialized = false;
> -}
> -
> -static uint32_t amt_verify_code_versions(const struct
> amt_host_if_resp_header *resp) -{
> -     uint32_t status = AMT_STATUS_SUCCESS;
> -     struct amt_code_versions *code_ver;
> -     size_t code_ver_len;
> -     uint32_t ver_type_cnt;
> -     uint32_t len;
> -     uint32_t i;
> -
> -     code_ver = (struct amt_code_versions *)resp->data;
> -     /* length - sizeof(status) */
> -     code_ver_len = resp->header.length - sizeof(uint32_t);
> -     ver_type_cnt = code_ver_len -
> -                     sizeof(code_ver->bios) -
> -                     sizeof(code_ver->count);
> -     if (code_ver->count != ver_type_cnt / sizeof(struct
> amt_version_type)) {
> -             status = AMT_STATUS_INTERNAL_ERROR;
> -             goto out;
> -     }
> -
> -     for (i = 0; i < code_ver->count; i++) {
> -             len = code_ver->versions[i].description.length;
> -
> -             if (len > AMT_UNICODE_STRING_LEN) {
> -                     status = AMT_STATUS_INTERNAL_ERROR;
> -                     goto out;
> -             }
> -
> -             len = code_ver->versions[i].version.length;
> -             if (code_ver->versions[i].version.string[len] != '\0' ||
> -                 len != strlen(code_ver->versions[i].version.string)) {
> -                     status = AMT_STATUS_INTERNAL_ERROR;
> -                     goto out;
> -             }
> -     }
> -out:
> -     return status;
> -}
> -
> -static uint32_t amt_verify_response_header(uint32_t command,
> -                             const struct amt_host_if_msg_header
> *resp_hdr,
> -                             uint32_t response_size)
> -{
> -     if (response_size < sizeof(struct amt_host_if_resp_header)) {
> -             return AMT_STATUS_INTERNAL_ERROR;
> -     } else if (response_size != (resp_hdr->length +
> -                             sizeof(struct amt_host_if_msg_header))) {
> -             return AMT_STATUS_INTERNAL_ERROR;
> -     } else if (resp_hdr->command != command) {
> -             return AMT_STATUS_INTERNAL_ERROR;
> -     } else if (resp_hdr->_reserved != 0) {
> -             return AMT_STATUS_INTERNAL_ERROR;
> -     } else if (resp_hdr->version.major != AMT_MAJOR_VERSION ||
> -                resp_hdr->version.minor < AMT_MINOR_VERSION) {
> -             return AMT_STATUS_INTERNAL_ERROR;
> -     }
> -     return AMT_STATUS_SUCCESS;
> -}
> -
> -static uint32_t amt_host_if_call(struct amt_host_if *acmd,
> -                     const unsigned char *command, ssize_t
> command_sz,
> -                     uint8_t **read_buf, uint32_t rcmd,
> -                     unsigned int expected_sz)
> -{
> -     uint32_t in_buf_sz;
> -     uint32_t out_buf_sz;
> -     ssize_t written;
> -     uint32_t status;
> -     struct amt_host_if_resp_header *msg_hdr;
> -
> -     in_buf_sz = acmd->mei_cl.buf_size;
> -     *read_buf = (uint8_t *)malloc(sizeof(uint8_t) * in_buf_sz);
> -     if (*read_buf == NULL)
> -             return AMT_STATUS_SDK_RESOURCES;
> -     memset(*read_buf, 0, in_buf_sz);
> -     msg_hdr = (struct amt_host_if_resp_header *)*read_buf;
> -
> -     written = mei_send_msg(&acmd->mei_cl,
> -                             command, command_sz, acmd-
> >send_timeout);
> -     if (written != command_sz)
> -             return AMT_STATUS_INTERNAL_ERROR;
> -
> -     out_buf_sz = mei_recv_msg(&acmd->mei_cl, *read_buf, in_buf_sz,
> 2000);
> -     if (out_buf_sz <= 0)
> -             return AMT_STATUS_HOST_IF_EMPTY_RESPONSE;
> -
> -     status = msg_hdr->status;
> -     if (status != AMT_STATUS_SUCCESS)
> -             return status;
> -
> -     status = amt_verify_response_header(rcmd,
> -                             &msg_hdr->header, out_buf_sz);
> -     if (status != AMT_STATUS_SUCCESS)
> -             return status;
> -
> -     if (expected_sz && expected_sz != out_buf_sz)
> -             return AMT_STATUS_INTERNAL_ERROR;
> -
> -     return AMT_STATUS_SUCCESS;
> -}
> -
> -
> -static uint32_t amt_get_code_versions(struct amt_host_if *cmd,
> -                            struct amt_code_versions *versions)
> -{
> -     struct amt_host_if_resp_header *response = NULL;
> -     uint32_t status;
> -
> -     status = amt_host_if_call(cmd,
> -                     (const unsigned char *)&CODE_VERSION_REQ,
> -                     sizeof(CODE_VERSION_REQ),
> -                     (uint8_t **)&response,
> -                     AMT_HOST_IF_CODE_VERSIONS_RESPONSE, 0);
> -
> -     if (status != AMT_STATUS_SUCCESS)
> -             goto out;
> -
> -     status = amt_verify_code_versions(response);
> -     if (status != AMT_STATUS_SUCCESS)
> -             goto out;
> -
> -     memcpy(versions, response->data, sizeof(struct
> amt_code_versions));
> -out:
> -     if (response != NULL)
> -             free(response);
> -
> -     return status;
> -}
> -
> -/************************** end of amt_host_if_command
> ***********************/ -int main(int argc, char **argv) -{
> -     struct amt_code_versions ver;
> -     struct amt_host_if acmd;
> -     unsigned int i;
> -     uint32_t status;
> -     int ret;
> -     bool verbose;
> -
> -     verbose = (argc > 1 && strcmp(argv[1], "-v") == 0);
> -
> -     if (!amt_host_if_init(&acmd, 5000, verbose)) {
> -             ret = 1;
> -             goto out;
> -     }
> -
> -     status = amt_get_code_versions(&acmd, &ver);
> -
> -     amt_host_if_deinit(&acmd);
> -
> -     switch (status) {
> -     case AMT_STATUS_HOST_IF_EMPTY_RESPONSE:
> -             printf("Intel AMT: DISABLED\n");
> -             ret = 0;
> -             break;
> -     case AMT_STATUS_SUCCESS:
> -             printf("Intel AMT: ENABLED\n");
> -             for (i = 0; i < ver.count; i++) {
> -                     printf("%s:\t%s\n", ver.versions[i].description.string,
> -                             ver.versions[i].version.string);
> -             }
> -             ret = 0;
> -             break;
> -     default:
> -             printf("An error has occurred\n");
> -             ret = 1;
> -             break;
> -     }
> -
> -out:
> -     return ret;
> -}
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a5e1270..afd3577 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6261,6 +6261,7 @@ F:      include/linux/mei_cl_bus.h
>  F:   drivers/misc/mei/*
>  F:   drivers/watchdog/mei_wdt.c
>  F:   Documentation/misc-devices/mei/*
> +F:   samples/mei/*
> 
>  INTEL MIC DRIVERS (mic)
>  M:   Sudeep Dutt <sudeep.d...@intel.com>
> diff --git a/samples/mei/.gitignore b/samples/mei/.gitignore new file mode
> 100644 index 0000000..f356b81
> --- /dev/null
> +++ b/samples/mei/.gitignore
> @@ -0,0 +1 @@
> +mei-amt-version
> diff --git a/samples/mei/Makefile b/samples/mei/Makefile new file mode
> 100644 index 0000000..7aac216
> --- /dev/null
> +++ b/samples/mei/Makefile
> @@ -0,0 +1,9 @@
> +CC := $(CROSS_COMPILE)gcc
> +CFLAGS := -I../../usr/include
> +
> +PROGS := mei-amt-version
> +
> +all: $(PROGS)
> +
> +clean:
> +     rm -fr $(PROGS)
> diff --git a/samples/mei/TODO b/samples/mei/TODO new file mode 100644
> index 0000000..6b3625d
> --- /dev/null
> +++ b/samples/mei/TODO
> @@ -0,0 +1,2 @@
> +TODO:
> +     - Cleanup and split the timer function
> diff --git a/samples/mei/mei-amt-version.c b/samples/mei/mei-amt-
> version.c new file mode 100644 index 0000000..57d0d87
> --- /dev/null
> +++ b/samples/mei/mei-amt-version.c
> @@ -0,0 +1,479 @@
> +/*********************************************************
> *************
> +********
> + * Intel Management Engine Interface (Intel MEI) Linux driver
> + * Intel MEI Interface Header
> + *
> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> + * redistributing this file, you may do so under either license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright(c) 2012 Intel Corporation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
> + * USA
> + *
> + * The full GNU General Public License is included in this distribution
> + * in the file called LICENSE.GPL.
> + *
> + * Contact Information:
> + *   Intel Corporation.
> + *   linux-...@linux.intel.com
> + *   http://www.intel.com
> + *
> + * BSD LICENSE
> + *
> + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + *  * Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + *  * Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in
> + *    the documentation and/or other materials provided with the
> + *    distribution.
> + *  * Neither the name Intel Corporation nor the names of its
> + *    contributors may be used to endorse or promote products derived
> + *    from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS
> +FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> +INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF
> +USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> AND ON
> +ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE
> +USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> + *
> +
> +*********************************************************
> **************
> +******/
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <fcntl.h>
> +#include <sys/ioctl.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <stdint.h>
> +#include <stdbool.h>
> +#include <bits/wordsize.h>
> +#include <linux/mei.h>
> +
> +/*********************************************************
> *************
> +*******
> + * Intel Management Engine Interface
> +
> +*********************************************************
> **************
> +******/
> +
> +#define mei_msg(_me, fmt, ARGS...) do {         \
> +     if (_me->verbose)                       \
> +             fprintf(stderr, fmt, ##ARGS);   \
> +} while (0)
> +
> +#define mei_err(_me, fmt, ARGS...) do {         \
> +     fprintf(stderr, "Error: " fmt, ##ARGS); \ } while (0)
> +
> +struct mei {
> +     uuid_le guid;
> +     bool initialized;
> +     bool verbose;
> +     unsigned int buf_size;
> +     unsigned char prot_ver;
> +     int fd;
> +};
> +
> +static void mei_deinit(struct mei *cl)
> +{
> +     if (cl->fd != -1)
> +             close(cl->fd);
> +     cl->fd = -1;
> +     cl->buf_size = 0;
> +     cl->prot_ver = 0;
> +     cl->initialized = false;
> +}
> +
> +static bool mei_init(struct mei *me, const uuid_le *guid,
> +             unsigned char req_protocol_version, bool verbose) {
> +     int result;
> +     struct mei_client *cl;
> +     struct mei_connect_client_data data;
> +
> +     me->verbose = verbose;
> +
> +     me->fd = open("/dev/mei", O_RDWR);
> +     if (me->fd == -1) {
> +             mei_err(me, "Cannot establish a handle to the Intel MEI
> driver\n");
> +             goto err;
> +     }
> +     memcpy(&me->guid, guid, sizeof(*guid));
> +     memset(&data, 0, sizeof(data));
> +     me->initialized = true;
> +
> +     memcpy(&data.in_client_uuid, &me->guid, sizeof(me->guid));
> +     result = ioctl(me->fd, IOCTL_MEI_CONNECT_CLIENT, &data);
> +     if (result) {
> +             mei_err(me, "IOCTL_MEI_CONNECT_CLIENT receive
> message. err=%d\n", result);
> +             goto err;
> +     }
> +     cl = &data.out_client_properties;
> +     mei_msg(me, "max_message_length %d\n", cl->max_msg_length);
> +     mei_msg(me, "protocol_version %d\n", cl->protocol_version);
> +
> +     if ((req_protocol_version > 0) &&
> +          (cl->protocol_version != req_protocol_version)) {
> +             mei_err(me, "Intel MEI protocol version not supported\n");
> +             goto err;
> +     }
> +
> +     me->buf_size = cl->max_msg_length;
> +     me->prot_ver = cl->protocol_version;
> +
> +     return true;
> +err:
> +     mei_deinit(me);
> +     return false;
> +}
> +
> +static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer,
> +                     ssize_t len, unsigned long timeout)
> +{
> +     ssize_t rc;
> +
> +     mei_msg(me, "call read length = %zd\n", len);
> +
> +     rc = read(me->fd, buffer, len);
> +     if (rc < 0) {
> +             mei_err(me, "read failed with status %zd %s\n",
> +                             rc, strerror(errno));
> +             mei_deinit(me);
> +     } else {
> +             mei_msg(me, "read succeeded with result %zd\n", rc);
> +     }
> +     return rc;
> +}
> +
> +static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer,
> +                     ssize_t len, unsigned long timeout)
> +{
> +     struct timeval tv;
> +     ssize_t written;
> +     ssize_t rc;
> +     fd_set set;
> +
> +     tv.tv_sec = timeout / 1000;
> +     tv.tv_usec = (timeout % 1000) * 1000000;
> +
> +     mei_msg(me, "call write length = %zd\n", len);
> +
> +     written = write(me->fd, buffer, len);
> +     if (written < 0) {
> +             rc = -errno;
> +             mei_err(me, "write failed with status %zd %s\n",
> +                     written, strerror(errno));
> +             goto out;
> +     }
> +
> +     FD_ZERO(&set);
> +     FD_SET(me->fd, &set);
> +     rc = select(me->fd + 1 , &set, NULL, NULL, &tv);
> +     if (rc > 0 && FD_ISSET(me->fd, &set)) {
> +             mei_msg(me, "write success\n");
> +     } else if (rc == 0) {
> +             mei_err(me, "write failed on timeout with status\n");
> +             goto out;
> +     } else { /* rc < 0 */
> +             mei_err(me, "write failed on select with status %zd\n", rc);
> +             goto out;
> +     }
> +
> +     rc = written;
> +out:
> +     if (rc < 0)
> +             mei_deinit(me);
> +
> +     return rc;
> +}
> +
> +/*********************************************************
> *************
> +*****
> + * Intel Advanced Management Technology ME Client
> +*********************************************************
> **************
> +****/
> +
> +#define AMT_MAJOR_VERSION 1
> +#define AMT_MINOR_VERSION 1
> +
> +#define AMT_STATUS_SUCCESS                0x0
> +#define AMT_STATUS_INTERNAL_ERROR         0x1
> +#define AMT_STATUS_NOT_READY              0x2
> +#define AMT_STATUS_INVALID_AMT_MODE       0x3
> +#define AMT_STATUS_INVALID_MESSAGE_LENGTH 0x4
> +
> +#define AMT_STATUS_HOST_IF_EMPTY_RESPONSE  0x4000
> +#define AMT_STATUS_SDK_RESOURCES      0x1004
> +
> +
> +#define AMT_BIOS_VERSION_LEN   65
> +#define AMT_VERSIONS_NUMBER    50
> +#define AMT_UNICODE_STRING_LEN 20
> +
> +struct amt_unicode_string {
> +     uint16_t length;
> +     char string[AMT_UNICODE_STRING_LEN];
> +} __attribute__((packed));
> +
> +struct amt_version_type {
> +     struct amt_unicode_string description;
> +     struct amt_unicode_string version;
> +} __attribute__((packed));
> +
> +struct amt_version {
> +     uint8_t major;
> +     uint8_t minor;
> +} __attribute__((packed));
> +
> +struct amt_code_versions {
> +     uint8_t bios[AMT_BIOS_VERSION_LEN];
> +     uint32_t count;
> +     struct amt_version_type versions[AMT_VERSIONS_NUMBER]; }
> +__attribute__((packed));
> +
> +/*********************************************************
> *************
> +*****
> + * Intel Advanced Management Technology Host Interface
> +*********************************************************
> **************
> +****/
> +
> +struct amt_host_if_msg_header {
> +     struct amt_version version;
> +     uint16_t _reserved;
> +     uint32_t command;
> +     uint32_t length;
> +} __attribute__((packed));
> +
> +struct amt_host_if_resp_header {
> +     struct amt_host_if_msg_header header;
> +     uint32_t status;
> +     unsigned char data[0];
> +} __attribute__((packed));
> +
> +const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,  \
> +                             0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c);
> +
> +#define AMT_HOST_IF_CODE_VERSIONS_REQUEST  0x0400001A #define
> +AMT_HOST_IF_CODE_VERSIONS_RESPONSE 0x0480001A
> +
> +const struct amt_host_if_msg_header CODE_VERSION_REQ = {
> +     .version = {AMT_MAJOR_VERSION, AMT_MINOR_VERSION},
> +     ._reserved = 0,
> +     .command = AMT_HOST_IF_CODE_VERSIONS_REQUEST,
> +     .length = 0
> +};
> +
> +
> +struct amt_host_if {
> +     struct mei mei_cl;
> +     unsigned long send_timeout;
> +     bool initialized;
> +};
> +
> +
> +static bool amt_host_if_init(struct amt_host_if *acmd,
> +                   unsigned long send_timeout, bool verbose) {
> +     acmd->send_timeout = (send_timeout) ? send_timeout : 20000;
> +     acmd->initialized = mei_init(&acmd->mei_cl, &MEI_IAMTHIF, 0,
> verbose);
> +     return acmd->initialized;
> +}
> +
> +static void amt_host_if_deinit(struct amt_host_if *acmd) {
> +     mei_deinit(&acmd->mei_cl);
> +     acmd->initialized = false;
> +}
> +
> +static uint32_t amt_verify_code_versions(const struct
> +amt_host_if_resp_header *resp) {
> +     uint32_t status = AMT_STATUS_SUCCESS;
> +     struct amt_code_versions *code_ver;
> +     size_t code_ver_len;
> +     uint32_t ver_type_cnt;
> +     uint32_t len;
> +     uint32_t i;
> +
> +     code_ver = (struct amt_code_versions *)resp->data;
> +     /* length - sizeof(status) */
> +     code_ver_len = resp->header.length - sizeof(uint32_t);
> +     ver_type_cnt = code_ver_len -
> +                     sizeof(code_ver->bios) -
> +                     sizeof(code_ver->count);
> +     if (code_ver->count != ver_type_cnt / sizeof(struct
> amt_version_type)) {
> +             status = AMT_STATUS_INTERNAL_ERROR;
> +             goto out;
> +     }
> +
> +     for (i = 0; i < code_ver->count; i++) {
> +             len = code_ver->versions[i].description.length;
> +
> +             if (len > AMT_UNICODE_STRING_LEN) {
> +                     status = AMT_STATUS_INTERNAL_ERROR;
> +                     goto out;
> +             }
> +
> +             len = code_ver->versions[i].version.length;
> +             if (code_ver->versions[i].version.string[len] != '\0' ||
> +                 len != strlen(code_ver->versions[i].version.string)) {
> +                     status = AMT_STATUS_INTERNAL_ERROR;
> +                     goto out;
> +             }
> +     }
> +out:
> +     return status;
> +}
> +
> +static uint32_t amt_verify_response_header(uint32_t command,
> +                             const struct amt_host_if_msg_header
> *resp_hdr,
> +                             uint32_t response_size)
> +{
> +     if (response_size < sizeof(struct amt_host_if_resp_header)) {
> +             return AMT_STATUS_INTERNAL_ERROR;
> +     } else if (response_size != (resp_hdr->length +
> +                             sizeof(struct amt_host_if_msg_header))) {
> +             return AMT_STATUS_INTERNAL_ERROR;
> +     } else if (resp_hdr->command != command) {
> +             return AMT_STATUS_INTERNAL_ERROR;
> +     } else if (resp_hdr->_reserved != 0) {
> +             return AMT_STATUS_INTERNAL_ERROR;
> +     } else if (resp_hdr->version.major != AMT_MAJOR_VERSION ||
> +                resp_hdr->version.minor < AMT_MINOR_VERSION) {
> +             return AMT_STATUS_INTERNAL_ERROR;
> +     }
> +     return AMT_STATUS_SUCCESS;
> +}
> +
> +static uint32_t amt_host_if_call(struct amt_host_if *acmd,
> +                     const unsigned char *command, ssize_t
> command_sz,
> +                     uint8_t **read_buf, uint32_t rcmd,
> +                     unsigned int expected_sz)
> +{
> +     uint32_t in_buf_sz;
> +     uint32_t out_buf_sz;
> +     ssize_t written;
> +     uint32_t status;
> +     struct amt_host_if_resp_header *msg_hdr;
> +
> +     in_buf_sz = acmd->mei_cl.buf_size;
> +     *read_buf = (uint8_t *)malloc(sizeof(uint8_t) * in_buf_sz);
> +     if (*read_buf == NULL)
> +             return AMT_STATUS_SDK_RESOURCES;
> +     memset(*read_buf, 0, in_buf_sz);
> +     msg_hdr = (struct amt_host_if_resp_header *)*read_buf;
> +
> +     written = mei_send_msg(&acmd->mei_cl,
> +                             command, command_sz, acmd-
> >send_timeout);
> +     if (written != command_sz)
> +             return AMT_STATUS_INTERNAL_ERROR;
> +
> +     out_buf_sz = mei_recv_msg(&acmd->mei_cl, *read_buf, in_buf_sz,
> 2000);
> +     if (out_buf_sz <= 0)
> +             return AMT_STATUS_HOST_IF_EMPTY_RESPONSE;
> +
> +     status = msg_hdr->status;
> +     if (status != AMT_STATUS_SUCCESS)
> +             return status;
> +
> +     status = amt_verify_response_header(rcmd,
> +                             &msg_hdr->header, out_buf_sz);
> +     if (status != AMT_STATUS_SUCCESS)
> +             return status;
> +
> +     if (expected_sz && expected_sz != out_buf_sz)
> +             return AMT_STATUS_INTERNAL_ERROR;
> +
> +     return AMT_STATUS_SUCCESS;
> +}
> +
> +
> +static uint32_t amt_get_code_versions(struct amt_host_if *cmd,
> +                            struct amt_code_versions *versions) {
> +     struct amt_host_if_resp_header *response = NULL;
> +     uint32_t status;
> +
> +     status = amt_host_if_call(cmd,
> +                     (const unsigned char *)&CODE_VERSION_REQ,
> +                     sizeof(CODE_VERSION_REQ),
> +                     (uint8_t **)&response,
> +                     AMT_HOST_IF_CODE_VERSIONS_RESPONSE, 0);
> +
> +     if (status != AMT_STATUS_SUCCESS)
> +             goto out;
> +
> +     status = amt_verify_code_versions(response);
> +     if (status != AMT_STATUS_SUCCESS)
> +             goto out;
> +
> +     memcpy(versions, response->data, sizeof(struct
> amt_code_versions));
> +out:
> +     if (response != NULL)
> +             free(response);
> +
> +     return status;
> +}
> +
> +/************************** end of amt_host_if_command
> +***********************/ int main(int argc, char **argv) {
> +     struct amt_code_versions ver;
> +     struct amt_host_if acmd;
> +     unsigned int i;
> +     uint32_t status;
> +     int ret;
> +     bool verbose;
> +
> +     verbose = (argc > 1 && strcmp(argv[1], "-v") == 0);
> +
> +     if (!amt_host_if_init(&acmd, 5000, verbose)) {
> +             ret = 1;
> +             goto out;
> +     }
> +
> +     status = amt_get_code_versions(&acmd, &ver);
> +
> +     amt_host_if_deinit(&acmd);
> +
> +     switch (status) {
> +     case AMT_STATUS_HOST_IF_EMPTY_RESPONSE:
> +             printf("Intel AMT: DISABLED\n");
> +             ret = 0;
> +             break;
> +     case AMT_STATUS_SUCCESS:
> +             printf("Intel AMT: ENABLED\n");
> +             for (i = 0; i < ver.count; i++) {
> +                     printf("%s:\t%s\n", ver.versions[i].description.string,
> +                             ver.versions[i].version.string);
> +             }
> +             ret = 0;
> +             break;
> +     default:
> +             printf("An error has occurred\n");
> +             ret = 1;
> +             break;
> +     }
> +
> +out:
> +     return ret;
> +}
> --
> 2.7.4

Reply via email to