// Load an External File into a specified memory buffer static eEsifError ReadFileIntoBuffer( esif_string filename, void **buffer, UInt32 *buf_size ) { eEsifError rc = ESIF_OK; IOStreamPtr file = IOStream_Create(); BytePtr bufPtr = NULL; size_t size = 0; size_t bytesRead = 0; if (IOStream_SetFile(file, filename, "rb") != EOK) { rc = ESIF_E_IO_ERROR; goto exit; } size = IOStream_GetSize(file); bufPtr = (BytePtr) esif_ccb_malloc(size + 1); if (NULL == bufPtr) { rc = ESIF_E_NO_MEMORY; goto exit; } if (IOStream_Open(file) != 0) { rc = ESIF_E_IO_ERROR; goto exit; } bytesRead = IOStream_ReadAt(file, bufPtr, size, 0); if (bytesRead != size) { rc = ESIF_E_IO_ERROR; goto exit; } bufPtr[size] = 0; *buffer = bufPtr; *buf_size = (UInt32)size; exit: IOStream_Destroy(file); if (rc != ESIF_OK) { esif_ccb_free(bufPtr); } return rc; }
/* Add DSP Entry */ static eEsifError esif_dsp_entry_create(struct esif_ccb_file *file_ptr) { eEsifError rc = ESIF_E_UNSPECIFIED; EsifDspPtr dspPtr = NULL; EsifFpcPtr fpcPtr = NULL; UInt32 fpcIsStatic = ESIF_FALSE; UInt8 i = 0; char path[MAX_PATH]={0}; UInt32 fpcSize = 0; UInt32 edpSize = 0; size_t numFpcBytesRead = 0; struct edp_dir edp_dir; EsifDataPtr nameSpace = 0; EsifDataPtr key = 0; EsifDataPtr value = 0; IOStreamPtr ioPtr = IOStream_Create(); if ((NULL == file_ptr) || (NULL == ioPtr)) { ESIF_TRACE_ERROR("The file pointer or IO stream is NULL\n"); goto exit; } nameSpace = EsifData_CreateAs(ESIF_DATA_STRING, ESIF_DSP_NAMESPACE, 0, ESIFAUTOLEN); key = EsifData_CreateAs(ESIF_DATA_STRING, file_ptr->filename, 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; } ESIF_TRACE_DEBUG("Filename: %s", file_ptr->filename); dspPtr = esif_dsp_create(); if (NULL == dspPtr) { ESIF_TRACE_ERROR("Fail to allocate dsp entry\n"); goto exit; } // Look for EDP file on disk first then in DataVault (static or file) esif_build_path(path, sizeof(path), ESIF_PATHTYPE_DSP, file_ptr->filename, NULL); if (!esif_ccb_file_exists(path) && EsifConfigGet(nameSpace, key, value) == ESIF_OK) { esif_ccb_strcpy(path, file_ptr->filename, MAX_PATH); IOStream_SetMemory(ioPtr, StoreReadOnly, (BytePtr)value->buf_ptr, value->data_len); } else { IOStream_SetFile(ioPtr, StoreReadOnly, path, "rb"); } ESIF_TRACE_DEBUG("Fullpath: %s", path); if (IOStream_Open(ioPtr) != 0) { ESIF_TRACE_ERROR("File not found (%s)", path); goto exit; } /* Read FPC From EDP File */ if (esif_ccb_strstr(&path[0], ".edp")) { /* EDP - Only Read The FPC Part */ edpSize = (UInt32)IOStream_GetSize(ioPtr); if (!edpSize) { goto exit; } numFpcBytesRead = IOStream_Read(ioPtr, &edp_dir, sizeof(edp_dir)); if (!esif_verify_edp(&edp_dir, numFpcBytesRead)) { ESIF_TRACE_ERROR("Invalid EDP Header: Signature=%4.4s Version=%d\n", (char *)&edp_dir.signature, edp_dir.version); goto exit; } if (edpSize > MAX_EDP_SIZE || edp_dir.fpc_offset > MAX_FPC_SIZE || edp_dir.fpc_offset > edpSize) { ESIF_TRACE_ERROR("The edp or fpc file size is larger than maximum\n"); goto exit; } fpcSize = edpSize - edp_dir.fpc_offset; IOStream_Seek(ioPtr, edp_dir.fpc_offset, SEEK_SET); ESIF_TRACE_DEBUG("File found (%s) size %u, FPC size %u from offset %u", path, edpSize, fpcSize, edp_dir.fpc_offset); } else { ESIF_TRACE_DEBUG("File %s does not have .fpc and .edp format!", path); } // use static DataVault buffer (if available), otherwise allocate space for our FPC file contents (which will not be freed) if (IOStream_GetType(ioPtr) == StreamMemory && value->buf_len == 0) { fpcPtr = (EsifFpcPtr)IOStream_GetMemoryBuffer(ioPtr); if (NULL == fpcPtr) { ESIF_TRACE_ERROR("NULL buffer"); goto exit; } fpcPtr = (EsifFpcPtr) (((BytePtr) fpcPtr) + IOStream_GetOffset(ioPtr)); numFpcBytesRead = fpcSize; ESIF_TRACE_DEBUG("Static vault size %u buf_ptr=0x%p\n", (int)numFpcBytesRead, fpcPtr); fpcIsStatic = ESIF_TRUE; } else { fpcPtr = (EsifFpcPtr)esif_ccb_malloc(fpcSize); if (NULL == fpcPtr) { ESIF_TRACE_ERROR("malloc failed to allocate %u bytes\n", fpcSize); goto exit; } ESIF_TRACE_DEBUG("File malloc size %u", fpcSize); // read file contents numFpcBytesRead = IOStream_Read(ioPtr, fpcPtr, fpcSize); if (numFpcBytesRead < fpcSize) { ESIF_TRACE_ERROR("Read short received %u of %u bytes\n", (int)numFpcBytesRead, fpcSize); goto exit; } ESIF_TRACE_DEBUG("File read size %u", (int)numFpcBytesRead); } ESIF_TRACE_DEBUG("\nDecode Length: %u", fpcPtr->size); ESIF_TRACE_DEBUG("Code: %s", fpcPtr->header.code); ESIF_TRACE_DEBUG("Ver Major: %u", fpcPtr->header.ver_major); ESIF_TRACE_DEBUG("Ver Minor: %u", fpcPtr->header.ver_minor); ESIF_TRACE_DEBUG("Name: %s", fpcPtr->header.name); ESIF_TRACE_DEBUG("Description: %s", fpcPtr->header.description); ESIF_TRACE_DEBUG("Type: %s", fpcPtr->header.type); ESIF_TRACE_DEBUG("Bus Enumerator: %u", fpcPtr->header.bus_enum); ESIF_TRACE_DEBUG("ACPI Device: %s", fpcPtr->header.acpi_device); ESIF_TRACE_DEBUG("ACPI Scope: %s", fpcPtr->header.acpi_scope); ESIF_TRACE_DEBUG("ACPI Type: %s", fpcPtr->header.acpi_type); ESIF_TRACE_DEBUG("ACPI UID: %s", fpcPtr->header.acpi_UID); ESIF_TRACE_DEBUG("PCI Vendor ID: %s", fpcPtr->header.pci_vendor_id); ESIF_TRACE_DEBUG("PCI Device ID: %s", fpcPtr->header.pci_device_id); ESIF_TRACE_DEBUG("PCI Bus: %s", fpcPtr->header.pci_bus); ESIF_TRACE_DEBUG("PCI Device: %s", fpcPtr->header.pci_device); ESIF_TRACE_DEBUG("PCI Function: %s", fpcPtr->header.pci_function); dspPtr->code_ptr = (EsifString)fpcPtr->header.name; dspPtr->bus_enum = (UInt8 *)&fpcPtr->header.bus_enum; dspPtr->type = (EsifString)fpcPtr->header.type; dspPtr->ver_major_ptr = (UInt8 *)&fpcPtr->header.ver_major; dspPtr->ver_minor_ptr = (UInt8 *)&fpcPtr->header.ver_minor; dspPtr->acpi_device = (EsifString)fpcPtr->header.acpi_device; dspPtr->acpi_scope = (EsifString)fpcPtr->header.acpi_scope; dspPtr->acpi_type = (EsifString)fpcPtr->header.acpi_type; dspPtr->acpi_uid = (EsifString)fpcPtr->header.acpi_UID; dspPtr->vendor_id = (EsifString)fpcPtr->header.pci_vendor_id; dspPtr->device_id = (EsifString)fpcPtr->header.pci_device_id; dspPtr->pci_bus = (EsifString)&fpcPtr->header.pci_bus; dspPtr->pci_bus_device = (EsifString)&fpcPtr->header.pci_device; dspPtr->pci_function = (EsifString)&fpcPtr->header.pci_function; /* Assign Function Pointers */ dspPtr->get_code = get_code; dspPtr->get_ver_minor = get_ver_minor; dspPtr->get_ver_major = get_ver_major; dspPtr->get_temp_tc1 = get_temp_c1; dspPtr->get_percent_xform = get_percent_xform; dspPtr->insert_primitive = insert_primitive; dspPtr->insert_algorithm = insert_algorithm; dspPtr->insert_domain = insert_domain; dspPtr->insert_event = insert_event; dspPtr->get_primitive = get_primitive; dspPtr->get_action = get_action; dspPtr->get_algorithm = get_algorithm; dspPtr->get_domain = get_domain; dspPtr->get_event_by_type = get_event_by_type; dspPtr->get_event_by_guid = get_event_by_guid; dspPtr->init_fpc_iterator = init_fpc_iterator; dspPtr->get_next_fpc_domain = get_next_fpc_domain; dspPtr->get_domain_count = get_domain_count; rc = esif_fpc_load(fpcPtr, dspPtr); if (ESIF_OK == rc) { ESIF_TRACE_DEBUG("FPC %s load successfully", path); } else { ESIF_TRACE_DEBUG("Unable to load FPC %s, rc %s", path, esif_rc_str(rc)); goto exit; } /* Lock DSP Manager */ esif_ccb_write_lock(&g_dm.lock); /* Simple Table Lookup For Now. Scan Table And Find First Empty Slot */ /* Empty slot indicated by AVAILABLE state */ for (i = 0; i < MAX_DSP_MANAGER_ENTRY; i++) { if (NULL == g_dm.dme[i].dsp_ptr) { break; } } /* If No Available Slots Return */ if (i >= MAX_DSP_MANAGER_ENTRY) { esif_ccb_write_unlock(&g_dm.lock); ESIF_TRACE_ERROR("No free dsp manager entry is available for %s\n", file_ptr->filename); goto exit; } /* ** Take Slot */ g_dm.dme[i].dsp_ptr = dspPtr; g_dm.dme[i].file_ptr = file_ptr; g_dm.dme[i].fpc_ptr = (fpcIsStatic ? 0 : fpcPtr); g_dm.dme_count++; dspPtr = NULL; // Prevent deallocate on exit fpcPtr = NULL; // Prevent deallocate on exit esif_ccb_write_unlock(&g_dm.lock); rc = ESIF_OK; ESIF_TRACE_INFO("Create entry in dsp manager successfully for %s\n", file_ptr->filename); exit: IOStream_Destroy(ioPtr); EsifData_Destroy(nameSpace); EsifData_Destroy(key); EsifData_Destroy(value); esif_dsp_destroy(dspPtr); if (!fpcIsStatic) { esif_ccb_free(fpcPtr); } return rc; }
static eEsifError EsifGetActionDelegateCnfg( const EsifUpDomainPtr domainPtr, const EsifDataPtr requestPtr, EsifDataPtr responsePtr ) { extern int g_shell_enabled; // ESIF Shell Enabled Flag extern Bool g_ws_restricted;// Web Server Restricted Mode Flag eEsifError rc = ESIF_OK; EsifPrimitiveTuple dcfgTuple = { GET_CONFIG_ACCESS_CONTROL_SUR, 0, 255 }; EsifPrimitiveTuple gddvTuple = { GET_CONFIG_DATAVAULT_SUR, 0, 255 }; EsifData dcfgData = { ESIF_DATA_UINT32, NULL, ESIF_DATA_ALLOCATE, 0 }; EsifData gddvData = { ESIF_DATA_AUTO, NULL, ESIF_DATA_ALLOCATE, 0 }; ESIF_ASSERT(NULL != domainPtr); ESIF_ASSERT(NULL != requestPtr); UNREFERENCED_PARAMETER(responsePtr); // Not currently used by DPTF dcfgTuple.domain = domainPtr->domain; gddvTuple.domain = domainPtr->domain; // Execute DCFG to read Access Control List Bitmask from BIOS, if it exists rc = EsifUp_ExecutePrimitive(domainPtr->upPtr, &dcfgTuple, requestPtr, &dcfgData); if (rc == ESIF_OK && dcfgData.buf_ptr != NULL && dcfgData.buf_len >= sizeof(UInt32)) { DCfgOptions newmask = { .asU32 = *(UInt32 *)dcfgData.buf_ptr }; DCfg_Set(newmask); ESIF_TRACE_INFO("DCFG Loaded: 0x%08X\n", newmask.asU32); // Disable ESIF Shell if Access Control forbids it if (DCfg_Get().opt.ShellAccessControl) { g_shell_enabled = 0; } // Stop Web Server (if Started) if Restricted or Generic Access Control forbids it if (EsifWebIsStarted() && ((!g_ws_restricted && DCfg_Get().opt.GenericUIAccessControl)|| (g_ws_restricted && DCfg_Get().opt.RestrictedUIAccessControl)) ) { EsifWebStop(); } } // Execute GDDV to read DataVault from BIOS, if it exists rc = EsifUp_ExecutePrimitive(domainPtr->upPtr, &gddvTuple, requestPtr, &gddvData); if (rc != ESIF_OK) { // Always Return OK if no ESIF_LF or GDDV object in BIOS if (rc == ESIF_E_NO_LOWER_FRAMEWORK || rc == ESIF_E_ACPI_OBJECT_NOT_FOUND) { rc = ESIF_OK; } } else { char *dv_name = "__merge"; // Temporary DV Name DataVaultPtr DB = DataBank_GetNameSpace(g_DataBankMgr, dv_name); if (DB != NULL) { DataBank_CloseNameSpace(g_DataBankMgr, dv_name); } DB = DataBank_OpenNameSpace(g_DataBankMgr, dv_name); // Load Datavault into temporary namespace. DV may or may not be preceded by a variant if (DB) { u32 skipbytes = 0; void *buffer = NULL; // // This is in place to resolve a static code analysis issue. // This should never happen if EsifUp_ExecutePrimitive is successful above. // if (NULL == gddvData.buf_ptr) { DataBank_CloseNameSpace(g_DataBankMgr, dv_name); ESIF_TRACE_DEBUG("No data returned for BIOS datavault.\n"); goto exit; } skipbytes = (memcmp(gddvData.buf_ptr, "\xE5\x1F", 2) == 0 ? 0 : sizeof(union esif_data_variant)); buffer = esif_ccb_malloc(gddvData.data_len); if (NULL == buffer) { DataBank_CloseNameSpace(g_DataBankMgr, dv_name); ESIF_TRACE_DEBUG("Unable to allocate memory\n"); rc = ESIF_E_NO_MEMORY; goto exit; } esif_ccb_memcpy(buffer, (u8*)gddvData.buf_ptr + skipbytes, gddvData.data_len - skipbytes); IOStream_SetMemory(DB->stream, buffer, gddvData.data_len - skipbytes); if ((rc = DataVault_ReadVault(DB)) != ESIF_OK) { DataBank_CloseNameSpace(g_DataBankMgr, dv_name); ESIF_TRACE_DEBUG("Unable to Open DataVault: %s\n", esif_rc_str(rc)); rc = ESIF_OK; } else { EsifDataPtr data_nspace = NULL; EsifDataPtr data_key = NULL; EsifDataPtr data_targetdv = NULL; esif_flags_t options = 0; // NOPERSIST esif_string keyspec = "*"; // Merge All Keys esif_string targetdv = g_DataVaultDefault; DB->flags |= (ESIF_SERVICE_CONFIG_READONLY); // Merge Contents into Default DataVault data_nspace = EsifData_CreateAs(ESIF_DATA_STRING, dv_name, 0, ESIFAUTOLEN); data_targetdv = EsifData_CreateAs(ESIF_DATA_STRING, targetdv, 0, ESIFAUTOLEN); data_key = EsifData_CreateAs(ESIF_DATA_STRING, keyspec, 0, ESIFAUTOLEN); if (data_nspace == NULL || data_key == NULL || data_targetdv == NULL) { rc = ESIF_E_NO_MEMORY; } else { rc = EsifConfigCopy(data_nspace, data_targetdv, data_key, options, ESIF_FALSE, NULL); } ESIF_TRACE_INFO("GDDV Loaded: %d bytes, %d keys => %s.dv [%s]\n", (int)IOStream_GetSize(DB->stream), DataCache_GetCount(DB->cache), targetdv, esif_rc_str(rc)); EsifData_Destroy(data_nspace); EsifData_Destroy(data_key); EsifData_Destroy(data_targetdv); DataBank_CloseNameSpace(g_DataBankMgr, dv_name); } esif_ccb_free(buffer); } } exit: esif_ccb_free(dcfgData.buf_ptr); esif_ccb_free(gddvData.buf_ptr); return rc; }
// Write DataVault to Disk eEsifError DataVault_WriteVault(DataVaultPtr self) { eEsifError rc = ESIF_OK; DataCacheEntryPtr pairPtr = NULL; IOStreamPtr diskStreamPtr = NULL; IOStreamPtr memStreamPtr = NULL; BytePtr memStreamBuffer = NULL; size_t memStreamBufSize = 0; UInt32 idx; DataCachePtr cacheClonePtr = NULL; if (FLAGS_TEST(self->flags, ESIF_SERVICE_CONFIG_STATIC | ESIF_SERVICE_CONFIG_READONLY)) { rc = ESIF_E_READONLY; goto exit; } if (self->stream->file.name == NULL || self->cache == NULL) { rc = ESIF_E_PARAMETER_IS_NULL; goto exit; } // // As the cache data can be modified while writing the data vault (due to // non-cached values), we create a clone of the current cache so that we can // fall back to it in case of a failure. // cacheClonePtr = DataCache_Clone(self->cache); if ((NULL == cacheClonePtr) && (self->cache != NULL)) { rc = ESIF_E_NO_MEMORY; goto exit; } // // Use a memory stream for creation before writing the final output to a file // memStreamPtr = IOStream_Create(); if (!memStreamPtr) { rc = ESIF_E_NO_MEMORY; goto exit; } if (IOStream_SetMemory(memStreamPtr, NULL, 0) != EOK) { rc = ESIF_E_NO_MEMORY; goto exit; } // // If any rows contain NOCACHE PERSIST values, we need to read them from the // original file before we overwrite it // diskStreamPtr = IOStream_Create(); if (diskStreamPtr == NULL) { rc = ESIF_E_NO_MEMORY; goto exit; } if (IOStream_Seek(memStreamPtr, sizeof(DataVaultHeader), SEEK_CUR) != EOK) { rc = ESIF_E_IO_ERROR; goto exit; } // // Write the key/value pairs to the memory stream for each data category // Fill in the data header for each category after the key/value pairs are written // Note: Only write persisted data // // Write All Persisted Rows from Sorted List to DataVault for (idx = 0; rc == ESIF_OK && idx < self->cache->size; idx++) { pairPtr = &self->cache->elements[idx]; if (!(pairPtr->flags & ESIF_SERVICE_CONFIG_PERSIST)) { continue; } rc = DataVault_WriteKeyValuePair(self, pairPtr, memStreamPtr); if (rc != ESIF_OK) { goto exit; } } // // Now go back and complete the headers // Fill in and write the main header // if (IOStream_Open(memStreamPtr) != EOK) { rc = ESIF_E_IO_ERROR; goto exit; } DataVaultHeader header = { 0 }; esif_ccb_memcpy(&header.signature, ESIFDV_SIGNATURE, sizeof(header.signature)); header.headersize = sizeof(header); header.version = ESIFDV_VERSION(1, 0, ESIFDV_REVISION); header.flags = self->flags; if (IOStream_Write(memStreamPtr, &header, sizeof(header)) != sizeof(header)) { rc = ESIF_E_IO_ERROR; goto exit; } memStreamBuffer = IOStream_GetMemoryBuffer(memStreamPtr); memStreamBufSize = IOStream_GetSize(memStreamPtr); // // Now write the memory stream to the disk // if (rc == ESIF_OK && IOStream_OpenFile(diskStreamPtr, self->stream->file.name, "wb") != EOK) { rc = ESIF_E_IO_OPEN_FAILED; goto exit; } if (rc == ESIF_OK && (IOStream_Write(diskStreamPtr, memStreamBuffer, memStreamBufSize) != memStreamBufSize)) { rc = ESIF_E_IO_ERROR; goto exit; } exit: IOStream_Destroy(diskStreamPtr); IOStream_Destroy(memStreamPtr); if (rc != ESIF_OK && cacheClonePtr != NULL) { DataCache_Destroy(self->cache); self->cache = cacheClonePtr; } else { DataCache_Destroy(cacheClonePtr); } return rc; }