377 lines
11 KiB
C
377 lines
11 KiB
C
/*********************************************************************
|
|
* Copyright (c) Intel Corporation 2011 - 2020
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
**********************************************************************/
|
|
|
|
#ifndef _MINCORE
|
|
|
|
#include <windows.h>
|
|
#include <setupapi.h>
|
|
#include <initguid.h>
|
|
#include <winioctl.h>
|
|
#include "HECIWin.h"
|
|
#include "heci_if.h"
|
|
|
|
#define false 0
|
|
#define true 1
|
|
#define HECI_MAX_LINE_LEN 300
|
|
|
|
DEFINE_GUID(GUID_DEVINTERFACE_HECI, 0xE2D1FF34, 0x3458, 0x49A9, 0x88, 0xDA, 0x8E, 0x69, 0x15, 0xCE, 0x9B, 0xE5);
|
|
DEFINE_GUID(HECI_PTHI_GUID , 0x12F80028, 0xB4B7, 0x4b2d, 0xAC, 0xA8, 0x46, 0xE0, 0xFF, 0x65, 0x81, 0x4c);
|
|
DEFINE_GUID(LMS_GUID , 0x6733a4db, 0x0476, 0x4e7b, 0xb3, 0xaf, 0xbc, 0xfc, 0x29, 0xbe, 0xe7, 0xa7);
|
|
DEFINE_GUID(MKHI_GUID , 0x8E6A6715, 0x9ABC, 0x4043, 0x88, 0xEF, 0x9E, 0x39, 0xC6, 0xF6, 0x3E, 0x0F);
|
|
|
|
//VOID _displayHECIError(UINT32 errorCode,DWORD lastError);
|
|
//VOID _displayHECIData(UINT32 messageId);
|
|
int heci_doIoctl(struct MEImodule* module, DWORD code, void *inbuf, int inlen, void *outbuf, int outlen);
|
|
|
|
struct MEImodule MEI_global;
|
|
|
|
/***************************** public functions *****************************/
|
|
|
|
unsigned int heci_GetBufferSize(struct MEImodule* module) { if (module != NULL) return module->_bufSize; else return MEI_global._bufSize; }
|
|
unsigned char heci_GetProtocolVersion(struct MEImodule* module) { if (module != NULL) return module->_protocolVersion; else return MEI_global._protocolVersion; }
|
|
bool heci_IsInitialized(struct MEImodule* module) { if (module != NULL) return module->_initialized; else return MEI_global._initialized; }
|
|
|
|
bool heci_GetHeciVersion(struct MEImodule* module, HECI_VERSION *version)
|
|
{
|
|
if (module == NULL) module = &MEI_global;
|
|
|
|
if (module->m_haveHeciVersion)
|
|
{
|
|
memcpy_s(version, sizeof(HECI_VERSION), &(module->m_heciVersion), sizeof(HECI_VERSION));
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool heci_Init(struct MEImodule* module, HECI_CLIENTS client)
|
|
{
|
|
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail = NULL;
|
|
HDEVINFO hDeviceInfo;
|
|
DWORD bufferSize;
|
|
SP_DEVICE_INTERFACE_DATA interfaceData;
|
|
LONG ii = 0;
|
|
int result;
|
|
HECI_CLIENT properties;
|
|
GUID guid;
|
|
|
|
if (client == PTHI_CLIENT) guid = HECI_PTHI_GUID;
|
|
if (client == LMS_CLIENT) guid = LMS_GUID;
|
|
if (client == MKHI_CLIENT) guid = MKHI_GUID;
|
|
if (module == NULL) module = &MEI_global;
|
|
module->_verbose = false;
|
|
|
|
if (module->_initialized) {
|
|
heci_Deinit(module);
|
|
}
|
|
|
|
// Find all devices that have our interface
|
|
hDeviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_HECI, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
|
if (hDeviceInfo == INVALID_HANDLE_VALUE) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(GET_CLASS_DEVS,GetLastError());
|
|
}
|
|
return false; //GET_CLASS_DEVS;
|
|
}
|
|
|
|
// Setup the interface data struct
|
|
interfaceData.cbSize = sizeof(interfaceData);
|
|
for (ii = 0;
|
|
SetupDiEnumDeviceInterfaces(hDeviceInfo, NULL, (LPGUID)&GUID_DEVINTERFACE_HECI, ii, &interfaceData);
|
|
++ii) {
|
|
// Found our device instance
|
|
if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &interfaceData, NULL, 0, &bufferSize, NULL)) {
|
|
DWORD err = GetLastError();
|
|
if (err != ERROR_INSUFFICIENT_BUFFER) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(GET_INTERFACE_DETAIL,err);
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Allocate a big enough buffer to get detail data
|
|
deviceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(bufferSize);
|
|
if (deviceDetail == NULL) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(ALLOCATE_MEMORY_ERROR,0);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// Setup the device interface struct
|
|
deviceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
|
|
|
// Try again to get the device interface detail info
|
|
if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &interfaceData, deviceDetail, bufferSize, NULL, NULL))
|
|
{
|
|
/*
|
|
if (_verbose)
|
|
{
|
|
DWORD err = GetLastError();
|
|
_displayHECIError(GET_INTERFACE_DETAIL,err);
|
|
}
|
|
*/
|
|
free(deviceDetail);
|
|
deviceDetail = NULL;
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
SetupDiDestroyDeviceInfoList(hDeviceInfo);
|
|
|
|
if (deviceDetail == NULL) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(FIND_HECI_FAILURE,0);
|
|
}
|
|
return false; //FIND_HECI_FAILURE;
|
|
}
|
|
|
|
module->_handle = CreateFile(deviceDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
|
free(deviceDetail);
|
|
|
|
if (module->_handle == INVALID_HANDLE_VALUE) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(CREATE_HECI_FILE_FAILURE,GetLastError());
|
|
}
|
|
return false; //CREATE_HECI_FILE_FAILURE;
|
|
}
|
|
module->_initialized = true;
|
|
|
|
result = heci_doIoctl(module, (DWORD)IOCTL_HECI_GET_VERSION, NULL, 0, &(module->m_heciVersion), sizeof(HECI_VERSION));
|
|
if (result != sizeof(HECI_VERSION)) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(GET_HECI_DRIVER_VERSION_FAILURE,0);
|
|
}
|
|
heci_Deinit(module);
|
|
return false; //GET_HECI_DRIVER_VERSION_FAILURE;
|
|
}
|
|
module->m_haveHeciVersion = true;
|
|
|
|
if (module->_verbose) {
|
|
//_displayHECIData(HECI_DRIVER_VERSION);
|
|
//_ftprintf(stdout,_T("%d.%d.%d.%d\n"), (m_heciVersion).major, (m_heciVersion).minor, (m_heciVersion).hotfix, (m_heciVersion).build);
|
|
}
|
|
|
|
memset(&properties, 0, sizeof(properties));
|
|
result = heci_doIoctl(module, (DWORD)IOCTL_HECI_CONNECT_CLIENT, (void*)(&guid), sizeof(GUID), &properties, sizeof(properties));
|
|
if (result != sizeof(properties))
|
|
{
|
|
if (module->_verbose) {
|
|
//_displayHECIError(HECI_CONNECT_TO_PTHI_CLIENT_FAILURE,0);
|
|
}
|
|
//Deinit();
|
|
return false; //HECI_CONNECT_TO_PTHI_CLIENT_FAILURE;
|
|
}
|
|
module->_bufSize = properties.MaxMessageLength;
|
|
|
|
return true;
|
|
}
|
|
|
|
void heci_Deinit(struct MEImodule* module)
|
|
{
|
|
if (module == NULL) module = &MEI_global;
|
|
if (module->_initialized == false) return;
|
|
module->_initialized = false;
|
|
module->_bufSize = 0;
|
|
|
|
if (module->_handle != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(module->_handle);
|
|
module->_handle = INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
int heci_ReceiveMessage(struct MEImodule* module, unsigned char *buffer, int len, unsigned long timeout) // Timeout default is 2000
|
|
{
|
|
DWORD bytesRead = 0;
|
|
int res;
|
|
HANDLE h_event = NULL;
|
|
OVERLAPPED overlapped;
|
|
DWORD error;
|
|
DWORD eventRes;
|
|
|
|
if (module == NULL) module = &MEI_global;
|
|
if ((h_event = CreateEvent(NULL, FALSE, FALSE, NULL)) == 0) goto out;
|
|
overlapped.hEvent = h_event;
|
|
overlapped.Offset = 0;
|
|
overlapped.OffsetHigh = 0;
|
|
|
|
res = ReadFile(module->_handle, buffer, len, &bytesRead, &overlapped);
|
|
error = GetLastError();
|
|
if ((0 == res) && (ERROR_IO_PENDING != error)) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(READ_FILE,GetLastError());
|
|
}
|
|
bytesRead = (DWORD)-1;
|
|
goto out;
|
|
}
|
|
|
|
eventRes = WaitForSingleObject(h_event, timeout);
|
|
if (eventRes == WAIT_TIMEOUT) {
|
|
bytesRead = 0;
|
|
goto out;
|
|
}
|
|
|
|
res = GetOverlappedResult(module->_handle, &overlapped, &bytesRead, true);
|
|
|
|
if (res == 0) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(READ_FILE,GetLastError());
|
|
}
|
|
bytesRead = (DWORD)-1;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
if (h_event != NULL) CloseHandle(h_event);
|
|
if (bytesRead <= 0) heci_Deinit(module);
|
|
|
|
return bytesRead;
|
|
}
|
|
|
|
int heci_SendMessage(struct MEImodule* module, const unsigned char *buffer, int len, unsigned long timeout) // Timeout default is 2000
|
|
{
|
|
DWORD bytesWritten = 0;
|
|
int res;
|
|
HANDLE h_event = NULL;
|
|
OVERLAPPED overlapped;
|
|
DWORD lastError;
|
|
DWORD eventRes;
|
|
|
|
if (module == NULL) module = &MEI_global;
|
|
if ((h_event = CreateEvent(NULL, FALSE, FALSE, NULL)) == 0) goto out;
|
|
overlapped.hEvent = h_event;
|
|
overlapped.Offset = 0;
|
|
overlapped.OffsetHigh = 0;
|
|
|
|
res = WriteFile(module->_handle, buffer, len, &bytesWritten, &overlapped);
|
|
|
|
lastError = GetLastError();
|
|
if ((0 == res) && (ERROR_IO_PENDING !=lastError )) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(WRITE_FILE,GetLastError());
|
|
}
|
|
bytesWritten = (DWORD)-1;
|
|
goto out;
|
|
}
|
|
|
|
eventRes = WaitForSingleObject(h_event, timeout);
|
|
if (eventRes == WAIT_TIMEOUT) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(WRITE_FILE_TIME_OUT,0);
|
|
}
|
|
bytesWritten = 0;
|
|
goto out;
|
|
}
|
|
|
|
res = GetOverlappedResult(module->_handle, &overlapped, &bytesWritten, false);
|
|
|
|
if (res == 0) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(WRITE_FILE,GetLastError());
|
|
}
|
|
bytesWritten = (DWORD)-1;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
if (h_event != NULL) CloseHandle(h_event);
|
|
if (bytesWritten <= 0) heci_Deinit(module);
|
|
|
|
return bytesWritten;
|
|
}
|
|
|
|
int heci_doIoctl(struct MEImodule* module, DWORD code, void *inbuf, int inlen, void *outbuf, int outlen)
|
|
{
|
|
int res;
|
|
DWORD bytesRead = 0;
|
|
HANDLE h_event = NULL;
|
|
OVERLAPPED overlapped;
|
|
|
|
if (module == NULL) module = &MEI_global;
|
|
if (!module->_initialized) return -1;
|
|
|
|
if ((h_event = CreateEvent(NULL, FALSE, FALSE, NULL)) == 0) goto out;
|
|
overlapped.hEvent = h_event;
|
|
overlapped.Offset = 0;
|
|
overlapped.OffsetHigh = 0;
|
|
|
|
res = DeviceIoControl(module->_handle, code, inbuf, inlen, outbuf, outlen, &bytesRead, &overlapped);
|
|
|
|
if ((0 == res) && (ERROR_IO_PENDING != GetLastError())) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(IOCTL_COMMAND,GetLastError());
|
|
}
|
|
bytesRead = (DWORD)-1;
|
|
goto out;
|
|
}
|
|
|
|
WaitForSingleObject(h_event, INFINITE);
|
|
|
|
res = GetOverlappedResult(module->_handle, &overlapped, &bytesRead, true);
|
|
if (res == 0) {
|
|
if (module->_verbose) {
|
|
//_displayHECIError(IOCTL_COMMAND,GetLastError());
|
|
}
|
|
bytesRead = (DWORD)-1;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
if (h_event != NULL) CloseHandle(h_event);
|
|
if (bytesRead == (DWORD)-1) heci_Deinit(module);
|
|
|
|
return bytesRead;
|
|
}
|
|
|
|
TCHAR *_getErrMsg(DWORD err)
|
|
{
|
|
static TCHAR buffer[1024];
|
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
err,
|
|
0,
|
|
buffer,
|
|
sizeof(buffer) - 1,
|
|
0);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
/*
|
|
// Display a HECI error message
|
|
void _displayHECIError(UINT32 errorCode, DWORD lastError)
|
|
{
|
|
TCHAR str[HECI_MAX_LINE_LEN];
|
|
TCHAR *msg;
|
|
LoadString(GetModuleHandle(NULL), HECI_ERROR_MESSAGE, str, sizeof(str)/sizeof(TCHAR));
|
|
_ftprintf(stderr, _T("%s"), str);
|
|
_ftprintf(stderr, _T("%s"), L" ");
|
|
LoadString(GetModuleHandle(NULL), errorCode , str, sizeof(str)/sizeof(TCHAR));
|
|
if(0!= lastError)
|
|
{
|
|
msg = _getErrMsg(lastError);
|
|
_ftprintf(stderr, _T("%s (%d): %s\n"),str, lastError, msg);
|
|
}
|
|
else
|
|
{
|
|
_ftprintf(stderr, _T("%s\n"),str);
|
|
}
|
|
}
|
|
|
|
// Display a HECI data message
|
|
void _displayHECIData(UINT32 messageId)
|
|
{
|
|
TCHAR str[HECI_MAX_LINE_LEN];
|
|
LoadString(GetModuleHandle(NULL), messageId , str, sizeof(str)/sizeof(TCHAR));
|
|
_ftprintf(stdout,_T("%s"),str);
|
|
_ftprintf(stdout,_T("%s"),L" ");
|
|
}
|
|
*/
|
|
|
|
#endif
|