Compare commits

...

46 Commits

Author SHA1 Message Date
Carter Li 469e21cce9 Merge pull request #1813 from fastfetch-cli/dev
Release: v2.46.0
2025-06-20 14:30:06 +08:00
李通洲 925e09c88a Doc: update changelog [ci skip] 2025-06-20 14:28:33 +08:00
李通洲 488454c1aa Logo (Builtin): simplify kali linux 2025-06-20 14:19:05 +08:00
李通洲 c67c52d606 Logo (Builtin): add Kalpa Desktop
Fix #1807
2025-06-20 14:18:21 +08:00
李通洲 e4e11ee509 Release: v2.46.0 2025-06-20 09:51:54 +08:00
李通洲 a3e2592555 Doc: update help.json 2025-06-20 09:51:40 +08:00
Carter Li e0e966dadf Logo (Builtin): rename hydra framework to hydrapwk
Fix #1812
2025-06-20 08:59:53 +08:00
李通洲 b079a8643b Chore: code cleanups 2025-06-19 22:41:30 +08:00
apocelipes 3291a9945f Global: add missing O_CLOEXEC to open() 2025-06-19 22:40:06 +08:00
李通洲 68fd21d0e4 GPU (Linux): fix an issue which vram_usage is bigger t han vram_visible 2025-06-19 22:00:48 +08:00
李通洲 0e1ef96992 GPU (Linux): detect shared vram usage of AMD GPU 2025-06-19 15:54:26 +08:00
李通洲 c377872438 GPU (Linux): correctly call radeon driver 2025-06-19 15:43:37 +08:00
李通洲 4f42d38e4d GPU (FreeBSD): fix mem leaks 2025-06-18 20:20:49 +08:00
李通洲 7b2243496b GPU (Windows): fix build 2025-06-18 18:53:29 +08:00
Carter Li 960a817d03 GPU (Linux): fix building without features 2025-06-18 18:37:30 +08:00
Carter Li 6917f9479e GPU (Linux / FreeBSD): add DRM detection support for old radeon driver
Ref: #1810
2025-06-18 16:41:02 +08:00
Carter Li 8559cc45eb GPU (Linux / FreeBSD): unifies DRM related code and code clean up 2025-06-18 10:01:32 +08:00
李通洲 40e33c676d GPU (FreeBSD): support detection by DRM [wip] 2025-06-17 20:58:09 +08:00
李通洲 d20371040e WM (FreeBSD): fix Hyprland version detection 2025-06-17 20:38:10 +08:00
李通洲 71faf1c7e3 GPU (macOS): detect Metal 4 support 2025-06-17 14:07:18 +08:00
李通洲 d182f3f743 OS (macOS): seems macOS 26 Beta 1 still reports itself as macOS 16. Honor it. 2025-06-17 14:01:22 +08:00
李通洲 39e009b945 CI: upgrade OpenBSD version 2025-06-17 09:30:14 +08:00
李通洲 a1873f3e9e CI: split amd64 and arm64 builds
So we can test both platforms in CI
2025-06-17 09:01:38 +08:00
李通洲 636bcaaaf9 Kmod: remove Chinese comments [ci skip] 2025-06-17 08:43:09 +08:00
李通洲 3fcbd80ef0 Board (macOS): detect board-id if available
Ref: https://github.com/GuillaumeGomez/sysinfo/pull/1545
2025-06-17 00:06:31 +08:00
李通洲 38887e7fbd Logo (Builtin): add GhostFreak
Fix #1801
2025-06-15 12:28:45 +08:00
AVSISP da958e11f9 Logo (Builtin): added AnushOS (#1806)
* Added AnushOS to builtin.c

Added AnushOS config to builtin.c

* Create anushos.txt

Added anushos.txt to ASCII logos

* Update builtin.c

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-06-15 12:23:27 +08:00
李通洲 c2ed71c4eb Global: set SetErrorMode(SEM_FAILCRITICALERRORS) globally
Fix #1805
2025-06-15 00:00:22 +08:00
ᡥᠠᡳᡤᡳᠶᠠ ᡥᠠᠯᠠ·ᠨᡝᡴᠣ 猫 2e1ddcf9f8 Logo (Builtin): Add HarmonyOS support (#1804)
* Logo (Builtin): add HarmonyOS

* OS (HarmonyOS): detect HarmonyOS

* Update src/detection/os/os_linux.c

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update os_linux.c

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-14 09:03:57 +08:00
Carter Li f1cc2d124c Packages (OpenBSD): fix counting by ignoring hidden folders 2025-06-13 20:38:51 +08:00
Techflash 1e32a95f83 CPU (NetBSD): properly support PowerPC (#1802)
Some devices store their CPU name in hw.model, so check that as well
before giving up.  Tested on NetBSD 10.1 evbppc/wii, and allows it to
detect the CPU as "750 (Revision 2.0)".

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-06-11 00:15:40 -05:00
CopticFelo 9e959bc57f WM (MacOS): Added Aerospace WM detection 2025-06-10 11:22:31 +08:00
李通洲 e68406ee22 DE (macOS): report Liquid Glass on macOS 26+ 2025-06-10 10:56:13 +08:00
李通洲 ba69e316b2 OS (MacOS): add macOS 26 Tahoe 2025-06-10 10:48:35 +08:00
李通洲 f3e8e8af52 Logo (Builtin): detect and add TrueNAS Scale 2025-06-10 10:22:13 +08:00
李通洲 c9adab3892 OS (Linux): detect Raspberry Pi OS
Fix #1773
2025-06-10 09:55:13 +08:00
李通洲 c8d1d29017 Disk (Linux): hide /boot/firmware by default 2025-06-10 09:54:11 +08:00
Carter Li 541acca7c0 Logo (Builtin): add xenia_old; update colors of xenia
#1797
2025-06-10 09:13:21 +08:00
Derek Passen ddf5099461 TerminalFont: support rio terminal emulator (#1789)
* Enable terminal font detection for rio terminal emulator

https://rioterm.com
https://rioterm.com/docs/config
https://rioterm.com/docs/config#fonts

* Update src/detection/terminalfont/terminalfont.c

Fix default rio font name

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-06-08 00:00:03 +08:00
李通洲 781a692b06 JsonSchema: document swap.separate 2025-06-07 19:23:25 +08:00
李通洲 9c37f1b370 CPU (Windows): use perflib.h instead of pdh.h for querying CPU temp
Fix #1787
2025-06-07 19:17:46 +08:00
Carter Li a66c26f4df Logo (Builtin): improve colors of bedrock_small
Fix #1790
2025-06-07 17:39:45 +08:00
Carter Li 3bd750bedf Host (Linux): detect Linux Binary Compatibility on FreeBSD
Fix #1786
2025-06-06 15:38:46 +08:00
Carter Li 4a1ada604c Host (Linux): more detailed info of WSL 2025-06-06 14:49:32 +08:00
Noah Michaels e5f57a34a2 Logo (Builtin): Add Fedora2_small (#1785)
* Add 1 more small Fedora logo

* Update builtin.c

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-06-05 20:12:44 -05:00
Carter Li 20a3737dce Packaging: update debian stuff [ci skip] 2025-06-05 10:59:16 +08:00
56 changed files with 1347 additions and 486 deletions
+55 -7
View File
@@ -408,9 +408,9 @@ jobs:
name: fastfetch-musl-amd64
path: ./fastfetch-*.*
macos-universal:
name: macOS-universal
runs-on: macos-latest
macos-amd64:
name: macOS-amd64
runs-on: macos-13
permissions:
security-events: write
contents: read
@@ -426,7 +426,7 @@ jobs:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --target package --verbose -j4
@@ -452,7 +452,54 @@ jobs:
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-macos-universal
name: fastfetch-macos-amd64
path: ./fastfetch-*.*
macos-aarch64:
name: macOS-aarch64
runs-on: macos-latest
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: uname -a
run: uname -a
- name: install required packages
run: |
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --target package --verbose -j4
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: otool -L fastfetch
- name: run tests
run: ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-macos-aarch64
path: ./fastfetch-*.*
sunos-amd64:
@@ -542,7 +589,7 @@ jobs:
architecture: x86-64
cpu_count: 4
shell: bash
version: '7.6'
version: '7.7'
run: |
uname -a
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa
@@ -808,7 +855,8 @@ jobs:
- linux-ppc64le
- linux-s390x
- musl-amd64
- macos-universal
- macos-amd64
- macos-aarch64
- freebsd-amd64
- openbsd-amd64
- netbsd-amd64
+38
View File
@@ -1,3 +1,41 @@
# 2.46.0
Features:
* Support Rio terminal font detection (#1789, TerminalFont, Linux)
* Support GPU detection by DRM on FreeBSD (GPU, FreeBSD)
* Enable by `--gpu-detection-method auto`
* Require proper DRM drivers installed and loaded
* Support PowerPC CPU detection on NetBSD (#1802, CPU, NetBSD)
* Support Aerospace WM detection (#1796, WM, macOS)
* Improve Raspberry Pi OS for RPI5 detection (#1773, OS, Linux)
* Support Linux Binary Compatibility detection on FreeBSD (#1786, Host, Linux)
* Use `board-id` as board name if available (Board, macOS)
* Intel only
* Support shared VRAM usage detection for AMD GPUs (GPU, Linux)
* Use `perflib.h` instead of `pdh.h` for CPU temperature querying to get rid of pdh.dll (#1787, CPU, Windows)
* Support GPU info detection for old ATI radeon driver (#1810, GPU, Linux)
* Add macOS 26 Tahoe support (macOS)
* Report macOS 26 code name (OS)
* Report Liquid Glass DE on macOS 26+ (DE)
* Detect Metal 4 support (GPU)
Bugfixes:
* Fix packages counting by ignoring hidden folders (Packages, OpenBSD)
* Fix Hyprland version detection (WM, FreeBSD)
* Don't show `Please insert a disk into drive D:` error dialogs (#1805, Disk, Windows)
* Hide `/boot/firmware` by default (Disk, Linux)
Logos:
* Rename Hydra Framework to HydraPwk (#1812)
* Add AnushOS (#1806)
* Add HarmonyOS (#1804)
* Add GhostFreak (#1801)
* Add TrueNAS Scale (#1795)
* Add Fedora2_small (#1785)
* Add xenia_old; update colors of xenia (#1797)
* Improve colors of bedrock_small (#1790)
* Add Kalpa Desktop (#1807)
# 2.45.0
Features:
+14 -13
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.45.0
VERSION 2.46.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -61,7 +61,7 @@ cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeB
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX OR FreeBSD" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR Haiku" OFF)
@@ -529,6 +529,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_drm.c
src/detection/gpu/gpu_pci.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_linux.c
@@ -676,6 +677,7 @@ elseif(FreeBSD)
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_bsd.c
src/detection/gpu/gpu_drm.c
src/detection/gpu/gpu_pci.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_bsd.c
@@ -1593,7 +1595,6 @@ elseif(WIN32)
PRIVATE "winbrand"
PRIVATE "propsys"
PRIVATE "secur32"
PRIVATE "pdh"
)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
# WoA only works on Windows 10 or higher
@@ -1925,17 +1926,17 @@ install(
##################
set(CPACK_GENERATOR "TGZ;ZIP")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
set(CMAKE_SYSTEM_PROCESSOR "amd64")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(CMAKE_SYSTEM_PROCESSOR "aarch64")
endif()
if(APPLE)
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-universal" CPACK_PACKAGE_FILE_NAME)
else() # We don't use this in Windows
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
set(CMAKE_SYSTEM_PROCESSOR "amd64")
endif()
if(IS_MUSL)
string(TOLOWER "${CMAKE_PROJECT_NAME}-musl-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
else()
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
endif()
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME) # use macos instead of darwin
elseif(IS_MUSL)
string(TOLOWER "${CMAKE_PROJECT_NAME}-musl-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
else()
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
endif()
if(LINUX)
+6
View File
@@ -1,3 +1,9 @@
fastfetch (2.45.0) jammy; urgency=medium
* Update to 2.45.0
-- Carter Li <zhangsongcui@live.cn> Thu, 05 Jun 2025 10:56:38 +0800
fastfetch (2.44.0) jammy; urgency=medium
* Update to 2.44.0
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.44.0_source.buildinfo universe/utils optional
fastfetch_2.45.0_source.buildinfo universe/utils optional
+5
View File
@@ -3002,6 +3002,11 @@
"const": "swap",
"description": "Print swap (paging file) space usage"
},
"separate": {
"type": "boolean",
"description": "Set if detailed swap devices should be reported on separate lines instead of a summary",
"default": false
},
"percent": {
"$ref": "#/$defs/percent"
},
+4 -1
View File
@@ -52,7 +52,10 @@
},
"memory",
"physicalmemory",
"swap",
{
"type": "swap",
"separate": true
},
"disk",
"btrfs",
"zpool",
+4 -1
View File
@@ -54,7 +54,10 @@
},
"memory",
"physicalmemory",
"swap",
{
"type": "swap",
"separate": true
},
"disk",
"btrfs",
"zpool",
+1
View File
@@ -105,6 +105,7 @@ void ffStart(void)
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc;
#ifdef _WIN32
SetErrorMode(SEM_FAILCRITICALERRORS);
if (instance.config.display.noBuffer)
setvbuf(stdout, NULL, _IONBF, 0);
else
+1 -1
View File
@@ -290,7 +290,7 @@ bool ffSuppressIO(bool suppress)
void listFilesRecursively(uint32_t baseLength, FFstrbuf* folder, uint8_t indentation, const char* folderName, bool pretty)
{
FF_AUTO_CLOSE_FD int dfd = open(folder->chars, O_RDONLY);
FF_AUTO_CLOSE_FD int dfd = open(folder->chars, O_RDONLY | O_CLOEXEC);
if (dfd < 0)
return;
+2 -2
View File
@@ -1144,11 +1144,11 @@
"arg": {
"type": "enum",
"enum": {
"auto": "Query platform-specific graphics APIs. Requires proper GPU drivers to be installed. Not supported on BSDs",
"auto": "Query platform-specific graphics APIs. Requires proper GPU drivers to be installed. Supported on Linux, FreeBSD, Windows and macOS",
"pci": "Search PCI devices, which does not require GPU drivers to be installed. Not supported on Windows and macOS",
"vulkan": "Use Vulkan API. Slow and requires proper Vulkan drivers to be installed. Used for Android",
"opencl": "Use OpenCL API. Slow and requires proper OpenCL drivers to be installed",
"opengl": "Use OpenGL API. Slow and only detects one GPU"
"opengl": "Use OpenGL API. Slow and only detects one GPU. Used for OpenBSD"
},
"default": "auto"
}
+2 -2
View File
@@ -16,8 +16,8 @@
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
prop_dictionary_t root = NULL;
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
+2 -2
View File
@@ -8,9 +8,9 @@
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* result)
{
FF_AUTO_CLOSE_FD int devfd = open("/dev/apm", O_RDONLY);
FF_AUTO_CLOSE_FD int devfd = open("/dev/apm", O_RDONLY | O_CLOEXEC);
if (devfd < 0) return "open(dev/apm, O_RDONLY) failed";
if (devfd < 0) return "open(dev/apm, O_RDONLY | O_CLOEXEC) failed";
struct apm_power_info info = {};
+13 -3
View File
@@ -9,9 +9,19 @@ const char* ffDetectBoard(FFBoardResult* result)
if (!service)
return "No IOPlatformExpertDevice found";
io_name_t name;
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
ffStrbufSetS(&result->name, name);
FF_CFTYPE_AUTO_RELEASE CFTypeRef boardId = IORegistryEntryCreateCFProperty(service, CFSTR("board-id"), kCFAllocatorDefault, kNilOptions);
if (boardId)
ffCfStrGetString(boardId, &result->name);
else
{
io_name_t name;
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
ffStrbufSetS(&result->name, name);
}
FF_CFTYPE_AUTO_RELEASE CFStringRef version = IORegistryEntryCreateCFProperty(service, CFSTR("version"), kCFAllocatorDefault, kNilOptions);
if (version)
ffCfStrGetString(version, &result->version);
FF_CFTYPE_AUTO_RELEASE CFTypeRef manufacturer = IORegistryEntryCreateCFProperty(service, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
if (manufacturer)
+1 -1
View File
@@ -20,7 +20,7 @@
const char* ffDetectBootmgr(FFBootmgrResult* result)
{
FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR);
FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR | O_CLOEXEC);
if (efifd < 0) return "open(/dev/efi) failed";
uint8_t buffer[2048];
+1 -1
View File
@@ -12,7 +12,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
for (char i = '0'; i <= '9'; ++i) {
path[strlen("/dev/ttyC")] = i;
FF_AUTO_CLOSE_FD int devfd = open(path, O_RDONLY);
FF_AUTO_CLOSE_FD int devfd = open(path, O_RDONLY | O_CLOEXEC);
if (devfd < 0) {
if (errno == EACCES && i == '0')
+1 -1
View File
@@ -20,7 +20,7 @@ const char* ffDetectCamera(FFlist* result)
for (uint32_t i = 0; i <= 9; ++i)
{
path[ARRAY_SIZE(path) - 2] = (char) (i + '0');
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0)
{
if (errno == ENOENT)
+1 -1
View File
@@ -474,7 +474,7 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC
static const char* detectPhysicalCores(FFCPUResult* cpu)
{
int dfd = open("/sys/devices/system/cpu/", O_RDONLY | O_DIRECTORY);
int dfd = open("/sys/devices/system/cpu/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (dfd < 0) return "open(\"/sys/devices/system/cpu/\") failed";
FF_AUTO_CLOSE_DIR DIR* dir = fdopendir(dfd);
+4 -3
View File
@@ -18,8 +18,8 @@ static void freePropDict(prop_dictionary_t* pdict)
static const char* detectCpuTemp(double* current)
{
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
__attribute__((__cleanup__(freePropDict))) prop_dictionary_t root = NULL;
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
@@ -51,7 +51,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
if (ffSysctlGetString("machdep.cpu_brand", &cpu->name) != NULL &&
ffSysctlGetString("machdep.dmi.processor-version", &cpu->name) != NULL &&
ffSysctlGetString("hw.cpu0.name", &cpu->name) != NULL)
ffSysctlGetString("hw.cpu0.name", &cpu->name) != NULL &&
ffSysctlGetString("hw.model", &cpu->name) != NULL)
{
ffStrbufSetS(&cpu->name, "Unknown CPU");
}
+97 -23
View File
@@ -4,42 +4,116 @@
#include "util/mallocHelper.h"
#include "util/smbiosHelper.h"
#include <pdh.h>
#include <windows.h>
#include "perflib_.h"
#include <wchar.h>
static void ffPdhOpenCloseQuery(HQUERY* query)
static inline void ffPerfCloseQueryHandle(HANDLE* phQuery)
{
assert(query);
if (*query)
if (*phQuery != NULL)
{
PdhCloseQuery(*query);
*query = NULL;
PerfCloseQueryHandle(*phQuery);
*phQuery = NULL;
}
}
static const char* detectThermalTemp(double* result)
const char* detectThermalTemp(double* result)
{
// typeperf.exe -sc 1 "\Thermal Zone Information(*)\Temperature"
struct FFPerfQuerySpec
{
PERF_COUNTER_IDENTIFIER Identifier;
WCHAR Name[16];
} querySpec = {
.Identifier = {
// Thermal Zone Information
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{383487a6-3676-4870-a4e7-d45b30c35629}\{52bc5412-dac2-449c-8bc2-96443888fe6b}
.CounterSetGuid = { 0x52bc5412, 0xdac2, 0x449c, {0x8b, 0xc2, 0x96, 0x44, 0x38, 0x88, 0xfe, 0x6b} },
.Size = sizeof(querySpec),
.CounterId = PERF_WILDCARD_COUNTER,
.InstanceId = PERF_WILDCARD_COUNTER,
},
.Name = L"\\_TZ.CPUZ", // The standard(?) instance name for CPU temperature in the thermal provider
};
__attribute__((__cleanup__(ffPdhOpenCloseQuery))) HQUERY query = NULL;
DWORD dataSize = 0;
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
return "PerfEnumerateCounterSetInstances() failed";
if (PdhOpenQueryW(NULL, 0, &query) != ERROR_SUCCESS)
return "Failed to open PDH query";
if (dataSize <= sizeof(PERF_INSTANCE_HEADER))
return "No `Thermal Zone Information` instances found";
HCOUNTER counter = NULL;
if (PdhAddEnglishCounterW(query,
L"\\Thermal Zone Information(*)\\Temperature",
0,
&counter) != ERROR_SUCCESS)
return "Failed to add TZI temperature counter";
{
FF_AUTO_FREE PERF_INSTANCE_HEADER* const pHead = malloc(dataSize);
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, pHead, dataSize, &dataSize) != ERROR_SUCCESS)
return "PerfEnumerateCounterSetInstances() failed to get instance headers";
if (PdhCollectQueryData(query) != ERROR_SUCCESS)
return "Failed to collect query data";
PERF_INSTANCE_HEADER* pInstanceHeader = pHead;
while (1)
{
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pInstanceHeader + sizeof(*pInstanceHeader));
if (wcscmp(instanceName, querySpec.Name) == 0)
break;
PDH_FMT_COUNTERVALUE value;
if (PdhGetFormattedCounterValue(counter, PDH_FMT_DOUBLE, NULL, &value) != ERROR_SUCCESS)
return "Failed to format counter value";
dataSize -= pInstanceHeader->Size;
if (dataSize == 0)
break;
pInstanceHeader = (PERF_INSTANCE_HEADER*)((BYTE*)pInstanceHeader + pInstanceHeader->Size);
}
*result = value.doubleValue - 273;
if (dataSize == 0)
{
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pHead + sizeof(*pHead));
wcscpy(querySpec.Name, instanceName); // Use the first instance name if the specific one is not found
}
}
__attribute__((__cleanup__(ffPerfCloseQueryHandle)))
HANDLE hQuery = NULL;
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS)
return "PerfOpenQueryHandle() failed";
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS)
return "PerfAddCounters() failed";
if (querySpec.Identifier.Status != ERROR_SUCCESS)
return "PerfAddCounters() reports invalid identifier";
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
return "PerfQueryCounterData(NULL) failed";
if (dataSize <= sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER)) // PERF_ERROR_RETURN, should not happen
return "instance doesn't exist";
FF_AUTO_FREE PERF_DATA_HEADER* const pDataHeader = malloc(dataSize);
if (PerfQueryCounterData(hQuery, pDataHeader, dataSize, &dataSize) != ERROR_SUCCESS)
return "PerfQueryCounterData(pDataHeader) failed";
PERF_COUNTER_HEADER* pCounterHeader = (PERF_COUNTER_HEADER*)(pDataHeader + 1);
if (pCounterHeader->dwType != PERF_MULTIPLE_COUNTERS)
return "Invalid counter type";
PERF_MULTI_COUNTERS* pMultiCounters = (PERF_MULTI_COUNTERS*)(pCounterHeader + 1);
PERF_COUNTER_DATA* pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pMultiCounters + pMultiCounters->dwSize);
for (ULONG iCounter = 0; iCounter != pMultiCounters->dwCounters; iCounter++)
{
if (pCounterData->dwDataSize == sizeof(int32_t))
{
DWORD* pCounterIds = (DWORD*)(pMultiCounters + 1);
switch (pCounterIds[iCounter]) {
case 0: // Temperature
*result = *(int32_t*)(pCounterData + 1) - 273;
break;
case 3: // High Precision Temperature
*result = *(int32_t*)(pCounterData + 1) / 10.0 - 273;
break;
}
}
pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pCounterData + pCounterData->dwSize);
}
return NULL;
}
+133
View File
@@ -0,0 +1,133 @@
#pragma once
#include <windows.h>
#include <perflib.h>
// Missing from <perflib.h> of MinGW-w64 SDK
#define PERF_WILDCARD_COUNTER 0xFFFFFFFF
#define PERF_WILDCARD_INSTANCE L"*"
#define PERF_AGGREGATE_INSTANCE L"_Total"
#define PERF_MAX_INSTANCE_NAME 1024
typedef struct _PERF_INSTANCE_HEADER {
ULONG Size; // = sizeof(PERF_INSTANCE_HEADER) + sizeof(InstanceName) + sizeof(Padding)
ULONG InstanceId; // Instance ID.
// Followed by:
// WCHAR InstanceName[]; // Nul-terminated.
// WCHAR Padding[]; // Pad to a multiple of 8 bytes
} PERF_INSTANCE_HEADER, *PPERF_INSTANCE_HEADER;
typedef struct _PERF_COUNTER_IDENTIFIER {
GUID CounterSetGuid; // The GUID of the counterset.
ULONG Status; // Win32 error code indicating success/failure of the add/delete operation.
ULONG Size; // sizeof(PERF_COUNTER_IDENTIFIER) + sizeof(InstanceName) + sizeof(Padding)
ULONG CounterId; // CounterId, or PERF_WILDCARD_COUNTER for all counters.
ULONG InstanceId; // InstanceId, or 0xFFFFFFFF to not filter on instance ID.
ULONG Index; // Set by PerfQueryCounterInfo to the position in which the corresponding counter data is returned.
ULONG Reserved; // Reserved.
// Followed by:
// WCHAR InstanceName[];
// WCHAR Padding[];
} PERF_COUNTER_IDENTIFIER, * PPERF_COUNTER_IDENTIFIER;
typedef struct _PERF_DATA_HEADER {
ULONG dwTotalSize; // = sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER blocks...)
ULONG dwNumCounters; // The number of PERF_COUNTER_HEADER blocks.
LONGLONG PerfTimeStamp; // Timestamp from a high-resolution clock.
LONGLONG PerfTime100NSec; // The number of 100 nanosecond intervals since January 1, 1601, in Coordinated Universal Time (UTC).
LONGLONG PerfFreq; // The frequency of a high-resolution clock.
SYSTEMTIME SystemTime; // The time at which data is collected on the provider side.
// Followed by:
// PERF_COUNTER_HEADER blocks...;
} PERF_DATA_HEADER, * PPERF_DATA_HEADER;
typedef enum _PerfCounterDataType {
PERF_ERROR_RETURN = 0, /* An error occurred when the performance counter value was queried. */
PERF_SINGLE_COUNTER = 1, /* Query returned a single counter from a single-instance. */
PERF_MULTIPLE_COUNTERS = 2, /* Query returned multiple counters from a single instance. */
PERF_MULTIPLE_INSTANCES = 4, /* Query returned a single counter from each of multiple instances. */
PERF_COUNTERSET = 6 /* Query returned multiple counters from each of multiple instances. */
} PerfCounterDataType;
typedef struct _PERF_COUNTER_HEADER {
ULONG dwStatus; // Win32 error code indicating success/failure of the query operation.
PerfCounterDataType dwType; // Result type - error, single/single, multi/single, single/multi, multi/multi.
ULONG dwSize; // = sizeof(PERF_COUNTER_HEADER) + sizeof(Additional data)
ULONG Reserved; // Reserved.
// Followed by additional data:
// If dwType == PERF_ERROR_RETURN: nothing.
// If dwType == PERF_SINGLE_COUNTER: PERF_COUNTER_DATA block.
// If dwType == PERF_MULTIPLE_COUNTERS: PERF_MULTI_COUNTERS block + PERF_COUNTER_DATA blocks.
// If dwType == PERF_MULTIPLE_INSTANCES: PERF_MULTI_INSTANCES block.
// If dwType == PERF_COUNTERSET: PERF_MULTI_COUNTERS block + PERF_MULTI_INSTANCES block.
} PERF_COUNTER_HEADER, * PPERF_COUNTER_HEADER;
typedef struct _PERF_MULTI_COUNTERS {
ULONG dwSize; // sizeof(PERF_MULTI_COUNTERS) + sizeof(CounterIds)
ULONG dwCounters; // Number of counter ids.
// Followed by:
// DWORD CounterIds[dwCounters];
} PERF_MULTI_COUNTERS, * PPERF_MULTI_COUNTERS;
typedef struct _PERF_COUNTER_DATA {
ULONG dwDataSize; // Size of the counter data, in bytes.
ULONG dwSize; // = sizeof(PERF_COUNTER_DATA) + sizeof(Data) + sizeof(Padding)
// Followed by:
// BYTE Data[dwDataSize];
// BYTE Padding[];
} PERF_COUNTER_DATA, * PPERF_COUNTER_DATA;
_Success_(return == ERROR_SUCCESS)
ULONG
WINAPI
PerfEnumerateCounterSetInstances(
_In_opt_z_ LPCWSTR szMachine,
_In_ LPCGUID pCounterSetId,
_Out_opt_bytecap_post_bytecount_(cbInstances, *pcbInstancesActual) PPERF_INSTANCE_HEADER pInstances,
DWORD cbInstances,
_Out_ LPDWORD pcbInstancesActual
);
_Success_(return == ERROR_SUCCESS)
ULONG
WINAPI
PerfOpenQueryHandle(
_In_opt_z_ LPCWSTR szMachine,
_Out_ HANDLE * phQuery
);
_Success_(return == ERROR_SUCCESS)
ULONG
WINAPI
PerfCloseQueryHandle(
_In_ HANDLE hQuery
);
_Success_(return == ERROR_SUCCESS)
ULONG
WINAPI
PerfAddCounters(
_In_ HANDLE hQuery,
_Inout_bytecount_(cbCounters) PPERF_COUNTER_IDENTIFIER pCounters,
DWORD cbCounters
);
_Success_(return == ERROR_SUCCESS)
ULONG
WINAPI
PerfDeleteCounters(
_In_ HANDLE hQuery,
_Inout_bytecount_(cbCounters) PPERF_COUNTER_IDENTIFIER pCounters,
DWORD cbCounters
);
_Success_(return == ERROR_SUCCESS)
ULONG
WINAPI
PerfQueryCounterData(
_In_ HANDLE hQuery,
_Out_opt_bytecap_post_bytecount_(cbCounterBlock, *pcbCounterBlockActual) PPERF_DATA_HEADER pCounterBlock,
DWORD cbCounterBlock,
_Out_ LPDWORD pcbCounterBlockActual
);
-4
View File
@@ -99,9 +99,6 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
//https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#remarks
UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
DWORD diskFlags;
BOOL result = GetVolumeInformationW(mountpoint,
diskName, ARRAY_SIZE(diskName), //Volume name
@@ -110,7 +107,6 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
&diskFlags, //File system flags
diskFileSystem, ARRAY_SIZE(diskFileSystem)
);
SetErrorMode(errorMode);
if(result)
{
@@ -2,6 +2,7 @@
#include "util/apple/cf_helpers.h"
#include "util/stringUtils.h"
#include "util/edidHelper.h"
#include "detection/os/os.h"
#include <stdlib.h>
#include <string.h>
@@ -194,7 +195,22 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
ffStrbufSetStatic(&ds->wmPrettyName, "Quartz Compositor");
}
}
ffStrbufSetStatic(&ds->dePrettyName, "Aqua");
const FFOSResult* os = ffDetectOS();
char* str_end;
const char* version = os->version.chars;
unsigned long osNum = strtoul(version, &str_end, 10);
if (str_end != version)
{
if (osNum > 15) { // Tahoe
ffStrbufSetStatic(&ds->dePrettyName, "Liquid Glass");
} else if (osNum < 10) {
ffStrbufSetStatic(&ds->dePrettyName, "Platinum");
} else {
ffStrbufSetStatic(&ds->dePrettyName, "Aqua");
}
}
detectDisplays(ds);
}
+19 -1
View File
@@ -49,7 +49,25 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
const char* ffGPUGetVendorString(unsigned vendorId);
typedef struct FFGpuDriverPciBusId
{
uint32_t domain;
uint32_t bus;
uint32_t device;
uint32_t func;
} FFGpuDriverPciBusId;
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu);
#endif
#if FF_HAVE_DRM
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd);
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd);
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd);
#endif // FF_HAVE_DRM
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId);
#endif // defined(XXX)
+6 -1
View File
@@ -3,6 +3,9 @@
#import <Metal/MTLDevice.h>
#import <IOKit/kext/KextManager.h>
#ifndef MAC_OS_VERSION_26_0
#define MTLGPUFamilyMetal4 ((MTLGPUFamily) 5002)
#endif
#ifndef MAC_OS_VERSION_13_0
#define MTLGPUFamilyMetal3 ((MTLGPUFamily) 5001)
#endif
@@ -57,7 +60,9 @@ const char* ffGpuDetectMetal(FFlist* gpus)
else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1])
ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1");
#else // MAC_OS_X_VERSION_10_15
if ([device supportsFamily:MTLGPUFamilyMetal3])
if ([device supportsFamily:MTLGPUFamilyMetal4])
ffStrbufSetStatic(&gpu->platformApi, "Metal 4");
else if ([device supportsFamily:MTLGPUFamilyMetal3])
ffStrbufSetStatic(&gpu->platformApi, "Metal 3");
else if ([device supportsFamily:MTLGPUFamilyCommon3])
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3");
+156 -44
View File
@@ -1,6 +1,7 @@
#include "gpu_driver_specific.h"
#include "common/io/io.h"
#include "util/mallocHelper.h"
#include <sys/pciio.h>
#include <fcntl.h>
@@ -10,11 +11,145 @@
#include <bus/pci/pcireg.h> // DragonFly
#endif
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
static void fillGPUTypeGeneric(FFGPUResult* gpu)
{
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY, 0);
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
// 0000:00:02.0 is reserved for Intel integrated graphics
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
}
}
}
#if FF_HAVE_DRM
#include "common/library.h"
#include "util/stringUtils.h"
#include <xf86drm.h>
static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
{
FF_LIBRARY_LOAD(libdrm, "dlopen libdrm" FF_LIBRARY_EXTENSION " failed", "libdrm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
drmDevicePtr devices[64];
int nDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
if (nDevices < 0)
return "drmGetDevices() failed";
for (int iDev = 0; iDev < nDevices; ++iDev)
{
drmDevice* dev = devices[iDev];
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY)))
continue;
const char* path = dev->nodes[DRM_NODE_PRIMARY];
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInitS(&gpu->platformApi, path);
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
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 = 0;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
switch (dev->bustype)
{
case DRM_BUS_PCI:
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id));
gpu->deviceId = (dev->businfo.pci->domain * 100000ull) + (dev->businfo.pci->bus * 1000ull) + (dev->businfo.pci->dev * 10ull) + dev->businfo.pci->func;
break;
case DRM_BUS_HOST1X:
ffStrbufSetS(&gpu->name, dev->deviceinfo.host1x->compatible[0]);
gpu->type = FF_GPU_TYPE_INTEGRATED;
break;
case DRM_BUS_PLATFORM:
ffStrbufSetS(&gpu->name, dev->deviceinfo.platform->compatible[0]);
gpu->type = FF_GPU_TYPE_INTEGRATED;
break;
case DRM_BUS_USB:
ffStrbufSetF(&gpu->name, "USB Device (%u-%u)", dev->deviceinfo.usb->vendor, dev->deviceinfo.usb->product);
gpu->type = FF_GPU_TYPE_DISCRETE;
break;
}
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) continue;
char driverName[64];
driverName[0] = '\0';
struct drm_version ver = {
.name = driverName,
.name_len = ARRAY_SIZE(driverName),
};
if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0)
ffStrbufSetF(&gpu->driver, "%*s %d.%d.%d", (int) ver.name_len, ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel);
if (ffStrStartsWith(driverName, "i915"))
ffDrmDetectI915(gpu, fd);
else if (ffStrStartsWith(driverName, "amdgpu"))
ffDrmDetectAmdgpu(options, gpu, dev->nodes[DRM_NODE_RENDER]);
else if (ffStrStartsWith(driverName, "radeon"))
ffDrmDetectRadeon(options, gpu, dev->nodes[DRM_NODE_RENDER]);
else if (ffStrStartsWith(driverName, "xe"))
ffDrmDetectXe(gpu, fd);
else if (ffStrStartsWith(driverName, "asahi"))
ffDrmDetectAsahi(gpu, fd);
else if (dev->bustype == DRM_BUS_PCI)
{
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
.domain = (uint32_t) dev->businfo.pci->domain,
.bus = dev->businfo.pci->bus,
.device = dev->businfo.pci->dev,
.func = dev->businfo.pci->func,
});
}
if (gpu->name.length == 0)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
ffGPUQueryAmdGpuName(dev->deviceinfo.pci->device_id, dev->deviceinfo.pci->revision_id, gpu);
if (gpu->name.length == 0)
ffGPUFillVendorAndName(0, dev->deviceinfo.pci->vendor_id, dev->deviceinfo.pci->device_id, gpu);
}
fillGPUTypeGeneric(gpu);
}
ffdrmFreeDevices(devices, nDevices);
return NULL;
}
#endif
static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
{
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY | O_CLOEXEC);
if (fd < 0)
return "open(\"/dev/pci\", O_RDONLY, 0) failed";
return "open(\"/dev/pci\", O_RDONLY | O_CLOEXEC, 0) failed";
struct pci_conf confs[128];
struct pci_match_conf match = {
@@ -54,27 +189,12 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
gpu->deviceId = (pc->pc_sel.pc_domain * 100000ull) + (pc->pc_sel.pc_bus * 1000ull) + (pc->pc_sel.pc_dev * 10ull) + pc->pc_sel.pc_func;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
{
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = {
.domain = (uint32_t) pc->pc_sel.pc_domain,
.bus = pc->pc_sel.pc_bus,
.device = pc->pc_sel.pc_dev,
.func = pc->pc_sel.pc_func,
},
}, (FFGpuDriverResult) {
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.type = &gpu->type,
.frequency = &gpu->frequency,
.coreUsage = &gpu->coreUsage,
.name = &gpu->name,
}, "libnvidia-ml.so");
}
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
.domain = (uint32_t) pc->pc_sel.pc_domain,
.bus = pc->pc_sel.pc_bus,
.device = pc->pc_sel.pc_dev,
.func = pc->pc_sel.pc_func,
});
if (gpu->name.length == 0)
{
@@ -84,27 +204,19 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
}
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
// 0000:00:02.0 is reserved for Intel integrated graphics
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
}
}
fillGPUTypeGeneric(gpu);
}
return NULL;
}
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO)
{
detectByDrm(options, gpus);
if (gpus->length > 0) return NULL;
}
return detectByPci(options, gpus);
}
-8
View File
@@ -10,14 +10,6 @@ typedef enum __attribute__((__packed__)) FFGpuDriverConditionType
FF_GPU_DRIVER_CONDITION_TYPE_FORCE_UNSIGNED = UINT8_MAX,
} FFGpuDriverConditionType;
typedef struct FFGpuDriverPciBusId
{
uint32_t domain;
uint32_t bus;
uint32_t device;
uint32_t func;
} FFGpuDriverPciBusId;
typedef struct FFGpuDriverPciDeviceId
{
uint32_t deviceId;
+372
View File
@@ -0,0 +1,372 @@
#include "gpu.h"
#if FF_HAVE_DRM
#include <drm.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "common/io/io.h"
#include "common/library.h"
#include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include "intel_drm.h"
#include "asahi_drm.h"
#include <radeon_drm.h>
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath)
{
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "Failed to open DRM render device";
uint32_t value;
// https://github.com/torvalds/linux/blob/fb4d33ab452ea254e2c319bac5703d1b56d895bf/drivers/gpu/drm/radeon/radeon_kms.c#L231
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_ACTIVE_CU_COUNT,
.value = (uintptr_t) &value,
}) >= 0)
gpu->coreCount = (int32_t) value;
if (options->temp)
{
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_CURRENT_GPU_TEMP, // millidegrees C
.value = (uintptr_t) &value,
}) >= 0 && value != 0) // 0 means unavailable
gpu->temperature = (double) value / 1000.0;
}
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_MAX_SCLK, // MHz
.value = (uintptr_t) &value,
}) >= 0)
gpu->frequency = (uint32_t) (value / 1000u);
if (options->driverSpecific)
{
struct drm_radeon_gem_info gemInfo;
if (ioctl(fd, DRM_IOCTL_RADEON_GEM_INFO, &gemInfo) >= 0)
{
// vram_usage can be bigger than vram_usage, so we use vram_size here
gpu->dedicated.total = gemInfo.vram_size;
gpu->shared.total = gemInfo.gart_size;
uint64_t memSize;
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_VRAM_USAGE, // uint64_t
.value = (uintptr_t) &memSize,
}) >= 0)
gpu->dedicated.used = memSize;
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_GTT_USAGE, // uint64_t
.value = (uintptr_t) &memSize,
}) >= 0)
gpu->shared.used = memSize;
}
}
return NULL;
}
#ifdef FF_HAVE_DRM_AMDGPU
#include <amdgpu.h>
#include <amdgpu_drm.h>
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath)
{
#if FF_HAVE_DRM_AMDGPU
FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_sensor_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize)
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "Failed to open DRM render device";
amdgpu_device_handle handle;
uint32_t majorVersion, minorVersion;
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0)
return "Failed to initialize AMDGPU device";
uint32_t value;
if (options->temp)
{
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0)
gpu->temperature = value / 1000.;
}
ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle));
struct amdgpu_gpu_info gpuInfo;
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0)
{
gpu->coreCount = (int32_t) gpuInfo.cu_active_number;
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
#define FF_VRAM_CASE(name, value) case value /* AMDGPU_VRAM_TYPE_ ## name */: ffStrbufSetStatic(&gpu->memoryType, #name); break
switch (gpuInfo.vram_type)
{
FF_VRAM_CASE(UNKNOWN, 0);
FF_VRAM_CASE(GDDR1, 1);
FF_VRAM_CASE(DDR2, 2);
FF_VRAM_CASE(GDDR3, 3);
FF_VRAM_CASE(GDDR4, 4);
FF_VRAM_CASE(GDDR5, 5);
FF_VRAM_CASE(HBM, 6);
FF_VRAM_CASE(DDR3, 7);
FF_VRAM_CASE(DDR4, 8);
FF_VRAM_CASE(GDDR6, 9);
FF_VRAM_CASE(DDR5, 10);
FF_VRAM_CASE(LPDDR4, 11);
FF_VRAM_CASE(LPDDR5, 12);
default:
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
break;
}
struct amdgpu_heap_info heapInfo;
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0)
{
gpu->dedicated.total = heapInfo.heap_size;
gpu->dedicated.used = heapInfo.heap_usage;
}
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_GTT, 0, &heapInfo) >= 0)
{
gpu->shared.total = heapInfo.heap_size;
gpu->shared.used = heapInfo.heap_usage;
}
}
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0)
gpu->coreUsage = value;
ffamdgpu_device_deinitialize(handle);
return NULL;
#else
FF_UNUSED(gpu, renderPath);
return "Fastfetch is compiled without libdrm support";
#endif
}
#endif
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd)
{
{
int value;
drm_i915_getparam_t getparam = { .param = I915_PARAM_EU_TOTAL, .value = &value };
if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &getparam) >= 0)
gpu->coreCount = value;
}
{
struct drm_i915_query_item queryItem = {
.query_id = DRM_I915_QUERY_MEMORY_REGIONS,
};
struct drm_i915_query query = {
.items_ptr = (uintptr_t) &queryItem,
.num_items = 1,
};
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0 )
{
FF_AUTO_FREE uint8_t* buffer = calloc(1, (size_t) queryItem.length);
queryItem.data_ptr = (uintptr_t) buffer;
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0)
{
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
struct drm_i915_query_memory_regions* regionInfo = (void*) buffer;
for (uint32_t i = 0; i < regionInfo->num_regions; i++)
{
struct drm_i915_memory_region_info* region = regionInfo->regions + i;
switch (region->region.memory_class)
{
case I915_MEMORY_CLASS_SYSTEM:
gpu->shared.total += region->probed_size;
gpu->shared.used += region->probed_size - region->unallocated_size;
break;
case I915_MEMORY_CLASS_DEVICE:
gpu->dedicated.total += region->probed_size;
gpu->dedicated.used += region->probed_size - region->unallocated_size;
break;
}
}
}
}
}
return NULL;
}
static inline int popcountBytes(uint8_t* bytes, uint32_t length)
{
int count = 0;
while (length >= 8)
{
count += __builtin_popcountll(*(uint64_t*) bytes);
bytes += 8;
length -= 8;
}
if (length >= 4)
{
count += __builtin_popcountl(*(uint32_t*) bytes);
bytes += 4;
length -= 4;
}
if (length >= 2)
{
count += __builtin_popcountl(*(uint16_t*) bytes);
bytes += 2;
length -= 2;
}
if (length)
{
count += __builtin_popcountl(*(uint8_t*) bytes);
}
return count;
}
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd)
{
bool flag = false;
{
struct drm_xe_device_query query = {
.query = DRM_XE_DEVICE_QUERY_GT_TOPOLOGY,
};
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
query.data = (uintptr_t) buffer;
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
int dssCount = 0, euPerDssCount = 0;
for (struct drm_xe_query_topology_mask* topo = (void*) buffer;
(uint8_t*) topo < buffer + query.size;
topo = (void*) (topo->mask + topo->num_bytes)
) {
switch (topo->type)
{
case DRM_XE_TOPO_DSS_COMPUTE:
case DRM_XE_TOPO_DSS_GEOMETRY:
dssCount += popcountBytes(topo->mask, topo->num_bytes);
break;
case DRM_XE_TOPO_EU_PER_DSS:
euPerDssCount += popcountBytes(topo->mask, topo->num_bytes);
break;
}
}
gpu->coreCount = dssCount * euPerDssCount;
flag = true;
}
}
}
{
struct drm_xe_device_query query = {
.query = DRM_XE_DEVICE_QUERY_MEM_REGIONS,
};
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
query.data = (uintptr_t) buffer;
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
struct drm_xe_query_mem_regions* regionInfo = (void*) buffer;
for (uint32_t i = 0; i < regionInfo->num_mem_regions; i++)
{
struct drm_xe_mem_region* region = regionInfo->mem_regions + i;
switch (region->mem_class)
{
case DRM_XE_MEM_REGION_CLASS_SYSMEM:
gpu->shared.total += region->total_size;
gpu->shared.used += region->used;
break;
case DRM_XE_MEM_REGION_CLASS_VRAM:
gpu->dedicated.total += region->total_size;
gpu->dedicated.used += region->used;
break;
}
}
flag = true;
}
}
}
return flag ? NULL : "Failed to query Xe GPU information";
}
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd)
{
struct drm_asahi_params_global paramsGlobal = {};
if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params) {
.param_group = DRM_ASAHI_GET_PARAMS,
.pointer = (uint64_t) &paramsGlobal,
.size = sizeof(paramsGlobal),
}) >= 0)
{
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
gpu->deviceId = paramsGlobal.chip_id;
if (!gpu->name.length)
{
const char* variant = " Unknown";
switch (paramsGlobal.gpu_variant) {
case 'G':
variant = "";
break;
case 'S':
variant = " Pro";
break;
case 'C':
variant = " Max";
break;
case 'D':
variant = " Ultra";
break;
}
ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)",
paramsGlobal.gpu_generation - 12, variant,
paramsGlobal.gpu_generation, paramsGlobal.gpu_variant,
paramsGlobal.gpu_revision + 0xA0);
}
return NULL;
}
return "Failed to query Asahi GPU information";
}
#endif // FF_HAVE_DRM
#include "gpu_driver_specific.h"
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId)
{
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
const char* soName;
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific))
{
return detectFn(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = pciBusId,
}, (FFGpuDriverResult) {
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = &gpu->name,
}, soName);
}
return "No driver-specific detection function found for the GPU vendor";
}
+1 -1
View File
@@ -5,7 +5,7 @@
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
FF_AUTO_CLOSE_FD int pokefd = open(POKE_DEVICE_FULLNAME, O_RDWR);
FF_AUTO_CLOSE_FD int pokefd = open(POKE_DEVICE_FULLNAME, O_RDWR | O_CLOEXEC);
if (pokefd < 0) return "open(POKE_DEVICE_FULLNAME) failed";
pci_info dev;
+55 -306
View File
@@ -105,93 +105,23 @@ FF_MAYBE_UNUSED static const char* drmFindRenderFromCard(const char* drmCardKey,
static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
{
#if FF_HAVE_DRM_AMDGPU
FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_sensor_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize)
#if FF_HAVE_DRM
const char* error = drmFindRenderFromCard(drmKey, buffer);
if (error) return error;
if (ffStrbufEqualS(&gpu->driver, "radeon"))
return ffDrmDetectRadeon(options, gpu, buffer->chars);
else
{
const char* error = drmFindRenderFromCard(drmKey, buffer);
if (error) return error;
#if FF_HAVE_DRM_AMDGPU
return ffDrmDetectAmdgpu(options, gpu, buffer->chars);
#else
FF_UNUSED(options, gpu, drmKey, buffer);
return "Fastfetch is not compiled with libdrm_amdgpu support";
#endif
}
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
if (fd < 0) return "Failed to open DRM device";
amdgpu_device_handle handle;
uint32_t majorVersion, minorVersion;
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0)
return "Failed to initialize AMDGPU device";
ffStrbufAppendF(&gpu->driver, " %u.%u", (unsigned) majorVersion, (unsigned) minorVersion);
uint32_t value;
if (options->temp)
{
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0)
gpu->temperature = value / 1000.;
}
ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle));
struct amdgpu_gpu_info gpuInfo;
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0)
{
gpu->coreCount = (int32_t) gpuInfo.cu_active_number;
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
#define FF_VRAM_CASE(name, value) case value /* AMDGPU_VRAM_TYPE_ ## name */: ffStrbufSetStatic(&gpu->memoryType, #name); break
switch (gpuInfo.vram_type)
{
FF_VRAM_CASE(UNKNOWN, 0);
FF_VRAM_CASE(GDDR1, 1);
FF_VRAM_CASE(DDR2, 2);
FF_VRAM_CASE(GDDR3, 3);
FF_VRAM_CASE(GDDR4, 4);
FF_VRAM_CASE(GDDR5, 5);
FF_VRAM_CASE(HBM, 6);
FF_VRAM_CASE(DDR3, 7);
FF_VRAM_CASE(DDR4, 8);
FF_VRAM_CASE(GDDR6, 9);
FF_VRAM_CASE(DDR5, 10);
FF_VRAM_CASE(LPDDR4, 11);
FF_VRAM_CASE(LPDDR5, 12);
default:
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
break;
}
struct amdgpu_heap_info heapInfo;
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0)
{
if (gpu->type == FF_GPU_TYPE_DISCRETE)
{
gpu->dedicated.total = heapInfo.heap_size;
gpu->dedicated.used = heapInfo.heap_usage;
}
else
{
gpu->shared.total = heapInfo.heap_size;
gpu->shared.used = heapInfo.heap_usage;
}
}
}
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0)
gpu->coreUsage = value;
ffamdgpu_device_deinitialize(handle);
return NULL;
#else
FF_UNUSED(options, gpu, drmKey, buffer);
return "Fastfetch is compiled without libdrm support";
FF_UNUSED(gpu, drmKey, buffer);
return "Fastfetch is not compiled with drm support";
#endif
}
@@ -215,47 +145,50 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu,
ffStrbufAppendC(pciDir, '/');
const uint32_t hwmonLen = pciDir->length;
ffStrbufAppendS(pciDir, "in1_input"); // Northbridge voltage in millivolts (APUs only)
if (ffPathExists(pciDir->chars, FF_PATHTYPE_ANY))
gpu->type = FF_GPU_TYPE_INTEGRATED;
else
gpu->type = FF_GPU_TYPE_DISCRETE;
uint64_t value = 0;
if (options->temp)
{
ffStrbufSubstrBefore(pciDir, hwmonLen);
ffStrbufAppendS(pciDir, "temp1_input"); // The on die GPU temperature in millidegrees Celsius
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
gpu->temperature = (double) value / 1000;
}
if (options->driverSpecific)
if (ffStrbufEqualS(&gpu->driver, "amdgpu")) // Ancient radeon drivers don't have these files
{
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
{
if (gpu->type == FF_GPU_TYPE_DISCRETE)
gpu->dedicated.total = value;
else
gpu->shared.total = value;
ffStrbufSubstrBefore(pciDir, hwmonLen);
ffStrbufAppendS(pciDir, "in1_input"); // Northbridge voltage in millivolts (APUs only)
if (ffPathExists(pciDir->chars, FF_PATHTYPE_ANY))
gpu->type = FF_GPU_TYPE_INTEGRATED;
else
gpu->type = FF_GPU_TYPE_DISCRETE;
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used");
if (options->driverSpecific)
{
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
{
if (gpu->type == FF_GPU_TYPE_DISCRETE)
gpu->dedicated.used = value;
gpu->dedicated.total = value;
else
gpu->shared.used = value;
}
}
gpu->shared.total = value;
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/gpu_busy_percent");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
gpu->coreUsage = (double) value;
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
{
if (gpu->type == FF_GPU_TYPE_DISCRETE)
gpu->dedicated.used = value;
else
gpu->shared.used = value;
}
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/gpu_busy_percent");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
gpu->coreUsage = (double) value;
}
}
}
@@ -311,150 +244,19 @@ static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu
}
}
static inline int popcountBytes(uint8_t* bytes, uint32_t length)
{
int count = 0;
while (length >= 8)
{
count += __builtin_popcountll(*(uint64_t*) bytes);
bytes += 8;
length -= 8;
}
if (length >= 4)
{
count += __builtin_popcountl(*(uint32_t*) bytes);
bytes += 4;
length -= 4;
}
if (length >= 2)
{
count += __builtin_popcountl(*(uint16_t*) bytes);
bytes += 2;
length -= 2;
}
if (length)
{
count += __builtin_popcountl(*(uint8_t*) bytes);
}
return count;
}
static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
{
#if FF_HAVE_DRM
ffStrbufSetS(buffer, "/dev/dri/");
ffStrbufAppendS(buffer, drmKey);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "Failed to open drm device";
if (ffStrbufEqualS(&gpu->driver, "xe"))
{
{
struct drm_xe_device_query query = {
.query = DRM_XE_DEVICE_QUERY_GT_TOPOLOGY,
};
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
query.data = (uintptr_t) buffer;
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
int dssCount = 0, euPerDssCount = 0;
for (struct drm_xe_query_topology_mask* topo = (void*) buffer;
(uint8_t*) topo < buffer + query.size;
topo = (void*) (topo->mask + topo->num_bytes)
) {
switch (topo->type)
{
case DRM_XE_TOPO_DSS_COMPUTE:
case DRM_XE_TOPO_DSS_GEOMETRY:
dssCount += popcountBytes(topo->mask, topo->num_bytes);
break;
case DRM_XE_TOPO_EU_PER_DSS:
euPerDssCount += popcountBytes(topo->mask, topo->num_bytes);
break;
}
}
gpu->coreCount = dssCount * euPerDssCount;
}
}
}
{
struct drm_xe_device_query query = {
.query = DRM_XE_DEVICE_QUERY_MEM_REGIONS,
};
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
query.data = (uintptr_t) buffer;
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
struct drm_xe_query_mem_regions* regionInfo = (void*) buffer;
for (uint32_t i = 0; i < regionInfo->num_mem_regions; i++)
{
struct drm_xe_mem_region* region = regionInfo->mem_regions + i;
switch (region->mem_class)
{
case DRM_XE_MEM_REGION_CLASS_SYSMEM:
gpu->shared.total += region->total_size;
gpu->shared.used += region->used;
break;
case DRM_XE_MEM_REGION_CLASS_VRAM:
gpu->dedicated.total += region->total_size;
gpu->dedicated.used += region->used;
break;
}
}
}
}
}
}
return ffDrmDetectXe(gpu, fd);
else if (ffStrbufEqualS(&gpu->driver, "i915"))
{
{
int value;
drm_i915_getparam_t getparam = { .param = I915_PARAM_EU_TOTAL, .value = &value };
if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &getparam) >= 0)
gpu->coreCount = value;
}
{
struct drm_i915_query_item queryItem = {
.query_id = DRM_I915_QUERY_MEMORY_REGIONS,
};
struct drm_i915_query query = {
.items_ptr = (uintptr_t) &queryItem,
.num_items = 1,
};
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0 )
{
FF_AUTO_FREE uint8_t* buffer = calloc(1, (size_t) queryItem.length);
queryItem.data_ptr = (uintptr_t) buffer;
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0)
{
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
struct drm_i915_query_memory_regions* regionInfo = (void*) buffer;
for (uint32_t i = 0; i < regionInfo->num_regions; i++)
{
struct drm_i915_memory_region_info* region = regionInfo->regions + i;
switch (region->region.memory_class)
{
case I915_MEMORY_CLASS_SYSTEM:
gpu->shared.total += region->probed_size;
gpu->shared.used += region->probed_size - region->unallocated_size;
break;
case I915_MEMORY_CLASS_DEVICE:
gpu->dedicated.total += region->probed_size;
gpu->dedicated.used += region->probed_size - region->unallocated_size;
break;
}
}
}
}
}
}
return NULL;
return ffDrmDetectI915(gpu, fd);
return "Unknown Intel GPU driver";
#else
FF_UNUSED(gpu, drmKey, buffer);
return "Fastfetch is not compiled with drm support";
@@ -569,29 +371,12 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
}
else
{
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
const char* soName;
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific))
{
detectFn(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = {
.domain = pciDomain,
.bus = pciBus,
.device = pciDevice,
.func = pciFunc,
},
}, (FFGpuDriverResult) {
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = &gpu->name,
}, soName);
}
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
.domain = pciDomain,
.bus = pciBus,
.device = pciDevice,
.func = pciFunc,
});
}
if (gpu->name.length == 0)
@@ -627,45 +412,9 @@ FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, cons
#if FF_HAVE_DRM_ASAHI
ffStrbufSetS(buffer, "/dev/dri/");
ffStrbufAppendS(buffer, drmKey);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
if (fd >= 0)
{
struct drm_asahi_params_global paramsGlobal = {};
if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params) {
.param_group = DRM_ASAHI_GET_PARAMS,
.pointer = (uint64_t) &paramsGlobal,
.size = sizeof(paramsGlobal),
}) >= 0)
{
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
gpu->deviceId = paramsGlobal.chip_id;
if (!gpu->name.length)
{
const char* variant = " Unknown";
switch (paramsGlobal.gpu_variant) {
case 'G':
variant = "";
break;
case 'S':
variant = " Pro";
break;
case 'C':
variant = " Max";
break;
case 'D':
variant = " Ultra";
break;
}
ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)",
paramsGlobal.gpu_generation - 12, variant,
paramsGlobal.gpu_generation, paramsGlobal.gpu_variant,
paramsGlobal.gpu_revision + 0xA0);
}
}
}
return ffDrmDetectAsahi(gpu, fd);
#endif
return NULL;
+4
View File
@@ -36,6 +36,10 @@ const char* getOthersByIokit(FFHostResult* host)
if (manufacturer)
ffCfStrGetString(manufacturer, &host->vendor);
FF_CFTYPE_AUTO_RELEASE CFStringRef version = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("version"), kCFAllocatorDefault, kNilOptions);
if (version)
ffCfStrGetString(version, &host->version);
return NULL;
}
+14 -2
View File
@@ -77,10 +77,11 @@ const char* ffDetectHost(FFHostResult* host)
//On WSL, the real host can't be detected. Instead use WSL as host.
if(wslDistroName != NULL || getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL)
{
ffStrbufAppendS(&host->name, "Windows Subsystem for Linux");
ffStrbufSetStatic(&host->name, "Windows Subsystem for Linux");
if (wslDistroName)
ffStrbufAppendF(&host->name, " - %s", wslDistroName);
ffStrbufAppendS(&host->family, "WSL");
ffStrbufSetStatic(&host->family, "WSL");
ffStrbufSetStatic(&host->vendor, "Microsoft Corporation");
if (instance.config.general.detectVersion)
{
@@ -92,6 +93,17 @@ const char* ffDetectHost(FFHostResult* host)
}); // supported in 2.2.3 and later
}
}
else if (ffStrbufStartsWithS(&instance.state.platform.sysinfo.version, "FreeBSD "))
{
ffStrbufSetStatic(&host->name, "Linux Binary Compatibility on FreeBSD");
ffStrbufSetStatic(&host->family, "FreeBSD");
ffStrbufSetStatic(&host->vendor, "FreeBSD Foundation");
if (instance.config.general.detectVersion)
{
ffStrbufSetS(&host->version, instance.state.platform.sysinfo.version.chars + strlen("FreeBSD "));
ffStrbufSubstrBeforeFirstC(&host->version, ' ');
}
}
}
return NULL;
+2
View File
@@ -37,6 +37,8 @@ static bool detectOSCodeName(FFOSResult* os)
switch (num)
{
case 26:
case 16: ffStrbufSetStatic(&os->codename, "Tahoe"); return true;
case 15: ffStrbufSetStatic(&os->codename, "Sequoia"); return true;
case 14: ffStrbufSetStatic(&os->codename, "Sonoma"); return true;
case 13: ffStrbufSetStatic(&os->codename, "Ventura"); return true;
+30 -1
View File
@@ -231,6 +231,24 @@ FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result)
ffStrbufSetF(&result->prettyName, "Proxmox VE %s", result->versionID.chars);
return true;
}
else if (ffStrbufContainS(&instance.state.platform.sysinfo.release, "+rpt-rpi-"))
{
// Raspberry Pi OS
ffStrbufSetS(&result->id, "raspbian");
ffStrbufSetS(&result->idLike, "debian");
ffStrbufSetS(&result->name, "Raspberry Pi OS");
ffStrbufSetS(&result->prettyName, "Raspberry Pi OS");
return true;
}
else if (ffStrbufEndsWithS(&instance.state.platform.sysinfo.release, "+truenas"))
{
// TrueNAS Scale
ffStrbufSetS(&result->id, "truenas-scale");
ffStrbufSetS(&result->idLike, "debian");
ffStrbufSetS(&result->name, "TrueNAS Scale");
ffStrbufSetS(&result->prettyName, "TrueNAS Scale");
return true;
}
else
{
// Hack for MX Linux. See #847
@@ -286,8 +304,19 @@ static void detectOS(FFOSResult* os)
parseOsRelease(FASTFETCH_TARGET_DIR_ETC "/os-release", os);
if (os->id.length == 0 || os->version.length == 0 || os->prettyName.length == 0 || os->codename.length == 0)
parseLsbRelease(FASTFETCH_TARGET_DIR_ETC "/lsb-release", os);
if (os->id.length == 0 || os->name.length > 0 || os->prettyName.length > 0)
if (os->id.length == 0 || os->name.length == 0 || os->prettyName.length == 0)
parseOsRelease(FASTFETCH_TARGET_DIR_USR "/lib/os-release", os);
if (os->id.length == 0 && os->name.length == 0 && os->prettyName.length == 0)
{
// HarmonyOS has no os-release file
if (ffStrbufEqualS(&instance.state.platform.sysinfo.name, "HarmonyOS"))
{
ffStrbufSetS(&os->id, "harmonyos");
ffStrbufSetS(&os->idLike, "harmonyos");
ffStrbufSetS(&os->name, "HarmonyOS");
ffStrbufSetS(&os->prettyName, "HarmonyOS");
}
}
}
void ffDetectOSImpl(FFOSResult* os)
+11 -10
View File
@@ -100,22 +100,23 @@ uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir)
{
bool ok = false;
#if !defined(__sun) && !defined(__HAIKU__)
if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK)
ok = entry->d_type == (isdir ? DT_DIR : DT_REG);
else
#endif
if (entry->d_name[0] != '.')
{
struct stat stbuf;
if (fstatat(dirfd(dirp), entry->d_name, &stbuf, 0) == 0)
ok = isdir ? S_ISDIR(stbuf.st_mode) : S_ISREG(stbuf.st_mode);
#if !defined(__sun) && !defined(__HAIKU__)
if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK)
ok = entry->d_type == (isdir ? DT_DIR : DT_REG);
else
#endif
{
struct stat stbuf;
if (fstatat(dirfd(dirp), entry->d_name, &stbuf, 0) == 0)
ok = isdir ? S_ISDIR(stbuf.st_mode) : S_ISREG(stbuf.st_mode);
}
}
if(ok) ++num_elements;
}
if(isdir && num_elements >= 2)
num_elements -= 2; // accounting for . and ..
return num_elements;
}
@@ -10,7 +10,7 @@
static const char* detectDisk(FFstrbuf* path, const char* diskType, FFlist* result)
{
FF_AUTO_CLOSE_FD int rawfd = open(path->chars, O_RDONLY);
FF_AUTO_CLOSE_FD int rawfd = open(path->chars, O_RDONLY | O_CLOEXEC);
if (rawfd < 0) return "detectDisk: open(rawfd) failed";
device_geometry geometry;
+1 -1
View File
@@ -32,7 +32,7 @@ const char* ffDetectSound(FFlist* devices)
for (int idev = 0; idev <= info.nummixers; ++idev)
{
path[strlen("/dev/mixer")] = (char) ('0' + idev);
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR);
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR | O_CLOEXEC);
if (fd < 0) break;
if (idev == 0)
+1 -1
View File
@@ -25,7 +25,7 @@ const char* ffDetectSound(FFlist* devices)
for (int idev = 0; idev < 9; ++idev)
{
path[strlen("/dev/audio")] = (char) ('0' + idev);
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR);
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR | O_CLOEXEC);
if (fd < 0) break;
audio_device_t ad;
+25
View File
@@ -243,6 +243,29 @@ static bool detectContour(const FFstrbuf* exe, FFTerminalFontResult* result)
return true;
}
static bool detectRio(FFTerminalFontResult* terminalFont)
{
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
FFpropquery fontQueryToml[] = {
{"family =", &fontName},
{"size =", &fontSize},
};
ffParsePropFileConfigValues("rio/config.toml", 2, fontQueryToml);
if(fontName.length == 0)
ffStrbufAppendS(&fontName, "Cascadia Code");
if(fontSize.length == 0)
ffStrbufAppendS(&fontSize, "18");
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
return true;
}
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont);
static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
@@ -257,6 +280,8 @@ static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTermina
detectContour(&terminal->exe, terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "ghostty"))
detectGhostty(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "rio"))
detectRio(terminalFont);
#ifndef _WIN32
else if(ffStrbufStartsWithIgnCaseS(&terminal->exe, "/dev/pts/"))
+1
View File
@@ -30,6 +30,7 @@ const char* ffDetectWMPlugin(FFstrbuf* pluginName)
!ffStrEqualsIgnCase(comm, "kwm") &&
!ffStrEqualsIgnCase(comm, "chunkwm") &&
!ffStrEqualsIgnCase(comm, "yabai") &&
!ffStrEqualsIgnCase(comm, "aerospace") &&
!ffStrEqualsIgnCase(comm, "rectangle")
) continue;
+1 -1
View File
@@ -237,7 +237,7 @@ const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE
if (!wmName)
return "No WM detected";
if (ffStrbufEqualS(wmName, "Hyprland"))
if (ffStrbufIgnCaseEqualS(wmName, "Hyprland"))
return getHyprland(result);
if (ffStrbufEqualS(wmName, "sway"))
+20
View File
@@ -0,0 +1,20 @@
$4#######################
$4# $2##### $4#
$4# $2####### $4#
$4# $2##$5O$2#$5O$2## $4#
$4# $2#$3#####$2# $4#
$4# $2##$1##$3###$1##$2## $4#
$4# $2#$1##########$2## $4#
$4# $2#$1############$2## $4#
$4# $2#$1######$5A_O$1####$2### $4#
$4# $3##$2#$1############$2##$3## $4#
$4#$3######$2#$1#######$2#$3######$4#
$4#$3#######$2#$1#####$2#$3#######$4#
$4# $3#####$2#######$3##### $4#
$4#######################
$4#$5╔═╗╔╗╔╦ ╦╔═╗╦ ╦╔═╗╔═╗$4#
$4#$5╠═╣║║║║ ║╚═╗╠═╣║ ║╚═╗$4#
$4#$5╩ ╩╝╚╝╚═╝╚═╝╩ ╩╚═╝╚═╝$4#
$4#######################
$4# $3WWW.ANUSHOS.ORG $4#
$4#######################
+5 -5
View File
@@ -1,6 +1,6 @@
_________
| __ |
| \ \___ |
| \ _ \ |
| \___/ |
_________
| $2__ $1 |
| $2\ \___ $1 |
| $2 \ _ \$1 |
| $2 \___/$1 |
|_________|
+5
View File
@@ -0,0 +1,5 @@
__
/ \
__ |_
/ |
\__/
+19
View File
@@ -0,0 +1,19 @@
xSSSSSSSSSSSx:
XSSSSSSSSSSSSSSSSSSSSX
xSSSSSSSSSSSSSSSSSSSSSSSxSSX
xSSSSSSSSSSSSSSSSSSSSSSSSSSSSXSS
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSXXXS;
+SSSSSSx++SSSSSSSSSSSSSSSSSSSSSSSSSXSX
SSSSS:::::::SSSSSSSSSSSSSXSSSSSSSSSS+S+
XSSSX::::::::XxSSSSSSSSXSx;::xSSSSSSSSSS
;SSSS:::::::::XSSSSSSSSS+:::::::xSSSSSSSS;
+SSSSx::::::::SSSSSSSSS;:::::::::XSSSSSSSX
SSSSXSx:::::SSSSxXSSSS::::::::::XSSSSSSSX
xSSSSSSSSSSSS:::::SSSX::::::::::XSSSSSSS;
+SSSSSSSSSSSSSSX:SSSSS;:::::::SxSSSSSSS
+SSSSSSSSSSSSSSSSSSSSSSSSSXSSxSSSSSS
xxSSSSSSSSSSSSSSSSSSSSSSSSSSSSSx
SSSSSSSSSSSSSSSSSSSSSSSSSSSX
xXSSSSSSSSSSSSX
SSS +SSSxSSSSS
;x xSSx
+19
View File
@@ -0,0 +1,19 @@
....-----....
.-+##############+-..
.+######################+..
.########+- -++#######-.
.+######- -######+.
.######. .######..
.+####+ +#####..
.-####+. +####+.
.+####+ -####+..
..+####+ -####+...
$2......--$1+####+$2--.......................--$1+####+$2-.........
..$1--++++-$2...... ...$1-++++--$2..
..$1--+++--$2... ...$1-+++++-$2..
.$1--+++--$2.... ....$1--+++-$2...
..$1-++++++--$2..... ......$1---+---$2...
...$1-+++++++++-----$2..$1----++++++--$2..
...$1---++++++----++++++++---$2...
.....$1-----+++-----$2...
...$1---$2...
+22
View File
@@ -0,0 +1,22 @@
+++
++++++++ +
++++++++++++ +++
++++++++++* +++++++++ ++++
+++++++ ++++++++++++++++++
++++ ++++ +++++
++++ +++ ++++
+++++ +++ ++++++ +++
+++++++++++++ +++++++++ +++
+++++++++++++ +++ +++ +++
+++++++++++++ ++++ +++ +++
++++++++ +++ +++++++ +++
+++++++ +++
++++++++ ++++ ++
+++++++++++ +++++ +++++
++++++++ ++++++++++++ +++++++++
++++++++++++++ ++++++++++++++++
++++++++++++++++++++++++ +++++++++
++++++ +++++++++ ++++
+ +++++++
+++++++
+++++
+18
View File
@@ -0,0 +1,18 @@
++ $2++
$1++++++ $2++++++
$1+++++++++ $2+++++++++
$1+++++++ $2+++++++
$1+++ $2+++ $1+ $3--------$1 $2+ $1+++ $2+++
$1++++++ $2++++++ $3------$1 ++++++ $2++++++
$1++++++++ $2++++++++++ $1++++++++++ $2++++++++
$1+++++++ $3--$1 $2+++++++ $1+++++++ $3--$1 $2+++++++
$2+++ $1+ $3--------$1 $2+ $1+++ $2+++ $1+ $3--------$1 $2+ $1+++
$2++++++ $3--------$1 ++++++ $2++++++ $3--------$1 ++++++
$2++++++++++ $1+++++++++ $2+++++++++ $1++++++++++
$2+++++++++ $1+++++++ $3--$1 $2+++++++ $1+++++++++
$2+++++ +++ $3--------$1 +++ +++++
$2++ +++++++ $3------$1 +++++++ ++
$2++++++++++ $1++++++++++
$2++++++++ $1++++++++
$2+++++ $1+++++
$2++ $1++
+1 -1
View File
@@ -1,4 +1,4 @@
$1 **
**
* ** */
$2@$1///// / *** *** **** ***/
//////////////**** ** * ** *** **/
+21
View File
@@ -0,0 +1,21 @@
$2 ,c. .c;
$2 .$1KMMMk$2.... ....$1kMMMK$2.
$2 .$1WMMMMMX$2..... .....$1KMMMMMW.
$1 XMMMMMMM0$2..... ....$1OMMMMMMMN
$1 dMMMMMMMMM;$2.... ..... ....,$1MMMMMMMMMd
$1 WMMMMMMMMMl;$3okKKKKKKKKKOo$1;cMMMMMMMMMM
$1 'MMMMMMMNX$2K0$3KKKKKKKKKKKKKKK$20K$1XNMMMMMMM;
$1 oMMMMMMM$2Oxo$3KKKKKKKKKKKKKKKKK$2oxO$1MMMMMMMd
$1 dMMMMMMM$2dxxx$3KKKKKKKKKKKKKKK$2xxxd$1NMMMMMMk
$1 :MMMMX0$2xxxxxx$30KKKKKKKK0KK0$2xxxxxx0$1XMMMMc
$1 MMMO$2xxxxxxxxdx$3kdd$20x0$3ddk$2xdxxxxxxxx$1OMMM
$1 ;$2xxkxddxxxxdodxxxxdxdxxxxdodxxxxddxkxx$1;
$1dxd$2KMMMWXo$1'.....'$2cdxxxdc$1'.....'$2lXWMMMX$1dxd
$1cxd$2XMMMN$1,..........$2dxd$1'.........'$2XMMMN$1dxl
$1 .xx$2WMMl$1...''....'.;k:.'....''...$2lMMW$1xx.
$1..:kXMMx..'....''..kMk..''....'..xMMXkc..
$1 dMMMMMMd.....'...xMMMx...''....dMMMMMMx
$1 kMMMMWOoc:coOkolllokOoc:coOWMMMMO
$1 .MMMMMMMMl$2...$1lNMMMMMMM.
$1 KMMMMMMX$2l$1KMMMMMMX
$1 .MMMMMMMMM.
+109 -28
View File
@@ -252,6 +252,20 @@ static const FFlogo A[] = {
.colorKeys = FF_COLOR_FG_RED,
.colorTitle = FF_COLOR_FG_WHITE,
},
// AnushOS
{
.names = {"AnushOS"},
.lines = FASTFETCH_DATATEXT_LOGO_ANUSHOS,
.colors = {
FF_COLOR_FG_WHITE,
FF_COLOR_FG_BLACK,
FF_COLOR_FG_YELLOW,
FF_COLOR_FG_CYAN,
FF_COLOR_FG_RED,
},
.colorKeys = FF_COLOR_FG_WHITE,
.colorTitle = FF_COLOR_FG_WHITE,
},
// AoscOsRetro
{
.names = {"Aosc OS/Retro", "aoscosretro"},
@@ -706,10 +720,10 @@ static const FFlogo B[] = {
.lines = FASTFETCH_DATATEXT_LOGO_BEDROCK,
.colors = {
FF_COLOR_FG_LIGHT_BLACK, //grey
FF_COLOR_FG_WHITE,
FF_COLOR_FG_DEFAULT,
},
.colorKeys = FF_COLOR_FG_LIGHT_BLACK, //grey
.colorTitle = FF_COLOR_FG_WHITE,
.colorTitle = FF_COLOR_FG_DEFAULT,
},
// BedrockSmall
{
@@ -717,10 +731,11 @@ static const FFlogo B[] = {
.lines = FASTFETCH_DATATEXT_LOGO_BEDROCK_SMALL,
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.colors = {
FF_COLOR_FG_WHITE,
FF_COLOR_FG_LIGHT_BLACK, //grey
FF_COLOR_FG_DEFAULT,
},
.colorKeys = FF_COLOR_FG_WHITE,
.colorTitle = FF_COLOR_FG_WHITE,
.colorKeys = FF_COLOR_FG_LIGHT_BLACK, //grey
.colorTitle = FF_COLOR_FG_DEFAULT,
},
// BigLinux
{
@@ -1731,6 +1746,16 @@ static const FFlogo F[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
{
.names = {"Fedora2_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT | FF_LOGO_LINE_TYPE_ALTER_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_FEDORA2_SMALL,
.colors = {
FF_COLOR_FG_BLUE,
},
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
// FedoraOld
{
.names = {"Fedora_old"},
@@ -1989,6 +2014,16 @@ static const FFlogo G[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_RED,
},
// GhostFreak
{
.names = {"GhostFreak"},
.lines = FASTFETCH_DATATEXT_LOGO_GHOSTFREAK,
.colors = {
FF_COLOR_FG_DEFAULT,
},
.colorKeys = FF_COLOR_FG_DEFAULT,
.colorTitle = FF_COLOR_FG_BLUE,
},
// Glaucus
{
.names = {"Glaucus"},
@@ -2175,6 +2210,17 @@ static const FFlogo H[] = {
.colorKeys = FF_COLOR_FG_RED,
.colorTitle = FF_COLOR_FG_RED,
},
// HarmonyOS
{
.names = {"HarmonyOS"},
.lines = FASTFETCH_DATATEXT_LOGO_HARMONYOS,
.colors = {
FF_COLOR_FG_WHITE,
FF_COLOR_FG_BLUE,
},
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
// Hash
{
.names = {"Hash"},
@@ -2267,13 +2313,13 @@ static const FFlogo H[] = {
.colorKeys = FF_COLOR_FG_LIGHT_BLACK,
.colorTitle = FF_COLOR_FG_WHITE,
},
// Hydra Framework
// HydraPWK
{
.names = {"Hydra"},
.lines = FASTFETCH_DATATEXT_LOGO_HYDRA,
.names = {"HydraPWK"},
.lines = FASTFETCH_DATATEXT_LOGO_HYDRAPWK,
.colors = {
FF_COLOR_FG_RED,
FF_COLOR_FG_WHITE,
FF_COLOR_FG_RED,
FF_COLOR_FG_DEFAULT,
},
},
// LAST
@@ -2378,18 +2424,18 @@ static const FFlogo K[] = {
},
// Kali
{
.names = {"Kali", "Kalilinux"},
.names = {"Kali"},
.lines = FASTFETCH_DATATEXT_LOGO_KALI,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_LIGHT_BLACK,
},
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_WHITE,
.colorTitle = FF_COLOR_FG_DEFAULT,
},
// KaliSmall
{
.names = {"Kali_small", "Kalilinux_small"},
.names = {"Kali_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_KALI_SMALL,
.colors = {
@@ -2397,7 +2443,17 @@ static const FFlogo K[] = {
FF_COLOR_FG_LIGHT_BLACK,
},
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_WHITE,
.colorTitle = FF_COLOR_FG_DEFAULT,
},
// Kalpa Desktop
{
.names = {"kalpa-desktop"},
.lines = FASTFETCH_DATATEXT_LOGO_KALPA_DESKTOP,
.colors = {
FF_COLOR_FG_GREEN,
},
.colorKeys = FF_COLOR_FG_GREEN,
.colorTitle = FF_COLOR_FG_DEFAULT,
},
// KaOS
{
@@ -4728,6 +4784,18 @@ static const FFlogo T[] = {
FF_COLOR_FG_CYAN,
},
},
// TrueNAS Scale
{
.names = {"TrueNAS-Scale"},
.lines = FASTFETCH_DATATEXT_LOGO_TRUENAS_SCALE,
.colors = {
FF_COLOR_FG_256 "39",
FF_COLOR_FG_256 "32",
FF_COLOR_FG_256 "248",
},
.colorKeys = FF_COLOR_FG_256 "248",
.colorTitle = FF_COLOR_FG_256 "32",
},
// TuxedoOS
{
.names = {"Tuxedo OS", "tuxedo"},
@@ -5256,15 +5324,6 @@ static const FFlogo W[] = {
};
static const FFlogo X[] = {
// Xenia
{
.names = {"Xenia"},
.lines = FASTFETCH_DATATEXT_LOGO_XENIA,
.colors = {
FF_COLOR_FG_RED,
FF_COLOR_FG_WHITE,
}
},
// XCP-ng
{
.names = {"XCP-ng", "xenenterprise"},
@@ -5278,14 +5337,27 @@ static const FFlogo X[] = {
FF_COLOR_FG_YELLOW,
}
},
// Xferience
// Xenia
{
.names = {"Xferience"},
.lines = FASTFETCH_DATATEXT_LOGO_XFERIENCE,
.names = {"Xenia"},
.lines = FASTFETCH_DATATEXT_LOGO_XENIA,
.colors = {
FF_COLOR_FG_CYAN,
FF_COLOR_FG_CYAN,
FF_COLOR_FG_RED,
FF_COLOR_FG_LIGHT_BLACK,
},
.colorKeys = FF_COLOR_FG_DEFAULT,
.colorTitle = FF_COLOR_FG_RED,
},
// Xenia_old
{
.names = {"Xenia_old"},
.lines = FASTFETCH_DATATEXT_LOGO_XENIA_OLD,
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
.colors = {
FF_COLOR_FG_YELLOW,
FF_COLOR_FG_GREEN,
FF_COLOR_FG_RED,
}
},
//XeroArch
{
@@ -5300,6 +5372,15 @@ static const FFlogo X[] = {
FF_COLOR_FG_256 "15",
}
},
// Xferience
{
.names = {"Xferience"},
.lines = FASTFETCH_DATATEXT_LOGO_XFERIENCE,
.colors = {
FF_COLOR_FG_CYAN,
FF_COLOR_FG_CYAN,
},
},
// LAST
{},
};
+1 -1
View File
@@ -535,7 +535,7 @@ void ffInitDiskOptions(FFDiskOptions* options)
#if _WIN32 || __APPLE__ || __ANDROID__
ffStrbufInit(&options->hideFolders);
#else
ffStrbufInitStatic(&options->hideFolders, "/efi:/boot:/boot/efi");
ffStrbufInitStatic(&options->hideFolders, "/efi:/boot:/boot/efi:/boot/firmware");
#endif
ffStrbufInit(&options->hideFS);
options->showTypes = FF_DISK_VOLUME_TYPE_REGULAR_BIT | FF_DISK_VOLUME_TYPE_EXTERNAL_BIT | FF_DISK_VOLUME_TYPE_READONLY_BIT;
+1 -1
View File
@@ -63,7 +63,7 @@ const char* ffBinaryExtractStrings(const char* elfFile, bool (*cb)(const char* s
return "load libelf failed";
// Open the ELF file
FF_AUTO_CLOSE_FD int fd = open(elfFile, O_RDONLY, 0);
FF_AUTO_CLOSE_FD int fd = open(elfFile, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "open() failed";
Elf* elf = elfData.ffelf_begin(fd, ELF_C_READ, NULL);
-1
View File
@@ -51,7 +51,6 @@ bool ffKmodLoaded(const char* modName)
{
struct iovec iov = {};
// 初始尝试分配的内存大小
for (size_t len = 8192;; len = iov.iov_len)
{
iov.iov_len = len;
+3 -3
View File
@@ -183,7 +183,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
}
FF_DEBUG("Parsed SMBIOS entry address: 0x%lx", (unsigned long)entryAddress);
FF_AUTO_CLOSE_FD int fd = open("/dev/mem", O_RDONLY);
FF_AUTO_CLOSE_FD int fd = open("/dev/mem", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
FF_DEBUG("Failed to open /dev/mem: %s", strerror(errno));
return NULL;
@@ -219,7 +219,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
#endif
);
FF_AUTO_CLOSE_FD int fd = open("/dev/smbios", O_RDONLY);
FF_AUTO_CLOSE_FD int fd = open("/dev/smbios", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
FF_DEBUG("Failed to open /dev/smbios: %s", strerror(errno));
return NULL;
@@ -328,7 +328,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
#else
"/dev/mem" // kern.securelevel must be -1
#endif
, O_RDONLY);
, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
FF_DEBUG("Failed to open memory device: %s", strerror(errno));
return NULL;