Files
fastfetch/src/detection/cpu/cpu_windows.c
T

187 lines
6.1 KiB
C
Raw Normal View History

2022-11-21 22:26:50 +08:00
#include "cpu.h"
2022-11-26 12:55:48 +08:00
#include "util/windows/registry.h"
#include "util/windows/nt.h"
2022-11-23 15:10:40 +08:00
#include "util/mallocHelper.h"
#include "util/smbiosHelper.h"
2022-11-21 22:26:50 +08:00
// 7.5
typedef struct FFSmbiosProcessorInfo
{
FFSmbiosHeader Header;
uint8_t SocketDesignation; // string
uint8_t ProcessorType; // enum
uint8_t ProcessorFamily; // enum
uint8_t ProcessorManufacturer; // string
uint64_t ProcessorID; // varies
uint8_t ProcessorVersion; // string
uint8_t Voltage; // varies
uint16_t ExternalClock; // varies
uint16_t MaxSpeed; // varies
uint16_t CurrentSpeed; // varies
uint8_t Status; // varies
uint8_t ProcessorUpgrade; // enum
// 2.1+
uint16_t L1CacheHandle; // varies
uint16_t L2CacheHandle; // varies
uint16_t L3CacheHandle; // varies
// 2.3+
uint8_t SerialNumber; // string
uint8_t AssertTag; // string
uint8_t PartNumber; // string
// 2.5+
uint8_t CoreCount; // varies
uint8_t CoreEnabled; // varies
uint8_t ThreadCount; // varies
uint16_t ProcessorCharacteristics; // bit field
// 2.6+
uint16_t ProcessorFamily2; // enum
// 3.0+
uint16_t CoreCount2; // varies
uint16_t CoreEnabled2; // varies
uint16_t ThreadCount2; // varies
// 3.6+
uint16_t ThreadEnabled; // varies
2024-05-10 22:46:10 +08:00
} __attribute__((__packed__)) FFSmbiosProcessorInfo;
static_assert(offsetof(FFSmbiosProcessorInfo, ThreadEnabled) == 0x30,
"FFSmbiosProcessorInfo: Wrong struct alignment");
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
{
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
if (!smbiosTable)
return "Failed to get SMBIOS data";
const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_PROCESSOR_INFO];
2024-01-06 14:46:54 +08:00
if (!data)
return "Processor information is not found in SMBIOS data";
while (data->ProcessorType != 0x03 /*Central Processor*/ || (data->Status & 0b00000111) != 1 /*Enabled*/)
{
2024-01-06 14:46:54 +08:00
data = (const FFSmbiosProcessorInfo*) ffSmbiosNextEntry(&data->Header);
if (data->Header.Type != FF_SMBIOS_TYPE_PROCESSOR_INFO)
return "No active CPU is found in SMBIOS data";
2024-01-06 14:46:54 +08:00
}
2024-07-17 10:56:30 +08:00
uint32_t speed = data->MaxSpeed;
// Sometimes SMBIOS reports invalid value. We assume that max speed is small than 2x of base
if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2)
return "Possible invalid CPU max speed in SMBIOS data. See #800";
cpu->frequencyMax = speed;
2024-01-06 14:46:54 +08:00
return NULL;
}
2024-03-12 23:48:03 +08:00
static const char* detectNCores(FFCPUResult* cpu)
2022-11-21 22:26:50 +08:00
{
2024-03-12 23:48:03 +08:00
DWORD length = 0;
GetLogicalProcessorInformationEx(RelationAll, NULL, &length);
if (length == 0)
return "GetLogicalProcessorInformationEx(RelationAll, NULL, &length) failed";
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
if (!pProcessorInfo || !GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length))
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
for(
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
)
2022-11-21 22:26:50 +08:00
{
2024-06-04 23:56:00 +08:00
if (ptr->Relationship == RelationProcessorCore)
2024-03-12 23:48:03 +08:00
++cpu->coresPhysical;
2024-06-04 23:56:00 +08:00
else if (ptr->Relationship == RelationGroup)
2022-11-21 22:26:50 +08:00
{
2024-03-12 23:48:03 +08:00
for (uint32_t index = 0; index < ptr->Group.ActiveGroupCount; ++index)
2022-11-21 22:26:50 +08:00
{
2024-03-12 23:48:03 +08:00
cpu->coresOnline += ptr->Group.GroupInfo[index].ActiveProcessorCount;
cpu->coresLogical += ptr->Group.GroupInfo[index].MaximumProcessorCount;
2022-11-21 22:26:50 +08:00
}
}
2024-11-26 02:53:01 +02:00
if (ptr->Relationship == RelationProcessorPackage) {
cpu->packages++;
2024-11-26 02:53:01 +02:00
}
2022-11-21 22:26:50 +08:00
}
2024-03-12 23:48:03 +08:00
return NULL;
}
static const char* detectByRegistry(FFCPUResult* cpu)
{
2023-09-07 17:03:24 +08:00
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
2023-06-12 09:56:03 +08:00
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
2022-11-21 22:26:50 +08:00
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
2023-02-23 21:31:33 +08:00
2024-03-12 23:48:03 +08:00
if (cpu->coresLogical == 0)
{
DWORD cores;
if (RegQueryInfoKeyW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor", NULL, NULL, &cores, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
cpu->coresOnline = cpu->coresPhysical = cpu->coresLogical = (uint16_t) cores;
}
2024-05-21 09:09:08 +08:00
uint32_t mhz;
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
2024-07-17 10:56:30 +08:00
cpu->frequencyBase = mhz;
2024-05-21 09:09:08 +08:00
return NULL;
}
static const char* detectCoreTypes(FFCPUResult* cpu)
{
FF_AUTO_FREE PROCESSOR_POWER_INFORMATION* pinfo = calloc(cpu->coresLogical, sizeof(PROCESSOR_POWER_INFORMATION));
if (!NT_SUCCESS(NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, (ULONG) sizeof(PROCESSOR_POWER_INFORMATION) * cpu->coresLogical)))
return "NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, size) failed";
2024-05-19 18:23:18 +08:00
for (uint32_t icore = 0; icore < cpu->coresLogical && pinfo[icore].MhzLimit; ++icore)
{
2024-05-19 18:23:18 +08:00
uint32_t ifreq = 0;
while (cpu->coreTypes[ifreq].freq != pinfo[icore].MhzLimit && cpu->coreTypes[ifreq].freq > 0)
++ifreq;
if (cpu->coreTypes[ifreq].freq == 0)
cpu->coreTypes[ifreq].freq = pinfo[icore].MhzLimit;
++cpu->coreTypes[ifreq].count;
}
2024-07-17 10:56:30 +08:00
if (cpu->frequencyBase == 0)
cpu->frequencyBase = pinfo->MaxMhz;
return NULL;
}
2024-09-24 11:09:51 +08:00
const char* detectThermalTemp(double* current, double* critical);
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
2024-03-12 23:48:03 +08:00
detectNCores(cpu);
const char* error = detectByRegistry(cpu);
if (error)
return error;
2024-08-18 17:26:53 +08:00
ffCPUDetectSpeedByCpuid(cpu);
2024-05-21 09:09:08 +08:00
if (options->showPeCoreCount) detectCoreTypes(cpu);
2024-07-17 10:56:30 +08:00
if (cpu->frequencyMax == 0)
detectMaxSpeedBySmbios(cpu);
2024-03-12 23:48:03 +08:00
2023-06-12 09:56:03 +08:00
if(options->temp)
2024-09-24 11:09:51 +08:00
detectThermalTemp(&cpu->temperature, NULL);
2023-06-12 09:56:03 +08:00
return NULL;
2022-11-21 22:26:50 +08:00
}