Commit 5a44988207ee16b96e5445b8e95ab9881ce310cc
Committed by
Greg Kroah-Hartman
1 parent
4f3afe1d8c
Exists in
master
and in
20 other branches
mei: move doc files Documentation/misc-devices/mei
1. move mei.txt, TODO, and the example code under Documentation/misc-devices/mei 2. update the TODO file Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 8 changed files with 710 additions and 706 deletions Side-by-side Diff
Documentation/Makefile
Documentation/misc-devices/mei/Makefile
Documentation/misc-devices/mei/TODO
Documentation/misc-devices/mei/mei-amt-version.c
1 | +/****************************************************************************** | |
2 | + * Intel Management Engine Interface (Intel MEI) Linux driver | |
3 | + * Intel MEI Interface Header | |
4 | + * | |
5 | + * This file is provided under a dual BSD/GPLv2 license. When using or | |
6 | + * redistributing this file, you may do so under either license. | |
7 | + * | |
8 | + * GPL LICENSE SUMMARY | |
9 | + * | |
10 | + * Copyright(c) 2012 Intel Corporation. All rights reserved. | |
11 | + * | |
12 | + * This program is free software; you can redistribute it and/or modify | |
13 | + * it under the terms of version 2 of the GNU General Public License as | |
14 | + * published by the Free Software Foundation. | |
15 | + * | |
16 | + * This program is distributed in the hope that it will be useful, but | |
17 | + * WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | + * General Public License for more details. | |
20 | + * | |
21 | + * You should have received a copy of the GNU General Public License | |
22 | + * along with this program; if not, write to the Free Software | |
23 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | |
24 | + * USA | |
25 | + * | |
26 | + * The full GNU General Public License is included in this distribution | |
27 | + * in the file called LICENSE.GPL. | |
28 | + * | |
29 | + * Contact Information: | |
30 | + * Intel Corporation. | |
31 | + * linux-mei@linux.intel.com | |
32 | + * http://www.intel.com | |
33 | + * | |
34 | + * BSD LICENSE | |
35 | + * | |
36 | + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. | |
37 | + * All rights reserved. | |
38 | + * | |
39 | + * Redistribution and use in source and binary forms, with or without | |
40 | + * modification, are permitted provided that the following conditions | |
41 | + * are met: | |
42 | + * | |
43 | + * * Redistributions of source code must retain the above copyright | |
44 | + * notice, this list of conditions and the following disclaimer. | |
45 | + * * Redistributions in binary form must reproduce the above copyright | |
46 | + * notice, this list of conditions and the following disclaimer in | |
47 | + * the documentation and/or other materials provided with the | |
48 | + * distribution. | |
49 | + * * Neither the name Intel Corporation nor the names of its | |
50 | + * contributors may be used to endorse or promote products derived | |
51 | + * from this software without specific prior written permission. | |
52 | + * | |
53 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
54 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
55 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
56 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
57 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
58 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
59 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
60 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
61 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
62 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
63 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
64 | + * | |
65 | + *****************************************************************************/ | |
66 | + | |
67 | +#include <stdio.h> | |
68 | +#include <stdlib.h> | |
69 | +#include <string.h> | |
70 | +#include <fcntl.h> | |
71 | +#include <sys/ioctl.h> | |
72 | +#include <unistd.h> | |
73 | +#include <errno.h> | |
74 | +#include <stdint.h> | |
75 | +#include <stdbool.h> | |
76 | +#include <bits/wordsize.h> | |
77 | +#include <linux/mei.h> | |
78 | + | |
79 | +/***************************************************************************** | |
80 | + * Intel Management Engine Interface | |
81 | + *****************************************************************************/ | |
82 | + | |
83 | +#define mei_msg(_me, fmt, ARGS...) do { \ | |
84 | + if (_me->verbose) \ | |
85 | + fprintf(stderr, fmt, ##ARGS); \ | |
86 | +} while (0) | |
87 | + | |
88 | +#define mei_err(_me, fmt, ARGS...) do { \ | |
89 | + fprintf(stderr, "Error: " fmt, ##ARGS); \ | |
90 | +} while (0) | |
91 | + | |
92 | +struct mei { | |
93 | + uuid_le guid; | |
94 | + bool initialized; | |
95 | + bool verbose; | |
96 | + unsigned int buf_size; | |
97 | + unsigned char prot_ver; | |
98 | + int fd; | |
99 | +}; | |
100 | + | |
101 | +static void mei_deinit(struct mei *cl) | |
102 | +{ | |
103 | + if (cl->fd != -1) | |
104 | + close(cl->fd); | |
105 | + cl->fd = -1; | |
106 | + cl->buf_size = 0; | |
107 | + cl->prot_ver = 0; | |
108 | + cl->initialized = false; | |
109 | +} | |
110 | + | |
111 | +static bool mei_init(struct mei *me, const uuid_le *guid, | |
112 | + unsigned char req_protocol_version, bool verbose) | |
113 | +{ | |
114 | + int result; | |
115 | + struct mei_client *cl; | |
116 | + struct mei_connect_client_data data; | |
117 | + | |
118 | + mei_deinit(me); | |
119 | + | |
120 | + me->verbose = verbose; | |
121 | + | |
122 | + me->fd = open("/dev/mei", O_RDWR); | |
123 | + if (me->fd == -1) { | |
124 | + mei_err(me, "Cannot establish a handle to the Intel MEI driver\n"); | |
125 | + goto err; | |
126 | + } | |
127 | + memcpy(&me->guid, guid, sizeof(*guid)); | |
128 | + memset(&data, 0, sizeof(data)); | |
129 | + me->initialized = true; | |
130 | + | |
131 | + memcpy(&data.in_client_uuid, &me->guid, sizeof(me->guid)); | |
132 | + result = ioctl(me->fd, IOCTL_MEI_CONNECT_CLIENT, &data); | |
133 | + if (result) { | |
134 | + mei_err(me, "IOCTL_MEI_CONNECT_CLIENT receive message. err=%d\n", result); | |
135 | + goto err; | |
136 | + } | |
137 | + cl = &data.out_client_properties; | |
138 | + mei_msg(me, "max_message_length %d\n", cl->max_msg_length); | |
139 | + mei_msg(me, "protocol_version %d\n", cl->protocol_version); | |
140 | + | |
141 | + if ((req_protocol_version > 0) && | |
142 | + (cl->protocol_version != req_protocol_version)) { | |
143 | + mei_err(me, "Intel MEI protocol version not supported\n"); | |
144 | + goto err; | |
145 | + } | |
146 | + | |
147 | + me->buf_size = cl->max_msg_length; | |
148 | + me->prot_ver = cl->protocol_version; | |
149 | + | |
150 | + return true; | |
151 | +err: | |
152 | + mei_deinit(me); | |
153 | + return false; | |
154 | +} | |
155 | + | |
156 | +static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer, | |
157 | + ssize_t len, unsigned long timeout) | |
158 | +{ | |
159 | + ssize_t rc; | |
160 | + | |
161 | + mei_msg(me, "call read length = %zd\n", len); | |
162 | + | |
163 | + rc = read(me->fd, buffer, len); | |
164 | + if (rc < 0) { | |
165 | + mei_err(me, "read failed with status %zd %s\n", | |
166 | + rc, strerror(errno)); | |
167 | + mei_deinit(me); | |
168 | + } else { | |
169 | + mei_msg(me, "read succeeded with result %zd\n", rc); | |
170 | + } | |
171 | + return rc; | |
172 | +} | |
173 | + | |
174 | +static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer, | |
175 | + ssize_t len, unsigned long timeout) | |
176 | +{ | |
177 | + struct timeval tv; | |
178 | + ssize_t written; | |
179 | + ssize_t rc; | |
180 | + fd_set set; | |
181 | + | |
182 | + tv.tv_sec = timeout / 1000; | |
183 | + tv.tv_usec = (timeout % 1000) * 1000000; | |
184 | + | |
185 | + mei_msg(me, "call write length = %zd\n", len); | |
186 | + | |
187 | + written = write(me->fd, buffer, len); | |
188 | + if (written < 0) { | |
189 | + rc = -errno; | |
190 | + mei_err(me, "write failed with status %zd %s\n", | |
191 | + written, strerror(errno)); | |
192 | + goto out; | |
193 | + } | |
194 | + | |
195 | + FD_ZERO(&set); | |
196 | + FD_SET(me->fd, &set); | |
197 | + rc = select(me->fd + 1 , &set, NULL, NULL, &tv); | |
198 | + if (rc > 0 && FD_ISSET(me->fd, &set)) { | |
199 | + mei_msg(me, "write success\n"); | |
200 | + } else if (rc == 0) { | |
201 | + mei_err(me, "write failed on timeout with status\n"); | |
202 | + goto out; | |
203 | + } else { /* rc < 0 */ | |
204 | + mei_err(me, "write failed on select with status %zd\n", rc); | |
205 | + goto out; | |
206 | + } | |
207 | + | |
208 | + rc = written; | |
209 | +out: | |
210 | + if (rc < 0) | |
211 | + mei_deinit(me); | |
212 | + | |
213 | + return rc; | |
214 | +} | |
215 | + | |
216 | +/*************************************************************************** | |
217 | + * Intel Advanced Management Technolgy ME Client | |
218 | + ***************************************************************************/ | |
219 | + | |
220 | +#define AMT_MAJOR_VERSION 1 | |
221 | +#define AMT_MINOR_VERSION 1 | |
222 | + | |
223 | +#define AMT_STATUS_SUCCESS 0x0 | |
224 | +#define AMT_STATUS_INTERNAL_ERROR 0x1 | |
225 | +#define AMT_STATUS_NOT_READY 0x2 | |
226 | +#define AMT_STATUS_INVALID_AMT_MODE 0x3 | |
227 | +#define AMT_STATUS_INVALID_MESSAGE_LENGTH 0x4 | |
228 | + | |
229 | +#define AMT_STATUS_HOST_IF_EMPTY_RESPONSE 0x4000 | |
230 | +#define AMT_STATUS_SDK_RESOURCES 0x1004 | |
231 | + | |
232 | + | |
233 | +#define AMT_BIOS_VERSION_LEN 65 | |
234 | +#define AMT_VERSIONS_NUMBER 50 | |
235 | +#define AMT_UNICODE_STRING_LEN 20 | |
236 | + | |
237 | +struct amt_unicode_string { | |
238 | + uint16_t length; | |
239 | + char string[AMT_UNICODE_STRING_LEN]; | |
240 | +} __attribute__((packed)); | |
241 | + | |
242 | +struct amt_version_type { | |
243 | + struct amt_unicode_string description; | |
244 | + struct amt_unicode_string version; | |
245 | +} __attribute__((packed)); | |
246 | + | |
247 | +struct amt_version { | |
248 | + uint8_t major; | |
249 | + uint8_t minor; | |
250 | +} __attribute__((packed)); | |
251 | + | |
252 | +struct amt_code_versions { | |
253 | + uint8_t bios[AMT_BIOS_VERSION_LEN]; | |
254 | + uint32_t count; | |
255 | + struct amt_version_type versions[AMT_VERSIONS_NUMBER]; | |
256 | +} __attribute__((packed)); | |
257 | + | |
258 | +/*************************************************************************** | |
259 | + * Intel Advanced Management Technolgy Host Interface | |
260 | + ***************************************************************************/ | |
261 | + | |
262 | +struct amt_host_if_msg_header { | |
263 | + struct amt_version version; | |
264 | + uint16_t _reserved; | |
265 | + uint32_t command; | |
266 | + uint32_t length; | |
267 | +} __attribute__((packed)); | |
268 | + | |
269 | +struct amt_host_if_resp_header { | |
270 | + struct amt_host_if_msg_header header; | |
271 | + uint32_t status; | |
272 | + unsigned char data[0]; | |
273 | +} __attribute__((packed)); | |
274 | + | |
275 | +const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, \ | |
276 | + 0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c); | |
277 | + | |
278 | +#define AMT_HOST_IF_CODE_VERSIONS_REQUEST 0x0400001A | |
279 | +#define AMT_HOST_IF_CODE_VERSIONS_RESPONSE 0x0480001A | |
280 | + | |
281 | +const struct amt_host_if_msg_header CODE_VERSION_REQ = { | |
282 | + .version = {AMT_MAJOR_VERSION, AMT_MINOR_VERSION}, | |
283 | + ._reserved = 0, | |
284 | + .command = AMT_HOST_IF_CODE_VERSIONS_REQUEST, | |
285 | + .length = 0 | |
286 | +}; | |
287 | + | |
288 | + | |
289 | +struct amt_host_if { | |
290 | + struct mei mei_cl; | |
291 | + unsigned long send_timeout; | |
292 | + bool initialized; | |
293 | +}; | |
294 | + | |
295 | + | |
296 | +static bool amt_host_if_init(struct amt_host_if *acmd, | |
297 | + unsigned long send_timeout, bool verbose) | |
298 | +{ | |
299 | + acmd->send_timeout = (send_timeout) ? send_timeout : 20000; | |
300 | + acmd->initialized = mei_init(&acmd->mei_cl, &MEI_IAMTHIF, 0, verbose); | |
301 | + return acmd->initialized; | |
302 | +} | |
303 | + | |
304 | +static void amt_host_if_deinit(struct amt_host_if *acmd) | |
305 | +{ | |
306 | + mei_deinit(&acmd->mei_cl); | |
307 | + acmd->initialized = false; | |
308 | +} | |
309 | + | |
310 | +static uint32_t amt_verify_code_versions(const struct amt_host_if_resp_header *resp) | |
311 | +{ | |
312 | + uint32_t status = AMT_STATUS_SUCCESS; | |
313 | + struct amt_code_versions *code_ver; | |
314 | + size_t code_ver_len; | |
315 | + uint32_t ver_type_cnt; | |
316 | + uint32_t len; | |
317 | + uint32_t i; | |
318 | + | |
319 | + code_ver = (struct amt_code_versions *)resp->data; | |
320 | + /* length - sizeof(status) */ | |
321 | + code_ver_len = resp->header.length - sizeof(uint32_t); | |
322 | + ver_type_cnt = code_ver_len - | |
323 | + sizeof(code_ver->bios) - | |
324 | + sizeof(code_ver->count); | |
325 | + if (code_ver->count != ver_type_cnt / sizeof(struct amt_version_type)) { | |
326 | + status = AMT_STATUS_INTERNAL_ERROR; | |
327 | + goto out; | |
328 | + } | |
329 | + | |
330 | + for (i = 0; i < code_ver->count; i++) { | |
331 | + len = code_ver->versions[i].description.length; | |
332 | + | |
333 | + if (len > AMT_UNICODE_STRING_LEN) { | |
334 | + status = AMT_STATUS_INTERNAL_ERROR; | |
335 | + goto out; | |
336 | + } | |
337 | + | |
338 | + len = code_ver->versions[i].version.length; | |
339 | + if (code_ver->versions[i].version.string[len] != '\0' || | |
340 | + len != strlen(code_ver->versions[i].version.string)) { | |
341 | + status = AMT_STATUS_INTERNAL_ERROR; | |
342 | + goto out; | |
343 | + } | |
344 | + } | |
345 | +out: | |
346 | + return status; | |
347 | +} | |
348 | + | |
349 | +static uint32_t amt_verify_response_header(uint32_t command, | |
350 | + const struct amt_host_if_msg_header *resp_hdr, | |
351 | + uint32_t response_size) | |
352 | +{ | |
353 | + if (response_size < sizeof(struct amt_host_if_resp_header)) { | |
354 | + return AMT_STATUS_INTERNAL_ERROR; | |
355 | + } else if (response_size != (resp_hdr->length + | |
356 | + sizeof(struct amt_host_if_msg_header))) { | |
357 | + return AMT_STATUS_INTERNAL_ERROR; | |
358 | + } else if (resp_hdr->command != command) { | |
359 | + return AMT_STATUS_INTERNAL_ERROR; | |
360 | + } else if (resp_hdr->_reserved != 0) { | |
361 | + return AMT_STATUS_INTERNAL_ERROR; | |
362 | + } else if (resp_hdr->version.major != AMT_MAJOR_VERSION || | |
363 | + resp_hdr->version.minor < AMT_MINOR_VERSION) { | |
364 | + return AMT_STATUS_INTERNAL_ERROR; | |
365 | + } | |
366 | + return AMT_STATUS_SUCCESS; | |
367 | +} | |
368 | + | |
369 | +static uint32_t amt_host_if_call(struct amt_host_if *acmd, | |
370 | + const unsigned char *command, ssize_t command_sz, | |
371 | + uint8_t **read_buf, uint32_t rcmd, | |
372 | + unsigned int expected_sz) | |
373 | +{ | |
374 | + uint32_t in_buf_sz; | |
375 | + uint32_t out_buf_sz; | |
376 | + ssize_t written; | |
377 | + uint32_t status; | |
378 | + struct amt_host_if_resp_header *msg_hdr; | |
379 | + | |
380 | + in_buf_sz = acmd->mei_cl.buf_size; | |
381 | + *read_buf = (uint8_t *)malloc(sizeof(uint8_t) * in_buf_sz); | |
382 | + if (*read_buf == NULL) | |
383 | + return AMT_STATUS_SDK_RESOURCES; | |
384 | + memset(*read_buf, 0, in_buf_sz); | |
385 | + msg_hdr = (struct amt_host_if_resp_header *)*read_buf; | |
386 | + | |
387 | + written = mei_send_msg(&acmd->mei_cl, | |
388 | + command, command_sz, acmd->send_timeout); | |
389 | + if (written != command_sz) | |
390 | + return AMT_STATUS_INTERNAL_ERROR; | |
391 | + | |
392 | + out_buf_sz = mei_recv_msg(&acmd->mei_cl, *read_buf, in_buf_sz, 2000); | |
393 | + if (out_buf_sz <= 0) | |
394 | + return AMT_STATUS_HOST_IF_EMPTY_RESPONSE; | |
395 | + | |
396 | + status = msg_hdr->status; | |
397 | + if (status != AMT_STATUS_SUCCESS) | |
398 | + return status; | |
399 | + | |
400 | + status = amt_verify_response_header(rcmd, | |
401 | + &msg_hdr->header, out_buf_sz); | |
402 | + if (status != AMT_STATUS_SUCCESS) | |
403 | + return status; | |
404 | + | |
405 | + if (expected_sz && expected_sz != out_buf_sz) | |
406 | + return AMT_STATUS_INTERNAL_ERROR; | |
407 | + | |
408 | + return AMT_STATUS_SUCCESS; | |
409 | +} | |
410 | + | |
411 | + | |
412 | +static uint32_t amt_get_code_versions(struct amt_host_if *cmd, | |
413 | + struct amt_code_versions *versions) | |
414 | +{ | |
415 | + struct amt_host_if_resp_header *response = NULL; | |
416 | + uint32_t status; | |
417 | + | |
418 | + status = amt_host_if_call(cmd, | |
419 | + (const unsigned char *)&CODE_VERSION_REQ, | |
420 | + sizeof(CODE_VERSION_REQ), | |
421 | + (uint8_t **)&response, | |
422 | + AMT_HOST_IF_CODE_VERSIONS_RESPONSE, 0); | |
423 | + | |
424 | + if (status != AMT_STATUS_SUCCESS) | |
425 | + goto out; | |
426 | + | |
427 | + status = amt_verify_code_versions(response); | |
428 | + if (status != AMT_STATUS_SUCCESS) | |
429 | + goto out; | |
430 | + | |
431 | + memcpy(versions, response->data, sizeof(struct amt_code_versions)); | |
432 | +out: | |
433 | + if (response != NULL) | |
434 | + free(response); | |
435 | + | |
436 | + return status; | |
437 | +} | |
438 | + | |
439 | +/************************** end of amt_host_if_command ***********************/ | |
440 | +int main(int argc, char **argv) | |
441 | +{ | |
442 | + struct amt_code_versions ver; | |
443 | + struct amt_host_if acmd; | |
444 | + unsigned int i; | |
445 | + uint32_t status; | |
446 | + int ret; | |
447 | + bool verbose; | |
448 | + | |
449 | + verbose = (argc > 1 && strcmp(argv[1], "-v") == 0); | |
450 | + | |
451 | + if (!amt_host_if_init(&acmd, 5000, verbose)) { | |
452 | + ret = 1; | |
453 | + goto out; | |
454 | + } | |
455 | + | |
456 | + status = amt_get_code_versions(&acmd, &ver); | |
457 | + | |
458 | + amt_host_if_deinit(&acmd); | |
459 | + | |
460 | + switch (status) { | |
461 | + case AMT_STATUS_HOST_IF_EMPTY_RESPONSE: | |
462 | + printf("Intel AMT: DISABLED\n"); | |
463 | + ret = 0; | |
464 | + break; | |
465 | + case AMT_STATUS_SUCCESS: | |
466 | + printf("Intel AMT: ENABLED\n"); | |
467 | + for (i = 0; i < ver.count; i++) { | |
468 | + printf("%s:\t%s\n", ver.versions[i].description.string, | |
469 | + ver.versions[i].version.string); | |
470 | + } | |
471 | + ret = 0; | |
472 | + break; | |
473 | + default: | |
474 | + printf("An error has occurred\n"); | |
475 | + ret = 1; | |
476 | + break; | |
477 | + } | |
478 | + | |
479 | +out: | |
480 | + return ret; | |
481 | +} |
Documentation/misc-devices/mei/mei.txt
1 | +Intel(R) Management Engine Interface (Intel(R) MEI) | |
2 | +======================= | |
3 | + | |
4 | +Introduction | |
5 | +======================= | |
6 | + | |
7 | +The Intel Management Engine (Intel ME) is an isolated and protected computing | |
8 | +resource (Co-processor) residing inside certain Intel chipsets. The Intel ME | |
9 | +provides support for computer/IT management features. The feature set | |
10 | +depends on the Intel chipset SKU. | |
11 | + | |
12 | +The Intel Management Engine Interface (Intel MEI, previously known as HECI) | |
13 | +is the interface between the Host and Intel ME. This interface is exposed | |
14 | +to the host as a PCI device. The Intel MEI Driver is in charge of the | |
15 | +communication channel between a host application and the Intel ME feature. | |
16 | + | |
17 | +Each Intel ME feature (Intel ME Client) is addressed by a GUID/UUID and | |
18 | +each client has its own protocol. The protocol is message-based with a | |
19 | +header and payload up to 512 bytes. | |
20 | + | |
21 | +Prominent usage of the Intel ME Interface is to communicate with Intel(R) | |
22 | +Active Management Technology (Intel AMT)implemented in firmware running on | |
23 | +the Intel ME. | |
24 | + | |
25 | +Intel AMT provides the ability to manage a host remotely out-of-band (OOB) | |
26 | +even when the operating system running on the host processor has crashed or | |
27 | +is in a sleep state. | |
28 | + | |
29 | +Some examples of Intel AMT usage are: | |
30 | + - Monitoring hardware state and platform components | |
31 | + - Remote power off/on (useful for green computing or overnight IT | |
32 | + maintenance) | |
33 | + - OS updates | |
34 | + - Storage of useful platform information such as software assets | |
35 | + - Built-in hardware KVM | |
36 | + - Selective network isolation of Ethernet and IP protocol flows based | |
37 | + on policies set by a remote management console | |
38 | + - IDE device redirection from remote management console | |
39 | + | |
40 | +Intel AMT (OOB) communication is based on SOAP (deprecated | |
41 | +starting with Release 6.0) over HTTP/S or WS-Management protocol over | |
42 | +HTTP/S that are received from a remote management console application. | |
43 | + | |
44 | +For more information about Intel AMT: | |
45 | +http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide | |
46 | + | |
47 | +Intel MEI Driver | |
48 | +======================= | |
49 | + | |
50 | +The driver exposes a misc device called /dev/mei. | |
51 | + | |
52 | +An application maintains communication with an Intel ME feature while | |
53 | +/dev/mei is open. The binding to a specific features is performed by calling | |
54 | +MEI_CONNECT_CLIENT_IOCTL, which passes the desired UUID. | |
55 | +The number of instances of an Intel ME feature that can be opened | |
56 | +at the same time depends on the Intel ME feature, but most of the | |
57 | +features allow only a single instance. | |
58 | + | |
59 | +The Intel AMT Host Interface (Intel AMTHI) feature supports multiple | |
60 | +simultaneous user applications. Therefore, the Intel MEI driver handles | |
61 | +this internally by maintaining request queues for the applications. | |
62 | + | |
63 | +The driver is oblivious to data that is passed between firmware feature | |
64 | +and host application. | |
65 | + | |
66 | +Because some of the Intel ME features can change the system | |
67 | +configuration, the driver by default allows only a privileged | |
68 | +user to access it. | |
69 | + | |
70 | +A code snippet for an application communicating with | |
71 | +Intel AMTHI client: | |
72 | + struct mei_connect_client_data data; | |
73 | + fd = open(MEI_DEVICE); | |
74 | + | |
75 | + data.d.in_client_uuid = AMTHI_UUID; | |
76 | + | |
77 | + ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &data); | |
78 | + | |
79 | + printf("Ver=%d, MaxLen=%ld\n", | |
80 | + data.d.in_client_uuid.protocol_version, | |
81 | + data.d.in_client_uuid.max_msg_length); | |
82 | + | |
83 | + [...] | |
84 | + | |
85 | + write(fd, amthi_req_data, amthi_req_data_len); | |
86 | + | |
87 | + [...] | |
88 | + | |
89 | + read(fd, &amthi_res_data, amthi_res_data_len); | |
90 | + | |
91 | + [...] | |
92 | + close(fd); | |
93 | + | |
94 | +IOCTL: | |
95 | +====== | |
96 | +The Intel MEI Driver supports the following IOCTL command: | |
97 | + IOCTL_MEI_CONNECT_CLIENT Connect to firmware Feature (client). | |
98 | + | |
99 | + usage: | |
100 | + struct mei_connect_client_data clientData; | |
101 | + ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &clientData); | |
102 | + | |
103 | + inputs: | |
104 | + mei_connect_client_data struct contain the following | |
105 | + input field: | |
106 | + | |
107 | + in_client_uuid - UUID of the FW Feature that needs | |
108 | + to connect to. | |
109 | + outputs: | |
110 | + out_client_properties - Client Properties: MTU and Protocol Version. | |
111 | + | |
112 | + error returns: | |
113 | + EINVAL Wrong IOCTL Number | |
114 | + ENODEV Device or Connection is not initialized or ready. | |
115 | + (e.g. Wrong UUID) | |
116 | + ENOMEM Unable to allocate memory to client internal data. | |
117 | + EFAULT Fatal Error (e.g. Unable to access user input data) | |
118 | + EBUSY Connection Already Open | |
119 | + | |
120 | + Notes: | |
121 | + max_msg_length (MTU) in client properties describes the maximum | |
122 | + data that can be sent or received. (e.g. if MTU=2K, can send | |
123 | + requests up to bytes 2k and received responses upto 2k bytes). | |
124 | + | |
125 | +Intel ME Applications: | |
126 | +============== | |
127 | + | |
128 | +1) Intel Local Management Service (Intel LMS) | |
129 | + | |
130 | + Applications running locally on the platform communicate with Intel AMT Release | |
131 | + 2.0 and later releases in the same way that network applications do via SOAP | |
132 | + over HTTP (deprecated starting with Release 6.0) or with WS-Management over | |
133 | + SOAP over HTTP. This means that some Intel AMT features can be accessed from a | |
134 | + local application using the same network interface as a remote application | |
135 | + communicating with Intel AMT over the network. | |
136 | + | |
137 | + When a local application sends a message addressed to the local Intel AMT host | |
138 | + name, the Intel LMS, which listens for traffic directed to the host name, | |
139 | + intercepts the message and routes it to the Intel MEI. | |
140 | + For more information: | |
141 | + http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide | |
142 | + Under "About Intel AMT" => "Local Access" | |
143 | + | |
144 | + For downloading Intel LMS: | |
145 | + http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/ | |
146 | + | |
147 | + The Intel LMS opens a connection using the Intel MEI driver to the Intel LMS | |
148 | + firmware feature using a defined UUID and then communicates with the feature | |
149 | + using a protocol called Intel AMT Port Forwarding Protocol(Intel APF protocol). | |
150 | + The protocol is used to maintain multiple sessions with Intel AMT from a | |
151 | + single application. | |
152 | + | |
153 | + See the protocol specification in the Intel AMT Software Development Kit(SDK) | |
154 | + http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide | |
155 | + Under "SDK Resources" => "Intel(R) vPro(TM) Gateway(MPS)" | |
156 | + => "Information for Intel(R) vPro(TM) Gateway Developers" | |
157 | + => "Description of the Intel AMT Port Forwarding (APF)Protocol" | |
158 | + | |
159 | + 2) Intel AMT Remote configuration using a Local Agent | |
160 | + A Local Agent enables IT personnel to configure Intel AMT out-of-the-box | |
161 | + without requiring installing additional data to enable setup. The remote | |
162 | + configuration process may involve an ISV-developed remote configuration | |
163 | + agent that runs on the host. | |
164 | + For more information: | |
165 | + http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide | |
166 | + Under "Setup and Configuration of Intel AMT" => | |
167 | + "SDK Tools Supporting Setup and Configuration" => | |
168 | + "Using the Local Agent Sample" | |
169 | + | |
170 | + An open source Intel AMT configuration utility, implementing a local agent | |
171 | + that accesses the Intel MEI driver, can be found here: | |
172 | + http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/ | |
173 | + | |
174 | + | |
175 | +Intel AMT OS Health Watchdog: | |
176 | +============================= | |
177 | +The Intel AMT Watchdog is an OS Health (Hang/Crash) watchdog. | |
178 | +Whenever the OS hangs or crashes, Intel AMT will send an event | |
179 | +to any subscriber to this event. This mechanism means that | |
180 | +IT knows when a platform crashes even when there is a hard failure on the host. | |
181 | + | |
182 | +The Intel AMT Watchdog is composed of two parts: | |
183 | + 1) Firmware feature - receives the heartbeats | |
184 | + and sends an event when the heartbeats stop. | |
185 | + 2) Intel MEI driver - connects to the watchdog feature, configures the | |
186 | + watchdog and sends the heartbeats. | |
187 | + | |
188 | +The Intel MEI driver uses the kernel watchdog to configure the Intel AMT | |
189 | +Watchdog and to send heartbeats to it. The default timeout of the | |
190 | +watchdog is 120 seconds. | |
191 | + | |
192 | +If the Intel AMT Watchdog feature does not exist (i.e. the connection failed), | |
193 | +the Intel MEI driver will disable the sending of heartbeats. | |
194 | + | |
195 | +Supported Chipsets: | |
196 | +================== | |
197 | +7 Series Chipset Family | |
198 | +6 Series Chipset Family | |
199 | +5 Series Chipset Family | |
200 | +4 Series Chipset Family | |
201 | +Mobile 4 Series Chipset Family | |
202 | +ICH9 | |
203 | +82946GZ/GL | |
204 | +82G35 Express | |
205 | +82Q963/Q965 | |
206 | +82P965/G965 | |
207 | +Mobile PM965/GM965 | |
208 | +Mobile GME965/GLE960 | |
209 | +82Q35 Express | |
210 | +82G33/G31/P35/P31 Express | |
211 | +82Q33 Express | |
212 | +82X38/X48 Express | |
213 | + | |
214 | +--- | |
215 | +linux-mei@linux.intel.com |
drivers/misc/mei/TODO
1 | -TODO: | |
2 | - - Cleanup and split the timer function | |
3 | -Upon Unstaging: | |
4 | - - Documentation/ioctl/ioctl-number.txt | |
5 | - - move mei.txt under Documentation/mei/ | |
6 | - - move mei-amt-version.c under Documentation/mei | |
7 | - - add hostprogs-y for mei-amt-version.c | |
8 | - - drop mei_version.h | |
9 | - - Updated MAINTAINERS |
drivers/misc/mei/mei-amt-version.c
1 | -/****************************************************************************** | |
2 | - * Intel Management Engine Interface (Intel MEI) Linux driver | |
3 | - * Intel MEI Interface Header | |
4 | - * | |
5 | - * This file is provided under a dual BSD/GPLv2 license. When using or | |
6 | - * redistributing this file, you may do so under either license. | |
7 | - * | |
8 | - * GPL LICENSE SUMMARY | |
9 | - * | |
10 | - * Copyright(c) 2012 Intel Corporation. All rights reserved. | |
11 | - * | |
12 | - * This program is free software; you can redistribute it and/or modify | |
13 | - * it under the terms of version 2 of the GNU General Public License as | |
14 | - * published by the Free Software Foundation. | |
15 | - * | |
16 | - * This program is distributed in the hope that it will be useful, but | |
17 | - * WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | - * General Public License for more details. | |
20 | - * | |
21 | - * You should have received a copy of the GNU General Public License | |
22 | - * along with this program; if not, write to the Free Software | |
23 | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | |
24 | - * USA | |
25 | - * | |
26 | - * The full GNU General Public License is included in this distribution | |
27 | - * in the file called LICENSE.GPL. | |
28 | - * | |
29 | - * Contact Information: | |
30 | - * Intel Corporation. | |
31 | - * linux-mei@linux.intel.com | |
32 | - * http://www.intel.com | |
33 | - * | |
34 | - * BSD LICENSE | |
35 | - * | |
36 | - * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. | |
37 | - * All rights reserved. | |
38 | - * | |
39 | - * Redistribution and use in source and binary forms, with or without | |
40 | - * modification, are permitted provided that the following conditions | |
41 | - * are met: | |
42 | - * | |
43 | - * * Redistributions of source code must retain the above copyright | |
44 | - * notice, this list of conditions and the following disclaimer. | |
45 | - * * Redistributions in binary form must reproduce the above copyright | |
46 | - * notice, this list of conditions and the following disclaimer in | |
47 | - * the documentation and/or other materials provided with the | |
48 | - * distribution. | |
49 | - * * Neither the name Intel Corporation nor the names of its | |
50 | - * contributors may be used to endorse or promote products derived | |
51 | - * from this software without specific prior written permission. | |
52 | - * | |
53 | - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
54 | - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
55 | - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
56 | - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
57 | - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
58 | - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
59 | - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
60 | - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
61 | - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
62 | - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
63 | - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
64 | - * | |
65 | - *****************************************************************************/ | |
66 | - | |
67 | -#include <stdio.h> | |
68 | -#include <stdlib.h> | |
69 | -#include <string.h> | |
70 | -#include <fcntl.h> | |
71 | -#include <sys/ioctl.h> | |
72 | -#include <unistd.h> | |
73 | -#include <errno.h> | |
74 | -#include <stdint.h> | |
75 | -#include <stdbool.h> | |
76 | -#include <bits/wordsize.h> | |
77 | -#include <linux/mei.h> | |
78 | - | |
79 | -/***************************************************************************** | |
80 | - * Intel Management Engine Interface | |
81 | - *****************************************************************************/ | |
82 | - | |
83 | -#define mei_msg(_me, fmt, ARGS...) do { \ | |
84 | - if (_me->verbose) \ | |
85 | - fprintf(stderr, fmt, ##ARGS); \ | |
86 | -} while (0) | |
87 | - | |
88 | -#define mei_err(_me, fmt, ARGS...) do { \ | |
89 | - fprintf(stderr, "Error: " fmt, ##ARGS); \ | |
90 | -} while (0) | |
91 | - | |
92 | -struct mei { | |
93 | - uuid_le guid; | |
94 | - bool initialized; | |
95 | - bool verbose; | |
96 | - unsigned int buf_size; | |
97 | - unsigned char prot_ver; | |
98 | - int fd; | |
99 | -}; | |
100 | - | |
101 | -static void mei_deinit(struct mei *cl) | |
102 | -{ | |
103 | - if (cl->fd != -1) | |
104 | - close(cl->fd); | |
105 | - cl->fd = -1; | |
106 | - cl->buf_size = 0; | |
107 | - cl->prot_ver = 0; | |
108 | - cl->initialized = false; | |
109 | -} | |
110 | - | |
111 | -static bool mei_init(struct mei *me, const uuid_le *guid, | |
112 | - unsigned char req_protocol_version, bool verbose) | |
113 | -{ | |
114 | - int result; | |
115 | - struct mei_client *cl; | |
116 | - struct mei_connect_client_data data; | |
117 | - | |
118 | - mei_deinit(me); | |
119 | - | |
120 | - me->verbose = verbose; | |
121 | - | |
122 | - me->fd = open("/dev/mei", O_RDWR); | |
123 | - if (me->fd == -1) { | |
124 | - mei_err(me, "Cannot establish a handle to the Intel MEI driver\n"); | |
125 | - goto err; | |
126 | - } | |
127 | - memcpy(&me->guid, guid, sizeof(*guid)); | |
128 | - memset(&data, 0, sizeof(data)); | |
129 | - me->initialized = true; | |
130 | - | |
131 | - memcpy(&data.in_client_uuid, &me->guid, sizeof(me->guid)); | |
132 | - result = ioctl(me->fd, IOCTL_MEI_CONNECT_CLIENT, &data); | |
133 | - if (result) { | |
134 | - mei_err(me, "IOCTL_MEI_CONNECT_CLIENT receive message. err=%d\n", result); | |
135 | - goto err; | |
136 | - } | |
137 | - cl = &data.out_client_properties; | |
138 | - mei_msg(me, "max_message_length %d\n", cl->max_msg_length); | |
139 | - mei_msg(me, "protocol_version %d\n", cl->protocol_version); | |
140 | - | |
141 | - if ((req_protocol_version > 0) && | |
142 | - (cl->protocol_version != req_protocol_version)) { | |
143 | - mei_err(me, "Intel MEI protocol version not supported\n"); | |
144 | - goto err; | |
145 | - } | |
146 | - | |
147 | - me->buf_size = cl->max_msg_length; | |
148 | - me->prot_ver = cl->protocol_version; | |
149 | - | |
150 | - return true; | |
151 | -err: | |
152 | - mei_deinit(me); | |
153 | - return false; | |
154 | -} | |
155 | - | |
156 | -static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer, | |
157 | - ssize_t len, unsigned long timeout) | |
158 | -{ | |
159 | - ssize_t rc; | |
160 | - | |
161 | - mei_msg(me, "call read length = %zd\n", len); | |
162 | - | |
163 | - rc = read(me->fd, buffer, len); | |
164 | - if (rc < 0) { | |
165 | - mei_err(me, "read failed with status %zd %s\n", | |
166 | - rc, strerror(errno)); | |
167 | - mei_deinit(me); | |
168 | - } else { | |
169 | - mei_msg(me, "read succeeded with result %zd\n", rc); | |
170 | - } | |
171 | - return rc; | |
172 | -} | |
173 | - | |
174 | -static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer, | |
175 | - ssize_t len, unsigned long timeout) | |
176 | -{ | |
177 | - struct timeval tv; | |
178 | - ssize_t written; | |
179 | - ssize_t rc; | |
180 | - fd_set set; | |
181 | - | |
182 | - tv.tv_sec = timeout / 1000; | |
183 | - tv.tv_usec = (timeout % 1000) * 1000000; | |
184 | - | |
185 | - mei_msg(me, "call write length = %zd\n", len); | |
186 | - | |
187 | - written = write(me->fd, buffer, len); | |
188 | - if (written < 0) { | |
189 | - rc = -errno; | |
190 | - mei_err(me, "write failed with status %zd %s\n", | |
191 | - written, strerror(errno)); | |
192 | - goto out; | |
193 | - } | |
194 | - | |
195 | - FD_ZERO(&set); | |
196 | - FD_SET(me->fd, &set); | |
197 | - rc = select(me->fd + 1 , &set, NULL, NULL, &tv); | |
198 | - if (rc > 0 && FD_ISSET(me->fd, &set)) { | |
199 | - mei_msg(me, "write success\n"); | |
200 | - } else if (rc == 0) { | |
201 | - mei_err(me, "write failed on timeout with status\n"); | |
202 | - goto out; | |
203 | - } else { /* rc < 0 */ | |
204 | - mei_err(me, "write failed on select with status %zd\n", rc); | |
205 | - goto out; | |
206 | - } | |
207 | - | |
208 | - rc = written; | |
209 | -out: | |
210 | - if (rc < 0) | |
211 | - mei_deinit(me); | |
212 | - | |
213 | - return rc; | |
214 | -} | |
215 | - | |
216 | -/*************************************************************************** | |
217 | - * Intel Advanced Management Technolgy ME Client | |
218 | - ***************************************************************************/ | |
219 | - | |
220 | -#define AMT_MAJOR_VERSION 1 | |
221 | -#define AMT_MINOR_VERSION 1 | |
222 | - | |
223 | -#define AMT_STATUS_SUCCESS 0x0 | |
224 | -#define AMT_STATUS_INTERNAL_ERROR 0x1 | |
225 | -#define AMT_STATUS_NOT_READY 0x2 | |
226 | -#define AMT_STATUS_INVALID_AMT_MODE 0x3 | |
227 | -#define AMT_STATUS_INVALID_MESSAGE_LENGTH 0x4 | |
228 | - | |
229 | -#define AMT_STATUS_HOST_IF_EMPTY_RESPONSE 0x4000 | |
230 | -#define AMT_STATUS_SDK_RESOURCES 0x1004 | |
231 | - | |
232 | - | |
233 | -#define AMT_BIOS_VERSION_LEN 65 | |
234 | -#define AMT_VERSIONS_NUMBER 50 | |
235 | -#define AMT_UNICODE_STRING_LEN 20 | |
236 | - | |
237 | -struct amt_unicode_string { | |
238 | - uint16_t length; | |
239 | - char string[AMT_UNICODE_STRING_LEN]; | |
240 | -} __attribute__((packed)); | |
241 | - | |
242 | -struct amt_version_type { | |
243 | - struct amt_unicode_string description; | |
244 | - struct amt_unicode_string version; | |
245 | -} __attribute__((packed)); | |
246 | - | |
247 | -struct amt_version { | |
248 | - uint8_t major; | |
249 | - uint8_t minor; | |
250 | -} __attribute__((packed)); | |
251 | - | |
252 | -struct amt_code_versions { | |
253 | - uint8_t bios[AMT_BIOS_VERSION_LEN]; | |
254 | - uint32_t count; | |
255 | - struct amt_version_type versions[AMT_VERSIONS_NUMBER]; | |
256 | -} __attribute__((packed)); | |
257 | - | |
258 | -/*************************************************************************** | |
259 | - * Intel Advanced Management Technolgy Host Interface | |
260 | - ***************************************************************************/ | |
261 | - | |
262 | -struct amt_host_if_msg_header { | |
263 | - struct amt_version version; | |
264 | - uint16_t _reserved; | |
265 | - uint32_t command; | |
266 | - uint32_t length; | |
267 | -} __attribute__((packed)); | |
268 | - | |
269 | -struct amt_host_if_resp_header { | |
270 | - struct amt_host_if_msg_header header; | |
271 | - uint32_t status; | |
272 | - unsigned char data[0]; | |
273 | -} __attribute__((packed)); | |
274 | - | |
275 | -const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, \ | |
276 | - 0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c); | |
277 | - | |
278 | -#define AMT_HOST_IF_CODE_VERSIONS_REQUEST 0x0400001A | |
279 | -#define AMT_HOST_IF_CODE_VERSIONS_RESPONSE 0x0480001A | |
280 | - | |
281 | -const struct amt_host_if_msg_header CODE_VERSION_REQ = { | |
282 | - .version = {AMT_MAJOR_VERSION, AMT_MINOR_VERSION}, | |
283 | - ._reserved = 0, | |
284 | - .command = AMT_HOST_IF_CODE_VERSIONS_REQUEST, | |
285 | - .length = 0 | |
286 | -}; | |
287 | - | |
288 | - | |
289 | -struct amt_host_if { | |
290 | - struct mei mei_cl; | |
291 | - unsigned long send_timeout; | |
292 | - bool initialized; | |
293 | -}; | |
294 | - | |
295 | - | |
296 | -static bool amt_host_if_init(struct amt_host_if *acmd, | |
297 | - unsigned long send_timeout, bool verbose) | |
298 | -{ | |
299 | - acmd->send_timeout = (send_timeout) ? send_timeout : 20000; | |
300 | - acmd->initialized = mei_init(&acmd->mei_cl, &MEI_IAMTHIF, 0, verbose); | |
301 | - return acmd->initialized; | |
302 | -} | |
303 | - | |
304 | -static void amt_host_if_deinit(struct amt_host_if *acmd) | |
305 | -{ | |
306 | - mei_deinit(&acmd->mei_cl); | |
307 | - acmd->initialized = false; | |
308 | -} | |
309 | - | |
310 | -static uint32_t amt_verify_code_versions(const struct amt_host_if_resp_header *resp) | |
311 | -{ | |
312 | - uint32_t status = AMT_STATUS_SUCCESS; | |
313 | - struct amt_code_versions *code_ver; | |
314 | - size_t code_ver_len; | |
315 | - uint32_t ver_type_cnt; | |
316 | - uint32_t len; | |
317 | - uint32_t i; | |
318 | - | |
319 | - code_ver = (struct amt_code_versions *)resp->data; | |
320 | - /* length - sizeof(status) */ | |
321 | - code_ver_len = resp->header.length - sizeof(uint32_t); | |
322 | - ver_type_cnt = code_ver_len - | |
323 | - sizeof(code_ver->bios) - | |
324 | - sizeof(code_ver->count); | |
325 | - if (code_ver->count != ver_type_cnt / sizeof(struct amt_version_type)) { | |
326 | - status = AMT_STATUS_INTERNAL_ERROR; | |
327 | - goto out; | |
328 | - } | |
329 | - | |
330 | - for (i = 0; i < code_ver->count; i++) { | |
331 | - len = code_ver->versions[i].description.length; | |
332 | - | |
333 | - if (len > AMT_UNICODE_STRING_LEN) { | |
334 | - status = AMT_STATUS_INTERNAL_ERROR; | |
335 | - goto out; | |
336 | - } | |
337 | - | |
338 | - len = code_ver->versions[i].version.length; | |
339 | - if (code_ver->versions[i].version.string[len] != '\0' || | |
340 | - len != strlen(code_ver->versions[i].version.string)) { | |
341 | - status = AMT_STATUS_INTERNAL_ERROR; | |
342 | - goto out; | |
343 | - } | |
344 | - } | |
345 | -out: | |
346 | - return status; | |
347 | -} | |
348 | - | |
349 | -static uint32_t amt_verify_response_header(uint32_t command, | |
350 | - const struct amt_host_if_msg_header *resp_hdr, | |
351 | - uint32_t response_size) | |
352 | -{ | |
353 | - if (response_size < sizeof(struct amt_host_if_resp_header)) { | |
354 | - return AMT_STATUS_INTERNAL_ERROR; | |
355 | - } else if (response_size != (resp_hdr->length + | |
356 | - sizeof(struct amt_host_if_msg_header))) { | |
357 | - return AMT_STATUS_INTERNAL_ERROR; | |
358 | - } else if (resp_hdr->command != command) { | |
359 | - return AMT_STATUS_INTERNAL_ERROR; | |
360 | - } else if (resp_hdr->_reserved != 0) { | |
361 | - return AMT_STATUS_INTERNAL_ERROR; | |
362 | - } else if (resp_hdr->version.major != AMT_MAJOR_VERSION || | |
363 | - resp_hdr->version.minor < AMT_MINOR_VERSION) { | |
364 | - return AMT_STATUS_INTERNAL_ERROR; | |
365 | - } | |
366 | - return AMT_STATUS_SUCCESS; | |
367 | -} | |
368 | - | |
369 | -static uint32_t amt_host_if_call(struct amt_host_if *acmd, | |
370 | - const unsigned char *command, ssize_t command_sz, | |
371 | - uint8_t **read_buf, uint32_t rcmd, | |
372 | - unsigned int expected_sz) | |
373 | -{ | |
374 | - uint32_t in_buf_sz; | |
375 | - uint32_t out_buf_sz; | |
376 | - ssize_t written; | |
377 | - uint32_t status; | |
378 | - struct amt_host_if_resp_header *msg_hdr; | |
379 | - | |
380 | - in_buf_sz = acmd->mei_cl.buf_size; | |
381 | - *read_buf = (uint8_t *)malloc(sizeof(uint8_t) * in_buf_sz); | |
382 | - if (*read_buf == NULL) | |
383 | - return AMT_STATUS_SDK_RESOURCES; | |
384 | - memset(*read_buf, 0, in_buf_sz); | |
385 | - msg_hdr = (struct amt_host_if_resp_header *)*read_buf; | |
386 | - | |
387 | - written = mei_send_msg(&acmd->mei_cl, | |
388 | - command, command_sz, acmd->send_timeout); | |
389 | - if (written != command_sz) | |
390 | - return AMT_STATUS_INTERNAL_ERROR; | |
391 | - | |
392 | - out_buf_sz = mei_recv_msg(&acmd->mei_cl, *read_buf, in_buf_sz, 2000); | |
393 | - if (out_buf_sz <= 0) | |
394 | - return AMT_STATUS_HOST_IF_EMPTY_RESPONSE; | |
395 | - | |
396 | - status = msg_hdr->status; | |
397 | - if (status != AMT_STATUS_SUCCESS) | |
398 | - return status; | |
399 | - | |
400 | - status = amt_verify_response_header(rcmd, | |
401 | - &msg_hdr->header, out_buf_sz); | |
402 | - if (status != AMT_STATUS_SUCCESS) | |
403 | - return status; | |
404 | - | |
405 | - if (expected_sz && expected_sz != out_buf_sz) | |
406 | - return AMT_STATUS_INTERNAL_ERROR; | |
407 | - | |
408 | - return AMT_STATUS_SUCCESS; | |
409 | -} | |
410 | - | |
411 | - | |
412 | -static uint32_t amt_get_code_versions(struct amt_host_if *cmd, | |
413 | - struct amt_code_versions *versions) | |
414 | -{ | |
415 | - struct amt_host_if_resp_header *response = NULL; | |
416 | - uint32_t status; | |
417 | - | |
418 | - status = amt_host_if_call(cmd, | |
419 | - (const unsigned char *)&CODE_VERSION_REQ, | |
420 | - sizeof(CODE_VERSION_REQ), | |
421 | - (uint8_t **)&response, | |
422 | - AMT_HOST_IF_CODE_VERSIONS_RESPONSE, 0); | |
423 | - | |
424 | - if (status != AMT_STATUS_SUCCESS) | |
425 | - goto out; | |
426 | - | |
427 | - status = amt_verify_code_versions(response); | |
428 | - if (status != AMT_STATUS_SUCCESS) | |
429 | - goto out; | |
430 | - | |
431 | - memcpy(versions, response->data, sizeof(struct amt_code_versions)); | |
432 | -out: | |
433 | - if (response != NULL) | |
434 | - free(response); | |
435 | - | |
436 | - return status; | |
437 | -} | |
438 | - | |
439 | -/************************** end of amt_host_if_command ***********************/ | |
440 | -int main(int argc, char **argv) | |
441 | -{ | |
442 | - struct amt_code_versions ver; | |
443 | - struct amt_host_if acmd; | |
444 | - unsigned int i; | |
445 | - uint32_t status; | |
446 | - int ret; | |
447 | - bool verbose; | |
448 | - | |
449 | - verbose = (argc > 1 && strcmp(argv[1], "-v") == 0); | |
450 | - | |
451 | - if (!amt_host_if_init(&acmd, 5000, verbose)) { | |
452 | - ret = 1; | |
453 | - goto out; | |
454 | - } | |
455 | - | |
456 | - status = amt_get_code_versions(&acmd, &ver); | |
457 | - | |
458 | - amt_host_if_deinit(&acmd); | |
459 | - | |
460 | - switch (status) { | |
461 | - case AMT_STATUS_HOST_IF_EMPTY_RESPONSE: | |
462 | - printf("Intel AMT: DISABLED\n"); | |
463 | - ret = 0; | |
464 | - break; | |
465 | - case AMT_STATUS_SUCCESS: | |
466 | - printf("Intel AMT: ENABLED\n"); | |
467 | - for (i = 0; i < ver.count; i++) { | |
468 | - printf("%s:\t%s\n", ver.versions[i].description.string, | |
469 | - ver.versions[i].version.string); | |
470 | - } | |
471 | - ret = 0; | |
472 | - break; | |
473 | - default: | |
474 | - printf("An error has occurred\n"); | |
475 | - ret = 1; | |
476 | - break; | |
477 | - } | |
478 | - | |
479 | -out: | |
480 | - return ret; | |
481 | -} |
drivers/misc/mei/mei.txt
1 | -Intel(R) Management Engine Interface (Intel(R) MEI) | |
2 | -======================= | |
3 | - | |
4 | -Introduction | |
5 | -======================= | |
6 | - | |
7 | -The Intel Management Engine (Intel ME) is an isolated and protected computing | |
8 | -resource (Co-processor) residing inside certain Intel chipsets. The Intel ME | |
9 | -provides support for computer/IT management features. The feature set | |
10 | -depends on the Intel chipset SKU. | |
11 | - | |
12 | -The Intel Management Engine Interface (Intel MEI, previously known as HECI) | |
13 | -is the interface between the Host and Intel ME. This interface is exposed | |
14 | -to the host as a PCI device. The Intel MEI Driver is in charge of the | |
15 | -communication channel between a host application and the Intel ME feature. | |
16 | - | |
17 | -Each Intel ME feature (Intel ME Client) is addressed by a GUID/UUID and | |
18 | -each client has its own protocol. The protocol is message-based with a | |
19 | -header and payload up to 512 bytes. | |
20 | - | |
21 | -Prominent usage of the Intel ME Interface is to communicate with Intel(R) | |
22 | -Active Management Technology (Intel AMT)implemented in firmware running on | |
23 | -the Intel ME. | |
24 | - | |
25 | -Intel AMT provides the ability to manage a host remotely out-of-band (OOB) | |
26 | -even when the operating system running on the host processor has crashed or | |
27 | -is in a sleep state. | |
28 | - | |
29 | -Some examples of Intel AMT usage are: | |
30 | - - Monitoring hardware state and platform components | |
31 | - - Remote power off/on (useful for green computing or overnight IT | |
32 | - maintenance) | |
33 | - - OS updates | |
34 | - - Storage of useful platform information such as software assets | |
35 | - - Built-in hardware KVM | |
36 | - - Selective network isolation of Ethernet and IP protocol flows based | |
37 | - on policies set by a remote management console | |
38 | - - IDE device redirection from remote management console | |
39 | - | |
40 | -Intel AMT (OOB) communication is based on SOAP (deprecated | |
41 | -starting with Release 6.0) over HTTP/S or WS-Management protocol over | |
42 | -HTTP/S that are received from a remote management console application. | |
43 | - | |
44 | -For more information about Intel AMT: | |
45 | -http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide | |
46 | - | |
47 | -Intel MEI Driver | |
48 | -======================= | |
49 | - | |
50 | -The driver exposes a misc device called /dev/mei. | |
51 | - | |
52 | -An application maintains communication with an Intel ME feature while | |
53 | -/dev/mei is open. The binding to a specific features is performed by calling | |
54 | -MEI_CONNECT_CLIENT_IOCTL, which passes the desired UUID. | |
55 | -The number of instances of an Intel ME feature that can be opened | |
56 | -at the same time depends on the Intel ME feature, but most of the | |
57 | -features allow only a single instance. | |
58 | - | |
59 | -The Intel AMT Host Interface (Intel AMTHI) feature supports multiple | |
60 | -simultaneous user applications. Therefore, the Intel MEI driver handles | |
61 | -this internally by maintaining request queues for the applications. | |
62 | - | |
63 | -The driver is oblivious to data that is passed between firmware feature | |
64 | -and host application. | |
65 | - | |
66 | -Because some of the Intel ME features can change the system | |
67 | -configuration, the driver by default allows only a privileged | |
68 | -user to access it. | |
69 | - | |
70 | -A code snippet for an application communicating with | |
71 | -Intel AMTHI client: | |
72 | - struct mei_connect_client_data data; | |
73 | - fd = open(MEI_DEVICE); | |
74 | - | |
75 | - data.d.in_client_uuid = AMTHI_UUID; | |
76 | - | |
77 | - ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &data); | |
78 | - | |
79 | - printf("Ver=%d, MaxLen=%ld\n", | |
80 | - data.d.in_client_uuid.protocol_version, | |
81 | - data.d.in_client_uuid.max_msg_length); | |
82 | - | |
83 | - [...] | |
84 | - | |
85 | - write(fd, amthi_req_data, amthi_req_data_len); | |
86 | - | |
87 | - [...] | |
88 | - | |
89 | - read(fd, &amthi_res_data, amthi_res_data_len); | |
90 | - | |
91 | - [...] | |
92 | - close(fd); | |
93 | - | |
94 | -IOCTL: | |
95 | -====== | |
96 | -The Intel MEI Driver supports the following IOCTL command: | |
97 | - IOCTL_MEI_CONNECT_CLIENT Connect to firmware Feature (client). | |
98 | - | |
99 | - usage: | |
100 | - struct mei_connect_client_data clientData; | |
101 | - ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &clientData); | |
102 | - | |
103 | - inputs: | |
104 | - mei_connect_client_data struct contain the following | |
105 | - input field: | |
106 | - | |
107 | - in_client_uuid - UUID of the FW Feature that needs | |
108 | - to connect to. | |
109 | - outputs: | |
110 | - out_client_properties - Client Properties: MTU and Protocol Version. | |
111 | - | |
112 | - error returns: | |
113 | - EINVAL Wrong IOCTL Number | |
114 | - ENODEV Device or Connection is not initialized or ready. | |
115 | - (e.g. Wrong UUID) | |
116 | - ENOMEM Unable to allocate memory to client internal data. | |
117 | - EFAULT Fatal Error (e.g. Unable to access user input data) | |
118 | - EBUSY Connection Already Open | |
119 | - | |
120 | - Notes: | |
121 | - max_msg_length (MTU) in client properties describes the maximum | |
122 | - data that can be sent or received. (e.g. if MTU=2K, can send | |
123 | - requests up to bytes 2k and received responses upto 2k bytes). | |
124 | - | |
125 | -Intel ME Applications: | |
126 | -============== | |
127 | - | |
128 | -1) Intel Local Management Service (Intel LMS) | |
129 | - | |
130 | - Applications running locally on the platform communicate with Intel AMT Release | |
131 | - 2.0 and later releases in the same way that network applications do via SOAP | |
132 | - over HTTP (deprecated starting with Release 6.0) or with WS-Management over | |
133 | - SOAP over HTTP. This means that some Intel AMT features can be accessed from a | |
134 | - local application using the same network interface as a remote application | |
135 | - communicating with Intel AMT over the network. | |
136 | - | |
137 | - When a local application sends a message addressed to the local Intel AMT host | |
138 | - name, the Intel LMS, which listens for traffic directed to the host name, | |
139 | - intercepts the message and routes it to the Intel MEI. | |
140 | - For more information: | |
141 | - http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide | |
142 | - Under "About Intel AMT" => "Local Access" | |
143 | - | |
144 | - For downloading Intel LMS: | |
145 | - http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/ | |
146 | - | |
147 | - The Intel LMS opens a connection using the Intel MEI driver to the Intel LMS | |
148 | - firmware feature using a defined UUID and then communicates with the feature | |
149 | - using a protocol called Intel AMT Port Forwarding Protocol(Intel APF protocol). | |
150 | - The protocol is used to maintain multiple sessions with Intel AMT from a | |
151 | - single application. | |
152 | - | |
153 | - See the protocol specification in the Intel AMT Software Development Kit(SDK) | |
154 | - http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide | |
155 | - Under "SDK Resources" => "Intel(R) vPro(TM) Gateway(MPS)" | |
156 | - => "Information for Intel(R) vPro(TM) Gateway Developers" | |
157 | - => "Description of the Intel AMT Port Forwarding (APF)Protocol" | |
158 | - | |
159 | - 2) Intel AMT Remote configuration using a Local Agent | |
160 | - A Local Agent enables IT personnel to configure Intel AMT out-of-the-box | |
161 | - without requiring installing additional data to enable setup. The remote | |
162 | - configuration process may involve an ISV-developed remote configuration | |
163 | - agent that runs on the host. | |
164 | - For more information: | |
165 | - http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide | |
166 | - Under "Setup and Configuration of Intel AMT" => | |
167 | - "SDK Tools Supporting Setup and Configuration" => | |
168 | - "Using the Local Agent Sample" | |
169 | - | |
170 | - An open source Intel AMT configuration utility, implementing a local agent | |
171 | - that accesses the Intel MEI driver, can be found here: | |
172 | - http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/ | |
173 | - | |
174 | - | |
175 | -Intel AMT OS Health Watchdog: | |
176 | -============================= | |
177 | -The Intel AMT Watchdog is an OS Health (Hang/Crash) watchdog. | |
178 | -Whenever the OS hangs or crashes, Intel AMT will send an event | |
179 | -to any subscriber to this event. This mechanism means that | |
180 | -IT knows when a platform crashes even when there is a hard failure on the host. | |
181 | - | |
182 | -The Intel AMT Watchdog is composed of two parts: | |
183 | - 1) Firmware feature - receives the heartbeats | |
184 | - and sends an event when the heartbeats stop. | |
185 | - 2) Intel MEI driver - connects to the watchdog feature, configures the | |
186 | - watchdog and sends the heartbeats. | |
187 | - | |
188 | -The Intel MEI driver uses the kernel watchdog to configure the Intel AMT | |
189 | -Watchdog and to send heartbeats to it. The default timeout of the | |
190 | -watchdog is 120 seconds. | |
191 | - | |
192 | -If the Intel AMT Watchdog feature does not exist (i.e. the connection failed), | |
193 | -the Intel MEI driver will disable the sending of heartbeats. | |
194 | - | |
195 | -Supported Chipsets: | |
196 | -================== | |
197 | -7 Series Chipset Family | |
198 | -6 Series Chipset Family | |
199 | -5 Series Chipset Family | |
200 | -4 Series Chipset Family | |
201 | -Mobile 4 Series Chipset Family | |
202 | -ICH9 | |
203 | -82946GZ/GL | |
204 | -82G35 Express | |
205 | -82Q963/Q965 | |
206 | -82P965/G965 | |
207 | -Mobile PM965/GM965 | |
208 | -Mobile GME965/GLE960 | |
209 | -82Q35 Express | |
210 | -82G33/G31/P35/P31 Express | |
211 | -82Q33 Express | |
212 | -82X38/X48 Express | |
213 | - | |
214 | ---- | |
215 | -linux-mei@linux.intel.com |