/* IOCTL */ static ssize_t esif_file_ipc( struct file *fp, char __user *buf, size_t count, loff_t *ppos ) { u32 len = 0; struct esif_ipc *ipc_req_ptr = esif_ipc_user_to_kernel( (struct esif_ipc *)buf); struct esif_ipc *ipc_rsp_ptr = NULL; if (count < sizeof(struct esif_ipc)) return -EINVAL; if (NULL == ipc_req_ptr) return -ENOMEM; ESIF_TRACE_DYN_IPC("linux_%s: user %p kernel %p count %d\n", __func__, buf, ipc_req_ptr, (int)count); ipc_rsp_ptr = esif_ipc_process(ipc_req_ptr); if (NULL != ipc_rsp_ptr) { len = esif_ipc_kernel_to_user((struct esif_ipc *)buf, ipc_rsp_ptr); ESIF_TRACE_DYN_IPC("linux_%s: user %p kernel %p count = %d\n", __func__, buf, ipc_rsp_ptr, (int)count); if (ipc_req_ptr != ipc_rsp_ptr) esif_ipc_free(ipc_rsp_ptr); } esif_ccb_free(ipc_req_ptr); return len; }
/* IOCTL */ static int esif_ipc_ioctl(struct esif_ipc *ipc_user_ptr) { int rc = 0; struct esif_ipc *ipc_req_ptr = esif_ipc_user_to_kernel(ipc_user_ptr); struct esif_ipc *ipc_rsp_ptr = NULL; if (NULL == ipc_req_ptr) return -ENOMEM; ESIF_TRACE_DYN_IPC("linux_%s: user %p kernel %p\n", __func__, ipc_user_ptr, ipc_req_ptr); ipc_rsp_ptr = esif_ipc_process(ipc_req_ptr); if (NULL != ipc_rsp_ptr) { esif_ipc_kernel_to_user((struct esif_ipc *)ipc_user_ptr, ipc_rsp_ptr); ESIF_TRACE_DYN_IPC("linux_%s: user %p kernel %p\n", __func__, ipc_user_ptr, ipc_rsp_ptr); if (ipc_req_ptr != ipc_rsp_ptr) esif_ipc_free(ipc_rsp_ptr); } else { rc = -EINVAL; } esif_ccb_free(ipc_req_ptr); return rc; }
// Dispatch An Event void EsifEvent_GetAndSignalIpcEvent() { #ifdef ESIF_FEAT_OPT_ACTION_SYSFS // NOOP #else int r_bytes = 0; int data_len = 1024; /* TODO: Change from "magic number" */ enum esif_rc rc = ESIF_OK; struct esif_ipc *ipc_ptr = NULL; struct esif_ipc_event *event_ptr = NULL; ipc_ptr = esif_ipc_alloc_event(&event_ptr, data_len); if (NULL == ipc_ptr) { ESIF_TRACE_ERROR("Fail to allocate esif_ipc\n"); return; } // // TODO: This needs to be in an OS abstraction layer // #ifdef ESIF_ATTR_OS_LINUX r_bytes = read(g_ipc_handle, ipc_ptr, data_len); #endif #ifdef ESIF_ATTR_OS_WINDOWS rc = ipc_execute(ipc_ptr); // // TODO: The return size check is a W/A until a better solution is developed to determine if an event was returned. // (The current LF code does not change the original data_len or fail the request if there are not events.) // r_bytes = 0; if ((ESIF_OK == rc) && (ipc_ptr->data_len != (u32)data_len)) { r_bytes = ipc_ptr->data_len; } #endif // Have Event? if (r_bytes > 0) { ESIF_TRACE_DEBUG("IPC version=%d, type=%d, len = %d, data_len=%d\n", ipc_ptr->version, ipc_ptr->type, r_bytes, ipc_ptr->data_len); EsifEvent_SignalIpcEvent(event_ptr); } esif_ipc_free(ipc_ptr); #endif }
// Send DSP enum esif_rc esif_send_dsp( char *filename, u8 dstId ) { enum esif_rc rc = ESIF_OK; int edpSize = 512; int cmdSize = 0; struct esif_ipc *ipcPtr = NULL; struct esif_ipc_command *commandPtr = NULL; struct esif_command_send_dsp *dspCommandPtr = NULL; struct edp_dir edpDir; size_t bytesRead; char *edpName = 0; IOStreamPtr ioPtr = IOStream_Create(); EsifDataPtr nameSpace = 0; EsifDataPtr key = 0; EsifDataPtr value = 0; if (ioPtr == NULL) { ESIF_TRACE_ERROR("Fail to create IOStream\n"); rc = ESIF_E_NO_MEMORY; goto exit; } // // If we have a filename provided use the contents of the file as the CPC // note this is opaque it is up to the receiver to verify that this is in fact // a CPC. // if (NULL == filename) { ESIF_TRACE_ERROR("Filename is null\n"); rc = ESIF_E_PARAMETER_IS_NULL; goto exit; } // Use name portion of filename for the DataVault key (C:\path\file.edp = file.edp) edpName = strrchr(filename, *ESIF_PATH_SEP); edpName = (edpName ? ++edpName : filename); nameSpace = EsifData_CreateAs(ESIF_DATA_STRING, ESIF_DSP_NAMESPACE, 0, ESIFAUTOLEN); key = EsifData_CreateAs(ESIF_DATA_STRING, edpName, 0, ESIFAUTOLEN); value = EsifData_CreateAs(ESIF_DATA_AUTO, NULL, ESIF_DATA_ALLOCATE, 0); if (nameSpace == NULL || key == NULL || value == NULL) { rc = ESIF_E_NO_MEMORY; goto exit; } // Look for EDP file on disk first then DataVault (static or file) if (!esif_ccb_file_exists(filename) && EsifConfigGet(nameSpace, key, value) == ESIF_OK) { filename = edpName; IOStream_SetMemory(ioPtr, (BytePtr)value->buf_ptr, value->data_len); } else { IOStream_SetFile(ioPtr, filename, (char *)"rb"); } /* FIND CPC within EDP file */ if (IOStream_Open(ioPtr) != 0) { ESIF_TRACE_ERROR("File not found (%s)\n", filename); rc = ESIF_E_IO_OPEN_FAILED; goto exit; } bytesRead = IOStream_Read(ioPtr, &edpDir, sizeof(struct edp_dir)); if (!esif_verify_edp(&edpDir, bytesRead)) { ESIF_TRACE_ERROR("Invalid EDP Header: Signature=%4.4s Version=%d\n", (char *)&edpDir.signature, edpDir.version); rc = ESIF_E_NOT_SUPPORTED; goto exit; } edpSize = edpDir.fpc_offset - edpDir.cpc_offset; IOStream_Seek(ioPtr, edpDir.cpc_offset, SEEK_SET); if (edpSize > MAX_EDP_SIZE) { ESIF_TRACE_ERROR("The edp size %d is larger than maximum edp size\n", edpSize); rc = -ESIF_E_UNSPECIFIED; goto exit; } cmdSize = edpSize + sizeof(*dspCommandPtr); ipcPtr = esif_ipc_alloc_command(&commandPtr, cmdSize); if (NULL == ipcPtr || NULL == commandPtr) { ESIF_TRACE_ERROR("Fail to allocate esif_ipc/esif_ipc_command\n"); rc = ESIF_E_NO_MEMORY; goto exit; } commandPtr->type = ESIF_COMMAND_TYPE_SEND_DSP; commandPtr->req_data_type = ESIF_DATA_STRUCTURE; commandPtr->req_data_offset = 0; commandPtr->req_data_len = cmdSize; commandPtr->rsp_data_type = ESIF_DATA_VOID; commandPtr->rsp_data_offset = 0; commandPtr->rsp_data_len = 0; dspCommandPtr = (struct esif_command_send_dsp *)(commandPtr + 1); dspCommandPtr->id = dstId; dspCommandPtr->data_len = edpSize; bytesRead = IOStream_Read(ioPtr, dspCommandPtr + 1, edpSize); ESIF_TRACE_DEBUG("loaded file %s bytes %d\n", filename, (int)bytesRead); ESIF_TRACE_INFO("CPC file %s(%d) sent to participant %d\n", filename, edpSize, dstId); ipc_execute(ipcPtr); if (ESIF_OK != ipcPtr->return_code) { ESIF_TRACE_ERROR("ipc error code = %s(%d)\n", esif_rc_str(ipcPtr->return_code), ipcPtr->return_code); rc = ipcPtr->return_code; goto exit; } rc = commandPtr->return_code; if ((rc != ESIF_OK) && (rc != ESIF_E_DSP_ALREADY_LOADED)) { ESIF_TRACE_ERROR("primitive error code = %s(%d)\n", esif_rc_str(commandPtr->return_code), commandPtr->return_code); goto exit; } exit: if (NULL != ipcPtr) { esif_ipc_free(ipcPtr); } if (NULL != ioPtr) { IOStream_Close(ioPtr); IOStream_Destroy(ioPtr); } EsifData_Destroy(nameSpace); EsifData_Destroy(key); EsifData_Destroy(value); return rc; }
/* Will sync any existing lower framework participatnts */ enum esif_rc sync_lf_participants() { eEsifError rc = ESIF_OK; struct esif_command_get_participants *data_ptr = NULL; const UInt32 data_len = sizeof(struct esif_command_get_participants); struct esif_ipc_command *command_ptr = NULL; UInt8 i = 0; UInt32 count = 0; struct esif_ipc *ipc_ptr = NULL; ESIF_TRACE_ENTRY_INFO(); ipc_ptr = esif_ipc_alloc_command(&command_ptr, data_len); if (NULL == ipc_ptr || NULL == command_ptr) { ESIF_TRACE_ERROR("Fail to allocate esif_ipc/esif_ipc_command\n"); rc = ESIF_E_NO_MEMORY; goto exit; } command_ptr->type = ESIF_COMMAND_TYPE_GET_PARTICIPANTS; command_ptr->req_data_type = ESIF_DATA_VOID; command_ptr->req_data_offset = 0; command_ptr->req_data_len = 0; command_ptr->rsp_data_type = ESIF_DATA_STRUCTURE; command_ptr->rsp_data_offset = 0; command_ptr->rsp_data_len = data_len; rc = ipc_execute(ipc_ptr); if (ESIF_OK != rc) { goto exit; } if (ESIF_OK != ipc_ptr->return_code) { rc = ipc_ptr->return_code; ESIF_TRACE_WARN("ipc_ptr return_code failure - %s\n", esif_rc_str(rc)); goto exit; } if (ESIF_OK != command_ptr->return_code) { rc = command_ptr->return_code; ESIF_TRACE_WARN("command_ptr return_code failure - %s\n", esif_rc_str(rc)); goto exit; } /* Participant Data */ data_ptr = (struct esif_command_get_participants *)(command_ptr + 1); count = data_ptr->count; for (i = 0; i < count; i++) { struct esif_ipc_event_data_create_participant participantData; EsifData esifParticipantData = {ESIF_DATA_BINARY, &participantData, sizeof(participantData), sizeof(participantData)}; rc = get_participant_data(&participantData, i); if (ESIF_OK != rc) { rc = ESIF_OK; /* Ignore RC for get_participant_data */ continue; } EsifEventMgr_SignalEvent(0, EVENT_MGR_DOMAIN_D0, ESIF_EVENT_PARTICIPANT_CREATE, &esifParticipantData); } exit: ESIF_TRACE_INFO("rc = %s(%u)", esif_rc_str(rc), rc); if (NULL != ipc_ptr) { esif_ipc_free(ipc_ptr); } ESIF_TRACE_EXIT_INFO_W_STATUS(rc); return rc; }
/* Work Around */ static enum esif_rc get_participant_data( struct esif_ipc_event_data_create_participant *pi_ptr, UInt8 participantId ) { eEsifError rc = ESIF_OK; struct esif_command_get_part_detail *data_ptr = NULL; struct esif_ipc_command *command_ptr = NULL; struct esif_ipc *ipc_ptr = NULL; const u32 data_len = sizeof(struct esif_command_get_part_detail); ipc_ptr = esif_ipc_alloc_command(&command_ptr, data_len); if (NULL == ipc_ptr || NULL == command_ptr) { ESIF_TRACE_ERROR("Fail to allocate esif_ipc/esif_ipc_command\n"); rc = ESIF_E_NO_MEMORY; goto exit; } command_ptr->type = ESIF_COMMAND_TYPE_GET_PARTICIPANT_DETAIL; command_ptr->req_data_type = ESIF_DATA_UINT32; command_ptr->req_data_offset = 0; command_ptr->req_data_len = 4; command_ptr->rsp_data_type = ESIF_DATA_STRUCTURE; command_ptr->rsp_data_offset = 0; command_ptr->rsp_data_len = data_len; // ID For Command *(u32 *)(command_ptr + 1) = participantId; rc = ipc_execute(ipc_ptr); if (ESIF_OK != rc) { goto exit; } if (ESIF_OK != ipc_ptr->return_code) { rc = ipc_ptr->return_code; ESIF_TRACE_WARN("ipc_ptr return_code failure - %s\n", esif_rc_str(rc)); goto exit; } if (ESIF_OK != command_ptr->return_code) { rc = command_ptr->return_code; ESIF_TRACE_WARN("command_ptr return_code failure - %s\n", esif_rc_str(rc)); goto exit; } // our data data_ptr = (struct esif_command_get_part_detail *)(command_ptr + 1); if (0 == data_ptr->version) { ESIF_TRACE_ERROR("Participant version is 0\n"); goto exit; } pi_ptr->id = (u8)data_ptr->id; pi_ptr->version = data_ptr->version; esif_ccb_memcpy(pi_ptr->class_guid, data_ptr->class_guid, ESIF_GUID_LEN); pi_ptr->enumerator = data_ptr->enumerator; pi_ptr->flags = data_ptr->flags; esif_ccb_strcpy(pi_ptr->name, data_ptr->name, ESIF_NAME_LEN); esif_ccb_strcpy(pi_ptr->desc, data_ptr->desc, ESIF_DESC_LEN); esif_ccb_strcpy(pi_ptr->driver_name, data_ptr->driver_name, ESIF_NAME_LEN); esif_ccb_strcpy(pi_ptr->device_name, data_ptr->device_name, ESIF_NAME_LEN); esif_ccb_strcpy(pi_ptr->device_path, data_ptr->device_path, ESIF_NAME_LEN); /* ACPI */ esif_ccb_strcpy(pi_ptr->acpi_device, data_ptr->acpi_device, ESIF_NAME_LEN); esif_ccb_strcpy(pi_ptr->acpi_scope, data_ptr->acpi_scope, ESIF_SCOPE_LEN); esif_ccb_strcpy(pi_ptr->acpi_uid, data_ptr->acpi_uid, sizeof(pi_ptr->acpi_uid)); pi_ptr->acpi_type = data_ptr->acpi_type; /* PCI */ pi_ptr->pci_vendor = data_ptr->pci_vendor; pi_ptr->pci_device = data_ptr->pci_device; pi_ptr->pci_bus = data_ptr->pci_bus; pi_ptr->pci_bus_device = data_ptr->pci_bus_device; pi_ptr->pci_function = data_ptr->pci_function; pi_ptr->pci_revision = data_ptr->pci_revision; pi_ptr->pci_class = data_ptr->pci_class; pi_ptr->pci_sub_class = data_ptr->pci_sub_class; pi_ptr->pci_prog_if = data_ptr->pci_prog_if; exit: if (NULL != ipc_ptr) { esif_ipc_free(ipc_ptr); } return rc; }