diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 183ade6423..0000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: [CarterLi, LinusDierheimer] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 461d96127d..1745a789d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: run: uname -a - name: configure project - run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF + run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF - name: build project run: cmake --build . --target package --verbose -j4 @@ -74,7 +74,7 @@ jobs: run: uname -a - name: install required packages - run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev + run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev python3-requests - name: install linuxbrew packages run: | @@ -87,7 +87,7 @@ jobs: languages: c - name: configure project - run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . + run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DCMAKE_INSTALL_PREFIX=/usr . - name: build project run: cmake --build . --target package --verbose -j4 @@ -247,12 +247,12 @@ jobs: run: | cat /etc/alpine-release uname -a - apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++ + apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev py3-requests gcc g++ shell: alpine.sh --root {0} - name: build run: | - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -GNinja . + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -GNinja . cmake --build . --target package --verbose -j4 shell: alpine.sh {0} @@ -422,8 +422,8 @@ jobs: run: | uname -a sudo pkg update - sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm libelf glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . + sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm libelf glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat py311-requests + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ab26cd0ef..ad1c1ae88a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +# 2.26.0 + +Changes: +* To be consistent to other platforms, CPU frequency detection on Linux no longer checks `bios_limit` + +Features: +* Detect GPU index (#1267, GPU) +* Count Flatpak runtime packages (#1085, Packages, Linux) +* Support pacstall package manager (Packages, Linux) +* Support CU core count, max frequency, VMEM usage detection for AMD cards on Linux (GPU, Linux) + * Requires `--gpu-driver-specific` +* Support EU core count, VMEM size detection Intel cards on Linux (GPU, Linux) + * Requires `--gpu-driver-specific`. VMEM usage detection requires root permissions. +* Add new module `TPM` to print TPM (Trusted Platform Module) version if available (TPM) +* Support GPU driver version detection (GPU, macOS) +* Add new CMake option `-DENABLE_EMBEDDED_PCIIDS=ON`. + * If enabled, fastfetch will download the newest [`pci.ids`](https://pci-ids.ucw.cz/) file, [transform it into C code](https://github.com/fastfetch-cli/fastfetch/blob/dev/scripts/gen-pciids.py) and compile it into fastfetch binaries. + +Bugfixes: +* Fix font size detecton of foot terminal (#1276, TerminalFont, Linux) +* Ignore `su` and `sudo` when detecting terminal (#1283, Terminal, Linux) +* Always print inches in integer (Display) +* Fix Wifi connection protocol detection on macOS Sequoia (Wifi, macOS) +* Fix hanging when font name is long when detecting kitty term font (#1289, TerminalFont) +* Detect all enabled or connected connectors (#1301, Display, Linux) + +Logos: +* Add FoxOS +* Add GXDE OS + # 2.25.0 Features: diff --git a/CMakeLists.txt b/CMakeLists.txt index 47b2792412..3f0a50900f 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.25.0 + VERSION 2.26.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -51,6 +51,7 @@ cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR FreeBSD OR SunOS" OF cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR FreeBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF) cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR SunOS" OFF) @@ -80,6 +81,7 @@ option(BUILD_TESTS "Build tests" OFF) # Also create test executables option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON) +option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF) set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static) set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch") @@ -254,6 +256,16 @@ else() file(READ "src/data/help.json" DATATEXT_JSON_HELP) endif() +if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "fastfetch_pciids.c.inc") + if(Python_FOUND) + execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py" + OUTPUT_FILE "fastfetch_pciids.c.inc") + else() + message(STATUS "Python3 is not found, 'fastfetch_pciids.c.inc' will not be generated") + set(ENABLE_EMBEDDED_PCIIDS OFF) + endif() +endif() + fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP) fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE) fastfetch_load_text(src/data/help_footer.txt DATATEXT_HELP_FOOTER) @@ -394,6 +406,7 @@ set(LIBFASTFETCH_SRC src/modules/terminalsize/terminalsize.c src/modules/theme/theme.c src/modules/title/title.c + src/modules/tpm/tpm.c src/modules/uptime/uptime.c src/modules/users/users.c src/modules/version/version.c @@ -412,6 +425,7 @@ set(LIBFASTFETCH_SRC src/util/base64.c src/util/FFlist.c src/util/FFstrbuf.c + src/util/kmod.c src/util/path.c src/util/platform/FFPlatform.c src/util/smbiosHelper.c @@ -480,11 +494,11 @@ if(LINUX) src/detection/gtk_qt/qt.c src/detection/sound/sound_linux.c src/detection/swap/swap_linux.c - src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_linux.c src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/tpm/tpm_linux.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -544,11 +558,11 @@ elseif(ANDROID) src/detection/processes/processes_linux.c src/detection/sound/sound_nosupport.c src/detection/swap/swap_linux.c - src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_android.c src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_nosupport.c @@ -625,11 +639,11 @@ elseif(FreeBSD) src/detection/gtk_qt/qt.c src/detection/sound/sound_bsd.c src/detection/swap/swap_bsd.c - src/detection/temps/temps_bsd.c src/detection/terminalfont/terminalfont_linux.c src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/tpm/tpm_bsd.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -691,11 +705,11 @@ elseif(APPLE) src/detection/processes/processes_bsd.c src/detection/sound/sound_apple.c src/detection/swap/swap_apple.c - src/detection/temps/temps_apple.c src/detection/terminalfont/terminalfont_apple.m src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_apple.m @@ -707,6 +721,7 @@ elseif(APPLE) src/detection/zpool/zpool_nosupport.c src/util/apple/cf_helpers.c src/util/apple/osascript.m + src/util/apple/smc_temps.c src/util/platform/FFPlatform_unix.c src/util/binary_apple.c ) @@ -726,6 +741,7 @@ elseif(WIN32) src/detection/btrfs/btrfs_nosupport.c src/detection/chassis/chassis_windows.c src/detection/cpu/cpu_windows.c + src/detection/cpu/cpu_windows.cpp src/detection/cpucache/cpucache_windows.c src/detection/cpuusage/cpuusage_windows.c src/detection/cursor/cursor_windows.c @@ -760,8 +776,8 @@ elseif(WIN32) src/detection/terminalfont/terminalfont_windows.c src/detection/terminalshell/terminalshell_windows.c src/detection/terminalsize/terminalsize_windows.c - src/detection/temps/temps_windows.cpp src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_windows.c src/detection/uptime/uptime_windows.c src/detection/users/users_windows.c src/detection/wallpaper/wallpaper_windows.c @@ -846,6 +862,7 @@ elseif(SunOS) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_sunos.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -1038,6 +1055,10 @@ ff_lib_enable(DRM "libdrm" "Libdrm" ) +ff_lib_enable(DRM_AMDGPU + "libdrm_amdgpu" + "Libdrm_Amdgpu" +) ff_lib_enable(GIO "gio-2.0" "GIO" @@ -1133,18 +1154,29 @@ if(ENABLE_LIBZFS) endif() endif() - if(ENABLE_THREADS) - target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1) if(CMAKE_USE_PTHREADS_INIT) #Threads::Threads is not set for WIN32 target_link_libraries(libfastfetch PRIVATE Threads::Threads) endif() endif() +if(ENABLE_EMBEDDED_PCIIDS) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_PCIIDS=1) +endif() + if(LINUX) target_link_libraries(libfastfetch PRIVATE "m" ) + + if(ENABLE_DIRECTX_HEADERS) + if(NOT BINARY_LINK_TYPE STREQUAL "dlopen") + target_link_libraries(libfastfetch + PRIVATE "/usr/lib/wsl/lib/libdxcore.so" + ) + endif() + endif() elseif(APPLE) target_link_libraries(libfastfetch PRIVATE "-framework AVFoundation" @@ -1168,7 +1200,7 @@ elseif(APPLE) PRIVATE "-weak_framework Apple80211" ) elseif(WIN32) - target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601) + target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0A00) target_link_libraries(libfastfetch PRIVATE "dwmapi" PRIVATE "gdi32" diff --git a/README.md b/README.md index e82de5b393..2d6e8e3d05 100644 --- a/README.md +++ b/README.md @@ -152,13 +152,13 @@ Fastfetch uses `format` to generate output. For example, to make the `GPU` modul "modules": [ { "type": "gpu", - "format": "{2}" // See `fastfetch -h gpu-format` for detail + "format": "{name}" // See `fastfetch -h gpu-format` for detail } ] } ``` -. . which is equivalent to `fastfetch -s gpu --gpu-format '{2}'` +. . which is equivalent to `fastfetch -s gpu --gpu-format '{name}'` See `fastfetch -h format` for information on basic usage. For module specific formattion, see `fastfetch -h -format` @@ -186,6 +186,10 @@ You can always use `fastfetch --pipe false` to force fastfetch running in colorf See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096). +### Q: I use Debian / Ubuntu / Debian deserved distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is it a bug? + +See [#1282](https://github.com/fastfetch-cli/fastfetch/issues/1282) + ### Q: I want feature A / B / C. Will fastfetch support it? Fastfetch is a system information tool. We only accept hardware or system level software feature requests. For most personal uses, I recommend using `Command` module to detect it yourself, which can be used to grab output from a custom shell script: @@ -210,6 +214,13 @@ Otherwise, open a feature request in [GitHub Issues](https://github.com/fastfetc * For usage questions, please start a discussion in [GitHub Discussions](https://github.com/fastfetch-cli/fastfetch/discussions). * For possible bugs, please open an issue in [GitHub Issues](https://github.com/fastfetch-cli/fastfetch/issues). Be sure to fill the bug-report template carefully for developers to investigate. +## Donate + +If you find Fastfetch to be useful, please consider donating. + +* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui) +* Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer) + ## Star History Give it a star to support us! diff --git a/debian/changelog b/debian/changelog index 647ba54c12..caa889c2fe 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +fastfetch (2.25.0) jammy; urgency=medium + + * Update to 2.25.0 + + -- Carter Li Thu, 19 Sep 2024 10:28:38 +0800 + fastfetch (2.24.0) jammy; urgency=medium * Update to 2.24.0 diff --git a/debian/files b/debian/files index 1e5930ffc0..fc11a7155e 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.24.0_source.buildinfo universe/utils optional +fastfetch_2.25.0_source.buildinfo universe/utils optional diff --git a/doc/json_schema.json b/doc/json_schema.json index 0ebda7d2cf..04266e3833 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -706,6 +706,7 @@ "terminaltheme", "title", "theme", + "tpm", "uptime", "users", "version", @@ -865,6 +866,10 @@ "const": "theme", "description": "Print current theme of desktop environment" }, + { + "const": "tpm", + "description": "Print info of Trusted Platform Module (TPM) Security Device" + }, { "const": "uptime", "description": "Print how long system has been running" diff --git a/presets/all.jsonc b/presets/all.jsonc index b1c28c31d9..9b27615e04 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -97,6 +97,7 @@ "type": "physicaldisk", "temp": true }, + "tpm", "version", "break", "colors" diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 2bb446bfdb..3027010d8f 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -99,6 +99,7 @@ "type": "physicaldisk", "temp": true }, + "tpm", "version", "break", "colors" diff --git a/presets/examples/24.jsonc b/presets/examples/24.jsonc index 66145db6ff..37c27c4b21 100644 --- a/presets/examples/24.jsonc +++ b/presets/examples/24.jsonc @@ -88,7 +88,7 @@ { "type": "disk", "key": "{#90}{$1}│ {#91}Disk {#90}│", - "format": "{$2}{$3}{size-used} / {size-used} ({size-percentage}{$2})" + "format": "{$2}{$3}{size-used} / {size-total} ({size-percentage}{$2})" }, { "type": "poweradapter", diff --git a/scripts/gen-pciids.py b/scripts/gen-pciids.py new file mode 100644 index 0000000000..80e7304fb6 --- /dev/null +++ b/scripts/gen-pciids.py @@ -0,0 +1,95 @@ +from requests import get as http_get + +class PciDeviceModel: + def __init__(self, id: int, name: str): + self.id = id + self.name = name + +class PciVendorModel: + def __init__(self, id: int, name: str): + self.id = id + self.name = name + self.devices = [] + +def main(keep_vendor_list: set): + vendors = [] + try: + with open('pci.ids', 'r') as f: + full_text = f.read() + except FileNotFoundError: + response = http_get('https://pci-ids.ucw.cz/v2.2/pci.ids') + full_text = response.text + + dev_list_text = full_text[:full_text.rfind('\n\n\n')] # remove known classes + for line in dev_list_text.split('\n'): + if not line or line[0] == '#': + continue + if line[0] != '\t': + id, name = line.split(' ', maxsplit=1) + vendors.append(PciVendorModel(int(id, 16), name)) + elif line[1] != '\t': + id, name = line[1:].split(' ', maxsplit=1) + vendors[-1].devices.append(PciDeviceModel(int(id, 16), name)) + + code = """\ +// SPDX-License-Identifier: BSD-3-Clause +// https://opensource.org/license/BSD-3-Clause +// Generated from https://pci-ids.ucw.cz/v2.2/pci.ids + +#include +#include + +typedef struct FFPciDevice +{ + const uint32_t id; + const char* name; +} FFPciDevice; + +typedef struct FFPciVendor +{ + const uint32_t id; + const char* name; + const FFPciDevice* devices; + const uint32_t nDevices; +} FFPciVendor; +""" + + if keep_vendor_list: + vendors = [vendor for vendor in vendors if vendor.id in keep_vendor_list] + + for vendor in vendors: + if vendor.devices: + piece = ',\n '.join('{{ 0x{:04X}, "{}" }}'.format(device.id, device.name.replace('"', '\\"')) for device in vendor.devices) + code += f""" +// {vendor.name} +static const FFPciDevice pciDevices_{vendor.id:04X}[] = {{ + {piece}, + {{}}, +}}; +""" + + piece = ',\n '.join('{{ 0x{:04X}, "{}", {}, {} }}'.format(vendor.id, vendor.name.replace('"', '\\"'), vendor.devices and f"pciDevices_{vendor.id:04X}" or "NULL", len(vendor.devices)) for vendor in vendors) + code += f""" +const FFPciVendor ffPciVendors[] = {{ + {piece}, + {{}}, +}};""" + + print(code) + +if __name__ == '__main__': + # From + main({ + 0x106b, # Apple + 0x1002, 0x1022, # AMD + 0x8086, 0x8087, 0x03e7, # Intel + 0x0955, 0x10de, 0x12d2, # Nvidia + 0x1ed5, # MThreads + 0x5143, # Qualcomm + 0x14c3, # MTK + 0x15ad, # VMware + 0x1af4, # RedHat + 0x1ab8, # Parallel + 0x1414, # Microsoft + 0x108e, # Oracle + }) diff --git a/src/common/init.c b/src/common/init.c index 8bf6f60e11..514b9fb6af 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -191,6 +191,9 @@ void ffListFeatures(void) #if FF_HAVE_DRM "drm\n" #endif + #if FF_HAVE_DRM_AMDGPU + "drm_amdgpu\n" + #endif #if FF_HAVE_GIO "gio\n" #endif @@ -260,6 +263,9 @@ void ffListFeatures(void) #if FF_HAVE_LINUX_WIRELESS "linux/wireless\n" #endif + #if FF_HAVE_EMBEDDED_PCIIDS + "Embedded pciids\n" + #endif "" , stdout); } diff --git a/src/common/modules.c b/src/common/modules.c index 232c555f04..4e8ae69e4c 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -137,6 +137,7 @@ static FFModuleBaseInfo* T[] = { (void*) &instance.config.modules.terminalTheme, (void*) &instance.config.modules.title, (void*) &instance.config.modules.theme, + (void*) &instance.config.modules.tpm, NULL, }; diff --git a/src/common/processing_windows.c b/src/common/processing_windows.c index 03fb7cbfdb..c2d2b10fa0 100644 --- a/src/common/processing_windows.c +++ b/src/common/processing_windows.c @@ -8,6 +8,43 @@ enum { FF_PIPE_BUFSIZ = 8192 }; +static void argvToCmdline(char* const argv[], FFstrbuf* result) +{ + // From https://gist.github.com/jin-x/cdd641d98887524b091fb1f82a68717d + + FF_STRBUF_AUTO_DESTROY temp = ffStrbufCreate(); + for (int i = 0; argv[i] != NULL; i++) + { + ffStrbufSetS(&temp, argv[i]); + // Add slash (\) before double quotes (") and duplicate slashes before it + for ( + uint32_t pos = ffStrbufFirstIndexC(&temp, '"'), cnt; + pos != temp.length; + pos = ffStrbufNextIndexC(&temp, pos + cnt * 2, '"') + ) { + cnt = 1; + while (pos > 0 && temp.chars[pos - 1] == '\\') { ++cnt, --pos; } + ffStrbufInsertNC(&temp, pos, cnt, '\\'); + } + + // Add quotes around string if whitespace chars are present (with slash duplicating at the end of string) + if (ffStrbufFirstIndexS(&temp, " \t") != temp.length) + { + uint32_t pos = temp.length; + uint32_t cnt = 0; + while (pos > 0 && temp.chars[pos - 1] == '\\') { ++cnt, --pos; } + if (cnt > 0) ffStrbufAppendNC(&temp, cnt, '\\'); + ffStrbufPrependC(&temp, '"'); + ffStrbufAppendC(&temp, '"'); + } + + // Add space delimiter + if (i > 0) ffStrbufAppendC(result, ' '); + ffStrbufAppend(result, &temp); + ffStrbufClear(&temp); + } +} + const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr) { int timeout = instance.config.general.processingTimeout; @@ -55,12 +92,8 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use else siStartInfo.hStdOutput = hChildPipeWrite; - FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreateF("\"%s\"", argv[0]); - for(char* const* parg = &argv[1]; *parg; ++parg) - { - ffStrbufAppendC(&cmdline, ' '); - ffStrbufAppendS(&cmdline, *parg); - } + FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate(); + argvToCmdline(argv, &cmdline); success = CreateProcessA( NULL, // application name diff --git a/src/data/help.json b/src/data/help.json index 486c6c61f0..0d3424adbe 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1379,7 +1379,7 @@ { "long": "command-param", "desc": "Set the parameter used when starting the shell", - "remark": "Due to the difference of how OSes handle command line parameters, Windows will parse whitespaces as param separators, while *nix will not", + "remark": "If set to empty string, it will be ignored", "arg": { "type": "str", "default": "\"/c\" for Windows; \"-c\" for *nix" diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index 1de81b963b..4f3d809b67 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -1,7 +1,7 @@ #include "fastfetch.h" #include "battery.h" #include "util/apple/cf_helpers.h" -#include "detection/temps/temps_apple.h" +#include "util/apple/smc_temps.h" #include #include diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 2f073aca14..0d76871c5d 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -1,6 +1,5 @@ #include "battery.h" #include "common/io/io.h" -#include "detection/temps/temps_linux.h" #include "util/stringUtils.h" #include diff --git a/src/detection/bootmgr/bootmgr_windows.c b/src/detection/bootmgr/bootmgr_windows.c index af6199b80f..19484a7ed3 100644 --- a/src/detection/bootmgr/bootmgr_windows.c +++ b/src/detection/bootmgr/bootmgr_windows.c @@ -38,7 +38,7 @@ const char* ffDetectBootmgr(FFBootmgrResult* result) uint8_t buffer[2048]; wchar_t key[16]; - wsprintfW(key, L"Boot%04X", value); + swprintf(key, sizeof(key) / sizeof(*key), L"Boot%04X", value); uint32_t size = GetFirmwareEnvironmentVariableW(key, L"{" FF_EFI_GLOBAL_GUID L"}", buffer, sizeof(buffer)); if (size < sizeof(FFEfiLoadOption) || size == sizeof(buffer)) return "GetFirmwareEnvironmentVariableW(Boot####) failed"; diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index 9ddc00300b..eb5bd90f44 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -21,7 +21,6 @@ typedef struct FFCPUResult uint32_t frequencyBase; // GHz uint32_t frequencyMax; // GHz - uint32_t frequencyBiosLimit; // GHz FFCPUCore coreTypes[16]; // number of P cores, E cores, etc. diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index efdad9502b..b08a8b5bc1 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -1,6 +1,6 @@ #include "cpu.h" #include "common/sysctl.h" -#include "detection/temps/temps_apple.h" +#include "util/apple/smc_temps.h" #include "util/stringUtils.h" static double detectCpuTemp(const FFstrbuf* cpuName) diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 4b073f9d51..961cb8478a 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -1,6 +1,27 @@ #include "cpu.h" #include "common/sysctl.h" -#include "detection/temps/temps_bsd.h" + +static const char* detectCpuTemp(double* current) +{ + int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999); + if (temp == -999999) + return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed"; + + // In tenth of degrees Kelvin + *current = (double) temp / 10 - 273.15; + return NULL; +} + +static const char* detectThermalTemp(double* current) +{ + int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999); + if (temp == -999999) + return "ffSysctlGetInt(\"hw.acpi.thermal.tz0.temperature\") failed"; + + // In tenth of degrees Kelvin + *current = (double) temp / 10 - 273.15; + return NULL; +} const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { @@ -46,8 +67,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if (options->temp) { - if (ffDetectCpuTemp(&cpu->temperature) != NULL) - ffDetectThermalTemp(&cpu->temperature); + if (detectCpuTemp(&cpu->temperature) != NULL) + detectThermalTemp(&cpu->temperature); } return NULL; diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 4dc9c38010..ffc6d835dc 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -2,13 +2,85 @@ #include "common/io/io.h" #include "common/processing.h" #include "common/properties.h" -#include "detection/temps/temps_linux.h" #include "util/mallocHelper.h" #include "util/stringUtils.h" #include #include #include +#include + +static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer) +{ + //https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface + uint32_t dirLength = dir->length; + ffStrbufAppendS(dir, "temp1_input"); + + if(!ffReadFileBuffer(dir->chars, buffer)) + { + // Some badly implemented system put temp file in /hwmonN/device + ffStrbufSubstrBefore(dir, dirLength); + ffStrbufAppendS(dir, "device/"); + dirLength = dir->length; + ffStrbufAppendS(dir, "temp1_input"); + + if(!ffReadFileBuffer(dir->chars, buffer)) + return 0.0/0.0; + } + + ffStrbufSubstrBefore(dir, dirLength); + + double value = ffStrbufToDouble(buffer);// millidegree Celsius + + if(value != value) + return 0.0/0.0; + + ffStrbufAppendS(dir, "name"); + if (!ffReadFileBuffer(dir->chars, buffer)) + return 0.0/0.0; + + ffStrbufTrimRightSpace(buffer); + + if( + ffStrbufContainS(buffer, "cpu") || + ffStrbufEqualS(buffer, "k10temp") || // AMD + ffStrbufEqualS(buffer, "coretemp") // Intel + ) return value / 1000.; + + return false; +} + +static double detectCPUTemp(void) +{ + FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64); + ffStrbufAppendS(&baseDir, "/sys/class/hwmon/"); + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + + uint32_t baseDirLength = baseDir.length; + + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); + if(dirp == NULL) + return 0.0/0.0; + + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + if(entry->d_name[0] == '.') + continue; + + ffStrbufAppendS(&baseDir, entry->d_name); + ffStrbufAppendC(&baseDir, '/'); + + double result = parseHwmonDir(&baseDir, &buffer); + if (result == result) + return result; + + ffStrbufSubstrBefore(&baseDir, baseDirLength); + } + + return 0.0/0.0; +} #ifdef __ANDROID__ #include "common/settings.h" @@ -253,18 +325,25 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) if (ffStrStartsWith(entry->d_name, "policy") && ffCharIsDigit(entry->d_name[strlen("policy")])) { ffStrbufAppendS(&path, entry->d_name); + + uint32_t fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer); + if (fmax == 0) continue; + + if (cpu->frequencyMax >= fmax) + { + if (!options->showPeCoreCount) + { + ffStrbufSubstrBefore(&path, baseLen); + continue; + } + } + else + cpu->frequencyMax = fmax; + uint32_t fbase = getFrequency(&path, "/base_frequency", NULL, &buffer); if (fbase > 0) cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase; - uint32_t fbioslimit = getFrequency(&path, "/bios_limit", NULL, &buffer); - if (fbioslimit > 0) - cpu->frequencyBiosLimit = cpu->frequencyBiosLimit > fbioslimit ? cpu->frequencyBiosLimit : fbioslimit; - - uint32_t fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer); - if (fmax > 0) - cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax; - if (options->showPeCoreCount) { uint32_t freq = fbase == 0 ? fmax : fbase; // seems base frequencies are more stable @@ -281,22 +360,6 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) return true; } -static double detectCPUTemp(void) -{ - const FFlist* tempsResult = ffDetectTemps(); - - FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult) - { - if( - ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length || - ffStrbufEqualS(&value->name, "k10temp") || - ffStrbufEqualS(&value->name, "coretemp") - ) return value->value; - } - - return FF_CPU_TEMP_UNSET; -} - FF_MAYBE_UNUSED static void parseIsa(FFstrbuf* cpuIsa) { // Always use the last part of the ISA string. Ref: #590 #1204 diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 411ffe6f79..7479ff6d1c 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -1,5 +1,4 @@ #include "cpu.h" -#include "detection/temps/temps_windows.h" #include "util/windows/registry.h" #include "util/windows/nt.h" #include "util/mallocHelper.h" @@ -160,6 +159,8 @@ static const char* detectCoreTypes(FFCPUResult* cpu) return NULL; } +const char* detectThermalTemp(double* current, double* critical); + const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { detectNCores(cpu); @@ -175,7 +176,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) detectMaxSpeedBySmbios(cpu); if(options->temp) - ffDetectSmbiosTemp(&cpu->temperature, NULL); + detectThermalTemp(&cpu->temperature, NULL); return NULL; } diff --git a/src/detection/temps/temps_windows.cpp b/src/detection/cpu/cpu_windows.cpp similarity index 90% rename from src/detection/temps/temps_windows.cpp rename to src/detection/cpu/cpu_windows.cpp index ac9fccab61..4a961d4c55 100644 --- a/src/detection/temps/temps_windows.cpp +++ b/src/detection/cpu/cpu_windows.cpp @@ -1,11 +1,7 @@ -extern "C" -{ -#include "temps_windows.h" -} #include "util/windows/wmi.hpp" extern "C" -const char* ffDetectSmbiosTemp(double* current, double* critical) +const char* detectThermalTemp(double* current, double* critical) { // Requires Administrator privileges // https://wutils.com/wmi/root/wmi/msacpi_thermalzonetemperature/#properties diff --git a/src/detection/cursor/cursor_apple.m b/src/detection/cursor/cursor_apple.m index 40d4b90c93..29187e11de 100644 --- a/src/detection/cursor/cursor_apple.m +++ b/src/detection/cursor/cursor_apple.m @@ -4,10 +4,10 @@ static void appendColor(FFstrbuf* str, NSDictionary* color) { - int r = (int) (((NSNumber*) [color valueForKey:@"red"]).doubleValue * 255); - int g = (int) (((NSNumber*) [color valueForKey:@"green"]).doubleValue * 255); - int b = (int) (((NSNumber*) [color valueForKey:@"blue"]).doubleValue * 255); - int a = (int) (((NSNumber*) [color valueForKey:@"alpha"]).doubleValue * 255); + int r = (int) (((NSNumber*) color[@"red"]).doubleValue * 255); + int g = (int) (((NSNumber*) color[@"green"]).doubleValue * 255); + int b = (int) (((NSNumber*) color[@"blue"]).doubleValue * 255); + int a = (int) (((NSNumber*) color[@"alpha"]).doubleValue * 255); if (r == 255 && g == 255 && b == 255 && a == 255) ffStrbufAppendS(str, "White"); @@ -32,19 +32,19 @@ void ffDetectCursor(FFCursorResult* result) NSDictionary* color; ffStrbufAppendS(&result->theme, "Fill - "); - if ((color = [dict valueForKey:@"cursorFill"])) + if ((color = dict[@"cursorFill"])) appendColor(&result->theme, color); else ffStrbufAppendS(&result->theme, "Black"); ffStrbufAppendS(&result->theme, ", Outline - "); - if ((color = [dict valueForKey:@"cursorOutline"])) + if ((color = dict[@"cursorOutline"])) appendColor(&result->theme, color); else ffStrbufAppendS(&result->theme, "White"); - NSNumber* mouseDriverCursorSize = [dict valueForKey:@"mouseDriverCursorSize"]; + NSNumber* mouseDriverCursorSize = dict[@"mouseDriverCursorSize"]; if (mouseDriverCursorSize) ffStrbufAppendF(&result->size, "%d", (int) (mouseDriverCursorSize.doubleValue * 32)); else diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index 1533b4990b..48949266d6 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -28,13 +28,19 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) ffStrbufAppendS(&drmDir, entry->d_name); uint32_t drmDirWithDnameLength = drmDir.length; - ffStrbufAppendS(&drmDir, "/status"); - char status = 'd'; // disconnected - ffReadFileData(drmDir.chars, sizeof(status), &status); - if (status != 'c') // connected - { + char buf; + ffStrbufAppendS(&drmDir, "/enabled"); + if (!ffReadFileData(drmDir.chars, sizeof(buf), &buf) || buf != 'e') { + /* read failed or enabled != "enabled" */ + ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); + ffStrbufAppendS(&drmDir, "/status"); + buf = 'd'; + ffReadFileData(drmDir.chars, sizeof(buf), &buf); + if (buf != 'c') { + /* read failed or status != "connected" */ ffStrbufSubstrBefore(&drmDir, drmDirLength); continue; + } } unsigned width = 0, height = 0, physicalWidth = 0, physicalHeight = 0; @@ -251,7 +257,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) if (!conn) continue; - if (conn->connection == DRM_MODE_CONNECTED) + if (conn->connection != DRM_MODE_DISCONNECTED) { drmModeEncoder* encoder = ffdrmModeGetEncoder(fd, conn->encoder_id); uint32_t width = 0, height = 0, refreshRate = 0; diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index d1831f92a9..a863760cd1 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -55,6 +55,7 @@ const char* detectByOpenGL(FFlist* gpus) ffStrbufInitMove(&gpu->name, &result.renderer); ffStrbufInitMove(&gpu->driver, &result.vendor); ffStrbufInitF(&gpu->platformApi, "OpenGL %s", result.version.chars); + gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index a914d5c2d4..3edd78fc16 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -7,6 +7,7 @@ #define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) #define FF_GPU_FREQUENCY_UNSET 0 #define FF_GPU_CORE_USAGE_UNSET (0/0.0) +#define FF_GPU_INDEX_UNSET ((uint32_t)-1) extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; @@ -27,6 +28,7 @@ typedef struct FFGPUMemory typedef struct FFGPUResult { + uint32_t index; FFGPUType type; FFstrbuf vendor; FFstrbuf name; @@ -38,7 +40,7 @@ typedef struct FFGPUResult uint32_t frequency; // Maximum time clock frequency in MHz FFGPUMemory dedicated; FFGPUMemory shared; - uint64_t deviceId; // Used internally, may be uninitialized + uint64_t deviceId; } FFGPUResult; const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result); @@ -47,5 +49,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus); const char* ffGetGPUVendorString(unsigned vendorId); #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu, FFstrbuf* coreName); +void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu); #endif diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c index 1510019ea0..72e1d9fc0c 100644 --- a/src/detection/gpu/gpu_amd.c +++ b/src/detection/gpu/gpu_amd.c @@ -65,5 +65,11 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu if (result.type) *result.type = device->isAPU ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + if (result.index) + *result.type = (uint32_t) device->adlAdapterIndex; + + if (result.name) + ffStrbufSetS(result.name, device->adapterString); + return NULL; } diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 1190a63676..16f9f9c0cb 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -1,12 +1,13 @@ #include "gpu.h" #include "common/library.h" #include "detection/cpu/cpu.h" -#include "detection/temps/temps_apple.h" #include "util/apple/cf_helpers.h" +#include "util/apple/smc_temps.h" #include const char* ffGpuDetectMetal(FFlist* gpus); +const char* ffGpuDetectDriverVersion(FFlist* gpus); static double detectGpuTemp(const FFstrbuf* gpuName) { @@ -185,5 +186,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) } ffGpuDetectMetal(gpus); + if (instance.config.general.detectVersion) + ffGpuDetectDriverVersion(gpus); return NULL; } diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index e5b6bebf60..95e4c30587 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -1,6 +1,7 @@ #include "gpu.h" #import +#import #ifndef MAC_OS_VERSION_13_0 #define MTLGPUFamilyMetal3 ((MTLGPUFamily) 5001) @@ -10,6 +11,28 @@ #define MTLFeatureSet_macOS_GPUFamily2_v1 ((MTLFeatureSet) 10005) #endif +const char* ffGpuDetectDriverVersion(FFlist* gpus) +{ + if (@available(macOS 10.7, *)) + { + NSMutableArray* arr = NSMutableArray.new; + FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) + [arr addObject:@(x->driver.chars)]; + + NSDictionary* dict = CFBridgingRelease(KextManagerCopyLoadedKextInfo((__bridge CFArrayRef)arr, (__bridge CFArrayRef)@[@"CFBundleVersion"])); + FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) + { + NSString* version = dict[@(x->driver.chars)][@"CFBundleVersion"]; + if (version) + { + ffStrbufAppendC(&x->driver, ' '); + ffStrbufAppendS(&x->driver, version.UTF8String); + } + } + } + return "Unsupported macOS version"; +} + const char* ffGpuDetectMetal(FFlist* gpus) { if (@available(macOS 10.13, *)) @@ -42,7 +65,8 @@ else if ([device supportsFamily:MTLGPUFamilyCommon1]) ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1"); - gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + gpu->type = device.location == MTLDeviceLocationBuiltIn ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + gpu->index = (uint32_t) device.locationNumber; #endif } return NULL; diff --git a/src/detection/gpu/gpu_asahi.h b/src/detection/gpu/gpu_asahi.h new file mode 100644 index 0000000000..b6cf9b65b4 --- /dev/null +++ b/src/detection/gpu/gpu_asahi.h @@ -0,0 +1,91 @@ +#if __aarch64__ && FF_HAVE_DRM + +#include +#include +#include + +#if __has_include() + +#include + +#else + +// https://github.com/AsahiLinux/linux/blob/asahi/include/uapi/drm/asahi_drm.h +/* SPDX-License-Identifier: MIT */ +/* Copyright (C) The Asahi Linux Contributors */ + +#define DRM_ASAHI_UNSTABLE_UABI_VERSION 10011 + +#define DRM_ASAHI_GET_PARAMS 0x00 +#define DRM_ASAHI_MAX_CLUSTERS 32 +struct drm_asahi_params_global +{ + __u32 unstable_uabi_version; + __u32 pad0; + + __u64 feat_compat; + __u64 feat_incompat; + + __u32 gpu_generation; + __u32 gpu_variant; + __u32 gpu_revision; + __u32 chip_id; + + __u32 num_dies; + __u32 num_clusters_total; + __u32 num_cores_per_cluster; + __u32 num_frags_per_cluster; + __u32 num_gps_per_cluster; + __u32 num_cores_total_active; + __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS]; + + __u32 vm_page_size; + __u32 pad1; + __u64 vm_user_start; + __u64 vm_user_end; + __u64 vm_usc_start; + __u64 vm_usc_end; + __u64 vm_kernel_min_size; + + __u32 max_syncs_per_submission; + __u32 max_commands_per_submission; + __u32 max_commands_in_flight; + __u32 max_attachments; + + __u32 timer_frequency_hz; + __u32 min_frequency_khz; + __u32 max_frequency_khz; + __u32 max_power_mw; + + __u32 result_render_size; + __u32 result_compute_size; + + __u32 firmware_version[4]; +}; + +struct drm_asahi_get_params +{ + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** @param: Parameter group to fetch (MBZ) */ + __u32 param_group; + + /** @pad: MBZ */ + __u32 pad; + + /** @value: User pointer to write parameter struct */ + __u64 pointer; + + /** @value: Size of user buffer, max size supported on return */ + __u64 size; +}; + +enum +{ + DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOWR(DRM_COMMAND_BASE + DRM_ASAHI_GET_PARAMS, struct drm_asahi_get_params), +}; + +#endif // __has_include + +#endif // FF_HAVE_DRM diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 6d75ed9c13..99195af20a 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -8,20 +8,6 @@ #include #include #include -#include - -static bool loadPciIds(FFstrbuf* pciids) -{ - // https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h - - ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", pciids); - if (pciids->length > 0) return true; - - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", pciids); - if (pciids->length > 0) return true; - - return false; -} const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) { @@ -45,8 +31,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) if (pcio.status == PCI_GETCONF_ERROR) return "ioctl(fd, PCIOCGETCONF, &pc) returned error"; - FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate(); - for (uint32_t i = 0; i < pcio.num_matches; ++i) { struct pci_conf* pc = &confs[i]; @@ -56,29 +40,15 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) ffStrbufInit(&gpu->name); ffStrbufInitS(&gpu->driver, pc->pd_name); ffStrbufInit(&gpu->platformApi); + 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 = ((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->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_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); - } - - FF_STRBUF_AUTO_DESTROY coreName = ffStrbufCreate(); - if (gpu->name.length == 0) - { - if (pciids.length == 0) - loadPciIds(&pciids); - ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu, &coreName); - } - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) { ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { @@ -90,16 +60,29 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) .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 = options->driverSpecific ? &gpu->name : NULL, + .name = &gpu->name, }, "libnvidia-ml.so"); } + if (gpu->name.length == 0) + { + 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) + 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) @@ -116,12 +99,8 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) } else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) { - if ((coreName.chars[0] == 'D' || coreName.chars[0] == 'S') && - coreName.chars[1] == 'G' && - ffCharIsDigit(coreName.chars[2])) - gpu->type = FF_GPU_TYPE_DISCRETE; // DG1 / DG2 / SG1 - else - gpu->type = FF_GPU_TYPE_INTEGRATED; + // 0000:00:02.0 is reserved for Intel integrated graphics + gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; } } } diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 945b92cff6..989ef6093f 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -37,6 +37,7 @@ typedef struct FFGpuDriverCondition // detect x if not NULL typedef struct FFGpuDriverResult { + uint32_t* index; double* temp; FFGPUMemory* memory; uint32_t* coreCount; diff --git a/src/detection/gpu/gpu_intel.c b/src/detection/gpu/gpu_intel.c index 1b4da5ed81..ffa04ccb8d 100644 --- a/src/detection/gpu/gpu_intel.c +++ b/src/detection/gpu/gpu_intel.c @@ -195,5 +195,8 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe } } + if (result.name) + ffStrbufSetS(result.name, properties.name); + return NULL; } diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index cb038989ec..2862f73c0a 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -1,100 +1,33 @@ #include "detection/gpu/gpu.h" #include "detection/vulkan/vulkan.h" -#include "detection/temps/temps_linux.h" #include "detection/cpu/cpu.h" #include "detection/gpu/gpu_driver_specific.h" #include "common/io/io.h" +#include "common/library.h" #include "common/properties.h" #include "util/stringUtils.h" +#include "util/mallocHelper.h" #include -#if __aarch64__ && FF_HAVE_DRM - #include +#ifdef FF_HAVE_DRM_AMDGPU + #include + #include #include - #include - - // https://github.com/AsahiLinux/linux/blob/asahi/include/uapi/drm/asahi_drm.h - /* SPDX-License-Identifier: MIT */ - /* Copyright (C) The Asahi Linux Contributors */ - - #define DRM_ASAHI_UNSTABLE_UABI_VERSION 10011 - - #define DRM_ASAHI_GET_PARAMS 0x00 - #define DRM_ASAHI_MAX_CLUSTERS 32 - struct drm_asahi_params_global - { - __u32 unstable_uabi_version; - __u32 pad0; - - __u64 feat_compat; - __u64 feat_incompat; - - __u32 gpu_generation; - __u32 gpu_variant; - __u32 gpu_revision; - __u32 chip_id; - - __u32 num_dies; - __u32 num_clusters_total; - __u32 num_cores_per_cluster; - __u32 num_frags_per_cluster; - __u32 num_gps_per_cluster; - __u32 num_cores_total_active; - __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS]; - - __u32 vm_page_size; - __u32 pad1; - __u64 vm_user_start; - __u64 vm_user_end; - __u64 vm_usc_start; - __u64 vm_usc_end; - __u64 vm_kernel_min_size; - - __u32 max_syncs_per_submission; - __u32 max_commands_per_submission; - __u32 max_commands_in_flight; - __u32 max_attachments; - - __u32 timer_frequency_hz; - __u32 min_frequency_khz; - __u32 max_frequency_khz; - __u32 max_power_mw; - - __u32 result_render_size; - __u32 result_compute_size; - - __u32 firmware_version[4]; - }; - - struct drm_asahi_get_params - { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** @param: Parameter group to fetch (MBZ) */ - __u32 param_group; - - /** @pad: MBZ */ - __u32 pad; - - /** @value: User pointer to write parameter struct */ - __u64 pointer; - - /** @value: Size of user buffer, max size supported on return */ - __u64 size; - }; +#endif - enum - { - DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOWR(DRM_COMMAND_BASE + DRM_ASAHI_GET_PARAMS, struct drm_asahi_get_params), - }; +#ifdef FF_HAVE_DRM + #include "intel_drm.h" + #include + #include #endif +#include "gpu_asahi.h" + #define FF_STR_INDIR(x) #x #define FF_STR(x) FF_STR_INDIR(x) -static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey) +static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey) { uint32_t pciDirLength = pciDir->length; ffStrbufAppendS(pciDir, "/driver"); @@ -106,17 +39,17 @@ static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer if (slash) { slash++; - ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash); + ffStrbufSetNS(result, (uint32_t) (resultLength - (slash - pathBuf)), slash); } - if (ffStrbufEqualS(&gpu->driver, "nvidia")) + if (ffStrbufEqualS(result, "nvidia")) { if (ffReadFileBuffer("/proc/driver/nvidia/version", buffer)) { if (ffStrbufContainS(buffer, " Open ")) - ffStrbufAppendS(&gpu->driver, " (open source)"); + ffStrbufAppendS(result, " (open source)"); else - ffStrbufAppendS(&gpu->driver, " (proprietary)"); + ffStrbufAppendS(result, " (proprietary)"); } } @@ -126,18 +59,18 @@ static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer if (ffReadFileBuffer(pciDir->chars, buffer)) { ffStrbufTrimRightSpace(buffer); - ffStrbufAppendC(&gpu->driver, ' '); - ffStrbufAppend(&gpu->driver, buffer); + ffStrbufAppendC(result, ' '); + ffStrbufAppend(result, buffer); } - else if (ffStrbufEqualS(&gpu->driver, "zx")) + else if (ffStrbufEqualS(result, "zx")) { ffStrbufSubstrBefore(pciDir, pciDirLength); ffStrbufAppendS(pciDir, "/zx_info/driver_version"); if (ffReadFileBuffer(pciDir->chars, buffer)) { ffStrbufTrimRightSpace(buffer); - ffStrbufAppendC(&gpu->driver, ' '); - ffStrbufAppend(&gpu->driver, buffer); + ffStrbufAppendC(result, ' '); + ffStrbufAppend(result, buffer); } } } @@ -145,6 +78,98 @@ static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer return true; } +static const char* drmFindRenderFromCard(const char* drmCardKey, FFstrbuf* result) +{ + char path[PATH_MAX]; + sprintf(path, "/sys/class/drm/%s/device/drm", drmCardKey); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path); + if (!dirp) return "Failed to open `/sys/class/drm/{drmCardKey}/device/drm`"; + + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) + { + if (ffStrStartsWith(entry->d_name, "render")) + { + ffStrbufSetS(result, "/dev/dri/"); + ffStrbufAppendS(result, entry->d_name); + return NULL; + } + } + return "Failed to find render device"; +} + +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) + + { + const char* error = drmFindRenderFromCard(drmKey, buffer); + if (error) return error; + } + 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; + + 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"; + #endif +} + static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) { // https://www.kernel.org/doc/html/v5.10/gpu/amdgpu.html#mem-info-vis-vram-total @@ -186,6 +211,11 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, 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, 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))) @@ -199,61 +229,174 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, } } -static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const FFstrbuf* coreName) +static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey) { // Works for Intel GPUs // https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/ - if ((coreName->chars[0] == 'D' || coreName->chars[0] == 'S') && - coreName->chars[1] == 'G' && - ffCharIsDigit(coreName->chars[2])) - gpu->type = FF_GPU_TYPE_DISCRETE; // DG1 / DG2 / SG1 - else - gpu->type = FF_GPU_TYPE_INTEGRATED; + // 0000:00:02.0 is reserved for Intel integrated graphics + gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + + if (!drmKey) return; if (ffStrbufEqualS(&gpu->driver, "xe")) - { ffStrbufAppendS(pciDir, "/tile0/gt0/freq0/max_freq"); - } else - { - ffStrbufAppendS(pciDir, "/drm/"); - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars); - if (!dirp) return; - struct dirent* entry; - while ((entry = readdir(dirp)) != NULL) - { - if (ffStrStartsWith(entry->d_name, "card")) break; - } - if (!entry) return; - ffStrbufAppendS(pciDir, entry->d_name); - ffStrbufAppendS(pciDir, "/gt_max_freq_mhz"); - } + ffStrbufAppendF(pciDir, "/drm/%s/gt_max_freq_mhz", drmKey); if (ffReadFileBuffer(pciDir->chars, buffer)) gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0); } -static bool loadPciIds(FFstrbuf* pciids) +static inline int popcountBytes(uint8_t* bytes, uint32_t length) { - #ifdef FF_CUSTOM_PCI_IDS_PATH - - ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), pciids); - if (pciids->length > 0) return true; - - #else - - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids); - if (pciids->length > 0) return true; + 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; +} - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", pciids); // debian? - if (pciids->length > 0) return true; +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); + if (fd < 0) return "Failed to open drm device"; - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids); - if (pciids->length > 0) return true; + if (ffStrbufEqualS(&gpu->driver, "xe")) + { + { + struct drm_xe_device_query query = { + .extensions = 0, + .query = DRM_XE_DEVICE_QUERY_GT_TOPOLOGY, + .size = 0, + .data = 0, + }; + 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; + } + } + } + } + } + } + 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; + #else + return "Fastfetch is not compiled with drm support"; #endif - - return false; } static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey) @@ -262,7 +405,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf uint32_t vendorId, deviceId, subVendorId, subDeviceId; uint8_t classId, subclassId; if (sscanf(buffer->chars + strlen("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) - return "Invalid modalias string"; + return "Failed to parse pci modalias"; if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) return "Not a GPU device"; @@ -295,61 +438,78 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInit(&gpu->platformApi); + gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_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 = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc; + gpu->deviceId = (pciDomain * 100000ull) + (pciBus * 1000ull) + (pciDevice * 10ull) + pciFunc; gpu->frequency = FF_GPU_FREQUENCY_UNSET; - if (drmKey) ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey); - - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) + char drmKeyBuffer[8]; + if (!drmKey) { - ffStrbufAppendS(deviceDir, "/revision"); - if (ffReadFileBuffer(deviceDir->chars, buffer)) + ffStrbufAppendS(deviceDir, "/drm"); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(deviceDir->chars); + if (dirp) { - char* pend; - uint64_t revision = strtoul(buffer->chars, &pend, 16); - if (pend != buffer->chars) + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) { - char query[32]; - snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision); - #ifdef FF_CUSTOM_AMDGPU_IDS_PATH - ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name); - #else - ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); - #endif + if (ffStrStartsWith(entry->d_name, "card")) + { + strncpy(drmKeyBuffer, entry->d_name, sizeof(drmKeyBuffer) - 1); + drmKeyBuffer[sizeof(drmKeyBuffer) - 1] = '\0'; + drmKey = drmKeyBuffer; + break; + } } } ffStrbufSubstrBefore(deviceDir, drmDirPathLength); } - FF_STRBUF_AUTO_DESTROY coreName = ffStrbufCreate(); - if (gpu->name.length == 0) - { - static FFstrbuf pciids; - if (pciids.chars == NULL) - { - ffStrbufInit(&pciids); - loadPciIds(&pciids); - } - ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu, &coreName); - } + if (drmKey) ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey); - pciDetectDriver(gpu, deviceDir, buffer, drmKey); + pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey); ffStrbufSubstrBefore(deviceDir, drmDirPathLength); if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { - pciDetectAmdSpecific(options, gpu, deviceDir, buffer); - ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + bool ok = false; + if (drmKey && options->driverSpecific) + ok = drmDetectAmdSpecific(options, gpu, drmKey, buffer) == NULL; + + if (!ok) + { + pciDetectAmdSpecific(options, gpu, deviceDir, buffer); + ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + + ffStrbufAppendS(deviceDir, "/revision"); + if (ffReadFileBuffer(deviceDir->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); + #ifdef FF_CUSTOM_AMDGPU_IDS_PATH + ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name); + #else + ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); + #endif + } + } + ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + } } else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) { - pciDetectIntelSpecific(gpu, deviceDir, buffer, &coreName); + pciDetectIntelSpecific(gpu, deviceDir, buffer, drmKey); ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + if (options->driverSpecific && drmKey) + drmDetectIntelSpecific(gpu, drmKey, buffer); } else { @@ -366,13 +526,14 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf .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 = options->driverSpecific ? &gpu->name : NULL, + .name = &gpu->name, }, soName); } @@ -393,33 +554,19 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf } } + if (gpu->name.length == 0) + ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); + return NULL; } #if __aarch64__ -FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey) +FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, const char* name, FFstrbuf* buffer, const char* drmKey) { - uint32_t index = ffStrbufFirstIndexS(buffer, "apple,agx-t"); - if (index == buffer->length) return "display-subsystem?"; - index += (uint32_t) strlen("apple,agx-t"); - - FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - gpu->deviceId = strtoul(buffer->chars + index, NULL, 10); - ffStrbufInitStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId)); - if (!gpu->name.length) - ffStrbufAppendF(&gpu->name, "Apple Silicon T%u", (uint32_t) gpu->deviceId); - ffStrbufInitStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); - ffStrbufInit(&gpu->driver); - ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey); - 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_INTEGRATED; - gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; - gpu->frequency = FF_GPU_FREQUENCY_UNSET; - - pciDetectDriver(gpu, drmDir, buffer, drmKey); + if (sscanf(name, "agx-t%lu", &gpu->deviceId) == 1) + ffStrbufSetStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId)); + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); #if FF_HAVE_DRM ffStrbufSetS(buffer, "/dev/dri/"); @@ -428,12 +575,14 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F if (fd >= 0) { struct drm_asahi_params_global paramsGlobal = {}; - if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params){ + if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params) { .param_group = DRM_ASAHI_GET_PARAMS, .pointer = (uint64_t) ¶msGlobal, .size = sizeof(paramsGlobal), }) >= 0) { + ffStrbufAppendF(&gpu->driver, " %u", paramsGlobal.unstable_uabi_version); + // FIXME: They will introduce ABI breaking changes. Always check the latest version // https://www.reddit.com/r/AsahiLinux/comments/1ei2qiv/comment/lgm0v5s/ if (paramsGlobal.unstable_uabi_version == DRM_ASAHI_UNSTABLE_UABI_VERSION) @@ -441,6 +590,29 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F gpu->coreCount = (int) paramsGlobal.num_cores_total_active; 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); + } } } } @@ -450,6 +622,51 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F } #endif +static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey) +{ + char compatible[256]; // vendor,model-name + if (sscanf(buffer->chars + strlen("of:"), "NgpuT%*[^C]C%256[^C]", compatible) != 1) + return "Failed to parse of modalias or not a GPU device"; + + char* name = strchr(compatible, ','); + if (name) + { + *name = '\0'; + ++name; + } + + FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + gpu->index = FF_GPU_INDEX_UNSET; + gpu->deviceId = 0; + ffStrbufInit(&gpu->name); + ffStrbufInit(&gpu->vendor); + ffStrbufInit(&gpu->driver); + ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey); + 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_INTEGRATED; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; + + pciDetectDriver(&gpu->driver, drmDir, buffer, drmKey); + + #ifdef __aarch64__ + if (ffStrbufEqualS(&gpu->driver, "asahi")) + drmDetectAsahiSpecific(gpu, name, buffer, drmKey); + #endif + + if (!gpu->name.length) + ffStrbufSetS(&gpu->name, name ? name : compatible); + if (!gpu->vendor.length && name) + { + compatible[0] = (char) toupper(compatible[0]); + ffStrbufSetS(&gpu->vendor, compatible); + } + + return NULL; +} + static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus) { FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64); @@ -478,10 +695,8 @@ static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus) if (ffStrbufStartsWithS(&buffer, "pci:")) detectPci(options, gpus, &buffer, &drmDir, entry->d_name); - #ifdef __aarch64__ else if (ffStrbufStartsWithS(&buffer, "of:")) - detectAsahi(gpus, &buffer, &drmDir, entry->d_name); - #endif + detectOf(gpus, &buffer, &drmDir, entry->d_name); ffStrbufSubstrBefore(&drmDir, drmDirLength); } diff --git a/src/detection/gpu/gpu_mthreads.c b/src/detection/gpu/gpu_mthreads.c index ac0ffa07b5..80164320d1 100644 --- a/src/detection/gpu/gpu_mthreads.c +++ b/src/detection/gpu/gpu_mthreads.c @@ -30,7 +30,7 @@ struct FFMtmlData MtmlSystem *sys; } mtmlData; -static void shutdownMtml() +FF_MAYBE_UNUSED static void shutdownMtml(void) { mtmlData.ffmtmlLibraryShutDown(mtmlData.lib); } @@ -134,6 +134,13 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive } } + if (result.index) + { + unsigned int value; + if (mtmlData.ffmtmlDeviceGetIndex(device, &value) == MTML_SUCCESS) + *result.index = value; + } + if (result.temp) { MtmlGpu *gpu = NULL; diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index fdd88f6ce2..c2cc33d1d5 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -14,6 +14,7 @@ struct FFNvmlData { FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo) FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates) FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand) + FF_LIBRARY_SYMBOL(nvmlDeviceGetIndex) FF_LIBRARY_SYMBOL(nvmlDeviceGetName) bool inited; @@ -39,6 +40,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetIndex) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetName) if (ffnvmlInit_v2() != NVML_SUCCESS) @@ -105,6 +107,14 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR } } + if (result.index) + { + unsigned int value; + if (nvmlData.ffnvmlDeviceGetIndex(device, &value) == NVML_SUCCESS) + *result.index = value; + } + + if (result.temp) { uint32_t value; diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c index de81f9b60c..5397f0fe6e 100644 --- a/src/detection/gpu/gpu_pci.c +++ b/src/detection/gpu/gpu_pci.c @@ -1,6 +1,54 @@ #include "gpu.h" +#include "common/io/io.h" -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu, FFstrbuf* coreName) +#include +#ifdef __FreeBSD__ +#include +#endif + +#if FF_HAVE_EMBEDDED_PCIIDS +#include "fastfetch_pciids.c.inc" +#endif + +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + +static const FFstrbuf* loadPciIds() +{ + static FFstrbuf pciids; + + if (pciids.chars) return &pciids; + ffStrbufInit(&pciids); + + #ifdef FF_CUSTOM_PCI_IDS_PATH + + ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), &pciids); + + #else // FF_CUSTOM_PCI_IDS_PATH + + #if __linux__ + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", &pciids); + if (pciids.length == 0) + { + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", &pciids); // debian? + if (pciids.length == 0) + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", &pciids); + } + #elif __FreeBSD__ + // https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h + ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids); + if (pciids.length == 0) + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", &pciids); + #elif __sun + ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids); + #endif + + #endif // FF_CUSTOM_PCI_IDS_PATH + + return &pciids; +} + +static void parsePciIdsFile(const FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) { if (content->length) { @@ -52,11 +100,6 @@ void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint { openingBracket++; ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket); - if (coreName) - { - ffStrbufSetNS(coreName, (uint32_t) (openingBracket - start) - 1, start); - ffStrbufTrimRight(coreName, ' '); - } } } if (!gpu->name.length) @@ -79,3 +122,66 @@ void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr); } } + +#if FF_HAVE_EMBEDDED_PCIIDS +static inline int pciDeviceCmp(const uint16_t* key, const FFPciDevice* element) +{ + return (int) *key - (int) element->id; +} + +static bool loadPciidsInc(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) +{ + for (const FFPciVendor* pvendor = ffPciVendors; pvendor->name; pvendor++) + { + if (pvendor->id != vendor) continue; + + if (!gpu->vendor.length) + ffStrbufSetS(&gpu->vendor, pvendor->name); + + const FFPciDevice* pdevice = (const FFPciDevice*) bsearch(&device, pvendor->devices, pvendor->nDevices, sizeof(FFPciDevice), (void*) pciDeviceCmp); + + if (pdevice) + { + uint32_t nameLen = (uint32_t) strlen(pdevice->name); + const char* closingBracket = pdevice->name + nameLen - 1; + if (*closingBracket == ']') + { + const char* openingBracket = memrchr(pdevice->name, '[', nameLen - 1); + if (openingBracket) + { + openingBracket++; + ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket); + } + } + if (!gpu->name.length) + ffStrbufSetNS(&gpu->name, nameLen, pdevice->name); + return true; + } + + 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); + } + return true; + } + return false; +} +#endif + +void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) +{ + #if FF_HAVE_EMBEDDED_PCIIDS + bool ok = loadPciidsInc(subclass, vendor, device, gpu); + if (ok) return; + #endif + return parsePciIdsFile(loadPciIds(), subclass, vendor, device, gpu); +} diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c index 442d87ce80..6e8d19460c 100644 --- a/src/detection/gpu/gpu_sunos.c +++ b/src/detection/gpu/gpu_sunos.c @@ -20,8 +20,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (!ffStrbufStartsWithS(&buffer, "\npci ")) return "Invalid scanpci result"; - FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate(); - // pci bus 0x0000 cardnum 0x00 function 0x00: vendor 0x1414 device 0x008e // Device unknown // CardVendor 0x0000 card 0x0000 (Card unknown) @@ -57,6 +55,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInit(&gpu->platformApi); + 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; @@ -74,9 +73,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (gpu->name.length == 0) { - if (pciids.length == 0) - ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids); - ffGPUParsePciIds(&pciids, (uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu, NULL); + ffGPUFillVendorAndName((uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu); } } diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 6ad1cd2e81..4e6939be18 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -38,6 +38,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInitStatic(&gpu->platformApi, "SetupAPI"); + 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; @@ -46,9 +47,18 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->deviceId = 0; gpu->frequency = FF_GPU_FREQUENCY_UNSET; + uint32_t pciBus, pciAddr, pciDev, pciFunc; + if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) && + SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL)) + { + pciDev = (pciAddr >> 16) & 0xFFFF; + pciFunc = pciAddr & 0xFFFF; + gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc; + } + wchar_t buffer[256]; - if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) - ffStrbufSetWS(&gpu->name, buffer); + + uint64_t adapterLuid = 0; FF_HKEY_AUTO_DESTROY hVideoIdKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (!hVideoIdKey) continue; @@ -60,9 +70,19 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) { + uint32_t vendorId = 0; + if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId) + ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); + + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) + gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + uint64_t dedicatedVideoMemory = 0; if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL)) - gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + { + if (gpu->type == FF_GPU_TYPE_UNKNOWN) + gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + } uint64_t dedicatedSystemMemory, sharedSystemMemory; if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) && @@ -72,7 +92,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->shared.total = sharedSystemMemory; } - ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL); + ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL); uint32_t featureLevel = 0; if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) @@ -90,10 +110,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* (unsigned) (driverVersion >> 0) & 0xFFFF ); } - - uint32_t vendorId = 0; - if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId) - ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); } } @@ -131,43 +147,43 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); } - uint32_t pciBus, pciAddr; - if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) && - SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL)) - { - uint32_t pciDev = (pciAddr >> 16) & 0xFFFF; - uint32_t pciFunc = pciAddr & 0xFFFF; - - detectFn( - &(FFGpuDriverCondition) { - .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID - | (gpu->deviceId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0) - | (vendorId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), - .pciDeviceId = { - .deviceId = deviceId, - .vendorId = vendorId, - .subSystemId = subSystemId, - .revId = revId, - }, - .pciBusId = { - .domain = 0, - .bus = pciBus, - .device = pciDev, - .func = pciFunc, - }, - .luid = gpu->deviceId, + detectFn( + &(FFGpuDriverCondition) { + .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID + | (adapterLuid > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0) + | (vendorId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), + .pciDeviceId = { + .deviceId = deviceId, + .vendorId = vendorId, + .subSystemId = subSystemId, + .revId = revId, }, - (FFGpuDriverResult) { - .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, + .pciBusId = { + .domain = 0, + .bus = pciBus, + .device = pciDev, + .func = pciFunc, }, - dllName - ); - } + .luid = adapterLuid, + }, + (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, + .name = &gpu->name, + .frequency = options->driverSpecific ? &gpu->frequency : NULL, + }, + dllName + ); + } + + if (!gpu->name.length) + { + if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) + ffStrbufSetWS(&gpu->name, buffer); } } diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp index ae144aca9b..5448bb6b95 100644 --- a/src/detection/gpu/gpu_wsl.cpp +++ b/src/detection/gpu/gpu_wsl.cpp @@ -70,6 +70,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus); ffStrbufInitS(&gpu->name, desc); + gpu->index = FF_GPU_INDEX_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; @@ -117,7 +118,8 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF .revId = hardwareId.revision, }, }; - ffDetectNvidiaGpuInfo(&cond, (FFGpuDriverResult) { + ffDetectNvidiaGpuInfo(&cond, (FFGpuDriverResult){ + .index = &gpu->index, .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, diff --git a/src/detection/gpu/intel_drm.h b/src/detection/gpu/intel_drm.h new file mode 100644 index 0000000000..97b3b07bdc --- /dev/null +++ b/src/detection/gpu/intel_drm.h @@ -0,0 +1,125 @@ +#pragma once + +/* SPDX-License-Identifier: MIT */ +#include + +// xe_drm.h + +/* + * Copyright © 2023 Intel Corporation + */ + +#define DRM_XE_DEVICE_QUERY 0x00 + +#define DRM_IOCTL_XE_DEVICE_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY, struct drm_xe_device_query) + +enum drm_xe_memory_class { + DRM_XE_MEM_REGION_CLASS_SYSMEM = 0, + DRM_XE_MEM_REGION_CLASS_VRAM +}; + +struct drm_xe_mem_region { + __u16 mem_class; + __u16 instance; + __u32 min_page_size; + __u64 total_size; + __u64 used; + __u64 cpu_visible_size; + __u64 cpu_visible_used; + __u64 reserved[6]; +}; + +struct drm_xe_query_mem_regions { + __u32 num_mem_regions; + __u32 pad; + struct drm_xe_mem_region mem_regions[]; +}; + +struct drm_xe_query_topology_mask { + __u16 gt_id; + +#define DRM_XE_TOPO_DSS_GEOMETRY 1 +#define DRM_XE_TOPO_DSS_COMPUTE 2 +#define DRM_XE_TOPO_EU_PER_DSS 4 + __u16 type; + __u32 num_bytes; + __u8 mask[]; +}; + +struct drm_xe_device_query { + __u64 extensions; + +#define DRM_XE_DEVICE_QUERY_MEM_REGIONS 1 +#define DRM_XE_DEVICE_QUERY_GT_TOPOLOGY 5 + __u32 query; + __u32 size; + __u64 data; + __u64 reserved[2]; +}; + +// i915_drm.h + +/* + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + */ + +#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t) + +struct drm_i915_getparam { + __s32 param; + int *value; +}; +typedef struct drm_i915_getparam drm_i915_getparam_t; + +#define DRM_I915_GETPARAM 0x06 +#define DRM_I915_QUERY 0x39 +#define DRM_I915_QUERY_MEMORY_REGIONS 4 +#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) +#define I915_PARAM_EU_TOTAL 34 + +struct drm_i915_query_item { + __u64 query_id; +#define DRM_I915_QUERY_MEMORY_REGIONS 4 + + __s32 length; + __u32 flags; + __u64 data_ptr; +}; + +struct drm_i915_query { + __u32 num_items; + __u32 flags; + __u64 items_ptr; +}; + +enum drm_i915_gem_memory_class { + I915_MEMORY_CLASS_SYSTEM = 0, + I915_MEMORY_CLASS_DEVICE, +}; + +struct drm_i915_gem_memory_class_instance { + __u16 memory_class; + __u16 memory_instance; +}; + +struct drm_i915_memory_region_info { + struct drm_i915_gem_memory_class_instance region; + __u32 rsvd0; + __u64 probed_size; + __u64 unallocated_size; + + union { + __u64 rsvd1[8]; + struct { + __u64 probed_cpu_visible_size; + __u64 unallocated_cpu_visible_size; + }; + }; +}; + +struct drm_i915_query_memory_regions { + __u32 num_regions; + __u32 rsvd[3]; + struct drm_i915_memory_region_info regions[]; +}; diff --git a/src/detection/gpu/nvml.h b/src/detection/gpu/nvml.h index fd10d651fe..693f9bff8c 100644 --- a/src/detection/gpu/nvml.h +++ b/src/detection/gpu/nvml.h @@ -132,5 +132,7 @@ extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type); // Retrieves the current utilization rates for the device extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t *utilization); +// Retrieves the globally unique immutable UUID associated with this device, as a 5 part hexadecimal string, that augments the immutable, board serial identifier. +extern nvmlReturn_t nvmlDeviceGetIndex(nvmlDevice_t device, unsigned int *index); // Retrieves the name of this device. extern nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char *name, unsigned int length); diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m index 70d71eeb6f..04163bc7cb 100644 --- a/src/detection/monitor/monitor_apple.m +++ b/src/detection/monitor/monitor_apple.m @@ -29,7 +29,7 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) for (NSScreen* screen in NSScreen.screens) { if (screen == mainScreen) continue; - NSNumber* screenNumber = [screen.deviceDescription valueForKey:@"NSScreenNumber"]; + NSNumber* screenNumber = screen.deviceDescription[@"NSScreenNumber"]; if (screenNumber && screenNumber.longValue == (long) display->id) { #ifdef MAC_OS_X_VERSION_10_15 diff --git a/src/detection/monitor/monitor_linux.c b/src/detection/monitor/monitor_linux.c index ecf3bef34b..48d52d0b0b 100644 --- a/src/detection/monitor/monitor_linux.c +++ b/src/detection/monitor/monitor_linux.c @@ -176,7 +176,7 @@ FF_MAYBE_UNUSED static const char* detectByDrm(FFlist* results) { const char* drmDirPath = "/sys/class/drm/"; - DIR* dirp = opendir(drmDirPath); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); if(dirp == NULL) return "opendir(drmDirPath) == NULL"; @@ -232,23 +232,23 @@ FF_MAYBE_UNUSED static const char* detectByDrm(FFlist* results) ffStrbufSubstrBefore(&drmDir, drmDirLength); } - closedir(dirp); return NULL; } #endif // __linux__ const char* ffDetectMonitor(FFlist* results) { - const char* error = "Fastfetch was compiled without xrandr support"; + const char* error = NULL; + + #if defined(__linux__) + error = detectByDrm(results); + if (!error && results->length > 0) return NULL; + #endif #ifdef FF_HAVE_XRANDR error = detectByXrandr(results); if (!error) return NULL; #endif - #if defined(__linux__) - error = detectByDrm(results); - #endif - - return error; + return "Fastfetch was compiled without xrandr support"; } diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 9254816a17..cb51762570 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -75,6 +75,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) ffStrbufInit(&gpu->vendor); ffStrbufInit(&gpu->driver); ffStrbufInit(&gpu->platformApi); + gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m index 5a8ef621a0..b86202b1e4 100644 --- a/src/detection/os/os_apple.m +++ b/src/detection/os/os_apple.m @@ -19,11 +19,11 @@ static void parseSystemVersion(FFOSResult* os) NSString* value; - if((value = [dict valueForKey:@"ProductName"])) + if((value = dict[@"ProductName"])) ffStrbufInitS(&os->name, value.UTF8String); - if((value = [dict valueForKey:@"ProductUserVisibleVersion"])) + if((value = dict[@"ProductUserVisibleVersion"])) ffStrbufInitS(&os->version, value.UTF8String); - if((value = [dict valueForKey:@"ProductBuildVersion"])) + if((value = dict[@"ProductBuildVersion"])) ffStrbufInitS(&os->buildID, value.UTF8String); } diff --git a/src/detection/packages/packages.h b/src/detection/packages/packages.h index 43e9a78b48..aef482d84b 100644 --- a/src/detection/packages/packages.h +++ b/src/detection/packages/packages.h @@ -35,6 +35,7 @@ typedef struct FFPackagesResult uint32_t sorcery; uint32_t winget; uint32_t xbps; + uint32_t pacstall; uint32_t all; //Make sure this goes last diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index f3ca054f28..187b0bdf28 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -467,6 +467,78 @@ static uint32_t getGuixPackages(FFstrbuf* baseDir, const char* dirname) return num_elements; } +static inline uint32_t getFlatpakRuntimePackagesArch(FFstrbuf* baseDir) +{ + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars); + if (dirp == NULL) + return 0; + + uint32_t num_elements = 0; + + struct dirent *entry; + while ((entry = readdir(dirp)) != NULL) + { + if(entry->d_type == DT_DIR && entry->d_name[0] != '.') + { + num_elements += getNumElements(baseDir, entry->d_name, DT_DIR); + } + } + + return num_elements; +} + +static inline uint32_t getFlatpakRuntimePackages(FFstrbuf* baseDir) +{ + ffStrbufAppendS(baseDir, "runtime/"); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars); + if (dirp == NULL) + return 0; + + uint32_t runtimeDirLength = baseDir->length; + uint32_t num_elements = 0; + + struct dirent *entry; + while ((entry = readdir(dirp)) != NULL) + { + if(entry->d_type == DT_DIR && entry->d_name[0] != '.') + { + // `flatpak list` ignores `.Locale` and `.Debug` packages, and maybe others + const char* dot = strrchr(entry->d_name, '.'); + if (__builtin_expect(!dot, false)) continue; + dot++; + + if (ffStrEquals(dot, "Locale") || ffStrEquals(dot, "Debug")) + continue; + + ffStrbufAppendS(baseDir, entry->d_name); + ffStrbufAppendC(baseDir, '/'); + num_elements += getFlatpakRuntimePackagesArch(baseDir); + ffStrbufSubstrBefore(baseDir, runtimeDirLength); + } + } + + return num_elements; +} + +static uint32_t getFlatpakPackages(FFstrbuf* baseDir, const char* dirname) +{ + uint32_t num_elements = 0; + uint32_t baseDirLength = baseDir->length; + ffStrbufAppendS(baseDir, dirname); + ffStrbufAppendS(baseDir, "/flatpak/"); + uint32_t flatpakDirLength = baseDir->length; + + ffStrbufAppendS(baseDir, "app"); + num_elements += getNumElementsImpl(baseDir->chars, DT_DIR); + ffStrbufSubstrBefore(baseDir, flatpakDirLength); + + num_elements += getFlatpakRuntimePackages(baseDir); + + ffStrbufSubstrBefore(baseDir, baseDirLength); + + return num_elements; +} + static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options) { if (!(options->disabled & FF_PACKAGES_FLAG_APK_BIT)) packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q", "apk"); @@ -474,7 +546,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, if (!(options->disabled & FF_PACKAGES_FLAG_LPKG_BIT)) packageCounts->lpkg += getNumStrings(baseDir, "/opt/Loc-OS-LPKG/installed-lpkg/Listinstalled-lpkg.list", "\n", "lpkg"); if (!(options->disabled & FF_PACKAGES_FLAG_EMERGE_BIT)) packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE"); if (!(options->disabled & FF_PACKAGES_FLAG_EOPKG_BIT)) packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", DT_DIR); - if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getNumElements(baseDir, "/var/lib/flatpak/app", DT_DIR); + if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getFlatpakPackages(baseDir, "/var/lib"); if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT)) { packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default"); @@ -500,6 +572,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, packageCounts->guixSystem += getGuixPackages(baseDir, "/run/current-system/profile"); } if (!(options->disabled & FF_PACKAGES_FLAG_LINGLONG_BIT)) packageCounts->linglong += getNumElements(baseDir, "/var/lib/linglong/repo/refs/heads/main", DT_DIR); + if (!(options->disabled & FF_PACKAGES_FLAG_PACSTALL_BIT)) packageCounts->pacstall += getNumElements(baseDir, "/var/lib/pacstall/metadata", DT_REG); } static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options) @@ -603,5 +676,5 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) } if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) - result->flatpakUser = getNumElements(&baseDir, "/.local/share/flatpak/app", DT_DIR); + result->flatpakUser = getFlatpakPackages(&baseDir, "/.local/share"); } diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index b5a3bbc2a7..1b12d70fbc 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -1,12 +1,34 @@ #include "physicaldisk.h" #include "common/io/io.h" #include "common/properties.h" -#include "detection/temps/temps_linux.h" #include "util/stringUtils.h" #include #include +static double detectNvmeTemp(const char* devName) +{ + char pathSysBlock[PATH_MAX]; + int index = snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/hwmon$/temp1_input", devName); + if (index <= 0) return FF_PHYSICALDISK_TEMP_UNSET; + index -= (int) sizeof("/temp1_input"); + + for (char c = '0'; c <= '9'; c++) // hopefully there's only one digit + { + pathSysBlock[index] = c; + char buffer[64]; + ssize_t size = ffReadFileData(pathSysBlock, sizeof(buffer), buffer); + if (size > 0) + { + buffer[size] = '\0'; + double temp = strtod(buffer, NULL); + return temp > 0 ? temp / 1000 : FF_PHYSICALDISK_TEMP_UNSET; + } + } + + return FF_PHYSICALDISK_TEMP_UNSET; +} + const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) { FF_AUTO_CLOSE_DIR DIR* sysBlockDirp = opendir("/sys/block/"); @@ -157,20 +179,10 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) } } - device->temperature = FF_PHYSICALDISK_TEMP_UNSET; if (options->temp) - { - const FFlist* tempsResult = ffDetectTemps(); - - FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult) - { - if (ffStrStartsWith(devName, value->deviceName.chars)) // nvme0 - nvme0n1 - { - device->temperature = value->value; - break; - } - } - } + device->temperature = detectNvmeTemp(devName); + else + device->temperature = FF_PHYSICALDISK_TEMP_UNSET; } return NULL; diff --git a/src/detection/temps/temps_bsd.c b/src/detection/temps/temps_bsd.c deleted file mode 100644 index d3160775fd..0000000000 --- a/src/detection/temps/temps_bsd.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "temps_bsd.h" -#include "common/sysctl.h" - -const char* ffDetectCpuTemp(double* current) -{ - int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999); - if (temp == -999999) - return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed"; - - // In tenth of degrees Kelvin - *current = (double) temp / 10 - 273.15; - return NULL; -} - -const char* ffDetectThermalTemp(double* current) -{ - int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999); - if (temp == -999999) - return "ffSysctlGetInt(\"hw.acpi.thermal.tz0.temperature\") failed"; - - // In tenth of degrees Kelvin - *current = (double) temp / 10 - 273.15; - return NULL; -} diff --git a/src/detection/temps/temps_bsd.h b/src/detection/temps/temps_bsd.h deleted file mode 100644 index 36789740b2..0000000000 --- a/src/detection/temps/temps_bsd.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -const char* ffDetectCpuTemp(double* current); -const char* ffDetectThermalTemp(double* current); diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c deleted file mode 100644 index 89d9f941ec..0000000000 --- a/src/detection/temps/temps_linux.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "fastfetch.h" -#include "common/io/io.h" -#include "common/thread.h" -#include "temps_linux.h" - -#include -#include - -static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) -{ - //https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface - uint32_t dirLength = dir->length; - - FF_STRBUF_AUTO_DESTROY valueBuffer = ffStrbufCreate(); - - ffStrbufAppendS(dir, "temp1_input"); - if(!ffReadFileBuffer(dir->chars, &valueBuffer)) - return false; - - ffStrbufSubstrBefore(dir, dirLength); - - value->value = ffStrbufToDouble(&valueBuffer) / 1000; // valueBuffer is millidegree Celsius - - if(value->value != value->value) - return false; - - ffStrbufAppendS(dir, "name"); - ffReadFileBuffer(dir->chars, &value->name); - ffStrbufTrimRightSpace(&value->name); - ffStrbufSubstrBefore(dir, dirLength); - - ffStrbufAppendS(dir, "device/class"); - if(!ffReadFileBuffer(dir->chars, &valueBuffer)) - { - ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "device/device/class"); - ffReadFileBuffer(dir->chars, &valueBuffer); - } - ffStrbufTrimRightSpace(&valueBuffer); - ffStrbufSubstrBefore(dir, dirLength); - if(valueBuffer.length) - value->deviceClass = (uint32_t) strtoul(valueBuffer.chars, NULL, 16); - - ffStrbufClear(&valueBuffer); - ffStrbufEnsureFree(&valueBuffer, 64); - ffStrbufAppendS(dir, "device"); - ssize_t linkLen = readlink(dir->chars, valueBuffer.chars, valueBuffer.allocated - 1); - if (linkLen > 0) - { - valueBuffer.length = (uint32_t) linkLen; - valueBuffer.chars[linkLen] = 0; - ffStrbufSubstrAfterLastC(&valueBuffer, '/'); - ffStrbufInitMove(&value->deviceName, &valueBuffer); - } - else - ffStrbufInit(&value->deviceName); - - return value->name.length > 0 || value->deviceClass > 0; -} - -const FFlist* ffDetectTemps(void) -{ - static FFlist result; - - if(result.elementSize > 0) - return &result; - - ffListInitA(&result, sizeof(FFTempValue), 16); - - FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64); - ffStrbufAppendS(&baseDir, "/sys/class/hwmon/"); - - uint32_t baseDirLength = baseDir.length; - - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); - if(dirp == NULL) - return &result; - - struct dirent* entry; - while((entry = readdir(dirp)) != NULL) - { - if(entry->d_name[0] == '.') - continue; - - ffStrbufAppendS(&baseDir, entry->d_name); - ffStrbufAppendC(&baseDir, '/'); - - FFTempValue* temp = ffListAdd(&result); - ffStrbufInit(&temp->name); - temp->deviceClass = 0; - if(!parseHwmonDir(&baseDir, temp)) - { - ffStrbufDestroy(&temp->name); - --result.length; - } - - ffStrbufSubstrBefore(&baseDir, baseDirLength); - } - - return &result; -} diff --git a/src/detection/temps/temps_linux.h b/src/detection/temps/temps_linux.h deleted file mode 100644 index ccb908b44b..0000000000 --- a/src/detection/temps/temps_linux.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "fastfetch.h" - -typedef struct FFTempValue -{ - FFstrbuf name; - FFstrbuf deviceName; - uint32_t deviceClass; - double value; -} FFTempValue; - -const FFlist* /* List of FFTempValue */ ffDetectTemps(); diff --git a/src/detection/temps/temps_windows.h b/src/detection/temps/temps_windows.h deleted file mode 100644 index 501cc0aa77..0000000000 --- a/src/detection/temps/temps_windows.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -const char* ffDetectSmbiosTemp(double* current, double* critical); diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 0a531b285d..e992f78929 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -82,7 +82,7 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResul if (ffGetTerminalResponse( "\eP+q6b697474792d71756572792d666f6e745f66616d696c79;6b697474792d71756572792d666f6e745f73697a65\e\\", // kitty-query-font_family;kitty-query-font_size 2, - "\eP1+r%*[^=]=%64[^\e]\e\\\eP1+r%*[^=]=%64[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) + "\eP1+r%*[^=]=%512[^\e]\e\\\eP1+r%*[^=]=%512[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) { // decode hex string for (const char* p = fontHex; p[0] && p[1]; p += 2) diff --git a/src/detection/terminalfont/terminalfont_apple.m b/src/detection/terminalfont/terminalfont_apple.m index 7d6aca2828..90fed7fd16 100644 --- a/src/detection/terminalfont/terminalfont_apple.m +++ b/src/detection/terminalfont/terminalfont_apple.m @@ -26,12 +26,12 @@ static void detectIterm2(FFTerminalFontResult* terminalFont) return; } - for(NSDictionary* bookmark in [dict valueForKey:@"New Bookmarks"]) + for(NSDictionary* bookmark in dict[@"New Bookmarks"]) { - if(![[bookmark valueForKey:@"Name"] isEqualToString:@(profile)]) + if(![bookmark[@"Name"] isEqualToString:@(profile)]) continue; - NSString* normalFont = [bookmark valueForKey:@"Normal Font"]; + NSString* normalFont = bookmark[@"Normal Font"]; if(!normalFont) { ffStrbufAppendF(&terminalFont->error, "`Normal Font` key in profile `%s` doesn't exist", profile); @@ -39,10 +39,10 @@ static void detectIterm2(FFTerminalFontResult* terminalFont) } ffFontInitWithSpace(&terminalFont->font, normalFont.UTF8String); - NSNumber* useNonAsciiFont = [bookmark valueForKey:@"Use Non-ASCII Font"]; + NSNumber* useNonAsciiFont = bookmark[@"Use Non-ASCII Font"]; if(useNonAsciiFont.boolValue) { - NSString* nonAsciiFont = [bookmark valueForKey:@"Non Ascii Font"]; + NSString* nonAsciiFont = bookmark[@"Non Ascii Font"]; if (nonAsciiFont) ffFontInitWithSpace(&terminalFont->fallback, nonAsciiFont.UTF8String); } @@ -78,13 +78,13 @@ static void detectWarpTerminal(FFTerminalFontResult* terminalFont) return; } - NSString* fontName = [dict valueForKey:@"FontName"]; + NSString* fontName = dict[@"FontName"]; if(!fontName) fontName = @"Hack"; else fontName = [fontName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\""]]; - NSString* fontSize = [dict valueForKey:@"FontSize"]; + NSString* fontSize = dict[@"FontSize"]; if(!fontSize) fontSize = @"13"; diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 843648c576..baf383def6 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -244,13 +244,19 @@ static void detectFootTerminal(FFTerminalFontResult* terminalFont) return; } uint32_t equal = ffStrbufNextIndexS(&font, colon, "size="); - font.chars[colon] = 0; + font.chars[colon] = '\0'; if (equal == font.length) { ffFontInitValues(&terminalFont->font, font.chars, "8"); return; } - ffFontInitValues(&terminalFont->font, font.chars, &font.chars[equal + strlen("size=")]); + uint32_t size = equal + strlen("size="); + uint32_t comma = ffStrbufNextIndexC(&font, size, ','); + if (comma < font.length) + font.chars[comma] = '\0'; + ffFontInitValues(&terminalFont->font, font.chars, &font.chars[size]); + if (comma < font.length) + ffFontInitValues(&terminalFont->fallback, &font.chars[comma + 1], NULL); } static void detectQTerminal(FFTerminalFontResult* terminalFont) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index c44ecc32c2..4280f20df2 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -365,6 +365,13 @@ FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* v FF_MAYBE_UNUSED static bool getTerminalVersionFoot(FFstrbuf* exe, FFstrbuf* version) { + uint32_t major = 0, minor = 0, patch = 0; + if (ffGetTerminalResponse("\e[>c", 3, "\e[>1;%2u%2u%2u;0c", &major, &minor, &patch) == NULL) + { + ffStrbufSetF(version, "%u.%u.%u", major, minor, patch); + return true; + } + if(!getExeVersionRaw(exe, version)) return false; //foot version: 1.13.1 -pgo +ime -graphemes -assertions @@ -664,7 +671,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe return getTerminalVersionKonsole(exe, version); if(ffStrbufIgnCaseEqualS(processName, "yakuake")) - return getExeVersionGeneral(exe, version);//yakuake 22.12.3 + return getTerminalVersionKonsole(exe, version); // yakuake shares code with konsole if(ffStrbufIgnCaseEqualS(processName, "xfce4-terminal")) return getTerminalVersionXfce4Terminal(exe, version); diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index da4e96dfd6..0355e25636 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -83,6 +83,8 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid) { //Known shells if ( + ffStrbufEqualS(&result->processName, "sudo") || + ffStrbufEqualS(&result->processName, "su") || ffStrbufEqualS(&result->processName, "sh") || ffStrbufEqualS(&result->processName, "ash") || ffStrbufEqualS(&result->processName, "bash") || diff --git a/src/detection/tpm/tpm.h b/src/detection/tpm/tpm.h new file mode 100644 index 0000000000..2310a23bfe --- /dev/null +++ b/src/detection/tpm/tpm.h @@ -0,0 +1,11 @@ +#pragma once + +#include "fastfetch.h" + +typedef struct FFTPMResult +{ + FFstrbuf version; + FFstrbuf description; +} FFTPMResult; + +const char* ffDetectTPM(FFTPMResult* result); diff --git a/src/detection/tpm/tpm_bsd.c b/src/detection/tpm/tpm_bsd.c new file mode 100644 index 0000000000..2e32d512b4 --- /dev/null +++ b/src/detection/tpm/tpm_bsd.c @@ -0,0 +1,21 @@ +#include "tpm.h" +#include "common/sysctl.h" +#include "util/kmod.h" + +const char* ffDetectTPM(FFTPMResult* result) +{ + if (ffSysctlGetString("dev.tpmcrb.0.%desc", &result->description) != NULL) + { + if (!ffKmodLoaded("tpm")) return "`tpm` kernel module is not loaded"; + return "TPM device is not found"; + } + + if (ffStrbufContainS(&result->description, "2.0")) + ffStrbufSetStatic(&result->version, "2.0"); + else if (ffStrbufContainS(&result->description, "1.2")) + ffStrbufSetStatic(&result->version, "1.2"); + else + ffStrbufSetStatic(&result->version, "unknown"); + + return NULL; +} diff --git a/src/detection/tpm/tpm_linux.c b/src/detection/tpm/tpm_linux.c new file mode 100644 index 0000000000..2547339c65 --- /dev/null +++ b/src/detection/tpm/tpm_linux.c @@ -0,0 +1,24 @@ +#include "tpm.h" +#include "common/io/io.h" + +const char* ffDetectTPM(FFTPMResult* result) +{ + if (!ffPathExists("/sys/class/tpm/tpm0", FF_PATHTYPE_DIRECTORY)) + { + if (!ffPathExists("/sys/class/tpm", FF_PATHTYPE_DIRECTORY)) + return "TPM is not supported by kernel"; + return "TPM device is not found"; + } + + if (ffReadFileBuffer("/sys/class/tpm/tpm0/tpm_version_major", &result->version)) + { + ffStrbufTrimRightSpace(&result->version); + if (ffStrbufEqualS(&result->version, "2")) + ffStrbufSetStatic(&result->version, "2.0"); + } + + if (ffReadFileBuffer("/sys/class/tpm/tpm0/device/description", &result->description)) + ffStrbufTrimRightSpace(&result->description); + + return NULL; +} diff --git a/src/detection/tpm/tpm_nosupport.c b/src/detection/tpm/tpm_nosupport.c new file mode 100644 index 0000000000..7865f70b5b --- /dev/null +++ b/src/detection/tpm/tpm_nosupport.c @@ -0,0 +1,6 @@ +#include "tpm.h" + +const char* ffDetectTPM(FF_MAYBE_UNUSED FFTPMResult* result) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/tpm/tpm_windows.c b/src/detection/tpm/tpm_windows.c new file mode 100644 index 0000000000..a63a93f5f2 --- /dev/null +++ b/src/detection/tpm/tpm_windows.c @@ -0,0 +1,82 @@ +#include "tpm.h" +#include "common/library.h" + +// #include + +#define TBS_SUCCESS 0u +#define TBS_E_INTERNAL_ERROR 0x80284001u +#define TBS_E_INVALID_CONTEXT 0x80284004u +typedef UINT32 TBS_RESULT; + +#define TPM_VERSION_UNKNOWN 0 +#define TPM_VERSION_12 1 +#define TPM_VERSION_20 2 + +#define TPM_IFTYPE_UNKNOWN 0 +#define TPM_IFTYPE_1 1 // for 1.2 - use I/O-port or MMIO +#define TPM_IFTYPE_TRUSTZONE 2 // 2.0: Trustzone +#define TPM_IFTYPE_HW 3 // 2.0: HW TPM +#define TPM_IFTYPE_EMULATOR 4 // 2.0: SW-emulator +#define TPM_IFTYPE_SPB 5 // 2.0: SPB attached + +typedef struct _TPM_DEVICE_INFO +{ + UINT32 structVersion; // = 1 for now + UINT32 tpmVersion; // 1.2 / 2.0 + UINT32 tpmInterfaceType; // HW, simulator, ... + UINT32 tpmImpRevision; // code-drop revision, + // implenmentation-specific +} TPM_DEVICE_INFO, *PTPM_DEVICE_INFO; +typedef const TPM_DEVICE_INFO *PCTPM_DEVICE_INFO; + +TBS_RESULT WINAPI +Tbsi_GetDeviceInfo( + _In_ UINT32 Size, + _Out_writes_bytes_(Size) PVOID Info); + +const char* ffDetectTPM(FFTPMResult* result) +{ + FF_LIBRARY_LOAD(tbs, "dlopen TBS" FF_LIBRARY_EXTENSION " failed", "TBS" FF_LIBRARY_EXTENSION, -1) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(tbs, Tbsi_GetDeviceInfo) + + TPM_DEVICE_INFO deviceInfo = {}; + TBS_RESULT code = ffTbsi_GetDeviceInfo(sizeof(deviceInfo), &deviceInfo); + if (code != TBS_SUCCESS) + return code == (TBS_RESULT) TBS_E_INVALID_CONTEXT ? "TPM device is not found" : "Tbsi_GetDeviceInfo() failed"; + + switch (deviceInfo.tpmVersion) + { + case TPM_VERSION_12: + ffStrbufSetStatic(&result->version, "1.2"); + break; + case TPM_VERSION_20: + ffStrbufSetStatic(&result->version, "2.0"); + break; + default: + ffStrbufSetStatic(&result->version, "unknown"); + break; + } + + switch (deviceInfo.tpmInterfaceType) + { + case TPM_IFTYPE_1: + ffStrbufSetF(&result->description, "I/O-port or MMIO TPM %s", result->version.chars); + break; + case TPM_IFTYPE_TRUSTZONE: + ffStrbufSetF(&result->description, "Trustzone TPM %s", result->version.chars); + break; + case TPM_IFTYPE_HW: + ffStrbufSetF(&result->description, "HW TPM %s", result->version.chars); + break; + case TPM_IFTYPE_EMULATOR: + ffStrbufSetF(&result->description, "SW-emulator TPM %s", result->version.chars); + break; + case TPM_IFTYPE_SPB: + ffStrbufSetF(&result->description, "SPB attached TPM %s", result->version.chars); + break; + default: + break; + } + + return NULL; +} diff --git a/src/detection/vulkan/vulkan.c b/src/detection/vulkan/vulkan.c index 1d49ec5844..eb4c05ac8d 100644 --- a/src/detection/vulkan/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -234,6 +234,7 @@ static const char* detectVulkan(FFVulkanResult* result) } //No way to detect those using vulkan + gpu->index = FF_GPU_INDEX_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; diff --git a/src/detection/wallpaper/wallpaper_apple.m b/src/detection/wallpaper/wallpaper_apple.m index eb330dda17..6780828d39 100644 --- a/src/detection/wallpaper/wallpaper_apple.m +++ b/src/detection/wallpaper/wallpaper_apple.m @@ -18,16 +18,16 @@ NSArray* choices = [dict valueForKeyPath:@"SystemDefault.Desktop.Content.Choices"]; if (choices.count > 0) { - NSDictionary* choice = [choices objectAtIndex:0]; - NSArray* files = [choice valueForKey:@"Files"]; + NSDictionary* choice = choices[0]; + NSArray* files = choice[@"Files"]; if (files.count > 0) { - NSString* file = [[files objectAtIndex: 0] valueForKey: @"relative"]; + NSString* file = files[0][@"relative"]; ffStrbufAppendS(result, [NSURL URLWithString:file].path.UTF8String); } else { - NSString* provider = [choice valueForKey:@"Provider"]; + NSString* provider = choice[@"Provider"]; NSString* builtinPrefix = @"com.apple.wallpaper.choice."; if ([provider hasPrefix:builtinPrefix]) provider = [provider substringFromIndex:builtinPrefix.length]; diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 242ac941e4..17cebcdfb9 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -134,7 +134,7 @@ @interface CWInterface() ffStrbufSetStatic(&item->conn.protocol, "802.11be (Wi-Fi 7)"); break; default: - if (inf.activePHYMode < 64) + if (inf.activePHYMode < 8) ffStrbufAppendF(&item->conn.protocol, "Unknown (%ld)", inf.activePHYMode); else if (sp || (sp = getWifiInfoBySystemProfiler(inf.interfaceName))) { diff --git a/src/detection/wmtheme/wmtheme_apple.m b/src/detection/wmtheme/wmtheme_apple.m index 08810b6cc5..8c43877b12 100644 --- a/src/detection/wmtheme/wmtheme_apple.m +++ b/src/detection/wmtheme/wmtheme_apple.m @@ -15,7 +15,7 @@ bool ffDetectWmTheme(FFstrbuf* themeOrError) return false; } - NSNumber* wmThemeColor = [dict valueForKey:@"AppleAccentColor"]; + NSNumber* wmThemeColor = dict[@"AppleAccentColor"]; if(!wmThemeColor) ffStrbufAppendS(themeOrError, "Multicolor"); else @@ -34,7 +34,7 @@ bool ffDetectWmTheme(FFstrbuf* themeOrError) } } - NSString* wmTheme = [dict valueForKey:@"AppleInterfaceStyle"]; + NSString* wmTheme = dict[@"AppleInterfaceStyle"]; ffStrbufAppendF(themeOrError, " (%s)", wmTheme ? wmTheme.UTF8String : "Light"); return true; } diff --git a/src/detection/zpool/zpool_linux.c b/src/detection/zpool/zpool_linux.c index c183c37857..59890990b3 100644 --- a/src/detection/zpool/zpool_linux.c +++ b/src/detection/zpool/zpool_linux.c @@ -1,6 +1,7 @@ #include "zpool.h" #ifdef FF_HAVE_LIBZFS +#include "util/kmod.h" #ifdef __sun #define FF_DISABLE_DLOPEN @@ -82,7 +83,11 @@ const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, libzfs_init); libzfs_handle_t* handle = fflibzfs_init(); - if (!handle) return "libzfs_init() failed"; + if (!handle) + { + if (!ffKmodLoaded("zfs")) return "`zfs` kernel module is not loaded"; + return "libzfs_init() failed"; + } __attribute__((__cleanup__(cleanLibzfs))) FFZfsData data = { .handle = handle, diff --git a/src/logo/ascii/deepin.txt b/src/logo/ascii/deepin.txt index d79eaa42f5..f28458c675 100644 --- a/src/logo/ascii/deepin.txt +++ b/src/logo/ascii/deepin.txt @@ -1,4 +1,4 @@ -$1 ............ + ............ .';;;;;. .,;,. .,;;;;;;;. ';;;;;;;. .;::::::::' .,::;;,''''',. diff --git a/src/logo/ascii/foxos.txt b/src/logo/ascii/foxos.txt new file mode 100644 index 0000000000..91f114bb0b --- /dev/null +++ b/src/logo/ascii/foxos.txt @@ -0,0 +1,8 @@ + ________ ________ ___ ___ ________ ________ +|\ _____\\ __ \ |\ \ / /|\ __ \|\ ____\ +\ \ \__/\ \ \|\ \ \ \ \/ / | \ \|\ \ \ \___|_ + \ \ __\\ \ \\\ \ \ \ / / \ \ \\\ \ \_____ \ + \ \ \_| \ \ \\\ \ / \/ \ \ \\\ \|____|\ \ + \ \__\ \ \_______\/ /\ \ \ \_______\____\_\ \ + \|__| \|_______/__/ /\ __\ \|_______|\_________\ + |__|/ \|__| \|_________| \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 52f1a91664..62f8291cad 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1666,6 +1666,14 @@ static const FFlogo F[] = { .colorKeys = FF_COLOR_FG_RED, .colorTitle = FF_COLOR_FG_WHITE, }, + // FoxOS + { + .names = {"FoxOS"}, + .lines = FASTFETCH_DATATEXT_LOGO_FOXOS, + .colors = { + FF_COLOR_FG_YELLOW, + }, + }, // FreeBSD { .names = {"Freebsd"}, @@ -1914,6 +1922,16 @@ static const FFlogo G[] = { .colorKeys = FF_COLOR_FG_YELLOW, .colorTitle = FF_COLOR_FG_WHITE, }, + // GXDE + { + .names = {"GXDE"}, + .lines = FASTFETCH_DATATEXT_LOGO_DEEPIN, + .colors = { + FF_COLOR_FG_RED, + }, + .colorKeys = FF_COLOR_FG_RED, + .colorTitle = FF_COLOR_FG_RED, + }, // LAST {}, }; diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 6bf2de570d..0381b32f4a 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -6,7 +6,7 @@ #include "modules/cpu/cpu.h" #include "util/stringUtils.h" -#define FF_CPU_NUM_FORMAT_ARGS 10 +#define FF_CPU_NUM_FORMAT_ARGS 9 static int sortCores(const FFCPUCore* a, const FFCPUCore* b) { @@ -19,7 +19,6 @@ void ffPrintCPU(FFCPUOptions* options) .temperature = FF_CPU_TEMP_UNSET, .frequencyMax = 0, .frequencyBase = 0, - .frequencyBiosLimit = 0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate(), }; @@ -71,9 +70,7 @@ void ffPrintCPU(FFCPUOptions* options) else if(cpu.coresOnline > 1) ffStrbufAppendF(&str, " (%u)", cpu.coresOnline); - uint32_t freq = cpu.frequencyBiosLimit; - if(freq == 0) - freq = cpu.frequencyMax; + uint32_t freq = cpu.frequencyMax; if(freq == 0) freq = cpu.frequencyBase; if(freq > 0) @@ -96,8 +93,6 @@ void ffPrintCPU(FFCPUOptions* options) ffParseFrequency(cpu.frequencyBase, &freqBase); FF_STRBUF_AUTO_DESTROY freqMax = ffStrbufCreate(); ffParseFrequency(cpu.frequencyMax, &freqMax); - FF_STRBUF_AUTO_DESTROY freqBioslimit = ffStrbufCreate(); - ffParseFrequency(cpu.frequencyBiosLimit, &freqBioslimit); FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs); @@ -111,7 +106,6 @@ void ffPrintCPU(FFCPUOptions* options) FF_FORMAT_ARG(freqMax, "freq-max"), FF_FORMAT_ARG(tempStr, "temperature"), FF_FORMAT_ARG(coreTypes, "core-types"), - FF_FORMAT_ARG(freqBioslimit, "freq-bios-limit"), })); } } @@ -190,7 +184,6 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ .temperature = FF_CPU_TEMP_UNSET, .frequencyMax = 0, .frequencyBase = 0, - .frequencyBiosLimit = 0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate(), }; @@ -219,7 +212,6 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_val* frequency = yyjson_mut_obj_add_obj(doc, obj, "frequency"); yyjson_mut_obj_add_uint(doc, frequency, "base", cpu.frequencyBase); yyjson_mut_obj_add_uint(doc, frequency, "max", cpu.frequencyMax); - yyjson_mut_obj_add_uint(doc, frequency, "biosLimit", cpu.frequencyBiosLimit); yyjson_mut_val* coreTypes = yyjson_mut_obj_add_arr(doc, obj, "coreTypes"); for (uint32_t i = 0; i < sizeof (cpu.coreTypes) / sizeof (cpu.coreTypes[0]) && cpu.coreTypes[i].count > 0; i++) @@ -248,7 +240,6 @@ void ffPrintCPUHelpFormat(void) "Max frequency (formatted) - freq-max", "Temperature (formatted) - temperature", "Logical core count grouped by frequency - core-types", - "Bios limited frequency (formatted) - freq-bios-limit", })); } diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 4e3f67eb3a..ff1c93528b 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -100,7 +100,7 @@ void ffPrintDisplay(FFDisplayOptions* options) } FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - double inch = sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4; + uint32_t inch = (uint32_t) (sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4 + 0.5); if(options->moduleArgs.outputFormat.length == 0) { @@ -121,8 +121,8 @@ void ffPrintDisplay(FFDisplayOptions* options) result->scaledHeight > 0 && result->scaledHeight != result->height) ffStrbufAppendF(&buffer, " (as %ix%i)", result->scaledWidth, result->scaledHeight); - if (inch > 0) - ffStrbufAppendF(&buffer, " in %i″", (uint32_t) (inch + 0.5)); + if (inch > 1) + ffStrbufAppendF(&buffer, " in %i″", inch); if(result->type != FF_DISPLAY_TYPE_UNKNOWN) ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]"); diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index bdc2e890da..1d449d33a1 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -10,7 +10,7 @@ #include -#define FF_GPU_NUM_FORMAT_ARGS 12 +#define FF_GPU_NUM_FORMAT_ARGS 13 static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResult* gpu) { @@ -103,6 +103,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu FF_FORMAT_ARG(sUsed, "shared-used"), FF_FORMAT_ARG(gpu->platformApi, "platform-api"), FF_FORMAT_ARG(frequency, "frequency"), + FF_FORMAT_ARG(index, "index"), })); } } @@ -322,6 +323,12 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + + if (gpu->index != FF_GPU_INDEX_UNSET) + yyjson_mut_obj_add_uint(doc, obj, "index", gpu->index); + else + yyjson_mut_obj_add_null(doc, obj, "index"); + if (gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) yyjson_mut_obj_add_int(doc, obj, "coreCount", gpu->coreCount); else @@ -402,6 +409,7 @@ void ffPrintGPUHelpFormat(void) "GPU used shared memory - shared-used", "The platform API used when detecting the GPU - platform-api", "Current frequency in GHz - frequency", + "GPU vendor specific index - index", })); } diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 7802c3fd25..d53b12ff4f 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -32,7 +32,6 @@ void ffPrintLoadavg(FFLoadavgOptions* options) .temperature = FF_CPU_TEMP_UNSET, .frequencyMax = 0, .frequencyBase = 0, - .frequencyBiosLimit = 0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate(), }; diff --git a/src/modules/modules.h b/src/modules/modules.h index 84d9e6fcb2..4f9fa7a407 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -62,6 +62,7 @@ #include "modules/terminaltheme/terminaltheme.h" #include "modules/theme/theme.h" #include "modules/title/title.h" +#include "modules/tpm/tpm.h" #include "modules/uptime/uptime.h" #include "modules/users/users.h" #include "modules/version/version.h" diff --git a/src/modules/options.h b/src/modules/options.h index 2677d2515f..783757d3a1 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -62,6 +62,7 @@ #include "modules/terminaltheme/option.h" #include "modules/theme/option.h" #include "modules/title/option.h" +#include "modules/tpm/option.h" #include "modules/uptime/option.h" #include "modules/users/option.h" #include "modules/version/option.h" diff --git a/src/modules/packages/option.h b/src/modules/packages/option.h index de28caa336..e3f3d54c79 100644 --- a/src/modules/packages/option.h +++ b/src/modules/packages/option.h @@ -32,6 +32,7 @@ typedef enum FFPackagesFlags FF_PACKAGES_FLAG_LPKGBUILD_BIT = 1 << 22, FF_PACKAGES_FLAG_GUIX_BIT = 1 << 23, FF_PACKAGES_FLAG_LINGLONG_BIT = 1 << 24, + FF_PACKAGES_FLAG_PACSTALL_BIT = 1 << 25, } FFPackagesFlags; typedef struct FFPackagesOptions diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 3e2b09fc7e..e33b18d493 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -4,7 +4,7 @@ #include "modules/packages/packages.h" #include "util/stringUtils.h" -#define FF_PACKAGES_NUM_FORMAT_ARGS 37 +#define FF_PACKAGES_NUM_FORMAT_ARGS 38 void ffPrintPackages(FFPackagesOptions* options) { @@ -72,6 +72,7 @@ void ffPrintPackages(FFPackagesOptions* options) FF_PRINT_PACKAGE_NAME(guixUser, "guix-user") FF_PRINT_PACKAGE_NAME(guixHome, "guix-home") FF_PRINT_PACKAGE(linglong) + FF_PRINT_PACKAGE(pacstall) putchar('\n'); } @@ -115,6 +116,7 @@ void ffPrintPackages(FFPackagesOptions* options) FF_FORMAT_ARG(counts.guixUser, "guix-user"), FF_FORMAT_ARG(counts.guixHome, "guix-home"), FF_FORMAT_ARG(counts.linglong, "linglong"), + FF_FORMAT_ARG(counts.pacstall, "pacstall"), FF_FORMAT_ARG(nixAll, "nix-all"), FF_FORMAT_ARG(flatpakAll, "flatpak-all"), FF_FORMAT_ARG(brewAll, "brew-all"), @@ -186,9 +188,10 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key, break; case 'P': if (false); FF_TEST_PACKAGE_NAME(PACMAN) + FF_TEST_PACKAGE_NAME(PACSTALL) + FF_TEST_PACKAGE_NAME(PALUDIS) FF_TEST_PACKAGE_NAME(PKG) FF_TEST_PACKAGE_NAME(PKGTOOL) - FF_TEST_PACKAGE_NAME(PALUDIS) break; case 'R': if (false); FF_TEST_PACKAGE_NAME(RPM) @@ -295,9 +298,10 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) break; case 'P': if (false); FF_TEST_PACKAGE_NAME(PACMAN) + FF_TEST_PACKAGE_NAME(PACSTALL) + FF_TEST_PACKAGE_NAME(PALUDIS) FF_TEST_PACKAGE_NAME(PKG) FF_TEST_PACKAGE_NAME(PKGTOOL) - FF_TEST_PACKAGE_NAME(PALUDIS) break; case 'R': if (false); FF_TEST_PACKAGE_NAME(RPM) @@ -352,6 +356,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do FF_TEST_PACKAGE_NAME(NIX) FF_TEST_PACKAGE_NAME(OPKG) FF_TEST_PACKAGE_NAME(PACMAN) + FF_TEST_PACKAGE_NAME(PACSTALL) FF_TEST_PACKAGE_NAME(PALUDIS) FF_TEST_PACKAGE_NAME(PKG) FF_TEST_PACKAGE_NAME(PKGTOOL) @@ -412,6 +417,7 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy FF_APPEND_PACKAGE_COUNT(guixUser) FF_APPEND_PACKAGE_COUNT(guixHome) FF_APPEND_PACKAGE_COUNT(linglong) + FF_APPEND_PACKAGE_COUNT(pacstall) yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch); } @@ -451,6 +457,7 @@ void ffPrintPackagesHelpFormat(void) "Number of guix-user packages - guix-user", "Number of guix-home packages - guix-home", "Number of linglong packages - linglong", + "Number of pacstall packages - pacstall", "Total number of all nix packages - nix-all", "Total number of all flatpak app packages - flatpak-all", "Total number of all brew packages - brew-all", diff --git a/src/modules/tpm/option.h b/src/modules/tpm/option.h new file mode 100644 index 0000000000..d98c21df27 --- /dev/null +++ b/src/modules/tpm/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFTPMOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFTPMOptions; diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c new file mode 100644 index 0000000000..3934fb4ce5 --- /dev/null +++ b/src/modules/tpm/tpm.c @@ -0,0 +1,127 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/tpm/tpm.h" +#include "modules/tpm/tpm.h" +#include "util/stringUtils.h" + +#define FF_TPM_NUM_FORMAT_ARGS 2 + +void ffPrintTPM(FFTPMOptions* options) +{ + FFTPMResult result = { + .version = ffStrbufCreate(), + .description = ffStrbufCreate() + }; + const char* error = ffDetectTPM(&result); + + if(error) + { + ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return; + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + if (result.description.length > 0) + ffStrbufPutTo(&result.description, stdout); + else + ffStrbufPutTo(&result.version, stdout); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_TPM_NUM_FORMAT_ARGS, ((FFformatarg[]){ + FF_FORMAT_ARG(result.version, "version"), + FF_FORMAT_ARG(result.description, "description"), + })); + } + + ffStrbufDestroy(&result.version); + ffStrbufDestroy(&result.description); +} + +bool ffParseTPMCommandOptions(FFTPMOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_TPM_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseTPMJsonObject(FFTPMOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateTPMJsonConfig(FFTPMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyTPMOptions))) FFTPMOptions defaultOptions; + ffInitTPMOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateTPMJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFTPMResult result = { + .version = ffStrbufCreate(), + .description = ffStrbufCreate() + }; + const char* error = ffDetectTPM(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); + yyjson_mut_obj_add_strbuf(doc, obj, "description", &result.description); + + ffStrbufDestroy(&result.version); + ffStrbufDestroy(&result.description); +} + +void ffPrintTPMHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_TPM_MODULE_NAME, "{2}", FF_TPM_NUM_FORMAT_ARGS, ((const char* []) { + "TPM device version - version", + "TPM general description - description", + })); +} + +void ffInitTPMOptions(FFTPMOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_TPM_MODULE_NAME, + "Print info of Trusted Platform Module (TPM) Security Device", + ffParseTPMCommandOptions, + ffParseTPMJsonObject, + ffPrintTPM, + ffGenerateTPMJsonResult, + ffPrintTPMHelpFormat, + ffGenerateTPMJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyTPMOptions(FFTPMOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/tpm/tpm.h b/src/modules/tpm/tpm.h new file mode 100644 index 0000000000..3356a46dc0 --- /dev/null +++ b/src/modules/tpm/tpm.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_TPM_MODULE_NAME "TPM" + +void ffPrintTPM(FFTPMOptions* options); +void ffInitTPMOptions(FFTPMOptions* options); +void ffDestroyTPMOptions(FFTPMOptions* options); diff --git a/src/options/modules.c b/src/options/modules.c index 10b6fc627a..cea3c7af0d 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -63,6 +63,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitTerminalThemeOptions(&options->terminalTheme); ffInitThemeOptions(&options->theme); ffInitTitleOptions(&options->title); + ffInitTPMOptions(&options->tpm); ffInitUptimeOptions(&options->uptime); ffInitUsersOptions(&options->users); ffInitVersionOptions(&options->version); @@ -137,6 +138,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyTerminalThemeOptions(&options->terminalTheme); ffDestroyThemeOptions(&options->theme); ffDestroyTitleOptions(&options->title); + ffDestroyTPMOptions(&options->tpm); ffDestroyUptimeOptions(&options->uptime); ffDestroyUsersOptions(&options->users); ffDestroyVersionOptions(&options->version); diff --git a/src/options/modules.h b/src/options/modules.h index 7f210be69b..919d924089 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -64,6 +64,7 @@ typedef struct FFOptionsModules FFTerminalThemeOptions terminalTheme; FFThemeOptions theme; FFTitleOptions title; + FFTPMOptions tpm; FFUptimeOptions uptime; FFUsersOptions users; FFVersionOptions version; diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index c4a01592e8..4387a5d7bc 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -211,6 +211,14 @@ void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value) strbuf->length += length; } +void ffStrbufPrependC(FFstrbuf* strbuf, char c) +{ + ffStrbufEnsureFree(strbuf, 1); + memmove(strbuf->chars + 1, strbuf->chars, strbuf->length + 1); // + 1 for the null byte + strbuf->chars[0] = c; + strbuf->length += 1; +} + void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value) { ffStrbufClear(strbuf); @@ -511,3 +519,15 @@ void ffStrbufLowerCase(FFstrbuf* strbuf) for (uint32_t i = 0; i < strbuf->length; ++i) strbuf->chars[i] = (char) tolower(strbuf->chars[i]); } + +void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c) +{ + if(num == 0) return; + if (index >= strbuf->length) + index = strbuf->length; + + ffStrbufEnsureFree(strbuf, num); + memmove(strbuf->chars + index + num, strbuf->chars + index, strbuf->length - index + 1); + memset(&strbuf->chars[index], c, num); + strbuf->length += num; +} diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index a3b7179a44..a79ba2cc19 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -47,6 +47,9 @@ void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments); const char* ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until); void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value); +void ffStrbufPrependC(FFstrbuf* strbuf, char c); + +void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c); void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value); void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value); diff --git a/src/detection/temps/temps_apple.c b/src/util/apple/smc_temps.c similarity index 99% rename from src/detection/temps/temps_apple.c rename to src/util/apple/smc_temps.c index c4cef78277..1f9d8179dc 100644 --- a/src/detection/temps/temps_apple.c +++ b/src/util/apple/smc_temps.c @@ -1,5 +1,5 @@ #include "fastfetch.h" -#include "temps_apple.h" +#include "smc_temps.h" #include "util/stringUtils.h" #include diff --git a/src/detection/temps/temps_apple.h b/src/util/apple/smc_temps.h similarity index 95% rename from src/detection/temps/temps_apple.h rename to src/util/apple/smc_temps.h index c04b41569d..0d6e104c10 100644 --- a/src/detection/temps/temps_apple.h +++ b/src/util/apple/smc_temps.h @@ -1,7 +1,6 @@ #pragma once #include "fastfetch.h" -#include "util/FFlist.h" typedef struct FFTempValue { diff --git a/src/util/kmod.c b/src/util/kmod.c new file mode 100644 index 0000000000..60d1889bf1 --- /dev/null +++ b/src/util/kmod.c @@ -0,0 +1,52 @@ +#include "kmod.h" + +#if __linux__ +#include "common/io/io.h" + +bool ffKmodLoaded(const char* modName) +{ + static FFstrbuf modules; + if (modules.chars == NULL) + { + ffStrbufInitS(&modules, "\n"); + ffAppendFileBuffer("/proc/modules", &modules); + } + + if (modules.length == 0) return false; + + uint32_t len = (uint32_t) strlen(modName); + if (len > 250) return false; + + char temp[256]; + temp[0] = '\n'; + memcpy(temp + 1, modName, len); + temp[1 + len] = ' '; + return memmem(modules.chars, modules.length, temp, len + 2) != NULL; +} +#elif __FreeBSD__ +#include +#include + +bool ffKmodLoaded(const char* modName) +{ + return modfind(modName) >= 0; +} +#elif __APPLE__ +#include "util/apple/cf_helpers.h" +#include +#include + +bool ffKmodLoaded(const char* modName) +{ + FF_CFTYPE_AUTO_RELEASE CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, modName, kCFStringEncodingUTF8); + FF_CFTYPE_AUTO_RELEASE CFArrayRef identifiers = CFArrayCreate(kCFAllocatorDefault, (const void**) &name, 1, &kCFTypeArrayCallBacks); + FF_CFTYPE_AUTO_RELEASE CFArrayRef keys = CFArrayCreate(kCFAllocatorDefault, NULL, 0, NULL); + FF_CFTYPE_AUTO_RELEASE CFDictionaryRef kextInfo = KextManagerCopyLoadedKextInfo(identifiers, keys); + return CFDictionaryContainsKey(kextInfo, name); +} +#else +bool ffKmodLoaded(FF_MAYBE_UNUSED const char* modName) +{ + return true; // Don't generate kernel module related errors +} +#endif diff --git a/src/util/kmod.h b/src/util/kmod.h new file mode 100644 index 0000000000..013340b1a7 --- /dev/null +++ b/src/util/kmod.h @@ -0,0 +1,5 @@ +#pragma once + +#include "fastfetch.h" + +bool ffKmodLoaded(const char* modName); diff --git a/tests/strbuf.c b/tests/strbuf.c index 01db4e0940..d901faab1e 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -279,6 +279,20 @@ int main(void) VERIFY(ffStrbufEqualS(&strbuf, "TEST_TEST")); VERIFY(strbuf.length == 9); VERIFY(strbuf.allocated >= 10); + ffStrbufAppendC(&strbuf, '_'); + VERIFY(ffStrbufEqualS(&strbuf, "TEST_TEST_")); + ffStrbufDestroy(&strbuf); + VERIFY(strbuf.length == 0); + VERIFY(strbuf.allocated == 0); + + //ffStrbufCreateStatic / Prepend + ffStrbufInitStatic(&strbuf, "TEST"); + ffStrbufPrependS(&strbuf, "TEST_"); + VERIFY(ffStrbufEqualS(&strbuf, "TEST_TEST")); + VERIFY(strbuf.length == 9); + VERIFY(strbuf.allocated >= 10); + ffStrbufPrependC(&strbuf, '_'); + VERIFY(ffStrbufEqualS(&strbuf, "_TEST_TEST")); ffStrbufDestroy(&strbuf); VERIFY(strbuf.length == 0); VERIFY(strbuf.allocated == 0); @@ -416,6 +430,18 @@ int main(void) VERIFY(ffStrbufEqualS(&strbuf, "__TEST__")); ffStrbufDestroy(&strbuf); + //ffStrbufInsertNC + ffStrbufInitStatic(&strbuf, "123456"); + ffStrbufInsertNC(&strbuf, 0, 2, 'A'); + VERIFY(ffStrbufEqualS(&strbuf, "AA123456")); + ffStrbufInsertNC(&strbuf, 4, 2, 'B'); + VERIFY(ffStrbufEqualS(&strbuf, "AA12BB3456")); + ffStrbufInsertNC(&strbuf, strbuf.length, 2, 'C'); + VERIFY(ffStrbufEqualS(&strbuf, "AA12BB3456CC")); + ffStrbufInsertNC(&strbuf, 999, 2, 'D'); + VERIFY(ffStrbufEqualS(&strbuf, "AA12BB3456CCDD")); + ffStrbufDestroy(&strbuf); + //Success puts("\e[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET); }