diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ace39fb41..e052c2f3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -371,16 +371,16 @@ jobs: run: ctest - name: create zip archive - run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-windows-amd64.zip *.dll fastfetch.exe flashfetch.exe presets + run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip *.dll fastfetch.exe flashfetch.exe presets - name: create 7z archive - run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-windows-amd64.7z *.dll fastfetch.exe flashfetch.exe presets + run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z *.dll fastfetch.exe flashfetch.exe presets - name: upload artifacts uses: actions/upload-artifact@v4 with: name: fastfetch-windows-amd64 - path: ./fastfetch-*-windows-amd64.* + path: ./fastfetch-windows-amd64.* windows-i686: name: Windows-i686 @@ -438,16 +438,16 @@ jobs: run: ctest - name: create zip archive - run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-windows-i686.zip *.dll fastfetch.exe flashfetch.exe presets + run: 7z a -tzip -mx9 -bd -y fastfetch-windows-i686.zip *.dll fastfetch.exe flashfetch.exe presets - name: create 7z archive - run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-windows-i686.7z *.dll fastfetch.exe flashfetch.exe presets + run: 7z a -t7z -mx9 -bd -y fastfetch-windows-i686.7z *.dll fastfetch.exe flashfetch.exe presets - name: upload artifacts uses: actions/upload-artifact@v4 with: name: fastfetch-windows-i686 - path: ./fastfetch-*-windows-i686.* + path: ./fastfetch-windows-i686.* release: if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch' @@ -474,6 +474,7 @@ jobs: uses: actions/download-artifact@v4 - name: rm old artifacts + if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release run: | rm -rf fastfetch-*-old-* diff --git a/CHANGELOG.md b/CHANGELOG.md index fce1fe7a4..cadf827f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 2.8.3 + +Bugfixes: +* Fix GPU name detection for AMD graphic cards (GPU, Linux / FreeBSD) + # 2.8.2 Changes: diff --git a/CMakeLists.txt b/CMakeLists.txt index dcb829ad4..b0c499b91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.8.2 + VERSION 2.8.3 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -401,6 +401,7 @@ if(LINUX) src/detection/displayserver/linux/xlib.c src/detection/font/font_linux.c src/detection/gpu/gpu_linux.c + src/detection/gpu/gpu_pci.c src/detection/gtk_qt/gtk.c src/detection/host/host_linux.c src/detection/icons/icons_linux.c @@ -518,6 +519,7 @@ elseif(BSD) src/detection/displayserver/linux/xlib.c src/detection/font/font_linux.c src/detection/gpu/gpu_bsd.c + src/detection/gpu/gpu_pci.c src/detection/gtk_qt/gtk.c src/detection/host/host_bsd.c src/detection/lm/lm_linux.c @@ -1108,9 +1110,9 @@ install( set(CPACK_GENERATOR "TGZ;ZIP") if(APPLE) - string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_PROJECT_VERSION}-macos-universal" CPACK_PACKAGE_FILE_NAME) + string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-universal" CPACK_PACKAGE_FILE_NAME) else() # We don't use this in Windows - string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME) + string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME) endif() if(LINUX) diff --git a/README.md b/README.md index 41e5cddbf..38f8a7db5 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,13 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/ ### Linux * Debian / Ubuntu: Download `fastfetch--Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `dpkg -i fastfetch--Linux.deb` -* Arch Linux: `sudo pacman -S fastfetch` +* Arch Linux: `sudo pacman -S fastfetch`. You can also find fastfetch [on the AUR](https://aur.archlinux.org/packages/fastfetch-git). * Fedora: `sudo dnf install fastfetch` * Gentoo: `sudo emerge --ask app-misc/fastfetch` +* Alpine: `apk add --upgrade fastfetch` * NixOS: `sudo nix-shell -p fastfetch` * openSUSE: `sudo zypper install fastfetch` +* ALT Linux: `sudo apt-get install fastfetch` Replace sudo with doas depending on what you use. @@ -40,8 +42,14 @@ Replace sudo with doas depending on what you use. ### macOS +...via [HomeBrew](https://brew.sh): + `brew install fastfetch` +...via [MacPorts](https://www.macports.org): + +`sudo port install fastfetch` + ### Windows `scoop install fastfetch` diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index 7368d3039..3f65e1791 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -118,75 +118,3 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) return "GPU detection failed"; } - -#ifndef _WIN32 -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) -{ - if (content->length) - { - char buffer[32]; - uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", vendor); - char* start = (char*) memmem(content->chars, content->length, buffer, len); - char* end = content->chars + content->length; - if (start) - { - start += len; - end = memchr(start, '\n', (uint32_t) (end - start)); - if (!end) - end = content->chars + content->length; - if (!gpu->vendor.length) - ffStrbufSetNS(&gpu->vendor, (uint32_t) (end - start), start); - - start = end; // point to '\n' of vendor - end = start + 1; // point to start of devices - // find the start of next vendor - while (end[0] == '\t' || end[0] == '#') - { - end = strchr(end, '\n'); - if (!end) - { - end = content->chars + content->length; - break; - } - else - end++; - } - - len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", device); - start = memmem(start, (size_t) (end - start), buffer, len); - if (start) - { - start += len; - end = memchr(start, '\n', (uint32_t) (end - start)); - if (!end) - end = content->chars + content->length; - - char* openingBracket = memchr(start, '[', (uint32_t) (end - start)); - if (openingBracket) - { - openingBracket++; - char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket)); - if (closingBracket) - ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket); - } - if (!gpu->name.length) - ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start); - } - } - } - - if (!gpu->name.length) - { - const char* subclassStr; - switch (subclass) - { - case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break; - case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break; - case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break; - default: subclassStr = ""; break; - } - - ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr); - } -} -#endif diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index b3d6b035f..8f404f243 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -43,6 +43,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus); const char* ffGetGPUVendorString(unsigned vendorId); -#ifndef _WIN32 -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu); +#if defined(__linux__) || defined(__FreeBSD__) +void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, uint16_t subVendor, uint16_t subDevice, FFGPUResult* gpu); #endif diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index c51ef7ffb..ed0f7337d 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -1,9 +1,9 @@ #include "gpu_driver_specific.h" #include "common/io/io.h" +#include "common/properties.h" #include "3rdparty/nvml/nvml.h" #include "util/mallocHelper.h" -#include "common/io/io.h" #include #include @@ -46,7 +46,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) return "ioctl(fd, PCIOCGETCONF, &pc) returned error"; FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate(); - loadPciIds(&pciids); for (uint32_t i = 0; i < pcio.num_matches; ++i) { @@ -64,7 +63,19 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) gpu->deviceId = ((uint64_t) pc->pc_sel.pc_domain << 6) | ((uint64_t) pc->pc_sel.pc_bus << 4) | ((uint64_t) pc->pc_sel.pc_dev << 2) | pc->pc_sel.pc_func; gpu->frequency = FF_GPU_FREQUENCY_UNSET; - ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) + { + char query[32]; + snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) pc->pc_device, (unsigned) pc->pc_revid); + ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); + } + + if (gpu->name.length == 0) + { + if (pciids.length == 0) + loadPciIds(&pciids); + ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, pc->pc_subvendor, pc->pc_subdevice, gpu); + } #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 979e25d7c..c97660b9d 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -2,6 +2,7 @@ #include "detection/vulkan/vulkan.h" #include "detection/temps/temps_linux.h" #include "common/io/io.h" +#include "common/properties.h" #include "util/stringUtils.h" #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API @@ -80,7 +81,6 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus) FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate(); - loadPciIds(&pciids); struct dirent* entry; while((entry = readdir(dirp)) != NULL) @@ -98,9 +98,9 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus) continue; ffStrbufSubstrBefore(&pciDir, pciDevDirLength); - uint32_t vendorId, deviceId; + uint32_t vendorId, deviceId, subVendorId, subDeviceId; uint8_t classId, subclassId; - if (sscanf(buffer.chars, "pci:v%8" SCNx32 "d%8" SCNx32 "sv%*8ssd%*8sbc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &classId, &subclassId) != 4) + if (sscanf(buffer.chars, "pci:v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6) continue; if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) @@ -122,7 +122,29 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus) gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc; gpu->frequency = FF_GPU_FREQUENCY_UNSET; - ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) + { + ffStrbufAppendS(&pciDir, "/revision"); + if (ffReadFileBuffer(pciDir.chars, &buffer)) + { + char* pend; + uint64_t revision = strtoul(buffer.chars, &pend, 16); + if (pend != buffer.chars) + { + char query[32]; + snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision); + ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); + } + } + ffStrbufSubstrBefore(&pciDir, pciDevDirLength); + } + + if (gpu->name.length == 0) + { + if (!pciids.length) + loadPciIds(&pciids); + ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, (uint16_t) subVendorId, (uint16_t) subDeviceId, gpu); + } pciDetectDriver(gpu, &pciDir, &buffer); ffStrbufSubstrBefore(&pciDir, pciDevDirLength); diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c new file mode 100644 index 000000000..e8d454aec --- /dev/null +++ b/src/detection/gpu/gpu_pci.c @@ -0,0 +1,81 @@ +#include "gpu.h" + +void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, uint16_t subVendor, uint16_t subDevice, FFGPUResult* gpu) +{ + if (content->length) + { + char buffer[32]; + + // Search for vendor + uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", vendor); + char* start = (char*) memmem(content->chars, content->length, buffer, len); + char* end = content->chars + content->length; + if (start) + { + start += len; + end = memchr(start, '\n', (uint32_t) (end - start)); + if (!end) + end = content->chars + content->length; + if (!gpu->vendor.length) + ffStrbufSetNS(&gpu->vendor, (uint32_t) (end - start), start); + + start = end; // point to '\n' of vendor + end = start + 1; // point to start of devices + // find the start of next vendor + while (end[0] == '\t' || end[0] == '#') + { + end = strchr(end, '\n'); + if (!end) + { + end = content->chars + content->length; + break; + } + else + end++; + } + + // Search for device + len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", device); + start = memmem(start, (size_t) (end - start), buffer, len); + if (start) + { + start += len; + + // Search for subvendor and subdevice + len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t\t%04x %04x ", subVendor, subDevice); + char* subStart = memmem(start, (size_t) (end - start), buffer, len); + if (subStart) + start = subStart + len; + + end = memchr(start, '\n', (uint32_t) (end - start)); + if (!end) + end = content->chars + content->length; + + char* openingBracket = memchr(start, '[', (uint32_t) (end - start)); + if (openingBracket) + { + openingBracket++; + char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket)); + if (closingBracket) + ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket); + } + if (!gpu->name.length) + ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start); + } + } + } + + if (!gpu->name.length) + { + const char* subclassStr; + switch (subclass) + { + case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break; + case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break; + case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break; + default: subclassStr = ""; break; + } + + ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr); + } +} diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 255211a34..b57bb499d 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -7,6 +7,7 @@ #include #include #include +#include #ifdef __APPLE__ #include @@ -135,6 +136,9 @@ static void getDataDirs(FFPlatform* platform) ffPlatformPathAddHome(&platform->dataDirs, platform, ""); platformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); +#ifdef _PATH_LOCALBASE + ffPlatformPathAddAbsolute(&platform->dataDirs, _PATH_LOCALBASE "/share/"); +#endif ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/local/share/"); ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/share/"); }