From 0686d1db4a81740ea37df2b2d697977f56dde6df Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 30 Jan 2026 18:49:26 +0800 Subject: [PATCH] GPU (Hurd): uses native API; removes libpciaccess dep --- CMakeLists.txt | 7 +- src/common/impl/init.c | 3 - src/detection/gpu/gpu_general.c | 70 ------------------ src/detection/gpu/gpu_gnu.c | 123 ++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 79 deletions(-) delete mode 100644 src/detection/gpu/gpu_general.c create mode 100644 src/detection/gpu/gpu_gnu.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f4cd8ddae..3357fef61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,7 +92,6 @@ cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF) cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF) cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku OR GNU" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF) -cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "GNU" OFF) option(ENABLE_ZLIB "Enable zlib" ON) option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF) @@ -1262,7 +1261,7 @@ elseif(GNU) src/detection/displayserver/linux/xcb.c src/detection/displayserver/linux/xlib.c src/detection/font/font_linux.c - src/detection/gpu/gpu_general.c + src/detection/gpu/gpu_gnu.c src/detection/gpu/gpu_pci.c src/detection/gtk_qt/gtk.c src/detection/host/host_nosupport.c @@ -1641,10 +1640,6 @@ ff_lib_enable(DIRECTX_HEADERS "DirectX-Headers" "DirectX-Headers" ) -ff_lib_enable(PCIACCESS - "pciaccess" - "pciaccess" -) if(ENABLE_THREADS) target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1) diff --git a/src/common/impl/init.c b/src/common/impl/init.c index 0825aec0a..4b9033a6f 100644 --- a/src/common/impl/init.c +++ b/src/common/impl/init.c @@ -225,9 +225,6 @@ void ffListFeatures(void) #if FF_HAVE_FREETYPE "freetype\n" #endif - #if FF_HAVE_PCIACCESS - "libpciaccess\n" - #endif #if FF_HAVE_PULSE "libpulse\n" #endif diff --git a/src/detection/gpu/gpu_general.c b/src/detection/gpu/gpu_general.c deleted file mode 100644 index 6fcb6829b..000000000 --- a/src/detection/gpu/gpu_general.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "gpu.h" - -#ifdef FF_HAVE_PCIACCESS - -#include "common/io.h" -#include "common/library.h" - -#include - -const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) -{ - FF_LIBRARY_LOAD_MESSAGE(pciaccess, "libpciaccess" FF_LIBRARY_EXTENSION, 0) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_system_init) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_slot_match_iterator_create) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_device_next) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_system_cleanup) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_iterator_destroy) - - { - // Requires root access - // Same behavior can be observed with `cp $(which scanpci) /tmp/ && /tmp/scanpci` - FF_SUPPRESS_IO(); - if (ffpci_system_init() < 0) - return "pci_system_init() failed"; - } - - struct pci_device_iterator* iter = ffpci_slot_match_iterator_create(NULL); - for (struct pci_device* dev = NULL; (dev = ffpci_device_next(iter)); ) - { - if (dev->device_class >> 16 != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) - continue; - - uint8_t subclass = (dev->device_class >> 8) & 0xFF; - - if (dev->func > 0 && subclass == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/) - continue; // Likely an auxiliary display controller (#2034) - - FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->vendor_id)); - ffStrbufInit(&gpu->name); - ffStrbufInit(&gpu->driver); - ffStrbufInitStatic(&gpu->platformApi, "libpciaccess"); - ffStrbufInit(&gpu->memoryType); - gpu->temperature = FF_GPU_TEMP_UNSET; - gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; - gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; - gpu->type = FF_GPU_TYPE_UNKNOWN; - gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; - gpu->deviceId = ffGPUPciAddr2Id(dev->domain, dev->bus, dev->dev, dev->func); - gpu->frequency = FF_GPU_FREQUENCY_UNSET; - - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) - ffGPUQueryAmdGpuName(dev->device_id, dev->revision, gpu); - - if (gpu->name.length == 0) - ffGPUFillVendorAndName(subclass, dev->vendor_id, dev->device_id, gpu); - } - ffpci_iterator_destroy(iter); - - ffpci_system_cleanup(); - return NULL; -} - -#else - -const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FF_MAYBE_UNUSED FFlist* gpus) -{ - return "Fastfetch was built without libpciaccess support"; -} -#endif diff --git a/src/detection/gpu/gpu_gnu.c b/src/detection/gpu/gpu_gnu.c new file mode 100644 index 000000000..be1eedba8 --- /dev/null +++ b/src/detection/gpu/gpu_gnu.c @@ -0,0 +1,123 @@ +#include "gpu.h" +#include "common/io.h" + +#include +#include +#include + +enum { + PCI_VENDOR_ID = 0x00, + PCI_DEVICE_ID = 0x02, + PCI_REVISION_ID = 0x08, + PCI_CLASS_PROG = 0x09, + PCI_SUBCLASS = 0x0a, + PCI_CLASS_DEVICE = 0x0b, + PCI_CONF_SIZE = 0x40, +}; + +const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) +{ + int dDomainFd = open(_SERVERS_BUS "/pci/0000", O_RDONLY | O_CLOEXEC); + if (dDomainFd < 0) return "open(_SERVERS_BUS \"/pci/0000\") failed"; + + FF_AUTO_CLOSE_DIR DIR* dirDomain = fdopendir(dDomainFd); + if (dirDomain == NULL) return "fdopendir(domain) failed"; + + struct dirent* busEntry; + while ((busEntry = readdir(dirDomain)) != NULL) + { + if (busEntry->d_type != DT_DIR || busEntry->d_name[0] == '.') + continue; + + char* endptr; + uint16_t pciBus = (uint16_t) strtoul(busEntry->d_name, &endptr, 16); + if (*endptr != '\0') continue; + + int dBusFd = openat(dDomainFd, busEntry->d_name, O_RDONLY | O_CLOEXEC); + if (dBusFd < 0) continue; + + FF_AUTO_CLOSE_DIR DIR* dirBus = fdopendir(dBusFd); + if (dirBus == NULL) continue; + + struct dirent* devEntry; + while ((devEntry = readdir(dirBus)) != NULL) + { + if (devEntry->d_type != DT_DIR || devEntry->d_name[0] == '.') + continue; + + uint8_t pciDev = (uint8_t) strtoul(devEntry->d_name, &endptr, 16); + if (*endptr != '\0') continue; + + int dDevFd = openat(dBusFd, devEntry->d_name, O_RDONLY | O_CLOEXEC); + if (dDevFd < 0) continue; + + FF_AUTO_CLOSE_DIR DIR* dirDev = fdopendir(dDevFd); + if (dirDev == NULL) continue; + + struct dirent* funcEntry; + while ((funcEntry = readdir(dirDev)) != NULL) + { + if (funcEntry->d_type != DT_DIR || funcEntry->d_name[0] == '.') + continue; + + uint8_t pciFunc = (uint8_t) strtoul(funcEntry->d_name, &endptr, 16); + if (*endptr != '\0') continue; + + char subpath[PATH_MAX]; + snprintf(subpath, ARRAY_SIZE(subpath), "%s/%s/%s/%s/config", _SERVERS_BUS "/pci/0000", busEntry->d_name, devEntry->d_name, funcEntry->d_name); + + mach_port_t devicePort = file_name_lookup(subpath, 0, 0); + if (devicePort == MACH_PORT_NULL) + continue; + + mach_msg_type_number_t nread = 0; + + uint8_t data[PCI_CONF_SIZE]; + data_t pData = (data_t) data; + kern_return_t kr = pci_conf_read(devicePort, 0, &pData, &nread, PCI_CONF_SIZE); + mach_port_deallocate(mach_task_self(), devicePort); + if (kr != KERN_SUCCESS || nread < PCI_CONF_SIZE) continue; + + if (pData != (data_t) data) + { + memcpy(data, pData, PCI_CONF_SIZE); + vm_deallocate(mach_task_self(), (vm_address_t)pData, nread); + } + + uint8_t classBase = data[PCI_CLASS_DEVICE]; + if (classBase != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) + continue; + + uint8_t classSub = data[PCI_SUBCLASS]; + if (pciFunc > 0 && classSub == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/) // Likely an auxiliary display controller (#2034) + continue; + + uint8_t revision = data[PCI_REVISION_ID]; + uint16_t vendorId = data[PCI_VENDOR_ID] | (data[PCI_VENDOR_ID + 1] << 8); + uint16_t deviceId = data[PCI_DEVICE_ID] | (data[PCI_DEVICE_ID + 1] << 8); + + FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(vendorId)); + ffStrbufInit(&gpu->name); + ffStrbufInit(&gpu->driver); + ffStrbufInitStatic(&gpu->platformApi, "/servers/bus/pci"); + ffStrbufInit(&gpu->memoryType); + gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; + gpu->type = FF_GPU_TYPE_UNKNOWN; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; + gpu->deviceId = ffGPUPciAddr2Id(0, pciBus, pciDev, pciFunc); + gpu->frequency = FF_GPU_FREQUENCY_UNSET; + + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) + ffGPUQueryAmdGpuName(deviceId, revision, gpu); + + if (gpu->name.length == 0) + ffGPUFillVendorAndName(classSub, vendorId, deviceId, gpu); + } + } + } + + return NULL; +}