예제 #1
0
void SupportedPolicyList::update(void)
{
    m_guid.clear();

    // TODO: This should be moved to a DPTF Initialization class. For now, ignore empty result buffer
    DptfBuffer ignore = m_dptfManager->getEsifServices()->primitiveExecuteGet(
        esif_primitive_type::GET_DPTF_CONFIGURATION, ESIF_DATA_BINARY);
    
    DptfBuffer buffer = m_dptfManager->getEsifServices()->primitiveExecuteGet(
        esif_primitive_type::GET_SUPPORTED_POLICIES, ESIF_DATA_BINARY);

    if ((buffer.size() % sizeof(AcpiEsifGuid)) != 0)
    {
        std::stringstream message;
        message << "Received invalid data length [" << buffer.size() << "] from primitive call: GET_SUPPORTED_POLICIES";
        throw dptf_exception(message.str());
    }

    UInt32 guidCount = buffer.size() / sizeof(AcpiEsifGuid);
    AcpiEsifGuid* acpiEsifGuid = reinterpret_cast<AcpiEsifGuid*>(buffer.get());

    for (UInt32 i = 0; i < guidCount; i++)
    {
        UInt8 guidByteArray[GuidSize] = {0};
        esif_ccb_memcpy(guidByteArray, &acpiEsifGuid[i].uuid, GuidSize);
        Guid guid(guidByteArray);
        m_dptfManager->getEsifServices()->writeMessageInfo("Supported GUID: " + guid.toString());
        m_guid.push_back(guid);
    }
}
예제 #2
0
void SupportedPolicyList::update(void)
{
	try
	{
		DptfBuffer buffer = m_dptfManager->getEsifServices()->primitiveExecuteGet(
			esif_primitive_type::GET_SUPPORTED_POLICIES, ESIF_DATA_BINARY);
		if (isBufferValid(buffer))
		{
			m_guid = parseBufferForPolicyGuids(buffer);
		}
		else
		{
			std::stringstream message;
			message << "Received invalid data length [" << buffer.size()
				<< "] from primitive call: GET_SUPPORTED_POLICIES";
			throw dptf_exception(message.str());
		}
	}
	catch (const std::exception& ex)
	{
		m_dptfManager->getEsifServices()->writeMessageWarning(ex.what());
	}

	postMessageWithSupportedGuids();
}
예제 #3
0
void DomainPowerControl_001::setPowerControlDynamicCapsSet(UIntN participantIndex, UIntN domainIndex,
    PowerControlDynamicCapsSet capsSet)
{
    DptfBuffer buffer = capsSet.toPpccBinary();
    getParticipantServices()->primitiveExecuteSet(
        esif_primitive_type::SET_RAPL_POWER_CONTROL_CAPABILITIES, ESIF_DATA_BINARY,
        buffer.get(), buffer.size(), buffer.size(), domainIndex, Constants::Esif::NoPersistInstance);
    m_powerControlDynamicCaps.set(getDynamicCapabilities());
}
예제 #4
0
PowerControlDynamicCapsSet PowerControlDynamicCapsSet::createFromPpcc(const DptfBuffer& buffer)
{
    std::vector<PowerControlDynamicCaps> controls;
    UInt8* data = reinterpret_cast<UInt8*>(buffer.get());
    data += sizeof(esif_data_variant); //Ignore revision field
    struct EsifDataBinaryPpccPackage* currentRow = reinterpret_cast<struct EsifDataBinaryPpccPackage*>(data);

    if (buffer.size() == 0)
    {
        throw dptf_exception("Received empty PPSS buffer.");
    }

    UIntN rows = (buffer.size() - sizeof(esif_data_variant)) / sizeof(EsifDataBinaryPpccPackage);

    if ((buffer.size() - sizeof(esif_data_variant)) % sizeof(EsifDataBinaryPpccPackage))
    {
        throw dptf_exception("Expected binary data size mismatch. (PPSS)");
    }

    for (UIntN i = 0; i < rows; i++)
    {
        PowerControlDynamicCaps temp(
            static_cast<PowerControlType::Type>(currentRow->powerLimitIndex.integer.value),
            static_cast<UIntN>(currentRow->powerLimitMinimum.integer.value),
            static_cast<UIntN>(currentRow->powerLimitMaximum.integer.value),
            static_cast<UIntN>(currentRow->stepSize.integer.value),
            TimeSpan::createFromMilliseconds(static_cast<UIntN>(currentRow->timeWindowMinimum.integer.value)),
            TimeSpan::createFromMilliseconds(static_cast<UIntN>(currentRow->timeWindowMaximum.integer.value)),
            Percentage(0.0),
            Percentage(0.0));

        // TODO : Need to revisit if there are more than 2 power limits
        if (controls.empty())
        {
            controls.push_back(temp);
        }
        else if (controls.front().getPowerControlType() < temp.getPowerControlType())
        {
            controls.push_back(temp);
        }
        else
        {
            controls.insert(controls.begin(), temp);
        }

        data += sizeof(struct EsifDataBinaryPpccPackage);
        currentRow = reinterpret_cast<struct EsifDataBinaryPpccPackage*>(data);
    }

    return PowerControlDynamicCapsSet(controls);
}
예제 #5
0
void DomainPowerControl_001::clearCachedData(void)
{
    m_powerControlDynamicCaps.invalidate();

    if (m_capabilitiesLocked == false)
    {
        DptfBuffer capabilitiesBuffer = createResetPrimitiveTupleBinary(
            esif_primitive_type::SET_RAPL_POWER_CONTROL_CAPABILITIES, Constants::Esif::NoPersistInstance);
        getParticipantServices()->primitiveExecuteSet(
            esif_primitive_type::SET_CONFIG_RESET, ESIF_DATA_BINARY,
            capabilitiesBuffer.get(), capabilitiesBuffer.size(), capabilitiesBuffer.size(),
            0, Constants::Esif::NoInstance);
    }
}
예제 #6
0
std::vector<Guid> SupportedPolicyList::parseBufferForPolicyGuids(const DptfBuffer& buffer)
{
	UInt32 guidCount = buffer.size() / sizeof(AcpiEsifGuid);
	AcpiEsifGuid* acpiEsifGuid = reinterpret_cast<AcpiEsifGuid*>(buffer.get());

	std::vector<Guid> guids;
	for (UInt32 i = 0; i < guidCount; i++)
	{
		UInt8 guidByteArray[GuidSize] = { 0 };
		esif_ccb_memcpy(guidByteArray, &acpiEsifGuid[i].uuid, GuidSize);
		guids.push_back(Guid(guidByteArray));
	}
	return guids;
}
예제 #7
0
void DomainPerformanceControl_001::clearCachedData(void)
{
    m_performanceControlSet.invalidate();
    m_performanceControlDynamicCaps.invalidate();
    m_performanceControlStaticCaps.invalidate();
    m_performanceControlStatus.invalidate();

    if (m_capabilitiesLocked == false)
    {
        DptfBuffer depthLimitBuffer = createResetPrimitiveTupleBinary(
            esif_primitive_type::SET_PERF_PSTATE_DEPTH_LIMIT, Constants::Esif::NoPersistInstance);
        getParticipantServices()->primitiveExecuteSet(
            esif_primitive_type::SET_CONFIG_RESET, ESIF_DATA_BINARY,
            depthLimitBuffer.get(), depthLimitBuffer.size(), depthLimitBuffer.size(),
            0, Constants::Esif::NoInstance);
    }
}
예제 #8
0
ActiveControlSet ActiveControlSet::createFromFps(const DptfBuffer& buffer)
{
	std::vector<ActiveControl> controls;
	UInt8* data = reinterpret_cast<UInt8*>(buffer.get());
	data += sizeof(esif_data_variant); // Ignore revision field
	struct EsifDataBinaryFpsPackage* currentRow = reinterpret_cast<struct EsifDataBinaryFpsPackage*>(data);

	if (buffer.size() == 0)
	{
		throw dptf_exception("Received empty FPS buffer.");
	}

	UIntN rows = (buffer.size() - sizeof(esif_data_variant)) / sizeof(EsifDataBinaryFpsPackage);

	if ((buffer.size() - sizeof(esif_data_variant)) % sizeof(EsifDataBinaryFpsPackage))
	{
		throw dptf_exception("Expected binary data size mismatch. (FPS)");
	}

	for (UIntN i = 0; i < rows; i++)
	{
		ActiveControl temp(
			static_cast<UInt32>(currentRow->control.integer.value),
			static_cast<UInt32>(currentRow->tripPoint.integer
									.value), // May want to represent this differently; -1 is MAX_INT for whatever type
			static_cast<UInt32>(currentRow->speed.integer.value),
			static_cast<UInt32>(currentRow->noiseLevel.integer.value),
			static_cast<UInt32>(currentRow->power.integer.value));

		controls.push_back(temp);

		data += sizeof(struct EsifDataBinaryFpsPackage);
		currentRow = reinterpret_cast<struct EsifDataBinaryFpsPackage*>(data);
	}

	return ActiveControlSet(controls);
}
예제 #9
0
void DomainDisplayControl_001::clearCachedData(void)
{
    m_displayControlDynamicCaps.invalidate();
    m_displayControlSet.invalidate();
    m_currentDisplayControlIndex.invalidate();

    if (m_capabilitiesLocked == false)
    {
        DptfBuffer capabilityBuffer = createResetPrimitiveTupleBinary(
            esif_primitive_type::SET_DISPLAY_CAPABILITY, Constants::Esif::NoPersistInstance);
        getParticipantServices()->primitiveExecuteSet(
            esif_primitive_type::SET_CONFIG_RESET, ESIF_DATA_BINARY,
            capabilityBuffer.get(), capabilityBuffer.size(), capabilityBuffer.size(), 
            0, Constants::Esif::NoInstance);

        DptfBuffer depthLimitBuffer = createResetPrimitiveTupleBinary(
            esif_primitive_type::SET_DISPLAY_DEPTH_LIMIT, Constants::Esif::NoPersistInstance);
        getParticipantServices()->primitiveExecuteSet(
            esif_primitive_type::SET_CONFIG_RESET, ESIF_DATA_BINARY,
            depthLimitBuffer.get(), depthLimitBuffer.size(), depthLimitBuffer.size(),
            0, Constants::Esif::NoInstance);
    }
}
예제 #10
0
Bool SupportedPolicyList::isBufferValid(const DptfBuffer& buffer) const
{
	return ((buffer.size() % sizeof(AcpiEsifGuid)) == 0);
}
예제 #11
0
ThermalRelationshipTable ThermalRelationshipTable::createTrtFromDptfBuffer(const DptfBuffer& buffer)
{
    std::vector<std::shared_ptr<RelationshipTableEntryBase>> entries;
    UInt8* data = reinterpret_cast<UInt8*>(buffer.get());
    struct EsifDataBinaryTrtPackage* currentRow = reinterpret_cast<struct EsifDataBinaryTrtPackage*>(data);

    if (buffer.size() != 0)
    {
        UIntN rows = countTrtRows(buffer.size(), data);

        // Reset currentRow to point to the beginning of the data block
        data = reinterpret_cast<UInt8*>(buffer.get());
        currentRow = reinterpret_cast<struct EsifDataBinaryTrtPackage*>(data);

        for (UIntN i = 0; i < rows; i++)
        {
            // Since the TRT has 2 strings in it, the process for extracting them is:
            //  1. Extract the source at the beginning of the structure
            //  2. Since the actual string data is placed between the source and target, the pointer needs moved
            //  3. Move the pointer past the source string data and set current row
            //  4. Now the targetDevice field will actually point to the right spot
            //  5. Extract target device
            //  6. Move the pointer as before (past the targetDevice string data) and set current row
            //  7. Extract the remaining fields
            //  8. Point data and currentRow to the next row

            std::string source(
                reinterpret_cast<const char*>(&(currentRow->sourceDevice)) + sizeof(union esif_data_variant),
                currentRow->sourceDevice.string.length);

            data += currentRow->sourceDevice.string.length;
            currentRow = reinterpret_cast<struct EsifDataBinaryTrtPackage*>(data);

            std::string target(
                reinterpret_cast<const char*>(&(currentRow->targetDevice)) + sizeof(union esif_data_variant),
                currentRow->targetDevice.string.length);

            data += currentRow->targetDevice.string.length;
            currentRow = reinterpret_cast<struct EsifDataBinaryTrtPackage*>(data);

            auto newTrtEntry = std::make_shared<ThermalRelationshipTableEntry>(
                BinaryParse::normalizeAcpiScope(source),
                BinaryParse::normalizeAcpiScope(target),
                static_cast<UInt32>(currentRow->thermalInfluence.integer.value),
                TimeSpan::createFromTenthSeconds(static_cast<UInt32>(currentRow->thermalSamplingPeriod.integer.value)));

            if (newTrtEntry)
            {
                // Check for duplicate entries. Don't add entry if previous entry exists with same target/source pair
                Bool isDuplicateEntry = false;
                for (auto e = entries.begin(); e != entries.end(); e++)
                {
                    auto trtEntry = std::dynamic_pointer_cast<ThermalRelationshipTableEntry>(*e);
                    if (trtEntry && newTrtEntry->isSameAs(*trtEntry))
                    {
                        isDuplicateEntry = true;
                        break;
                    }
                }

                if (isDuplicateEntry == false)
                {
                    entries.push_back(newTrtEntry);
                }
            }

            // Since we've already accounted for the strings, we now move the pointer by the size of the structure
            //  to get to the next row.
            data += sizeof(struct EsifDataBinaryTrtPackage);
            currentRow = reinterpret_cast<struct EsifDataBinaryTrtPackage*>(data);
        }
    }
    return ThermalRelationshipTable(entries);
}
예제 #12
0
DptfBuffer ThermalRelationshipTable::toTrtBinary() const
{
    DptfBuffer packages;
    UInt32 offset = 0;
    for (auto entry = m_entries.begin(); entry != m_entries.end(); entry++)
    {
        auto trtEntry = std::dynamic_pointer_cast<ThermalRelationshipTableEntry>(*entry);
        if (trtEntry)
        {
            UInt32 sourceScopeLength = (UInt32)(*entry)->getSourceDeviceScope().size();
            UInt32 targetScopeLength = (UInt32)(*entry)->getTargetDeviceScope().size();

            DptfBuffer packageBuffer;
            packageBuffer.allocate(sizeof(EsifDataBinaryTrtPackage) + sourceScopeLength + targetScopeLength);

            EsifDataBinaryTrtPackage entryPackage;
            UInt32 dataAddress = 0;

            // Source Scope
            entryPackage.sourceDevice.string.length = sourceScopeLength;
            entryPackage.sourceDevice.type = esif_data_type::ESIF_DATA_STRING;
            packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.sourceDevice)), sizeof(entryPackage.sourceDevice));
            dataAddress += sizeof(entryPackage.sourceDevice);
            packageBuffer.put(dataAddress, (UInt8*)((*entry)->getSourceDeviceScope().c_str()), sourceScopeLength);
            dataAddress += sourceScopeLength;

            // Target Scope
            entryPackage.targetDevice.string.length = targetScopeLength;
            entryPackage.targetDevice.type = esif_data_type::ESIF_DATA_STRING;
            packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.targetDevice)), sizeof(entryPackage.targetDevice));
            dataAddress += sizeof(entryPackage.targetDevice);
            packageBuffer.put(dataAddress, (UInt8*)((*entry)->getTargetDeviceScope().c_str()), targetScopeLength);
            dataAddress += targetScopeLength;

            // Thermal Influence
            entryPackage.thermalInfluence.integer.type = esif_data_type::ESIF_DATA_UINT64;
            entryPackage.thermalInfluence.integer.value = trtEntry->thermalInfluence();
            packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.thermalInfluence)),
                sizeof(entryPackage.thermalInfluence));
            dataAddress += sizeof(entryPackage.thermalInfluence);

            // Sampling Period
            entryPackage.thermalSamplingPeriod.integer.type = esif_data_type::ESIF_DATA_UINT64;
            entryPackage.thermalSamplingPeriod.integer.value = trtEntry->thermalSamplingPeriod().asTenthSecondsInt();
            packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.thermalSamplingPeriod)),
                sizeof(entryPackage.thermalSamplingPeriod));
            dataAddress += sizeof(entryPackage.thermalSamplingPeriod);

            // Reserved1
            entryPackage.reserved1.integer.type = esif_data_type::ESIF_DATA_UINT64;
            entryPackage.reserved1.integer.value = 0;
            packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.reserved1)), sizeof(entryPackage.reserved1));
            dataAddress += sizeof(entryPackage.reserved1);

            // Reserved2
            entryPackage.reserved2.integer.type = esif_data_type::ESIF_DATA_UINT64;
            entryPackage.reserved2.integer.value = 0;
            packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.reserved2)), sizeof(entryPackage.reserved2));
            dataAddress += sizeof(entryPackage.reserved2);

            // Reserved3
            entryPackage.reserved3.integer.type = esif_data_type::ESIF_DATA_UINT64;
            entryPackage.reserved3.integer.value = 0;
            packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.reserved3)), sizeof(entryPackage.reserved3));
            dataAddress += sizeof(entryPackage.reserved3);

            // Reserved4
            entryPackage.reserved4.integer.type = esif_data_type::ESIF_DATA_UINT64;
            entryPackage.reserved4.integer.value = 0;
            packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.reserved4)), sizeof(entryPackage.reserved4));
            dataAddress += sizeof(entryPackage.reserved4);

            packages.put(offset, packageBuffer.get(), packageBuffer.size());
            offset += packageBuffer.size();
        }
    }

    DptfBuffer buffer(packages.size());
    buffer.put(0, packages.get(), packages.size());
    return buffer;
}
예제 #13
0
ActiveRelationshipTable ActiveRelationshipTable::createArtFromDptfBuffer(const DptfBuffer& buffer)
{
	std::vector<std::shared_ptr<RelationshipTableEntryBase>> entries;

	UInt8* data = reinterpret_cast<UInt8*>(buffer.get());
	struct EsifDataBinaryArtPackage* currentRow = reinterpret_cast<struct EsifDataBinaryArtPackage*>(data);

	if (buffer.size() == 0)
	{
		throw dptf_exception("There is no data to process.");
	}

	UIntN rows = countArtRows(buffer.size(), data);

	// Reset currentRow to point to the beginning of the data block
	data = reinterpret_cast<UInt8*>(buffer.get());
	data += sizeof(esif_data_variant); // Ignore revision field
	currentRow = reinterpret_cast<struct EsifDataBinaryArtPackage*>(data);

	for (UIntN i = 0; i < rows; i++)
	{
		// Since the ART has 2 strings in it, the process for extracting them is:
		//  1. Extract the source at the beginning of the structure
		//  2. Since the actual string data is placed between the source and target, the pointer needs moved
		//  3. Move the pointer past the source string data and set current row
		//  4. Now the targetDevice field will actually point to the right spot
		//  5. Extract target device
		//  6. Move the pointer as before (past the targetDevice string data) and set current row
		//  7. Extract the remaining fields
		//  8. Point data and currentRow to the next row

		std::string source = TableStringParser::getDeviceString((currentRow->sourceDevice));

		data += currentRow->sourceDevice.string.length;
		currentRow = reinterpret_cast<struct EsifDataBinaryArtPackage*>(data);

		std::string target = TableStringParser::getDeviceString((currentRow->targetDevice));

		data += currentRow->targetDevice.string.length;
		currentRow = reinterpret_cast<struct EsifDataBinaryArtPackage*>(data);

		std::vector<UInt32> acEntries;
		acEntries.push_back(static_cast<UInt32>(currentRow->ac0MaxFanSpeed.integer.value));
		acEntries.push_back(static_cast<UInt32>(currentRow->ac1MaxFanSpeed.integer.value));
		acEntries.push_back(static_cast<UInt32>(currentRow->ac2MaxFanSpeed.integer.value));
		acEntries.push_back(static_cast<UInt32>(currentRow->ac3MaxFanSpeed.integer.value));
		acEntries.push_back(static_cast<UInt32>(currentRow->ac4MaxFanSpeed.integer.value));
		acEntries.push_back(static_cast<UInt32>(currentRow->ac5MaxFanSpeed.integer.value));
		acEntries.push_back(static_cast<UInt32>(currentRow->ac6MaxFanSpeed.integer.value));
		acEntries.push_back(static_cast<UInt32>(currentRow->ac7MaxFanSpeed.integer.value));
		acEntries.push_back(static_cast<UInt32>(currentRow->ac8MaxFanSpeed.integer.value));
		acEntries.push_back(static_cast<UInt32>(currentRow->ac9MaxFanSpeed.integer.value));

		auto newArtEntry = std::make_shared<ActiveRelationshipTableEntry>(
			BinaryParse::normalizeAcpiScope(source),
			BinaryParse::normalizeAcpiScope(target),
			static_cast<UInt32>(currentRow->weight.integer.value),
			acEntries);

		if (newArtEntry)
		{
			// Check for duplicate entries. Don't add entry if previous entry exists with same target/source pair
			Bool isDuplicateEntry = false;
			for (auto e = entries.begin(); e != entries.end(); e++)
			{
				auto artEntry = std::dynamic_pointer_cast<ActiveRelationshipTableEntry>(*e);
				if (artEntry && newArtEntry->isSameAs(*artEntry))
				{
					isDuplicateEntry = true;
					break;
				}
			}

			if (isDuplicateEntry == false)
			{
				entries.push_back(newArtEntry);
			}
		}

		// Since we've already accounted for the strings, we now move the pointer by the size of the structure
		//  to get to the next row.
		data += sizeof(struct EsifDataBinaryArtPackage);
		currentRow = reinterpret_cast<struct EsifDataBinaryArtPackage*>(data);
	}

	return ActiveRelationshipTable(entries);
}
예제 #14
0
DptfBuffer ActiveRelationshipTable::toArtBinary() const
{
	esif_data_variant revisionField;
	revisionField.integer.type = esif_data_type::ESIF_DATA_UINT64;
	revisionField.integer.value = 1;

	DptfBuffer packages;
	UInt32 offset = 0;
	for (auto entry = m_entries.begin(); entry != m_entries.end(); entry++)
	{
		auto artEntry = std::dynamic_pointer_cast<ActiveRelationshipTableEntry>(*entry);
		if (artEntry)
		{
			UInt32 sourceScopeLength = (UInt32)(*entry)->getSourceDeviceScope().size();
			UInt32 targetScopeLength = (UInt32)(*entry)->getTargetDeviceScope().size();

			DptfBuffer packageBuffer;
			packageBuffer.allocate(sizeof(EsifDataBinaryArtPackage) + sourceScopeLength + targetScopeLength);

			EsifDataBinaryArtPackage entryPackage;
			UInt32 dataAddress = 0;

			// Source Scope
			entryPackage.sourceDevice.string.length = sourceScopeLength;
			entryPackage.sourceDevice.type = esif_data_type::ESIF_DATA_STRING;
			packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.sourceDevice)), sizeof(entryPackage.sourceDevice));
			dataAddress += sizeof(entryPackage.sourceDevice);
			packageBuffer.put(dataAddress, (UInt8*)((*entry)->getSourceDeviceScope().c_str()), sourceScopeLength);
			dataAddress += sourceScopeLength;

			// Target Scope
			entryPackage.targetDevice.string.length = targetScopeLength;
			entryPackage.targetDevice.type = esif_data_type::ESIF_DATA_STRING;
			packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.targetDevice)), sizeof(entryPackage.targetDevice));
			dataAddress += sizeof(entryPackage.targetDevice);
			packageBuffer.put(dataAddress, (UInt8*)((*entry)->getTargetDeviceScope().c_str()), targetScopeLength);
			dataAddress += targetScopeLength;

			// Weight
			entryPackage.weight.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.weight.integer.value = artEntry->getWeight();
			packageBuffer.put(dataAddress, (UInt8*)(&(entryPackage.weight)), sizeof(entryPackage.weight));
			dataAddress += sizeof(entryPackage.weight);

			// AC0
			entryPackage.ac0MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac0MaxFanSpeed.integer.value = artEntry->ac(0);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac0MaxFanSpeed)), sizeof(entryPackage.ac0MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac0MaxFanSpeed);

			// AC1
			entryPackage.ac1MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac1MaxFanSpeed.integer.value = artEntry->ac(1);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac1MaxFanSpeed)), sizeof(entryPackage.ac1MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac1MaxFanSpeed);

			// AC2
			entryPackage.ac2MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac2MaxFanSpeed.integer.value = artEntry->ac(2);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac2MaxFanSpeed)), sizeof(entryPackage.ac2MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac2MaxFanSpeed);

			// AC3
			entryPackage.ac3MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac3MaxFanSpeed.integer.value = artEntry->ac(3);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac3MaxFanSpeed)), sizeof(entryPackage.ac3MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac3MaxFanSpeed);

			// AC4
			entryPackage.ac4MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac4MaxFanSpeed.integer.value = artEntry->ac(4);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac4MaxFanSpeed)), sizeof(entryPackage.ac4MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac4MaxFanSpeed);

			// AC5
			entryPackage.ac5MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac5MaxFanSpeed.integer.value = artEntry->ac(5);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac5MaxFanSpeed)), sizeof(entryPackage.ac5MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac5MaxFanSpeed);

			// AC6
			entryPackage.ac6MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac6MaxFanSpeed.integer.value = artEntry->ac(6);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac6MaxFanSpeed)), sizeof(entryPackage.ac6MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac6MaxFanSpeed);

			// AC7
			entryPackage.ac7MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac7MaxFanSpeed.integer.value = artEntry->ac(7);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac7MaxFanSpeed)), sizeof(entryPackage.ac7MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac7MaxFanSpeed);

			// AC8
			entryPackage.ac8MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac8MaxFanSpeed.integer.value = artEntry->ac(8);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac8MaxFanSpeed)), sizeof(entryPackage.ac8MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac8MaxFanSpeed);

			// AC9
			entryPackage.ac9MaxFanSpeed.integer.type = esif_data_type::ESIF_DATA_UINT64;
			entryPackage.ac9MaxFanSpeed.integer.value = artEntry->ac(9);
			packageBuffer.put(
				dataAddress, (UInt8*)(&(entryPackage.ac9MaxFanSpeed)), sizeof(entryPackage.ac9MaxFanSpeed));
			dataAddress += sizeof(entryPackage.ac9MaxFanSpeed);

			packages.put(offset, packageBuffer.get(), packageBuffer.size());
			offset += packageBuffer.size();
		}
	}

	UInt32 sizeOfRevision = (UInt32)sizeof(revisionField);
	DptfBuffer buffer(sizeOfRevision + packages.size());
	buffer.put(0, (UInt8*)&revisionField, sizeOfRevision);
	buffer.put(sizeOfRevision, packages.get(), packages.size());
	return buffer;
}