master ohmu/fastfetch-openbsd / src / detection / cpu / cpu_nbsd.c
ohmu  ·  2026-10-15
  1#include "cpu.h"
  2#include "common/debug.h"
  3#include "common/sysctl.h"
  4#include "common/io.h"
  5
  6#include <sys/envsys.h>
  7#include <prop/proplib.h>
  8#include <paths.h>
  9#include <time.h>
 10#include <unistd.h>
 11#include <fcntl.h>
 12#include <errno.h>
 13#include <string.h>
 14
 15static void freePropDict(prop_dictionary_t* pdict) {
 16    assert(pdict != nullptr);
 17    if (*pdict == nullptr) {
 18        return;
 19    }
 20    prop_object_release(*pdict);
 21}
 22
 23static const char* detectCpuTemp(const FFCPUOptions* options, double* current) {
 24    FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
 25    if (fd < 0) {
 26        FF_DEBUG("open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed: %s", strerror(errno));
 27        return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
 28    }
 29
 30    [[gnu::cleanup(freePropDict)]] prop_dictionary_t root = nullptr;
 31    if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0) {
 32        FF_DEBUG("prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed: %s", strerror(errno));
 33        return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
 34    }
 35
 36    prop_array_t array;
 37
 38    if (options->tempSensor.length > 0) {
 39        array = prop_dictionary_get(root, options->tempSensor.chars);
 40        if (!array) {
 41            FF_DEBUG("No temp data found in specified sensor");
 42            return "No temp data found in specified sensor";
 43        }
 44    } else {
 45        array = prop_dictionary_get(root, "coretemp0");
 46        if (!array) {
 47            array = prop_dictionary_get(root, "amdzentemp0");
 48        }
 49        if (!array) {
 50            array = prop_dictionary_get(root, "viac7temp0");
 51        }
 52        if (!array) {
 53            array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
 54        }
 55        if (!array) {
 56            FF_DEBUG("No temp data found in root dictionary");
 57            return "No temp data found in root dictionary";
 58        }
 59    }
 60
 61    if (prop_array_count(array) != 2) {
 62        FF_DEBUG("Unexpected `xtemp0` data");
 63        return "Unexpected `xtemp0` data";
 64    }
 65
 66    prop_dictionary_t dict = prop_array_get(array, 0);
 67    if (prop_object_type(dict) != PROP_TYPE_DICTIONARY) {
 68        FF_DEBUG("Unexpected `xtemp0[0]`");
 69        return "Unexpected `xtemp0[0]`";
 70    }
 71
 72    int temp = 0; // in µK
 73    if (!prop_dictionary_get_int(dict, "cur-value", &temp)) {
 74        FF_DEBUG("Failed to get temperature");
 75        return "Failed to get temperature";
 76    }
 77
 78    *current = temp / 1e6 - 273.15;
 79
 80    return nullptr;
 81}
 82
 83const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
 84    if (ffSysctlGetString("machdep.cpu_brand", &cpu->name) != nullptr &&
 85        ffSysctlGetString("machdep.dmi.processor-version", &cpu->name) != nullptr &&
 86        ffSysctlGetString("hw.cpu0.name", &cpu->name) != nullptr &&
 87        ffSysctlGetString("hw.model", &cpu->name) != nullptr) {
 88        ffStrbufSetS(&cpu->name, "Unknown CPU");
 89    }
 90
 91    if (ffSysctlGetString("machdep.dmi.processor-vendor", &cpu->vendor) == nullptr) {
 92        ffStrbufTrimRightSpace(&cpu->vendor);
 93    }
 94
 95    cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
 96    cpu->coresLogical = cpu->coresPhysical;
 97    cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.ncpuonline", cpu->coresLogical);
 98
 99    ffCPUDetectByCpuid(cpu);
100
101    uint32_t freq = (uint32_t) ffSysctlGetInt("machdep.cpu.frequency.target", 0);
102    if (freq == 0) {
103        freq = (uint32_t) (ffSysctlGetInt64("hw.cpu0.clock_frequency", 0) / 1000000);
104    }
105    if (freq == 0) {
106        freq = (uint32_t) ffSysctlGetInt("machdep.dmi.processor-frequency", 0);
107    }
108    if (freq > cpu->frequencyBase) {
109        cpu->frequencyBase = freq;
110    }
111
112    cpu->temperature = FF_CPU_TEMP_UNSET;
113
114    if (options->temp) {
115        detectCpuTemp(options, &cpu->temperature);
116    }
117
118    return nullptr;
119}